mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Compare commits
340 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e1c92712a0 | |||
| 6ec0f1bfce | |||
| db410d8b44 | |||
| cd07f3de96 | |||
| 12072a0342 | |||
| c6f3761bb9 | |||
| 673f0e78b1 | |||
| 65c8960ec8 | |||
| 089ecc67d1 | |||
| 0f84af5b32 | |||
| 710ed6dd56 | |||
| 335aabd4ff | |||
| 98c97a8aed | |||
| 23d18d2ac5 | |||
| a136b8b1e5 | |||
| 7f8b71cf28 | |||
| 9e5f2b18b9 | |||
| bdfeddecd5 | |||
| 23cbe63cd4 | |||
| f0f53455a5 | |||
| d8b49f57a9 | |||
| 7eaaf3bbb4 | |||
| d4f83cd38b | |||
| 9eca5f518e | |||
| d17bed02e6 | |||
| b4b194a59b | |||
| c6f62a2b81 | |||
| e3a9f42a56 | |||
| 323bcef1fe | |||
| 095b92b498 | |||
| 18c2ccd66c | |||
| 28fdeac01c | |||
| a7e4267b9b | |||
| d6837aa121 | |||
| 5a2913b36f | |||
| 20180fa89c | |||
| c6b89055d8 | |||
| bfda7ab2c3 | |||
| 953ce32bea | |||
| 961fa5ffe6 | |||
| b1b2959bcb | |||
| 70ef715dc6 | |||
| ffa58aae34 | |||
| 24f5209c03 | |||
| 7fd96732d6 | |||
| 6e0759f719 | |||
| 63434e1e2f | |||
| 9c17bc412a | |||
| d40144d50c | |||
| 131c0f5a37 | |||
| 7086314d8b | |||
| d75b2c2bb7 | |||
| c46d174869 | |||
| 17e03f2903 | |||
| 2c12a34051 | |||
| 2d3dde2101 | |||
| d539f5ecf2 | |||
| b17d6be4fc | |||
| 3c737f2360 | |||
| 9ac5e714b8 | |||
| 94defa3091 | |||
| 052ada221e | |||
| 1d5e4cf2a9 | |||
| c46aef3ea0 | |||
| d30e141693 | |||
| 305940396e | |||
| 2ab567a9d3 | |||
| a9c488ff03 | |||
| 8817b50c95 | |||
| 84c3710a35 | |||
| be7be9bba4 | |||
| b50ae284fb | |||
| 97716d5c26 | |||
| e77253c843 | |||
| 6aed8d003f | |||
| 0083e60c49 | |||
| 0fc79fd845 | |||
| a7c3bc7ac5 | |||
| 83b16e5f4b | |||
| ee17c6d75e | |||
| c0525ac69c | |||
| e9d2a39098 | |||
| 4d6fd16767 | |||
| b398870823 | |||
| e68c50d614 | |||
| f6a27718a2 | |||
| f136fa3e3a | |||
| 8e55a3dbf3 | |||
| 923227a0e8 | |||
| 14ecafe0e2 | |||
| b93f8323ab | |||
| 77f43cde9a | |||
| e4d018393d | |||
| 9a816090de | |||
| 4b04aa65be | |||
| 489bb55788 | |||
| 9d244611bc | |||
| 3533916149 | |||
| 46bc3e7f72 | |||
| ed0f0107e3 | |||
| a855d7043a | |||
| 66fd795763 | |||
| 05da43484f | |||
| a58de2278b | |||
| 6743df23e9 | |||
| 35ec0d05e2 | |||
| 6ead7207ec | |||
| 0d5223036d | |||
| 640fc433b8 | |||
| 35d814c3f6 | |||
| f8b9d2b0d9 | |||
| 3390b865e0 | |||
| 883486da9c | |||
| d048203f45 | |||
| f9d70d1196 | |||
| 4413b7b4fb | |||
| 7a4f263a62 | |||
| 1a360d5282 | |||
| dc785fc116 | |||
| 009593f7cc | |||
| 884be3a93e | |||
| 9a25328787 | |||
| 2d8ec490b1 | |||
| 3b19ca99e1 | |||
| f751a48568 | |||
| 4549989a63 | |||
| 19e2c4e051 | |||
| 6f5e90be53 | |||
| 34fa0620ab | |||
| fe37af1a3f | |||
| 3459802d67 | |||
| b8bf847941 | |||
| 5b6024584a | |||
| 4833a44542 | |||
| eb93e2bb7e | |||
| 291700dfc7 | |||
| 7a4913b394 | |||
| 0dae71f4b7 | |||
| 08e4229533 | |||
| 101a31628d | |||
| 2a2ce883b4 | |||
| 5a0e26bdb5 | |||
| 0c9277dfd0 | |||
| 37886cf296 | |||
| df5ba2eced | |||
| 3c2ddb96b3 | |||
| e2a825dfb2 | |||
| 8d49c7e595 | |||
| 966d5dac24 | |||
| 7f684f4d2e | |||
| 1510f7f3a8 | |||
| 6916becf7f | |||
| ad5b496f5c | |||
| e647401db4 | |||
| 3113f9c3ab | |||
| a1e47865c5 | |||
| 3a5f9b3fed | |||
| 5ffbc19d03 | |||
| d9db4b818a | |||
| 693efdbd0f | |||
| 399b783437 | |||
| 4bc574dfbe | |||
| 294af0981d | |||
| e8c7014993 | |||
| 0edc8303c1 | |||
| 8c89c3e225 | |||
| a93c8ab055 | |||
| c5cb79d116 | |||
| b3c50b9571 | |||
| 41579de502 | |||
| e6f735b8bc | |||
| 70b6f2cdfa | |||
| c1e716d6a3 | |||
| dde59b4673 | |||
| 9d77920adf | |||
| 6f50ee0cfb | |||
| 4c86d6d49e | |||
| 963327dd64 | |||
| 5cba1ccd98 | |||
| de8e6b6852 | |||
| 811089f3b3 | |||
| e045a09d36 | |||
| a3a6919b08 | |||
| cbee839a43 | |||
| efdd92b6a1 | |||
| 75296e189a | |||
| 708a68119e | |||
| 1d5ab98892 | |||
| 07753e211d | |||
| 8135d96300 | |||
| d151e825da | |||
| d5289cc3df | |||
| af40a8b57e | |||
| 529139099e | |||
| b4aa18abae | |||
| a7cee63d1c | |||
| eda735925a | |||
| 46650c8cc3 | |||
| fbab156d22 | |||
| 539cb670f1 | |||
| 2a6aba110b | |||
| 0351a1e974 | |||
| d48ab128a0 | |||
| ef67585529 | |||
| 953e7c6da0 | |||
| ab5a9c9d60 | |||
| af91cf7413 | |||
| 6a618986d0 | |||
| 9eefcacbc1 | |||
| e245e29058 | |||
| 7d879f8d1f | |||
| f7963a56e9 | |||
| 0a73877c25 | |||
| 1b57880be3 | |||
| f54144e7e8 | |||
| b735759bd0 | |||
| a7199ecedf | |||
| 2cb529be32 | |||
| 235038027b | |||
| e8eb036594 | |||
| d531eb8b47 | |||
| a88a619099 | |||
| 00bc429f20 | |||
| 3f25d002e4 | |||
| 74c6f20c3e | |||
| 8728a0a39b | |||
| dcf5cf7f54 | |||
| 7f89ecea5c | |||
| 30a63dd13b | |||
| a5d2642c37 | |||
| 79e5eedab0 | |||
| 27da217eb7 | |||
| a0c71a5387 | |||
| 4d19a59cb6 | |||
| 819a9f415a | |||
| dff1ef3778 | |||
| 7131f5774e | |||
| aa572508dc | |||
| 1f880efb3f | |||
| 72ace5c156 | |||
| 2f34a6ffa4 | |||
| afdfe7bbaa | |||
| 14f43f2a79 | |||
| f3353cf6e9 | |||
| 722f2cad1e | |||
| b135093628 | |||
| be44789b01 | |||
| 233197095b | |||
| 494cb728c3 | |||
| 60e9a9101a | |||
| c23dac6f99 | |||
| 3965319ef4 | |||
| c4db7c515f | |||
| fbf88e102b | |||
| d5ea043893 | |||
| f70c79ba4a | |||
| 0b2a26e2f1 | |||
| b968ba67b3 | |||
| e234cc864b | |||
| b47e75eed6 | |||
| 6b684bf030 | |||
| ea89d37461 | |||
| 814af177d1 | |||
| 1ccbb7177f | |||
| 3118dbd32b | |||
| 1a5e062dac | |||
| 0bcaea6f01 | |||
| 8283a6c4ad | |||
| cd159bac6c | |||
| 21f917004f | |||
| 0abf2ff00c | |||
| 0ca92ec6b5 | |||
| e66fa53537 | |||
| a51013cc00 | |||
| 171500a97d | |||
| 9a4851961e | |||
| e5ddbacb2e | |||
| 03c7d78e2b | |||
| 00498b02b3 | |||
| ad6e2d1a9f | |||
| 5cfa71cd72 | |||
| 0551044ef9 | |||
| 5126b3eeb2 | |||
| 8d7078f96f | |||
| c446440537 | |||
| 333e4c9eca | |||
| fb1f5df234 | |||
| cc419a9f62 | |||
| 2469b6efef | |||
| b7446c9a93 | |||
| 0c9b5bbaf4 | |||
| 3126544f00 | |||
| ccdad0469d | |||
| 9f3eeb3d0d | |||
| 92bc53b672 | |||
| 1355303360 | |||
| 7227f513a5 | |||
| 4933d66000 | |||
| 977b21618c | |||
| 5cecd5bec3 | |||
| d8db39f9c7 | |||
| 736fc44870 | |||
| 537127ec4e | |||
| a5167f3739 | |||
| d481541ad8 | |||
| 7ab19fb8af | |||
| 715a2c0653 | |||
| 350cd0539c | |||
| 9f8fe08c75 | |||
| 5048239563 | |||
| 6e135e06a9 | |||
| d52647b288 | |||
| c0a729978c | |||
| 041c95c6d2 | |||
| 8de0fed18e | |||
| dd75a8e858 | |||
| 2e77db23d5 | |||
| 04a4a02235 | |||
| 2910730bc1 | |||
| 23458a6c64 | |||
| 9679b22072 | |||
| 3fae301ec2 | |||
| d08069f7b0 | |||
| 56a0607a5e | |||
| 9c08617f7d | |||
| 812dc8d738 | |||
| d8b278a1f5 | |||
| 4368a4f63e | |||
| 72ae90ae93 | |||
| c36ce7a8ab | |||
| 404097fe30 | |||
| 07d5c719d4 | |||
| 13a43473cc | |||
| 5a84198829 | |||
| 1f443cd87c | |||
| 4901b92ee2 | |||
| cd48e15071 | |||
| 2d4b570f48 | |||
| 3f0b36bd4b | |||
| b342fb9c30 |
@@ -0,0 +1,3 @@
|
||||
ko_fi: adbenitez
|
||||
liberapay: adbenitez
|
||||
custom: "https://arcanechat.me/#contribute"
|
||||
@@ -1 +1 @@
|
||||
blank_issues_enabled: true
|
||||
blank_issues_enabled: false
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
- uses: nttld/setup-ndk@v1
|
||||
id: setup-ndk
|
||||
with:
|
||||
ndk-version: r23c
|
||||
ndk-version: r27
|
||||
|
||||
- name: Compile core
|
||||
env:
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
run: ./gradlew --no-daemon -PABI_FILTER=armeabi-v7a assembleFossDebug
|
||||
|
||||
- name: Upload APK
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: app-preview.apk
|
||||
path: 'build/outputs/apk/foss/debug/*.apk'
|
||||
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
- uses: nttld/setup-ndk@v1
|
||||
id: setup-ndk
|
||||
with:
|
||||
ndk-version: r23c
|
||||
ndk-version: r27
|
||||
|
||||
- name: Compile core
|
||||
env:
|
||||
@@ -49,11 +49,12 @@ jobs:
|
||||
- name: Build APK
|
||||
run: |
|
||||
mkdir -p ~/.gradle
|
||||
echo -n ${{ secrets.SIGNING_KEY }} | base64 -d >> ~/app.keystore
|
||||
echo "DC_RELEASE_STORE_FILE=$HOME/app.keystore" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_STORE_PASSWORD=${{ secrets.KEY_STORE_PASSWORD }}" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_KEY_ALIAS=${{ secrets.ALIAS }}" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_KEY_PASSWORD=${{ secrets.KEY_PASSWORD }}" >> ~/.gradle/gradle.properties
|
||||
echo -n ${{ secrets.KEYSTORE_FILE }} | base64 -d >> ~/keystore.jks
|
||||
echo "DC_RELEASE_STORE_FILE=$HOME/keystore.jks" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_STORE_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_KEY_ALIAS_FDROID=${{ secrets.ALIAS_FDROID }}" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_KEY_ALIAS_GPLAY=${{ secrets.ALIAS_GPLAY }}" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_KEY_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> ~/.gradle/gradle.properties
|
||||
./gradlew assembleFossRelease
|
||||
rm build/outputs/apk/foss/release/*universal*
|
||||
./gradlew assembleGplayRelease
|
||||
@@ -63,7 +64,7 @@ jobs:
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
body: '[<img src="store/get-it-on-fdroid.png" alt="Get it on F-Droid" height="48">](https://f-droid.org/packages/chat.delta.lite) [<img src="store/get-it-on-IzzyOnDroid.png" alt="Get it on IzzyOnDroid" height="48">](https://apt.izzysoft.de/fdroid/index/apk/chat.delta.lite) [<img src="store/get-it-on-apklis.png" alt="Disponible en Apklis" height="48">](https://www.apklis.cu/application/chat.delta.lite) [<img src="store/get-it-on-github.png" alt="Get it on GitHub" height="48">](https://github.com/ArcaneChat/android/releases/latest/download/ArcaneChat-gplay.apk)'
|
||||
body: '[<img src="store/get-it-on-gplay.png" alt="Get it on Google Play" height="48">](https://play.google.com/store/apps/details?id=com.github.arcanechat) [<img src="store/get-it-on-fdroid.png" alt="Get it on F-Droid" height="48">](https://f-droid.org/packages/chat.delta.lite) [<img src="store/get-it-on-IzzyOnDroid.png" alt="Get it on IzzyOnDroid" height="48">](https://apt.izzysoft.de/fdroid/index/apk/chat.delta.lite) [<img src="store/get-it-on-apklis.png" alt="Disponible en Apklis" height="48">](https://www.apklis.cu/application/chat.delta.lite) [<img src="store/get-it-on-github.png" alt="Get it on GitHub" height="48">](https://github.com/ArcaneChat/android/releases/latest/download/ArcaneChat-gplay.apk)'
|
||||
prerelease: ${{ contains(github.event.ref, '-beta') }}
|
||||
fail_on_unmatched_files: true
|
||||
files: build/outputs/apk/foss/release/*.apk
|
||||
|
||||
+99
-3
@@ -1,6 +1,94 @@
|
||||
# ArcaneChat Android Changelog
|
||||
|
||||
## v1.48.1
|
||||
## v1.52.1
|
||||
2025-01
|
||||
|
||||
* the app now requires less storage on your SD card by deduplicating newly received/sent files
|
||||
* some small bug fixes
|
||||
* update translations
|
||||
* update to core 1.155.1
|
||||
|
||||
## v1.52.0
|
||||
2025-01
|
||||
|
||||
* new group consistency algorithm
|
||||
* fix: don't show animated .webp stickers as static stickers
|
||||
* fix the chat shortcuts (created via long-press in launcher) to properly support multi-profile
|
||||
* fix some small bugs in certain android versions and special situations
|
||||
* avoid the app freezing in slow phones in some situations
|
||||
* improve menu in the help screen
|
||||
* update translations
|
||||
* update to core 1.155.0
|
||||
|
||||
## v1.50.5
|
||||
2025-01
|
||||
|
||||
* fix push-notifications handling for certain devices where it was not working correctly
|
||||
* update translations
|
||||
* using core 1.153.0
|
||||
|
||||
## v1.50.4
|
||||
2025-01
|
||||
|
||||
* properly send as animated stickers GIF files selected from keyboard
|
||||
* improve emoji picker in landscape mode and when changing from landscape to portrait
|
||||
* avoid crash when receiving push notifications if the user restricted the app from working in background
|
||||
* improve UI when attaching a file or image to easily recognize it is attached but not sent yet
|
||||
* avoid slow loading of in-chat apps in some devices when quickly re-opening an app after closing it
|
||||
* allow to select multiple images at once in the media picker via "Gallery" button
|
||||
* mark holiday notice messages as bot-generated
|
||||
* don't mark contacts as bot when receiving location-only and sync messages
|
||||
* prefer to encrypt even if peers have their preference to "no preference"
|
||||
* start ephemeral messages timers when the chat is archived or noticed
|
||||
* several bug fixes and updated translations
|
||||
* update to core 1.153.0
|
||||
|
||||
## v1.50.3
|
||||
2024-12
|
||||
|
||||
* Add in-chat apps picker to attachments options
|
||||
* Notify replies and reactions to your messages in muted chats (can be disabled in settings)
|
||||
* Cache HTTP GET requests (ex. when loading images from HTML messages)
|
||||
* update to core 1.152.0
|
||||
|
||||
## v1.50.2
|
||||
2024-12
|
||||
|
||||
* Encrypt notification tokens
|
||||
* update to core 1.151.5
|
||||
|
||||
## v1.50.0
|
||||
2024-12
|
||||
|
||||
* New emoji picker with support for more emojis
|
||||
* Webxdc apps can now trigger notifications
|
||||
* Webxdc apps can now deep-link to internal sections when you click their info-messages in chat
|
||||
* Add "Show in Chat" to the menu of opened Webxdc apps
|
||||
* Reverse order of messages in the notification group
|
||||
* Notify reactions to own messages
|
||||
* Improve the button to start Webxdc apps
|
||||
* Make account deletion confirmation dialog faster
|
||||
* Rename "Back up Chats to External Storage" to "Export Backup"
|
||||
* Improve compatibility with classic email clients in the outgoing messages
|
||||
* Removed internal font scaling setting in favor of the better system settings
|
||||
* Use privacy-preserving webxdc addresses
|
||||
* Use Rustls for connections with strict TLS
|
||||
* QR codes for adding contacts and joining groups provide help when opened in a normal browser
|
||||
* Mark Saved Messages chat as protected
|
||||
* Allow the user to replace maps integration
|
||||
* fix: Trim whitespace from scanned QR codes
|
||||
* fix quotes: Line-before-quote may be up to 120 character long instead of 80
|
||||
* fix: Prevent accidental wrong-password-notifications
|
||||
* fix: Remove footers from "Show Full Message..."
|
||||
* fix: Only add "member added/removed" messages if they actually do that
|
||||
* fix: Update state of message when fully downloading it
|
||||
* fix: send message: Do not fail if the message does not exist anymore
|
||||
* fix: Do not percent-encode dot when passing to autoconfig server (so, fix handling of some servers)
|
||||
* fix displaynames not being updated when intially scanned by a QR code
|
||||
* several bug fixes
|
||||
* update to core 1.151.3
|
||||
|
||||
## v1.48.3
|
||||
2024-10
|
||||
|
||||
* new Proxy settings screen available at "Advanced / Proxy"
|
||||
@@ -10,6 +98,8 @@
|
||||
* scan Proxies' QR code and use them
|
||||
* make Proxy URLs inside Delta Chat tappable
|
||||
* open Delta Chat when tapping Proxy URLs in other apps
|
||||
* support for realtime webxdc apps moved out of experimental and enabled by default
|
||||
* realtime webxdc apps can be disabled at "Settings / Advanced"
|
||||
* "New Contact / Link" button to view, share or copy the invite line
|
||||
* "New Contact / Scan" button to easier access the scanner functionality
|
||||
* open "New Contact" scan/show activities directly, do not try to be too smart and open the last active tab
|
||||
@@ -44,8 +134,10 @@
|
||||
* assign messages to ad-hoc group with matching name and members
|
||||
* use stricter TLS checks for HTTPS downloads (images in HTML mails, Autoconfig)
|
||||
* improve logging for failed QR code scans, AEAP, Autocrypt, notification permissions and sending errors
|
||||
* improve logging of multi account setup (log account ID)
|
||||
* show more context for the "Cannot establish guaranteed..." info message
|
||||
* show original file name in "Message Info"
|
||||
* show file name in "Message Info"
|
||||
* show root SMTP connection failure in connectivity view
|
||||
* fix: Sort received outgoing message down if it's fresher than all non fresh messages
|
||||
* fix: avoid app being killed when processing a PUSH notification
|
||||
* fix crash when refreshing avatar
|
||||
@@ -65,8 +157,12 @@
|
||||
* fix: normalize proxy URLs
|
||||
* fix connections getting stuck in "Updating..." sometimes
|
||||
* fix scanning "add second device" QR code from scanner above chatlist
|
||||
* fix warning about wrong password
|
||||
* fix app getting stale when receiving a PUSH notifications takes longer
|
||||
* fix app getting stale on network changes
|
||||
* fix: skip IDLE if we got unsolicited FETCH
|
||||
* update translations and local help
|
||||
* update to core 1.148.4
|
||||
* update to core 1.148.6
|
||||
|
||||
|
||||
## v1.46.14
|
||||
|
||||
+3
-3
@@ -34,10 +34,10 @@ ENV PATH ${PATH}:${ANDROID_SDK_ROOT}/cmdline-tools/bin
|
||||
# Install NDK manually. Other SDK parts are installed automatically by gradle.
|
||||
#
|
||||
# If you change the NDK version here, also change it in `flake.nix`.
|
||||
# NDK version r23c LTS aka 23.2.8568313
|
||||
RUN sdkmanager --sdk_root=${ANDROID_SDK_ROOT} 'ndk;23.2.8568313'
|
||||
# NDK version r27 LTS aka 27.0.11902837
|
||||
RUN sdkmanager --sdk_root=${ANDROID_SDK_ROOT} 'ndk;27.0.11902837'
|
||||
|
||||
ENV ANDROID_NDK_ROOT ${ANDROID_SDK_ROOT}/ndk/23.2.8568313
|
||||
ENV ANDROID_NDK_ROOT ${ANDROID_SDK_ROOT}/ndk/27.0.11902837
|
||||
ENV PATH ${PATH}:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/
|
||||
|
||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
## ArcaneChat Android Client
|
||||
|
||||
A [Delta Chat](https://delta.chat/) client for Android.
|
||||
A [Delta Chat](https://delta.chat/) client for Android. Learn more at: https://arcanechat.me
|
||||
|
||||
[<img src="store/get-it-on-gplay.png" alt="Get it on Google Play" height="48">](https://play.google.com/store/apps/details?id=com.github.arcanechat)
|
||||
[<img src="store/get-it-on-fdroid.png" alt="Get it on F-Droid" height="48">](https://f-droid.org/packages/chat.delta.lite)
|
||||
[<img src="store/get-it-on-IzzyOnDroid.png" alt="Get it on IzzyOnDroid" height="48">](https://apt.izzysoft.de/fdroid/index/apk/chat.delta.lite)
|
||||
[<img src="store/get-it-on-apklis.png" alt="Disponible en Apklis" height="48">](https://www.apklis.cu/application/chat.delta.lite)
|
||||
|
||||
+13
-8
@@ -48,7 +48,8 @@ the following steps are done in a PR called `prep-VERSION` (no leading "v"):
|
||||
6. build APKs:
|
||||
a) generate debug APK at "Build / Build Bundle(s)/APK / Build APK(s)"
|
||||
b) generate release APK at "Build / Generate Signed Bundle or APK",
|
||||
select "APK", add keys, flavor `gplayRelease`
|
||||
select "APK", add keys, flavor `gplayRelease`.
|
||||
this APK will go to the stores and is located at `gplay/release`
|
||||
|
||||
|
||||
## Push Test Releases
|
||||
@@ -79,16 +80,21 @@ only afterwards, push the APK to stores. **consider a blog post.**
|
||||
|
||||
on <https://play.google.com/apps/publish/>:
|
||||
|
||||
9. a) open "Delta Chat/Release/Production"
|
||||
then "Create new release" and upload APK from above
|
||||
9. a) open "Delta Chat / Test and release / Production"
|
||||
then "Create new release" and upload APK from above
|
||||
b) fill out "Release details/Release notes" (500 chars), add the line
|
||||
"These features will roll out over the coming days. Thanks for using Delta Chat!";
|
||||
release name should be default ("123 (1.2.3)")
|
||||
c) click "Next", set "Rollout Percentage" to 1% (later 2%, 5%, 10%, 20%, 50%, 100%),
|
||||
click "Save"
|
||||
c) click "Next", set "Rollout Percentage" to 50%, click "Save"
|
||||
d) Go to "Publishing Overview", "Managed publishing" is usually off;
|
||||
click "Send change for review", confirm
|
||||
|
||||
2 days later, change "Rollout Percentage" to 99%. Two more days later to 100%.
|
||||
Rollout is anyways slower in practise, however,
|
||||
only as long as we do not enter 100%, we can retract the version
|
||||
(Once we reach 100%, we have to submit a new version for approval.
|
||||
During these up to 4 days, sometimes longer, we cannot do anything on existing rollout)
|
||||
|
||||
|
||||
## Tag for F-Droid and create Github release
|
||||
|
||||
@@ -111,9 +117,8 @@ on <https://developer.amazon.com/dashboard>:
|
||||
12. a) for "Delta Chat", select "Add upcoming version" on the left
|
||||
b) at "Step 1 / Existing file(s)" hit "Replace", upload the APK from above
|
||||
c) on the "Step 1" page, add "Release notes" from CHANGELOG.md, hit "Next"
|
||||
d) on "Step 2" page: "Does your app collect or transfer user data to third parties?" -> No, then "Next"
|
||||
e) on "Step 3" page: "Next"
|
||||
f) on "Step 4" page: "Submit app"
|
||||
d) on "Step 2" and "Step 3" pages, hit "Next"
|
||||
e) on "Step 4" page: "Submit app"
|
||||
|
||||
|
||||
## Release on Huawei AppGallery
|
||||
|
||||
+45
-27
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id 'com.android.application' version '8.1.4'
|
||||
id 'com.android.application' version '8.5.2'
|
||||
id 'com.google.gms.google-services' version '4.4.1'
|
||||
}
|
||||
|
||||
@@ -29,12 +29,12 @@ android {
|
||||
// > Task :stripFatDebugDebugSymbols
|
||||
// Unable to strip the following libraries, packaging them as they are: libanimation-decoder-gif.so, libnative-utils.so.
|
||||
// See <https://issuetracker.google.com/issues/237187538> for details.
|
||||
ndkVersion "23.2.8568313"
|
||||
ndkVersion "27.0.12077973"
|
||||
useLibrary 'org.apache.http.legacy'
|
||||
|
||||
defaultConfig {
|
||||
versionCode 30000694
|
||||
versionName "1.48.2"
|
||||
versionCode 30000708
|
||||
versionName "1.52.2"
|
||||
|
||||
applicationId "chat.delta.lite"
|
||||
multiDexEnabled true
|
||||
@@ -87,15 +87,45 @@ android {
|
||||
storeFile file(DC_DEBUG_STORE_FILE )
|
||||
}
|
||||
}
|
||||
release {
|
||||
releaseFdroid {
|
||||
// can be defined at `~/.gradle/gradle.properties` or at "Build/Generate signed APK"
|
||||
if(project.hasProperty("DC_RELEASE_STORE_FILE")) {
|
||||
storeFile file(DC_RELEASE_STORE_FILE)
|
||||
storePassword DC_RELEASE_STORE_PASSWORD
|
||||
keyAlias DC_RELEASE_KEY_ALIAS
|
||||
keyAlias DC_RELEASE_KEY_ALIAS_FDROID
|
||||
keyPassword DC_RELEASE_KEY_PASSWORD
|
||||
}
|
||||
}
|
||||
releaseApk {
|
||||
// can be defined at `~/.gradle/gradle.properties` or at "Build/Generate signed APK"
|
||||
if(project.hasProperty("DC_RELEASE_STORE_FILE")) {
|
||||
storeFile file(DC_RELEASE_STORE_FILE)
|
||||
storePassword DC_RELEASE_STORE_PASSWORD
|
||||
keyAlias DC_RELEASE_KEY_ALIAS_GPLAY
|
||||
keyPassword DC_RELEASE_KEY_PASSWORD
|
||||
}
|
||||
}
|
||||
releaseBundle {
|
||||
if(project.hasProperty("DC_BUNDLE_STORE_FILE")) {
|
||||
storeFile file(DC_BUNDLE_STORE_FILE)
|
||||
storePassword DC_BUNDLE_STORE_PASSWORD
|
||||
keyAlias DC_BUNDLE_KEY_ALIAS
|
||||
keyPassword DC_BUNDLE_STORE_PASSWORD
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
foss {
|
||||
dimension "none"
|
||||
buildConfigField "boolean", "USE_PLAY_SERVICES", "false"
|
||||
}
|
||||
gplay {
|
||||
dimension "none"
|
||||
apply plugin: "com.google.gms.google-services"
|
||||
buildConfigField "boolean", "USE_PLAY_SERVICES", "true"
|
||||
applicationId "com.github.arcanechat"
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -114,23 +144,12 @@ android {
|
||||
// nb: it is highly recommended to use the same settings in debug+release -
|
||||
// otherwise problems might be noticed delayed only
|
||||
minifyEnabled true
|
||||
signingConfig signingConfigs.release
|
||||
productFlavors.foss.signingConfig signingConfigs.releaseFdroid
|
||||
productFlavors.gplay.signingConfig signingConfigs.releaseApk
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
foss {
|
||||
dimension "none"
|
||||
buildConfigField "boolean", "USE_PLAY_SERVICES", "false"
|
||||
}
|
||||
gplay {
|
||||
dimension "none"
|
||||
apply plugin: "com.google.gms.google-services"
|
||||
buildConfigField "boolean", "USE_PLAY_SERVICES", "true"
|
||||
}
|
||||
}
|
||||
|
||||
if(!project.hasProperty("ABI_FILTER")) {
|
||||
splits {
|
||||
abi {
|
||||
@@ -190,7 +209,7 @@ dependencies {
|
||||
implementation 'com.airbnb.android:lottie:4.2.2' // Lottie animations support.
|
||||
|
||||
implementation 'androidx.sharetarget:sharetarget:1.2.0'
|
||||
implementation 'androidx.webkit:webkit:1.11.0'
|
||||
implementation 'androidx.webkit:webkit:1.12.1'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||
implementation 'com.google.android.material:material:1.12.0'
|
||||
@@ -206,11 +225,11 @@ dependencies {
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.6.2'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
|
||||
implementation 'androidx.work:work-runtime:2.9.1'
|
||||
implementation 'androidx.emoji2:emoji2-emojipicker:1.4.0'
|
||||
implementation 'androidx.emoji2:emoji2-emojipicker:1.5.0'
|
||||
implementation 'com.google.guava:guava:31.1-android'
|
||||
implementation 'com.google.android.exoplayer:exoplayer-core:2.19.1' // plays video and audio
|
||||
implementation 'com.google.android.exoplayer:exoplayer-ui:2.19.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
|
||||
implementation 'com.google.zxing:core:3.3.0' // fixed version to support SDK<24
|
||||
implementation ('com.journeyapps:zxing-android-embedded:4.3.0') { transitive = false } // QR Code scanner
|
||||
implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.1' // used as JSON library
|
||||
@@ -218,14 +237,13 @@ dependencies {
|
||||
implementation "me.leolin:ShortcutBadger:1.1.16" // display messagecount on the home screen icon.
|
||||
implementation 'com.jpardogo.materialtabstrip:library:1.0.9' // used in the emoji selector for the tab selection.
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.1.3' // does the zooming on photos / media
|
||||
implementation 'com.github.penfeizhou.android.animation:glide-plugin:2.25.0' // APNG & animated webp support.
|
||||
implementation 'com.github.penfeizhou.android.animation:glide-plugin:3.0.2' // APNG & animated webp support.
|
||||
implementation 'com.caverock:androidsvg-aar:1.4' // SVG support.
|
||||
implementation 'com.github.bumptech.glide:glide:4.12.0'
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
|
||||
annotationProcessor 'androidx.annotation:annotation:1.8.2'
|
||||
annotationProcessor 'androidx.annotation:annotation:1.9.1'
|
||||
implementation 'com.makeramen:roundedimageview:2.1.0' // crops the avatars to circles
|
||||
implementation 'com.pnikosis:materialish-progress:1.5' // used only in the "Progress Wheel" in Share Activity.
|
||||
implementation 'com.soundcloud.android:android-crop:1.0.1@aar' // used for profile and group avatar selection in Android SDK<19
|
||||
implementation 'com.github.amulyakhare:TextDrawable:558677ea31' // number of unread messages,
|
||||
// the one-letter circle for the contacts (when there is not avatar) and a white background.
|
||||
implementation 'com.googlecode.mp4parser:isoparser:1.0.6' // MP4 recoding; upgrading eg. to 1.1.22 breaks recoding, however, i have not investigated further, just reset to 1.0.6
|
||||
@@ -240,7 +258,7 @@ dependencies {
|
||||
// <https://github.com/cketti/SafeContentResolver>
|
||||
implementation 'de.cketti.safecontentresolver:safe-content-resolver-v14:1.0.0'
|
||||
|
||||
gplayImplementation('com.google.firebase:firebase-messaging:24.0.0') { // for PUSH notifications
|
||||
gplayImplementation('com.google.firebase:firebase-messaging:24.1.0') { // for PUSH notifications
|
||||
exclude group: 'com.google.firebase', module: 'firebase-core'
|
||||
exclude group: 'com.google.firebase', module: 'firebase-analytics'
|
||||
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
|
||||
@@ -254,7 +272,7 @@ dependencies {
|
||||
testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.1'
|
||||
testImplementation 'org.powermock:powermock-classloading-xstream:1.6.1'
|
||||
|
||||
androidTestImplementation 'androidx.test:runner:1.6.1'
|
||||
androidTestImplementation 'androidx.test:runner:1.6.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.6.1'
|
||||
androidTestImplementation 'androidx.test:rules:1.6.1'
|
||||
|
||||
@@ -17,19 +17,21 @@ ArcaneChat is a Delta Chat client and was created with a focus on usability, goo
|
||||
<b>Main differences with official Delta Chat client:</b>
|
||||
|
||||
<ul>
|
||||
<li>Basic markdown support (bold, italic, strike, etc.)</li>
|
||||
<li>Support for some markdown styles in text messages (bold, italic, strike, etc.)</li>
|
||||
<li>Support for displaying Telegram's animated stickers (.tgs files)</li>
|
||||
<li>Support for SVG images previews</li>
|
||||
<li>Multiple color themes/skins</li>
|
||||
<li>It is possible to disable accounts to completely disconnect them to save data/bandwidth</li>
|
||||
<li>It is possible to disable profiles to completely disconnect them saving data/bandwidth</li>
|
||||
<li>You can easily see the connection status of all your profiles in the profile switcher</li>
|
||||
<li>A videochat instance is set by default</li>
|
||||
<li>Replies to your messages in muted groups trigger notifications</li>
|
||||
<li>Location streaming feature enabled by default and extra option to share location for 12 hours</li>
|
||||
<li>Clicking on a message with a POI location, will open the POI on the map</li>
|
||||
<li>Last-seen status of contacts is shown in your contact list, like in WhatsApp, Telegram, etc.</li>
|
||||
<li>Videos are played in loop, useful for short GIF videos</li>
|
||||
<li>Verified icon is shown in the chat list for the "Device Messages" chat</li>
|
||||
<li>Voice messages have more aggressive compression in "worse quality" mode to save data plan</li>
|
||||
<li>Automatic download of messages limited to 640KB by default</li>
|
||||
<li>Account's display name is always shown in the app's title bar instead of the name of the app</li>
|
||||
<li>Profile's display name is always shown in the app's title bar instead of the name of the app</li>
|
||||
<li>Your avatar is visible to other users in Mailing Lists</li>
|
||||
<li>Can be selected as app to open .xdc files</li>
|
||||
<li>For mini-apps developers: there are some extra features in the WebXDC API, check https://github.com/ArcaneChat/android/#webxdc</li>
|
||||
|
||||
Generated
+26
-94
@@ -3,15 +3,15 @@
|
||||
"android": {
|
||||
"inputs": {
|
||||
"devshell": "devshell",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710633978,
|
||||
"narHash": "sha256-yemnwSvW7cdWtXGpivFA5jDO35rGPs6fqxlQ4l6ODXs=",
|
||||
"lastModified": 1733948466,
|
||||
"narHash": "sha256-o/uq/tU458Ykudi8Zk3sRga5iazkuSczt9wDOCUDOSU=",
|
||||
"owner": "tadfisher",
|
||||
"repo": "android-nixpkgs",
|
||||
"rev": "e91fb3d8517538e5ad9b422c9a4f604b56008a9e",
|
||||
"rev": "0bf99ffaea6a7c0948ae10cf2e40c2905e4e4d6b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -22,18 +22,17 @@
|
||||
},
|
||||
"devshell": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": [
|
||||
"android",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1708939976,
|
||||
"narHash": "sha256-O5+nFozxz2Vubpdl1YZtPrilcIXPcRAjqNdNE8oCRoA=",
|
||||
"lastModified": 1728330715,
|
||||
"narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=",
|
||||
"owner": "numtide",
|
||||
"repo": "devshell",
|
||||
"rev": "5ddecd67edbd568ebe0a55905273e56cc82aabe3",
|
||||
"rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -47,11 +46,11 @@
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1701680307,
|
||||
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -65,47 +64,11 @@
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709126324,
|
||||
"narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=",
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "d465f4819400de7c8d874d50b982301f28a84605",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_3": {
|
||||
"inputs": {
|
||||
"systems": "systems_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_4": {
|
||||
"inputs": {
|
||||
"systems": "systems_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1705309234,
|
||||
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -116,11 +79,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1709237383,
|
||||
"narHash": "sha256-cy6ArO4k5qTx+l5o+0mL9f5fa86tYUX3ozE1S+Txlds=",
|
||||
"lastModified": 1733759999,
|
||||
"narHash": "sha256-463SNPWmz46iLzJKRzO3Q2b0Aurff3U1n0nYItxq7jU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "1536926ef5621b09bba54035ae2bb6d806d72ac8",
|
||||
"rev": "a73246e2eef4c6ed172979932bc80e1404ba2d56",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -132,11 +95,11 @@
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1710889954,
|
||||
"narHash": "sha256-Pr6F5Pmd7JnNEMHHmspZ0qVqIBVxyZ13ik1pJtm2QXk=",
|
||||
"lastModified": 1733749988,
|
||||
"narHash": "sha256-+5qdtgXceqhK5ZR1YbP1fAUsweBIrhL38726oIEAtDs=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "7872526e9c5332274ea5932a0c3270d6e4724f3b",
|
||||
"rev": "bc27f0fde01ce4e1bfec1ab122d72b7380278e68",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -148,11 +111,11 @@
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1706487304,
|
||||
"narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=",
|
||||
"lastModified": 1728538411,
|
||||
"narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "90f456026d284c22b3e3497be980b2e47d0b28ac",
|
||||
"rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -165,22 +128,21 @@
|
||||
"root": {
|
||||
"inputs": {
|
||||
"android": "android",
|
||||
"flake-utils": "flake-utils_3",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"rust-overlay": "rust-overlay"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_4",
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1711073443,
|
||||
"narHash": "sha256-PpNb4xq7U5Q/DdX40qe7CijUsqhVVM3VZrhN0+c6Lcw=",
|
||||
"lastModified": 1733970833,
|
||||
"narHash": "sha256-sPEKtSaZk2CtfF9cdhtbY93S6qGq+d2PKI1fcoDfDaI=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "eec55ba9fcde6be4c63942827247e42afef7fafe",
|
||||
"rev": "f7f4c59ccdf1bec3f1547d27398e9589aa94e3e8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -218,36 +180,6 @@
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_3": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_4": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
|
||||
@@ -15,12 +15,11 @@
|
||||
pkgs = import nixpkgs { inherit system overlays; };
|
||||
android-sdk = android.sdk.${system} (sdkPkgs:
|
||||
with sdkPkgs; [
|
||||
build-tools-33-0-1
|
||||
build-tools-34-0-0
|
||||
cmdline-tools-latest
|
||||
ndk-bundle
|
||||
platform-tools
|
||||
platforms-android-34
|
||||
ndk-23-2-8568313
|
||||
ndk-27-0-11902837
|
||||
]);
|
||||
rust-version = pkgs.lib.removeSuffix "\n"
|
||||
(builtins.readFile ./scripts/rust-toolchain);
|
||||
@@ -28,7 +27,7 @@
|
||||
devShells.default = pkgs.mkShell {
|
||||
ANDROID_SDK_ROOT = "${android-sdk}/share/android-sdk";
|
||||
ANDROID_NDK_ROOT =
|
||||
"${android-sdk}/share/android-sdk/ndk/23.2.8568313";
|
||||
"${android-sdk}/share/android-sdk/ndk/27.0.11902837";
|
||||
buildInputs = [
|
||||
android-sdk
|
||||
pkgs.openjdk17
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:922391085500:android:6f54e2c4e49405673e2bb9",
|
||||
"android_client_info": {
|
||||
"package_name": "chat.delta.lite.beta"
|
||||
"package_name": "com.github.arcanechat.beta"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
@@ -47,7 +47,7 @@
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:922391085500:android:aff82fbc40c8172e3e2bb9",
|
||||
"android_client_info": {
|
||||
"package_name": "chat.delta.lite"
|
||||
"package_name": "com.github.arcanechat"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
@@ -66,7 +66,7 @@
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:922391085500:android:92b4cf12669cc2083e2bb9",
|
||||
"android_client_info": {
|
||||
"package_name": "com.github.arcanechat"
|
||||
"package_name": "chat.delta.lite"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
@@ -85,7 +85,7 @@
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:922391085500:android:228a205b8aa2bacc3e2bb9",
|
||||
"android_client_info": {
|
||||
"package_name": "com.github.arcanechat.beta"
|
||||
"package_name": "chat.delta.lite.beta"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
|
||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
+36
-71
@@ -7,57 +7,6 @@
|
||||
#include "deltachat-core-rust/deltachat-ffi/deltachat.h"
|
||||
|
||||
|
||||
#if __ANDROID_API__ == 16
|
||||
unsigned long getauxval(unsigned long type) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
|
||||
int flags)
|
||||
{
|
||||
if (flags != 0) {
|
||||
// Not supported by the fallback.
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vlen == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t n = sendmsg(sockfd, &msgvec->msg_hdr, flags);
|
||||
if (n == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
(*msgvec).msg_len = n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
|
||||
int flags, struct timespec *timeout)
|
||||
{
|
||||
if (flags != 0) {
|
||||
// Not supported by the fallback.
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vlen == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n = recvmsg(sockfd, &msgvec->msg_hdr, flags);
|
||||
if (n == -1) {
|
||||
return -1;
|
||||
}
|
||||
(*msgvec).msg_len = n;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static dc_msg_t* get_dc_msg(JNIEnv *env, jobject obj);
|
||||
|
||||
|
||||
@@ -753,12 +702,6 @@ JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_resendMsgs(JNIEnv *env, job
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcContext_prepareMsg(JNIEnv *env, jobject obj, jint chat_id, jobject msg)
|
||||
{
|
||||
return dc_prepare_msg(get_dc_context(env, obj), chat_id, get_dc_msg(env, msg));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcContext_sendMsg(JNIEnv *env, jobject obj, jint chat_id, jobject msg)
|
||||
{
|
||||
return dc_send_msg(get_dc_context(env, obj), chat_id, get_dc_msg(env, msg));
|
||||
@@ -780,12 +723,10 @@ JNIEXPORT jint Java_com_b44t_messenger_DcContext_sendVideochatInvitation(JNIEnv
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_sendWebxdcStatusUpdate(JNIEnv *env, jobject obj, jint msg_id, jstring payload, jstring descr)
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_sendWebxdcStatusUpdate(JNIEnv *env, jobject obj, jint msg_id, jstring payload)
|
||||
{
|
||||
CHAR_REF(payload);
|
||||
CHAR_REF(descr);
|
||||
jboolean ret = dc_send_webxdc_status_update(get_dc_context(env, obj), msg_id, payloadPtr, descrPtr) != 0;
|
||||
CHAR_UNREF(descr);
|
||||
jboolean ret = dc_send_webxdc_status_update(get_dc_context(env, obj), msg_id, payloadPtr, NULL) != 0;
|
||||
CHAR_UNREF(payload);
|
||||
return ret;
|
||||
}
|
||||
@@ -1423,12 +1364,6 @@ JNIEXPORT jint Java_com_b44t_messenger_DcMsg_getId(JNIEnv *env, jobject obj)
|
||||
return dc_msg_get_id(get_dc_msg(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isOutgoing(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jboolean)(dc_msg_is_outgoing(get_dc_msg(env, obj))!=0);
|
||||
}
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcMsg_getSenderColor(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return dc_msg_get_sender_color(get_dc_msg(env, obj));
|
||||
@@ -1626,15 +1561,18 @@ JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getWebxdcInfoJson(JNIEnv *env, j
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isForwarded(JNIEnv *env, jobject obj)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getWebxdcHref(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return dc_msg_is_forwarded(get_dc_msg(env, obj))!=0;
|
||||
char* temp = dc_msg_get_webxdc_href(get_dc_msg(env, obj));
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
dc_str_unref(temp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isIncreation(JNIEnv *env, jobject obj)
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isForwarded(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return dc_msg_is_increation(get_dc_msg(env, obj))!=0;
|
||||
return dc_msg_is_forwarded(get_dc_msg(env, obj))!=0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1714,6 +1652,33 @@ JNIEXPORT void Java_com_b44t_messenger_DcMsg_setFile(JNIEnv *env, jobject obj, j
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcMsg_forceSticker(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_msg_force_sticker(get_dc_msg(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getPOILocation(JNIEnv *env, jobject obj)
|
||||
{
|
||||
char* temp = dc_msg_get_poi_location(get_dc_msg(env, obj));
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
dc_str_unref(temp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcMsg_setFileAndDeduplicate(JNIEnv *env, jobject obj, jstring file, jstring name, jstring filemime)
|
||||
{
|
||||
CHAR_REF(file);
|
||||
CHAR_REF(name);
|
||||
CHAR_REF(filemime);
|
||||
dc_msg_set_file_and_deduplicate(get_dc_msg(env, obj), filePtr, namePtr, filemimePtr);
|
||||
CHAR_UNREF(filemime);
|
||||
CHAR_UNREF(name);
|
||||
CHAR_UNREF(file);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcMsg_setDimension(JNIEnv *env, jobject obj, int width, int height)
|
||||
{
|
||||
dc_msg_set_dimension(get_dc_msg(env, obj), width, height);
|
||||
|
||||
+1
-1
Submodule jni/deltachat-core-rust updated: f66fbc2e29...e98f6a2c9b
@@ -1 +1 @@
|
||||
../deltachat-pages/tools/create-local-help.py ../deltachat-pages/_site src/main/assets/help
|
||||
../deltachat-pages/tools/create-local-help.py ../deltachat-pages/result src/main/assets/help
|
||||
|
||||
+11
-10
@@ -38,8 +38,6 @@
|
||||
#
|
||||
# If anything doesn't work, please open an issue!!
|
||||
|
||||
"$(dirname "$0")/rebrand.sh"
|
||||
|
||||
set -e
|
||||
echo "starting time: `date`"
|
||||
|
||||
@@ -77,9 +75,9 @@ if test -z "$NDK_HOST_TAG"; then
|
||||
fi
|
||||
|
||||
TOOLCHAIN="$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/$NDK_HOST_TAG"
|
||||
export CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER="$TOOLCHAIN/bin/armv7a-linux-androideabi16-clang"
|
||||
export CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER="$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang"
|
||||
export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="$TOOLCHAIN/bin/aarch64-linux-android21-clang"
|
||||
export CARGO_TARGET_I686_LINUX_ANDROID_LINKER="$TOOLCHAIN/bin/i686-linux-android16-clang"
|
||||
export CARGO_TARGET_I686_LINUX_ANDROID_LINKER="$TOOLCHAIN/bin/i686-linux-android21-clang"
|
||||
export CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER="$TOOLCHAIN/bin/x86_64-linux-android21-clang"
|
||||
|
||||
export RUSTUP_TOOLCHAIN=$(cat "$(dirname "$0")/rust-toolchain")
|
||||
@@ -125,10 +123,10 @@ unset CPATH
|
||||
|
||||
if test -z $1 || test $1 = armeabi-v7a; then
|
||||
echo "-- cross compiling to armv7-linux-androideabi (arm) --"
|
||||
TARGET_CC="$TOOLCHAIN/bin/armv7a-linux-androideabi16-clang" \
|
||||
TARGET_CC="$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang" \
|
||||
TARGET_AR="$TOOLCHAIN/bin/llvm-ar" \
|
||||
TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib" \
|
||||
cargo build $RELEASEFLAG --target armv7-linux-androideabi -p deltachat_ffi --features jsonrpc
|
||||
cargo build $RELEASEFLAG --target armv7-linux-androideabi -p deltachat_ffi
|
||||
cp $CARGO_TARGET_DIR/armv7-linux-androideabi/$RELEASE/libdeltachat.a $jnidir/armeabi-v7a
|
||||
fi
|
||||
|
||||
@@ -137,16 +135,16 @@ if test -z $1 || test $1 = arm64-v8a; then
|
||||
TARGET_CC="$TOOLCHAIN/bin/aarch64-linux-android21-clang" \
|
||||
TARGET_AR="$TOOLCHAIN/bin/llvm-ar" \
|
||||
TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib" \
|
||||
cargo build $RELEASEFLAG --target aarch64-linux-android -p deltachat_ffi --features jsonrpc
|
||||
cargo build $RELEASEFLAG --target aarch64-linux-android -p deltachat_ffi
|
||||
cp $CARGO_TARGET_DIR/aarch64-linux-android/$RELEASE/libdeltachat.a $jnidir/arm64-v8a
|
||||
fi
|
||||
|
||||
if test -z $1 || test $1 = x86; then
|
||||
echo "-- cross compiling to i686-linux-android (x86) --"
|
||||
TARGET_CC="$TOOLCHAIN/bin/i686-linux-android16-clang" \
|
||||
TARGET_CC="$TOOLCHAIN/bin/i686-linux-android21-clang" \
|
||||
TARGET_AR="$TOOLCHAIN/bin/llvm-ar" \
|
||||
TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib" \
|
||||
cargo build $RELEASEFLAG --target i686-linux-android -p deltachat_ffi --features jsonrpc
|
||||
cargo build $RELEASEFLAG --target i686-linux-android -p deltachat_ffi
|
||||
cp $CARGO_TARGET_DIR/i686-linux-android/$RELEASE/libdeltachat.a $jnidir/x86
|
||||
fi
|
||||
|
||||
@@ -155,7 +153,7 @@ fi
|
||||
TARGET_CC="$TOOLCHAIN/bin/x86_64-linux-android21-clang" \
|
||||
TARGET_AR="$TOOLCHAIN/bin/llvm-ar" \
|
||||
TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib" \
|
||||
cargo build $RELEASEFLAG --target x86_64-linux-android -p deltachat_ffi --features jsonrpc
|
||||
cargo build $RELEASEFLAG --target x86_64-linux-android -p deltachat_ffi
|
||||
cp $CARGO_TARGET_DIR/x86_64-linux-android/$RELEASE/libdeltachat.a $jnidir/x86_64
|
||||
fi
|
||||
|
||||
@@ -176,4 +174,7 @@ else
|
||||
rm -f ndkArch # Remove ndkArch, ignore if it doesn't exist
|
||||
fi
|
||||
|
||||
"$(dirname "$0")/rebrand.sh"
|
||||
|
||||
|
||||
echo "ending time: `date`"
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.77.0
|
||||
1.83.0
|
||||
|
||||
@@ -4,3 +4,4 @@ find ./src/main/assets/help/ -type f -name '*.html' | xargs sed -i 's/github.com
|
||||
find ./src/main/assets/help/ -type f -name '*.html' | xargs sed -i 's/ArcaneChat/Delta Chat/g'
|
||||
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/github.com\/ArcaneChat/get.delta.chat/g'
|
||||
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/ArcaneChat/Delta Chat/g'
|
||||
sed -i 's/>Delta Chat</>ArcaneChat</g' ./src/main/res/values/strings.xml
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e # stop on all errors
|
||||
|
||||
git submodule update --init --recursive
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
VERSION=$1
|
||||
|
||||
@@ -29,7 +30,6 @@ echo ""
|
||||
echo "and now: here is Delta Chat $VERSION - choose your flavour and mind your backups:"
|
||||
echo "- 🍋 https://download.delta.chat/android/beta/deltachat-gplay-release-$VERSION.apk (google play candidate, overwrites existing installs, should keep data)"
|
||||
echo "- 🍉 https://download.delta.chat/android/beta/deltachat-foss-debug-$VERSION.apk (f-droid candidate, can be installed beside google play)"
|
||||
echo "- 🍏 https://testflight.apple.com/join/uEMc1NxS (ios, update to $VERSION may take a day or so)"
|
||||
echo ""
|
||||
echo "what to test: PLEASE_FILL_OUT"
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
VERSION=$1
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ public class SharingTest {
|
||||
}
|
||||
}
|
||||
Uri uri = Uri.parse("content://" + BuildConfig.APPLICATION_ID + ".attachments/" + Uri.encode(pngImage));
|
||||
DcHelper.sharedFiles.put("/" + pngImage, 1);
|
||||
DcHelper.sharedFiles.put(pngImage, 1);
|
||||
|
||||
Intent i = new Intent(Intent.ACTION_SEND);
|
||||
i.setType("image/png");
|
||||
|
||||
@@ -28,11 +28,6 @@ public class FcmReceiveService extends FirebaseMessagingService {
|
||||
private static volatile String prefixedToken;
|
||||
|
||||
public static void register(Context context) {
|
||||
if (Build.VERSION.SDK_INT < 19) {
|
||||
Log.w(TAG, "FCM not available on SDK < 19");
|
||||
triedRegistering = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (FcmReceiveService.prefixedToken != null) {
|
||||
Log.i(TAG, "FCM already registered");
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
@@ -66,6 +65,10 @@
|
||||
android:resource="@xml/automotive_app_desc" />
|
||||
-->
|
||||
|
||||
<!-- Opt out of metrics collection: https://developer.android.com/develop/ui/views/layout/webapps/managing-webview#metrics -->
|
||||
<meta-data android:name="android.webkit.WebView.MetricsOptOut"
|
||||
android:value="true" />
|
||||
|
||||
<activity android:name=".ShareActivity"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||
android:excludeFromRecents="true"
|
||||
@@ -325,8 +328,6 @@
|
||||
android:theme="@style/TextSecure.ScribbleTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
|
||||
<activity android:name="com.soundcloud.android.crop.CropImageActivity" />
|
||||
|
||||
<activity android:name=".InstantOnboardingActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:windowSoftInputMode="stateHidden|adjustResize"
|
||||
@@ -385,6 +386,11 @@
|
||||
android:exported="true">
|
||||
</activity>
|
||||
|
||||
<activity android:name=".WebxdcStoreActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize|uiMode">
|
||||
</activity>
|
||||
|
||||
<activity android:name=".FullMsgActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#lze-delta-chat-používat-s-protonmail--tutanota--criptext">Lze Delta Chat používat s Protonmail / Tutanota / Criptext?</a></li>
|
||||
<li><a href="#remove-account">How can I delete my account?</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>
|
||||
<li><a href="#where-can-my-friends-find-delta-chat">Where can my friends find Delta Chat?</a></li>
|
||||
<li><a href="#jak-je-financován-vývoj-delta-chatu">Jak je financován vývoj Delta Chatu?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -297,8 +298,7 @@ Archived chats remain accessible above the chat list or via search.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>To archive or pin a chat, long tap (Android), use the chat’s menu (Android/Desktop) or swipe to the left (iOS);
|
||||
to mute a chat, use the chat’s menu (Android/Desktop) or the chat’s profile (iOS).</p>
|
||||
<p>To use the functions, long tap or right click a chat in the chat list.</p>
|
||||
|
||||
<h3 id="what-does-the-green-dot-mean">
|
||||
|
||||
@@ -599,16 +599,16 @@ to any system involved in the delivery of Push Notifications.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>A Delta Chat app obtains a “device token” locally and stores it
|
||||
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
|
||||
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
|
||||
it forwards the “device token” to the central Delta Chat notification proxy.</p>
|
||||
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The central Delta Chat notification proxy forwards
|
||||
the “device token” to the respective Push service (Apple, Google, etc.),
|
||||
<p>The central Delta Chat notification proxy decrypts the device token
|
||||
and forwards it to the respective Push service (Apple, Google, etc.),
|
||||
without ever knowing the IP or e-mail address of Delta Chat users.</p>
|
||||
</li>
|
||||
<li>
|
||||
@@ -621,14 +621,15 @@ and also never see any message content (also not in encrypted forms).</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>As of May 2024, chatmail servers know about “device tokens”
|
||||
but we plan to encrypt this information to the notification proxy
|
||||
such that the chatmail server never learns the device token.</p>
|
||||
|
||||
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
|
||||
and forgets about device-tokens as soon as Apple/Google/etc processed them,
|
||||
usually in a matter of milliseconds.</p>
|
||||
|
||||
<p>Note that the device token is encrypted between apps and notification proxy
|
||||
but it is not signed.
|
||||
The notification proxy thus never sees e-mail addresses, IP-addresses or
|
||||
any cryptographic identity information associated with a user’s device (token).</p>
|
||||
|
||||
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
|
||||
or the full seizure of the central Delta Chat notification proxy
|
||||
would not reveal private information that Push services do not already have.</p>
|
||||
@@ -1309,6 +1310,12 @@ One device is not needed for the other to work.</p>
|
||||
and make sure, <strong>Private Network</strong> is selected as “Network profile type”
|
||||
(after transfer, you can change back to the original value)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>iOS</strong>, make sure “System Settings / Apps / Delta Chat / <strong>Local Network</strong>” access is granted</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>macOS</strong>, enable “System Settings / Privacy & Security / <strong>Local Network</strong> / Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Your system might have a “personal firewall”,
|
||||
which is known to cause problems (especially on Windows).
|
||||
@@ -1425,6 +1432,7 @@ you only open attachments from senders you trust, and not from spammers.</li>
|
||||
<ul>
|
||||
<li>In general, anyone can share webxdc apps with each
|
||||
other without restrictions.</li>
|
||||
<li>From <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
|
||||
<li>You can <a href="https://delta.chat/en/2023-08-11-xstore">send ‘hi’ to xstore@testrun.org</a>
|
||||
to see an experimental webxdc appstore.
|
||||
All of the apps are open source and for free.</li>
|
||||
@@ -1874,6 +1882,35 @@ Otherwise you might receive undecryptable messages from those group chats.</p>
|
||||
<li>Dobrý začátek je <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">Standards used in Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="where-can-my-friends-find-delta-chat">
|
||||
|
||||
|
||||
Where can my friends find Delta Chat? <a href="#where-can-my-friends-find-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat is available for all major and some minor platforms:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>The <strong>official website</strong>, <a href="https://delta.chat/download">https://delta.chat/download</a> shows all options in detail</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If unavailable, use the <strong>mirror</strong> at <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, Amazon App Store, iOS and macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Check the <strong>package manager</strong> of your Linux distributions</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Android APKs</strong> are also available on <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="jak-je-financován-vývoj-delta-chatu">
|
||||
|
||||
|
||||
|
||||
@@ -30,14 +30,14 @@
|
||||
<li><a href="#was-sind-push-benachrichtigungen-wie-kann-ich-nachrichten-sofort-erhalten">Was sind Push-Benachrichtigungen? Wie kann ich Nachrichten sofort erhalten?</a></li>
|
||||
<li><a href="#sind-push-benachrichtigungen-auf-ios-geräten-aktiviert-gibt-es-alternativen">Sind Push-Benachrichtigungen auf iOS-Geräten aktiviert? Gibt es Alternativen?</a></li>
|
||||
<li><a href="#android-push">Sind Push-Benachrichtigungen auf Android-Geräten aktiviert/erforderlich?</a></li>
|
||||
<li><a href="#privacy-notifications">Wie privat sind Delta Chat Push-Benachrichtigungen?</a></li>
|
||||
<li><a href="#privacy-notifications">Wie privat sind Delta-Chat-Push-Benachrichtigungen?</a></li>
|
||||
<li><a href="#warum-integriert-sich-delta-chat-in-zentralisierte-proprietäre-applegoogle-push-dienste">Warum integriert sich Delta Chat in zentralisierte, proprietäre Apple/Google-Push-Dienste?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#verschlüsselung-und-sicherheit">Verschlüsselung und Sicherheit</a>
|
||||
<ul>
|
||||
<li><a href="#welche-standards-werden-für-die-ende-zu-ende-verschlüsselung-verwendet">Welche Standards werden für die Ende-zu-Ende-Verschlüsselung verwendet?</a></li>
|
||||
<li><a href="#whene2e">Wie kann ich wissen, ob Nachrichten Ende-zu-Ende verschlüsselt sind?</a></li>
|
||||
<li><a href="#whene2e">Wie kann ich wissen, ob Nachrichten Ende-zu-Ende-verschlüsselt sind?</a></li>
|
||||
<li><a href="#howtoe2ee">Wie kann ich garantierte Ende-zu-Ende-Verschlüsselung und grüne Häkchen erhalten?</a></li>
|
||||
<li><a href="#e2eeguarantee">Was bedeuten das “Grüne Häkchen” und die “garantierte Ende-zu-Ende-Verschlüsselung”?</a></li>
|
||||
<li><a href="#nocryptanymore">Ein Kontakt hat eine Nachricht von einem anderen Gerät gesendet”, was kann ich tun?</a></li>
|
||||
@@ -65,10 +65,10 @@
|
||||
<li><a href="#kann-ich-delta-chat-auf-mehreren-geräten-zur-selben-zeit-verwenden">Kann ich Delta Chat auf mehreren Geräten zur selben Zeit verwenden?</a></li>
|
||||
<li><a href="#fehlersuche">Fehlersuche</a></li>
|
||||
<li><a href="#backup">Manueller Transfer</a></li>
|
||||
<li><a href="#gibt-es-pläne-für-eine-delta-chat-web-anwendung">Gibt es Pläne für eine Delta Chat Web-Anwendung?</a></li>
|
||||
<li><a href="#gibt-es-pläne-für-eine-delta-chat-web-anwendung">Gibt es Pläne für eine Delta-Chat-Web-Anwendung?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#webxdc">Webxdc Apps</a>
|
||||
<li><a href="#webxdc">Webxdc-Apps</a>
|
||||
<ul>
|
||||
<li><a href="#wie-privat-sind-webxdc-apps">Wie privat sind Webxdc Apps?</a></li>
|
||||
<li><a href="#wo-bekomme-ich-webxdc-apps">Wo bekomme ich Webxdc Apps?</a></li>
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#ist-delta-chat-kompatibel-mit-protonmail--tutanota--criptext">Ist Delta Chat kompatibel mit Protonmail / Tutanota / Criptext?</a></li>
|
||||
<li><a href="#remove-account">Wie kann ich mein Konto löschen?</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>
|
||||
<li><a href="#wo-können-meine-freunde-delta-chat-finden">Wo können meine Freunde Delta Chat finden?</a></li>
|
||||
<li><a href="#wie-wird-delta-chat-finanziert">Wie wird Delta Chat finanziert?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -152,7 +153,7 @@ auch wenn der Empfänger Delta Chat nicht benutzt.</p>
|
||||
die sofortige Push-Benachrichtigungen für iOS- und Android-Geräte bieten.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Durchgängige <a href="#multiple-accounts">Multi-Profil</a> und Multi-Geräte-Unterstützung auf allen Plattformen.</p>
|
||||
<p>Durchgängige <a href="#multiple-accounts">Multi-Profil-</a> und Multi-Geräte-Unterstützung auf allen Plattformen.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Interaktive <a href="https://webxdc.org/apps">Webanwendungen in Chats</a> für Spiele und für die Zusammenarbeit</p>
|
||||
@@ -286,7 +287,7 @@ unter dem Text Ihrer Nachrichten.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Zum Archivieren oder Anheften, tippen Sie lange auf den Chat (Android), verwenden Sie das Chatmenü (Android/Desktop) oder wischen Sie nach links (iOS); zum Stummschalten, verwenden Sie das Chatmenü (Android/Desktop) oder das Chatprofil (iOS).</p>
|
||||
<p>Um die Funktionen zu nutzen, lang auf einen Chat in der Chatliste tippen oder den Chat mit der rechten Maustaste anklicken.</p>
|
||||
|
||||
<h3 id="was-bedeutet-der-grüne-punkt">
|
||||
|
||||
@@ -303,7 +304,7 @@ unter dem Text Ihrer Nachrichten.</p>
|
||||
<li>entweder weil der Kontakt Ihnen direkt eine Nachricht gesendet hat,</li>
|
||||
<li>weil der Kontakt etwas an eine Gruppe geschrieben hat, in der sie beide Mitglied sind,</li>
|
||||
<li>weil der Kontakt Ihnen eine Lesebestätigung für eine von Ihnen geschriebene Nachricht gesendet hat</li>
|
||||
<li>oder weil der Kontakt Daten mithilfe einer <a href="#webxdc">Webxdc App</a> an Ihre Delta Chat-App gesendet hat.</li>
|
||||
<li>oder weil der Kontakt Daten mithilfe einer <a href="#webxdc">Webxdc-App</a> an Ihre Delta-Chat-App gesendet hat.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Dies ist also kein Echtzeit-Online-Status - und wenn jemand nicht sofort antwortet, obwohl er online zu sein scheint, machen Sie sich keine Sorgen und geben Sie ihm etwas Raum. ;-)</li>
|
||||
@@ -486,7 +487,7 @@ und Benachrichtigungen auf dem Telefon des Nutzers anzeigen kann.</p>
|
||||
<p>iOS-Geräten, durch die Integration mit den Apple-Push-Diensten.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Android-Geräten, durch die Integration des Google FCM Push-Dienste,
|
||||
<p>Android-Geräten, durch die Integration des Google-FCM-Push-Dienstes,
|
||||
auch auf Geräten, die <a href="https://microg.org">microG</a>
|
||||
anstelle von proprietärem Google-Code auf dem Telefon.</p>
|
||||
</li>
|
||||
@@ -517,7 +518,7 @@ keine Daten an Apple weitergibt, die Apple nicht bereits hat.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Wenn ein „Push-Service“ verfügbar ist, aktiviert Delta Chat Push-Benachrichtigungen
|
||||
<p>Wenn ein „Push-Service“ verfügbar ist, aktiviert Delta Chat Push-Benachrichtigungen,
|
||||
um eine sofortige Nachrichtenzustellung für alle Chatmail-Benutzer zu erreichen.
|
||||
Wenn Sie einen klassischen E-Mail-Anbieter anstelle von <a href="https://delta.chat/chatmail">chatmail</a> Servern verwenden,
|
||||
sind Push-Benachrichtigungen nicht verfügbar.</p>
|
||||
@@ -543,7 +544,7 @@ können sicher ausprobiert werden, wenn Sie feststellen, dass Nachrichten nur mi
|
||||
<h3 id="privacy-notifications">
|
||||
|
||||
|
||||
Wie privat sind Delta Chat Push-Benachrichtigungen? <a href="#privacy-notifications" class="anchor"></a>
|
||||
Wie privat sind Delta-Chat-Push-Benachrichtigungen? <a href="#privacy-notifications" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -556,16 +557,15 @@ an irgendein System, das an der Zustellung von Push-Benachrichtigungen beteiligt
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Eine Delta-Chat-Anwendung erhält lokal ein „Geräte-Token“ (eine zufällige Zahl) und speichert es
|
||||
<p>Eine Delta-Chat-Anwendung erhält lokal ein „Geräte-Token“, verschlüsselt und speichert es
|
||||
auf dem <a href="https://delta.chat/chatmail">Chatmail</a>-Server.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Wenn ein <a href="https://delta.chat/chatmail">Chatmail</a>-Server eine E-Mail für einen Delta Chat-Benutzer erhält
|
||||
erhält, leitet er den „Geräte-Token“ an den zentralen Delta-Chat-Benachrichtigungs-Proxy weiter.</p>
|
||||
<p>Wenn ein <a href="https://delta.chat/chatmail">Chatmail</a>-Server eine E-Mail für einen Delta-Chat-Benutzer erhält
|
||||
erhält, leitet er das verschlüsselte Geräte-Token an den zentralen Delta-Chat-Benachrichtigungs-Proxy weiter.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Der zentrale Delta-Chat-Benachrichtigungs-Proxy leitet
|
||||
das „Geräte-Token“ an den jeweiligen Push-Dienst (Apple, Google, etc.) weiter,
|
||||
<p>Der zentrale Delta-Chat-Benachrichtigungs-Proxy entschlüsselt das Geräte-Token und leitet es an den jeweiligen Push-Dienst (Apple, Google, etc.) weiter,
|
||||
ohne jemals die IP- oder E-Mail-Adresse des Delta-Chat-Benutzers zu kennen.</p>
|
||||
</li>
|
||||
<li>
|
||||
@@ -577,14 +577,15 @@ und auch nie den Inhalt einer Nachricht (auch nicht in verschlüsselter Form).</
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Stand Mai 2024 kennen die Chatmail-Server die Geräte-Token,
|
||||
aber wir planen, diese Informationen an den Benachrichtigungs-Proxy zu verschlüsseln
|
||||
zu verschlüsseln, so dass der Chatmail-Server niemals das „Geräte-Token“ erfährt.</p>
|
||||
|
||||
<p>Der zentrale Delta-Chat-Benachrichtigungs-Proxy <a href="https://github.com/deltachat/notifiers">ist klein und vollständig in Rust implementiert</a>
|
||||
und vergisst die Geräte-Token, sobald Apple/Google/etc. sie verarbeitet hat,
|
||||
normalerweise innerhalb weniger Millisekunden.</p>
|
||||
|
||||
<p>Beachten Sie, dass das Geräte-Token zwischen Anwendungen und dem Benachrichtigungs-Proxy verschlüsselt,
|
||||
aber nicht signiert ist.
|
||||
Der Benachrichtigungs-Proxy sieht also niemals E-Mail-Adressen, IP-Adressen oder
|
||||
irgendwelche kryptografischen Identitätsinformationen, die mit dem Gerät oder dem Geräte-Token eines Nutzers verbunden sind.</p>
|
||||
|
||||
<p>Aufgrund dieses umfassenden Datenschutzkonzepts würde sogar die Beschlagnahmung eines Chatmail-Servers,
|
||||
oder die vollständige Beschlagnahmung des zentralen Delta-Chat-Benachrichtigungsproxys
|
||||
keine privaten Informationen preisgeben, die den zentralen Push-Diensten nicht bereits vorliegen.</p>
|
||||
@@ -626,7 +627,7 @@ Willkommen bei der Macht des interoperablen und massiven Chatmail- und E-Mail-Sy
|
||||
<p><a href="https://autocrypt.org">Autocrypt</a> wird verwendet, um automatisch
|
||||
eine Ende-zu-Ende-Verschlüsselung mit Kontakten und Gruppenchats herzustellen.
|
||||
Autocrypt verwendet eine begrenzte und <a href="#openpgp-secure">sichere Untermenge des OpenPGP-Standards</a>.
|
||||
Ende-zu-Ende verschlüsselte Nachrichten sind mit einem Vorhängeschloss gekennzeichnet <img style="vertical-align:middle; width:1.2em; margin:1px" src="../lock-icon.png" alt="padlock" /></p>
|
||||
Ende-zu-Ende-verschlüsselte Nachrichten sind mit einem Vorhängeschloss gekennzeichnet <img style="vertical-align:middle; width:1.2em; margin:1px" src="../lock-icon.png" alt="padlock" /></p>
|
||||
|
||||
<p><a href="https://securejoin.delta.chat/en/latest/new.html">Secure-Join-Protokolle</a>
|
||||
werden für Chats mit garantierter Ende-zu-Ende-Verschlüsselung verwendet,
|
||||
@@ -638,7 +639,7 @@ garantieren Ende-zu-Ende-verschlüsselte Nachrichten.</p>
|
||||
<h3 id="whene2e">
|
||||
|
||||
|
||||
Wie kann ich wissen, ob Nachrichten Ende-zu-Ende verschlüsselt sind? <a href="#whene2e" class="anchor"></a>
|
||||
Wie kann ich wissen, ob Nachrichten Ende-zu-Ende-verschlüsselt sind? <a href="#whene2e" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -729,7 +730,7 @@ Das Einführen geschieht automatisch, wenn Sie Mitglieder zu Gruppen hinzufügen
|
||||
Wer einen Kontakt zu einer Gruppe mit grünem Häkchen hinzufügt, wird zum Einführenden
|
||||
für die Mitglieder, die noch nichts von dem hinzugefügten Kontakt wussten.
|
||||
In einem Kontaktprofil können Sie wiederholt auf den Text “Eingeführt von …” tippen
|
||||
bis du zu demjenigen gelangst, mit dem Sie einen direkten <a href="#howtoe2ee">QR-Scan</a> gemacht haben.</p>
|
||||
bis Sie zu demjenigen gelangen, mit dem Sie einen direkten <a href="#howtoe2ee">QR-Scan</a> gemacht haben.</p>
|
||||
|
||||
<p>Beachten Sie, dass Sie in einem Kontaktprofil unter Umständen Einführende sehen und antippen können, aber kein grünes Häkchen im Profiltitel vorhanden ist.
|
||||
Dies bedeutet normalerweise, dass der Kontakt <a href="#nocryptanymore">“eine Nachricht von einem anderen Gerät gesendet hat”</a>.</p>
|
||||
@@ -760,7 +761,7 @@ auch wenn der Kontakt dort Mitglied ist.</p>
|
||||
<p><strong>Ihr Kontakt verwendet Delta Chat auf einem zweiten Gerät (Smartphone oder Laptop)</strong></p>
|
||||
|
||||
<p>Wenn Ihr Kontakt ein weiteres Gerät mit Delta Chat eingerichtet hat,
|
||||
sollte das Konto von dem neuen Gerät entfernen werden und <a href="#multiclient">als zweites Gerät, wie hier beschrieben</a> erneut hinzugefügt werden.
|
||||
sollte das Konto von dem neuen Gerät entfernen werden und <a href="#multiclient">als zweites Gerät, wie hier beschrieben</a>, erneut hinzugefügt werden.
|
||||
Sobald sie sich danach schreiben, wird die Warnung verschwinden
|
||||
und die Verschlüsselung ist mit beiden Geräten Ihres Kontakts garantiert.</p>
|
||||
|
||||
@@ -882,7 +883,7 @@ wenn dieser falsch ist.</p>
|
||||
<p>Delta Chat war auch nie anfällig für den EFAIL-Angriff “Direct Exfiltration”,
|
||||
da nur <code class="language-plaintext highlighter-rouge">multipart/encrypted</code> Nachrichten entschlüsselt werden,
|
||||
die genau einen verschlüsselten und signierten Teil enthalten;
|
||||
so wie in der Autocrypt Level 1 Spezifikation definiert.</p>
|
||||
so wie in der Autocrypt-Level-1-Spezifikation definiert.</p>
|
||||
|
||||
<h3 id="tls">
|
||||
|
||||
@@ -948,7 +949,7 @@ Nachrichten an die Geräte der Empfänger weiterzuleiten und zuzustellen.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Sowohl zum Schutz vor E-Mail-Servern, die Metadaten sammeln
|
||||
<p>Sowohl zum Schutz vor E-Mail-Servern, die Metadaten sammeln,
|
||||
als auch gegen die Gefahr der Beschlagnahmung von Geräten
|
||||
empfehlen wir die Verwendung einer für Delta Chat optimierten <a href="https://delta.chat/serverguide">E-Mail-Server-Instanz</a>, um pseudonym-temporäre Konten durch Scannen von QR-Codes zu erstellen.
|
||||
Beachten Sie, dass Delta-Chat-Apps auf allen Plattformen mehrere Konten unterstützen.
|
||||
@@ -995,7 +996,7 @@ ohne Ende-zu-Ende-Unterstützung verwendet.</p>
|
||||
</h3>
|
||||
|
||||
<p>Wenn ein Kontakt keine Autocrypt-fähige App verwendet,
|
||||
werden alle Nachrichten, die diesen Kontakt betreffen (in Gruppen- oder Direkt-Chats)
|
||||
werden alle Nachrichten, die diesen Kontakt betreffen (in Gruppen- oder Direkt-Chats),
|
||||
nicht Ende-zu-Ende-verschlüsselt und zeigen daher kein “Vorhängeschloss”.
|
||||
Beachten Sie, auch Kontakte, die primär Delta Chat verwenden,
|
||||
können gleichzeitig auch nicht-Autocrypt-fähige Apps verwenden.
|
||||
@@ -1011,7 +1012,7 @@ um zu verhindern, dass unlesbare Nachrichten auf der Seite Ihrer Kontakte ankomm
|
||||
</h3>
|
||||
|
||||
<p>Wenn Sie einen sicheren Ende-zu-Ende-verschlüsselten Chat mit einem Kontakt benötigen,
|
||||
der sowohl Delta Chat als auch nicht-Autocrypt-Anwendungen nutzt,
|
||||
der sowohl Delta Chat als auch Nicht-Autocrypt-Anwendungen nutzt,
|
||||
können Sie eine <a href="#howtoe2ee">garantierte Ende-zu-Ende-Verschlüsselung</a> einrichten, mit einer Gruppe mit Ihnen beiden als Mitgliedern.
|
||||
In diesem Gruppenchat werden alle Nachrichten Ende-zu-Ende verschlüsselt werdejn,
|
||||
auch wenn im Direkt-Chat eine
|
||||
@@ -1025,10 +1026,10 @@ auch wenn im Direkt-Chat eine
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Der beste Weg, um sicherzustellen, dass alle Nachrichten Ende-zu-Ende verschlüsselt sind
|
||||
<p>Der beste Weg, um sicherzustellen, dass alle Nachrichten Ende-zu-Ende-verschlüsselt sind
|
||||
und Metadaten so schnell wie möglich gelöscht werden,
|
||||
ist <a href="#howtoe2ee">die Verwendung von Chats mit garantierter Ende-zu-Ende-Verschlüsselung</a>
|
||||
und die Aktivierung von <a href="#ephemeralmsgs">Verschwindende Nachrichten</a>.</p>
|
||||
und die Aktivierung von <a href="#ephemeralmsgs">verschwindenden Nachrichten</a>.</p>
|
||||
|
||||
<p>Garantierte Ende-zu-Ende-Verschlüsselung schützt vor <a href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack">MITM-Angriffen</a>
|
||||
und das Aktivieren von “Verschwindende Nachrichten” löscht die Nachrichten
|
||||
@@ -1045,7 +1046,7 @@ auf dem Server und Lokal nach einer vom Benutzer eingestellten Zeit.</p>
|
||||
</h3>
|
||||
|
||||
<p>Nein, Delta Chat unterstützt kein “Perfect Forward Secrecy” (PFS).
|
||||
Das bedeutet, dass wenn Ihr privater Delta-Chat-Schlüssel durchgesickert ist,
|
||||
Das bedeutet, wenn Ihr privater Delta-Chat-Schlüssel durchgesickert ist
|
||||
und jemand Ihre vorherigen In-Transit-Nachrichten gesammelt hat,
|
||||
können diese mit dem veröffentlichtem Schlüssel entschlüsselt werden.</p>
|
||||
|
||||
@@ -1056,7 +1057,7 @@ Die typische, reale Situation für durchgesickerte private Schlüssel, ist die <
|
||||
OpenPGP ist nur ein Container für verschlüsselte Nachrichten mit dem
|
||||
die Verwaltung der Schlüssel (und damit die Schlüsselrotation oder das Schlüssel-“Ratcheting”)
|
||||
auf flexible Weise organisiert werden kann.
|
||||
Siehe <a href="https://gitlab.com/sequoia-pgp/openpgp-dr">Seqouia’s PFS-Prototyp</a>
|
||||
Siehe <a href="https://gitlab.com/sequoia-pgp/openpgp-dr">Seqouias PFS-Prototyp</a>
|
||||
für bestehende Experimente in der OpenPGP-Community.</p>
|
||||
|
||||
<h3 id="ist-die-ende-zu-ende-verschlüsselung-von-delta-chat-genauso-sicher-wie-die-von-signal">
|
||||
@@ -1145,7 +1146,7 @@ Für andere Programme können Sie online eine Lösung finden.</p>
|
||||
Weitere Informationen finden Sie in unserem Blogbeitrag über <a href="https://delta.chat/en/2024-03-25-crypto-analysis-securejoin">Hardening Guaranteed End-to-End encryption</a> und in der hinterher publizierten <a href="https://eprint.iacr.org/2024/918.pdf">Kryptografischen Analyse von Delta Chat</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Im April 2023 haben wir Sicherheits- und Datenschutzprobleme mit den “In Chats geteilten Apps”-Feature behoben, die mit Fehlern beim Sandboxing, insbesondere mit Chromium zusammenhängen. Wir haben daraufhin eine unabhängige Sicherheitsprüfung von Cure53 durchführen lassen, und alle gefundenen Probleme wurden mit den im April 2023 veröffentlichten 1.36 Releases behoben. Siehe <a href="https://delta.chat/en/2023-05-22-webxdc-security">hier für die vollständige Hintergrundgeschichte</a>.</p>
|
||||
<p>Im April 2023 haben wir Sicherheits- und Datenschutzprobleme mit dem “In Chats geteilten Apps”-Feature behoben, die mit Fehlern beim Sandboxing, insbesondere mit Chromium zusammenhängen. Wir haben daraufhin eine unabhängige Sicherheitsprüfung von Cure53 durchführen lassen, und alle gefundenen Probleme wurden mit den im April 2023 veröffentlichten 1.36 Releases behoben. Siehe <a href="https://delta.chat/en/2023-05-22-webxdc-security">hier für die vollständige Hintergrundgeschichte</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Im März 2023 analysierte <a href="https://cure53.de">Cure53</a> sowohl die Transportverschlüsselung von Delta Chats Netzwerkverbindungen als auch das reproduzierbare Mailserver-Setup wie <a href="https://delta.chat/de/serverguide">auf dieser Seite empfohlen</a>. Sie können mehr über das Audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">in unserem Blog</a> lesen oder Sie lesen den <a href="https://delta.chat/assets/blog/MER-01-report.pdf">vollständigen Bericht hier</a>.</p>
|
||||
@@ -1155,7 +1156,7 @@ Weitere Informationen finden Sie in unserem Blogbeitrag über <a href="https://d
|
||||
Es wurden keine kritischen oder hochgradig gefährlichen Probleme gefunden. Der Bericht wies auf einige Schwachstellen mittlerer Schwere hin - sie stellen für sich genommen keine Bedrohung für Delta-Chat-Benutzer dar, da sie von der Umgebung abhängen, in der Delta Chat verwendet wird. Aus Gründen der Benutzerfreundlichkeit und der Kompatibilität können wir nicht alle Schwachstellen beseitigen und haben beschlossen, Sicherheitsempfehlungen für bedrohte Benutzer zu geben. Sie können den <a href="https://delta.chat/assets/blog/2020-second-security-review.pdf">vollständigen Bericht hier</a> lesen.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Im Jahr 2019 analysierte <a href="https://includesecurity.com">Include Security</a> die von Delta Chat verwendeten <a href="https://github.com/rpgp/rpgp">PGP</a> und <a href="https://github.com/RustCrypto/RSA">RSA</a> Bibliotheken.
|
||||
<p>Im Jahr 2019 analysierte <a href="https://includesecurity.com">Include Security</a> die von Delta Chat verwendeten <a href="https://github.com/rpgp/rpgp">PGP-</a> und <a href="https://github.com/RustCrypto/RSA">RSA-</a> Bibliotheken.
|
||||
Es wurden keine kritischen Probleme gefunden, aber zwei Probleme mit hohem Schweregrad, die wir anschließend behoben haben. Außerdem wurden ein mittelschweres und einige weniger schwerwiegende Probleme gefunden, aber es gab keine Möglichkeit, diese Schwachstellen in der Delta-Chat-Implementierung auszunutzen. Einige dieser Schwachstellen haben wir dennoch nach Abschluss des Audits behoben. Sie können den [vollständigen Bericht hier] lesen (../assets/blog/2019-first-security-review.pdf).</p>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -1215,6 +1216,12 @@ Es wurden keine kritischen Probleme gefunden, aber zwei Probleme mit hohem Schwe
|
||||
und sicherstellen, dass <strong>Privates Netzwerk</strong> als “Netzwerkprofiltyp” ausgewählt ist.
|
||||
(nach der Übertragung kann wieder der ursprüngliche Wert verwendet werden)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Auf <strong>iOS</strong>, sicherstellen, dass „Systemeinstellungen / Apps / Delta Chat / <strong>Lokales Netzwerk</strong>“ eingeschaltet ist</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Auf <strong>macOS,</strong> „Systemeinstellungen / Datenschutz & Sicherheit / <strong>Lokales Netzwerk</strong> / Delta Chat“ aktivieren</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Ihr System verfügt möglicherweise über eine “Personal Firewall”, diese sind dafür bekannt, Probleme zu verursachen (insbesondere bei Windows). <strong>Deaktivieren Sie die Personal Firewall</strong> für Delta Chat auf beiden Seiten und versuchen Sie es erneut</p>
|
||||
</li>
|
||||
@@ -1253,32 +1260,32 @@ Verwenden Sie nach Möglichkeit ein Nicht-Gast-Netzwerk. Wenn Sie Zugriff auf de
|
||||
<li><strong>Wenn Sie iOS verwenden</strong> und auf Schwierigkeiten stoßen, hilft Ihnen vielleicht <a href="https://support.delta.chat/t/import-backup-to-ios/1628">diese Anleitung</a>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Sie sind nun synchronisiert und können beide Geräte zum Senden und Empfangen von Ende-zu-Ende verschlüsselten Nachrichten mit Ihren Kommunikationspartnern verwenden.</li>
|
||||
<li>Sie sind nun synchronisiert und können beide Geräte zum Senden und Empfangen von Ende-zu-Ende-verschlüsselten-Nachrichten mit Ihren Kommunikationspartnern verwenden.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="gibt-es-pläne-für-eine-delta-chat-web-anwendung">
|
||||
|
||||
|
||||
Gibt es Pläne für eine Delta Chat Web-Anwendung? <a href="#gibt-es-pläne-für-eine-delta-chat-web-anwendung" class="anchor"></a>
|
||||
Gibt es Pläne für eine Delta-Chat-Web-Anwendung? <a href="#gibt-es-pläne-für-eine-delta-chat-web-anwendung" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>Es gibt keine direkten Pläne, aber einige vorläufige Gedanken.</li>
|
||||
<li>Es gibt 2-3 Möglichkeiten, einen Delta Chat Web-Client einzuführen, aber sie bedeuten alle immense Arbeit. Im Moment fokussieren wir uns darauf, stabile native Apps in den Appstores (Google Play/iOS/Windows/macOS/Linux repositories) anzubieten.</li>
|
||||
<li>Sollten Sie einen Web-Client benötigen, weil Sie auf Ihrem Arbeitsrechner keine Software installieren dürfen, können Sie den Windows Desktop-Client bzw. Applmage für Linux nutzen. Sie finden diese unter <a href="https://get.delta.chat">get.delta.chat</a>.</li>
|
||||
<li>Es gibt 2-3 Möglichkeiten, einen Delta-Chat-Web-Client einzuführen, aber sie bedeuten alle immense Arbeit. Im Moment fokussieren wir uns darauf, stabile native Apps in den Appstores (Google Play/iOS/Windows/macOS/Linux repositories) anzubieten.</li>
|
||||
<li>Sollten Sie einen Web-Client benötigen, weil Sie auf Ihrem Arbeitsrechner keine Software installieren dürfen, können Sie den Windows-Desktop-Client bzw. Applmage für Linux nutzen. Sie finden diese unter <a href="https://get.delta.chat">get.delta.chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="webxdc">
|
||||
|
||||
|
||||
Webxdc Apps <a href="#webxdc" class="anchor"></a>
|
||||
Webxdc-Apps <a href="#webxdc" class="anchor"></a>
|
||||
|
||||
|
||||
</h2>
|
||||
|
||||
<p>In Delta Chat können Sie <a href="https://webxdc.org">Webxdc Apps</a>, Anhänge mit der Dateierweiterung “.xdc” teilen. Sie können sehr unterschiedliche Dinge tun und machen Delta Chat zu einem wirklich erweiterbaren Messenger.</p>
|
||||
<p>In Delta Chat können Sie <a href="https://webxdc.org">Webxdc-Apps</a>, Anhänge mit der Dateierweiterung “.xdc” teilen. Sie können sehr unterschiedliche Dinge tun und machen Delta Chat zu einem wirklich erweiterbaren Messenger.</p>
|
||||
|
||||
<h3 id="wie-privat-sind-webxdc-apps">
|
||||
|
||||
@@ -1304,7 +1311,8 @@ Verwenden Sie nach Möglichkeit ein Nicht-Gast-Netzwerk. Wenn Sie Zugriff auf de
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>Grundsätzlich kann jeder Webxdc Apps mit anderen ohne Einschränkungen teilen.</li>
|
||||
<li>Grundsätzlich kann jeder Webxdc-Apps mit anderen ohne Einschränkungen teilen.</li>
|
||||
<li>Von <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
|
||||
<li>Sie können <a href="https://delta.chat/en/2023-08-11-xstore">‘hallo’ an xstore@testrun.org senden</a>
|
||||
um einen experimentellen Webxdc Appstore zu sehen.
|
||||
Alle Apps dort sind Open Source und umsonst.</li>
|
||||
@@ -1322,7 +1330,7 @@ forum</a> veröffentlicht und diskutiert.</li>
|
||||
|
||||
<ul>
|
||||
<li>Webxdc Apps sind nur ZIP-Dateien, die HTML-, CSS- und JavaScript-Code enthalten.</li>
|
||||
<li>Sie können die <a href="https://github.com/webxdc/hello">Hello World-Beispiel-App</a> erweitern, um loszulegen.</li>
|
||||
<li>Sie können die <a href="https://github.com/webxdc/hello">Hello-World-Beispiel-App</a> erweitern, um loszulegen.</li>
|
||||
<li>Alles andere, was Sie wissen müssen, steht in der <a href="https://docs.webxdc.org/">Dokumentation</a>.</li>
|
||||
<li>Wenn Sie Fragen haben, können Sie andere mit Erfahrung im <a href="https://support.delta.chat/c/webxdc/20">Delta-Chat-Forum</a> fragen.</li>
|
||||
</ul>
|
||||
@@ -1635,7 +1643,7 @@ wenn Sie eine <a href="#signature">Signaturtext</a> einfügen.</p>
|
||||
<ul>
|
||||
<li>Ja und Nein.</li>
|
||||
<li>Nein, Sie können sich nicht mit Delta Chat in ein Protonmail-, Tutanota- oder Criptext-Konto einloggen, da diese keinen Standard-E-Mail-Empfang über IMAP anbieten.</li>
|
||||
<li>Ja, Sie können Delta Chat verwenden, um Nachrichten an Personen zu senden, die Protonmail, Tutanota oder Criptext verwenden. Diese Nachrichten werden jedoch nicht ende-zu-ende-verschlüsselt, da diese Anbieter keine mit dem <a href="https://autocrypt.org/">Autocrypt</a>-Standard kompatible Verschlüsselung verwenden.</li>
|
||||
<li>Ja, Sie können Delta Chat verwenden, um Nachrichten an Personen zu senden, die Protonmail, Tutanota oder Criptext verwenden. Diese Nachrichten werden jedoch nicht Ende-zu-Ende-verschlüsselt, da diese Anbieter keine mit dem <a href="https://autocrypt.org/">Autocrypt</a>-Standard kompatible Verschlüsselung verwenden.</li>
|
||||
<li>Delta Chat kann Ende-zu-Ende-Verschlüsselung über jeden E-Mail-Anbieter mit jeder
|
||||
<a href="https://autocrypt.org/dev-status.html">Autocrypt-fähige E-Mail-Anwendung</a> herstellen</li>
|
||||
</ul>
|
||||
@@ -1680,6 +1688,34 @@ Andernfalls könnten Sie unverschlüsselte Nachrichten aus diesen Gruppenchats e
|
||||
<li>Siehe hierzu <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">in Delta Chat genutzte Standards</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="wo-können-meine-freunde-delta-chat-finden">
|
||||
|
||||
|
||||
Wo können meine Freunde Delta Chat finden? <a href="#wo-können-meine-freunde-delta-chat-finden" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat ist für alle großen und einige kleinere Plattformen verfügbar:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Die <strong>offizielle Website</strong>, <a href="https://delta.chat/download">https://delta.chat/download</a> zeigt alle Optionen im Detail</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Falls nicht verfügbar, verwenden Sie den <strong>Mirror</strong> auf <a href="https://deltachat.github.io/deltachat-pages">https://deltachat.github.io/deltachat-pages</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Öffnen Sie einen der folgenden <strong>App-Stores und suchen Sie nach „Delta Chat“:</strong> Google Play Store, F-Droid, Huawei App Gallery, Amazon App Store, iOS und macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Im <strong>Paketmanager</strong> Ihrer Linux-Distribution nachschauen</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Android-APKs</strong> sind auch auf <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a> verfügbar.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="wie-wird-delta-chat-finanziert">
|
||||
|
||||
|
||||
@@ -1705,10 +1741,10 @@ Die zweite Förderung 2019/2020 (~$300K) half uns bei der Erstellung der iOS-Ve
|
||||
<p>Die <a href="https://nlnet.nl/">NLnet-Stiftung</a> bewilligte 2019/2020 46K EUR für die Fertigstellung von Rust-/Python-Bindungs und die Einrichtung eines Chat-Bot-Ökosystems.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Im Jahr 2021 erhielten wir weitere EU-Mittel für zwei “Next-Generation-Internet” Anträge, nämlich für <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - E-Mail-Provider-Portabilitätsverzeichnis</a> (~97K EUR) und <a href="https://nlnet.nl/project/EmailPorting/">AEAP - E-Mail-Adressportierung</a> (~90K EUR). Ziel sind bessere Unterstützung von Mehrfachkonten, verbesserten QR-Code-Kontakt- und -Gruppen-Setups sowie Netzwerkverbesserungen auf allen Plattformen.</p>
|
||||
<p>Im Jahr 2021 erhielten wir weitere EU-Mittel für zwei “Next-Generation-Internet”-Anträge, nämlich für <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - E-Mail-Provider-Portabilitätsverzeichnis</a> (~97K EUR) und <a href="https://nlnet.nl/project/EmailPorting/">AEAP - E-Mail-Adressportierung</a> (~90K EUR). Ziel sind bessere Unterstützung von Mehrfachkonten, verbesserten QR-Code-Kontakt- und -Gruppen-Setups sowie Netzwerkverbesserungen auf allen Plattformen.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Von Ende 2021 bis März 2023 erhielten wir eine <em>Internet Freedom</em> Finanzierung (500K USD) vom U.S. Bureau of Democracy, Human Rights and Labor (DRL). Diese Finanzierung unterstützte unsere langjährigen Ziele, Delta Chat benutzerfreundlicher und kompatibel mit einer breiten Palette von E-Mail-Servern weltweit zu machen, sowie widerstandsfähiger und sicherer an Orten, die häufig von Internetzensur und Abschaltungen betroffen sind.</p>
|
||||
<p>Von Ende 2021 bis März 2023 erhielten wir eine <em>Internet-Freedom</em>-Finanzierung (500K USD) vom U.S. Bureau of Democracy, Human Rights and Labor (DRL). Diese Finanzierung unterstützte unsere langjährigen Ziele, Delta Chat benutzerfreundlicher und kompatibel mit einer breiten Palette von E-Mail-Servern weltweit zu machen, sowie widerstandsfähiger und sicherer an Orten, die häufig von Internetzensur und Abschaltungen betroffen sind.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>2023-2024 schlossen wir erfolgreich das vom OTF finanzierte
|
||||
@@ -1718,11 +1754,11 @@ das <a href="https://delta.chat/chatmail">Chatmail-Server-Netzwerk</a>
|
||||
und „Instant Onboarding“ allen ab April 2024 veröffentlichten Anwendungen hinzu.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>2023 und 2024 wurden wir in das Next Generation Internet (NGI)
|
||||
Programm für unsere Arbeit an <a href="https://nlnet.nl/project/WebXDC-Push/">webxdc PUSH</a> aufgenommen,
|
||||
<p>2023 und 2024 wurden wir in das Next-Generation-Internet-Programm (NGI)
|
||||
für unsere Arbeit an <a href="https://nlnet.nl/project/WebXDC-Push/">Webxdc-PUSH</a> aufgenommen,
|
||||
zusammen mit Kooperationspartnern, die an
|
||||
<a href="https://nlnet.nl/project/Webxdc-Evolve/">webxdc evolve</a>,
|
||||
<a href="https://nlnet.nl/project/WebXDC-XMPP/">webxdc XMPP</a>,
|
||||
<a href="https://nlnet.nl/project/Webxdc-Evolve/">Webxdc-Evolve</a>,
|
||||
<a href="https://nlnet.nl/project/WebXDC-XMPP/">Webxdc-XMPP</a>,
|
||||
<a href="https://nlnet.nl/project/DeltaTouch/">DeltaTouch</a> und
|
||||
<a href="https://nlnet.nl/project/DeltaTauri/">DeltaTauri</a>.
|
||||
Alle diese Projekte sind teilweise abgeschlossen oder sollen Anfang 2025 abgeschlossen werden.</p>
|
||||
@@ -1740,7 +1776,7 @@ Der Erhalt von Spenden hilft uns auch, unabhängiger und langfristig lebensfähi
|
||||
|
||||
<p>Die oben aufgeführte finanzielle Förderung wird hauptsächlich von der merlinux GmbH in Freiburg (Deutschland) organisiert und an mehr als ein Dutzend Mitwirkende weltweit verteilt.</p>
|
||||
|
||||
<p>Möglichkeiten mitzuwirken finden Sie Auf der <a href="https://delta.chat/de/contribute">Delta Chat Seite “Mitwirken”</a>.</p>
|
||||
<p>Möglichkeiten mitzuwirken finden Sie Auf der <a href="https://delta.chat/de/contribute">Delta-Chat-Seite “Mitwirken”</a>.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#is-delta-chat-compatible-with-protonmail--tutanota--criptext">Is Delta Chat compatible with Protonmail / Tutanota / Criptext?</a></li>
|
||||
<li><a href="#remove-account">How can I delete my account?</a></li>
|
||||
<li><a href="#im-interested-in-the-technical-details-can-you-tell-me-more">I’m interested in the technical details. Can you tell me more?</a></li>
|
||||
<li><a href="#where-can-my-friends-find-delta-chat">Where can my friends find Delta Chat?</a></li>
|
||||
<li><a href="#how-are-delta-chat-developments-funded">How are Delta Chat developments funded?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -301,8 +302,7 @@ Archived chats remain accessible above the chat list or via search.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>To archive or pin a chat, long tap (Android), use the chat’s menu (Android/Desktop) or swipe to the left (iOS);
|
||||
to mute a chat, use the chat’s menu (Android/Desktop) or the chat’s profile (iOS).</p>
|
||||
<p>To use the functions, long tap or right click a chat in the chat list.</p>
|
||||
|
||||
<h3 id="what-does-the-green-dot-mean">
|
||||
|
||||
@@ -603,16 +603,16 @@ to any system involved in the delivery of Push Notifications.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>A Delta Chat app obtains a “device token” locally and stores it
|
||||
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
|
||||
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
|
||||
it forwards the “device token” to the central Delta Chat notification proxy.</p>
|
||||
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The central Delta Chat notification proxy forwards
|
||||
the “device token” to the respective Push service (Apple, Google, etc.),
|
||||
<p>The central Delta Chat notification proxy decrypts the device token
|
||||
and forwards it to the respective Push service (Apple, Google, etc.),
|
||||
without ever knowing the IP or e-mail address of Delta Chat users.</p>
|
||||
</li>
|
||||
<li>
|
||||
@@ -625,14 +625,15 @@ and also never see any message content (also not in encrypted forms).</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>As of May 2024, chatmail servers know about “device tokens”
|
||||
but we plan to encrypt this information to the notification proxy
|
||||
such that the chatmail server never learns the device token.</p>
|
||||
|
||||
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
|
||||
and forgets about device-tokens as soon as Apple/Google/etc processed them,
|
||||
usually in a matter of milliseconds.</p>
|
||||
|
||||
<p>Note that the device token is encrypted between apps and notification proxy
|
||||
but it is not signed.
|
||||
The notification proxy thus never sees e-mail addresses, IP-addresses or
|
||||
any cryptographic identity information associated with a user’s device (token).</p>
|
||||
|
||||
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
|
||||
or the full seizure of the central Delta Chat notification proxy
|
||||
would not reveal private information that Push services do not already have.</p>
|
||||
@@ -1315,6 +1316,12 @@ One device is not needed for the other to work.</p>
|
||||
and make sure, <strong>Private Network</strong> is selected as “Network profile type”
|
||||
(after transfer, you can change back to the original value)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>iOS</strong>, make sure “System Settings / Apps / Delta Chat / <strong>Local Network</strong>” access is granted</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>macOS</strong>, enable “System Settings / Privacy & Security / <strong>Local Network</strong> / Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Your system might have a “personal firewall”,
|
||||
which is known to cause problems (especially on Windows).
|
||||
@@ -1432,6 +1439,7 @@ you only open attachments from senders you trust, and not from spammers.</li>
|
||||
<ul>
|
||||
<li>In general, anyone can share webxdc apps with each
|
||||
other without restrictions.</li>
|
||||
<li>From <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
|
||||
<li>You can <a href="https://delta.chat/en/2023-08-11-xstore">send ‘hi’ to xstore@testrun.org</a>
|
||||
to see an experimental webxdc appstore.
|
||||
All of the apps are open source and for free.</li>
|
||||
@@ -1883,6 +1891,35 @@ Otherwise you might receive undecryptable messages from those group chats.</p>
|
||||
<li>See <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">Standards used in Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="where-can-my-friends-find-delta-chat">
|
||||
|
||||
|
||||
Where can my friends find Delta Chat? <a href="#where-can-my-friends-find-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat is available for all major and some minor platforms:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>The <strong>official website</strong>, <a href="https://delta.chat/download">https://delta.chat/download</a> shows all options in detail</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If unavailable, use the <strong>mirror</strong> at <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, Amazon App Store, iOS and macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Check the <strong>package manager</strong> of your Linux distributions</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Android APKs</strong> are also available on <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="how-are-delta-chat-developments-funded">
|
||||
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#delta-chat-es-compatible-con-protonmail--tutanota--criptext">¿Delta Chat es compatible con Protonmail / Tutanota / Criptext?</a></li>
|
||||
<li><a href="#remove-account">¿Cómo puedo eliminar mi cuenta?</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>
|
||||
<li><a href="#where-can-my-friends-find-delta-chat">Where can my friends find Delta Chat?</a></li>
|
||||
<li><a href="#cómo-se-financia-el-desarrollo-de-delta-chat">¿Cómo se financia el desarrollo de Delta Chat?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -596,16 +597,16 @@ to any system involved in the delivery of Push Notifications.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>A Delta Chat app obtains a “device token” locally and stores it
|
||||
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
|
||||
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
|
||||
it forwards the “device token” to the central Delta Chat notification proxy.</p>
|
||||
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The central Delta Chat notification proxy forwards
|
||||
the “device token” to the respective Push service (Apple, Google, etc.),
|
||||
<p>The central Delta Chat notification proxy decrypts the device token
|
||||
and forwards it to the respective Push service (Apple, Google, etc.),
|
||||
without ever knowing the IP or e-mail address of Delta Chat users.</p>
|
||||
</li>
|
||||
<li>
|
||||
@@ -618,14 +619,15 @@ and also never see any message content (also not in encrypted forms).</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>As of May 2024, chatmail servers know about “device tokens”
|
||||
but we plan to encrypt this information to the notification proxy
|
||||
such that the chatmail server never learns the device token.</p>
|
||||
|
||||
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
|
||||
and forgets about device-tokens as soon as Apple/Google/etc processed them,
|
||||
usually in a matter of milliseconds.</p>
|
||||
|
||||
<p>Note that the device token is encrypted between apps and notification proxy
|
||||
but it is not signed.
|
||||
The notification proxy thus never sees e-mail addresses, IP-addresses or
|
||||
any cryptographic identity information associated with a user’s device (token).</p>
|
||||
|
||||
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
|
||||
or the full seizure of the central Delta Chat notification proxy
|
||||
would not reveal private information that Push services do not already have.</p>
|
||||
@@ -1277,6 +1279,12 @@ No es necesario un dispositivo para que el otro funcione.</p>
|
||||
and make sure, <strong>Private Network</strong> is selected as “Network profile type”
|
||||
(after transfer, you can change back to the original value)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>iOS</strong>, make sure “System Settings / Apps / Delta Chat / <strong>Local Network</strong>” access is granted</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>macOS</strong>, enable “System Settings / Privacy & Security / <strong>Local Network</strong> / Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Your system might have a “personal firewall”,
|
||||
which is known to cause problems (especially on Windows).
|
||||
@@ -1394,6 +1402,7 @@ solo abre archivos adjuntos de remitentes en los que confía y no de spammers.</
|
||||
<ul>
|
||||
<li>In general, anyone can share webxdc apps with each
|
||||
other without restrictions.</li>
|
||||
<li>From <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
|
||||
<li>You can <a href="https://delta.chat/en/2023-08-11-xstore">send ‘hi’ to xstore@testrun.org</a>
|
||||
to see an experimental webxdc appstore.
|
||||
All of the apps are open source and for free.</li>
|
||||
@@ -1827,6 +1836,35 @@ Otherwise you might receive undecryptable messages from those group chats.</p>
|
||||
<li>Visita la página <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">Estándares usados en Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="where-can-my-friends-find-delta-chat">
|
||||
|
||||
|
||||
Where can my friends find Delta Chat? <a href="#where-can-my-friends-find-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat is available for all major and some minor platforms:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>The <strong>official website</strong>, <a href="https://delta.chat/download">https://delta.chat/download</a> shows all options in detail</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If unavailable, use the <strong>mirror</strong> at <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, Amazon App Store, iOS and macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Check the <strong>package manager</strong> of your Linux distributions</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Android APKs</strong> are also available on <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="cómo-se-financia-el-desarrollo-de-delta-chat">
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<li><a href="#delta-chat-prend-il-en-charge-les-images-vidéos-et-autres-pièces-jointes-">Delta Chat prend-il en charge les images, vidéos et autres pièces jointes ?</a></li>
|
||||
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
||||
<li><a href="#qui-peut-voir-ma-photo-de-profil-">Qui peut voir ma photo de profil ?</a></li>
|
||||
<li><a href="#signature">Can I set a Bio/Signature/Status/Motto with Delta Chat?</a></li>
|
||||
<li><a href="#signature">Puis-je afficher une Bio/Signature ou un Status/Motto avec Delta Chat?</a></li>
|
||||
<li><a href="#que-signifient-épingler-sourdine-et-archiver-">Que signifient “épingler”, “sourdine” et “archiver” ?</a></li>
|
||||
<li><a href="#que-signifie-le-point-vert-">Que signifie le point vert ?</a></li>
|
||||
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#delta-chat-est-il-compatible-avec-protonmail--tutanota--criptext-">Delta Chat est-il compatible avec Protonmail / Tutanota / Criptext ?</a></li>
|
||||
<li><a href="#remove-account">Comment supprimer mon compte ?</a></li>
|
||||
<li><a href="#les-détails-techniques-mintéressent-pouvez-vous-men-dire-plus-">Les détails techniques m’intéressent. Pouvez-vous m’en dire plus ?</a></li>
|
||||
<li><a href="#where-can-my-friends-find-delta-chat">Where can my friends find Delta Chat?</a></li>
|
||||
<li><a href="#comment-est-financé-le-développement-de-delta-chat-">Comment est financé le développement de Delta Chat ?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -114,14 +115,14 @@
|
||||
|
||||
</h2>
|
||||
|
||||
<p>Delta Chat is a reliable, decentralized and secure messaging app,
|
||||
available for mobile and desktop platforms.</p>
|
||||
<p>Delta Chat est une application de messagerie fiable, décentralisée et sécurisée,
|
||||
Disponible pour les plateformes smartphone et ordinateurs de bureau.</p>
|
||||
|
||||
<p>Delta Chat feels like Whatsapp or Telegram but you can also use and regard it as an e-mail app.
|
||||
You can signup anonymously to a variety of <a href="https://delta.chat/chatmail">interoperable chatmail servers</a>
|
||||
which are minimal e-mail servers optimized for fast and secure operations.
|
||||
Or you may use classic e-mail servers and an existing e-mail account
|
||||
in which case Delta Chat acts as an e-mail app.</p>
|
||||
<p>Delta Chat ressemble à Whatsapp ou Telegram mais vous pouvez aussi l’utiliser et la considérer comme une application e-mail.
|
||||
Vous pouvez vous inscrire anonymement à une variété <a href="https://delta.chat/chatmail">de serveurs chatmail interéopérables</a>
|
||||
Qui sont des serveurs e-mails minimalistes optimisés pour des opérations rapides et sécurisées.
|
||||
Ou vous pouvez utiliser des serveurs e-mail classiques et utiliser votre compte e-mail
|
||||
dans ce cas Delta Chat agit comme une application de courriel.</p>
|
||||
|
||||
<p><img style="float:right; width:50%; max-width:360%; margin:1em;" src="../delta-what-optim.png" /></p>
|
||||
|
||||
@@ -133,15 +134,15 @@ in which case Delta Chat acts as an e-mail app.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>To securely setup contact with others <a href="#howtoe2ee">scan an invite QR code
|
||||
or share an invite link</a>.
|
||||
This is required when using a (default) chatmail-based chat profile
|
||||
because chatmail servers reject un-encrypted outgoing messages.</p>
|
||||
<p>Pour établir un contact en toute sécurité avec d’autres personnes <a href="#howtoe2ee">scanner un code QR d’invitation
|
||||
ou partager un lien d’invitation</a>.
|
||||
Cette opération est nécessaire lors de l’utilisation d’un profil de discussion basé sur le chatmail (par défaut).
|
||||
car les serveurs de chatmail rejettent les messages sortants non chiffrés.</p>
|
||||
|
||||
<p>If you create a chat profile with a classic e-mail address
|
||||
you may manually create a contact if you know their e-mail address
|
||||
and then write a message to them
|
||||
even if the recipient is not using Delta Chat.</p>
|
||||
<p>Si vous créez un profil discussion avec une adresse courriel classique
|
||||
vous pouvez créer manuellement un contact si vous connaissez son adresse courriel
|
||||
et lui écrire un message
|
||||
même si le destinataire n’utilise pas Delta Chat.</p>
|
||||
|
||||
<h3 id="quels-sont-les-avantages-de-delta-chat-par-rapport-aux-autres-messageries-">
|
||||
|
||||
@@ -153,23 +154,23 @@ even if the recipient is not using Delta Chat.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Anonymous chat profiles with fast, secure and interoperable <a href="https://delta.chat/chatmail">chatmail servers</a>
|
||||
which offer instant Push Notifications for iOS and Android devices.</p>
|
||||
<p>Profils anonymes de discussion avec des <a href="https://delta.chat/chatmail">serveurs de chatmail</a> rapides, sécurisés et interopérables
|
||||
qui offrent des notifications push instantanées pour les appareils iOS et Android.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Pervasive <a href="#multiple-accounts">multi-profile</a> and multi-device support on all platforms.</p>
|
||||
<p>Fonctionnalités de <a href="#multiple-accounts">multi-profil</a> et de multi-appareil supportées sur toutes les plateformes.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Interactive <a href="https://webxdc.org/apps">web apps in chats</a> for gaming and collaboration</p>
|
||||
<p><a href="https://webxdc.org/apps">web apps dans les chats</a> interactifs pour le gaming et la collaboration</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="#security-audits">Audited end-to-end encryption</a>
|
||||
safe against network and server attacks.</p>
|
||||
<p><a href="#security-audits">Chiffrement de bout en bout audité</a>
|
||||
contre les attaques ciblées sur le réseau et les serveurs.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Free and Open Source software, both app and server side.
|
||||
Built on <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md">E-mail and Web Internet Standards</a>,
|
||||
<a href="https://xkcd.com/927/">to avoid “yet another standard syndrome (xkcd 927)”</a></p>
|
||||
<p>Logiciel libre et open source, à la fois appli et côté serveur.
|
||||
Construit sur des <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md">Standards d’Internet et d’e-mail</a>,
|
||||
<a href="https://xkcd.com/927/">pour éviter le syndrome du “standard de plus” (xkcd 927)</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -255,16 +256,16 @@ that tend to cause unsolicited messages (“spam”) sooner or later.</p>
|
||||
<h3 id="signature">
|
||||
|
||||
|
||||
Can I set a Bio/Signature/Status/Motto with Delta Chat? <a href="#signature" class="anchor"></a>
|
||||
Puis-je afficher une Bio/Signature ou un Status/Motto avec Delta Chat? <a href="#signature" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes,
|
||||
you can do so under <strong>Settings → Profile → Bio</strong>.
|
||||
Your contacts who use Delta Chat will see it
|
||||
when they view your contact details.
|
||||
Moreover, it will appear as a classic e-mail signature.</p>
|
||||
<p>Oui,
|
||||
vous pouvez le faire sous <strong>Paramètres → Profil → Bio</strong>.
|
||||
Vos contacts qui utilisent Delta Chat le verront
|
||||
lorsqu’ils consulteront vos coordonnées.
|
||||
De plus, elle apparaîtra sous la forme d’une signature classique sur vos courriels.</p>
|
||||
|
||||
<h3 id="que-signifient-épingler-sourdine-et-archiver-">
|
||||
|
||||
@@ -577,16 +578,16 @@ to any system involved in the delivery of Push Notifications.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>A Delta Chat app obtains a “device token” locally and stores it
|
||||
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
|
||||
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
|
||||
it forwards the “device token” to the central Delta Chat notification proxy.</p>
|
||||
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The central Delta Chat notification proxy forwards
|
||||
the “device token” to the respective Push service (Apple, Google, etc.),
|
||||
<p>The central Delta Chat notification proxy decrypts the device token
|
||||
and forwards it to the respective Push service (Apple, Google, etc.),
|
||||
without ever knowing the IP or e-mail address of Delta Chat users.</p>
|
||||
</li>
|
||||
<li>
|
||||
@@ -599,14 +600,15 @@ and also never see any message content (also not in encrypted forms).</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>As of May 2024, chatmail servers know about “device tokens”
|
||||
but we plan to encrypt this information to the notification proxy
|
||||
such that the chatmail server never learns the device token.</p>
|
||||
|
||||
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
|
||||
and forgets about device-tokens as soon as Apple/Google/etc processed them,
|
||||
usually in a matter of milliseconds.</p>
|
||||
|
||||
<p>Note that the device token is encrypted between apps and notification proxy
|
||||
but it is not signed.
|
||||
The notification proxy thus never sees e-mail addresses, IP-addresses or
|
||||
any cryptographic identity information associated with a user’s device (token).</p>
|
||||
|
||||
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
|
||||
or the full seizure of the central Delta Chat notification proxy
|
||||
would not reveal private information that Push services do not already have.</p>
|
||||
@@ -1262,6 +1264,12 @@ L’un n’a pas besoin de l’autre pour pouvoir fonctionner.</p>
|
||||
and make sure, <strong>Private Network</strong> is selected as “Network profile type”
|
||||
(after transfer, you can change back to the original value)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>iOS</strong>, make sure “System Settings / Apps / Delta Chat / <strong>Local Network</strong>” access is granted</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>macOS</strong>, enable “System Settings / Privacy & Security / <strong>Local Network</strong> / Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Il se peut que votre système dispose d’un “pare-feu personnalisé”,
|
||||
source bien connue de dysfonctionnements (en particulier sur Windows).
|
||||
@@ -1375,6 +1383,7 @@ you only open attachments from senders you trust, and not from spammers.</li>
|
||||
<ul>
|
||||
<li>In general, anyone can share webxdc apps with each
|
||||
other without restrictions.</li>
|
||||
<li>From <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
|
||||
<li>You can <a href="https://delta.chat/en/2023-08-11-xstore">send ‘hi’ to xstore@testrun.org</a>
|
||||
to see an experimental webxdc appstore.
|
||||
All of the apps are open source and for free.</li>
|
||||
@@ -1789,6 +1798,35 @@ Otherwise you might receive undecryptable messages from those group chats.</p>
|
||||
<li>Consultez les <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">standards utilisés dans Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="where-can-my-friends-find-delta-chat">
|
||||
|
||||
|
||||
Where can my friends find Delta Chat? <a href="#where-can-my-friends-find-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat is available for all major and some minor platforms:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>The <strong>official website</strong>, <a href="https://delta.chat/download">https://delta.chat/download</a> shows all options in detail</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If unavailable, use the <strong>mirror</strong> at <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, Amazon App Store, iOS and macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Check the <strong>package manager</strong> of your Linux distributions</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Android APKs</strong> are also available on <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="comment-est-financé-le-développement-de-delta-chat-">
|
||||
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#is-delta-chat-compatible-with-protonmail--tutanota--criptext">Is Delta Chat compatible with Protonmail / Tutanota / Criptext?</a></li>
|
||||
<li><a href="#remove-account">How can I delete my account?</a></li>
|
||||
<li><a href="#im-interested-in-the-technical-details-can-you-tell-me-more">I’m interested in the technical details. Can you tell me more?</a></li>
|
||||
<li><a href="#where-can-my-friends-find-delta-chat">Where can my friends find Delta Chat?</a></li>
|
||||
<li><a href="#how-are-delta-chat-developments-funded">How are Delta Chat developments funded?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -301,8 +302,7 @@ Archived chats remain accessible above the chat list or via search.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>To archive or pin a chat, long tap (Android), use the chat’s menu (Android/Desktop) or swipe to the left (iOS);
|
||||
to mute a chat, use the chat’s menu (Android/Desktop) or the chat’s profile (iOS).</p>
|
||||
<p>To use the functions, long tap or right click a chat in the chat list.</p>
|
||||
|
||||
<h3 id="what-does-the-green-dot-mean">
|
||||
|
||||
@@ -603,16 +603,16 @@ to any system involved in the delivery of Push Notifications.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>A Delta Chat app obtains a “device token” locally and stores it
|
||||
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
|
||||
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
|
||||
it forwards the “device token” to the central Delta Chat notification proxy.</p>
|
||||
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The central Delta Chat notification proxy forwards
|
||||
the “device token” to the respective Push service (Apple, Google, etc.),
|
||||
<p>The central Delta Chat notification proxy decrypts the device token
|
||||
and forwards it to the respective Push service (Apple, Google, etc.),
|
||||
without ever knowing the IP or e-mail address of Delta Chat users.</p>
|
||||
</li>
|
||||
<li>
|
||||
@@ -625,14 +625,15 @@ and also never see any message content (also not in encrypted forms).</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>As of May 2024, chatmail servers know about “device tokens”
|
||||
but we plan to encrypt this information to the notification proxy
|
||||
such that the chatmail server never learns the device token.</p>
|
||||
|
||||
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
|
||||
and forgets about device-tokens as soon as Apple/Google/etc processed them,
|
||||
usually in a matter of milliseconds.</p>
|
||||
|
||||
<p>Note that the device token is encrypted between apps and notification proxy
|
||||
but it is not signed.
|
||||
The notification proxy thus never sees e-mail addresses, IP-addresses or
|
||||
any cryptographic identity information associated with a user’s device (token).</p>
|
||||
|
||||
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
|
||||
or the full seizure of the central Delta Chat notification proxy
|
||||
would not reveal private information that Push services do not already have.</p>
|
||||
@@ -1315,6 +1316,12 @@ One device is not needed for the other to work.</p>
|
||||
and make sure, <strong>Private Network</strong> is selected as “Network profile type”
|
||||
(after transfer, you can change back to the original value)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>iOS</strong>, make sure “System Settings / Apps / Delta Chat / <strong>Local Network</strong>” access is granted</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>macOS</strong>, enable “System Settings / Privacy & Security / <strong>Local Network</strong> / Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Your system might have a “personal firewall”,
|
||||
which is known to cause problems (especially on Windows).
|
||||
@@ -1432,6 +1439,7 @@ you only open attachments from senders you trust, and not from spammers.</li>
|
||||
<ul>
|
||||
<li>In general, anyone can share webxdc apps with each
|
||||
other without restrictions.</li>
|
||||
<li>From <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
|
||||
<li>You can <a href="https://delta.chat/en/2023-08-11-xstore">send ‘hi’ to xstore@testrun.org</a>
|
||||
to see an experimental webxdc appstore.
|
||||
All of the apps are open source and for free.</li>
|
||||
@@ -1883,6 +1891,35 @@ Otherwise you might receive undecryptable messages from those group chats.</p>
|
||||
<li>See <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">Standards used in Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="where-can-my-friends-find-delta-chat">
|
||||
|
||||
|
||||
Where can my friends find Delta Chat? <a href="#where-can-my-friends-find-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat is available for all major and some minor platforms:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>The <strong>official website</strong>, <a href="https://delta.chat/download">https://delta.chat/download</a> shows all options in detail</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If unavailable, use the <strong>mirror</strong> at <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, Amazon App Store, iOS and macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Check the <strong>package manager</strong> of your Linux distributions</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Android APKs</strong> are also available on <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="how-are-delta-chat-developments-funded">
|
||||
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#delta-chat-è-compatibile-con-protonmail--tutanota--criptext">Delta Chat è compatibile con Protonmail / Tutanota / Criptext?</a></li>
|
||||
<li><a href="#remove-account">Come posso eliminare il mio profilo?</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>
|
||||
<li><a href="#dove-possono-trovare-delta-chat-i-miei-amici">Dove possono trovare Delta Chat i miei amici?</a></li>
|
||||
<li><a href="#come-viene-finanziato-lo-sviluppo-di-delta-chat">Come viene finanziato lo sviluppo di Delta Chat?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -596,17 +597,17 @@ a qualsiasi sistema coinvolto nella consegna di Notifiche Push.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Un’app Delta Chat ottiene un “gettone del dispositivo” localmente e lo memorizza
|
||||
sul server <a href="https://delta.chat/chatmail">chatmail</a>.</p>
|
||||
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
|
||||
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Quando un server <a href="https://delta.chat/chatmail">chatmail</a> riceve un’e-mail per un utente Delta Chat
|
||||
inoltra il “gettone del dispositivo” al proxy di notifica centrale di Delta Chat.</p>
|
||||
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
|
||||
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Il proxy di notifica centrale di Delta Chat inoltra
|
||||
il “gettone del dispositivo” al rispettivo servizio Push (Apple, Google, ecc.),
|
||||
senza mai conoscere l’IP o l’indirizzo e-mail degli utenti Delta Chat.</p>
|
||||
<p>The central Delta Chat notification proxy decrypts the device token
|
||||
and forwards it to the respective Push service (Apple, Google, etc.),
|
||||
without ever knowing the IP or e-mail address of Delta Chat users.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Il Servizio Push centrale (Apple, Google, ecc.)
|
||||
@@ -618,14 +619,15 @@ e inoltre non vedono mai il contenuto del messaggio (anche non in forma crittogr
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>A partire da Maggio 2024, i server chatmail conoscono i “gettoni del dispositivo”
|
||||
ma prevediamo di crittografare queste informazioni nel proxy di notifica
|
||||
in modo tale che il server chatmail non apprenda mai il gettone del dispositivo.</p>
|
||||
|
||||
<p>Il proxy di notifica centrale di Delta Chat <a href="https://github.com/deltachat/notifiers">è piccolo e completamente implementato in Rust</a>
|
||||
e si dimentica dei gettoni del dispositivo non appena Apple/Google/ecc li elabora,
|
||||
di solito nel giro di pochi millisecondi.</p>
|
||||
|
||||
<p>Note that the device token is encrypted between apps and notification proxy
|
||||
but it is not signed.
|
||||
The notification proxy thus never sees e-mail addresses, IP-addresses or
|
||||
any cryptographic identity information associated with a user’s device (token).</p>
|
||||
|
||||
<p>Come risultato di questo disegno complessivo sulla riservatezza, anche il sequestro di un server chatmail,
|
||||
o il sequestro totale del proxy di notifica centrale di Delta Chat
|
||||
non rivelerebbe informazioni private che i servizi Push non abbiano già.</p>
|
||||
@@ -1302,6 +1304,12 @@ Un dispositivo non è necessario perché l’altro funzioni.</p>
|
||||
e assicurati che <strong>Rete Privata</strong> sia selezionata come “Tipo di profilo di rete”
|
||||
(dopo il trasferimento è possibile ripristinare il valore originale)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Su <strong>iOS</strong>, assicurati che l’accesso a “Impostazioni di Sistema / App / Delta Chat / <strong>Rete locale</strong>” sia concesso</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Su <strong>macOS</strong>, abilita “Impostazioni di Sistema / Privacy & Sicurezza / <strong>Rete locale</strong> / Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Il sistema potrebbe avere un “personal firewall”,
|
||||
che è noto per causare problemi (soprattutto su Windows).
|
||||
@@ -1845,6 +1853,35 @@ Altrimenti potresti ricevere messaggi non decifrabili da quelle chat di gruppo.<
|
||||
<li>Vedi <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">Standard usati in Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="dove-possono-trovare-delta-chat-i-miei-amici">
|
||||
|
||||
|
||||
Dove possono trovare Delta Chat i miei amici? <a href="#dove-possono-trovare-delta-chat-i-miei-amici" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat è disponibile per tutte le piattaforme principali e alcune minori:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Il <strong>sito ufficiale</strong>, <a href="https://delta.chat/download">https://delta.chat/download</a> mostra tutte le opzioni in dettaglio</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Se non disponibile, utilizzare <strong>mirror</strong> su <a href="https://deltachat.github.io/deltachat-pages">https://deltachat.github.io/deltachat-pages</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Apri uno dei seguenti <strong>app store e cerca “Delta Chat”:</strong>
|
||||
Google Play Store, F-Droid, Huawei App Gallery, Amazon App Store, iOS e macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Controlla il <strong>gestore pacchetti</strong> delle tue distribuzioni Linux</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>APK Android</strong> sono disponibili anche su <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="come-viene-finanziato-lo-sviluppo-di-delta-chat">
|
||||
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#is-delta-chat-compatibel-met-protonmailtutanotacriptext">Is Delta Chat compatibel met Protonmail/Tutanota/Criptext?</a></li>
|
||||
<li><a href="#remove-account">Hoe kan ik mijn account verwijderen?</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>
|
||||
<li><a href="#where-can-my-friends-find-delta-chat">Where can my friends find Delta Chat?</a></li>
|
||||
<li><a href="#hoe-wordt-de-ontwikkeling-van-delta-chat-gefinancierd">Hoe wordt de ontwikkeling van Delta Chat gefinancierd?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -596,16 +597,16 @@ to any system involved in the delivery of Push Notifications.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>A Delta Chat app obtains a “device token” locally and stores it
|
||||
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
|
||||
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
|
||||
it forwards the “device token” to the central Delta Chat notification proxy.</p>
|
||||
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The central Delta Chat notification proxy forwards
|
||||
the “device token” to the respective Push service (Apple, Google, etc.),
|
||||
<p>The central Delta Chat notification proxy decrypts the device token
|
||||
and forwards it to the respective Push service (Apple, Google, etc.),
|
||||
without ever knowing the IP or e-mail address of Delta Chat users.</p>
|
||||
</li>
|
||||
<li>
|
||||
@@ -618,14 +619,15 @@ and also never see any message content (also not in encrypted forms).</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>As of May 2024, chatmail servers know about “device tokens”
|
||||
but we plan to encrypt this information to the notification proxy
|
||||
such that the chatmail server never learns the device token.</p>
|
||||
|
||||
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
|
||||
and forgets about device-tokens as soon as Apple/Google/etc processed them,
|
||||
usually in a matter of milliseconds.</p>
|
||||
|
||||
<p>Note that the device token is encrypted between apps and notification proxy
|
||||
but it is not signed.
|
||||
The notification proxy thus never sees e-mail addresses, IP-addresses or
|
||||
any cryptographic identity information associated with a user’s device (token).</p>
|
||||
|
||||
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
|
||||
or the full seizure of the central Delta Chat notification proxy
|
||||
would not reveal private information that Push services do not already have.</p>
|
||||
@@ -1306,6 +1308,12 @@ op beide apparaten</strong>. Hierdoor hoef je niet het ene apparaat bij de hand
|
||||
and make sure, <strong>Private Network</strong> is selected as “Network profile type”
|
||||
(after transfer, you can change back to the original value)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>iOS</strong>, make sure “System Settings / Apps / Delta Chat / <strong>Local Network</strong>” access is granted</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>macOS</strong>, enable “System Settings / Privacy & Security / <strong>Local Network</strong> / Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Wellicht is een firewall actief op je apparaat,
|
||||
welke problemen kan veroorzaken (met name op Windows).
|
||||
@@ -1423,6 +1431,7 @@ you only open attachments from senders you trust, and not from spammers.</li>
|
||||
<ul>
|
||||
<li>In general, anyone can share webxdc apps with each
|
||||
other without restrictions.</li>
|
||||
<li>From <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
|
||||
<li>You can <a href="https://delta.chat/en/2023-08-11-xstore">send ‘hi’ to xstore@testrun.org</a>
|
||||
to see an experimental webxdc appstore.
|
||||
All of the apps are open source and for free.</li>
|
||||
@@ -1868,6 +1877,35 @@ Otherwise you might receive undecryptable messages from those group chats.</p>
|
||||
<li>Bekijk de pagina <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">Door Delta Chat gebruikte standaarden</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="where-can-my-friends-find-delta-chat">
|
||||
|
||||
|
||||
Where can my friends find Delta Chat? <a href="#where-can-my-friends-find-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat is available for all major and some minor platforms:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>The <strong>official website</strong>, <a href="https://delta.chat/download">https://delta.chat/download</a> shows all options in detail</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If unavailable, use the <strong>mirror</strong> at <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, Amazon App Store, iOS and macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Check the <strong>package manager</strong> of your Linux distributions</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Android APKs</strong> are also available on <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="hoe-wordt-de-ontwikkeling-van-delta-chat-gefinancierd">
|
||||
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#czy-delta-chat-jest-kompatybilny-z-protonmail--tutanota--criptext">Czy Delta Chat jest kompatybilny z Protonmail / Tutanota / Criptext?</a></li>
|
||||
<li><a href="#remove-account">Jak mogę usunąć swoje konto?</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>
|
||||
<li><a href="#gdzie-moi-znajomi-mogą-znaleźć-delta-chat">Gdzie moi znajomi mogą znaleźć Delta Chat?</a></li>
|
||||
<li><a href="#w-jaki-sposób-finansowany-jest-rozwój-delta-chat">W jaki sposób finansowany jest rozwój Delta Chat?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -265,8 +266,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Aby zarchiwizować lub przypiąć czat, dotknij i przytrzymaj (Android), użyj menu czatu (Android/Desktop) lub przesuń palcem w lewo (iOS);
|
||||
aby wyciszyć czat, użyj menu czatu (Android/Desktop) lub profilu czatu (iOS).</p>
|
||||
<p>Aby skorzystać z tych funkcji, przytrzymaj dłużej lub kliknij prawym przyciskiem myszy czat na liście czatów.</p>
|
||||
|
||||
<h3 id="co-oznacza-zielona-kropka">
|
||||
|
||||
@@ -494,23 +494,23 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Aplikacja Delta Chat uzyskuje lokalnie „token urządzenia” i przechowuje go na serwerze <a href="https://delta.chat/chatmail">chatmail</a>.</p>
|
||||
<p>Aplikacja Delta Chat uzyskuje lokalnie „token urządzenia”, szyfruje i przechowuje go na serwerze <a href="https://delta.chat/chatmail">chatmail</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Kiedy serwer <a href="https://delta.chat/chatmail">chatmail</a> odbierze wiadomość e-mail od użytkownika Delta Chat, przekazuje „token urządzenia” do centralnego serwera proxy powiadomień Delta Chat.</p>
|
||||
<p>Kiedy serwer <a href="https://delta.chat/chatmail">chatmail</a> odbierze wiadomość e-mail od użytkownika Delta Chat, przekazuje zaszyfrowany token urządzenia do centralnego serwera proxy powiadomień Delta Chat.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Centralny serwer proxy powiadomień Delta Chat przekazuje „token urządzenia” do odpowiedniej usługi Push (Apple, Google itp.), nie znając nawet adresu IP ani adresu e-mail użytkowników Delta Chat.</p>
|
||||
<p>Centralny serwer proxy powiadomień Delta Chat deszyfruje token urządzenia i przekazuje go do odpowiedniej usługi Push (Apple, Google itp.), nie znając nawet adresu IP ani adresu e-mail użytkowników Delta Chat.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Centralna usługa Push (Apple, Google itp.) budzi aplikację Delta Chat na twoim urządzeniu, aby sprawdzić w tle nowe wiadomości. Nie zna chatmaila ani adresu e-mail urządzenia, na którym się budzi. Centralne usługi push Apple/Google nigdy nie widzą adresu e-mail (nadawcy ani odbiorcy), a także nigdy nie widzą treści wiadomości (również w formie zaszyfrowanej).</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Od maja 2024 r. serwery chatmail znają „tokeny urządzenia”, ale planujemy szyfrować te informacje na serwerze proxy powiadomień, tak aby serwer chatmail nigdy nie poznał tokena urządzenia.</p>
|
||||
|
||||
<p>Centralny serwer proxy powiadomień Delta Chat <a href="https://github.com/deltachat/notifiers">jest mały i w pełni zaimplementowany w Rust</a> i zapomina o tokenach urządzeń zaraz po ich przetworzeniu przez Apple/Google/itp, zwykle w ciągu kilku milisekund.</p>
|
||||
|
||||
<p>Pamiętaj, że token urządzenia jest szyfrowany między aplikacjami a serwerem proxy powiadomień, ale nie jest podpisany. Serwer proxy powiadomień nigdy nie widzi adresów e-mail, adresów IP ani żadnych kryptograficznych informacji identyfikujących powiązanych z urządzeniem użytkownika (tokenem).</p>
|
||||
|
||||
<p>W wyniku tego ogólnego projektu ochrony prywatności nawet przejęcie serwera chatmail lub pełne przejęcie centralnego serwera proxy powiadomień Delta Chat nie spowodowałoby ujawnienia prywatnych informacji, których usługi Push jeszcze nie posiadają.</p>
|
||||
|
||||
<h3 id="dlaczego-delta-chat-integruje-się-ze-scentralizowanymi-zastrzeżonymi-usługami-push-applegoogle">
|
||||
@@ -941,6 +941,12 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
<p>Na <strong>Windowsie</strong>, przejdź do <strong>Panel sterowania / Sieć i internet</strong> i upewnij się, że <strong>Sieć prywatna</strong> jest wybrana jako “Typ profilu sieci”
|
||||
(po przeniesieniu możesz wrócić do pierwotnej wartości)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>W systemie <strong>iOS</strong> upewnij się, że jest przydzielony dostęp do opcji „Ustawienia » Aplikacje » Delta Chat » <strong>Sieć lokalna</strong>”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>W systemie <strong>macOS</strong> włącz „Preferencje systemowe » Ochrona i prywatność » <strong>Sieć lokalna</strong> » Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Twój system może mieć „zaporę ogniową”, o której wiadomo, że powoduje problemy (szczególnie w systemie Windows).
|
||||
<strong>Wyłącz zaporę</strong> dla Delta Chat po obu stronach i spróbuj ponownie</p>
|
||||
@@ -1031,6 +1037,7 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
|
||||
<ul>
|
||||
<li>Ogólnie rzecz biorąc, każdy może udostępniać sobie aplikacje webxdc bez ograniczeń.</li>
|
||||
<li>Od <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
|
||||
<li>Możesz <a href="https://delta.chat/en/2023-08-11-xstore">wysłać „hi” na adres xstore@testrun.org</a>, aby zobaczyć eksperymentalny sklep z aplikacjami webxdc. Wszystkie aplikacje są otwarto źródłowe i są bezpłatne.</li>
|
||||
<li>Wiele osób pisze własne, aplikacje webxdc i publikuje je na <a href="https://support.delta.chat/c/webxdc/20">forum Delta Chat</a>.</li>
|
||||
</ul>
|
||||
@@ -1356,6 +1363,34 @@ jeśli chcesz sprawdzić, czy Twoje poświadczenia są przetwarzane w bezpieczny
|
||||
<li>Zobacz <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">Standardy używane w Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="gdzie-moi-znajomi-mogą-znaleźć-delta-chat">
|
||||
|
||||
|
||||
Gdzie moi znajomi mogą znaleźć Delta Chat? <a href="#gdzie-moi-znajomi-mogą-znaleźć-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat jest dostępny na wszystkich głównych i niektórych mniejszych platformach:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Oficjalna <strong>strona internetowa</strong> <a href="https://delta.chat/download">https://delta.chat/download</a> pokazuje wszystkie opcje szczegółowo</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Jeśli nie jest dostępna, użyj <strong>kopii strony</strong> pod adresem <a href="https://deltachat.github.io/deltachat-pages">https://deltachat.github.io/deltachat-pages</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Otwórz jeden z następujących <strong>sklepów z aplikacjami i wyszukaj „Delta Chat”</strong>: Google Play Store, F-Droid, Huawei App Gallery, Amazon App Store, iOS i macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Sprawdź <strong>menedżera pakietów</strong> swoich dystrybucji Linuksa</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Aplikacje na Androida</strong> są również dostępne na <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="w-jaki-sposób-finansowany-jest-rozwój-delta-chat">
|
||||
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#o-delta-chat-é-compatível-com-protonmail--tutanota--criptext">O Delta Chat é compatível com Protonmail / Tutanota / Criptext?</a></li>
|
||||
<li><a href="#remove-account">How can I delete my account?</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>
|
||||
<li><a href="#where-can-my-friends-find-delta-chat">Where can my friends find Delta Chat?</a></li>
|
||||
<li><a href="#como-são-os-desenvolvimentos-do-delta-chat-financiados">Como são os desenvolvimentos do Delta Chat financiados?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -297,8 +298,7 @@ Archived chats remain accessible above the chat list or via search.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>To archive or pin a chat, long tap (Android), use the chat’s menu (Android/Desktop) or swipe to the left (iOS);
|
||||
to mute a chat, use the chat’s menu (Android/Desktop) or the chat’s profile (iOS).</p>
|
||||
<p>To use the functions, long tap or right click a chat in the chat list.</p>
|
||||
|
||||
<h3 id="what-does-the-green-dot-mean">
|
||||
|
||||
@@ -597,16 +597,16 @@ to any system involved in the delivery of Push Notifications.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>A Delta Chat app obtains a “device token” locally and stores it
|
||||
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
|
||||
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
|
||||
it forwards the “device token” to the central Delta Chat notification proxy.</p>
|
||||
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The central Delta Chat notification proxy forwards
|
||||
the “device token” to the respective Push service (Apple, Google, etc.),
|
||||
<p>The central Delta Chat notification proxy decrypts the device token
|
||||
and forwards it to the respective Push service (Apple, Google, etc.),
|
||||
without ever knowing the IP or e-mail address of Delta Chat users.</p>
|
||||
</li>
|
||||
<li>
|
||||
@@ -619,14 +619,15 @@ and also never see any message content (also not in encrypted forms).</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>As of May 2024, chatmail servers know about “device tokens”
|
||||
but we plan to encrypt this information to the notification proxy
|
||||
such that the chatmail server never learns the device token.</p>
|
||||
|
||||
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
|
||||
and forgets about device-tokens as soon as Apple/Google/etc processed them,
|
||||
usually in a matter of milliseconds.</p>
|
||||
|
||||
<p>Note that the device token is encrypted between apps and notification proxy
|
||||
but it is not signed.
|
||||
The notification proxy thus never sees e-mail addresses, IP-addresses or
|
||||
any cryptographic identity information associated with a user’s device (token).</p>
|
||||
|
||||
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
|
||||
or the full seizure of the central Delta Chat notification proxy
|
||||
would not reveal private information that Push services do not already have.</p>
|
||||
@@ -1309,6 +1310,12 @@ One device is not needed for the other to work.</p>
|
||||
and make sure, <strong>Private Network</strong> is selected as “Network profile type”
|
||||
(after transfer, you can change back to the original value)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>iOS</strong>, make sure “System Settings / Apps / Delta Chat / <strong>Local Network</strong>” access is granted</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>macOS</strong>, enable “System Settings / Privacy & Security / <strong>Local Network</strong> / Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Your system might have a “personal firewall”,
|
||||
which is known to cause problems (especially on Windows).
|
||||
@@ -1426,6 +1433,7 @@ you only open attachments from senders you trust, and not from spammers.</li>
|
||||
<ul>
|
||||
<li>In general, anyone can share webxdc apps with each
|
||||
other without restrictions.</li>
|
||||
<li>From <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
|
||||
<li>You can <a href="https://delta.chat/en/2023-08-11-xstore">send ‘hi’ to xstore@testrun.org</a>
|
||||
to see an experimental webxdc appstore.
|
||||
All of the apps are open source and for free.</li>
|
||||
@@ -1869,6 +1877,35 @@ Otherwise you might receive undecryptable messages from those group chats.</p>
|
||||
<li>Veja <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">As normas usadas no Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="where-can-my-friends-find-delta-chat">
|
||||
|
||||
|
||||
Where can my friends find Delta Chat? <a href="#where-can-my-friends-find-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat is available for all major and some minor platforms:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>The <strong>official website</strong>, <a href="https://delta.chat/download">https://delta.chat/download</a> shows all options in detail</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If unavailable, use the <strong>mirror</strong> at <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, Amazon App Store, iOS and macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Check the <strong>package manager</strong> of your Linux distributions</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Android APKs</strong> are also available on <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="como-são-os-desenvolvimentos-do-delta-chat-financiados">
|
||||
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
<li><a href="#разное">Разное</a>
|
||||
<ul>
|
||||
<li><a href="#какие-разрешения-нужны-delta-chat">Какие разрешения нужны Delta Chat?</a></li>
|
||||
<li><a href="#работает-ли-delta-chat-работу-с-моим-провайдером-электронной-почты">Работает ли Delta Chat работу с <em>моим</em> провайдером электронной почты?</a></li>
|
||||
<li><a href="#работает-ли-delta-chat-с-моим-провайдером-электронной-почты">Работает ли Delta Chat с <em>моим</em> провайдером электронной почты?</a></li>
|
||||
<li><a href="#я-хочу-управлять-своим-собственным-почтовым-сервером-для-delta-chat-что-вы-посоветуете">Я хочу управлять своим собственным почтовым сервером для Delta Chat. Что вы посоветуете?</a></li>
|
||||
<li><a href="#почему-я-должен-вводить-свой-пароль-от-электронной-почты-в-delta-chat-это-безопасно">Почему я должен вводить свой пароль от электронной почты в Delta Chat? Это безопасно?</a></li>
|
||||
<li><a href="#какие-сообщения-отображаются-в-delta-chat">Какие сообщения отображаются в Delta Chat?</a></li>
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#совместим-ли-delta-chat-с-protonmail--tutanota--criptext">Совместим ли Delta Chat с Protonmail / Tutanota / Criptext?</a></li>
|
||||
<li><a href="#remove-account">Как я могу удалить свой аккаунт?</a></li>
|
||||
<li><a href="#меня-интересуют-технические-детали-можете-рассказать-больше">Меня интересуют технические детали. Можете рассказать больше?</a></li>
|
||||
<li><a href="#где-мои-друзья-могут-найти-delta-chat">Где мои друзья могут найти Delta Chat?</a></li>
|
||||
<li><a href="#как-финансируются-разработки-delta-chat">Как финансируются разработки Delta Chat?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -217,7 +218,7 @@
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Профиль - это <strong>имя, изображение</strong> и некоторая дополнительная информация для шифрования сообщений.
|
||||
<p>Профиль — это <strong>имя, изображение</strong> и некоторая дополнительная информация для шифрования сообщений.
|
||||
Профиль существует только на вашем устройстве(ах)
|
||||
и использует серверы chatmail или обычные серверы электронной почты для передачи сообщений.</p>
|
||||
|
||||
@@ -301,8 +302,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Чтобы архивировать или закрепить чат, нажмите на него долгим нажатием (Android), воспользуйтесь меню чата (Android/Desktop) или проведите пальцем влево (iOS);
|
||||
чтобы отключить уведомления, воспользуйтесь меню чата (Android/Desktop) или профиль чата (iOS).</p>
|
||||
<p>Чтобы использовать функции, нажмите долгим нажатием или щелкните правой кнопкой мыши по чату в списке чатов.</p>
|
||||
|
||||
<h3 id="что-означает-зеленая-точка">
|
||||
|
||||
@@ -350,7 +350,7 @@
|
||||
приложение Delta Chat каждого участника чата позаботится
|
||||
об удалении сообщений
|
||||
по истечении выбранного периода времени.
|
||||
Отсчет времени начинается
|
||||
Отсчет времени начинается,
|
||||
когда получатель впервые видит сообщение в Delta Chat.
|
||||
Сообщения удаляются
|
||||
как в каждой учетной записи электронной почты на сервере,
|
||||
@@ -429,7 +429,7 @@
|
||||
Если позже вы снова захотите присоединиться к группе, попросите другого участника группы добавить вас.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Или, вместо этого, вы можете “отключить уведомления” для группы - это означает, что вы будете получать все сообщения и сможете их писать, но больше не будете получать уведомления о новых сообщениях.</p>
|
||||
<p>Или, вместо этого, вы можете “отключить уведомления” для группы — это означает, что вы будете получать все сообщения и сможете их писать, но больше не будете получать уведомления о новых сообщениях.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -474,7 +474,7 @@
|
||||
По истечении этого срока все сообщения, полученные Delta Chat, будут удалены с сервера.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Обратите внимание, что если вы используете Delta Chat на нескольких устройствах,
|
||||
<p>Обратите внимание, что, если вы используете Delta Chat на нескольких устройствах,
|
||||
необходимо оставлять сообщения на сервере с достаточным временным интервалом,
|
||||
чтобы другое устройство(а) тоже смогло их загрузить.</p>
|
||||
</li>
|
||||
@@ -575,8 +575,8 @@ Push-уведомления недоступны.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Принудительное соединение в фоновом режиме: это запасной вариант
|
||||
если предыдущие варианты недоступны или или не обеспечивают “мгновенную доставку”.
|
||||
Включение этого параметра вызывает постоянное уведомление на вашем телефоне
|
||||
если предыдущие варианты недоступны или не обеспечивают “мгновенную доставку”.
|
||||
Включение этого параметра вызывает постоянное уведомление на вашем телефоне,
|
||||
которое иногда может быть “сжато” на последних телефонах Android.</p>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -600,16 +600,16 @@ Push-уведомления недоступны.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Приложение Delta Chat локально получает “токен устройства” и сохраняет его
|
||||
<p>Приложение Delta Chat локально получает “токен устройства” шифрует его и сохраняет
|
||||
на сервере <a href="https://delta.chat/chatmail">chatmail</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Когда сервер <a href="https://delta.chat/chatmail">chatmail</a> получает электронную почту для пользователя Delta Chat
|
||||
он пересылает “токен устройства” центральному прокси-серверу уведомлений Delta Chat.</p>
|
||||
он пересылает “зашифрованный токен устройства” центральному прокси-серверу уведомлений Delta Chat.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Центральный прокси-сервер уведомлений Delta Chat пересылает
|
||||
“токен устройства” в соответствующую службу Push (Apple, Google и т. д.),
|
||||
<p>Центральный прокси-сервер уведомлений Delta Chat расшифровывает “токен устройства” и
|
||||
пересылает его в соответствующую службу Push (Apple, Google и т. д.),
|
||||
даже не зная IP-адрес или адрес электронной почты пользователей Delta Chat.</p>
|
||||
</li>
|
||||
<li>
|
||||
@@ -622,14 +622,15 @@ Push-уведомления недоступны.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>По состоянию на май 2024 года серверы chatmail знают о “токенах устройства”,
|
||||
но мы планируем зашифровать эту информацию для прокси-сервера уведомлений
|
||||
так, чтобы сервер chatmail не смог получить доступ к токену устройства.</p>
|
||||
|
||||
<p>Центральный прокси-сервер уведомлений Delta Chat <a href="https://github.com/deltachat/notifiers">небольшой и полностью реализован на Rust</a>
|
||||
забывает о токенах устройств, как только Apple/Google/и т. д. обработали их,
|
||||
обычно за несколько миллисекунд.</p>
|
||||
|
||||
<p>Обратите внимание, что токен устройства шифруется между приложениями и прокси-сервером уведомлений,
|
||||
но не подписывается.
|
||||
Прокси-сервер уведомлений не получает доступ к адресам электронной почты, IP-адресам
|
||||
или криптографическим идентификационным данным устройства пользователя (токену).</p>
|
||||
|
||||
<p>В результате такого общего подхода к обеспечению конфиденциальности, даже захват почтового сервера chatmail,
|
||||
или полный захват центрального прокси-сервера уведомлений Delta Chat
|
||||
не раскроет конфиденциальную информацию, которой сервисы Push уже не обладают.</p>
|
||||
@@ -642,7 +643,7 @@ Push-уведомления недоступны.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat - это бесплатный децентрализованный мессенджер с открытым исходным кодом и возможностью выбора сервера,
|
||||
<p>Delta Chat — это бесплатный децентрализованный мессенджер с открытым исходным кодом и возможностью выбора сервера,
|
||||
но мы хотим, чтобы пользователи гарантированно получали “мгновенную доставку” сообщений,
|
||||
такую же, что и в приложениях WhatsApp, Signal или Telegram,
|
||||
не задавая вопросов, которые больше подходят для опытных пользователей или разработчиков.</p>
|
||||
@@ -671,7 +672,7 @@ Push-уведомления недоступны.</p>
|
||||
<p><a href="https://autocrypt.org">Autocrypt</a> используется для автоматической
|
||||
установки сквозного шифрования при работе с контактами и групповыми чатами.
|
||||
Autocrypt использует ограниченное и <a href="#openpgp-secure">безопасное подмножество стандарта OpenPGP</a>.
|
||||
Сообщения, зашифрованные сквозным шифрованием помечаются замком
|
||||
Сообщения, зашифрованные сквозным шифрованием, помечаются замком
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../lock-icon.png" alt="padlock" />.</p>
|
||||
|
||||
<p><a href="https://securejoin.delta.chat/en/latest/new.html">Протоколы Secure-Join</a>
|
||||
@@ -689,7 +690,7 @@ Autocrypt использует ограниченное и <a href="#openpgp-sec
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Все сообщения зашифрованые сквозным шифрованием имеют значок замка:</p>
|
||||
<p>Все сообщения, зашифрованные сквозным шифрованием, имеют значок замка:</p>
|
||||
|
||||
<p><img style="width:160px; margin:1px" src="../lock-screenshot.png" alt="Значок замка в пузырьке" /></p>
|
||||
|
||||
@@ -779,7 +780,7 @@ Autocrypt использует ограниченное и <a href="#openpgp-sec
|
||||
В профиле контакта можно несколько раз нажать на текст “Представлен …” несколько раз
|
||||
пока не дойдёте до того, с кем вы непосредственно провели <a href="#howtoe2ee">QR-сканирование</a>.</p>
|
||||
|
||||
<p>Обратите внимание, что в профиле контакта вы можете увидеть и присоеденённых знакомых
|
||||
<p>Обратите внимание, что в профиле контакта вы можете увидеть и присоединённых знакомых,
|
||||
но в заголовке профиля нет зелёной галочки.
|
||||
Обычно это означает, что контакт <a href="#nocryptanymore">“отправил сообщение с другого устройства”</a>.</p>
|
||||
|
||||
@@ -797,10 +798,10 @@ Autocrypt использует ограниченное и <a href="#openpgp-sec
|
||||
</h3>
|
||||
|
||||
<p>Ваш чат с контактом утратил гарантированное сквозное шифрование.
|
||||
Зелёная галочка была удалёна для этого чата и контакта, и когда вы увидели предупреждение.
|
||||
Зелёная галочка была удалена для этого чата и контакта, и когда вы увидели предупреждение.
|
||||
<strong>Если вы обнаружили внезапное прекращение гарантированного сквозного шифрования
|
||||
для этого контакта, не принимайте предупреждение!</strong>
|
||||
Вместо этого свяжитесь со своим контактом по второму каналу
|
||||
Вместо этого свяжитесь со своим контактом по второму каналу,
|
||||
например, видеозвонок, другой мессенджер или телефонный звонок,
|
||||
чтобы узнать, что произошло.</p>
|
||||
|
||||
@@ -935,7 +936,7 @@ Delta Chat вместо этого использует реализацию Ope
|
||||
и возвращает <a href="https://docs.rs/pgp/latest/pgp/errors/enum.Error.html#variant.MdcError">ошибку</a>
|
||||
если код обнаружения модификаций не совпадает.</p>
|
||||
|
||||
<p>Delta Chat также никогда не был уязвим к атаке “Direct Exfiltration” EFAIL
|
||||
<p>Delta Chat также никогда не был уязвим к атаке “Direct Exfiltration” EFAIL,
|
||||
потому что он расшифровывает только <code class="language-plaintext highlighter-rouge">многочастные/зашифрованные</code> сообщения,
|
||||
которые содержат ровно одну зашифрованную и подписанную часть,
|
||||
как определено спецификацией Autocrypt Level 1.</p>
|
||||
@@ -1172,16 +1173,16 @@ Look for something like <strong>Start Autocrypt Setup Transfer</strong> in the s
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Наиболее вероятная причина - это то, что ваш ключ зашифрован и/или имеет пароль.
|
||||
<p>Наиболее вероятная причина — это то, что ваш ключ зашифрован и/или имеет пароль.
|
||||
Delta Chat не поддерживает такие ключи.
|
||||
Вы можете снять шифрование пароля и пароль, а затем повторить попытку импорта.</p>
|
||||
|
||||
<p>Другая распространенная ошибка - неправильное расширение файла.
|
||||
Используйте формат ASCII armored и расширение файла <code class="language-plaintext highlighter-rouge">.asc</code>.</p>
|
||||
|
||||
<p>Delta Chat поддерживает расспространённые форматы закрытых ключей OpenPGP, однако
|
||||
<p>Delta Chat поддерживает распространённые форматы закрытых ключей OpenPGP, однако
|
||||
маловероятно, что мы будем поддерживать все закрытые ключи из любых источников. Это
|
||||
не является основной целью Delta Chat. На самом деле, подавляющее большинство пользователей
|
||||
не является основной целью Delta Chat. На самом деле, подавляющее большинство пользователей
|
||||
Delta Chat не будут иметь никакого ключа, прежде чем они начнут использовать его.
|
||||
Однако мы стремимся поддерживать закрытые ключи из как можно большего числа источников.</p>
|
||||
|
||||
@@ -1305,13 +1306,19 @@ Chat <a href="https://github.com/rpgp/rpgp">PGP</a> и
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Перепроверьте, что оба устройства находятся в <strong>в одной Wi-Fi или локальной сети</strong>.</p>
|
||||
<p>Перепроверьте, что оба устройства находятся <strong>в одной Wi-Fi или локальной сети</strong>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>В <strong>Windows</strong> перейдите в <strong>Панель управления / Сеть и Интернет</strong>
|
||||
и убедитесь, что в качестве “Типа сетевого профиля” выбрана <strong>Частная сеть</strong>.
|
||||
(после передачи, вы можете изменить обратно на исходное значение)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>На <strong>iOS</strong>, убедитесь, что предоставлен доступ “Настройки системы / Приложения / Delta Chat / <strong>Локальная сеть</strong>”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>На <strong>macOS</strong>, включите “Системные настройки / Конфиденциальность и безопасность / <strong>Локальная сеть</strong> / Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>В вашей системе может быть установлен “персональный брандмауэр”,
|
||||
который может вызвать проблемы (особенно на Windows).
|
||||
@@ -1407,12 +1414,12 @@ PIN-код разблокировки экрана, графический кл
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>Приложения webxdc webxdc не могут отправлять данные в Интернет или скачивать что-либо.</li>
|
||||
<li>Приложения webxdc не могут отправлять данные в Интернет или скачивать что-либо.</li>
|
||||
<li>Приложение webxdc может обмениваться данными только внутри чата Delta Chat, с его
|
||||
копиями на устройствах ваших собеседников по чату.
|
||||
В остальном, оно полностью
|
||||
изолировано от Интернета.</li>
|
||||
<li>Конфиденциальность, которую обеспечивает приложение webxdc - это конфиденциальность вашего чата - пока
|
||||
<li>Конфиденциальность, которую обеспечивает приложение webxdc — это конфиденциальность вашего чата - пока
|
||||
вы доверяете людям, с которыми вы общаетесь, вы можете доверять приложению webxdc.</li>
|
||||
<li>Это также означает, что открытие приложений webxdc в чатах с участниками, которым вы
|
||||
не доверяете, тоже самое, что и с вложениями электронной почты, когда вы открываете
|
||||
@@ -1430,11 +1437,11 @@ PIN-код разблокировки экрана, графический кл
|
||||
<ul>
|
||||
<li>В общем, каждый может поделиться приложениями webxdc
|
||||
друг с другом без ограничений.</li>
|
||||
<li>Из <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
|
||||
<li>Вы можете <a href="https://delta.chat/en/2023-08-11-xstore">отправить ‘hi’ на xstore@testrun.org</a>
|
||||
чтобы увидеть экспериментальный магазин приложений webxdc.
|
||||
Все приложения с открытым исходным кодом и бесплатны.</li>
|
||||
<li>Многие люди пишут свои собственные приложения webxdc и публикуют их на <a href="https://support.delta.chat/c/webxdc/20">форуме
|
||||
Delta Chat</a>.</li>
|
||||
<li>Многие люди создают свои собственные приложения webxdc и публикуют их на <a href="https://support.delta.chat/c/webxdc/20">форуме Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="как-я-могу-создать-свои-собственные-приложения-webxdc">
|
||||
@@ -1446,7 +1453,7 @@ Delta Chat</a>.</li>
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>Приложения webxdc - это просто архивы zip, содержащие код html, css и javascript.</li>
|
||||
<li>Приложения webxdc — это просто архивы zip, содержащие код html, css и javascript.</li>
|
||||
<li>Вы можете расширить <a href="https://github.com/webxdc/hello">пример приложения Hello World</a>
|
||||
для начала.</li>
|
||||
<li>Все остальное, что вам нужно знать, написано в
|
||||
@@ -1572,7 +1579,7 @@ Delta Chat</a>.</li>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Измените свой адрес в разделе “Настройки → Дополнительные параметры → Пароль и аккаунт” и
|
||||
введите пароль вашей новой электронной почты (и если необходимо, настройки сервера).
|
||||
введите пароль вашей новой электронной почты (и, если необходимо, настройки сервера).
|
||||
Вы получите информационное сообщение о том, что переходите на новый адрес.
|
||||
Дополнительное уведомление также появится в вашем чате “Сообщения устройства”.</p>
|
||||
</li>
|
||||
@@ -1656,10 +1663,10 @@ Delta Chat</a>.</li>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="работает-ли-delta-chat-работу-с-моим-провайдером-электронной-почты">
|
||||
<h3 id="работает-ли-delta-chat-с-моим-провайдером-электронной-почты">
|
||||
|
||||
|
||||
Работает ли Delta Chat работу с <em>моим</em> провайдером электронной почты? <a href="#работает-ли-delta-chat-работу-с-моим-провайдером-электронной-почты" class="anchor"></a>
|
||||
Работает ли Delta Chat с <em>моим</em> провайдером электронной почты? <a href="#работает-ли-delta-chat-с-моим-провайдером-электронной-почты" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -1791,7 +1798,7 @@ Delta Chat необходим пароль, чтобы использовать
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Единственная причина, по которой вы можете захотеть наблюдать за папкой “Отправленные”, - это если вы используете другую
|
||||
<p>Единственная причина, по которой вы можете захотеть наблюдать за папкой “Отправленные”, — это если вы используете другую
|
||||
почтовую программу (например, Thunderbird) вместе с приложением Delta Chat, и хотите, чтобы ваш почтовый клиент
|
||||
мог участвовать в разговорах в чате.</p>
|
||||
|
||||
@@ -1879,6 +1886,35 @@ Chat.</li>
|
||||
<li>Смотрите <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">Стандарты, используемые в Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="где-мои-друзья-могут-найти-delta-chat">
|
||||
|
||||
|
||||
Где мои друзья могут найти Delta Chat? <a href="#где-мои-друзья-могут-найти-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat доступен на всех популярных и некоторых менее известных платформах:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>На <strong>официальной странице загрузки</strong>, <a href="https://delta.chat/download">https://delta.chat/download</a> можно найти подробную информацию о всех вариантах</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Если основной сайт недоступен, используйте <strong>зеркало</strong> <a href="https://deltachat.github.io/deltachat-pages">https://deltachat.github.io/deltachat-pages</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Откройте один из следующих <strong>онлайн-магазинов приложений и введите запрос “Delta Chat”:</strong>
|
||||
Google Play Store, F-Droid, Huawei App Gallery, Amazon App Store, App Store для iOS и macOS, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Проверьте <strong>менеджер пакетов</strong> вашего дистрибутива Linux</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Файлы <strong>APK для Android</strong> доступны на <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="как-финансируются-разработки-delta-chat">
|
||||
|
||||
|
||||
@@ -1895,7 +1931,7 @@ Chat.</li>
|
||||
основанную на Свободном и Открытом исходном коде.</p>
|
||||
|
||||
<p>В частности, разработка Delta Chat финансировалась из следующих источников,
|
||||
перечисленны в хронологическом порядке:</p>
|
||||
перечислены в хронологическом порядке:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
@@ -1910,7 +1946,7 @@ Chat.</li>
|
||||
и выпустили первую бета-версию приложения для настольных систем, а также провели
|
||||
исследования в области UX в контексте прав человека,
|
||||
см. наш заключительный отчет <a href="https://delta.chat/en/2019-07-19-uxreport">Needfinding and UX report</a>.
|
||||
Второй грант, полученый в 2019/2020 году (~$300тыс.), помог нам
|
||||
Второй грант, полученный в 2019/2020 году (~$300 тыс.), помог нам
|
||||
выпустить версии Delta/iOS, перевести наш основной код на Rust и
|
||||
предоставить новые функции для всех платформ.</p>
|
||||
</li>
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#je-delta-chat-kompatibilný-s-protonmail--tutanota--criptext">Je Delta Chat kompatibilný s Protonmail / Tutanota / Criptext?</a></li>
|
||||
<li><a href="#remove-account">How can I delete my account?</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>
|
||||
<li><a href="#where-can-my-friends-find-delta-chat">Where can my friends find Delta Chat?</a></li>
|
||||
<li><a href="#ako-sa-financuje-vývoj-delta-chat">Ako sa financuje vývoj Delta Chat?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -301,8 +302,7 @@ Archived chats remain accessible above the chat list or via search.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>To archive or pin a chat, long tap (Android), use the chat’s menu (Android/Desktop) or swipe to the left (iOS);
|
||||
to mute a chat, use the chat’s menu (Android/Desktop) or the chat’s profile (iOS).</p>
|
||||
<p>To use the functions, long tap or right click a chat in the chat list.</p>
|
||||
|
||||
<h3 id="what-does-the-green-dot-mean">
|
||||
|
||||
@@ -603,16 +603,16 @@ to any system involved in the delivery of Push Notifications.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>A Delta Chat app obtains a “device token” locally and stores it
|
||||
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
|
||||
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
|
||||
it forwards the “device token” to the central Delta Chat notification proxy.</p>
|
||||
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The central Delta Chat notification proxy forwards
|
||||
the “device token” to the respective Push service (Apple, Google, etc.),
|
||||
<p>The central Delta Chat notification proxy decrypts the device token
|
||||
and forwards it to the respective Push service (Apple, Google, etc.),
|
||||
without ever knowing the IP or e-mail address of Delta Chat users.</p>
|
||||
</li>
|
||||
<li>
|
||||
@@ -625,14 +625,15 @@ and also never see any message content (also not in encrypted forms).</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>As of May 2024, chatmail servers know about “device tokens”
|
||||
but we plan to encrypt this information to the notification proxy
|
||||
such that the chatmail server never learns the device token.</p>
|
||||
|
||||
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
|
||||
and forgets about device-tokens as soon as Apple/Google/etc processed them,
|
||||
usually in a matter of milliseconds.</p>
|
||||
|
||||
<p>Note that the device token is encrypted between apps and notification proxy
|
||||
but it is not signed.
|
||||
The notification proxy thus never sees e-mail addresses, IP-addresses or
|
||||
any cryptographic identity information associated with a user’s device (token).</p>
|
||||
|
||||
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
|
||||
or the full seizure of the central Delta Chat notification proxy
|
||||
would not reveal private information that Push services do not already have.</p>
|
||||
@@ -1315,6 +1316,12 @@ One device is not needed for the other to work.</p>
|
||||
and make sure, <strong>Private Network</strong> is selected as “Network profile type”
|
||||
(after transfer, you can change back to the original value)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>iOS</strong>, make sure “System Settings / Apps / Delta Chat / <strong>Local Network</strong>” access is granted</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>macOS</strong>, enable “System Settings / Privacy & Security / <strong>Local Network</strong> / Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Your system might have a “personal firewall”,
|
||||
which is known to cause problems (especially on Windows).
|
||||
@@ -1432,6 +1439,7 @@ you only open attachments from senders you trust, and not from spammers.</li>
|
||||
<ul>
|
||||
<li>In general, anyone can share webxdc apps with each
|
||||
other without restrictions.</li>
|
||||
<li>From <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
|
||||
<li>You can <a href="https://delta.chat/en/2023-08-11-xstore">send ‘hi’ to xstore@testrun.org</a>
|
||||
to see an experimental webxdc appstore.
|
||||
All of the apps are open source and for free.</li>
|
||||
@@ -1879,6 +1887,35 @@ Otherwise you might receive undecryptable messages from those group chats.</p>
|
||||
<li>Pozrite si <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">Štandardy používané v Delta Chate</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="where-can-my-friends-find-delta-chat">
|
||||
|
||||
|
||||
Where can my friends find Delta Chat? <a href="#where-can-my-friends-find-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat is available for all major and some minor platforms:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>The <strong>official website</strong>, <a href="https://delta.chat/download">https://delta.chat/download</a> shows all options in detail</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If unavailable, use the <strong>mirror</strong> at <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, Amazon App Store, iOS and macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Check the <strong>package manager</strong> of your Linux distributions</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Android APKs</strong> are also available on <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="ako-sa-financuje-vývoj-delta-chat">
|
||||
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#a-është-i-përputhshëm-delta-chat-i-me-protonmail-in--tutanota-n--criptext-in">A është i përputhshëm Delta Chat-i me Protonmail-in / Tutanota-n / Criptext-in?</a></li>
|
||||
<li><a href="#remove-account">Si mund ta fshij llogarinë time?</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>
|
||||
<li><a href="#where-can-my-friends-find-delta-chat">Where can my friends find Delta Chat?</a></li>
|
||||
<li><a href="#si-financohet-zhvillimi-i-delta-chat-it">Si financohet zhvillimi i Delta Chat-it?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -604,16 +605,16 @@ to any system involved in the delivery of Push Notifications.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>A Delta Chat app obtains a “device token” locally and stores it
|
||||
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
|
||||
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
|
||||
it forwards the “device token” to the central Delta Chat notification proxy.</p>
|
||||
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The central Delta Chat notification proxy forwards
|
||||
the “device token” to the respective Push service (Apple, Google, etc.),
|
||||
<p>The central Delta Chat notification proxy decrypts the device token
|
||||
and forwards it to the respective Push service (Apple, Google, etc.),
|
||||
without ever knowing the IP or e-mail address of Delta Chat users.</p>
|
||||
</li>
|
||||
<li>
|
||||
@@ -626,14 +627,15 @@ and also never see any message content (also not in encrypted forms).</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>As of May 2024, chatmail servers know about “device tokens”
|
||||
but we plan to encrypt this information to the notification proxy
|
||||
such that the chatmail server never learns the device token.</p>
|
||||
|
||||
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
|
||||
and forgets about device-tokens as soon as Apple/Google/etc processed them,
|
||||
usually in a matter of milliseconds.</p>
|
||||
|
||||
<p>Note that the device token is encrypted between apps and notification proxy
|
||||
but it is not signed.
|
||||
The notification proxy thus never sees e-mail addresses, IP-addresses or
|
||||
any cryptographic identity information associated with a user’s device (token).</p>
|
||||
|
||||
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
|
||||
or the full seizure of the central Delta Chat notification proxy
|
||||
would not reveal private information that Push services do not already have.</p>
|
||||
@@ -1315,6 +1317,12 @@ Njëra pajisja s’ka nevojë për tjetrën që të funksionojë.</p>
|
||||
and make sure, <strong>Private Network</strong> is selected as “Network profile type”
|
||||
(after transfer, you can change back to the original value)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>iOS</strong>, make sure “System Settings / Apps / Delta Chat / <strong>Local Network</strong>” access is granted</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On <strong>macOS</strong>, enable “System Settings / Privacy & Security / <strong>Local Network</strong> / Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Sistemi juaj mund të ketë një “firewall personal”,
|
||||
që dihet se shkakton probleme (veçanërisht në Windows).
|
||||
@@ -1890,6 +1898,35 @@ Otherwise you might receive undecryptable messages from those group chats.</p>
|
||||
<li>Shihni <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">Standarde të përdorur në Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="where-can-my-friends-find-delta-chat">
|
||||
|
||||
|
||||
Where can my friends find Delta Chat? <a href="#where-can-my-friends-find-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat is available for all major and some minor platforms:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>The <strong>official website</strong>, <a href="https://delta.chat/download">https://delta.chat/download</a> shows all options in detail</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If unavailable, use the <strong>mirror</strong> at <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, Amazon App Store, iOS and macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Check the <strong>package manager</strong> of your Linux distributions</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Android APKs</strong> are also available on <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="si-financohet-zhvillimi-i-delta-chat-it">
|
||||
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<li><a href="#чи-сумісний-delta-chat-із-protonmail--tutanota--criptext">Чи сумісний Delta Chat із Protonmail / Tutanota / Criptext?</a></li>
|
||||
<li><a href="#remove-account">Як мені видалити свій обліковий запис?</a></li>
|
||||
<li><a href="#мене-цікавлять-технічні-деталі-можете-розповісти-більше">Мене цікавлять технічні деталі. Можете розповісти більше?</a></li>
|
||||
<li><a href="#де-мої-друзі-можуть-знайти-delta-chat">Де мої друзі можуть знайти Delta Chat?</a></li>
|
||||
<li><a href="#як-фінансується-розробка-delta-chat">Як фінансується розробка Delta Chat?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -267,7 +268,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Щоб заархівувати або закріпити чат, довго торкніться (Android), скористайтеся меню чату (Android/комп’ютер) або проведіть пальцем ліворуч (iOS); щоб вимкнути звук чату, скористайтеся меню чату (Android/комп’ютер) або профілем чату (iOS).</p>
|
||||
<p>Щоб скористатися функціями, утримуйте натиснутою клавішу або клацніть правою кнопкою миші на чаті у списку чатів.</p>
|
||||
|
||||
<h3 id="що-означає-зелена-точка">
|
||||
|
||||
@@ -497,23 +498,23 @@ Push-сповіщення автоматично активуються для
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Додаток Delta Chat отримує “токен пристрою” локально і зберігає його на сервері <a href="https://delta.chat/chatmail">chatmail</a>.</p>
|
||||
<p>Додаток Delta Chat отримує “токен пристрою” локально, шифрує його і зберігає на сервері <a href="https://delta.chat/chatmail">chatmail</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Коли <a href="https://delta.chat/chatmail">chatmail</a>-сервер отримує електронний лист від користувача Delta Chat він пересилає “токен пристрою” до центрального проксі-сповіщення Delta Chat.</p>
|
||||
<p>Коли сервер <a href="https://delta.chat/chatmail">chatmail</a> отримує електронний лист від користувача Delta Chat він пересилає зашифрований токен пристрою до центрального проксі-сервера сповіщень Delta Chat.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Центральний проксі-сервер сповіщень Delta Chat пересилає “токен пристрою” до відповідного Push-сервісу (Apple, Google тощо), навіть не знаючи IP-адреси чи електронної пошти користувачів Delta Chat.</p>
|
||||
<p>Центральний проксі-сервер сповіщень Delta Chat розшифровує токен пристрою і пересилає його до відповідного Push-сервісу (Apple, Google тощо), навіть не знаючи IP-адреси або електронної пошти користувачів Delta Chat.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Центральний Push-сервіс (Apple, Google тощо) запускає додаток Delta Chat на вашому пристрої щоб перевірити наявність нових повідомлень у фоновому режимі. Він не знає про пошту чату або адресу електронної пошти пристрою, який він пробуджує. Центральні служби Apple/Google Push ніколи не бачать адресу електронної пошти (відправника або одержувача) а також ніколи не бачать жодного вмісту повідомлення (навіть в зашифрованому вигляді).</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Станом на травень 2024 року chatmail-сервери знають про “токени пристроїв” але ми плануємо зашифрувати цю інформацію для проксі-сповіщень таким чином, щоб сервер чату ніколи не дізнався токен пристрою.</p>
|
||||
|
||||
<p>Центральний проксі для сповіщень Delta Chat <a href="https://github.com/deltachat/notifiers">невеликий і повністю реалізований на Rust</a> забуває про токени пристроїв, як тільки Apple/Google/etc обробили їх, зазвичай за лічені мілісекунди.</p>
|
||||
|
||||
<p>Зверніть увагу, що токен пристрою шифрується між програмами та проксі-сповіщеннями але не підписується. Таким чином, проксі-служба сповіщень ніколи не бачить адреси електронної пошти, IP-адреси або будь-яку криптографічну ідентифікаційну інформацію, пов’язану з пристроєм користувача (токеном).</p>
|
||||
|
||||
<p>В результаті цього загального дизайну конфіденційності, навіть захоплення chatmail-сервера, або повне вилучення центрального проксі-сервера повідомлень Delta Chat не призведе до розкриття приватної інформації, якої ще не мають Push-сервіси.</p>
|
||||
|
||||
<h3 id="чому-delta-chat-інтегрується-з-централізованими-пропрієтарними-push-сервісами-applegoogle">
|
||||
@@ -944,6 +945,12 @@ Look for something like <strong>Start Autocrypt Setup Transfer</strong> in the s
|
||||
<li>
|
||||
<p>У <strong>Windows</strong> перейдіть до <strong>Панель керування / Мережа та Інтернет</strong> і переконайтеся, що <strong>Приватна мережа</strong> вибрано як “Тип мережевого профілю” (після перенесення ви можете повернути початкове значення)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>На <strong>iOS</strong> переконайтеся, що доступ до “Системні налаштування / Програми / Delta Chat / <strong>Локальна мережа</strong>” дозволено</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>У <strong>macOS</strong> увімкніть “Системні налаштування / Конфіденційність і безпека / <strong>Локальна мережа</strong> / Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Ваша система може мати “персональний брандмауер”, який, як відомо, викликає проблеми (особливо у Windows). <strong>Вимкніть персональний брандмауер</strong> для Delta Chat на обох кінцях і повторіть спробу</p>
|
||||
</li>
|
||||
@@ -1032,9 +1039,11 @@ Look for something like <strong>Start Autocrypt Setup Transfer</strong> in the s
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>Загалом, будь-хто може ділитися додатками webxdc один з одним один з одним без обмежень.</li>
|
||||
<li>Ви можете <a href="https://delta.chat/en/2023-08-11-xstore">надіслати “hi” на xstore@testrun.org</a> щоб побачити експериментальний магазин додатків webxdc. Всі програми мають відкритий вихідний код і є безкоштовними.</li>
|
||||
<li>Багато людей пишуть власні програми для webxdc і публікують їх на <a href="https://support.delta.chat/c/webxdc/20">форумі Delta Chat</a>.</li>
|
||||
<li>Загалом, будь-хто може ділитися додатками webxdc один з одним без обмежень.</li>
|
||||
<li>З <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
|
||||
<li>Ви можете <a href="https://delta.chat/en/2023-08-11-xstore">надіслати “привіт” на xstore@testrun.org</a> щоб побачити експериментальний магазин додатків webxdc.
|
||||
Всі програми мають відкритий вихідний код і є безкоштовними.</li>
|
||||
<li>Багато людей пишуть власні програми webxdc і публікують їх на <a href="https://support.delta.chat/c/webxdc/20">форумі Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="як-я-можу-створювати-власні-програми-webxdc">
|
||||
@@ -1374,6 +1383,34 @@ Look for something like <strong>Start Autocrypt Setup Transfer</strong> in the s
|
||||
<li>Дивіться <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">Стандарти, що використовуються у Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="де-мої-друзі-можуть-знайти-delta-chat">
|
||||
|
||||
|
||||
Де мої друзі можуть знайти Delta Chat? <a href="#де-мої-друзі-можуть-знайти-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat доступний для всіх основних і деяких другорядних платформ:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>На <strong>офіційному сайті</strong>, <a href="https://delta.chat/download">https://delta.chat/download</a> детально описані всі варіанти</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Якщо вона недоступна, скористайтеся <strong>дзеркалом</strong> за адресою <a href="https://deltachat.github.io/deltachat-pages">https://deltachat.github.io/deltachat-pages</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Відкрийте один з наступних <strong>магазинів додатків і введіть у пошук “Delta Chat”:</strong> Google Play Store, F-Droid, Huawei App Gallery, Amazon App Store, iOS та macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Перевірте <strong>менеджер пакунків</strong> вашого дистрибутива Linux</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>APK для Android</strong> також доступні на <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="як-фінансується-розробка-delta-chat">
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -2,16 +2,14 @@ package com.b44t.messenger;
|
||||
|
||||
public class DcContext {
|
||||
|
||||
public final static int DC_PREF_DEFAULT_MDNS_ENABLED = 1;
|
||||
public final static int DC_PREF_DEFAULT_TRIM_ENABLED = 0;
|
||||
public final static int DC_PREF_DEFAULT_TRIM_LENGTH = 500;
|
||||
|
||||
public final static int DC_EVENT_INFO = 100;
|
||||
public final static int DC_EVENT_WARNING = 300;
|
||||
public final static int DC_EVENT_ERROR = 400;
|
||||
public final static int DC_EVENT_ERROR_SELF_NOT_IN_GROUP = 410;
|
||||
public final static int DC_EVENT_MSGS_CHANGED = 2000;
|
||||
public final static int DC_EVENT_REACTIONS_CHANGED = 2001;
|
||||
public final static int DC_EVENT_INCOMING_REACTION = 2002;
|
||||
public final static int DC_EVENT_INCOMING_WEBXDC_NOTIFY = 2003;
|
||||
public final static int DC_EVENT_INCOMING_MSG = 2005;
|
||||
public final static int DC_EVENT_MSGS_NOTICED = 2008;
|
||||
public final static int DC_EVENT_MSG_DELIVERED = 2010;
|
||||
@@ -82,16 +80,13 @@ public class DcContext {
|
||||
public final static int DC_MEDIA_QUALITY_BALANCED = 0;
|
||||
public final static int DC_MEDIA_QUALITY_WORSE = 1;
|
||||
|
||||
public final static int DC_DECISION_START_CHAT = 0;
|
||||
public final static int DC_DECISION_BLOCK = 1;
|
||||
public final static int DC_DECISION_NOT_NOW = 2;
|
||||
|
||||
public final static int DC_CONNECTIVITY_NOT_CONNECTED = 1000;
|
||||
public final static int DC_CONNECTIVITY_CONNECTING = 2000;
|
||||
public final static int DC_CONNECTIVITY_WORKING = 3000;
|
||||
public final static int DC_CONNECTIVITY_CONNECTED = 4000;
|
||||
|
||||
private static final String CONFIG_ACCOUNT_ENABLED = "ui.enabled";
|
||||
private static final String CONFIG_MUTE_MENTIONS_IF_MUTED = "ui.mute_mentions_if_muted";
|
||||
|
||||
// when using DcAccounts, use DcAccounts.addAccount() instead
|
||||
public DcContext(String osName, String dbfile) {
|
||||
@@ -200,11 +195,10 @@ public class DcContext {
|
||||
public native void deleteMsgs (int msg_ids[]);
|
||||
public native void forwardMsgs (int msg_ids[], int chat_id);
|
||||
public native boolean resendMsgs (int msg_ids[]);
|
||||
public native int prepareMsg (int chat_id, DcMsg msg);
|
||||
public native int sendMsg (int chat_id, DcMsg msg);
|
||||
public native int sendTextMsg (int chat_id, String text);
|
||||
public native int sendVideochatInvitation(int chat_id);
|
||||
public native boolean sendWebxdcStatusUpdate(int msg_id, String payload, String descr);
|
||||
public native boolean sendWebxdcStatusUpdate(int msg_id, String payload);
|
||||
public native String getWebxdcStatusUpdates(int msg_id, int last_known_serial);
|
||||
public native void setWebxdcIntegration (String file);
|
||||
public native int initWebxdcIntegration(int chat_id);
|
||||
@@ -232,22 +226,12 @@ public class DcContext {
|
||||
}
|
||||
}
|
||||
|
||||
public String getNameNAddr() {
|
||||
String displayname = getConfig("displayname");
|
||||
String addr = getConfig("addr");
|
||||
String ret = "";
|
||||
public boolean isMentionsEnabled() {
|
||||
return getConfigInt(CONFIG_MUTE_MENTIONS_IF_MUTED) != 1;
|
||||
}
|
||||
|
||||
if (!displayname.isEmpty() && !addr.isEmpty()) {
|
||||
ret = String.format("%s (%s)", displayname, addr);
|
||||
} else if (!addr.isEmpty()) {
|
||||
ret = addr;
|
||||
}
|
||||
|
||||
if (ret.isEmpty() || isConfigured() == 0) {
|
||||
ret += " (not configured)";
|
||||
}
|
||||
|
||||
return ret.trim();
|
||||
public void setMentionsEnabled(boolean enabled) {
|
||||
setConfigInt(CONFIG_MUTE_MENTIONS_IF_MUTED, enabled? 0 : 1);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
||||
@@ -148,6 +148,7 @@ public class DcMsg {
|
||||
return new JSONObject();
|
||||
}
|
||||
}
|
||||
public native String getWebxdcHref ();
|
||||
public native boolean isForwarded ();
|
||||
public native boolean isInfo ();
|
||||
public native boolean isSetupMessage ();
|
||||
@@ -155,25 +156,26 @@ public class DcMsg {
|
||||
public native String getSetupCodeBegin ();
|
||||
public native String getVideochatUrl ();
|
||||
public native int getVideochatType ();
|
||||
public native boolean isIncreation ();
|
||||
public native void setText (String text);
|
||||
public native void setSubject (String text);
|
||||
public native void setHtml (String text);
|
||||
public native void setFile (String file, String filemime);
|
||||
public native void forceSticker ();
|
||||
public native void setFileAndDeduplicate(String file, String name, String filemime);
|
||||
public native void setDimension (int width, int height);
|
||||
public native void setDuration (int duration);
|
||||
public native void setLocation (float latitude, float longitude);
|
||||
public native String getPOILocation ();
|
||||
public void setQuote (DcMsg quote) { setQuoteCPtr(quote.msgCPtr); }
|
||||
public native String getQuotedText ();
|
||||
public native String getError ();
|
||||
public native String getOverrideSenderName();
|
||||
public native boolean isOutgoing();
|
||||
public native int getSenderColor();
|
||||
|
||||
public String getSenderName(DcContact dcContact, boolean markOverride) {
|
||||
public String getSenderName(DcContact dcContact) {
|
||||
String overrideName = getOverrideSenderName();
|
||||
if (overrideName != null) {
|
||||
return (markOverride ? "~" : "") + overrideName;
|
||||
return "~" + overrideName;
|
||||
} else {
|
||||
return dcContact.getDisplayName();
|
||||
}
|
||||
@@ -208,6 +210,10 @@ public class DcMsg {
|
||||
return ids;
|
||||
}
|
||||
|
||||
public boolean isOutgoing() {
|
||||
return getFromId() == DcContact.DC_CONTACT_ID_SELF;
|
||||
}
|
||||
|
||||
public String getDisplayBody() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@@ -79,23 +79,6 @@ public class Rpc {
|
||||
}
|
||||
}
|
||||
|
||||
public int addAccount() throws RpcException {
|
||||
return gson.fromJson(getResult("add_account"), int.class);
|
||||
}
|
||||
|
||||
public void startIO() throws RpcException {
|
||||
getResult("start_io_for_all_accounts");
|
||||
}
|
||||
|
||||
public void stopIO() throws RpcException {
|
||||
getResult("stop_io_for_all_accounts");
|
||||
}
|
||||
|
||||
public Map<String, String> getSystemInfo() throws RpcException {
|
||||
TypeToken<Map<String, String>> mapType = new TypeToken<Map<String, String>>(){};
|
||||
return gson.fromJson(getResult("get_system_info"), mapType.getType());
|
||||
}
|
||||
|
||||
public List<VcardContact> parseVcard(String path) throws RpcException {
|
||||
TypeToken<List<VcardContact>> listType = new TypeToken<List<VcardContact>>(){};
|
||||
return gson.fromJson(getResult("parse_vcard", path), listType.getType());
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.b44t.messenger.DcEvent;
|
||||
import com.b44t.messenger.DcEventEmitter;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
|
||||
import org.thoughtcrime.securesms.connect.AccountManager;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
@@ -37,7 +36,6 @@ import org.thoughtcrime.securesms.connect.KeepAliveService;
|
||||
import org.thoughtcrime.securesms.connect.NetworkStateReceiver;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSecret;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider;
|
||||
import org.thoughtcrime.securesms.crypto.PRNGFixes;
|
||||
import org.thoughtcrime.securesms.geolocation.DcLocationManager;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||
import org.thoughtcrime.securesms.notifications.FcmReceiveService;
|
||||
@@ -107,11 +105,6 @@ public class ApplicationContext extends MultiDexApplication {
|
||||
|
||||
Log.i("DeltaChat", "++++++++++++++++++ ApplicationContext.onCreate() ++++++++++++++++++");
|
||||
|
||||
// The first call to `getInstance` takes about 100ms-300ms, so, do it on a background thread
|
||||
Thread t = new Thread(() -> EmojiProvider.getInstance(this), "InitEmojiProviderThread");
|
||||
t.setPriority(Thread.MIN_PRIORITY);
|
||||
t.start();
|
||||
|
||||
System.loadLibrary("native-utils");
|
||||
|
||||
dcAccounts = new DcAccounts(new File(getFilesDir(), "accounts").getAbsolutePath());
|
||||
@@ -131,9 +124,6 @@ public class ApplicationContext extends MultiDexApplication {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ("deltafans@nine.testrun.org".equals(ac.getConfig("configured_addr")) && !ac.isCommunity()) {
|
||||
ac.setCommunityMode(true);
|
||||
}
|
||||
}
|
||||
if (allAccounts.length == 0) {
|
||||
dcAccounts.addAccount();
|
||||
@@ -209,7 +199,6 @@ public class ApplicationContext extends MultiDexApplication {
|
||||
|
||||
KeepAliveService.maybeStartSelf(this);
|
||||
|
||||
initializeRandomNumberFix();
|
||||
initializeLogging();
|
||||
initializeJobManager();
|
||||
InChatSounds.getInstance(this);
|
||||
@@ -240,11 +229,10 @@ public class ApplicationContext extends MultiDexApplication {
|
||||
TimeUnit.MILLISECONDS)
|
||||
.setConstraints(constraints)
|
||||
.build();
|
||||
try {
|
||||
// in Android 4 this throws exception due to R8/shrinking
|
||||
WorkManager.getInstance(this)
|
||||
.enqueueUniquePeriodicWork("FetchWorker", ExistingPeriodicWorkPolicy.KEEP, fetchWorkRequest);
|
||||
} catch (Throwable e) {}
|
||||
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
|
||||
"FetchWorker",
|
||||
ExistingPeriodicWorkPolicy.KEEP,
|
||||
fetchWorkRequest);
|
||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
|
||||
|
||||
if (Prefs.isPushEnabled(this)) {
|
||||
@@ -258,10 +246,6 @@ public class ApplicationContext extends MultiDexApplication {
|
||||
return jobManager;
|
||||
}
|
||||
|
||||
private void initializeRandomNumberFix() {
|
||||
PRNGFixes.apply();
|
||||
}
|
||||
|
||||
private void initializeLogging() {
|
||||
SignalProtocolLoggerProvider.setProvider(new AndroidSignalProtocolLogger());
|
||||
}
|
||||
|
||||
@@ -156,10 +156,6 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
||||
this.findPreference(PREFERENCE_CATEGORY_HELP)
|
||||
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_HELP));
|
||||
|
||||
if (VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
tintIcons(getActivity());
|
||||
}
|
||||
|
||||
DcHelper.getEventCenter(getActivity()).addObserver(DcContext.DC_EVENT_CONNECTIVITY_CHANGED, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,9 +33,6 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
onPreCreate();
|
||||
if (BaseActivity.isMenuWorkaroundRequired()) {
|
||||
forceOverflowMenu();
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@@ -46,20 +43,6 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
|
||||
dynamicTheme.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return (keyCode == KeyEvent.KEYCODE_MENU && BaseActivity.isMenuWorkaroundRequired()) || super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU && BaseActivity.isMenuWorkaroundRequired()) {
|
||||
openOptionsMenu();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
private void initializeScreenshotSecurity() {
|
||||
if (Prefs.isScreenSecurityEnabled(this)) {
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
public abstract class BaseActivity extends FragmentActivity {
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return (keyCode == KeyEvent.KEYCODE_MENU && isMenuWorkaroundRequired()) || super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU && isMenuWorkaroundRequired()) {
|
||||
openOptionsMenu();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
public static boolean isMenuWorkaroundRequired() {
|
||||
return VERSION.SDK_INT < VERSION_CODES.KITKAT && ("LGE".equalsIgnoreCase(Build.MANUFACTURER) || "E6710".equalsIgnoreCase(Build.DEVICE));
|
||||
}
|
||||
}
|
||||
@@ -364,9 +364,7 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
||||
|
||||
mode.setTitle("1");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
requireActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
}
|
||||
requireActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -395,11 +393,9 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
||||
actionMode = null;
|
||||
getListAdapter().initializeBatchMode(false);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
TypedArray color = requireActivity().getTheme().obtainStyledAttributes(new int[] {android.R.attr.statusBarColor});
|
||||
requireActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK));
|
||||
color.recycle();
|
||||
}
|
||||
TypedArray color = requireActivity().getTheme().obtainStyledAttributes(new int[]{android.R.attr.statusBarColor});
|
||||
requireActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK));
|
||||
color.recycle();
|
||||
|
||||
Context context = getContext();
|
||||
if (context != null) {
|
||||
|
||||
@@ -136,9 +136,7 @@ public class ContactSelectionListFragment extends Fragment
|
||||
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
|
||||
MenuInflater inflater = getActivity().getMenuInflater();
|
||||
inflater.inflate(R.menu.contact_list, menu);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
}
|
||||
getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
setCorrectMenuVisibility(menu);
|
||||
actionMode.setTitle("1");
|
||||
return true;
|
||||
@@ -170,11 +168,9 @@ public class ContactSelectionListFragment extends Fragment
|
||||
ContactSelectionListFragment.this.actionMode = null;
|
||||
getContactSelectionListAdapter().resetActionModeSelection();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
TypedArray color = getActivity().getTheme().obtainStyledAttributes(new int[] {android.R.attr.statusBarColor});
|
||||
getActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK));
|
||||
color.recycle();
|
||||
}
|
||||
TypedArray color = getActivity().getTheme().obtainStyledAttributes(new int[]{android.R.attr.statusBarColor});
|
||||
getActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK));
|
||||
color.recycle();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
@@ -53,6 +54,7 @@ import android.view.View.OnFocusChangeListener;
|
||||
import android.view.View.OnKeyListener;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
@@ -89,8 +91,6 @@ import org.thoughtcrime.securesms.components.InputPanel;
|
||||
import org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout.OnKeyboardShownListener;
|
||||
import org.thoughtcrime.securesms.components.ScaleStableImageView;
|
||||
import org.thoughtcrime.securesms.components.SendButton;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard;
|
||||
import org.thoughtcrime.securesms.connect.AccountManager;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
@@ -119,7 +119,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener;
|
||||
import org.thoughtcrime.securesms.util.guava.Optional;
|
||||
import org.thoughtcrime.securesms.util.views.Stub;
|
||||
import org.thoughtcrime.securesms.util.views.ProgressDialog;
|
||||
import org.thoughtcrime.securesms.video.recode.VideoRecoder;
|
||||
import org.thoughtcrime.securesms.videochat.VideochatUtil;
|
||||
|
||||
@@ -162,8 +162,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private static final int GROUP_EDIT = 6;
|
||||
private static final int TAKE_PHOTO = 7;
|
||||
private static final int RECORD_VIDEO = 8;
|
||||
private static final int PICK_LOCATION = 9; // TODO: i think, this can be deleted
|
||||
private static final int SMS_DEFAULT = 11; // TODO: i think, this can be deleted
|
||||
private static final int PICK_WEBXDC = 9;
|
||||
|
||||
private GlideRequests glideRequests;
|
||||
protected ComposeText composeText;
|
||||
@@ -176,11 +175,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private View composePanel;
|
||||
private ScaleStableImageView backgroundView;
|
||||
private MessageRequestsBottomView messageRequestBottomView;
|
||||
private ProgressDialog progressDialog;
|
||||
|
||||
private AttachmentTypeSelector attachmentTypeSelector;
|
||||
private AttachmentManager attachmentManager;
|
||||
private AudioRecorder audioRecorder;
|
||||
private Stub<MediaKeyboard> emojiDrawerStub;
|
||||
private FrameLayout emojiPickerContainer;
|
||||
private MediaKeyboard emojiPicker;
|
||||
protected HidingLinearLayout quickAttachmentToggle;
|
||||
private InputPanel inputPanel;
|
||||
|
||||
@@ -320,10 +321,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
super.onConfigurationChanged(newConfig);
|
||||
composeText.setTransport(sendButton.getSelectedTransport());
|
||||
|
||||
if (emojiDrawerStub.resolved() && container.getCurrentInput() == emojiDrawerStub.get()) {
|
||||
if (emojiPicker != null && container.getCurrentInput() == emojiPicker) {
|
||||
container.hideAttachedInput(true);
|
||||
}
|
||||
|
||||
emojiPicker = null; // force reloading next time onEmojiToggle() is called
|
||||
initializeBackground();
|
||||
}
|
||||
|
||||
@@ -337,8 +339,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
public void onActivityResult(final int reqCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(reqCode, resultCode, data);
|
||||
|
||||
if ((data == null && reqCode != TAKE_PHOTO && reqCode != RECORD_VIDEO && reqCode != SMS_DEFAULT) ||
|
||||
(resultCode != RESULT_OK && reqCode != SMS_DEFAULT))
|
||||
if (resultCode != RESULT_OK || (data == null && reqCode != TAKE_PHOTO && reqCode != RECORD_VIDEO))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -362,7 +363,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
for (int i = 0; i < uriCount; i++) {
|
||||
uriList.add(multipleUris.getItemAt(i).getUri());
|
||||
}
|
||||
askSendingFiles(uriList, () -> SendRelayedMessageUtil.sendMultipleMsgs(this, chatId, uriList, null));
|
||||
askSendingFiles(uriList, () -> {
|
||||
Util.runOnAnyBackgroundThread(() -> {
|
||||
SendRelayedMessageUtil.sendMultipleMsgs(this, chatId, uriList, null);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -374,6 +379,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
setMedia(data.getData(), docMediaType);
|
||||
break;
|
||||
|
||||
case PICK_WEBXDC:
|
||||
setMedia(data.getData(), MediaType.DOCUMENT);
|
||||
break;
|
||||
|
||||
case PICK_CONTACT:
|
||||
addAttachmentContactInfo(data.getIntExtra(AttachContactActivity.CONTACT_ID_EXTRA, 0));
|
||||
break;
|
||||
@@ -401,16 +410,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
break;
|
||||
|
||||
case PICK_LOCATION:
|
||||
break;
|
||||
|
||||
case ScribbleActivity.SCRIBBLE_REQUEST_CODE:
|
||||
setMedia(data.getData(), MediaType.IMAGE);
|
||||
break;
|
||||
|
||||
case SMS_DEFAULT:
|
||||
initializeSecurity(isSecureText, isDefaultSms);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -710,7 +712,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
DcMsg draft = dcContext.getDraft(chatId);
|
||||
final String sharedText = RelayUtil.getSharedText(this);
|
||||
|
||||
if (draft == null) {
|
||||
if (!draft.isOk()) {
|
||||
if (TextUtils.isEmpty(sharedText)) {
|
||||
composeText.setText("");
|
||||
future.set(false);
|
||||
@@ -737,8 +739,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
handleReplyMessage(quote);
|
||||
}
|
||||
|
||||
String filename = draft.getFile();
|
||||
if (filename.isEmpty() || !new File(filename).exists()) {
|
||||
String file = draft.getFile();
|
||||
if (file.isEmpty() || !new File(file).exists()) {
|
||||
future.set(!text.isEmpty());
|
||||
updateToggleButtonState();
|
||||
return future;
|
||||
@@ -758,26 +760,21 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
};
|
||||
|
||||
File file = new File(filename);
|
||||
Uri uri = Uri.fromFile(file);
|
||||
switch (draft.getType()) {
|
||||
case DcMsg.DC_MSG_IMAGE:
|
||||
setMedia(uri, MediaType.IMAGE).addListener(listener);
|
||||
setMedia(draft, MediaType.IMAGE).addListener(listener);
|
||||
break;
|
||||
case DcMsg.DC_MSG_GIF:
|
||||
setMedia(uri, MediaType.GIF).addListener(listener);
|
||||
setMedia(draft, MediaType.GIF).addListener(listener);
|
||||
break;
|
||||
case DcMsg.DC_MSG_AUDIO:
|
||||
setMedia(uri, MediaType.AUDIO).addListener(listener);
|
||||
setMedia(draft, MediaType.AUDIO).addListener(listener);
|
||||
break;
|
||||
case DcMsg.DC_MSG_VIDEO:
|
||||
setMedia(uri, MediaType.VIDEO).addListener(listener);
|
||||
break;
|
||||
case DcMsg.DC_MSG_WEBXDC:
|
||||
setMedia(draft, MediaType.DOCUMENT).addListener(listener);
|
||||
setMedia(draft, MediaType.VIDEO).addListener(listener);
|
||||
break;
|
||||
default:
|
||||
setMedia(uri, MediaType.DOCUMENT).addListener(listener);
|
||||
setMedia(draft, MediaType.DOCUMENT).addListener(listener);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -811,7 +808,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
sendButton = ViewUtil.findById(this, R.id.send_button);
|
||||
attachButton = ViewUtil.findById(this, R.id.attach_button);
|
||||
composeText = ViewUtil.findById(this, R.id.embedded_text_editor);
|
||||
emojiDrawerStub = ViewUtil.findStubById(this, R.id.emoji_drawer_stub);
|
||||
emojiPickerContainer = ViewUtil.findById(this, R.id.emoji_picker_container);
|
||||
composePanel = ViewUtil.findById(this, R.id.bottom_panel);
|
||||
container = ViewUtil.findById(this, R.id.layout_container);
|
||||
quickAttachmentToggle = ViewUtil.findById(this, R.id.quick_attachment_toggle);
|
||||
@@ -931,13 +928,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
case AttachmentTypeSelector.TAKE_PHOTO:
|
||||
attachmentManager.capturePhoto(this, TAKE_PHOTO); break;
|
||||
case AttachmentTypeSelector.RECORD_VIDEO:
|
||||
if(VideoRecoder.canRecode()) {
|
||||
attachmentManager.captureVideo(this, RECORD_VIDEO);
|
||||
}
|
||||
else {
|
||||
Toast.makeText(this, "This device does not support video-compression (requires Android 4.4 KitKat)", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
attachmentManager.captureVideo(this, RECORD_VIDEO);
|
||||
break;
|
||||
case AttachmentTypeSelector.ADD_WEBXDC:
|
||||
AttachmentManager.selectWebxdc(this, PICK_WEBXDC); break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -986,14 +980,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
protected static final int ACTION_SEND_OUT = 1;
|
||||
protected static final int ACTION_SAVE_DRAFT = 2;
|
||||
|
||||
private String getSelfReaction(int msgId) {
|
||||
try {
|
||||
final String [] selfReactions = rpc.getMsgReactions(dcContext.getAccountId(), msgId).getReactionsByContact().get(DcContact.DC_CONTACT_ID_SELF);
|
||||
if (selfReactions != null && selfReactions.length > 0) return selfReactions[0];
|
||||
} catch(Exception e) { e.printStackTrace(); }
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ListenableFuture<Integer> processComposeControls(int action) {
|
||||
return processComposeControls(action, composeText.getTextTrimmed(),
|
||||
attachmentManager.isAttachmentPresent() ?
|
||||
@@ -1042,7 +1028,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
msg = new DcMsg(dcContext, DcMsg.DC_MSG_FILE);
|
||||
}
|
||||
String path = attachment.getRealPath(this);
|
||||
msg.setFile(path, null);
|
||||
msg.setFileAndDeduplicate(path, attachment.getFileName(), null);
|
||||
}
|
||||
}
|
||||
msg.setText(body);
|
||||
@@ -1079,7 +1065,23 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
{
|
||||
boolean doSend = true;
|
||||
if (recompress==DcMsg.DC_MSG_VIDEO) {
|
||||
Util.runOnMain(() -> {
|
||||
progressDialog = ProgressDialog.show(
|
||||
ConversationActivity.this,
|
||||
"",
|
||||
getString(R.string.one_moment),
|
||||
true,
|
||||
false
|
||||
);
|
||||
});
|
||||
doSend = VideoRecoder.prepareVideo(ConversationActivity.this, dcChat.getId(), msg);
|
||||
Util.runOnMain(() -> {
|
||||
try {
|
||||
progressDialog.dismiss();
|
||||
} catch (final IllegalArgumentException e) {
|
||||
// The activity is finishing/destroyed, do nothing.
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (doSend) {
|
||||
@@ -1235,17 +1237,23 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
});
|
||||
}
|
||||
|
||||
private void reloadEmojiPicker() {
|
||||
emojiPickerContainer.removeAllViews();
|
||||
emojiPicker = (MediaKeyboard) LayoutInflater.from(this).inflate(R.layout.conversation_activity_emojidrawer_stub, emojiPickerContainer, false);
|
||||
emojiPickerContainer.addView(emojiPicker);
|
||||
inputPanel.setMediaKeyboard(emojiPicker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEmojiToggle() {
|
||||
if (!emojiDrawerStub.resolved()) {
|
||||
initializeMediaKeyboardProviders(emojiDrawerStub.get(), false);
|
||||
inputPanel.setMediaKeyboard(emojiDrawerStub.get());
|
||||
if (emojiPicker == null) {
|
||||
reloadEmojiPicker();
|
||||
}
|
||||
|
||||
if (container.getCurrentInput() == emojiDrawerStub.get()) {
|
||||
if (container.getCurrentInput() == emojiPicker) {
|
||||
container.showSoftkey(composeText);
|
||||
} else {
|
||||
container.show(composeText, emojiDrawerStub.get());
|
||||
container.show(composeText, emojiPicker);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1273,17 +1281,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
if (quote.isPresent()) {
|
||||
msg.setQuote(quote.get().getQuotedMsg());
|
||||
}
|
||||
msg.setFile(path, null);
|
||||
msg.setFileAndDeduplicate(path, null, null);
|
||||
msg.forceSticker();
|
||||
dcContext.sendMsg(chatId, msg);
|
||||
}
|
||||
|
||||
private void initializeMediaKeyboardProviders(@NonNull MediaKeyboard mediaKeyboard, boolean stickersAvailable) {
|
||||
boolean isSystemEmojiPreferred = Prefs.isSystemEmojiPreferred(this);
|
||||
if (!isSystemEmojiPreferred) {
|
||||
mediaKeyboard.setProviders(0, new EmojiKeyboardProvider(this, inputPanel));
|
||||
}
|
||||
}
|
||||
|
||||
// Listeners
|
||||
|
||||
private class AttachmentTypeListener implements AttachmentTypeSelector.AttachmentClickedListener {
|
||||
|
||||
@@ -24,9 +24,9 @@ import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -211,7 +211,7 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
dcContext.marknoticedChat((int) chatId);
|
||||
Util.runOnBackground(() -> dcContext.marknoticedChat((int) chatId));
|
||||
if (list.getAdapter() != null) {
|
||||
list.getAdapter().notifyDataSetChanged();
|
||||
}
|
||||
@@ -442,7 +442,7 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
|
||||
if (msg.getFromId() != prevMsg.getFromId() && !singleMsg) {
|
||||
DcContact contact = dcContext.getContact(msg.getFromId());
|
||||
result.append(msg.getSenderName(contact, false)).append(":\n");
|
||||
result.append(msg.getSenderName(contact)).append(":\n");
|
||||
}
|
||||
if (msg.getType() == DcMsg.DC_MSG_TEXT || (singleMsg && !msg.getText().isEmpty())) {
|
||||
result.append(msg.getText());
|
||||
@@ -704,7 +704,7 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
index++;
|
||||
}
|
||||
}
|
||||
dcContext.markseenMsgs(ids);
|
||||
Util.runOnAnyBackgroundThread(() -> dcContext.markseenMsgs(ids));
|
||||
}
|
||||
|
||||
|
||||
@@ -810,7 +810,10 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
DozeReminder.dozeReminderTapped(getContext());
|
||||
}
|
||||
else if(messageRecord.getInfoType() == DcMsg.DC_INFO_WEBXDC_INFO_MESSAGE) {
|
||||
scrollMaybeSmoothToMsgId(messageRecord.getParent().getId());
|
||||
WebxdcActivity.openWebxdcActivity(getContext(), messageRecord.getParent(), messageRecord.getWebxdcHref());
|
||||
}
|
||||
else if (!TextUtils.isEmpty(messageRecord.getPOILocation()) && messageRecord.getType() == DcMsg.DC_MSG_TEXT && !messageRecord.hasHtml()) {
|
||||
WebxdcActivity.openMaps(getContext(), getListAdapter().getChat().getId(), "index.html#"+messageRecord.getPOILocation());
|
||||
}
|
||||
else {
|
||||
String self_mail = dcContext.getConfig("configured_mail_user");
|
||||
@@ -911,11 +914,9 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
|
||||
mode.setTitle("1");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getActivity().getWindow();
|
||||
statusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
}
|
||||
Window window = getActivity().getWindow();
|
||||
statusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
|
||||
setCorrectMenuVisibility(menu);
|
||||
ConversationAdaptiveActionsToolbar.adjustMenuActions(menu, 10, requireActivity().getWindow().getDecorView().getMeasuredWidth());
|
||||
@@ -932,9 +933,7 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
((ConversationAdapter)list.getAdapter()).clearSelection();
|
||||
list.getAdapter().notifyDataSetChanged();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getActivity().getWindow().setStatusBarColor(statusBarColor);
|
||||
}
|
||||
getActivity().getWindow().setStatusBarColor(statusBarColor);
|
||||
|
||||
actionMode = null;
|
||||
hideAddReactionView();
|
||||
|
||||
@@ -22,12 +22,10 @@ import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.text.Spannable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
@@ -56,7 +54,6 @@ import org.thoughtcrime.securesms.components.DocumentView;
|
||||
import org.thoughtcrime.securesms.components.QuoteView;
|
||||
import org.thoughtcrime.securesms.components.VcardView;
|
||||
import org.thoughtcrime.securesms.components.WebxdcView;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.mms.AudioSlide;
|
||||
import org.thoughtcrime.securesms.mms.DocumentSlide;
|
||||
@@ -69,10 +66,10 @@ import org.thoughtcrime.securesms.mms.StickerSlide;
|
||||
import org.thoughtcrime.securesms.mms.VcardSlide;
|
||||
import org.thoughtcrime.securesms.reactions.ReactionsConversationView;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Linkifier;
|
||||
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
|
||||
import org.thoughtcrime.securesms.util.MarkdownUtil;
|
||||
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 org.thoughtcrime.securesms.util.views.Stub;
|
||||
@@ -112,6 +109,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
protected ViewGroup contactPhotoHolder;
|
||||
private ViewGroup container;
|
||||
private Button msgActionButton;
|
||||
private Button showFullButton;
|
||||
|
||||
private @NonNull Stub<ConversationItemThumbnail> mediaThumbnailStub;
|
||||
private @NonNull Stub<AudioView> audioViewStub;
|
||||
@@ -158,6 +156,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
this.container = findViewById(R.id.container);
|
||||
this.replyView = findViewById(R.id.reply_icon);
|
||||
this.msgActionButton = findViewById(R.id.msg_action_button);
|
||||
this.showFullButton = findViewById(R.id.show_full_button);
|
||||
|
||||
setOnClickListener(new ClickListener(null));
|
||||
|
||||
@@ -385,7 +384,6 @@ public class ConversationItem extends BaseConversationItem
|
||||
private void setBodyText(DcMsg messageRecord) {
|
||||
bodyText.setClickable(false);
|
||||
bodyText.setFocusable(false);
|
||||
bodyText.setTextSize(TypedValue.COMPLEX_UNIT_SP, Prefs.getMessageBodyTextSize(context));
|
||||
|
||||
String text = messageRecord.getText();
|
||||
|
||||
@@ -399,7 +397,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
else {
|
||||
Spannable spannable = (Spannable) MarkdownUtil.toMarkdown(context, text);
|
||||
if (batchSelected.isEmpty()) {
|
||||
spannable = EmojiTextView.linkify(spannable);
|
||||
spannable = Linkifier.linkify(spannable);
|
||||
}
|
||||
bodyText.setText(spannable);
|
||||
bodyText.setVisibility(View.VISIBLE);
|
||||
@@ -407,6 +405,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
|
||||
int downloadState = messageRecord.getDownloadState();
|
||||
if (downloadState == DcMsg.DC_DOWNLOAD_AVAILABLE || downloadState == DcMsg.DC_DOWNLOAD_FAILURE || downloadState == DcMsg.DC_DOWNLOAD_IN_PROGRESS) {
|
||||
showFullButton.setVisibility(View.GONE);
|
||||
msgActionButton.setVisibility(View.VISIBLE);
|
||||
if (downloadState==DcMsg.DC_DOWNLOAD_IN_PROGRESS) {
|
||||
msgActionButton.setEnabled(false);
|
||||
@@ -427,6 +426,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
}
|
||||
});
|
||||
} else if (messageRecord.getType() == DcMsg.DC_MSG_WEBXDC) {
|
||||
showFullButton.setVisibility(View.GONE);
|
||||
msgActionButton.setVisibility(View.VISIBLE);
|
||||
msgActionButton.setEnabled(true);
|
||||
msgActionButton.setText(webxdcViewStub.get().isCommunity()? R.string.join: R.string.start_app);
|
||||
@@ -439,10 +439,11 @@ public class ConversationItem extends BaseConversationItem
|
||||
});
|
||||
}
|
||||
else if (messageRecord.hasHtml()) {
|
||||
msgActionButton.setVisibility(View.VISIBLE);
|
||||
msgActionButton.setEnabled(true);
|
||||
msgActionButton.setText(R.string.show_full_message);
|
||||
msgActionButton.setOnClickListener(view -> {
|
||||
msgActionButton.setVisibility(View.GONE);
|
||||
showFullButton.setVisibility(View.VISIBLE);
|
||||
showFullButton.setEnabled(true);
|
||||
showFullButton.setText(R.string.show_full_message);
|
||||
showFullButton.setOnClickListener(view -> {
|
||||
if (eventListener != null && batchSelected.isEmpty()) {
|
||||
eventListener.onShowFullClicked(messageRecord);
|
||||
} else {
|
||||
@@ -451,6 +452,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
});
|
||||
} else {
|
||||
msgActionButton.setVisibility(View.GONE);
|
||||
showFullButton.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,9 +494,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
audioViewStub.get().setAudio(new AudioSlide(context, messageRecord), duration);
|
||||
audioViewStub.get().setOnClickListener(passthroughClickListener);
|
||||
audioViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
audioViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
audioViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -512,9 +512,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
documentViewStub.get().setDocument(new DocumentSlide(context, messageRecord));
|
||||
documentViewStub.get().setDocumentClickListener(new ThumbnailClickListener());
|
||||
documentViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
documentViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
documentViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -531,9 +529,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
webxdcViewStub.get().setWebxdc(messageRecord, context.getString(R.string.webxdc_app));
|
||||
webxdcViewStub.get().setWebxdcClickListener(new ThumbnailClickListener());
|
||||
webxdcViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
webxdcViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
webxdcViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -551,9 +547,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
vcardViewStub.get().setVcardClickListener(new ThumbnailClickListener());
|
||||
vcardViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
vcardViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
vcardViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -589,9 +583,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
mediaThumbnailStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
mediaThumbnailStub.get().setOnClickListener(passthroughClickListener);
|
||||
mediaThumbnailStub.get().showShade(TextUtils.isEmpty(messageRecord.getText()));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
mediaThumbnailStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
mediaThumbnailStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
|
||||
setThumbnailOutlineCorners(messageRecord, showSender);
|
||||
|
||||
@@ -614,9 +606,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
stickerStub.get().setThumbnailClickListener(new StickerClickListener());
|
||||
stickerStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
stickerStub.get().setOnClickListener(passthroughClickListener);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
stickerStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
stickerStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -677,7 +667,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
contactPhoto.setVisibility(View.GONE);
|
||||
} else {
|
||||
int color = messageRecord.getSenderColor();
|
||||
Recipient recipient = new Recipient(context, dcContact, messageRecord.getSenderName(dcContact, !dcContext.isCommunity()), color);
|
||||
Recipient recipient = new Recipient(context, dcContact, messageRecord.getSenderName(dcContact), color);
|
||||
contactPhoto.setAvatar(glideRequests, recipient, true);
|
||||
contactPhoto.setVisibility(View.VISIBLE);
|
||||
}
|
||||
@@ -802,14 +792,14 @@ public class ConversationItem extends BaseConversationItem
|
||||
|
||||
if (messageRecord.isForwarded()) {
|
||||
if (showSender && dcContact !=null) {
|
||||
this.groupSender.setText(context.getString(R.string.forwarded_by, messageRecord.getSenderName(dcContact, false)));
|
||||
this.groupSender.setText(context.getString(R.string.forwarded_by, messageRecord.getSenderName(dcContact)));
|
||||
} else {
|
||||
this.groupSender.setText(context.getString(R.string.forwarded_message));
|
||||
}
|
||||
this.groupSender.setTextColor(context.getResources().getColor(R.color.unknown_sender));
|
||||
}
|
||||
else if (showSender && dcContact !=null) {
|
||||
this.groupSender.setText(messageRecord.getSenderName(dcContact, true));
|
||||
this.groupSender.setText(messageRecord.getSenderName(dcContact));
|
||||
int color = messageRecord.getSenderColor();
|
||||
this.groupSender.setTextColor(Util.rgbToArgbColor(color!=0? color : dcContact.getColor()));
|
||||
}
|
||||
|
||||
@@ -174,9 +174,7 @@ class ConversationItemSwipeCallback extends ItemTouchHelper.SimpleCallback {
|
||||
vibrate(viewHolder.itemView.getContext());
|
||||
}
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
recyclerView.cancelPendingInputEvents();
|
||||
}
|
||||
recyclerView.cancelPendingInputEvents();
|
||||
}
|
||||
|
||||
private static void resetProgress(RecyclerView.ViewHolder viewHolder) {
|
||||
@@ -199,11 +197,7 @@ class ConversationItemSwipeCallback extends ItemTouchHelper.SimpleCallback {
|
||||
}
|
||||
|
||||
private static float getSignFromDirection(@NonNull View view) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -1f : 1f;
|
||||
} else {
|
||||
return 1f;
|
||||
}
|
||||
return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -1f : 1f;
|
||||
}
|
||||
|
||||
private static boolean sameSign(float dX, float sign) {
|
||||
|
||||
@@ -89,7 +89,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
public static final String CLEAR_NOTIFICATIONS = "clear_notifications";
|
||||
public static final String ACCOUNT_ID_EXTRA = "account_id";
|
||||
public static final String FROM_WELCOME = "from_welcome";
|
||||
public static final String WARN_CANNOT_ENCRYPT = "warn_cannot_encrypt";
|
||||
|
||||
private ConversationListFragment conversationListFragment;
|
||||
public TextView title;
|
||||
@@ -113,7 +112,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
// it is not needed to keep all past update messages, however, when deleted, also the strings should be deleted.
|
||||
try {
|
||||
DcContext dcContext = DcHelper.getContext(this);
|
||||
final String deviceMsgLabel = "update_1_46_0l_android";
|
||||
final String deviceMsgLabel = "update_1_50_0_android";
|
||||
if (!dcContext.wasDeviceMsgEverAdded(deviceMsgLabel)) {
|
||||
DcMsg msg = null;
|
||||
if (!getIntent().getBooleanExtra(FROM_WELCOME, false)) {
|
||||
@@ -124,7 +123,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
// Util.copy(inputStream, new FileOutputStream(outputFile));
|
||||
// msg.setFile(outputFile, "image/jpeg");
|
||||
|
||||
msg.setText(getString(R.string.update_1_46_android, "https://raw.githubusercontent.com/ArcaneChat/android/refs/heads/main/CHANGELOG.md"));
|
||||
msg.setText(getString(R.string.update_1_50_android, "https://raw.githubusercontent.com/ArcaneChat/android/refs/heads/main/CHANGELOG.md"));
|
||||
}
|
||||
dcContext.addDeviceMsg(deviceMsgLabel, msg);
|
||||
|
||||
@@ -257,6 +256,10 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
if (isFinishing()) {
|
||||
Log.w(TAG, "Activity is finishing, aborting onNewIntent()");
|
||||
return;
|
||||
}
|
||||
super.onNewIntent(intent);
|
||||
setIntent(intent);
|
||||
refresh();
|
||||
@@ -274,11 +277,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
AccountManager.getInstance().switchAccountAndStartActivity(this, accountId);
|
||||
}
|
||||
|
||||
String warnAddr = getIntent().getStringExtra(WARN_CANNOT_ENCRYPT);
|
||||
if (!TextUtils.isEmpty(warnAddr)) {
|
||||
DcHelper.showEncryptionRequiredDialog(this, warnAddr);
|
||||
}
|
||||
|
||||
refreshAvatar();
|
||||
refreshUnreadIndicator();
|
||||
refreshTitle();
|
||||
@@ -458,11 +456,8 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
case R.id.menu_all_media:
|
||||
startActivity(new Intent(this, ProfileActivity.class));
|
||||
return true;
|
||||
case R.id.menu_webxdc_apps_store:
|
||||
handleShowBot("juegos@buzon.uy", "OPENPGP4FPR:d3d403a734be71fe9293a00311fef80dbe5dbc89#a=juegos%40buzon.uy&n=&i=WQZY-8FODS3&s=ZQBkaclFzao");
|
||||
return true;
|
||||
case R.id.menu_public_bots:
|
||||
handleShowBot("puente@buzon.uy", "OPENPGP4FPR:4B41E5AFAF78A0C71DB56138D5BEFED00A45F97A#a=puente%40buzon.uy&n=Public%20Bots&i=ZC_oaJtuvJP&s=5SE96rRovsK");
|
||||
handleShowBot("botsindex@arcanechat.me", "https://i.delta.chat/#67889B0362BEDBFEE05ACD92C1D737FA632A9582&a=botsindex%40arcanechat.me&n=Public%20Bots&i=336MTEz38EH-RJxM9OKWygYK&s=TpVVGK6C4KrJmRG0bwHLalXt");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -564,7 +559,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
private void shareInvite() {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType("text/plain");
|
||||
String inviteURL = Util.QrDataToInviteURL(DcHelper.getContext(this).getSecurejoinQr(0));
|
||||
String inviteURL = DcHelper.getContext(this).getSecurejoinQr(0);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, getString(R.string.invite_friends_text, inviteURL));
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.chat_share_with_title)));
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ public class ConversationListItemInboxZero extends LinearLayout implements Binda
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public ConversationListItemInboxZero(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
@@ -31,12 +30,9 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.soundcloud.android.crop.Crop;
|
||||
|
||||
import org.thoughtcrime.securesms.components.AvatarSelector;
|
||||
import org.thoughtcrime.securesms.components.InputAwareLayout;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
|
||||
import org.thoughtcrime.securesms.mms.AttachmentManager;
|
||||
@@ -54,7 +50,7 @@ import java.security.SecureRandom;
|
||||
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public class CreateProfileActivity extends BaseActionBarActivity implements EmojiKeyboardProvider.EmojiEventListener {
|
||||
public class CreateProfileActivity extends BaseActionBarActivity {
|
||||
|
||||
private static final String TAG = CreateProfileActivity.class.getSimpleName();
|
||||
|
||||
@@ -66,7 +62,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
|
||||
private ImageView avatar;
|
||||
private EditText name;
|
||||
private EditText overridenName;
|
||||
private MediaKeyboard emojiDrawer;
|
||||
private EditText statusView;
|
||||
|
||||
private boolean fromWelcome;
|
||||
@@ -91,7 +86,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
|
||||
attachmentManager = new AttachmentManager(this, () -> {});
|
||||
avatarChanged = false;
|
||||
initializeResources();
|
||||
initializeEmojiInput();
|
||||
initializeProfileName();
|
||||
initializeProfileAvatar();
|
||||
initializeStatusText();
|
||||
@@ -130,15 +124,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
|
||||
if (container.getCurrentInput() == emojiDrawer) {
|
||||
container.hideAttachedInput(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
|
||||
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
||||
@@ -161,10 +146,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
|
||||
case ScribbleActivity.SCRIBBLE_REQUEST_CODE:
|
||||
setAvatarView(data.getData());
|
||||
break;
|
||||
|
||||
case Crop.REQUEST_CROP:
|
||||
setAvatarView(Crop.getOutput(data));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +187,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
|
||||
this.avatar = ViewUtil.findById(this, R.id.avatar);
|
||||
this.name = ViewUtil.findById(this, R.id.name_text);
|
||||
this.overridenName = ViewUtil.findById(this, R.id.overriden_name);
|
||||
this.emojiDrawer = ViewUtil.findById(this, R.id.emoji_drawer);
|
||||
this.container = ViewUtil.findById(this, R.id.container);
|
||||
this.statusView = ViewUtil.findById(this, R.id.status_text);
|
||||
|
||||
@@ -261,33 +241,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onEmojiSelected(String emoji) {
|
||||
final int start = name.getSelectionStart();
|
||||
final int end = name.getSelectionEnd();
|
||||
|
||||
name.getText().replace(Math.min(start, end), Math.max(start, end), emoji);
|
||||
name.setSelection(start + emoji.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyEvent(KeyEvent keyEvent) {
|
||||
name.dispatchKeyEvent(keyEvent);
|
||||
}
|
||||
|
||||
private void initializeMediaKeyboardProviders(@NonNull MediaKeyboard mediaKeyboard) {
|
||||
boolean isSystemEmojiPreferred = Prefs.isSystemEmojiPreferred(this);
|
||||
if (!isSystemEmojiPreferred) {
|
||||
mediaKeyboard.setProviders(0, new EmojiKeyboardProvider(this, this));
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeEmojiInput() {
|
||||
initializeMediaKeyboardProviders(emojiDrawer);
|
||||
this.name.setOnClickListener(v -> container.showSoftkey(name));
|
||||
}
|
||||
|
||||
private void initializeStatusText() {
|
||||
String status = DcHelper.get(this, DcHelper.CONFIG_SELF_STATUS);
|
||||
statusView.setText(status);
|
||||
|
||||
@@ -17,7 +17,6 @@ import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
|
||||
import com.b44t.messenger.DcChat;
|
||||
@@ -26,7 +25,6 @@ import com.b44t.messenger.DcContext;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.soundcloud.android.crop.Crop;
|
||||
|
||||
import org.thoughtcrime.securesms.components.AvatarSelector;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
@@ -221,22 +219,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
updateGroup(groupName);
|
||||
} else {
|
||||
verified = !broadcast && allMembersVerified();
|
||||
if (verified && getAdapter().getContacts().size() == 1) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setMessage(R.string.create_verified_group_ask)
|
||||
.setNeutralButton(R.string.learn_more, (d, w) -> DcHelper.openHelp(this, "#e2eeguarantee"))
|
||||
.setPositiveButton(R.string.yes, (d, w) -> {
|
||||
createGroup(groupName);
|
||||
})
|
||||
.setNegativeButton(R.string.no, (d, w) -> {
|
||||
verified = false;
|
||||
createGroup(groupName);
|
||||
})
|
||||
.setCancelable(true)
|
||||
.show();
|
||||
} else {
|
||||
createGroup(groupName);
|
||||
}
|
||||
createGroup(groupName);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -360,10 +343,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
case ScribbleActivity.SCRIBBLE_REQUEST_CODE:
|
||||
setAvatarView(data.getData());
|
||||
break;
|
||||
|
||||
case Crop.REQUEST_CROP:
|
||||
setAvatarView(Crop.getOutput(data));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@ import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.google.zxing.integration.android.IntentIntegrator;
|
||||
import com.google.zxing.integration.android.IntentResult;
|
||||
import com.soundcloud.android.crop.Crop;
|
||||
|
||||
import org.thoughtcrime.securesms.components.AvatarSelector;
|
||||
import org.thoughtcrime.securesms.connect.AccountManager;
|
||||
@@ -56,6 +55,7 @@ import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints;
|
||||
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
|
||||
import org.thoughtcrime.securesms.qr.RegistrationQrActivity;
|
||||
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
|
||||
import org.thoughtcrime.securesms.util.IntentUtils;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.views.ProgressDialog;
|
||||
@@ -71,7 +71,7 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
private static final String DCACCOUNT = "dcaccount";
|
||||
private static final String DCLOGIN = "dclogin";
|
||||
private static final String INSTANCES_URL = "https://delta.chat/chatmail";
|
||||
private static final String DEFAULT_CHATMAIL_HOST = "nine.testrun.org";
|
||||
private static final String DEFAULT_CHATMAIL_HOST = "arcanechat.me";
|
||||
|
||||
public static final String QR_ACCOUNT_EXTRA = "qr_account_extra";
|
||||
public static final String FROM_WELCOME = "from_welcome";
|
||||
@@ -191,10 +191,6 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
setAvatarView(data.getData());
|
||||
break;
|
||||
|
||||
case Crop.REQUEST_CROP:
|
||||
setAvatarView(Crop.getOutput(data));
|
||||
break;
|
||||
|
||||
case IntentIntegrator.REQUEST_CODE:
|
||||
String qrRaw = data.getStringExtra(RegistrationQrActivity.QRDATA_EXTRA);
|
||||
if (qrRaw == null) {
|
||||
@@ -246,16 +242,22 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
final String displayName = name.getText().toString();
|
||||
DcHelper.set(this, DcHelper.CONFIG_DISPLAY_NAME, TextUtils.isEmpty(displayName)? null : displayName);
|
||||
// Save display name and avatar in the unconfigured profile.
|
||||
// If the currently selected profile is configured, then this means that rollbackAccountCreation()
|
||||
// was called (see handleOnBackPressed() above), i.e. the newly created profile was removed already
|
||||
// and we can't save the display name & avatar.
|
||||
if (DcHelper.getContext(this).isConfigured() == 0) {
|
||||
final String displayName = name.getText().toString();
|
||||
DcHelper.set(this, DcHelper.CONFIG_DISPLAY_NAME, TextUtils.isEmpty(displayName) ? null : displayName);
|
||||
|
||||
if (avatarChanged) {
|
||||
try {
|
||||
AvatarHelper.setSelfAvatar(InstantOnboardingActivity.this, avatarBmp);
|
||||
Prefs.setProfileAvatarId(InstantOnboardingActivity.this, new SecureRandom().nextInt());
|
||||
avatarChanged = false;
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to save avatar", e);
|
||||
if (avatarChanged) {
|
||||
try {
|
||||
AvatarHelper.setSelfAvatar(InstantOnboardingActivity.this, avatarBmp);
|
||||
Prefs.setProfileAvatarId(InstantOnboardingActivity.this, new SecureRandom().nextInt());
|
||||
avatarChanged = false;
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to save avatar", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -327,14 +329,14 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
|
||||
privacyPolicyBtn.setOnClickListener(view -> {
|
||||
if (!isDcLogin) {
|
||||
WebViewActivity.openUrlInBrowser(this, "https://" + providerHost + "/privacy.html");
|
||||
IntentUtils.showInBrowser(this, "https://" + providerHost + "/privacy.html");
|
||||
}
|
||||
});
|
||||
|
||||
signUpBtn.setOnClickListener(view -> createProfile());
|
||||
|
||||
findViewById(R.id.use_other_server).setOnClickListener((v) -> {
|
||||
WebViewActivity.openUrlInBrowser(this, INSTANCES_URL);
|
||||
IntentUtils.showInBrowser(this, INSTANCES_URL);
|
||||
});
|
||||
findViewById(R.id.login_button).setOnClickListener((v) -> {
|
||||
startRegistrationActivity();
|
||||
|
||||
@@ -62,16 +62,16 @@ public class LocalHelpActivity extends WebViewActivity
|
||||
webView.scrollTo(0, 0);
|
||||
return true;
|
||||
case R.id.learn_more:
|
||||
openOnlineUrl("https://delta.chat");
|
||||
openOnlineUrl("https://arcanechat.me");
|
||||
return true;
|
||||
case R.id.privacy_policy:
|
||||
openOnlineUrl("https://delta.chat/gdpr");
|
||||
openOnlineUrl("https://arcanechat.me/privacy.html");
|
||||
return true;
|
||||
case R.id.contribute:
|
||||
openOnlineUrl("https://github.com/deltachat/deltachat-android");
|
||||
openOnlineUrl("https://arcanechat.me/#contribute");
|
||||
return true;
|
||||
case R.id.report_issue:
|
||||
openOnlineUrl("https://github.com/deltachat/deltachat-android/issues");
|
||||
openOnlineUrl("https://github.com/ArcaneChat/android/issues");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -197,12 +197,11 @@ public class LogViewFragment extends Fragment {
|
||||
asMegs(info.maxMemory()));
|
||||
}
|
||||
|
||||
@TargetApi(VERSION_CODES.KITKAT)
|
||||
public static String getMemoryClass(Context context) {
|
||||
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
String lowMem = "";
|
||||
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT && activityManager.isLowRamDevice()) {
|
||||
if (activityManager.isLowRamDevice()) {
|
||||
lowMem = ", low-mem device";
|
||||
}
|
||||
return activityManager.getMemoryClass() + lowMem;
|
||||
@@ -252,10 +251,8 @@ public class LogViewFragment extends Fragment {
|
||||
|
||||
Locale locale = Util.getLocale();
|
||||
builder.append("lang=").append(locale.toString()).append("\n");
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
boolean isRtl = Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL;
|
||||
builder.append("rtl=").append(isRtl).append("\n");
|
||||
}
|
||||
boolean isRtl = Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL;
|
||||
builder.append("rtl=").append(isRtl).append("\n");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
boolean notifPermGranted = PermissionChecker.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) == PermissionChecker.PERMISSION_GRANTED;
|
||||
|
||||
@@ -207,7 +207,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
messageRecord = null;
|
||||
long date = getIntent().getLongExtra(DATE_EXTRA, 0);
|
||||
long size = getIntent().getLongExtra(SIZE_EXTRA, 0);
|
||||
initialMedia = new MediaItem(null, getIntent().getData(), getIntent().getType(),
|
||||
initialMedia = new MediaItem(null, getIntent().getData(), null, getIntent().getType(),
|
||||
DcMsg.DC_MSG_NO_ID, date, size, false);
|
||||
|
||||
if (address != null) {
|
||||
@@ -218,7 +218,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
} else {
|
||||
messageRecord = dcContext.getMsg(msgId);
|
||||
initialMedia = new MediaItem(Recipient.fromChat(context, msgId), Uri.fromFile(messageRecord.getFileAsFile()),
|
||||
messageRecord.getFilemime(), messageRecord.getId(), messageRecord.getDateReceived(),
|
||||
messageRecord.getFilename(), messageRecord.getFilemime(), messageRecord.getId(), messageRecord.getDateReceived(),
|
||||
messageRecord.getFilebytes(), messageRecord.isOutgoing());
|
||||
conversationRecipient = Recipient.fromChat(context, msgId);
|
||||
}
|
||||
@@ -232,12 +232,11 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
// if you search for the place where the media are loaded, go to 'onCreateLoader'.
|
||||
|
||||
Log.w(TAG, "Loading Part URI: " + initialMedia);
|
||||
|
||||
if (messageRecord != null) {
|
||||
getSupportLoaderManager().restartLoader(0, null, this);
|
||||
} else {
|
||||
mediaPager.setAdapter(new SingleItemPagerAdapter(this, GlideApp.with(this),
|
||||
getWindow(), initialMedia.uri, initialMedia.type, initialMedia.size));
|
||||
getWindow(), initialMedia.uri, initialMedia.name, initialMedia.type, initialMedia.size));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,7 +312,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
private void performSavetoDisk(@NonNull MediaItem mediaItem) {
|
||||
SaveAttachmentTask saveTask = new SaveAttachmentTask(MediaPreviewActivity.this);
|
||||
long saveDate = (mediaItem.date > 0) ? mediaItem.date : System.currentTimeMillis();
|
||||
saveTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Attachment(mediaItem.uri, mediaItem.type, saveDate, null));
|
||||
saveTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Attachment(mediaItem.uri, mediaItem.type, saveDate, mediaItem.name));
|
||||
}
|
||||
|
||||
private void showInChat() {
|
||||
@@ -473,9 +472,12 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
MediaItemAdapter adapter = (MediaItemAdapter)mediaPager.getAdapter();
|
||||
|
||||
if (adapter != null) {
|
||||
MediaItem item = adapter.getMediaItemFor(position);
|
||||
if (item.recipient != null) item.recipient.removeListener(MediaPreviewActivity.this);
|
||||
|
||||
try {
|
||||
MediaItem item = adapter.getMediaItemFor(position);
|
||||
if (item.recipient != null) item.recipient.removeListener(MediaPreviewActivity.this);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.w(TAG, "Ignoring invalid position index");
|
||||
}
|
||||
adapter.pause(position);
|
||||
}
|
||||
}
|
||||
@@ -486,18 +488,20 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
private final GlideRequests glideRequests;
|
||||
private final Window window;
|
||||
private final Uri uri;
|
||||
private final String name;
|
||||
private final String mediaType;
|
||||
private final long size;
|
||||
|
||||
private final LayoutInflater inflater;
|
||||
|
||||
SingleItemPagerAdapter(@NonNull Context context, @NonNull GlideRequests glideRequests,
|
||||
@NonNull Window window, @NonNull Uri uri, @NonNull String mediaType,
|
||||
@NonNull Window window, @NonNull Uri uri, @Nullable String name, @NonNull String mediaType,
|
||||
long size)
|
||||
{
|
||||
this.glideRequests = glideRequests;
|
||||
this.window = window;
|
||||
this.uri = uri;
|
||||
this.name = name;
|
||||
this.mediaType = mediaType;
|
||||
this.size = size;
|
||||
this.inflater = LayoutInflater.from(context);
|
||||
@@ -519,7 +523,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
MediaView mediaView = itemView.findViewById(R.id.media_view);
|
||||
|
||||
try {
|
||||
mediaView.set(glideRequests, window, uri, mediaType, size, true);
|
||||
mediaView.set(glideRequests, window, uri, name, mediaType, size, true);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
@@ -539,7 +543,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Override
|
||||
public MediaItem getMediaItemFor(int position) {
|
||||
return new MediaItem(null, uri, mediaType, DcMsg.DC_MSG_NO_ID, -1, -1, true);
|
||||
return new MediaItem(null, uri, name, mediaType, DcMsg.DC_MSG_NO_ID, -1, -1, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -604,7 +608,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
try {
|
||||
//noinspection ConstantConditions
|
||||
mediaView.set(glideRequests, window, Uri.fromFile(msg.getFileAsFile()),
|
||||
mediaView.set(glideRequests, window, Uri.fromFile(msg.getFileAsFile()), msg.getFilename(),
|
||||
msg.getFilemime(), msg.getFilebytes(), autoplay);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
@@ -633,6 +637,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
return new MediaItem(Recipient.fromChat(context, msg.getId()),
|
||||
Uri.fromFile(msg.getFileAsFile()),
|
||||
msg.getFilename(),
|
||||
msg.getFilemime(),
|
||||
msg.getId(),
|
||||
msg.getDateReceived(),
|
||||
@@ -655,6 +660,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
private static class MediaItem {
|
||||
private final @Nullable Recipient recipient;
|
||||
private final @NonNull Uri uri;
|
||||
private final @Nullable String name;
|
||||
private final @NonNull String type;
|
||||
private final int msgId;
|
||||
private final long date;
|
||||
@@ -663,6 +669,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
private MediaItem(@Nullable Recipient recipient,
|
||||
@NonNull Uri uri,
|
||||
@Nullable String name,
|
||||
@NonNull String type,
|
||||
int msgId,
|
||||
long date,
|
||||
@@ -671,6 +678,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
{
|
||||
this.recipient = recipient;
|
||||
this.uri = uri;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.msgId = msgId;
|
||||
this.date = date;
|
||||
|
||||
@@ -111,8 +111,6 @@ public class NewConversationActivity extends ContactSelectionActivity {
|
||||
int contactId = dcContext.lookupContactIdByAddr(addr);
|
||||
if (contactId!=0 && dcContext.getChatIdByContactId(contactId)!=0) {
|
||||
openConversation(dcContext.getChatIdByContactId(contactId));
|
||||
} else if (contactId == 0 && dcContext.isChatmail()) {
|
||||
DcHelper.showEncryptionRequiredDialog(this, addr);
|
||||
} else {
|
||||
String nameNAddr = contactId == 0 ? addr : dcContext.getContact(contactId).getNameNAddr();
|
||||
new AlertDialog.Builder(this)
|
||||
|
||||
@@ -122,7 +122,13 @@ public class ProfileDocumentsFragment
|
||||
|
||||
noMedia.setVisibility(recyclerView.getAdapter().getItemCount() > 0 ? View.GONE : View.VISIBLE);
|
||||
if (chatId == DC_CHAT_NO_CHAT) {
|
||||
noMedia.setText(R.string.tab_all_media_empty_hint);
|
||||
if (showWebxdc) {
|
||||
noMedia.setText(R.string.all_apps_empty_hint);
|
||||
} else if (!showAudio){
|
||||
noMedia.setText(R.string.all_files_empty_hint);
|
||||
} else {
|
||||
noMedia.setText(R.string.tab_all_media_empty_hint);
|
||||
}
|
||||
} else if (showAudio) {
|
||||
noMedia.setText(R.string.tab_audio_empty_hint);
|
||||
} else if (showWebxdc) {
|
||||
@@ -229,11 +235,9 @@ public class ProfileDocumentsFragment
|
||||
mode.getMenuInflater().inflate(R.menu.profile_context, menu);
|
||||
mode.setTitle("1");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
}
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
setCorrectMenuVisibility(menu);
|
||||
return true;
|
||||
}
|
||||
@@ -283,9 +287,7 @@ public class ProfileDocumentsFragment
|
||||
actionMode = null;
|
||||
getListAdapter().clearSelection();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,11 +219,9 @@ public class ProfileGalleryFragment
|
||||
mode.getMenuInflater().inflate(R.menu.profile_context, menu);
|
||||
mode.setTitle("1");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
}
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
setCorrectMenuVisibility(menu);
|
||||
return true;
|
||||
}
|
||||
@@ -269,9 +267,7 @@ public class ProfileGalleryFragment
|
||||
actionMode = null;
|
||||
getListAdapter().clearSelection();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,11 +268,9 @@ public class ProfileSettingsFragment extends Fragment
|
||||
menu.findItem(R.id.menu_select_all).setVisible(false);
|
||||
mode.setTitle("1");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
}
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -314,9 +312,7 @@ public class ProfileSettingsFragment extends Fragment
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
actionMode = null;
|
||||
adapter.clearSelection();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,14 @@ import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
|
||||
import org.thoughtcrime.securesms.util.Linkifier;
|
||||
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
|
||||
|
||||
public class ProfileStatusItem extends LinearLayout {
|
||||
|
||||
private EmojiTextView statusTextView;
|
||||
private AppCompatTextView statusTextView;
|
||||
private final PassthroughClickListener passthroughClickListener = new PassthroughClickListener();
|
||||
|
||||
public ProfileStatusItem(Context context) {
|
||||
@@ -32,7 +34,7 @@ public class ProfileStatusItem extends LinearLayout {
|
||||
}
|
||||
|
||||
public void set(String status) {
|
||||
statusTextView.setText(EmojiTextView.linkify(new SpannableString(status)));
|
||||
statusTextView.setText(Linkifier.linkify(new SpannableString(status)));
|
||||
}
|
||||
|
||||
private class PassthroughClickListener implements View.OnLongClickListener, View.OnClickListener {
|
||||
|
||||
@@ -16,7 +16,6 @@ import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_ENABLED;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.getContext;
|
||||
import static org.thoughtcrime.securesms.service.IPCAddAccountsService.ACCOUNT_DATA;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
@@ -31,7 +30,6 @@ import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
@@ -59,6 +57,7 @@ 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;
|
||||
import org.thoughtcrime.securesms.util.views.ProgressDialog;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -185,7 +184,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
expandAdvanced = expandAdvanced || !TextUtils.isEmpty(strVal);
|
||||
|
||||
intVal = DcHelper.getInt(this, CONFIG_MAIL_SECURITY);
|
||||
imapSecurity.setSelection(intVal);
|
||||
imapSecurity.setSelection(ViewUtil.checkBounds(intVal, imapSecurity));
|
||||
expandAdvanced = expandAdvanced || intVal != 0;
|
||||
|
||||
TextInputEditText smtpLoginInput = findViewById(R.id.smtp_login_text);
|
||||
@@ -207,7 +206,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
expandAdvanced = expandAdvanced || !TextUtils.isEmpty(strVal);
|
||||
|
||||
intVal = DcHelper.getInt(this, CONFIG_SEND_SECURITY);
|
||||
smtpSecurity.setSelection(intVal);
|
||||
smtpSecurity.setSelection(ViewUtil.checkBounds(intVal, smtpSecurity));
|
||||
expandAdvanced = expandAdvanced || intVal != 0;
|
||||
|
||||
int serverFlags = DcHelper.getInt(this, CONFIG_SERVER_FLAGS);
|
||||
@@ -222,12 +221,15 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
}
|
||||
// /remove gmail oauth2
|
||||
}
|
||||
authMethod.setSelection(sel);
|
||||
authMethod.setSelection(ViewUtil.checkBounds(sel, authMethod));
|
||||
expandAdvanced = expandAdvanced || sel != 0;
|
||||
|
||||
int certCheckFlags = DcHelper.getInt(this, "imap_certificate_checks");
|
||||
certCheck.setSelection(certCheckFlags);
|
||||
expandAdvanced = expandAdvanced || certCheckFlags != 0;
|
||||
int imapCertificateChecks = DcHelper.getInt(this, "imap_certificate_checks");
|
||||
if (imapCertificateChecks == 3) {
|
||||
imapCertificateChecks = 2; // 3 is a deprecated alias for 2
|
||||
}
|
||||
certCheck.setSelection(ViewUtil.checkBounds(imapCertificateChecks, certCheck));
|
||||
expandAdvanced = expandAdvanced || imapCertificateChecks != 0;
|
||||
} else if (getIntent() != null && getIntent().getBundleExtra(ACCOUNT_DATA) != null) {
|
||||
// Companion app might have sent account data
|
||||
Bundle b = getIntent().getBundleExtra(ACCOUNT_DATA);
|
||||
@@ -435,7 +437,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
.setPositiveButton(R.string.perm_continue, (dialog, which)-> {
|
||||
// pass control to browser, we'll be back in business at (**)
|
||||
activity.oauth2Requested = System.currentTimeMillis();
|
||||
IntentUtils.showBrowserIntent(activity, oauth2url);
|
||||
IntentUtils.showInBrowser(activity, oauth2url);
|
||||
oauth2started.set(true);
|
||||
})
|
||||
.setCancelable(false)
|
||||
@@ -490,11 +492,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
if (provider!=null) {
|
||||
String url = provider.getOverviewPage();
|
||||
if(!url.isEmpty()) {
|
||||
try {
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(this, R.string.no_browser_installed, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
IntentUtils.showInBrowser(this, url);
|
||||
} else {
|
||||
// this should normally not happen
|
||||
Toast.makeText(this, "ErrProviderWithoutUrl", Toast.LENGTH_LONG).show();
|
||||
|
||||
@@ -58,6 +58,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
|
||||
{
|
||||
private static final String TAG = ShareActivity.class.getSimpleName();
|
||||
|
||||
public static final String EXTRA_ACC_ID = "acc_id";
|
||||
public static final String EXTRA_CHAT_ID = "chat_id";
|
||||
public static final String EXTRA_MSG_TYPE = "msg_type";
|
||||
public static final String EXTRA_MSG_SUBJECT = "msg_subject";
|
||||
@@ -213,14 +214,10 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
|
||||
}
|
||||
|
||||
private void handleResolvedMedia(Intent intent) {
|
||||
int accId = intent.getIntExtra(EXTRA_ACC_ID, -1);
|
||||
int chatId = intent.getIntExtra(EXTRA_CHAT_ID, -1);
|
||||
String msgType = intent.getStringExtra(EXTRA_MSG_TYPE);
|
||||
|
||||
String shortcutId = intent.getStringExtra(ShortcutManagerCompat.EXTRA_SHORTCUT_ID);
|
||||
if (chatId == -1 && shortcutId != null) {
|
||||
chatId = Integer.parseInt(shortcutId);
|
||||
}
|
||||
|
||||
String[] extraEmail = getIntent().getStringArrayExtra(Intent.EXTRA_EMAIL);
|
||||
/*
|
||||
usually, external app will try to start "e-mail sharing" intent, providing it:
|
||||
@@ -259,28 +256,21 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
|
||||
}
|
||||
*/
|
||||
|
||||
String addr = null;
|
||||
if(chatId == -1 && extraEmail != null && extraEmail.length > 0) {
|
||||
addr = extraEmail[0];
|
||||
final String addr = extraEmail[0];
|
||||
int contactId = dcContext.lookupContactIdByAddr(addr);
|
||||
|
||||
if(contactId != 0 || !dcContext.isChatmail()) {
|
||||
if(contactId == 0) {
|
||||
contactId = dcContext.createContact(null, addr);
|
||||
}
|
||||
|
||||
chatId = dcContext.createChatByContactId(contactId);
|
||||
addr = null;
|
||||
if(contactId == 0) {
|
||||
contactId = dcContext.createContact(null, addr);
|
||||
}
|
||||
|
||||
chatId = dcContext.createChatByContactId(contactId);
|
||||
}
|
||||
Intent composeIntent;
|
||||
if (addr != null) {
|
||||
composeIntent = new Intent(this, ConversationListActivity.class);
|
||||
composeIntent.putExtra(ConversationListActivity.WARN_CANNOT_ENCRYPT, addr);
|
||||
startActivity(composeIntent);
|
||||
} else if (chatId != -1) {
|
||||
if (accId != -1 && chatId != -1) {
|
||||
composeIntent = getBaseShareIntent(ConversationActivity.class);
|
||||
composeIntent.putExtra(ConversationActivity.CHAT_ID_EXTRA, chatId);
|
||||
composeIntent.putExtra(ConversationActivity.ACCOUNT_ID_EXTRA, accId);
|
||||
RelayUtil.setSharedType(composeIntent, msgType);
|
||||
RelayUtil.setSharedUris(composeIntent, resolvedExtras);
|
||||
startActivity(composeIntent);
|
||||
|
||||
@@ -26,6 +26,7 @@ import androidx.webkit.ProxyController;
|
||||
import androidx.webkit.ProxyConfig;
|
||||
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.IntentUtils;
|
||||
|
||||
public class WebViewActivity extends PassphraseRequiredActionBarActivity
|
||||
implements SearchView.OnQueryTextListener,
|
||||
@@ -278,16 +279,8 @@ public class WebViewActivity extends PassphraseRequiredActionBarActivity
|
||||
// onBackPressed() can be overwritten by derived classes as needed.
|
||||
// the default behavior (close the activity) is just fine eg. for Webxdc, Connectivity, HTML-mails
|
||||
|
||||
public static void openUrlInBrowser(Context context, String url) {
|
||||
try {
|
||||
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(context, R.string.no_browser_installed, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean openOnlineUrl(String url) {
|
||||
openUrlInBrowser(this, url);
|
||||
IntentUtils.showInBrowser(this, url);
|
||||
// returning `true` causes the WebView to abort loading
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
@@ -40,11 +39,13 @@ import com.b44t.messenger.DcEvent;
|
||||
import com.b44t.messenger.DcMsg;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
import com.google.common.base.Charsets;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.thoughtcrime.securesms.connect.AccountManager;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.util.IntentUtils;
|
||||
import org.thoughtcrime.securesms.util.JsonUtils;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
@@ -54,6 +55,8 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -63,7 +66,9 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
private static final String EXTRA_ACCOUNT_ID = "accountId";
|
||||
private static final String EXTRA_APP_MSG_ID = "appMessageId";
|
||||
private static final String EXTRA_HIDE_ACTION_BAR = "hideActionBar";
|
||||
private static final String EXTRA_HREF = "href";
|
||||
private static final int REQUEST_CODE_FILE_PICKER = 51426;
|
||||
private static long lastOpenTime = 0;
|
||||
|
||||
private ValueCallback<Uri[]> filePathCallback;
|
||||
private DcContext dcContext;
|
||||
@@ -71,12 +76,23 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
private DcMsg dcAppMsg;
|
||||
private String baseURL;
|
||||
private String sourceCodeUrl = "";
|
||||
private String selfAddr;
|
||||
private int sendUpdateMaxSize;
|
||||
private int sendUpdateInterval;
|
||||
private boolean internetAccess = false;
|
||||
private boolean hideActionBar = false;
|
||||
|
||||
public static void openMaps(Context context, int chatId) {
|
||||
openMaps(context, chatId, "");
|
||||
}
|
||||
|
||||
public static void openMaps(Context context, int chatId, String href) {
|
||||
DcContext dcContext = DcHelper.getContext(context);
|
||||
int msgId = dcContext.initWebxdcIntegration(chatId);
|
||||
int msgId = 0;
|
||||
final int mapsVersion = 2;
|
||||
if (dcContext.getConfigInt("ui.maps_version") >= mapsVersion) {
|
||||
msgId = dcContext.initWebxdcIntegration(chatId);
|
||||
}
|
||||
if (msgId == 0) {
|
||||
try {
|
||||
InputStream inputStream = context.getResources().getAssets().open("webxdc/maps.xdc");
|
||||
@@ -91,34 +107,36 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
Toast.makeText(context, "Cannot get maps.xdc, see log for details.", Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
dcContext.setConfigInt("ui.maps_version", mapsVersion);
|
||||
}
|
||||
openWebxdcActivity(context, msgId, true);
|
||||
openWebxdcActivity(context, msgId, true, href);
|
||||
}
|
||||
|
||||
public static void openWebxdcActivity(Context context, DcMsg instance) {
|
||||
openWebxdcActivity(context, instance.getId(), false);
|
||||
openWebxdcActivity(context, instance, "");
|
||||
}
|
||||
|
||||
public static void openWebxdcActivity(Context context, int msgId, boolean hideActionBar) {
|
||||
public static void openWebxdcActivity(Context context, DcMsg instance, String href) {
|
||||
openWebxdcActivity(context, instance.getId(), false, href);
|
||||
}
|
||||
|
||||
public static void openWebxdcActivity(Context context, int msgId, boolean hideActionBar, String href) {
|
||||
if (!Util.isClickedRecently()) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (Prefs.isDeveloperModeEnabled(context)) {
|
||||
WebView.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
context.startActivity(getWebxdcIntent(context, msgId, hideActionBar));
|
||||
} else {
|
||||
Toast.makeText(context, "At least Android 5.0 (Lollipop) required for Webxdc.", Toast.LENGTH_LONG).show();
|
||||
if (Prefs.isDeveloperModeEnabled(context)) {
|
||||
WebView.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
context.startActivity(getWebxdcIntent(context, msgId, hideActionBar, href));
|
||||
}
|
||||
}
|
||||
|
||||
private static Intent getWebxdcIntent(Context context, int msgId, boolean hideActionBar) {
|
||||
private static Intent getWebxdcIntent(Context context, int msgId, boolean hideActionBar, String href) {
|
||||
DcContext dcContext = DcHelper.getContext(context);
|
||||
Intent intent = new Intent(context, WebxdcActivity.class);
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.putExtra(EXTRA_ACCOUNT_ID, dcContext.getAccountId());
|
||||
intent.putExtra(EXTRA_APP_MSG_ID, msgId);
|
||||
intent.putExtra(EXTRA_HIDE_ACTION_BAR, hideActionBar);
|
||||
intent.putExtra(EXTRA_HREF, href);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@@ -129,7 +147,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
.putExtra(ConversationActivity.CHAT_ID_EXTRA, dcContext.getMsg(msgId).getChatId())
|
||||
.setAction(Intent.ACTION_VIEW);
|
||||
|
||||
final Intent webxdcIntent = getWebxdcIntent(context, msgId, false);
|
||||
final Intent webxdcIntent = getWebxdcIntent(context, msgId, false, "");
|
||||
|
||||
return TaskStackBuilder.create(context)
|
||||
.addNextIntentWithParentStack(chatIntent)
|
||||
@@ -197,6 +215,9 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
// this is needed here because if the app is opened while already in landscape mode, onConfigurationChanged() is not triggered
|
||||
setScreenMode(getResources().getConfiguration());
|
||||
}
|
||||
selfAddr = info.optString("self_addr");
|
||||
sendUpdateMaxSize = info.optInt("send_update_max_size");
|
||||
sendUpdateInterval = info.optInt("send_update_interval");
|
||||
|
||||
toggleFakeProxy(!internetAccess);
|
||||
|
||||
@@ -213,7 +234,20 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
webView.setNetworkAvailable(internetAccess); // this does not block network but sets `window.navigator.isOnline` in js land
|
||||
webView.addJavascriptInterface(new InternalJSApi(), "InternalJSApi");
|
||||
|
||||
webView.loadUrl(this.baseURL + "/index.html");
|
||||
String extraHref = b.getString(EXTRA_HREF, "");
|
||||
if (TextUtils.isEmpty(extraHref)) {
|
||||
extraHref = "index.html";
|
||||
}
|
||||
|
||||
String href = baseURL + "/" + extraHref;
|
||||
String encodedHref = "";
|
||||
try {
|
||||
encodedHref = URLEncoder.encode(href, Charsets.UTF_8.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
webView.loadUrl(this.baseURL + "/webxdc_bootstrap324567869.html?i=1&href=" + encodedHref);
|
||||
|
||||
Util.runOnAnyBackgroundThread(() -> {
|
||||
final DcChat chat = dcContext.getChat(dcAppMsg.getChatId());
|
||||
@@ -223,8 +257,21 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
DcHelper.getNotificationCenter(this).updateVisibleWebxdc(dcContext.getAccountId(), dcAppMsg.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
DcHelper.getNotificationCenter(this).clearVisibleWebxdc();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
lastOpenTime = System.currentTimeMillis();
|
||||
DcHelper.getEventCenter(this.getApplicationContext()).removeObservers(this);
|
||||
leaveRealtimeChannel();
|
||||
super.onDestroy();
|
||||
@@ -247,7 +294,10 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
addToHomeScreen(this, dcAppMsg.getId());
|
||||
return true;
|
||||
case R.id.source_code:
|
||||
openUrlInBrowser(this, sourceCodeUrl);
|
||||
IntentUtils.showInBrowser(this, sourceCodeUrl);
|
||||
return true;
|
||||
case R.id.show_in_chat:
|
||||
showInChat();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -334,7 +384,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
res = new WebResourceResponse("text/plain", "UTF-8", targetStream);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !internetAccess) {
|
||||
if (!internetAccess) {
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Content-Security-Policy",
|
||||
"default-src 'self'; "
|
||||
@@ -353,9 +403,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
}
|
||||
|
||||
private void callJavaScriptFunction(String func) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
webView.evaluateJavascript("window." + func + ";", null);
|
||||
}
|
||||
webView.evaluateJavascript("document.getElementById('frame').contentWindow." + func + ";", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -394,6 +442,13 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
}
|
||||
}
|
||||
|
||||
private void showInChat() {
|
||||
Intent intent = new Intent(this, ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.CHAT_ID_EXTRA, dcAppMsg.getChatId());
|
||||
intent.putExtra(ConversationActivity.STARTING_POSITION_EXTRA, DcMsg.getMessagePosition(dcAppMsg, dcContext));
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
public static void addToHomeScreen(Activity activity, int msgId) {
|
||||
Context context = activity.getApplicationContext();
|
||||
try {
|
||||
@@ -469,13 +524,23 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
return dcContext.isCommunity();
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public int sendUpdateMaxSize() {
|
||||
return WebxdcActivity.this.sendUpdateMaxSize;
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public int sendUpdateInterval() {
|
||||
return WebxdcActivity.this.sendUpdateInterval;
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public String selfAddr() {
|
||||
if (dcContext.isCommunity() && !TextUtils.isEmpty(dcContext.getCommunityUser())) {
|
||||
int flags = Base64.NO_WRAP | Base64.NO_PADDING | Base64.URL_SAFE;
|
||||
return Base64.encodeToString(dcContext.getCommunityUser().getBytes(), flags);
|
||||
}
|
||||
return dcContext.getConfig("configured_addr");
|
||||
return WebxdcActivity.this.selfAddr;
|
||||
}
|
||||
|
||||
/** @noinspection unused*/
|
||||
@@ -493,9 +558,9 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
|
||||
/** @noinspection unused*/
|
||||
@JavascriptInterface
|
||||
public boolean sendStatusUpdate(String payload, String descr) {
|
||||
public boolean sendStatusUpdate(String payload) {
|
||||
Log.i(TAG, "sendStatusUpdate");
|
||||
if (!WebxdcActivity.this.dcContext.sendWebxdcStatusUpdate(WebxdcActivity.this.dcAppMsg.getId(), payload, descr)) {
|
||||
if (!WebxdcActivity.this.dcContext.sendWebxdcStatusUpdate(WebxdcActivity.this.dcAppMsg.getId(), payload)) {
|
||||
DcChat dcChat = WebxdcActivity.this.dcContext.getChat(WebxdcActivity.this.dcAppMsg.getChatId());
|
||||
Toast.makeText(WebxdcActivity.this,
|
||||
dcChat.isContactRequest() ?
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.rpc.HttpResponse;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
|
||||
import org.thoughtcrime.securesms.util.IntentUtils;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class WebxdcStoreActivity extends PassphraseRequiredActionBarActivity {
|
||||
private static final String TAG = WebxdcStoreActivity.class.getSimpleName();
|
||||
|
||||
private DcContext dcContext;
|
||||
private Rpc rpc;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle state, boolean ready) {
|
||||
setContentView(R.layout.web_view_activity);
|
||||
rpc = DcHelper.getRpc(this);
|
||||
dcContext = DcHelper.getContext(this);
|
||||
WebView webView = findViewById(R.id.webview);
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setTitle(R.string.webxdc_apps);
|
||||
}
|
||||
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
String ext = MediaUtil.getFileExtensionFromUrl(Uri.parse(url).getPath());
|
||||
if ("xdc".equals(ext)) {
|
||||
Util.runOnAnyBackgroundThread(() -> {
|
||||
try {
|
||||
HttpResponse httpResponse = rpc.getHttpResponse(dcContext.getAccountId(), url);
|
||||
Uri uri = PersistentBlobProvider.getInstance().create(WebxdcStoreActivity.this, httpResponse.getBlob(), "application/octet-stream", "app.xdc");
|
||||
Intent intent = new Intent();
|
||||
intent.setData(uri);
|
||||
setResult(Activity.RESULT_OK, intent);
|
||||
finish();
|
||||
} catch (RpcException e) {
|
||||
e.printStackTrace();
|
||||
Util.runOnMain(() -> Toast.makeText(WebxdcStoreActivity.this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
IntentUtils.showInBrowser(WebxdcStoreActivity.this, url);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
return shouldOverrideUrlLoading(view, request.getUrl().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
||||
return interceptRequest(request.getUrl().toString());
|
||||
}
|
||||
});
|
||||
|
||||
WebSettings webSettings = webView.getSettings();
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccess(false);
|
||||
webSettings.setAllowContentAccess(false);
|
||||
webSettings.setGeolocationEnabled(false);
|
||||
webSettings.setAllowFileAccessFromFileURLs(false);
|
||||
webSettings.setAllowUniversalAccessFromFileURLs(false);
|
||||
webSettings.setDatabaseEnabled(true);
|
||||
webSettings.setDomStorageEnabled(true);
|
||||
webView.setNetworkAvailable(true); // this does not block network but sets `window.navigator.isOnline` in js land
|
||||
|
||||
webView.loadUrl(Prefs.getWebxdcStoreUrl(this));
|
||||
}
|
||||
|
||||
private WebResourceResponse interceptRequest(String url) {
|
||||
WebResourceResponse res = null;
|
||||
try {
|
||||
if (url == null) {
|
||||
throw new Exception("no url specified");
|
||||
}
|
||||
HttpResponse httpResponse = rpc.getHttpResponse(dcContext.getAccountId(), url);
|
||||
String mimeType = httpResponse.getMimetype();
|
||||
if (mimeType == null) {
|
||||
mimeType = "application/octet-stream";
|
||||
}
|
||||
|
||||
ByteArrayInputStream data = new ByteArrayInputStream(httpResponse.getBlob());
|
||||
res = new WebResourceResponse(mimeType, httpResponse.getEncoding(), data);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ByteArrayInputStream data = new ByteArrayInputStream(("Could not load apps. Are you online?\n\n" + e.getMessage()).getBytes());
|
||||
res = new WebResourceResponse("text/plain", "UTF-8", data);
|
||||
}
|
||||
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
headers.put("access-control-allow-origin", "*");
|
||||
res.setResponseHeaders(headers);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
super.onOptionsItemSelected(item);
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -93,7 +93,7 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
|
||||
boolean canGoBack = AccountManager.getInstance().canRollbackAccountCreation(this);
|
||||
supportActionBar.setDisplayHomeAsUpEnabled(canGoBack);
|
||||
getSupportActionBar().setTitle(canGoBack? R.string.add_account : R.string.welcome_desktop);
|
||||
getSupportActionBar().setTitle(canGoBack? R.string.add_account : R.string.app_name);
|
||||
}
|
||||
|
||||
private void registerForEvents() {
|
||||
@@ -166,7 +166,7 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
.withPermanentDenialDialog(getString(R.string.perm_explain_access_to_storage_denied))
|
||||
.onAllGranted(() -> {
|
||||
File imexDir = DcHelper.getImexDir();
|
||||
if (Build.VERSION.SDK_INT >= 30) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
AttachmentManager.selectMediaType(this, "application/x-tar", null, PICK_BACKUP, StorageUtil.getDownloadUri());
|
||||
} else {
|
||||
final String backupFile = dcContext.imexHasBackup(imexDir.getAbsolutePath());
|
||||
|
||||
+10
-5
@@ -189,11 +189,16 @@ public class AccountSelectionListFragment extends DialogFragment implements DcEv
|
||||
avatar.setAvatar(GlideApp.with(activity), recipient, false);
|
||||
nameView.setText(name);
|
||||
addrView.setText(contact.getAddr());
|
||||
try {
|
||||
sizeView.setText(Util.getPrettyFileSize(rpc.getAccountFileSize(accountId)));
|
||||
} catch (RpcException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Util.runOnAnyBackgroundThread(() -> {
|
||||
try {
|
||||
final int sizeBytes = rpc.getAccountFileSize(accountId);
|
||||
Util.runOnMain(() -> {
|
||||
sizeView.setText(Util.getPrettyFileSize(sizeBytes));
|
||||
});
|
||||
} catch (RpcException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
description.setText(activity.getString(R.string.delete_account_explain_with_name, name));
|
||||
|
||||
AlertDialog dialog = new AlertDialog.Builder(activity)
|
||||
|
||||
@@ -48,7 +48,7 @@ public class AudioRecorder {
|
||||
ParcelFileDescriptor fds[] = ParcelFileDescriptor.createPipe();
|
||||
|
||||
captureUri = blobProvider.create(context, new ParcelFileDescriptor.AutoCloseInputStream(fds[0]),
|
||||
MediaUtil.AUDIO_AAC, null, null);
|
||||
MediaUtil.AUDIO_AAC, "voice.aac", null);
|
||||
audioCodec = new AudioCodec(context);
|
||||
|
||||
audioCodec.start(new ParcelFileDescriptor.AutoCloseOutputStream(fds[1]));
|
||||
|
||||
@@ -87,11 +87,14 @@ public class AudioSlidePlayer {
|
||||
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
||||
if (playbackState == Player.STATE_READY) {
|
||||
Util.runOnMain(() -> {
|
||||
Log.d(TAG, "request duration " + durationCalculator.getDuration());
|
||||
getListener().onReceivedDuration(Long.valueOf(durationCalculator.getDuration()).intValue());
|
||||
durationCalculator.release();
|
||||
durationCalculator.removeListener(this);
|
||||
durationCalculator = null;
|
||||
synchronized (AudioSlidePlayer.this) {
|
||||
if (durationCalculator == null) return;
|
||||
Log.d(TAG, "request duration " + durationCalculator.getDuration());
|
||||
getListener().onReceivedDuration(Long.valueOf(durationCalculator.getDuration()).intValue());
|
||||
durationCalculator.release();
|
||||
durationCalculator.removeListener(this);
|
||||
durationCalculator = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
public static final int TAKE_PHOTO = 5;
|
||||
public static final int ADD_LOCATION = 6;
|
||||
public static final int RECORD_VIDEO = 7;
|
||||
public static final int ADD_WEBXDC = 8;
|
||||
|
||||
private static final int ANIMATION_DURATION = 300;
|
||||
|
||||
@@ -53,7 +54,7 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
//private final @NonNull ImageView cameraButton;
|
||||
private final @NonNull ImageView videoButton;
|
||||
private final @NonNull ImageView locationButton;
|
||||
private final @NonNull ImageView closeButton;
|
||||
private final @NonNull ImageView webxdcButton;
|
||||
|
||||
private @Nullable View currentAnchor;
|
||||
private @Nullable AttachmentClickedListener listener;
|
||||
@@ -76,7 +77,7 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
//this.cameraButton = ViewUtil.findById(layout, R.id.camera_button);
|
||||
this.videoButton = ViewUtil.findById(layout, R.id.record_video_button);
|
||||
this.locationButton = ViewUtil.findById(layout, R.id.location_button);
|
||||
this.closeButton = ViewUtil.findById(layout, R.id.close_button);
|
||||
this.webxdcButton = ViewUtil.findById(layout, R.id.webxdc_button);
|
||||
|
||||
this.imageButton.setOnClickListener(new PropagatingClickListener(ADD_GALLERY));
|
||||
this.videoChatButton.setOnClickListener(new PropagatingClickListener(INVITE_VIDEO_CHAT));
|
||||
@@ -85,7 +86,7 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
//this.cameraButton.setOnClickListener(new PropagatingClickListener(TAKE_PHOTO));
|
||||
this.videoButton.setOnClickListener(new PropagatingClickListener(RECORD_VIDEO));
|
||||
this.locationButton.setOnClickListener(new PropagatingClickListener(ADD_LOCATION));
|
||||
this.closeButton.setOnClickListener(new CloseClickListener());
|
||||
this.webxdcButton.setOnClickListener(new PropagatingClickListener(ADD_WEBXDC));
|
||||
this.recentRail.setListener(new RecentPhotoSelectedListener());
|
||||
|
||||
if (!Prefs.isLocationStreamingEnabled(context)) {
|
||||
@@ -130,33 +131,23 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
public void onGlobalLayout() {
|
||||
getContentView().getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
animateWindowInCircular(anchor, getContentView());
|
||||
} else {
|
||||
animateWindowInTranslate(getContentView());
|
||||
}
|
||||
animateWindowInCircular(anchor, getContentView());
|
||||
}
|
||||
});
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
//animateButtonIn(cameraButton, ANIMATION_DURATION / 2);
|
||||
animateButtonIn(videoButton, ANIMATION_DURATION / 2);
|
||||
animateButtonIn(imageButton, ANIMATION_DURATION / 3);
|
||||
animateButtonIn(contactButton, ANIMATION_DURATION / 3);
|
||||
animateButtonIn(locationButton, ANIMATION_DURATION / 4);
|
||||
animateButtonIn(documentButton, ANIMATION_DURATION / 4);
|
||||
animateButtonIn(videoChatButton, 0);
|
||||
animateButtonIn(closeButton, 0);
|
||||
}
|
||||
//animateButtonIn(cameraButton, ANIMATION_DURATION / 2);
|
||||
animateButtonIn(videoButton, ANIMATION_DURATION / 2);
|
||||
animateButtonIn(imageButton, ANIMATION_DURATION / 3);
|
||||
animateButtonIn(contactButton, ANIMATION_DURATION / 3);
|
||||
animateButtonIn(locationButton, ANIMATION_DURATION / 4);
|
||||
animateButtonIn(documentButton, ANIMATION_DURATION / 4);
|
||||
animateButtonIn(webxdcButton, 0);
|
||||
animateButtonIn(videoChatButton, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
animateWindowOutCircular(currentAnchor, getContentView());
|
||||
} else {
|
||||
animateWindowOutTranslate(getContentView());
|
||||
}
|
||||
animateWindowOutCircular(currentAnchor, getContentView());
|
||||
}
|
||||
|
||||
public void setListener(@Nullable AttachmentClickedListener listener) {
|
||||
@@ -186,7 +177,6 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
button.startAnimation(animation);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private void animateWindowInCircular(@Nullable View anchor, @NonNull View contentView) {
|
||||
Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView);
|
||||
Animator animator = ViewAnimationUtils.createCircularReveal(contentView,
|
||||
@@ -205,7 +195,6 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
getContentView().startAnimation(animation);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private void animateWindowOutCircular(@Nullable View anchor, @NonNull View contentView) {
|
||||
Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView);
|
||||
Animator animator = ViewAnimationUtils.createCircularReveal(getContentView(),
|
||||
@@ -301,13 +290,6 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
|
||||
}
|
||||
|
||||
private class CloseClickListener implements View.OnClickListener {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
public interface AttachmentClickedListener {
|
||||
public void onClick(int type);
|
||||
public void onQuickAttachment(Uri uri);
|
||||
|
||||
@@ -71,12 +71,10 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
|
||||
this.pauseButton.setOnClickListener(new PauseClickedListener());
|
||||
this.seekBar.setOnSeekBarChangeListener(new SeekBarModifiedListener());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
this.playButton.setImageDrawable(context.getDrawable(R.drawable.play_icon));
|
||||
this.pauseButton.setImageDrawable(context.getDrawable(R.drawable.pause_icon));
|
||||
this.playButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp));
|
||||
this.pauseButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp));
|
||||
}
|
||||
this.playButton.setImageDrawable(context.getDrawable(R.drawable.play_icon));
|
||||
this.pauseButton.setImageDrawable(context.getDrawable(R.drawable.pause_icon));
|
||||
this.playButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp));
|
||||
this.pauseButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp));
|
||||
|
||||
setTint(getContext().getResources().getColor(R.color.audio_icon));
|
||||
}
|
||||
@@ -192,13 +190,8 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
|
||||
}
|
||||
|
||||
public void setTint(int foregroundTint) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
this.playButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint));
|
||||
this.pauseButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint));
|
||||
} else {
|
||||
this.playButton.setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
|
||||
this.pauseButton.setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
this.playButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint));
|
||||
this.pauseButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint));
|
||||
|
||||
this.seekBar.getProgressDrawable().setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
|
||||
|
||||
@@ -220,25 +213,20 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
|
||||
private void togglePlayToPause() {
|
||||
controlToggle.displayQuick(pauseButton);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
AnimatedVectorDrawable playToPauseDrawable = (AnimatedVectorDrawable)getContext().getDrawable(R.drawable.play_to_pause_animation);
|
||||
pauseButton.setImageDrawable(playToPauseDrawable);
|
||||
playToPauseDrawable.start();
|
||||
}
|
||||
AnimatedVectorDrawable playToPauseDrawable = (AnimatedVectorDrawable) getContext().getDrawable(R.drawable.play_to_pause_animation);
|
||||
pauseButton.setImageDrawable(playToPauseDrawable);
|
||||
playToPauseDrawable.start();
|
||||
}
|
||||
|
||||
private void togglePauseToPlay() {
|
||||
controlToggle.displayQuick(playButton);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
AnimatedVectorDrawable pauseToPlayDrawable = (AnimatedVectorDrawable)getContext().getDrawable(R.drawable.pause_to_play_animation);
|
||||
playButton.setImageDrawable(pauseToPlayDrawable);
|
||||
pauseToPlayDrawable.start();
|
||||
}
|
||||
AnimatedVectorDrawable pauseToPlayDrawable = (AnimatedVectorDrawable) getContext().getDrawable(R.drawable.pause_to_play_animation);
|
||||
playButton.setImageDrawable(pauseToPlayDrawable);
|
||||
pauseToPlayDrawable.start();
|
||||
}
|
||||
|
||||
private class PlayClickedListener implements View.OnClickListener {
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
@@ -279,7 +267,6 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
|
||||
}
|
||||
|
||||
private class PauseClickedListener implements View.OnClickListener {
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Log.w(TAG, "pausebutton onClick");
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.widget.AppCompatEditText;
|
||||
import androidx.core.view.inputmethod.EditorInfoCompat;
|
||||
import androidx.core.view.inputmethod.InputConnectionCompat;
|
||||
import androidx.core.view.inputmethod.InputContentInfoCompat;
|
||||
@@ -25,10 +26,9 @@ import android.view.inputmethod.InputConnection;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.TransportOption;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiEditText;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
|
||||
public class ComposeText extends EmojiEditText {
|
||||
public class ComposeText extends AppCompatEditText {
|
||||
|
||||
private CharSequence hint;
|
||||
private SpannableString subHint;
|
||||
@@ -122,7 +122,6 @@ public class ComposeText extends EmojiEditText {
|
||||
editorInfo.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < 21) return inputConnection;
|
||||
if (mediaListener == null) return inputConnection;
|
||||
if (inputConnection == null) return null;
|
||||
|
||||
|
||||
@@ -120,15 +120,10 @@ public class ConversationItemThumbnail extends FrameLayout {
|
||||
@SuppressWarnings("SuspiciousNameCombination")
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
if (cornerMask.isLegacy()) {
|
||||
cornerMask.mask(canvas);
|
||||
}
|
||||
|
||||
super.dispatchDraw(canvas);
|
||||
|
||||
if (!cornerMask.isLegacy()) {
|
||||
cornerMask.mask(canvas);
|
||||
}
|
||||
cornerMask.mask(canvas);
|
||||
|
||||
final float halfStrokeWidth = outlinePaint.getStrokeWidth() / 2;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import android.graphics.Path;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import android.view.View;
|
||||
|
||||
@@ -20,11 +20,7 @@ public class CornerMask {
|
||||
private final RectF bounds = new RectF();
|
||||
|
||||
public CornerMask(@NonNull View view) {
|
||||
if (isLegacy()) {
|
||||
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
||||
} else {
|
||||
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
}
|
||||
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
|
||||
clearPaint.setColor(Color.BLACK);
|
||||
clearPaint.setStyle(Paint.Style.FILL);
|
||||
@@ -44,19 +40,10 @@ public class CornerMask {
|
||||
// Note: There's a bug in the P beta where most PorterDuff modes aren't working. But CLEAR does.
|
||||
// So we find and inverse path and use Mode.CLEAR for versions that support Path.op().
|
||||
// See issue https://issuetracker.google.com/issues/111394085.
|
||||
if (!isLegacy()) {
|
||||
outline.reset();
|
||||
outline.addRect(bounds, Path.Direction.CW);
|
||||
outline.op(corners, Path.Op.DIFFERENCE);
|
||||
canvas.drawPath(outline, clearPaint);
|
||||
} else {
|
||||
corners.addRoundRect(bounds, radii, Path.Direction.CW);
|
||||
canvas.clipPath(corners);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLegacy() {
|
||||
return Build.VERSION.SDK_INT < 19;
|
||||
outline.reset();
|
||||
outline.addRect(bounds, Path.Direction.CW);
|
||||
outline.op(corners, Path.Op.DIFFERENCE);
|
||||
canvas.drawPath(outline, clearPaint);
|
||||
}
|
||||
|
||||
public void setRadius(int radius) {
|
||||
|
||||
@@ -2,6 +2,8 @@ package org.thoughtcrime.securesms.components;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
@@ -14,12 +16,11 @@ import android.text.style.TypefaceSpan;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
import org.thoughtcrime.securesms.util.spans.CenterAlignedRelativeSizeSpan;
|
||||
|
||||
public class FromTextView extends EmojiTextView {
|
||||
public class FromTextView extends AppCompatTextView {
|
||||
|
||||
private static final String TAG = FromTextView.class.getSimpleName();
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import android.os.Build;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
@@ -29,14 +28,12 @@ import com.b44t.messenger.util.concurrent.SettableFuture;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiToggle;
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.QuoteModel;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener;
|
||||
@@ -46,9 +43,9 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class InputPanel extends ConstraintLayout
|
||||
implements MicrophoneRecorderView.Listener,
|
||||
KeyboardAwareLinearLayout.OnKeyboardShownListener,
|
||||
EmojiKeyboardProvider.EmojiEventListener
|
||||
implements MicrophoneRecorderView.Listener,
|
||||
KeyboardAwareLinearLayout.OnKeyboardShownListener,
|
||||
MediaKeyboard.MediaKeyboardListener
|
||||
{
|
||||
|
||||
private static final String TAG = InputPanel.class.getSimpleName();
|
||||
@@ -56,7 +53,7 @@ public class InputPanel extends ConstraintLayout
|
||||
private static final int FADE_TIME = 150;
|
||||
|
||||
private QuoteView quoteView;
|
||||
private EmojiToggle mediaKeyboard;
|
||||
private EmojiToggle emojiToggle;
|
||||
private ComposeText composeText;
|
||||
private View quickCameraToggle;
|
||||
private View quickAudioToggle;
|
||||
@@ -70,7 +67,6 @@ public class InputPanel extends ConstraintLayout
|
||||
private ValueAnimator quoteAnimator;
|
||||
|
||||
private @Nullable Listener listener;
|
||||
private boolean emojiVisible;
|
||||
|
||||
public InputPanel(Context context) {
|
||||
super(context);
|
||||
@@ -92,7 +88,7 @@ public class InputPanel extends ConstraintLayout
|
||||
View quoteDismiss = findViewById(R.id.quote_dismiss);
|
||||
|
||||
this.quoteView = findViewById(R.id.quote_view);
|
||||
this.mediaKeyboard = findViewById(R.id.emoji_toggle);
|
||||
this.emojiToggle = findViewById(R.id.emoji_toggle);
|
||||
this.composeText = findViewById(R.id.embedded_text_editor);
|
||||
this.quickCameraToggle = findViewById(R.id.quick_camera_toggle);
|
||||
this.quickAudioToggle = findViewById(R.id.quick_audio_toggle);
|
||||
@@ -106,21 +102,13 @@ public class InputPanel extends ConstraintLayout
|
||||
|
||||
this.recordLockCancel.setOnClickListener(v -> microphoneRecorderView.cancelAction());
|
||||
|
||||
if (Prefs.isSystemEmojiPreferred(getContext())) {
|
||||
mediaKeyboard.setVisibility(View.GONE);
|
||||
emojiVisible = false;
|
||||
} else {
|
||||
mediaKeyboard.setVisibility(View.VISIBLE);
|
||||
emojiVisible = true;
|
||||
}
|
||||
|
||||
quoteDismiss.setOnClickListener(v -> clearQuote());
|
||||
}
|
||||
|
||||
public void setListener(final @NonNull Listener listener) {
|
||||
this.listener = listener;
|
||||
|
||||
mediaKeyboard.setOnClickListener(v -> listener.onEmojiToggle());
|
||||
emojiToggle.setOnClickListener(v -> listener.onEmojiToggle());
|
||||
}
|
||||
|
||||
public void setMediaListener(@NonNull MediaListener listener) {
|
||||
@@ -207,7 +195,7 @@ public class InputPanel extends ConstraintLayout
|
||||
}
|
||||
|
||||
public void setMediaKeyboard(@NonNull MediaKeyboard mediaKeyboard) {
|
||||
this.mediaKeyboard.attach(mediaKeyboard);
|
||||
mediaKeyboard.setKeyboardListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -221,7 +209,7 @@ public class InputPanel extends ConstraintLayout
|
||||
recordTime.display();
|
||||
slideToCancel.display();
|
||||
|
||||
if (emojiVisible) ViewUtil.fadeOut(mediaKeyboard, FADE_TIME, View.INVISIBLE);
|
||||
ViewUtil.fadeOut(emojiToggle, FADE_TIME, View.INVISIBLE);
|
||||
ViewUtil.fadeOut(composeText, FADE_TIME, View.INVISIBLE);
|
||||
ViewUtil.fadeOut(quickCameraToggle, FADE_TIME, View.INVISIBLE);
|
||||
ViewUtil.fadeOut(quickAudioToggle, FADE_TIME, View.INVISIBLE);
|
||||
@@ -276,7 +264,7 @@ public class InputPanel extends ConstraintLayout
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
composeText.setEnabled(enabled);
|
||||
mediaKeyboard.setEnabled(enabled);
|
||||
emojiToggle.setEnabled(enabled);
|
||||
quickAudioToggle.setEnabled(enabled);
|
||||
quickCameraToggle.setEnabled(enabled);
|
||||
}
|
||||
@@ -290,7 +278,7 @@ public class InputPanel extends ConstraintLayout
|
||||
future.addListener(new AssertedSuccessListener<Void>() {
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
if (emojiVisible) ViewUtil.fadeIn(mediaKeyboard, FADE_TIME);
|
||||
ViewUtil.fadeIn(emojiToggle, FADE_TIME);
|
||||
ViewUtil.fadeIn(composeText, FADE_TIME);
|
||||
ViewUtil.fadeIn(quickCameraToggle, FADE_TIME);
|
||||
ViewUtil.fadeIn(quickAudioToggle, FADE_TIME);
|
||||
@@ -304,17 +292,7 @@ public class InputPanel extends ConstraintLayout
|
||||
|
||||
@Override
|
||||
public void onKeyboardShown() {
|
||||
mediaKeyboard.setToMedia();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyEvent(KeyEvent keyEvent) {
|
||||
composeText.dispatchKeyEvent(keyEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEmojiSelected(String emoji) {
|
||||
composeText.insertEmoji(emoji);
|
||||
emojiToggle.setToMedia();
|
||||
}
|
||||
|
||||
public boolean isRecordingInLockedMode() {
|
||||
@@ -325,6 +303,25 @@ public class InputPanel extends ConstraintLayout
|
||||
microphoneRecorderView.unlockAction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShown() {
|
||||
emojiToggle.setToIme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHidden() {
|
||||
emojiToggle.setToMedia();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEmojiPicked(String emoji) {
|
||||
final int start = composeText.getSelectionStart();
|
||||
final int end = composeText.getSelectionEnd();
|
||||
|
||||
composeText.getText().replace(Math.min(start, end), Math.max(start, end), emoji);
|
||||
composeText.setSelection(start + emoji.length());
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void onRecorderStarted();
|
||||
void onRecorderLocked();
|
||||
|
||||
@@ -104,7 +104,7 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
|
||||
}
|
||||
|
||||
private void updateKeyboardState() {
|
||||
if (viewInset == 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) viewInset = getViewInset();
|
||||
if (viewInset == 0) viewInset = getViewInset();
|
||||
|
||||
getWindowVisibleDisplayFrame(rect);
|
||||
|
||||
@@ -148,7 +148,6 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
private int getViewInset() {
|
||||
try {
|
||||
Field attachInfoField = View.class.getDeclaredField("mAttachInfo");
|
||||
@@ -219,11 +218,7 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
|
||||
return Surface.ROTATION_0;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
return ServiceUtil.getWindowManager(getContext()).getDefaultDisplay().getRotation();
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 30) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
getContext().getDisplay().getRealMetrics(displayMetrics);
|
||||
} else {
|
||||
ServiceUtil.getWindowManager(getContext()).getDefaultDisplay().getRealMetrics(displayMetrics);
|
||||
|
||||
@@ -3,10 +3,8 @@ package org.thoughtcrime.securesms.components;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
@@ -40,7 +38,6 @@ public class MediaView extends FrameLayout {
|
||||
initialize();
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public MediaView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
initialize();
|
||||
@@ -56,6 +53,7 @@ public class MediaView extends FrameLayout {
|
||||
public void set(@NonNull GlideRequests glideRequests,
|
||||
@NonNull Window window,
|
||||
@NonNull Uri source,
|
||||
@Nullable String fileName,
|
||||
@NonNull String mediaType,
|
||||
long size,
|
||||
boolean autoplay)
|
||||
@@ -69,7 +67,7 @@ public class MediaView extends FrameLayout {
|
||||
imageView.setVisibility(View.GONE);
|
||||
videoView.get().setVisibility(View.VISIBLE);
|
||||
videoView.get().setWindow(window);
|
||||
videoView.get().setVideoSource(new VideoSlide(getContext(), source, size), autoplay);
|
||||
videoView.get().setVideoSource(new VideoSlide(getContext(), source, fileName, size), autoplay);
|
||||
} else {
|
||||
throw new IOException("Unsupported media type: " + mediaType);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ package org.thoughtcrime.securesms.components;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.text.Spannable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
@@ -17,7 +16,6 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
import com.b44t.messenger.DcContact;
|
||||
@@ -80,7 +78,6 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
initialize(attrs);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public QuoteView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
initialize(attrs);
|
||||
@@ -158,7 +155,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
if (contact == null) {
|
||||
authorView.setText(getContext().getString(R.string.forwarded_message));
|
||||
} else {
|
||||
authorView.setText(getContext().getString(R.string.forwarded_by, quotedMsg.getSenderName(contact, false)));
|
||||
authorView.setText(getContext().getString(R.string.forwarded_by, quotedMsg.getSenderName(contact)));
|
||||
}
|
||||
authorView.setTextColor(getForwardedColor());
|
||||
quoteBarView.setBackgroundColor(getForwardedColor());
|
||||
@@ -169,7 +166,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
quoteBarView.setBackgroundColor(getForwardedColor());
|
||||
} else {
|
||||
authorView.setVisibility(VISIBLE);
|
||||
authorView.setText(quotedMsg.getSenderName(contact, true));
|
||||
authorView.setText(quotedMsg.getSenderName(contact));
|
||||
if (hasSticker) {
|
||||
authorView.setTextColor(getResources().getColor(R.color.core_dark_05));
|
||||
quoteBarView.setBackgroundColor(getResources().getColor(R.color.core_dark_05));
|
||||
|
||||
@@ -29,7 +29,6 @@ public class RepeatableImageKey extends ImageButton {
|
||||
init();
|
||||
}
|
||||
|
||||
@TargetApi(VERSION_CODES.LOLLIPOP)
|
||||
public RepeatableImageKey(Context context, AttributeSet attrs, int defStyleAttr,
|
||||
int defStyleRes)
|
||||
{
|
||||
|
||||
@@ -130,15 +130,11 @@ public class SearchToolbar extends LinearLayout {
|
||||
|
||||
searchItem.expandActionView();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, 0, getWidth());
|
||||
animator.setDuration(400);
|
||||
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int) x, (int) y, 0, getWidth());
|
||||
animator.setDuration(400);
|
||||
|
||||
setVisibility(View.VISIBLE);
|
||||
animator.start();
|
||||
} else {
|
||||
setVisibility(View.VISIBLE);
|
||||
}
|
||||
setVisibility(View.VISIBLE);
|
||||
animator.start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,19 +149,15 @@ public class SearchToolbar extends LinearLayout {
|
||||
|
||||
if (listener != null) listener.onSearchClosed();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, getWidth(), 0);
|
||||
animator.setDuration(400);
|
||||
animator.addListener(new AnimationCompleteListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
setVisibility(View.INVISIBLE);
|
||||
}
|
||||
});
|
||||
animator.start();
|
||||
} else {
|
||||
setVisibility(View.INVISIBLE);
|
||||
}
|
||||
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int) x, (int) y, getWidth(), 0);
|
||||
animator.setDuration(400);
|
||||
animator.addListener(new AnimationCompleteListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
setVisibility(View.INVISIBLE);
|
||||
}
|
||||
});
|
||||
animator.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ public class SwitchPreferenceCompat extends CheckBoxPreference {
|
||||
setLayoutRes();
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public SwitchPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
setLayoutRes();
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Drawable.Callback;
|
||||
import android.text.style.ImageSpan;
|
||||
|
||||
public class AnimatingImageSpan extends ImageSpan {
|
||||
public AnimatingImageSpan(Drawable drawable, Callback callback) {
|
||||
super(drawable, ALIGN_BOTTOM);
|
||||
drawable.setCallback(callback);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
|
||||
public class AsciiEmojiView extends View {
|
||||
|
||||
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
|
||||
|
||||
private String emoji;
|
||||
|
||||
public AsciiEmojiView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public AsciiEmojiView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public void setEmoji(String emoji) {
|
||||
this.emoji = emoji;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (TextUtils.isEmpty(emoji)) {
|
||||
return;
|
||||
}
|
||||
|
||||
float targetFontSize = 0.75f * getHeight() - getPaddingTop() - getPaddingBottom();
|
||||
|
||||
paint.setTextSize(targetFontSize);
|
||||
paint.setColor(ResUtil.getColor(getContext(), R.attr.emoji_text_color));
|
||||
paint.setTextAlign(Paint.Align.CENTER);
|
||||
|
||||
int xPos = (getWidth() / 2);
|
||||
int yPos = (int) ((getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2));
|
||||
|
||||
float overflow = paint.measureText(emoji) / (getWidth() - getPaddingLeft() - getPaddingRight());
|
||||
if (overflow > 1f) {
|
||||
paint.setTextSize(targetFontSize / overflow);
|
||||
yPos = (int) ((getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2));
|
||||
}
|
||||
canvas.drawText(emoji, xPos, yPos, paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
//noinspection SuspiciousNameCombination
|
||||
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
|
||||
}
|
||||
}
|
||||
+109
File diff suppressed because one or more lines are too long
-55
@@ -1,55 +0,0 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import androidx.annotation.AttrRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class CompositeEmojiPageModel implements EmojiPageModel {
|
||||
@AttrRes private final int iconAttr;
|
||||
@NonNull private final EmojiPageModel[] models;
|
||||
|
||||
public CompositeEmojiPageModel(@AttrRes int iconAttr, @NonNull EmojiPageModel... models) {
|
||||
this.iconAttr = iconAttr;
|
||||
this.models = models;
|
||||
}
|
||||
|
||||
public int getIconAttr() {
|
||||
return iconAttr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull List<String> getEmoji() {
|
||||
List<String> emojis = new LinkedList<>();
|
||||
for (EmojiPageModel model : models) {
|
||||
emojis.addAll(model.getEmoji());
|
||||
}
|
||||
return emojis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull List<Emoji> getDisplayEmoji() {
|
||||
List<Emoji> emojis = new LinkedList<>();
|
||||
for (EmojiPageModel model : models) {
|
||||
emojis.addAll(model.getDisplayEmoji());
|
||||
}
|
||||
return emojis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSpriteMap() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getSprite() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDynamic() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Emoji {
|
||||
|
||||
private final List<String> variations;
|
||||
|
||||
public Emoji(String... variations) {
|
||||
this.variations = Arrays.asList(variations);
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return variations.get(0);
|
||||
}
|
||||
|
||||
public List<String> getVariations() {
|
||||
return variations;
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.AppCompatEditText;
|
||||
import android.text.InputFilter;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiProvider.EmojiDrawable;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
|
||||
|
||||
public class EmojiEditText extends AppCompatEditText {
|
||||
private static final String TAG = EmojiEditText.class.getSimpleName();
|
||||
|
||||
public EmojiEditText(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public EmojiEditText(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.editTextStyle);
|
||||
}
|
||||
|
||||
public EmojiEditText(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
if (!Prefs.isSystemEmojiPreferred(getContext())) {
|
||||
setFilters(appendEmojiFilter(this.getFilters()));
|
||||
}
|
||||
}
|
||||
|
||||
public void insertEmoji(String emoji) {
|
||||
final int start = getSelectionStart();
|
||||
final int end = getSelectionEnd();
|
||||
|
||||
getText().replace(Math.min(start, end), Math.max(start, end), emoji);
|
||||
setSelection(start + emoji.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateDrawable(@NonNull Drawable drawable) {
|
||||
if (drawable instanceof EmojiDrawable) invalidate();
|
||||
else super.invalidateDrawable(drawable);
|
||||
}
|
||||
|
||||
private InputFilter[] appendEmojiFilter(@Nullable InputFilter[] originalFilters) {
|
||||
InputFilter[] result;
|
||||
|
||||
if (originalFilters != null) {
|
||||
result = new InputFilter[originalFilters.length + 1];
|
||||
System.arraycopy(originalFilters, 0, result, 1, originalFilters.length);
|
||||
} else {
|
||||
result = new InputFilter[1];
|
||||
}
|
||||
|
||||
result[0] = new EmojiFilter(this);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import android.text.InputFilter;
|
||||
import android.text.Spannable;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class EmojiFilter implements InputFilter {
|
||||
private final TextView view;
|
||||
|
||||
public EmojiFilter(TextView view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)
|
||||
{
|
||||
char[] v = new char[end - start];
|
||||
TextUtils.getChars(source, start, end, v, 0);
|
||||
|
||||
Spannable emojified = EmojiProvider.getInstance(view.getContext()).emojify(new String(v), view);
|
||||
|
||||
if (source instanceof Spanned && emojified != null) {
|
||||
TextUtils.copySpansFrom((Spanned) source, start, end, null, emojified, 0);
|
||||
}
|
||||
|
||||
return emojified;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
public class EmojiImageView extends AppCompatImageView {
|
||||
public EmojiImageView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public EmojiImageView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public void setImageEmoji(CharSequence emoji) {
|
||||
setImageDrawable(EmojiProvider.getInstance(getContext()).getEmojiDrawable(emoji));
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter.VariationSelectorListener;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
import org.thoughtcrime.securesms.util.ThemeUtil;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A provider to select emoji in the {@link org.thoughtcrime.securesms.components.emoji.MediaKeyboard}.
|
||||
*/
|
||||
public class EmojiKeyboardProvider implements MediaKeyboardProvider,
|
||||
MediaKeyboardProvider.TabIconProvider,
|
||||
MediaKeyboardProvider.BackspaceObserver,
|
||||
VariationSelectorListener
|
||||
{
|
||||
private static final KeyEvent DELETE_KEY_EVENT = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL);
|
||||
|
||||
private static final String RECENT_STORAGE_KEY = "pref_recent_emoji2";
|
||||
|
||||
private final Context context;
|
||||
private final List<EmojiPageModel> models;
|
||||
private final RecentEmojiPageModel recentModel;
|
||||
private final EmojiPagerAdapter emojiPagerAdapter;
|
||||
private final EmojiEventListener emojiEventListener;
|
||||
|
||||
private Controller controller;
|
||||
|
||||
public EmojiKeyboardProvider(@NonNull Context context, @Nullable EmojiEventListener emojiEventListener) {
|
||||
this.context = context;
|
||||
this.emojiEventListener = emojiEventListener;
|
||||
this.models = new LinkedList<>();
|
||||
this.recentModel = new RecentEmojiPageModel(context, RECENT_STORAGE_KEY);
|
||||
this.emojiPagerAdapter = new EmojiPagerAdapter(context, models, new EmojiEventListener() {
|
||||
@Override
|
||||
public void onEmojiSelected(String emoji) {
|
||||
recentModel.onCodePointSelected(emoji);
|
||||
|
||||
if (emojiEventListener != null) {
|
||||
emojiEventListener.onEmojiSelected(emoji);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyEvent(KeyEvent keyEvent) {
|
||||
if (emojiEventListener != null) {
|
||||
emojiEventListener.onKeyEvent(keyEvent);
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
|
||||
models.add(recentModel);
|
||||
models.addAll(EmojiPages.DISPLAY_PAGES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPresentation(@NonNull Presenter presenter, boolean isSoloProvider) {
|
||||
presenter.present(this, emojiPagerAdapter, this, this, null, null, recentModel.getEmoji().size() > 0 ? 0 : 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setController(@Nullable Controller controller) {
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProviderIconView(boolean selected) {
|
||||
if (selected) {
|
||||
return ThemeUtil.isDarkTheme(context) ? R.layout.emoji_keyboard_icon_dark_selected : R.layout.emoji_keyboard_icon_light_selected;
|
||||
} else {
|
||||
return ThemeUtil.isDarkTheme(context) ? R.layout.emoji_keyboard_icon_dark : R.layout.emoji_keyboard_icon_light;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCategoryTabIcon(@NonNull GlideRequests glideRequests, @NonNull ImageView imageView, int index) {
|
||||
Drawable drawable = ResUtil.getDrawable(context, models.get(index).getIconAttr());
|
||||
imageView.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackspaceClicked() {
|
||||
if (emojiEventListener != null) {
|
||||
emojiEventListener.onKeyEvent(DELETE_KEY_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVariationSelectorStateChanged(boolean open) {
|
||||
if (controller != null) {
|
||||
controller.setViewPagerEnabled(!open);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return obj instanceof EmojiKeyboardProvider;
|
||||
}
|
||||
|
||||
private static class EmojiPagerAdapter extends PagerAdapter {
|
||||
private final Context context;
|
||||
private final List<EmojiPageModel> pages;
|
||||
private final EmojiEventListener emojiSelectionListener;
|
||||
private final VariationSelectorListener variationSelectorListener;
|
||||
|
||||
public EmojiPagerAdapter(@NonNull Context context,
|
||||
@NonNull List<EmojiPageModel> pages,
|
||||
@NonNull EmojiEventListener emojiSelectionListener,
|
||||
@NonNull VariationSelectorListener variationSelectorListener)
|
||||
{
|
||||
super();
|
||||
this.context = context;
|
||||
this.pages = pages;
|
||||
this.emojiSelectionListener = emojiSelectionListener;
|
||||
this.variationSelectorListener = variationSelectorListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return pages.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Object instantiateItem(@NonNull ViewGroup container, int position) {
|
||||
EmojiPageView page = new EmojiPageView(context, emojiSelectionListener, variationSelectorListener, true);
|
||||
page.setModel(pages.get(position));
|
||||
container.addView(page);
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(ViewGroup container, int position, Object object) {
|
||||
container.removeView((View)object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrimaryItem(ViewGroup container, int position, Object object) {
|
||||
EmojiPageView current = (EmojiPageView) object;
|
||||
current.onSelected();
|
||||
super.setPrimaryItem(container, position, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewFromObject(View view, Object object) {
|
||||
return view == object;
|
||||
}
|
||||
}
|
||||
|
||||
public interface EmojiEventListener {
|
||||
void onEmojiSelected(String emoji);
|
||||
void onKeyEvent(KeyEvent keyEvent);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface EmojiPageModel {
|
||||
int getIconAttr();
|
||||
List<String> getEmoji();
|
||||
List<Emoji> getDisplayEmoji();
|
||||
boolean hasSpriteMap();
|
||||
String getSprite();
|
||||
boolean isDynamic();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user