mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Compare commits
321 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f76b1cb3d3 | |||
| 98551713ae | |||
| bc2e4002c3 | |||
| 40b8f1297e | |||
| 84f8a39355 | |||
| 6874191143 | |||
| aea7e912e0 | |||
| 4f8068f144 | |||
| 4f4e42e20c | |||
| 8ddb51382e | |||
| 252263e6db | |||
| 4efdc0b1c8 | |||
| 30858c51d6 | |||
| 42cd1c6ad1 | |||
| e6b40adf8a | |||
| 500e5a910d | |||
| fe3f34222d | |||
| 408c7ae727 | |||
| 5198191728 | |||
| 6f2cc60017 | |||
| 091cb931d7 | |||
| 26ec26e75c | |||
| 1b0b87f148 | |||
| 9dbb918ed8 | |||
| a955d6f2f7 | |||
| 42f8eb9153 | |||
| 2143bc01d1 | |||
| 5a3728428b | |||
| f236085b92 | |||
| ac6119792f | |||
| b0cea8f099 | |||
| 7590b21928 | |||
| ea7fd0ec22 | |||
| cf4cb2f839 | |||
| 6a4e40d17b | |||
| 5302e86011 | |||
| 5382e880a9 | |||
| 2385b236c7 | |||
| 5224119f9e | |||
| dfef2b4120 | |||
| 6d7f417233 | |||
| 05ef95e757 | |||
| 8aa45b7bc9 | |||
| 7cea23caf5 | |||
| 4a2bed3e6c | |||
| 3aa2fbf67a | |||
| c5d9471f2a | |||
| 5117b70c58 | |||
| da4d17aa14 | |||
| 6135813bff | |||
| 8547f7aab8 | |||
| 6dca20045c | |||
| 58ef777091 | |||
| 4a836b3d82 | |||
| 363122fd15 | |||
| b751219c78 | |||
| e586fafc54 | |||
| 2c04319c52 | |||
| f9607e4453 | |||
| 6aec209ebc | |||
| 9adc9b34e5 | |||
| 9267501bc1 | |||
| 924c3f8920 | |||
| 8f93dacbff | |||
| a07e9312ea | |||
| 79f6010d5f | |||
| c5af1d4f2b | |||
| 20a3820871 | |||
| cb0d1106b4 | |||
| 291ef86a4f | |||
| b0457bc036 | |||
| 4d7107314a | |||
| 4185219088 | |||
| ef51492d0b | |||
| 4dc10f977e | |||
| aaba52dba6 | |||
| ca4808aaca | |||
| 66324fe914 | |||
| a5f67e9d9f | |||
| 8b5c887402 | |||
| 183cb03577 | |||
| b1e6d59ba9 | |||
| 33f38889c1 | |||
| f97e800907 | |||
| 21e597d09e | |||
| 6b040b160d | |||
| 57e5523bf3 | |||
| 874492c9ae | |||
| 8ae6407461 | |||
| ae8ce94c00 | |||
| 74208fff69 | |||
| 7ace2b9baf | |||
| f28fffb9df | |||
| 349e8d80c8 | |||
| 4b9217e3e6 | |||
| 4e6e805ede | |||
| 02a1c86f01 | |||
| b28fb4ac9e | |||
| fddc80e60b | |||
| e5b1becf13 | |||
| 01b78e37fd | |||
| d0b1f36f60 | |||
| e388464d28 | |||
| afc7a04b63 | |||
| b871e42b86 | |||
| 3479233f82 | |||
| 7e3e35a9a1 | |||
| 92711444e4 | |||
| ec576d7159 | |||
| 70a05221ab | |||
| 6335cfa178 | |||
| ebda8c4577 | |||
| de9a2df1b4 | |||
| a3c7e3db3d | |||
| 249fc829be | |||
| 5b62f7bf25 | |||
| df6c858b92 | |||
| c9816ae785 | |||
| a24069ce3d | |||
| f770f817d0 | |||
| bee804e095 | |||
| 6b1c6b37ac | |||
| 881e69c176 | |||
| ac6df2ff85 | |||
| 7698ac5c06 | |||
| c2abe42b60 | |||
| 3e95197d02 | |||
| 534a75feaa | |||
| 7a11234431 | |||
| 0e91537a4d | |||
| b074bf1819 | |||
| b8d2552aa8 | |||
| 320c120a61 | |||
| 6c1a3c850a | |||
| 7ec87f55b6 | |||
| f6ce98f9a2 | |||
| cb465ec85e | |||
| 6f10a90c5f | |||
| 9f439c852f | |||
| 2cc0451a8a | |||
| 02230d05a1 | |||
| 9a6f6d7ea6 | |||
| f4cd299f70 | |||
| d0358a4d0c | |||
| 4fc115b93d | |||
| 0157510c5d | |||
| 831ce19689 | |||
| 9431e26696 | |||
| 9ef01dd352 | |||
| 01c766db41 | |||
| 364d15442a | |||
| 32eefaab42 | |||
| 4b8177f7f0 | |||
| 092a5caf8b | |||
| bfe4438773 | |||
| d251fffc07 | |||
| 180c2bc8de | |||
| 082815f676 | |||
| 640688d774 | |||
| 30868198a2 | |||
| 75673ef1ad | |||
| 478d937b3c | |||
| 7a5eb6bea6 | |||
| 0142d51835 | |||
| 075bad3638 | |||
| 1f173bae9b | |||
| 2deb61477f | |||
| fcc1ab1079 | |||
| c72207da8a | |||
| 82233d7862 | |||
| 2547a0435c | |||
| b6ce6d908f | |||
| c6bbb0a524 | |||
| 826258a1be | |||
| 05dde13e68 | |||
| 06130c7cd8 | |||
| 5d7c701da8 | |||
| 91e898ee96 | |||
| 61e9466c59 | |||
| 39c48d3dcd | |||
| 1c7c3f06e6 | |||
| d4ddb68137 | |||
| c9ac421315 | |||
| e14bf24bb1 | |||
| 700d11f600 | |||
| fbb33c735c | |||
| 7cc9d7ea2f | |||
| ca27be240e | |||
| 8ab9b92517 | |||
| f95b48ad6a | |||
| 8ebdc5414a | |||
| a0e07cb2ea | |||
| 152360d94a | |||
| 8513f7cd36 | |||
| 17e3f3afdd | |||
| 7d7f62dae1 | |||
| 2bd0a0d935 | |||
| cf0414dd66 | |||
| 5fbd065882 | |||
| 5982a9dd8f | |||
| 4b20e3f41f | |||
| ac8d8886cc | |||
| a803d472bf | |||
| 396ed14067 | |||
| 5faea5e40a | |||
| 08bb248919 | |||
| 30dd7a9c33 | |||
| 28f57a2ccb | |||
| c0717237ad | |||
| 5716372453 | |||
| d362cf4467 | |||
| 56118d3732 | |||
| a03f51f7c5 | |||
| 6cf59133c2 | |||
| ef8d833f5e | |||
| b110c1f91e | |||
| e53a1f0b22 | |||
| 5a5cbfceb7 | |||
| 57a557a9b4 | |||
| 2328bf1e2a | |||
| ce4c9aaba0 | |||
| 71a2cb7a5b | |||
| 79462c0596 | |||
| 68f5d1ae27 | |||
| 77caced5ed | |||
| 88a4f99cf8 | |||
| 42544fd447 | |||
| 5ff869cd4a | |||
| 4af1666a31 | |||
| 786fd3f47d | |||
| a0d9315ff4 | |||
| 86954a3c42 | |||
| f136b6d7d1 | |||
| 9e4b744046 | |||
| 8db4604224 | |||
| 43f9094c04 | |||
| 1217e65889 | |||
| d8eaf0ad4b | |||
| 4fbb8d2b78 | |||
| 7cebd04086 | |||
| b584fdfd89 | |||
| db35fef6db | |||
| 068102a0d8 | |||
| 02ff8a2a6b | |||
| 321b5a223b | |||
| ab7fd960ca | |||
| dec685023e | |||
| 168d2ae16c | |||
| e55249182a | |||
| 0966487978 | |||
| fd057485db | |||
| a68f3a7024 | |||
| 1dad6ebf8a | |||
| a77b1a5dd6 | |||
| c0a65e2e9f | |||
| 82ef0560a5 | |||
| 9166b2a42a | |||
| 2ef3811a56 | |||
| 1b91c1c482 | |||
| 0d8962f76c | |||
| e98535418c | |||
| 5eb9065d89 | |||
| 9e70c43ab8 | |||
| fc8bfabeb2 | |||
| 681c22293f | |||
| bed8d511fe | |||
| eeeb686868 | |||
| 76dda10a31 | |||
| 6a7c4f24e9 | |||
| 8cdfafd7c3 | |||
| 1c6faeac04 | |||
| 7ecf0a7daa | |||
| b2bf7e8ae7 | |||
| 0a34456302 | |||
| 3ebcc1dd99 | |||
| ff7df0e1e6 | |||
| 68cd070b98 | |||
| 8ff8cffa15 | |||
| dc216feb30 | |||
| 84fc885617 | |||
| 72bcbe80c0 | |||
| b4ed26b842 | |||
| 7be6b0a1ee | |||
| 9a2fdcdcbd | |||
| e81960f98a | |||
| a37fcfcaf7 | |||
| fd4a377752 | |||
| d40652d394 | |||
| aacca5531c | |||
| 51cb844e63 | |||
| ef0b8efcfa | |||
| 3e943483da | |||
| a9013bb574 | |||
| aa5fcb139e | |||
| c526c42d19 | |||
| f66003c6b1 | |||
| cc64142e7b | |||
| a280407370 | |||
| dda5efedc4 | |||
| 1cd4ec1ec9 | |||
| 1a8b905071 | |||
| de13a70c66 | |||
| 2caa98e08a | |||
| ba997d9f71 | |||
| 3985f2f468 | |||
| 86bd38bdad | |||
| ffa1c69be2 | |||
| 3a3388ed59 | |||
| 8c04c199e6 | |||
| ecdbbed8c1 | |||
| a9541a936e | |||
| 571f49ab13 | |||
| 365f1dbbe6 | |||
| 100bb06e20 | |||
| 27f662707a | |||
| 3086c72304 | |||
| eee218a3b6 | |||
| fa868077b0 | |||
| e8776177ba | |||
| 677c0592fc | |||
| 40a79fbad5 |
@@ -7,7 +7,7 @@ on:
|
||||
jobs:
|
||||
artifacts-url-comments:
|
||||
name: add artifact links to pull request
|
||||
runs-on: windows-2019
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
steps:
|
||||
- name: add artifact links to pull request
|
||||
|
||||
@@ -2,16 +2,16 @@ name: Upload Preview APK
|
||||
|
||||
on: pull_request
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Upload Preview APK
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Validate Fastlane Metadata
|
||||
@@ -19,12 +19,12 @@ jobs:
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
working-directory: jni/deltachat-core-rust
|
||||
- uses: actions/setup-java@v3
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: 'temurin'
|
||||
- uses: android-actions/setup-android@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
@@ -37,6 +37,9 @@ jobs:
|
||||
with:
|
||||
ndk-version: r27
|
||||
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/actions/wrapper-validation@v4
|
||||
|
||||
- name: Compile core
|
||||
env:
|
||||
ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
|
||||
@@ -44,9 +47,6 @@ jobs:
|
||||
export PATH="${PATH}:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/"
|
||||
scripts/install-toolchains.sh && scripts/ndk-make.sh armeabi-v7a
|
||||
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
|
||||
- name: Build APK
|
||||
run: ./gradlew --no-daemon -PABI_FILTER=armeabi-v7a assembleFossDebug
|
||||
|
||||
|
||||
+257
@@ -0,0 +1,257 @@
|
||||
# Building and Testing
|
||||
|
||||
This document describes how to set up the build environment,
|
||||
build and test the app. Before diving into developing, please
|
||||
first read [CONTRIBUTING.md](./CONTRIBUTING.md) for general
|
||||
contribution hints and conventions.
|
||||
|
||||
Please follow all steps precisely.
|
||||
If you run into troubles,
|
||||
ask on one of the [communication channels](https://delta.chat/contribute) for help
|
||||
|
||||
|
||||
## Check Out Repository
|
||||
|
||||
When checking out _deltachat-android_, make sure also to check out the
|
||||
subproject _deltachat-core-rust_:
|
||||
|
||||
- When using Git, you can do this initially by
|
||||
`$ git clone --recursive https://github.com/deltachat/deltachat-android`
|
||||
or later by `git submodule update --init --recursive`. If you do this in your
|
||||
home directory, this results in the folder `~/deltachat-android` which is just fine.
|
||||
|
||||
## Generate JSON-RPC bindings
|
||||
|
||||
To generate the JSON-RPC bindings (ex. `chat.delta.rpc.*` package)
|
||||
install the [dcrpcgen tool](https://github.com/chatmail/dcrpcgen)
|
||||
then generate the `schema.json` file:
|
||||
|
||||
```
|
||||
# install deltachat-rpc-server program:
|
||||
cargo install --path ./jni/deltachat-core-rust/deltachat-rpc-server
|
||||
# check the version of core matches:
|
||||
deltachat-rpc-server --version
|
||||
# generate the schema:
|
||||
deltachat-rpc-server --openrpc > schema.json
|
||||
```
|
||||
|
||||
then pass the schema file to the `dcrpcgen` tool to generate the
|
||||
code:
|
||||
|
||||
```
|
||||
dcrpcgen java --schema schema.json -o ./src/main/java/
|
||||
```
|
||||
|
||||
## Build Using Nix
|
||||
|
||||
The repository contains [Nix](https://nixos.org/) development environment
|
||||
described in `flake.nix` file.
|
||||
If you don't have Nix installed,
|
||||
the easiest way is to follow the [Lix installation instructions](https://lix.systems/install/)
|
||||
as this results in a setup with [Flakes](https://nixos.wiki/wiki/Flakes) feature enabled out of the box
|
||||
and can be cleanly uninstalled with `/nix/nix-installer uninstall` once you don't need it anymore.
|
||||
|
||||
Once you have Nix with Flakes feature set up start the development environment shell:
|
||||
```
|
||||
nix develop
|
||||
```
|
||||
Nix development environment contains Rust with cross-compilation toolchains and Android SDK.
|
||||
|
||||
To [build an APK](https://developer.android.com/studio/build/building-cmdline) run the following 2 steps.
|
||||
Note that the first step may take some time to build for all architectures. You can optionally read
|
||||
[the first comment block in the `ndk-make.sh` script](https://github.com/deltachat/deltachat-android/blob/master/scripts/ndk-make.sh)
|
||||
for pointers on how to build for a specific architecture.
|
||||
```
|
||||
$ scripts/ndk-make.sh
|
||||
$ ./gradlew assembleDebug
|
||||
```
|
||||
|
||||
Resulting APK files can be found in
|
||||
`build/outputs/apk/gplay/debug/` and
|
||||
`build/outputs/apk/fat/debug/`.
|
||||
|
||||
## Build Using Dockerfile
|
||||
|
||||
Another way to build APK is to use provided `Dockerfile`
|
||||
with [Docker](https://www.docker.com/) or [Podman](https://podman.io/).
|
||||
Podman is a drop-in replacement for Docker that does not require root privileges.
|
||||
|
||||
If you don't have Docker or Podman setup yet, read [how to setup Podman](#setup-podman)
|
||||
below. If you don't want to use Docker or Podman, read [how to manually install the
|
||||
build environment](#install-build-environment).
|
||||
|
||||
First, build the image `deltachat-android` by running
|
||||
```
|
||||
podman build --build-arg UID=$(id -u) --build-arg GID=$(id -g) . -t deltachat-android
|
||||
```
|
||||
or
|
||||
```
|
||||
docker build --build-arg UID=$(id -u) --build-arg GID=$(id -g) . -t deltachat-android
|
||||
```
|
||||
|
||||
Then, run the image:
|
||||
```
|
||||
podman run --userns=keep-id -it --name deltachat -v $(pwd):/home/app:z -w /home/app localhost/deltachat-android
|
||||
```
|
||||
or
|
||||
```
|
||||
docker run -it --name deltachat -v $(pwd):/home/app:z -w /home/app localhost/deltachat-android
|
||||
```
|
||||
|
||||
You can leave the container with Ctrl+D or by typing `exit` and re-enter it with
|
||||
`docker start -ia deltachat` or `podman start -ia deltachat`.
|
||||
|
||||
Within the container, install toolchains and build the native library:
|
||||
```
|
||||
deltachat@6012dcb974fe:/home/app$ scripts/install-toolchains.sh
|
||||
deltachat@6012dcb974fe:/home/app$ scripts/ndk-make.sh
|
||||
```
|
||||
|
||||
Then, [build an APK](https://developer.android.com/studio/build/building-cmdline):
|
||||
```
|
||||
deltachat@6012dcb974fe:/home/app$ ./gradlew assembleDebug
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- Executing `./gradlew assembleDebug` inside the container fails with `The SDK directory '/home/user/Android/Sdk' does not exist.`:
|
||||
|
||||
The problem is that Android Studio (outside the container) automatically creates a file `local.properties` with a content like `sdk.dir=/home/username/Android/Sdk`,
|
||||
so, Gradle-inside-the-container looks for the Sdk at `/home/username/Android/Sdk`, where it can't find it.
|
||||
You could:
|
||||
- either: remove the file or just the line starting with `sdk.dir`
|
||||
- or: run `./gradlew assembleDebug` from outside the container (however, there may be incompatibility issues if different versions are installed inside and outside the container)
|
||||
|
||||
- Running the image fails with `ERRO[0000] The storage 'driver' option must be set in /etc/containers/storage.conf, guarantee proper operation.`:
|
||||
|
||||
In /etc/containers/storage.conf, replace the line: `driver = ""` with: `driver = "overlay"`.
|
||||
You can also set the `driver` option to something else, you just need to set it to _something_.
|
||||
[Read about possible options here](https://github.com/containers/storage/blob/master/docs/containers-storage.conf.5.md#storage-table).
|
||||
|
||||
## <a name="setup-podman"></a>Setup Podman
|
||||
|
||||
These instructions were only tested on a Manjaro machine so far. If anything doesn't work, please open an issue.
|
||||
|
||||
First, [Install Podman](https://podman.io/getting-started/installation).
|
||||
|
||||
Then, if you want to run Podman without root, run:
|
||||
```
|
||||
sudo touch /etc/subgid
|
||||
sudo touch /etc/subuid
|
||||
sudo usermod --add-subuids 165536-231072 --add-subgids 165536-231072 yourusername
|
||||
```
|
||||
(replace `yourusername` with your username).
|
||||
See https://wiki.archlinux.org/index.php/Podman#Rootless_Podman for more information.
|
||||
|
||||
## <a name="install-build-environment"></a>Install Build Environment (without Docker or Podman)
|
||||
|
||||
To setup build environment manually:
|
||||
- _Either_, in Android Studio, go to "Tools / SDK Manager / SDK Tools", enable "Show Package Details",
|
||||
select "CMake" and the desired NDK (install the same NDK version as the [Dockerfile](https://github.com/deltachat/deltachat-android/blob/master/Dockerfile)), hit "Apply".
|
||||
- _Or_ read [Dockerfile](https://github.com/deltachat/deltachat-android/blob/master/Dockerfile) and mimic what it does.
|
||||
|
||||
Then, in both cases, install Rust using [rustup](https://rustup.rs/)
|
||||
and Rust toolchains for cross-compilation by executing `scripts/install-toolchains.sh`.
|
||||
|
||||
Then, configure `ANDROID_NDK_ROOT` environment variable to point to the Android NDK
|
||||
installation directory e.g. by adding this to your `.bashrc`:
|
||||
|
||||
```bash
|
||||
export ANDROID_NDK_ROOT=${HOME}/Android/Sdk/ndk/[version] # (or wherever your NDK is) Note that there is no `/` at the end!
|
||||
export PATH=${PATH}:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/:${ANDROID_NDK_ROOT}
|
||||
```
|
||||
|
||||
After that, call `scripts/ndk-make.sh` in the root directory to build core-rust.
|
||||
Afterwards run the project in Android Studio. The project requires API 25.
|
||||
|
||||
With chance, that's it :) - if not, read on how to set up a proper development
|
||||
environment.
|
||||
|
||||
|
||||
## Install Development Environment
|
||||
|
||||
1. Some libs required by Android Studio may be missing on 64 bit Linux machines
|
||||
[Source](https://developer.android.com/studio/install.html)], so for Ubuntu execute
|
||||
`$ sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386`
|
||||
and for Fedora execute
|
||||
`$ sudo yum install zlib.i686 ncurses-libs.i686 bzip2-libs.i686`.
|
||||
|
||||
2. Download Android Studio from <https://developer.android.com> (android-studio-ide-...-linux.zip)
|
||||
and unpack the archive which contains a single folder called `android-studio`;
|
||||
move this folder e.g. to `~/android-studio`.
|
||||
|
||||
3. To launch Android Studio for the first time, open a terminal, navigate to
|
||||
`~/android-studio/bin`, execute `./studio.sh` and use all the standard values
|
||||
from the wizard.
|
||||
|
||||
4. Android Studio now asks you if you want to open an existing project;
|
||||
choose `~/deltachat-android` as created in the "Build" chapter (Android Studio starts to
|
||||
build the project, however, there are some steps missing before this will
|
||||
succeed).
|
||||
|
||||
5. If components are missing, click on the corresponding error
|
||||
message and install eg. required SDKs and the "Build-Tools" (you should
|
||||
also find the option at "Tools / Android / SDK Manager / SDK Platforms").
|
||||
Now the build should succeed - but the app still misses the native part.
|
||||
|
||||
6. Download Android NDK from
|
||||
[NDK Archives](https://developer.android.com/ndk/downloads)
|
||||
and extract the archive containing a single folder
|
||||
called something like `android-ndk-r23b-linux`; move this folder e.g. to `~/android-ndk`.
|
||||
|
||||
7. Export the folder path to your environment as `ANDROID_NDK_ROOT` and add it to `PATH`.
|
||||
You can achieve this e.g. by adding this to your `.bashrc`
|
||||
```bash
|
||||
export ANDROID_NDK_ROOT=${HOME}/android-ndk
|
||||
export PATH=${PATH}:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/:${ANDROID_NDK_ROOT}
|
||||
```
|
||||
|
||||
## Run UI Tests and Benchmarks
|
||||
|
||||
- You don't necessarily need a dedicated testing device.
|
||||
Backup your current account first, maybe there are some bugs in switching accounts.
|
||||
|
||||
- You can run benchmarks on either an emulated device or a real device.
|
||||
You need at least Android 9. For better benchmark results,
|
||||
you should run the benchmark on a real device and make sure that the core is compiled in release mode.
|
||||
|
||||
- Disable animations on your device, otherwise the test may fail:
|
||||
at "Developer options"
|
||||
set all of "Window animation scale", "Transition animation scale" and "Animator duration scale" to 0x
|
||||
|
||||
- In Android Studio: "File" / "Sync project with gradle files"
|
||||
|
||||
- In Android Studio: "Run" / "Edit configurations" / "+" / "Android Instrumented test":
|
||||
Either select a specific class or select "All in Module" / "OK" /
|
||||
Select your configuration in the toolbar / Click on the green "run" button in the toolbar to run the tests
|
||||
|
||||
### Get the benchmark results
|
||||
|
||||
When the benchmark is done, you will get a result like
|
||||
`MEASURED RESULTS (Benchmark) - Going thorough all 10 chats: 11635,11207,11363,11352,11279,11183,11137,11145,11032,11057`.
|
||||
You can paste `11635,11207,11363,11352,11279,11183,11137,11145,11032,11057`
|
||||
into a cell in a LibreOffice spreadsheet, do "Data" / "Text to columns",
|
||||
choose `,` as a separator, hit "OK", and create a diagram.
|
||||
|
||||
### Run online tests
|
||||
|
||||
For some tests, you need to provide the credentials to an actual email account.
|
||||
You have 2 ways to do this:
|
||||
|
||||
1. (Recommended): Put them into the file ~/.gradle/gradle.properties (create it if it doesn't exist):
|
||||
```
|
||||
TEST_ADDR=youraccount@yourdomain.org
|
||||
TEST_MAIL_PW=youpassword
|
||||
```
|
||||
|
||||
2. Or set them via environment variables.
|
||||
|
||||
## Decoding Symbols in Crash Reports
|
||||
|
||||
```
|
||||
$ANDROID_NDK_ROOT/ndk-stack --sym obj/local/armeabi-v7a --dump crash.txt > decoded.txt
|
||||
```
|
||||
|
||||
`obj/local/armeabi-v7a` is the extracted path from `deltachat-gplay-release-X.X.X.apk-symbols.zip` file from https://download.delta.chat/android/symbols/
|
||||
|
||||
Replace `armeabi-v7a` by the correct architecture the logs come from (can be guessed by trial and error)
|
||||
+50
-1
@@ -1,6 +1,55 @@
|
||||
# Delta Chat Android Changelog
|
||||
|
||||
## v2.22.0
|
||||
2025-10
|
||||
|
||||
* target Android 15
|
||||
* improve readability of info messages in dark mode
|
||||
* drop too short disappearing messages options
|
||||
* fix Direct Share shortcuts
|
||||
* fix: don't show error message when cancelling profile creation
|
||||
* enable permanent notification by default if push notifications are not available
|
||||
* hide "clone chat" and member list for incoming channels
|
||||
* show warning if background notifications will be unreliable
|
||||
* warn if the app has not been updated after 6 months instead of 1 year
|
||||
* avoid "unknown sender for this chat" error
|
||||
* properly display "Messages are end-to-end encrypted." in all encrypted groups
|
||||
* show dialog if user has permanently denied camera permission and tries to take picture for group avatar
|
||||
* several small fixes and improvements
|
||||
* add experimental built-in calls
|
||||
* update to core 2.22.0
|
||||
|
||||
## v2.11.0
|
||||
2025-08
|
||||
|
||||
* add "After 1 year" option to disappearing messages
|
||||
* improve image quality when setting group avatars
|
||||
* add Estonian translation, update other translations
|
||||
* allow to clone email chats
|
||||
* fix some small bugs
|
||||
* update to core 2.11.0
|
||||
|
||||
## v2.10.0
|
||||
2025-08
|
||||
|
||||
* fix "Archived" item's layout in chat-list
|
||||
* don't enlarge "Saved Messages" and "Devices Messages" avatars on click
|
||||
* share email address for email contacts instead of vCard
|
||||
* open existing encrypted chat when opening a mailto link or clicking an email address in a message bubble
|
||||
* update to core 2.10.0
|
||||
|
||||
## v2.9.0
|
||||
2025-07
|
||||
|
||||
* hide contact email addresses in search results
|
||||
* disable non-functional message editing and ephemeral messages timer settings in classic email thread chat
|
||||
* don't enlarge email chats avatar placeholder
|
||||
* improve message date/status footer layout, also in RTL languages
|
||||
* display correct text when receiving a "Disappearing messages enabled" system message
|
||||
* Update to core 2.9.0
|
||||
|
||||
## v2.8.0
|
||||
2025-07
|
||||
|
||||
* Profiles focus on recognizing contacts
|
||||
* See the number of media directly in the profile, no need to tap around
|
||||
@@ -12,7 +61,7 @@
|
||||
* New icon for the QR icon
|
||||
* Start rebuilding the experimental broadcast lists
|
||||
into proper channels - note that this is work-in-progress
|
||||
* Improved separation between unencryted chats/contacts and encrypted ones, avoiding mixing of encrypted and unencrypted messages in the same chat
|
||||
* Improved separation between unencrypted chats/contacts and encrypted ones, avoiding mixing of encrypted and unencrypted messages in the same chat
|
||||
* Removed padlocks, as encrypted is the default "normal" state. Instead, unencrypted email is marked with a small email / letter (✉️) icon
|
||||
* Classic email chats/threads get a big email / letter icon making it easy to recognize
|
||||
* After some time, add a device message asking to donate. Can't wait? Donate today at https://delta.chat/donate
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ Some rough ideas, that may be helpful when thinking about how to enhance things:
|
||||
|
||||
## Contributing Code
|
||||
|
||||
The [README](./README.md) explains in detail how to set up the build environment.
|
||||
The [BUILDING.md](./BUILDING.md) file explains in detail how to set up the build environment.
|
||||
Please follow all steps precisely.
|
||||
If you run into troubles,
|
||||
ask on one of the [communication channels](https://delta.chat/contribute) for help.
|
||||
|
||||
+25
-31
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id 'com.android.application' version '8.5.2'
|
||||
id 'com.android.application' version '8.11.1'
|
||||
id 'com.google.gms.google-services' version '4.4.1'
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ android {
|
||||
}
|
||||
namespace "org.thoughtcrime.securesms"
|
||||
flavorDimensions "none"
|
||||
compileSdk 34
|
||||
compileSdk 35
|
||||
|
||||
// Set NDK version to strip native libraries.
|
||||
// Even though we compile our libraries outside Gradle with `scripts/ndk-make.sh`,
|
||||
@@ -33,14 +33,14 @@ android {
|
||||
useLibrary 'org.apache.http.legacy'
|
||||
|
||||
defaultConfig {
|
||||
versionCode 30000726
|
||||
versionName "2.8.0"
|
||||
versionCode 30000730
|
||||
versionName "2.22.0"
|
||||
|
||||
applicationId "chat.delta.lite"
|
||||
multiDexEnabled true
|
||||
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 34
|
||||
targetSdkVersion 35
|
||||
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
@@ -209,9 +209,9 @@ dependencies {
|
||||
implementation 'com.airbnb.android:lottie:4.2.2' // Lottie animations support.
|
||||
|
||||
implementation 'androidx.sharetarget:sharetarget:1.2.0'
|
||||
implementation 'androidx.webkit:webkit:1.12.1'
|
||||
implementation 'androidx.webkit:webkit:1.14.0'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.7.1'
|
||||
implementation 'com.google.android.material:material:1.12.0'
|
||||
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
|
||||
implementation ('androidx.preference:preference:1.2.1') {
|
||||
@@ -219,7 +219,7 @@ dependencies {
|
||||
exclude group: 'androidx.lifecycle', module:'lifecycle-viewmodel-ktx'
|
||||
}
|
||||
implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.7'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.4.1'
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-common-java8:2.6.2'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.6.2'
|
||||
@@ -233,52 +233,46 @@ dependencies {
|
||||
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
|
||||
implementation 'com.google.code.gson:gson:2.12.1' // used as JSON library.
|
||||
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.Baseflow:PhotoView:2.3.0' // does the zooming on photos / media
|
||||
implementation 'com.github.penfeizhou.android.animation:awebp:3.0.2' // 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'
|
||||
implementation 'com.github.bumptech.glide:glide:4.16.0'
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
|
||||
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.makeramen:roundedimageview:2.3.0' // crops the avatars to circles
|
||||
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
|
||||
implementation ('com.davemorrissey.labs:subsampling-scale-image-view:3.6.0') { // for the zooming on photos / media
|
||||
implementation ('com.davemorrissey.labs:subsampling-scale-image-view:3.10.0') { // for the zooming on photos / media
|
||||
exclude group: 'com.android.support', module: 'support-annotations'
|
||||
}
|
||||
implementation 'com.annimon:stream:1.1.8' // brings future java streams api to SDK Version < 24
|
||||
|
||||
// Replacement for ContentResolver
|
||||
// that protects against the Surreptitious Sharing attack.
|
||||
// <https://github.com/cketti/SafeContentResolver>
|
||||
implementation 'de.cketti.safecontentresolver:safe-content-resolver-v21:1.0.0'
|
||||
|
||||
gplayImplementation('com.google.firebase:firebase-messaging:24.1.0') { // for PUSH notifications
|
||||
gplayImplementation('com.google.firebase:firebase-messaging:24.1.2') { // for PUSH notifications, don't upgrade: v25.0.0 requires minSdk>=23
|
||||
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'
|
||||
}
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.assertj:assertj-core:1.7.1'
|
||||
testImplementation 'org.mockito:mockito-core:1.9.5'
|
||||
testImplementation 'org.powermock:powermock-api-mockito:1.6.1'
|
||||
testImplementation 'org.powermock:powermock-module-junit4:1.6.1'
|
||||
testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.1'
|
||||
testImplementation 'org.powermock:powermock-classloading-xstream:1.6.1'
|
||||
testImplementation 'org.assertj:assertj-core:3.27.3'
|
||||
testImplementation 'org.mockito:mockito-core:5.18.0'
|
||||
testImplementation 'org.powermock:powermock-api-mockito:1.7.4'
|
||||
testImplementation 'org.powermock:powermock-module-junit4:2.0.9'
|
||||
testImplementation 'org.powermock:powermock-module-junit4-rule:2.0.9'
|
||||
testImplementation 'org.powermock:powermock-classloading-xstream:2.0.9'
|
||||
|
||||
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'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
|
||||
androidTestImplementation 'androidx.test:runner:1.7.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.7.0'
|
||||
androidTestImplementation 'androidx.test:rules:1.7.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.3.0'
|
||||
androidTestImplementation 'com.android.support:support-annotations:28.0.0'
|
||||
|
||||
androidTestImplementation ('org.assertj:assertj-core:1.7.1') {
|
||||
androidTestImplementation ('org.assertj:assertj-core:3.27.3') {
|
||||
exclude group: 'org.hamcrest', module: 'hamcrest-core'
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+15
-15
@@ -7,11 +7,11 @@
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1733948466,
|
||||
"narHash": "sha256-o/uq/tU458Ykudi8Zk3sRga5iazkuSczt9wDOCUDOSU=",
|
||||
"lastModified": 1756239746,
|
||||
"narHash": "sha256-0ibN685tT+u/Nbmbrrq9G3mRUzct2Votyv/a7Wwv26s=",
|
||||
"owner": "tadfisher",
|
||||
"repo": "android-nixpkgs",
|
||||
"rev": "0bf99ffaea6a7c0948ae10cf2e40c2905e4e4d6b",
|
||||
"rev": "256631d162ec883b2341ee59621516e1f65f0f6b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -28,11 +28,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1728330715,
|
||||
"narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=",
|
||||
"lastModified": 1741473158,
|
||||
"narHash": "sha256-kWNaq6wQUbUMlPgw8Y+9/9wP0F8SHkjy24/mN3UAppg=",
|
||||
"owner": "numtide",
|
||||
"repo": "devshell",
|
||||
"rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef",
|
||||
"rev": "7c9e793ebe66bcba8292989a68c0419b737a22a0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -79,11 +79,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1733759999,
|
||||
"narHash": "sha256-463SNPWmz46iLzJKRzO3Q2b0Aurff3U1n0nYItxq7jU=",
|
||||
"lastModified": 1756125398,
|
||||
"narHash": "sha256-XexyKZpf46cMiO5Vbj+dWSAXOnr285GHsMch8FBoHbc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a73246e2eef4c6ed172979932bc80e1404ba2d56",
|
||||
"rev": "3b9f00d7a7bf68acd4c4abb9d43695afb04e03a5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -95,11 +95,11 @@
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1733749988,
|
||||
"narHash": "sha256-+5qdtgXceqhK5ZR1YbP1fAUsweBIrhL38726oIEAtDs=",
|
||||
"lastModified": 1756159630,
|
||||
"narHash": "sha256-ohMvsjtSVdT/bruXf5ClBh8ZYXRmD4krmjKrXhEvwMg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "bc27f0fde01ce4e1bfec1ab122d72b7380278e68",
|
||||
"rev": "84c256e42600cb0fdf25763b48d28df2f25a0c8b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -138,11 +138,11 @@
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1747017456,
|
||||
"narHash": "sha256-C/U12fcO+HEF071b5mK65lt4XtAIZyJSSJAg9hdlvTk=",
|
||||
"lastModified": 1756197489,
|
||||
"narHash": "sha256-S16rPaBH1TnMbDyL5NlGSJcYd7wPlOEWTStdBDL7BHw=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "5b07506ae89b025b14de91f697eba23b48654c52",
|
||||
"rev": "8ec04f46f1edeeed3f870da62191745b93975da7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
pkgs = import nixpkgs { inherit system overlays; };
|
||||
android-sdk = android.sdk.${system} (sdkPkgs:
|
||||
with sdkPkgs; [
|
||||
build-tools-34-0-0
|
||||
build-tools-35-0-0
|
||||
cmdline-tools-latest
|
||||
platform-tools
|
||||
platforms-android-34
|
||||
platforms-android-35
|
||||
ndk-27-2-12479018
|
||||
]);
|
||||
rust-version = pkgs.lib.removeSuffix "\n"
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
distributionSha256Sum=20f1b1176237254a6fc204d8434196fa11a4cfb387567519c61556e8710aed78
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -735,12 +735,6 @@ JNIEXPORT jint Java_com_b44t_messenger_DcContext_sendTextMsg(JNIEnv *env, jobjec
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcContext_sendVideochatInvitation(JNIEnv *env, jobject obj, jint chat_id)
|
||||
{
|
||||
return (jint)dc_send_videochat_invitation(get_dc_context(env, obj), chat_id);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_sendWebxdcStatusUpdate(JNIEnv *env, jobject obj, jint msg_id, jstring payload)
|
||||
{
|
||||
CHAR_REF(payload);
|
||||
@@ -1608,21 +1602,6 @@ JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getSetupCodeBegin(JNIEnv *env, j
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getVideochatUrl(JNIEnv *env, jobject obj)
|
||||
{
|
||||
char* temp = dc_msg_get_videochat_url(get_dc_msg(env, obj));
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
dc_str_unref(temp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcMsg_getVideochatType(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jint)dc_msg_get_videochat_type(get_dc_msg(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcMsg_setSubject(JNIEnv *env, jobject obj, jstring text)
|
||||
{
|
||||
CHAR_REF(text);
|
||||
|
||||
+1
-1
Submodule jni/deltachat-core-rust updated: 9c68a91f41...73db91266e
Vendored
+5
-9
@@ -1,15 +1,11 @@
|
||||
# native methods
|
||||
-keep class com.b44t.messenger.** { * ; }
|
||||
|
||||
# Gson uses generic type information stored in a class file when working with
|
||||
# fields. Proguard removes such information by default, keep it.
|
||||
-keepattributes Signature
|
||||
# This is also needed for R8 in compat mode since multiple
|
||||
# optimizations will remove the generic signature such as class
|
||||
# merging and argument removal. See:
|
||||
# https://r8.googlesource.com/r8/+/refs/heads/main/compatibility-faq.md#troubleshooting-gson-gson
|
||||
-keep class com.google.gson.reflect.TypeToken { *; }
|
||||
-keep class * extends com.google.gson.reflect.TypeToken
|
||||
# Keep metadata needed by the JSON parser
|
||||
-keep class chat.delta.rpc.** { * ; }
|
||||
-keepattributes *Annotation*,EnclosingMethod,Signature
|
||||
-keepnames class com.fasterxml.jackson.** { *; }
|
||||
#-dontwarn com.fasterxml.jackson.databind.**
|
||||
|
||||
# bug with video recoder
|
||||
-keep class com.coremedia.iso.** { *; }
|
||||
|
||||
@@ -370,7 +370,7 @@
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
|
||||
</activity>
|
||||
|
||||
<activity android:name=".videochat.VideochatActivity"
|
||||
<activity android:name=".calls.CallActivity"
|
||||
android:label=""
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize|uiMode"
|
||||
@@ -436,6 +436,14 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".notifications.DeclineCallReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="org.thoughtcrime.securesms.notifications.DECLINE_CALL_NOTICED"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".notifications.RemoteReplyReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="false">
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#jaká-oprávnění-delta-chat-potřebuje">Jaká oprávnění Delta Chat potřebuje?</a></li>
|
||||
<li><a href="#pracuje-delta-chat-s-mým-poskytovatelem-e-mailu">Pracuje Delta Chat s <em>mým</em> poskytovatelem e-mailu?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</a></li>
|
||||
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
|
||||
<li><a href="#proč-musím-delta-chatu-zadat-mé-e-mailové-heslo-je-to-bezpečné">Proč musím Delta Chatu zadat mé e-mailové heslo? Je to bezpečné?</a></li>
|
||||
<li><a href="#jaké-zprávy-delta-chat-zobrazuje">Jaké zprávy Delta Chat zobrazuje?</a></li>
|
||||
@@ -407,7 +408,7 @@ who could have already replied, forwarded, saved, screenshotted or otherwise cop
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 1 minute and 5 weeks.</p>
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Until the setting is turned off again,
|
||||
each chat member’s Delta Chat app takes care
|
||||
@@ -780,8 +781,8 @@ there are no lock or similar markers on end-to-end encrypted messages, anymore.<
|
||||
it is impossible to receive or send messages without end-to-end encryption.</p>
|
||||
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages without end-to-end encryption.
|
||||
Such messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
@@ -1621,6 +1622,29 @@ Nicméně, někteří poskytovatelé vyžadují ke správnému chodu speciální
|
||||
podrobnější popis je na <a href="https://providers.delta.chat">Provider Overview</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">
|
||||
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#welche-app-berechtigungen-benötigt-delta-chat">Welche App-Berechtigungen benötigt Delta Chat?</a></li>
|
||||
<li><a href="#funktioniert-delta-chat-mit-meinem-e-mail-anbieter">Funktioniert Delta Chat mit <em>meinem</em> E-Mail-Anbieter?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</a></li>
|
||||
<li><a href="#ich-möchte-meinen-eigenen-server-für-delta-chat-verwalten-gibt-es-empfehlungen">Ich möchte meinen eigenen Server für Delta Chat verwalten. Gibt es Empfehlungen?</a></li>
|
||||
<li><a href="#weshalb-muss-ich-mein-e-mail-kennwort-in-delta-chat-eingeben-ist-das-sicher">Weshalb muss ich mein E-Mail-Kennwort in Delta Chat eingeben? Ist das sicher?</a></li>
|
||||
<li><a href="#welche-nachrichten-erscheinen-in-delta-chat">Welche Nachrichten erscheinen in Delta Chat?</a></li>
|
||||
@@ -389,10 +390,11 @@ die die Nachricht bereits beantwortet, weitergeleitet, gespeichert, mit einem Sc
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Sie schalten “Verschwindende Nachrichten”
|
||||
oben rechts im Chatfenster,
|
||||
durch Auswahl einer Zeitspanne
|
||||
zwischen 1 Minute und 5 Wochen ein.</p>
|
||||
<p>You can turn on “disappearing messages”
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Bis die Einstellung wieder ausgeschaltet wird,
|
||||
kümmern sich die Delta-Chat-Apps der Chat-Teilnehmer
|
||||
@@ -694,26 +696,23 @@ Willkommen bei der Macht des interoperablen und massiven Chatmail- und E-Mail-Sy
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat uses a <a href="#openpgp-secure">secure subset of the OpenPGP standard</a>
|
||||
to provide automatic end-to-end encryption using these protocols:</p>
|
||||
<p>Delta Chat verwendet eine <a href="#openpgp-secure">sichere Teilmenge des OpenPGP-Standards</a>, um eine automatische End-to-End-Verschlüsselung mit folgenden Protokollen bereitzustellen:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p><a href="https://securejoin.delta.chat/en/latest/new.html">Secure-Join</a>
|
||||
to exchange encryption setup information through QR-code scanning or “invite links”.</p>
|
||||
zum Austausch von Verschlüsselungsinformationen durch Scannen von QR-Codes oder „Einladungslinks“.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="https://autocrypt.org">Autocrypt</a> is used for automatically
|
||||
establishing end-to-end encryption between contacts and all members of a group chat.</p>
|
||||
<p><a href="https://autocrypt.org">Autocrypt</a> wird verwendet, um automatisch eine Ende-zu-Ende-Verschlüsselung zwischen Kontakten und allen Mitgliedern einer Gruppe herzustellen.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Sharing a contact to a
|
||||
chat</a>
|
||||
enables receivers to use end-to-end encryption with the contact.</p>
|
||||
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Teilen eines Kontakts im Chat</a>
|
||||
ermöglicht es den Empfängern, eine Ende-zu-Ende-Verschlüsselung mit dem Kontakt zu verwenden.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Delta Chat does not query, publish or interact with any OpenPGP key servers.</p>
|
||||
<p>Delta Chat fragt keine OpenPGP-Keyserver ab, veröffentlicht dort keine Daten und interagiert auch sonst nicht mit diesen.</p>
|
||||
|
||||
<h3 id="whene2e">
|
||||
|
||||
@@ -723,9 +722,8 @@ enables receivers to use end-to-end encryption with the contact.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>All messages in Delta Chat are <strong>end-to-end encrypted by default</strong>.
|
||||
Since the Delta Chat Version 2 release series (July 2025)
|
||||
there are no lock or similar markers on end-to-end encrypted messages, anymore.</p>
|
||||
<p>Alle Nachrichten in Delta Chat sind <strong>standardmäßig Ende-zu-Ende-verschlüsselt</strong>.
|
||||
Seit der Veröffentlichung von Delta Chat Version 2 (Juli 2025) gibt es keine Schlösser oder ähnliche Markierungen mehr an Ende‑zu‑Ende-verschlüsselten Nachrichten.</p>
|
||||
|
||||
<h3 id="kann-ich-e-mails-ohne-ende-zu-ende-verschlüsselung-empfangen-oder-senden">
|
||||
|
||||
@@ -737,9 +735,9 @@ there are no lock or similar markers on end-to-end encrypted messages, anymore.<
|
||||
|
||||
<p>Wenn Sie die Standard-<a href="https://chatmail.at/relays">Chatmail-Relays</a> verwenden, ist es unmöglich, Nachrichten ohne End-to-End-Verschlüsselung zu empfangen oder zu senden.</p>
|
||||
|
||||
<p>Wenn Sie stattdessen ein Profil mit einem klassischen E-Mail-Server erstellen,
|
||||
können Sie Nachrichten ohne End-to-End-Verschlüsselung senden und empfangen.
|
||||
Solche Nachrichten werden mit einem E-Mail-Symbol gekennzeichnet
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
@@ -750,9 +748,9 @@ Solche Nachrichten werden mit einem E-Mail-Symbol gekennzeichnet
|
||||
|
||||
</h3>
|
||||
|
||||
<p>You can send an invite link through another private chat,
|
||||
show an invitation QR code when next to each other or in a video call,
|
||||
or click on a “contact” that was shared in a chat.</p>
|
||||
<p>Man kann einen Einladungslink über einen anderen privaten Chat senden,
|
||||
einen Einladungs-QR-Code zeigen, wenn man nebeneinander steht oder einen Videoanruf tätigen,
|
||||
oder auf einen “Kontakt” klicken der per Chat geteilt wurde.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
@@ -761,35 +759,35 @@ tippen Sie auf den Titel der Gruppe, um die Mitgliederliste anzuzeigen,
|
||||
und wählen Sie „QR-Einladungscode“.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>For <strong>direct 1:1 chat invitations</strong>,
|
||||
tap the QR Code icon <img style="vertical-align:middle; width:1.8em; margin:1px" src="../qr-icon.png" />
|
||||
on the Delta Chat app main screen.</p>
|
||||
<p>Für <strong>direkte 1:1-Chat-Einladungen</strong>,
|
||||
tippt man auf das QR-Code-Symbol <img style="vertical-align:middle; width:1.8em; margin:1px" src="../qr-icon.png" />
|
||||
auf dem Hauptbildschirm der Delta-Chat-App.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Ask your chat partner to scan the QR image
|
||||
with their Delta Chat app,
|
||||
or click “Copy” or “Share” to create an invite link
|
||||
and share it with your chat partner.</p>
|
||||
<p>Man kann seinen Chat-Partner bitten, denn QR-Code
|
||||
mit seiner Delta Chat-App zu scannen,
|
||||
oder auf “Kopieren” oder “Teilen” drücken, um einen Einladungslink zu erstellen
|
||||
und diesen mit seinem Chat-Partner zu teilen.</p>
|
||||
|
||||
<p>Now wait while <a href="https://securejoin.delta.chat/en/latest/new.html#setup-contact-protocol">end-to-end encryption is getting established</a>.</p>
|
||||
<p>Nun wartet man, während die <a href="https://securejoin.delta.chat/en/latest/new.html#setup-contact-protocol">Ende-zu-Ende-Verschlüsselung eingerichtet wird</a>.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>If both sides are online, they will soon see a (group or direct) chat
|
||||
and can start messaging securely.</p>
|
||||
<p>Wenn beide Seiten online sind, sehen sie bald einen (Gruppen- oder direkten) Chat
|
||||
und können mit der sicheren Nachrichtenübermittlung beginnen.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If one side is offline or in bad network,
|
||||
the ability to chat is delayed until connectivity is restored.</p>
|
||||
<p>Wenn eine Seite offline ist oder eine schlechte Verbindung hat,
|
||||
wird die Möglichkeit zu chatten verzögert, bis die Verbindung wiederhergestellt ist.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Congratulations!
|
||||
You now will automatically use end-to-end encryption
|
||||
with this contact.
|
||||
If you add each other to chat groups,
|
||||
end-to-end encryption will be established among all members.</p>
|
||||
<p>Glückwunsch!
|
||||
Du verwenden jetzt automatisch eine Ende-zu-Ende-Verschlüsselung
|
||||
mit diesem Kontakt.
|
||||
Wenn man sich gegenseitig zu Chatgruppen hinzufügt,
|
||||
wird eine Ende-zu-Ende-Verschlüsselung zwischen allen Mitgliedern eingerichtet.</p>
|
||||
|
||||
<h3 id="e2eeguarantee">
|
||||
|
||||
@@ -838,9 +836,9 @@ und Anhang-Metadaten wie Dateinamen.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, Delta Chat uses a secure subset of OpenPGP
|
||||
requiring the whole message to be properly encrypted and signed.
|
||||
For example, “Detached signatures” are not treated as secure.</p>
|
||||
<p>Ja, Delta Chat verwendet ein sicheres subset von OpenPGP
|
||||
das verlangt, dass die gesamte Nachricht ordnungsgemäß verschlüsselt und signiert wurde.
|
||||
Als Beispiel, werden “angehängte Signaturen” nicht als sicher behandelt.</p>
|
||||
|
||||
<p>Die meisten öffentlich diskutierten OpenPGP-Probleme
|
||||
resultieren in Wirklichkeit aus schlechter Usability oder schlechter Implementierung von Tools oder Anwendungen - oder beidem.
|
||||
@@ -906,10 +904,11 @@ so wie in der Autocrypt-Level-1-Spezifikation definiert.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>If you are sending or receiving e-mail messages without end-to-end encryption (using a classic e-mail server),
|
||||
they are still protected from cell or cable companies who can not read or modify your e-mail messages.
|
||||
But both your and your recipient’s e-mail providers
|
||||
may read, analyze or modify your messages, including any attachments.</p>
|
||||
<p>Wenn Sie E-Mail-Nachrichten ohne Ende-zu-Ende-Verschlüsselung senden oder empfangen (mit einem klassischen E-Mail-Server),
|
||||
sind sie immer noch vor Mobilfunkanbietern oder Kabelnetzbetreibern geschützt, die Ihre E-Mail-Nachrichten nicht lesen oder verändern können.</p>
|
||||
|
||||
<p>Aber sowohl Ihr E-Mail-Anbieter als auch der E-Mail-Anbieter des Empfängers
|
||||
können Ihre Nachrichten, einschließlich aller Anhänge, lesen, analysieren oder verändern.</p>
|
||||
|
||||
<p>Delta Chat verwendet standardmäßig strikte
|
||||
<a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">TLS-Verschlüsselung</a>,
|
||||
@@ -948,7 +947,7 @@ Stattdessen werden alle Gruppen-Metadaten durchgängig verschlüsselt und aussch
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
||||
<p>Alle anderen Metadaten zu Nachrichten, Kontakten und Gruppen befinden sich im Ende-zu-Ende-verschlüsselten Teil der Nachrichten.</p>
|
||||
|
||||
<h3 id="device-seizure">
|
||||
|
||||
@@ -976,12 +975,12 @@ can not be identified easily.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>No, not yet.</p>
|
||||
<p>Nein, noch nichts.</p>
|
||||
|
||||
<p>The Signal messenger introduced <a href="https://signal.org/blog/sealed-sender/">“Sealed Sender” in 2018</a>
|
||||
to keep their server infrastructure ignorant of who is sending a message to a set of recipients.
|
||||
It is particularly important because the Signal server knows the mobile number of each account,
|
||||
which is usually associated with a passport identity.</p>
|
||||
<p>Der Signal-Messenger führte 2018 <a href="https://signal.org/blog/sealed-sender/">“Sealed Sender”</a> ein
|
||||
um seine Serverinfrastruktur darüber im Unklaren zu lassen, wer eine Nachricht an eine Gruppe von Empfängern sendet.
|
||||
Dies ist besonders wichtig, weil der Signal-Server die Handynummer jedes Kontos kennt,
|
||||
die in der Regel mit einer Passidentität verbunden ist.</p>
|
||||
|
||||
<p>Even if <a href="https://chatmail.at/relays">chatmail relays</a>
|
||||
do not ask for any private data (including no phone numbers),
|
||||
@@ -997,7 +996,7 @@ but an implementation has not been agreed as a priority yet.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>No, not yet.</p>
|
||||
<p>Nein, noch nichts.</p>
|
||||
|
||||
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||
This means that if your private decryption key is leaked,
|
||||
@@ -1023,12 +1022,11 @@ which would make it available in all <a href="https://chatmail.at/clients">chatm
|
||||
|
||||
</h3>
|
||||
|
||||
<p>No, not yet.</p>
|
||||
<p>Nein, noch nichts.</p>
|
||||
|
||||
<p>Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
||||
We aim to add PQC support in <a href="https://github.com/chatmail/core">chatmail core</a> after the draft is finalized at the IETF
|
||||
in collaboration with other OpenPGP implementers.</p>
|
||||
<p>Delta Chat verwendet die Rust OpenPGP-Bibliothek <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||
die den neuesten <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP Entwurf</a> unterstützt.
|
||||
Wir beabsichtigen, PQC-Unterstützung zum <a href="https://github.com/chatmail/core">chatmail core</a> hinzuzufügen, sobald der Entwurf bei der IETF in Zusammenarbeit mit anderen OpenPGP-Implementierern fertiggestellt ist.</p>
|
||||
|
||||
<h3 id="wie-kann-ich-die-verschlüsselung-manuell-überprüfen">
|
||||
|
||||
@@ -1379,10 +1377,10 @@ forum</a> veröffentlicht und diskutiert.</li>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Note:
|
||||
Changing email addresses is temporarily disabled
|
||||
because of ongoing changes to the DeltaChat core.
|
||||
It should be available again in a few months.</p>
|
||||
<p>Anmerkung:
|
||||
Das Ändern von E-Mail-Adressen ist vorübergehend deaktiviert
|
||||
wegen laufender Änderungen am DeltaChat-Core.
|
||||
Es sollte in ein paar Monaten wieder verfügbar sein.</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
@@ -1482,6 +1480,29 @@ gesendet haben, Nachrichten an Ihre neue Adresse senden.</p>
|
||||
Allerdings benötigen einige Anbieter besondere Einstellungen, um ordnungsgemäß zu funktionieren; eine von NutzerInnen erstellte Sammlung zu einigen Optionen findet sich unter <a href="https://providers.delta.chat">Provider Overview</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="ich-möchte-meinen-eigenen-server-für-delta-chat-verwalten-gibt-es-empfehlungen">
|
||||
|
||||
|
||||
@@ -1491,10 +1512,10 @@ Allerdings benötigen einige Anbieter besondere Einstellungen, um ordnungsgemä
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>Most mail servers will work well. But what we personally recommend is a
|
||||
chatmail relay server, as described <a href="https://delta.chat/en/2023-12-13-chatmail">in this
|
||||
blogpost</a>.</li>
|
||||
<li>You can find an <a href="https://github.com/chatmail/relay">installation guide on GitHub</a>.</li>
|
||||
<li>Die meisten Mailserver werden gut funktionieren. Aber wir persönlich empfehlen ein
|
||||
Chatmail-Relay-Server, wie er <a href="https://delta.chat/en/2023-12-13-chatmail">in diesem
|
||||
Blogpost</a> beschrieben wird.</li>
|
||||
<li>Man kann eine <a href="https://github.com/chatmail/relay">Installationsanleitung auf GitHub</a> finden.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="weshalb-muss-ich-mein-e-mail-kennwort-in-delta-chat-eingeben-ist-das-sicher">
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#which-permissions-does-delta-chat-need">Which permissions does Delta Chat need?</a></li>
|
||||
<li><a href="#does-delta-chat-work-with-my-e-mail-provider">Does Delta Chat work with <em>my</em> e-mail-provider?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</a></li>
|
||||
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
|
||||
<li><a href="#why-do-i-have-to-enter-my-e-mail-password-into-delta-chat-is-this-secure">Why do I have to enter my E-Mail password into Delta Chat? Is this secure?</a></li>
|
||||
<li><a href="#which-messages-do-appear-in-delta-chat">Which messages do appear in Delta Chat?</a></li>
|
||||
@@ -411,7 +412,7 @@ who could have already replied, forwarded, saved, screenshotted or otherwise cop
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 1 minute and 5 weeks.</p>
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Until the setting is turned off again,
|
||||
each chat member’s Delta Chat app takes care
|
||||
@@ -784,8 +785,8 @@ there are no lock or similar markers on end-to-end encrypted messages, anymore.<
|
||||
it is impossible to receive or send messages without end-to-end encryption.</p>
|
||||
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages without end-to-end encryption.
|
||||
Such messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
@@ -1626,6 +1627,29 @@ However, some providers need special options to work properly,
|
||||
see <a href="https://providers.delta.chat">Provider Overview</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<li><a href="#qué-significa-fijar-mutear-archivar">¿Qué significa fijar, mutear, archivar?</a></li>
|
||||
<li><a href="#save">¿Cómo funcionan los “Mensajes guardados”?</a></li>
|
||||
<li><a href="#qué-significa-el-punto-verde">¿Qué significa el punto verde?</a></li>
|
||||
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
||||
<li><a href="#edit">Corregir errores y borrar mensajes después de enviar</a></li>
|
||||
<li><a href="#ephemeralmsgs">¿Cómo funciona la desaparición de mensajes?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -27,12 +27,12 @@
|
||||
<li><a href="#delold">¿Qué pasa si activo “Borrar mensajes del dispositivo”?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#instant-delivery">Instant message delivery and Push Notifications</a>
|
||||
<li><a href="#instant-delivery">Entrega de mensajes instantáneos y notificaciones Push</a>
|
||||
<ul>
|
||||
<li><a href="#what-are-push-notifications-how-can-i-get-instant-message-delivery">What are Push Notifications? How can I get instant message delivery?</a></li>
|
||||
<li><a href="#are-push-notifications-enabled-on-ios-devices-is-there-an-alternative">Are Push Notifications enabled on iOS devices? Is there an alternative?</a></li>
|
||||
<li><a href="#android-push">Are Push notifications enabled / needed on Android devices?</a></li>
|
||||
<li><a href="#privacy-notifications">How private are Delta Chat Push Notifications?</a></li>
|
||||
<li><a href="#qué-son-las-notificaciones-push-cómo-puedo-recibir-mensajes-instantáneos">¿Qué son las Notificaciones Push? ¿Cómo puedo recibir mensajes instantáneos?</a></li>
|
||||
<li><a href="#están-activadas-las-notificaciones-push-en-los-dispositivos-ios-existe-alguna-alternativa">¿Están activadas las notificaciones Push en los dispositivos iOS? ¿Existe alguna alternativa?</a></li>
|
||||
<li><a href="#android-push">¿Están habilitadas / son necesarias las notificaciones Push en los dispositivos Android?</a></li>
|
||||
<li><a href="#privacy-notifications">¿Qué privadas son las notificaciones push de Delta Chat?</a></li>
|
||||
<li><a href="#why-does-delta-chat-integrate-with-centralized-proprietary-applegoogle-push-services">Why does Delta Chat integrate with centralized proprietary Apple/Google push services?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -41,7 +41,7 @@
|
||||
<li><a href="#qué-estándares-se-utilizan-para-el-cifrado-de-extremo-a-extremo">¿Qué estándares se utilizan para el cifrado de extremo a extremo?</a></li>
|
||||
<li><a href="#whene2e">¿Cómo puedo saber si los mensajes están cifrados de extremo a extremo?</a></li>
|
||||
<li><a href="#can-i-still-receive-or-send-mails-without-end-to-end-encryption">Can i still receive or send mails without end-to-end encryption?</a></li>
|
||||
<li><a href="#howtoe2ee">How can I establish a chat with a new contact?</a></li>
|
||||
<li><a href="#howtoe2ee">¿Cómo puedo establecer un chat con un nuevo contacto?</a></li>
|
||||
<li><a href="#e2eeguarantee">What does the green checkmark in a contact profile mean?</a></li>
|
||||
<li><a href="#los-adjuntos-imágenes-archivos-audio-etc-están-cifrados-de-extremo-a-extremo">¿Los adjuntos (imágenes, archivos, audio, etc.) están cifrados de extremo a extremo?</a></li>
|
||||
<li><a href="#openpgp-secure">¿Es OpenPGP seguro?</a></li>
|
||||
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#qué-permisos-necesita-delta-chat">¿Qué permisos necesita Delta Chat?</a></li>
|
||||
<li><a href="#delta-chat-funciona-con-mi-proveedor-de-correo-electrónico">¿Delta Chat funciona con <em>mi</em> proveedor de correo electrónico?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</a></li>
|
||||
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
|
||||
<li><a href="#por-qué-debo-ingresar-mi-contraseña-de-correo-electrónico-en-delta-chat-es-esto-seguro">¿Por qué debo ingresar mi contraseña de correo electrónico en Delta Chat? ¿Es esto seguro?</a></li>
|
||||
<li><a href="#qué-mensajes-se-muestran-en-delta-chat">¿Qué mensajes se muestran en Delta Chat?</a></li>
|
||||
@@ -215,18 +216,16 @@ Basado en <a href="https://github.com/chatmail/core/blob/main/standards.md#stand
|
||||
|
||||
</h3>
|
||||
|
||||
<p>A profile is <strong>a name, a picture</strong> and some additional information for encrypting messages.
|
||||
A profile lives on your device(s) only
|
||||
and uses a chatmail or a classic e-mail server to transport messages.</p>
|
||||
<p>Un perfil es <strong>un nombre, una foto</strong> y algunas informaciones adicionales para encriptar los mensajes.
|
||||
Un perfil solo existe dentro de tu dispositivo(s)
|
||||
y utilice un servidor de chatmail o correo electrónico clásico para el transporte de los mensajes.</p>
|
||||
|
||||
<p>En la primera instalación de Delta Chat se crea un primer perfil.</p>
|
||||
|
||||
<p>Después, puedes tocar la imagen de tu perfil en la esquina superior izquierda para <strong>Añadir perfiles</strong>
|
||||
o para <strong>Cambiar perfiles</strong>.</p>
|
||||
|
||||
<p>You may want to use separate profiles for political, family or work related activities,
|
||||
or e. g. for a dedicated “spam-profile” with which you register at websites and platforms
|
||||
that tend to cause unsolicited messages (“spam”) sooner or later.</p>
|
||||
<p>Se podría considerar la utilización de perfiles diferenciados para actividades vinculadas con políticas, familia o trabajo, o para un perfil dedicado a “spam”, que podría ser utilizado para páginas web y plataformas que tendrán la capacidad de generar mensajes no solicitados.</p>
|
||||
|
||||
<p>Quizás quieres aprender <a href="#multiclient">cómo se usa el mismo perfil en múltiples dispositivos</a>.</p>
|
||||
|
||||
@@ -265,11 +264,11 @@ dispositivo.</p>
|
||||
|
||||
</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>Sí,
|
||||
es posible hacerlo en “Ajustes → Perfil → Texto de firma”.
|
||||
Los contactos que usan Delta Chat podrán ver
|
||||
si revisan los detalles de tu perfil.<br />
|
||||
Además, se encontrará en la firma de correos electrónicos clásicos.</p>
|
||||
|
||||
<h3 id="qué-significa-fijar-mutear-archivar">
|
||||
|
||||
@@ -326,15 +325,15 @@ Con pulsar a <img style="vertical-align:middle; width:1.2em; margin:1px" src="..
|
||||
puedes volver al mensaje original en el chat original</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Finally, you can also use “Save Messages” to take <strong>personal notes</strong> - open the chat, type something, add a photo or a voice message etc.</p>
|
||||
<p>Finalmente, también se puede utilizar “Mensajes guardados” para tomar <strong>notas personales</strong> - abre el chat, escribe algo, añade una foto o un mensaje de voz, etc.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>As “Saved Message” are synced, they can become very handy for transferring data between devices</p>
|
||||
<p>Como los “mensajes guardados” se sincronizan, pueden ser muy útiles para transferir datos entre dispositivos.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Messages stay saved even if they are edited or deleted -
|
||||
may it be by <a href="#edit">sender</a>, by <a href="#delold">device cleanup</a> or by <a href="#ephemeralmsgs">disappearing messages of other chats</a>.</p>
|
||||
<p>Los mensajes se quedan guardados, también si se han cambiado o están borrados -
|
||||
Sea por el <a href="#edit">remitente</a>, por la <a href="#delold">limpieza del dispositivo</a> o por la <a href="#ephemeralmsgs">desaparición de mensajes de otros chats</a>.</p>
|
||||
|
||||
<h3 id="qué-significa-el-punto-verde">
|
||||
|
||||
@@ -349,16 +348,16 @@ junto al avatar de un contacto.
|
||||
Significa que ha sido <strong>visto recientemente</strong> en los últimos 10 minutos:</p>
|
||||
|
||||
<ul>
|
||||
<li>either because they messaged you directly,</li>
|
||||
<li>because they wrote something to a group you are both a member of,</li>
|
||||
<li>because they sent you a read receipt for a message you wrote,</li>
|
||||
<li>because they edit or delete a message in a chat shared with you,</li>
|
||||
<li>or because they use an <a href="#webxdc">app</a> in a chat shared with you.</li>
|
||||
<li>sea porque te enviaron un mensaje directamente,</li>
|
||||
<li>porque escribieron algo en un grupo en que ambos son miembros,</li>
|
||||
<li>porque te enviaron un acuse de recibo de un mensaje que escribiste,</li>
|
||||
<li>porque editaron o borraron un mensaje en un chat compartido contigo,</li>
|
||||
<li>o porque utilizan una <a href="#webxdc">app</a> en un chat compartido contigo.</li>
|
||||
</ul>
|
||||
|
||||
<p>So this is not a real time online status -
|
||||
and if someone doesn’t answer right away even though they seem to be online,
|
||||
don’t worry and give them some space :)</p>
|
||||
<p>Así que esto no es un estado de en línea en tiempo real -
|
||||
y si alguien no responde de inmediato, aunque parece que estar en línea,
|
||||
no te preocupes y dale un poco de espacio :)</p>
|
||||
|
||||
<p>On the other hand, others will not always “see that you are online”.
|
||||
If you have turned off read receipts,
|
||||
@@ -368,16 +367,16 @@ until one of the above conditions are met.</p>
|
||||
<h3 id="edit">
|
||||
|
||||
|
||||
Correct typos and delete messages after sending <a href="#edit" class="anchor"></a>
|
||||
Corregir errores y borrar mensajes después de enviar <a href="#edit" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>You can edit the text of your messages after sending.
|
||||
For that, long tap or right click the message and select <strong>Edit</strong>
|
||||
or <img style="vertical-align:middle; width:1.2em; margin:1px" src="../edit-icon.png" alt="Edit icon" />.</p>
|
||||
<p>Se puede editar el texto de los mensajes después de enviarlos.
|
||||
Para ello, mantenga pulsado o haz clic con el botón derecho en el mensaje y seleccione <strong>Editar</strong>
|
||||
o <img style="vertical-align:middle; width:1.2em; margin:1px" src="../edit-icon.png" alt="Edit icon" />.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Si has enviado un mensaje accidentalmente
|
||||
@@ -400,11 +399,11 @@ who could have already replied, forwarded, saved, screenshotted or otherwise cop
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Puedes activar “desaparición de mensajes”
|
||||
en la configuración de un chat,
|
||||
en la parte superior derecha de la ventana de chat,
|
||||
seleccionando un lapso de tiempo
|
||||
entre 1 minuto y 5 semanas.</p>
|
||||
<p>You can turn on “disappearing messages”
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Hasta que la configuración se desactive nuevamente,
|
||||
La aplicación Delta Chat de cada miembro del chat se encarga
|
||||
@@ -560,15 +559,15 @@ older than that.</li>
|
||||
<h2 id="instant-delivery">
|
||||
|
||||
|
||||
Instant message delivery and Push Notifications <a href="#instant-delivery" class="anchor"></a>
|
||||
Entrega de mensajes instantáneos y notificaciones Push <a href="#instant-delivery" class="anchor"></a>
|
||||
|
||||
|
||||
</h2>
|
||||
|
||||
<h3 id="what-are-push-notifications-how-can-i-get-instant-message-delivery">
|
||||
<h3 id="qué-son-las-notificaciones-push-cómo-puedo-recibir-mensajes-instantáneos">
|
||||
|
||||
|
||||
What are Push Notifications? How can I get instant message delivery? <a href="#what-are-push-notifications-how-can-i-get-instant-message-delivery" class="anchor"></a>
|
||||
¿Qué son las Notificaciones Push? ¿Cómo puedo recibir mensajes instantáneos? <a href="#qué-son-las-notificaciones-push-cómo-puedo-recibir-mensajes-instantáneos" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -577,11 +576,11 @@ older than that.</li>
|
||||
so that an inactive Delta Chat app can fetch messages in the background
|
||||
and show notifications on a user’s phone if needed.</p>
|
||||
|
||||
<p>Push Notifications work with all <a href="https://delta.chat/chatmail">chatmail</a> servers on</p>
|
||||
<p>Las notificaciones push funcionan con todos los servidores de <a href="https://delta.chat/chatmail">chatmail</a> en</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>iOS devices, by integrating with Apple Push services.</p>
|
||||
<p>dispositivos iOS, por la integración de los servicios Push de Apple.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Android devices, by integrating with the Google FCM Push service,
|
||||
@@ -590,13 +589,13 @@ instead of proprietary Google code on the phone.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>As of May 2024, classic e-mail servers do not support Push Notifications
|
||||
for Delta Chat users.</p>
|
||||
<p>A partir de mayo de 2024, los servidores de correo electrónico clásicos no admiten notificaciones push
|
||||
para los usuarios de Delta Chat.</p>
|
||||
|
||||
<h3 id="are-push-notifications-enabled-on-ios-devices-is-there-an-alternative">
|
||||
<h3 id="están-activadas-las-notificaciones-push-en-los-dispositivos-ios-existe-alguna-alternativa">
|
||||
|
||||
|
||||
Are Push Notifications enabled on iOS devices? Is there an alternative? <a href="#are-push-notifications-enabled-on-ios-devices-is-there-an-alternative" class="anchor"></a>
|
||||
¿Están activadas las notificaciones Push en los dispositivos iOS? ¿Existe alguna alternativa? <a href="#están-activadas-las-notificaciones-push-en-los-dispositivos-ios-existe-alguna-alternativa" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -611,7 +610,7 @@ does not expose data to Apple that it doesn’t already have.</p>
|
||||
<h3 id="android-push">
|
||||
|
||||
|
||||
Are Push notifications enabled / needed on Android devices? <a href="#android-push" class="anchor"></a>
|
||||
¿Están habilitadas / son necesarias las notificaciones Push en los dispositivos Android? <a href="#android-push" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -649,7 +648,7 @@ safe to try if you experience messages arrive only with long delays.</p>
|
||||
<h3 id="privacy-notifications">
|
||||
|
||||
|
||||
How private are Delta Chat Push Notifications? <a href="#privacy-notifications" class="anchor"></a>
|
||||
¿Qué privadas son las notificaciones push de Delta Chat? <a href="#privacy-notifications" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -658,7 +657,7 @@ safe to try if you experience messages arrive only with long delays.</p>
|
||||
It does not leak e-mail, IP address or message content (not even encrypted)
|
||||
to any system involved in the delivery of Push Notifications.</p>
|
||||
|
||||
<p>Here is how Delta Chat apps perform Push Notification delivery:</p>
|
||||
<p>Así es como las aplicaciones Delta Chat realizan la entrega de Notificaciones Push:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
@@ -776,14 +775,14 @@ there are no lock or similar markers on end-to-end encrypted messages, anymore.<
|
||||
it is impossible to receive or send messages without end-to-end encryption.</p>
|
||||
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages without end-to-end encryption.
|
||||
Such messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
|
||||
|
||||
How can I establish a chat with a new contact? <a href="#howtoe2ee" class="anchor"></a>
|
||||
¿Cómo puedo establecer un chat con un nuevo contacto? <a href="#howtoe2ee" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -1604,6 +1603,29 @@ Esto es lo que hace Delta Chat con esos permisos:</p>
|
||||
Sin embargo, algunos proveedores necesitan opciones especiales para funcionar correctamente, ver <a href="https://providers.delta.chat">Descripción de proveedores</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">
|
||||
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#de-quelles-autorisations-delta-chat-a-t-il-besoin">De quelles autorisations Delta Chat a-t-il besoin?</a></li>
|
||||
<li><a href="#est-ce-que-delta-chat-fonctionne-avec-mon-fournisseur-de-courriel-">Est-ce que Delta Chat fonctionne avec <em>mon</em> fournisseur de courriel ?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</a></li>
|
||||
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
|
||||
<li><a href="#pourquoi-dois-je-entrer-le-mot-de-passe-de-mon-compte-de-courriel-dans-delta-chat--est-ce-sécurisé-">Pourquoi dois-je entrer le mot de passe de mon compte de courriel dans Delta Chat ? Est-ce sécurisé ?</a></li>
|
||||
<li><a href="#quels-sont-les-messages-qui-apparaissent-dans-delta-chat-">Quels sont les messages qui apparaissent dans Delta Chat ?</a></li>
|
||||
@@ -397,7 +398,7 @@ who could have already replied, forwarded, saved, screenshotted or otherwise cop
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 1 minute and 5 weeks.</p>
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Until the setting is turned off again,
|
||||
each chat member’s Delta Chat app takes care
|
||||
@@ -758,8 +759,8 @@ there are no lock or similar markers on end-to-end encrypted messages, anymore.<
|
||||
it is impossible to receive or send messages without end-to-end encryption.</p>
|
||||
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages without end-to-end encryption.
|
||||
Such messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
@@ -1566,6 +1567,29 @@ Voici ce que fait Delta Chat avec ces autorisations:</p>
|
||||
Cependant, il faut activer des options spéciales pour que cela fonctionne correctement avec certains fournisseurs… Voir <a href="https://providers.delta.chat">la liste des fournisseurs</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">
|
||||
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#izin-apa-yang-dibutuhkan-delta-chat">Izin apa yang dibutuhkan Delta Chat?</a></li>
|
||||
<li><a href="#does-delta-chat-work-with-my-e-mail-provider">Does Delta Chat work with <em>my</em> e-mail-provider?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</a></li>
|
||||
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
|
||||
<li><a href="#mengapa-saya-harus-memasukkan-kata-sandi-e-mail-saya-ke-delta-chat-apakah-ini-aman">Mengapa saya harus memasukkan kata sandi E-Mail saya ke Delta Chat? Apakah ini aman?</a></li>
|
||||
<li><a href="#pesan-mana-yang-muncul-di-delta-chat">Pesan mana yang muncul di Delta Chat?</a></li>
|
||||
@@ -411,7 +412,7 @@ who could have already replied, forwarded, saved, screenshotted or otherwise cop
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 1 minute and 5 weeks.</p>
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Until the setting is turned off again,
|
||||
each chat member’s Delta Chat app takes care
|
||||
@@ -784,8 +785,8 @@ there are no lock or similar markers on end-to-end encrypted messages, anymore.<
|
||||
it is impossible to receive or send messages without end-to-end encryption.</p>
|
||||
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages without end-to-end encryption.
|
||||
Such messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
@@ -1626,6 +1627,29 @@ However, some providers need special options to work properly,
|
||||
see <a href="https://providers.delta.chat">Provider Overview</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">
|
||||
|
||||
|
||||
|
||||
@@ -50,10 +50,10 @@
|
||||
<li><a href="#tls">I messaggi contrassegnati dall’icona della posta sono esposti su Internet?</a></li>
|
||||
<li><a href="#message-metadata">In che modo Delta Chat protegge i metadati nei messaggi?</a></li>
|
||||
<li><a href="#device-seizure">Come proteggere i metadati e contatti quando un dispositivo viene sequestrato?</a></li>
|
||||
<li><a href="#sealedsender">Does Delta Chat support “Sealed Sender”?</a></li>
|
||||
<li><a href="#sealedsender">Delta Chat supporta “Mittente Sigillato”?</a></li>
|
||||
<li><a href="#pfs">Delta Chat supporta Perfect Forward Secrecy?</a></li>
|
||||
<li><a href="#pqc">Does Delta Chat support Post-Quantum-Cryptography?</a></li>
|
||||
<li><a href="#how-can-i-manually-check-encryption-information">How can I manually check encryption information?</a></li>
|
||||
<li><a href="#pqc">Delta Chat supporta la Crittografia Post-Quantistica?</a></li>
|
||||
<li><a href="#come-posso-controllare-manualmente-le-informazioni-di-crittografia">Come posso controllare manualmente le informazioni di crittografia?</a></li>
|
||||
<li><a href="#importkey">Posso riutilizzare la mia chiave privata esistente?</a></li>
|
||||
<li><a href="#security-audits">Delta Chat è stata verificata in modo indipendente per le vulnerabilità di sicurezza?</a></li>
|
||||
</ul>
|
||||
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#di-quali-autorizzazioni-ha-bisogno-delta-chat">Di quali autorizzazioni ha bisogno Delta Chat?</a></li>
|
||||
<li><a href="#delta-chat-funziona-con-il-mio-fornitore-e-mail">Delta Chat funziona con il <em>mio</em> fornitore e-mail?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</a></li>
|
||||
<li><a href="#vorrei-gestire-il-mio-server-per-delta-chat-cosa-mi-consigliate">Vorrei gestire il mio server per Delta Chat. Cosa mi consigliate?</a></li>
|
||||
<li><a href="#perché-devo-inserire-la-mia-password-e-mail-in-delta-chat-è-sicuro">Perché devo inserire la mia password E-Mail in Delta Chat? È sicuro?</a></li>
|
||||
<li><a href="#quali-messaggi-vengono-mostrati-in-delta-chat">Quali messaggi vengono mostrati in Delta Chat?</a></li>
|
||||
@@ -405,11 +406,11 @@ che avrebbero già potuto rispondere, inoltrare, salvare, scattare una schermata
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Puoi attivare i “messaggi che scompaiono”
|
||||
nelle impostazioni di una chat,
|
||||
in alto a destra nella finestra della chat,
|
||||
selezionando un intervallo di tempo
|
||||
tra 1 minuto e 5 settimane.</p>
|
||||
<p>You can turn on “disappearing messages”
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Fino a quando l’impostazione non viene nuovamente disattivata,
|
||||
l’app Delta Chat di ogni membro della chat si prende cura
|
||||
@@ -776,9 +777,9 @@ non ci sono più lucchetti o marcatori simili, sui messaggi crittografati end-to
|
||||
<p>Se si utilizzano i <a href="https://chatmail.at/relays">relays di chatmail</a>,
|
||||
è impossibile ricevere o inviare messaggi senza la crittografia end-to-end.</p>
|
||||
|
||||
<p>Se invece si crea un profilo utilizzando un server di posta elettronica classico,
|
||||
è possibile inviare e ricevere messaggi senza crittografia end-to-end.
|
||||
I messaggi privi di crittografia end-to-end sono contrassegnati da un’icona e-mail<br />
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
@@ -838,16 +839,16 @@ la crittografia end-to-end sarà stabilita tra tutti i membri.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>A contact profile might show a green checkmark
|
||||
<p>Il profilo di un contatto potrebbe mostrare una spunta verde
|
||||
<img style="vertical-align:middle; width:1.5em; margin:1px" src="../green-checkmark.png" alt="green checkmark" />
|
||||
and an “Introduced by” line.
|
||||
Every green-checkmarked contact either did a direct <a href="#howtoe2ee">QR-scan</a> with you
|
||||
or was introduced by a another green-checkmarked contact.
|
||||
Introductions happen automatically when adding members to groups.
|
||||
Whoever adds a green-checkmarked contact to a group with only green-checkmarked members
|
||||
becomes an introducer.
|
||||
In a contact profile you can tap on the “Introduced by …” text repeatedly
|
||||
until you get to the one with whom you directly did a <a href="#howtoe2ee">QR-scan</a>.</p>
|
||||
e una linea “Verificato da”.
|
||||
Ogni contatto con la spunta verde ha fatto un <a href="#howtoe2ee">QR-scan</a> con te
|
||||
o è stato verificato da un altro contatto con la spunta verde.
|
||||
La verifica si ha automaticamente all’aggiunta dei membri nei gruppi.
|
||||
Chiunque aggiunga un contatto con spunta verde a un gruppo con solo membri con la spunta verde
|
||||
diventa colui che l’ha verificato.
|
||||
Nel profilo di un contatto puoi premere sul campo “Verificato da …” ripetutamente
|
||||
fino a che vedi con chi hai avuto un <a href="#howtoe2ee">QR-scan</a>.</p>
|
||||
|
||||
<p>Per una discussione più approfondita sulla “crittografia end-to-end garantita”
|
||||
consultare <a href="https://securejoin.delta.chat/en/latest/new.html">Protocolli Secure-Join</a>
|
||||
@@ -969,25 +970,25 @@ anche se il messaggio non sarà crittografato end-to-end.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Unlike most other messengers,
|
||||
Delta Chat apps do not store any metadata about contacts or groups on servers, also not in encrypted form.
|
||||
Instead, all group metadata is end-to-end encrypted and stored on end-user devices, only.</p>
|
||||
<p>A differenza della maggior parte degli altri servizi di messaggistica,
|
||||
le apps Delta Chat non memorizzano alcun metadato sui contatti o sui gruppi sui server, né in forma crittografata.
|
||||
Tutti i metadati dei gruppi sono invece crittografati end-to-end e memorizzati esclusivamente sui dispositivi degli utenti finali.</p>
|
||||
|
||||
<p>E-mail Servers can therefore only see</p>
|
||||
<p>I Server E-mail possono quindi vedere solo</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>the message date,</p>
|
||||
<p>la data del messaggio,</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>sender and receiver addresses</p>
|
||||
<p>indirizzi del mittente e del destinatario</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>and message size.</p>
|
||||
<p>e dimensione del messaggio.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
||||
<p>Tutti gli altri metadati dei messaggi, dei contatti e dei gruppi risiedono nella parte crittografata end-to-end dei messaggi.</p>
|
||||
|
||||
<h3 id="device-seizure">
|
||||
|
||||
@@ -997,36 +998,36 @@ Instead, all group metadata is end-to-end encrypted and stored on end-user devic
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Both for protecting against metadata-collecting e-mail servers
|
||||
as well as against the threat of device seizure
|
||||
we recommend to use a <a href="https://chatmail.at/relays">chatmail relay</a>
|
||||
to create chat profiles using random e-mail addresses for transport.
|
||||
Note that Delta Chat apps on all platforms support multiple profiles
|
||||
so you can easily use situation-specific profiles next to your “main” profile
|
||||
with the knowledge that all their data, along with all metadata, will be deleted.
|
||||
Moreover, if a device is seized then chat contacts using short-lived profiles
|
||||
can not be identified easily.</p>
|
||||
<p>Sia per proteggersi dai server e-mail che raccolgono metadati
|
||||
sia per proteggersi dal rischio di sequestro del dispositivo,
|
||||
consigliamo di utilizzare un <a href="https://chatmail.at/relays">chatmail relay</a>
|
||||
per creare profili di chat utilizzando indirizzi e-mail casuali per il trasporto.
|
||||
Si noti che le apps Delta Chat su tutte le piattaforme supportano più profili,
|
||||
quindi è possibile utilizzare facilmente profili specifici per ogni situazione accanto al profilo “principale”,
|
||||
con la consapevolezza che tutti i loro dati, insieme a tutti i metadati, verranno eliminati.
|
||||
Inoltre, se un dispositivo viene sequestrato, i contatti di chat che utilizzano profili di breve durata
|
||||
non possono essere identificati facilmente.</p>
|
||||
|
||||
<h3 id="sealedsender">
|
||||
|
||||
|
||||
Does Delta Chat support “Sealed Sender”? <a href="#sealedsender" class="anchor"></a>
|
||||
Delta Chat supporta “Mittente Sigillato”? <a href="#sealedsender" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>No, non ancora.</p>
|
||||
|
||||
<p>The Signal messenger introduced <a href="https://signal.org/blog/sealed-sender/">“Sealed Sender” in 2018</a>
|
||||
to keep their server infrastructure ignorant of who is sending a message to a set of recipients.
|
||||
It is particularly important because the Signal server knows the mobile number of each account,
|
||||
which is usually associated with a passport identity.</p>
|
||||
<p>Il messenger Signal ha introdotto <a href="https://signal.org/blog/sealed-sender/">“Mittente Sigillato” nel 2018</a>
|
||||
per impedire che la propria infrastruttura server venga a conoscenza di chi sta inviando un messaggio a un insieme di destinatari.
|
||||
È particolarmente importante perché il server Signal conosce il numero di cellulare di ciascun profilo,
|
||||
che di solito è associato a un’identità tramite passaporto.</p>
|
||||
|
||||
<p>Even if <a href="https://chatmail.at/relays">chatmail relays</a>
|
||||
do not ask for any private data (including no phone numbers),
|
||||
it might still be worthwhile to protect relational metadata between addresses.
|
||||
We don’t foresee bigger problems in using random throw-away e-mail addresses for sealed sending
|
||||
but an implementation has not been agreed as a priority yet.</p>
|
||||
<p>Anche se i <a href="https://chatmail.at/relays">relays di chat</a>
|
||||
non richiedono dati privati (inclusi numeri di telefono),
|
||||
potrebbe comunque valere la pena proteggere i metadati relazionali tra gli indirizzi.
|
||||
Non prevediamo problemi maggiori nell’utilizzo di indirizzi e-mail casuali usa e getta per l’invio sigillato,
|
||||
ma un’implementazione non è stata ancora concordata come priorità.</p>
|
||||
|
||||
<h3 id="pfs">
|
||||
|
||||
@@ -1038,41 +1039,41 @@ but an implementation has not been agreed as a priority yet.</p>
|
||||
|
||||
<p>No, non ancora.</p>
|
||||
|
||||
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||
This means that if your private decryption key is leaked,
|
||||
and someone has collected your prior in-transit messages,
|
||||
they will be able to decrypt and read them using the leaked decryption key.
|
||||
Note that Forward Secrecy only increases security if you delete messages.
|
||||
Otherwise, someone obtaining your decryption keys
|
||||
is typically also able to get all your non-deleted messages
|
||||
and doesn’t even need to decrypt any previously collected messages.</p>
|
||||
<p>Delta Chat al momento non supporta la tecnologia Perfect Forward Secrecy (PFS).
|
||||
Ciò significa che se la tua chiave di decrittazione privata viene divulgata
|
||||
e qualcuno ha raccolto i tuoi messaggi in transito precedenti,
|
||||
sarà in grado di decifrarli e leggerli utilizzando la chiave di decrittazione divulgata.
|
||||
Tieni presente che la tecnologia Forward Secrecy aumenta la sicurezza solo se elimini i messaggi.
|
||||
In caso contrario, chi ottiene le tue chiavi di decrittazione
|
||||
in genere è in grado di ottenere anche tutti i tuoi messaggi non eliminati
|
||||
e non ha nemmeno bisogno di decifrare i messaggi raccolti in precedenza.</p>
|
||||
|
||||
<p>We designed a Forward Secrecy approach that withstood
|
||||
initial examination from some cryptographers and implementation experts
|
||||
but is pending a more formal write up
|
||||
to ascertain it reliably works in federated messaging and with multi-device usage,
|
||||
before it could be implemented in <a href="https://github.com/chatmail/core">chatmail core</a>,
|
||||
which would make it available in all <a href="https://chatmail.at/clients">chatmail clients</a>.</p>
|
||||
<p>Abbiamo progettato un approccio Forward Secrecy che ha superato
|
||||
l’esame iniziale di alcuni crittografi ed esperti di implementazione
|
||||
ma è in attesa di una stesura più formale
|
||||
per accertarne l’affidabilità nella messaggistica federata e nell’utilizzo su più dispositivi,
|
||||
prima di poter essere implementato in <a href="https://github.com/chatmail/core">chatmail core</a>,
|
||||
che lo renderebbe disponibile in tutti i <a href="https://chatmail.at/clients">clients di chatmail</a>.</p>
|
||||
|
||||
<h3 id="pqc">
|
||||
|
||||
|
||||
Does Delta Chat support Post-Quantum-Cryptography? <a href="#pqc" class="anchor"></a>
|
||||
Delta Chat supporta la Crittografia Post-Quantistica? <a href="#pqc" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>No, non ancora.</p>
|
||||
|
||||
<p>Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
||||
We aim to add PQC support in <a href="https://github.com/chatmail/core">chatmail core</a> after the draft is finalized at the IETF
|
||||
in collaboration with other OpenPGP implementers.</p>
|
||||
<p>Delta Chat utilizza la libreria Rust OpenPGP <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||
che supporta l’ultima <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">bozza IETF Post-Quantum-Cryptography OpenPGP</a>.
|
||||
Il nostro obiettivo è aggiungere il supporto PQC nel <a href="https://github.com/chatmail/core">core di chatmail</a> dopo che la bozza sarà stata finalizzata dall’IETF
|
||||
in collaborazione con altri implementatori di OpenPGP.</p>
|
||||
|
||||
<h3 id="how-can-i-manually-check-encryption-information">
|
||||
<h3 id="come-posso-controllare-manualmente-le-informazioni-di-crittografia">
|
||||
|
||||
|
||||
How can I manually check encryption information? <a href="#how-can-i-manually-check-encryption-information" class="anchor"></a>
|
||||
Come posso controllare manualmente le informazioni di crittografia? <a href="#come-posso-controllare-manualmente-le-informazioni-di-crittografia" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -1096,8 +1097,8 @@ la connessione è sicura.</p>
|
||||
<p>Delta Chat genera chiavi OpenPGP sicure in conformità alle specifiche di Autocrypt 1.1.
|
||||
Puoi esportare le tue chiavi private ma non puoi importare chiavi private aggiuntive.</p>
|
||||
|
||||
<p>In generale, non raccomandiamo on proponiamo agli utenti di gestire manualmente le chiavi.
|
||||
Noi vogliamo assicurare che gli audit di sicurezza si possano focalizzare su pochi algoritmi crittografici comprovati
|
||||
<p>In generale, non raccomandiamo o proponiamo agli utenti di gestire manualmente le chiavi.
|
||||
Noi vogliamo assicurare che gli audits di sicurezza si possano focalizzare su pochi algoritmi crittografici comprovati
|
||||
invece che sull’intera estensione dei possibili algoritmi consentiti con OpenPGP.</p>
|
||||
|
||||
<h3 id="security-audits">
|
||||
@@ -1596,6 +1597,29 @@ Tuttavia, alcuni provider necessitano di opzioni speciali per funzionare corrett
|
||||
vedi <a href="https://providers.delta.chat">Panoramica fornitore</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="vorrei-gestire-il-mio-server-per-delta-chat-cosa-mi-consigliate">
|
||||
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#welke-android-rechten-heeft-delta-chat-nodig">Welke Android-rechten heeft Delta Chat nodig?</a></li>
|
||||
<li><a href="#wordt-mijn-e-mailprovider-ondersteund-door-delta-chat">Wordt <em>mijn</em> e-mailprovider ondersteund door Delta Chat?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</a></li>
|
||||
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
|
||||
<li><a href="#waarom-moet-ik-mijn-e-mailwachtwoord-invoeren-in-delta-chat-is-dat-wel-veilig">Waarom moet ik mijn e-mailwachtwoord invoeren in Delta Chat? Is dat wel veilig?</a></li>
|
||||
<li><a href="#welke-berichten-vind-ik-terug-in-delta-chat">Welke berichten vind ik terug in Delta Chat?</a></li>
|
||||
@@ -407,7 +408,7 @@ who could have already replied, forwarded, saved, screenshotted or otherwise cop
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 1 minute and 5 weeks.</p>
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Until the setting is turned off again,
|
||||
each chat member’s Delta Chat app takes care
|
||||
@@ -777,8 +778,8 @@ there are no lock or similar markers on end-to-end encrypted messages, anymore.<
|
||||
it is impossible to receive or send messages without end-to-end encryption.</p>
|
||||
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages without end-to-end encryption.
|
||||
Such messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
@@ -1617,6 +1618,29 @@ Delta Chat doet het volgende met deze rechten:</p>
|
||||
Sommige providers verwachten echter bepaalde opties. Bekijk hiervoor het <a href="https://providers.delta.chat">provideroverzicht</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">
|
||||
|
||||
|
||||
|
||||
@@ -50,10 +50,10 @@
|
||||
<li><a href="#tls">Czy wiadomości oznaczone ikoną poczty są widoczne w internecie?</a></li>
|
||||
<li><a href="#message-metadata">W jaki sposób Delta Chat chroni metadane w wiadomościach?</a></li>
|
||||
<li><a href="#device-seizure">Jak chronić metadane i kontakty w przypadku przejęcia urządzenia?</a></li>
|
||||
<li><a href="#sealedsender">Does Delta Chat support “Sealed Sender”?</a></li>
|
||||
<li><a href="#sealedsender">Czy Delta Chat obsługuje funkcję „Sealed Sender”?</a></li>
|
||||
<li><a href="#pfs">Czy Delta Chat obsługuje funkcję Perfect Forward Secrecy?</a></li>
|
||||
<li><a href="#pqc">Does Delta Chat support Post-Quantum-Cryptography?</a></li>
|
||||
<li><a href="#how-can-i-manually-check-encryption-information">How can I manually check encryption information?</a></li>
|
||||
<li><a href="#pqc">Czy Delta Chat obsługuje kryptografię postkwantową?</a></li>
|
||||
<li><a href="#jak-mogę-ręcznie-sprawdzić-informacje-o-szyfrowaniu">Jak mogę ręcznie sprawdzić informacje o szyfrowaniu?</a></li>
|
||||
<li><a href="#importkey">Czy mogę ponownie wykorzystać mój istniejący klucz prywatny?</a></li>
|
||||
<li><a href="#security-audits">Czy Delta Chat był niezależnie kontrolowany pod kątem luk w zabezpieczeniach?</a></li>
|
||||
</ul>
|
||||
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#jakich-uprawnień-potrzebuje-delta-chat">Jakich uprawnień potrzebuje Delta Chat?</a></li>
|
||||
<li><a href="#czy-delta-chat-działa-z-moim-dostawcą-poczty-e-mail">Czy Delta Chat działa z <em>moim</em> dostawcą poczty e-mail?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</a></li>
|
||||
<li><a href="#chcę-zarządzać-własnym-serwerem-dla-delta-chat-co-polecacie">Chcę zarządzać własnym serwerem dla Delta Chat. Co polecacie?</a></li>
|
||||
<li><a href="#dlaczego-muszę-wpisać-moje-hasło-e-mail-do-delta-chat-czy-to-jest-bezpieczne">Dlaczego muszę wpisać moje hasło e-mail do Delta Chat? Czy to jest bezpieczne?</a></li>
|
||||
<li><a href="#jakie-wiadomości-pojawiają-się-w-delta-chat">Jakie wiadomości pojawiają się w Delta Chat?</a></li>
|
||||
@@ -356,7 +357,11 @@
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Możesz włączyć „znikające wiadomości” w ustawieniach czatu, w prawym górnym rogu okna czatu, wybierając przedział czasu od 1 minuty do 5 tygodni.</p>
|
||||
<p>You can turn on “disappearing messages”
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Dopóki ustawienie nie zostanie ponownie wyłączone, aplikacja Delta Chat u każdego członka czatu zajmie się usuwaniem wiadomości po wybranym okresie. Przedział czasu rozpoczyna się w momencie, gdy odbiorca po raz pierwszy zobaczy wiadomość w Delta Chat. Wiadomości są usuwane zarówno na każdym koncie e-mail na serwerze, jak i w samej aplikacji.</p>
|
||||
|
||||
@@ -638,7 +643,10 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
<p>Jeśli korzystasz z domyślnych <a href="https://chatmail.at/relays">przekaźników chatmail</a>, odbieranie ani wysyłanie wiadomości bez szyfrowania end-to-end jest niemożliwe.</p>
|
||||
|
||||
<p>Jeśli zamiast tego utworzysz profil przy użyciu klasycznego serwera poczty e-mail, możesz wysyłać i odbierać wiadomości bez szyfrowania end-to-end. Takie wiadomości bez szyfrowania end-to-end są oznaczone ikoną e-mail <img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
|
||||
@@ -782,36 +790,21 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Both for protecting against metadata-collecting e-mail servers
|
||||
as well as against the threat of device seizure
|
||||
we recommend to use a <a href="https://chatmail.at/relays">chatmail relay</a>
|
||||
to create chat profiles using random e-mail addresses for transport.
|
||||
Note that Delta Chat apps on all platforms support multiple profiles
|
||||
so you can easily use situation-specific profiles next to your “main” profile
|
||||
with the knowledge that all their data, along with all metadata, will be deleted.
|
||||
Moreover, if a device is seized then chat contacts using short-lived profiles
|
||||
can not be identified easily.</p>
|
||||
<p>Zarówno w celu ochrony przed serwerami poczty e-mail gromadzącymi metadane, jak i przed zagrożeniem przejęcia urządzenia, zalecamy użycie <a href="https://chatmail.at/relays">przełącznika chatmail</a> do tworzenia profili czatu z losowymi adresami e-mail do przesyłania. Pamiętaj, że aplikacje Delta Chat na wszystkich platformach obsługują wiele kont, dzięki czemu możesz z łatwością korzystać z kont „1-tygodniowych” lub „1-miesięcznych” związanych z konkretnymi działaniami obok konta „głównego”, wiedząc, że wszystkie tymczasowe dane konta wraz ze wszystkimi metadanymi zostaną usunięte. Co więcej, jeśli urządzenie zostanie przejęte, kontakty czatu korzystające z profili krótkotrwałych nie będą mogły zostać łatwo zidentyfikowane.</p>
|
||||
|
||||
<h3 id="sealedsender">
|
||||
|
||||
|
||||
Does Delta Chat support “Sealed Sender”? <a href="#sealedsender" class="anchor"></a>
|
||||
Czy Delta Chat obsługuje funkcję „Sealed Sender”? <a href="#sealedsender" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>No, not yet.</p>
|
||||
<p>Nie, jeszcze nie.</p>
|
||||
|
||||
<p>The Signal messenger introduced <a href="https://signal.org/blog/sealed-sender/">“Sealed Sender” in 2018</a>
|
||||
to keep their server infrastructure ignorant of who is sending a message to a set of recipients.
|
||||
It is particularly important because the Signal server knows the mobile number of each account,
|
||||
which is usually associated with a passport identity.</p>
|
||||
<p>Komunikator Signal wprowadził funkcję <a href="https://signal.org/blog/sealed-sender/">„Sealed Sender”</a> w 2018 roku, aby infrastruktura serwerowa nie wiedziała, kto wysyła wiadomość do grupy odbiorców. Jest to szczególnie ważne, ponieważ serwer Signal zna numer telefonu komórkowego każdego konta, który zazwyczaj jest powiązany z identyfikatorem paszportu.</p>
|
||||
|
||||
<p>Even if <a href="https://chatmail.at/relays">chatmail relays</a>
|
||||
do not ask for any private data (including no phone numbers),
|
||||
it might still be worthwhile to protect relational metadata between addresses.
|
||||
We don’t foresee bigger problems in using random throw-away e-mail addresses for sealed sending
|
||||
but an implementation has not been agreed as a priority yet.</p>
|
||||
<p>Nawet jeśli <a href="https://chatmail.at/relays">przekaźniki chatmail</a> nie proszą o żadne prywatne dane (w tym numery telefonów), warto chronić metadane relacji między adresami. Nie przewidujemy poważniejszych problemów w korzystaniu z losowych, jednorazowych adresów e-mail do wysyłania wiadomości w tajemnicy, ale wdrożenie tej funkcji nie zostało jeszcze uznane za priorytetowe.</p>
|
||||
|
||||
<h3 id="pfs">
|
||||
|
||||
@@ -821,43 +814,28 @@ but an implementation has not been agreed as a priority yet.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>No, not yet.</p>
|
||||
<p>Nie, jeszcze nie.</p>
|
||||
|
||||
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||
This means that if your private decryption key is leaked,
|
||||
and someone has collected your prior in-transit messages,
|
||||
they will be able to decrypt and read them using the leaked decryption key.
|
||||
Note that Forward Secrecy only increases security if you delete messages.
|
||||
Otherwise, someone obtaining your decryption keys
|
||||
is typically also able to get all your non-deleted messages
|
||||
and doesn’t even need to decrypt any previously collected messages.</p>
|
||||
<p>Delta Chat obecnie nie obsługuje mechanizmu Perfect Forward Secrecy (PFS). Oznacza to, że jeśli twój prywatny klucz deszyfrujący zostanie ujawniony, a ktoś zdobędzie twoje wcześniejsze wiadomości w trakcie transmisji, będzie mógł je odszyfrować i odczytać za pomocą ujawnionego klucza deszyfrującego. Należy pamiętać, że mechanizm Forward Secrecy zwiększa bezpieczeństwo tylko w przypadku usuwania wiadomości. W przeciwnym razie osoba, która uzyska twoje klucze deszyfrujące, zazwyczaj będzie mogła uzyskać dostęp do wszystkich nieusuniętych wiadomości i nie będzie musiała odszyfrowywać żadnych wcześniej zebranych wiadomości.</p>
|
||||
|
||||
<p>We designed a Forward Secrecy approach that withstood
|
||||
initial examination from some cryptographers and implementation experts
|
||||
but is pending a more formal write up
|
||||
to ascertain it reliably works in federated messaging and with multi-device usage,
|
||||
before it could be implemented in <a href="https://github.com/chatmail/core">chatmail core</a>,
|
||||
which would make it available in all <a href="https://chatmail.at/clients">chatmail clients</a>.</p>
|
||||
<p>Opracowaliśmy metodę Forward Secrecy, która przeszła wstępną analizę niektórych kryptografów i ekspertów ds. wdrożeń, ale oczekuje na bardziej formalne opracowanie, które potwierdzi jej niezawodne działanie w federacyjnym przesyłaniu wiadomości i w przypadku korzystania z wielu urządzeń, zanim zostanie zaimplementowana w <a href="https://github.com/chatmail/core">rdzeniu chatmail</a>, co uczyniłoby ją dostępną we wszystkich <a href="https://chatmail.at/clients">klientach chatmail</a>.</p>
|
||||
|
||||
<h3 id="pqc">
|
||||
|
||||
|
||||
Does Delta Chat support Post-Quantum-Cryptography? <a href="#pqc" class="anchor"></a>
|
||||
Czy Delta Chat obsługuje kryptografię postkwantową? <a href="#pqc" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>No, not yet.</p>
|
||||
<p>Nie, jeszcze nie.</p>
|
||||
|
||||
<p>Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
||||
We aim to add PQC support in <a href="https://github.com/chatmail/core">chatmail core</a> after the draft is finalized at the IETF
|
||||
in collaboration with other OpenPGP implementers.</p>
|
||||
<p>Delta Chat korzysta z biblioteki Rust OpenPGP <a href="https://github.com/rpgp/rpgp">rPGP</a>, która obsługuje najnowszy <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">projekt OpenPGP IETF Post-Quantum-Cryptography</a>. Planujemy dodać obsługę PQC do <a href="https://github.com/chatmail/core">rdzenia chatmail</a> po sfinalizowaniu projektu w IETF we współpracy z innymi implementatorami OpenPGP.</p>
|
||||
|
||||
<h3 id="how-can-i-manually-check-encryption-information">
|
||||
<h3 id="jak-mogę-ręcznie-sprawdzić-informacje-o-szyfrowaniu">
|
||||
|
||||
|
||||
How can I manually check encryption information? <a href="#how-can-i-manually-check-encryption-information" class="anchor"></a>
|
||||
Jak mogę ręcznie sprawdzić informacje o szyfrowaniu? <a href="#jak-mogę-ręcznie-sprawdzić-informacje-o-szyfrowaniu" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -1184,10 +1162,9 @@ Listy rozgłoszeniowe są nadal wysoce eksperymentalne i bardzo prawdopodobne,
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Note:
|
||||
Changing email addresses is temporarily disabled
|
||||
because of ongoing changes to the DeltaChat core.
|
||||
It should be available again in a few months.</p>
|
||||
<p>Uwaga: Zmiana adresów e-mail jest tymczasowo wyłączona
|
||||
z powodu trwających zmian w rdzeniu DeltaChat.
|
||||
Powinna być ponownie dostępna za kilka miesięcy.</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
@@ -1262,6 +1239,29 @@ Oto, co robi Delta Chat z tymi uprawnieniami:</p>
|
||||
Jednak niektórzy dostawcy potrzebują specjalnych opcji, aby działać poprawnie, zobacz <a href="https://providers.delta.chat">Przegląd dostawców</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="chcę-zarządzać-własnym-serwerem-dla-delta-chat-co-polecacie">
|
||||
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#quais-permissões-o-delta-chat-precisa">Quais permissões o Delta Chat precisa?</a></li>
|
||||
<li><a href="#o-delta-chat-funciona-com-meu-provedor-de-e-mail">O Delta Chat funciona com <em>meu</em> provedor de e-mail?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</a></li>
|
||||
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
|
||||
<li><a href="#por-que-preciso-entrar-com-a-senha-do-meu-email-no-delta-chat-isso-é-seguro">Por que preciso entrar com a senha do meu email no Delta Chat? Isso é seguro?</a></li>
|
||||
<li><a href="#quais-mensagens-aparecem-no-delta-chat">Quais mensagens aparecem no Delta Chat?</a></li>
|
||||
@@ -407,7 +408,7 @@ who could have already replied, forwarded, saved, screenshotted or otherwise cop
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 1 minute and 5 weeks.</p>
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Until the setting is turned off again,
|
||||
each chat member’s Delta Chat app takes care
|
||||
@@ -778,8 +779,8 @@ there are no lock or similar markers on end-to-end encrypted messages, anymore.<
|
||||
it is impossible to receive or send messages without end-to-end encryption.</p>
|
||||
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages without end-to-end encryption.
|
||||
Such messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
@@ -1618,6 +1619,29 @@ No entanto, alguns provedores precisam de opções especiais para funcionar corr
|
||||
ver <a href="https://providers.delta.chat">Visão Geral dos Provedores</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">
|
||||
|
||||
|
||||
|
||||
+139
-116
@@ -45,15 +45,15 @@
|
||||
<li><a href="#e2eeguarantee">Что означает зеленая галочка в профиле контакта?</a></li>
|
||||
<li><a href="#зашифрованы-ли-вложения-изображения-файлы-аудио-и-т-д-сквозным-шифрованием">Зашифрованы ли вложения (изображения, файлы, аудио и т. д.) сквозным шифрованием?</a></li>
|
||||
<li><a href="#openpgp-secure">OpenPGP безопасен?</a></li>
|
||||
<li><a href="#openpgp-alternatives">Did you consider using alternatives to OpenPGP for end-to-end-encryption?</a></li>
|
||||
<li><a href="#openpgp-alternatives">Рассматривали ли вы альтернативы OpenPGP для сквозного шифрования?</a></li>
|
||||
<li><a href="#подвержен-ли-delta-chat-уязвимости-efail">Подвержен ли Delta Chat уязвимости EFAIL?</a></li>
|
||||
<li><a href="#tls">Видны ли в Интернете сообщения, отмеченные значком почты?</a></li>
|
||||
<li><a href="#message-metadata">Как Delta Chat защищает метаданные в сообщениях?</a></li>
|
||||
<li><a href="#device-seizure">Как защитить метаданные и контакты при изъятии устройства?</a></li>
|
||||
<li><a href="#sealedsender">Does Delta Chat support “Sealed Sender”?</a></li>
|
||||
<li><a href="#pfs">Поддерживает ли Delta Chat совершенную прямую секретность (Perfect forward secrecy, PFS)?</a></li>
|
||||
<li><a href="#pqc">Does Delta Chat support Post-Quantum-Cryptography?</a></li>
|
||||
<li><a href="#how-can-i-manually-check-encryption-information">How can I manually check encryption information?</a></li>
|
||||
<li><a href="#sealedsender">Поддерживает ли Delta Chat функцию “Sealed Sender” (Засекреченный отправитель)?</a></li>
|
||||
<li><a href="#pfs">Поддерживает ли Delta Chat свойство Perfect forward secrecy, PFS (Совершенную прямую секретность)?</a></li>
|
||||
<li><a href="#pqc">Поддерживает ли Delta Chat Post-Quantum-Cryptography (Постквантовую криптографию)?</a></li>
|
||||
<li><a href="#как-можно-вручную-проверить-информацию-о-шифровании">Как можно вручную проверить информацию о шифровании?</a></li>
|
||||
<li><a href="#importkey">Можно ли повторно использовать существующий секретный ключ?</a></li>
|
||||
<li><a href="#security-audits">Проходил ли Delta Chat независимую проверку на наличие уязвимостей безопасности?</a></li>
|
||||
</ul>
|
||||
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#какие-разрешения-нужны-delta-chat">Какие разрешения нужны Delta Chat?</a></li>
|
||||
<li><a href="#работает-ли-delta-chat-с-моим-провайдером-электронной-почты">Работает ли Delta Chat с <em>моим</em> провайдером электронной почты?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</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>
|
||||
@@ -403,11 +404,11 @@
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Вы можете включить “исчезающие сообщения”
|
||||
в настройках чата,
|
||||
в правом верхнем углу окна чата,
|
||||
выбрав временной интервал
|
||||
от 1 минуты до 5 недель.</p>
|
||||
<p>You can turn on “disappearing messages”
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Пока настройка не будет снова отключена,
|
||||
приложение Delta Chat каждого участника чата позаботится
|
||||
@@ -732,22 +733,22 @@ Push-уведомления недоступны.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat uses a <a href="#openpgp-secure">secure subset of the OpenPGP standard</a>
|
||||
to provide automatic end-to-end encryption using these protocols:</p>
|
||||
<p>Delta Chat использует <a href="#openpgp-secure">безопасное подмножество стандарта OpenPGP</a>
|
||||
для реализации автоматического сквозного шифрования c помощью следующих протоколов:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p><a href="https://securejoin.delta.chat/en/latest/new.html">Secure-Join</a>
|
||||
to exchange encryption setup information through QR-code scanning or “invite links”.</p>
|
||||
для обмена информацией о настройке шифрования через сканирование QR-кода или “ссылок-приглашений”.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="https://autocrypt.org">Autocrypt</a> is used for automatically
|
||||
establishing end-to-end encryption between contacts and all members of a group chat.</p>
|
||||
<p><a href="https://autocrypt.org">Autocrypt</a> используется для автоматической
|
||||
настройки сквозного шифрования между контактами и всеми членами группового чата.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Sharing a contact to a
|
||||
chat</a>
|
||||
enables receivers to use end-to-end encryption with the contact.</p>
|
||||
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Обмен контактом в
|
||||
чате</a>
|
||||
позволяет получателям настроить сквозное шифрование с этим контактом.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -761,9 +762,9 @@ enables receivers to use end-to-end encryption with the contact.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>All messages in Delta Chat are <strong>end-to-end encrypted by default</strong>.
|
||||
Since the Delta Chat Version 2 release series (July 2025)
|
||||
there are no lock or similar markers on end-to-end encrypted messages, anymore.</p>
|
||||
<p>Все сообщения в Delta Chat <strong>по умолчанию шифруются сквозным шифрованием</strong>.
|
||||
С момента выхода серии релизов Delta Chat версии 2 (июль 2025 года)
|
||||
на сообщениях со сквозным шифрованием больше не отображаются замки или другие подобные индикаторы.</p>
|
||||
|
||||
<h3 id="могу-ли-я-получать-или-отправлять-письма-без-сквозного-шифрования">
|
||||
|
||||
@@ -773,12 +774,12 @@ there are no lock or similar markers on end-to-end encrypted messages, anymore.<
|
||||
|
||||
</h3>
|
||||
|
||||
<p>If you use default <a href="https://chatmail.at/relays">chatmail relays</a>,
|
||||
it is impossible to receive or send messages without end-to-end encryption.</p>
|
||||
<p>Если вы используете стандартные <a href="https://chatmail.at/relays">ретрансляторы chatmail</a>,
|
||||
невозможно получать или отправлять сообщения без сквозного шифрования.</p>
|
||||
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages without end-to-end encryption.
|
||||
Such messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
@@ -789,9 +790,9 @@ Such messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
|
||||
</h3>
|
||||
|
||||
<p>You can send an invite link through another private chat,
|
||||
show an invitation QR code when next to each other or in a video call,
|
||||
or click on a “contact” that was shared in a chat.</p>
|
||||
<p>Вы можете отправить ссылку-приглашение через другой личный чат,
|
||||
показать QR-код приглашения, когда вы рядом или во время видеозвонка,
|
||||
или нажать на “контакт”, которым поделились в чате.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
@@ -800,35 +801,34 @@ or click on a “contact” that was shared in a chat.</p>
|
||||
и выберите “QR-код приглашения”.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>For <strong>direct 1:1 chat invitations</strong>,
|
||||
tap the QR Code icon <img style="vertical-align:middle; width:1.8em; margin:1px" src="../qr-icon.png" />
|
||||
on the Delta Chat app main screen.</p>
|
||||
<p>Для <strong>приглашений в прямой чат 1:1</strong>,
|
||||
коснитесь значка QR-кода <img style="vertical-align:middle; width:1.8em; margin:1px" src="../qr-icon.png" />
|
||||
на главном экране приложения Delta Chat.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Ask your chat partner to scan the QR image
|
||||
with their Delta Chat app,
|
||||
or click “Copy” or “Share” to create an invite link
|
||||
and share it with your chat partner.</p>
|
||||
<p>Попросите вашего собеседника отсканировать QR-код
|
||||
с помощью приложения Delta Chat,
|
||||
или нажмите “Копировать” или “Поделиться”, чтобы создать ссылку-приглашение
|
||||
и отправьте её вашему собеседнику.</p>
|
||||
|
||||
<p>Now wait while <a href="https://securejoin.delta.chat/en/latest/new.html#setup-contact-protocol">end-to-end encryption is getting established</a>.</p>
|
||||
<p>Теперь дождитесь, <a href="https://securejoin.delta.chat/en/latest/new.html#setup-contact-protocol">пока устанавливается сквозное шифрование</a>.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>If both sides are online, they will soon see a (group or direct) chat
|
||||
and can start messaging securely.</p>
|
||||
<p>Если оба участника онлайн, они вскоре увидят (групповой или прямой) чат
|
||||
и смогут начать защищённую переписку.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If one side is offline or in bad network,
|
||||
the ability to chat is delayed until connectivity is restored.</p>
|
||||
<p>Если одна из сторон не в сети или имеет плохое соединение,
|
||||
возможность переписки будет отложена до восстановления связи.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Congratulations!
|
||||
You now will automatically use end-to-end encryption
|
||||
with this contact.
|
||||
If you add each other to chat groups,
|
||||
end-to-end encryption will be established among all members.</p>
|
||||
<p>Поздравляем!
|
||||
Теперь вы автоматически будете использовать сквозное шифрование с данным контактом.
|
||||
Если вы добавите друг друга в групповые чаты,
|
||||
сквозное шифрование будет настроено для всех участников.</p>
|
||||
|
||||
<h3 id="e2eeguarantee">
|
||||
|
||||
@@ -838,16 +838,16 @@ end-to-end encryption will be established among all members.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>A contact profile might show a green checkmark
|
||||
<img style="vertical-align:middle; width:1.5em; margin:1px" src="../green-checkmark.png" alt="green checkmark" />
|
||||
and an “Introduced by” line.
|
||||
Every green-checkmarked contact either did a direct <a href="#howtoe2ee">QR-scan</a> with you
|
||||
or was introduced by a another green-checkmarked contact.
|
||||
Introductions happen automatically when adding members to groups.
|
||||
Whoever adds a green-checkmarked contact to a group with only green-checkmarked members
|
||||
becomes an introducer.
|
||||
In a contact profile you can tap on the “Introduced by …” text repeatedly
|
||||
until you get to the one with whom you directly did a <a href="#howtoe2ee">QR-scan</a>.</p>
|
||||
<p>В профиле контакта может отображаться зелёная галочка
|
||||
<img style="vertical-align:middle; width:1.5em; margin:1px" src="../green-checkmark.png" alt="зелёная галочка" />
|
||||
и строка “Подтверждён пользователем”.
|
||||
Каждый контакт с зелёной галочкой либо выполнил непосредственное сканирование <a href="#howtoe2ee">QR-кода</a> с вами,
|
||||
либо был подтверждён другим контактом с зелёной галочкой.
|
||||
Подтверждения происходят автоматически при добавлении участников в группы.
|
||||
Тот, кто добавляет контакт с зелёной галочкой в группу, где только участники с зелёными галочками,
|
||||
становится подтверждающим.
|
||||
В профиле контакта вы можете последовательно нажимать на текст “Подтверждён …” до тех пор,
|
||||
пока не дойдёте до того, с кем вы напрямую выполнили сканирование <a href="#howtoe2ee">QR-кода</a>.</p>
|
||||
|
||||
<p>Для более подробного обсуждения “гарантированного сквозного шифрования”
|
||||
пожалуйста, обратитесь к <a href="https://securejoin.delta.chat/en/latest/new.html">протоколам Secure-Join</a>
|
||||
@@ -877,9 +877,9 @@ until you get to the one with whom you directly did a <a href="#howtoe2ee">QR-sc
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, Delta Chat uses a secure subset of OpenPGP
|
||||
requiring the whole message to be properly encrypted and signed.
|
||||
For example, “Detached signatures” are not treated as secure.</p>
|
||||
<p>Да, Delta Chat использует безопасное подмножество OpenPGP
|
||||
требующее, чтобы всё сообщение было правильно зашифровано и подписано.
|
||||
Например, “Отделённые подписи” не считаются безопасными.</p>
|
||||
|
||||
<p>OpenPGP сам по себе не является небезопасным.
|
||||
Большинство обсуждаемых в публичной сфере проблем безопасности OpenPGP
|
||||
@@ -899,7 +899,7 @@ Delta Chat вместо этого использует реализацию Ope
|
||||
<h3 id="openpgp-alternatives">
|
||||
|
||||
|
||||
Did you consider using alternatives to OpenPGP for end-to-end-encryption? <a href="#openpgp-alternatives" class="anchor"></a>
|
||||
Рассматривали ли вы альтернативы OpenPGP для сквозного шифрования? <a href="#openpgp-alternatives" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -947,10 +947,10 @@ Delta Chat вместо этого использует реализацию Ope
|
||||
|
||||
</h3>
|
||||
|
||||
<p>If you are sending or receiving e-mail messages without end-to-end encryption (using a classic e-mail server),
|
||||
they are still protected from cell or cable companies who can not read or modify your e-mail messages.
|
||||
But both your and your recipient’s e-mail providers
|
||||
may read, analyze or modify your messages, including any attachments.</p>
|
||||
<p>Если вы отправляете или получаете электронные сообщения без сквозного шифрования (используя классический почтовый сервер),
|
||||
они всё равно защищены от операторов сотовой связи или интернет-провайдеров, которые не могут прочитать или изменить ваши электронные сообщения.
|
||||
Однако и ваш почтовый провайдер, и почтовый провайдер вашего получателя
|
||||
могут читать, анализировать или изменять ваши сообщения, включая любые вложения.</p>
|
||||
|
||||
<p>Delta Chat по умолчанию использует строгое
|
||||
<a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">TLS-шифрование</a>,
|
||||
@@ -971,25 +971,25 @@ may read, analyze or modify your messages, including any attachments.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Unlike most other messengers,
|
||||
Delta Chat apps do not store any metadata about contacts or groups on servers, also not in encrypted form.
|
||||
Instead, all group metadata is end-to-end encrypted and stored on end-user devices, only.</p>
|
||||
<p>В отличие от большинства других мессенджеров,
|
||||
приложения Delta Chat не сохраняют никакие метаданные о контактах или группах на серверах, даже в зашифрованной форме.
|
||||
Вместо этого все групповые метаданные шифруются сквозным шифрованием и хранятся исключительно на устройствах конечных пользователей.</p>
|
||||
|
||||
<p>E-mail Servers can therefore only see</p>
|
||||
<p>Поэтому, почтовые серверы имеют доступ только к</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>the message date,</p>
|
||||
<p>дате сообщения,</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>sender and receiver addresses</p>
|
||||
<p>адресам отправителя и получателя</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>and message size.</p>
|
||||
<p>и размеру сообщения.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
||||
<p>Все прочие метаданные сообщений, контактов и групп содержатся в части сообщений, защищённой сквозным шифрованием.</p>
|
||||
|
||||
<h3 id="device-seizure">
|
||||
|
||||
@@ -999,82 +999,82 @@ Instead, all group metadata is end-to-end encrypted and stored on end-user devic
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Both for protecting against metadata-collecting e-mail servers
|
||||
as well as against the threat of device seizure
|
||||
we recommend to use a <a href="https://chatmail.at/relays">chatmail relay</a>
|
||||
to create chat profiles using random e-mail addresses for transport.
|
||||
Note that Delta Chat apps on all platforms support multiple profiles
|
||||
so you can easily use situation-specific profiles next to your “main” profile
|
||||
with the knowledge that all their data, along with all metadata, will be deleted.
|
||||
Moreover, if a device is seized then chat contacts using short-lived profiles
|
||||
can not be identified easily.</p>
|
||||
<p>Для защиты от серверов электронной почты, собирающих метаданные,
|
||||
а также от угрозы конфискации устройства,
|
||||
мы рекомендуем использовать <a href="https://chatmail.at/relays">релей chatmail</a>
|
||||
для создания чат-профилей с использованием случайных электронных адресов для передачи сообщений.
|
||||
Обратите внимание, что приложения Delta Chat на всех платформах поддерживают несколько профилей,
|
||||
так что вы можете легко использовать отдельные профили, для конкретной ситуации, помимо вашего “основного” профиля,
|
||||
зная, что все их данные, вместе с метаданными, будут удалены.
|
||||
Кроме того, если устройство изъято, контакты, использующие временные профили,
|
||||
не могут быть легко идентифицированы.</p>
|
||||
|
||||
<h3 id="sealedsender">
|
||||
|
||||
|
||||
Does Delta Chat support “Sealed Sender”? <a href="#sealedsender" class="anchor"></a>
|
||||
Поддерживает ли Delta Chat функцию “Sealed Sender” (Засекреченный отправитель)? <a href="#sealedsender" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Нет, пока нет.</p>
|
||||
|
||||
<p>The Signal messenger introduced <a href="https://signal.org/blog/sealed-sender/">“Sealed Sender” in 2018</a>
|
||||
to keep their server infrastructure ignorant of who is sending a message to a set of recipients.
|
||||
It is particularly important because the Signal server knows the mobile number of each account,
|
||||
which is usually associated with a passport identity.</p>
|
||||
<p>Мессенджер Signal внедрил функцию <a href="https://signal.org/blog/sealed-sender/">“Sealed Sender” (Засекреченный отправитель) в 2018 году</a>,
|
||||
чтобы их серверная инфраструктура не имела информации о том, кто отправляет сообщение группе получателей.
|
||||
Это особенно важно, поскольку сервер Signal знает мобильный номер каждого аккаунта,
|
||||
который обычно привязан к паспортным данным.</p>
|
||||
|
||||
<p>Even if <a href="https://chatmail.at/relays">chatmail relays</a>
|
||||
do not ask for any private data (including no phone numbers),
|
||||
it might still be worthwhile to protect relational metadata between addresses.
|
||||
We don’t foresee bigger problems in using random throw-away e-mail addresses for sealed sending
|
||||
but an implementation has not been agreed as a priority yet.</p>
|
||||
<p>Даже если <a href="https://chatmail.at/relays">релеи chatmail</a>
|
||||
не запрашивают никаких личных данных (включая телефонные номера),
|
||||
всё равно может быть полезно защитить реляционные метаданные между адресами
|
||||
Мы не видим серьёзных проблем в использовании случайных одноразовых электронных адресов для функции sealed sender,
|
||||
но реализация пока не определена как приоритетная задача.</p>
|
||||
|
||||
<h3 id="pfs">
|
||||
|
||||
|
||||
Поддерживает ли Delta Chat совершенную прямую секретность (Perfect forward secrecy, PFS)? <a href="#pfs" class="anchor"></a>
|
||||
Поддерживает ли Delta Chat свойство Perfect forward secrecy, PFS (Совершенную прямую секретность)? <a href="#pfs" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Нет, пока нет.</p>
|
||||
|
||||
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||
This means that if your private decryption key is leaked,
|
||||
and someone has collected your prior in-transit messages,
|
||||
they will be able to decrypt and read them using the leaked decryption key.
|
||||
Note that Forward Secrecy only increases security if you delete messages.
|
||||
Otherwise, someone obtaining your decryption keys
|
||||
is typically also able to get all your non-deleted messages
|
||||
and doesn’t even need to decrypt any previously collected messages.</p>
|
||||
<p>На данный момент, Delta Chat не поддерживает Perfect Forward Secrecy (PFS) (Совершенную прямую секретность).
|
||||
Это означает, что если ваш приватный ключ дешифрования будет скомпрометирован,
|
||||
и кто-то собрал ваши предыдущие сообщения во время передачи,
|
||||
они смогут расшифровать и прочитать их, используя скомпрометированный ключ дешифрования.
|
||||
Обратите внимание, что Forward Secrecy (Прямая секретность) повышает безопасность только если вы удаляете сообщения.
|
||||
В противном случае, тот, кто получает ваши ключи дешифрования
|
||||
также может получить все ваши не удалённые сообщения
|
||||
и ему даже не нужно расшифровывать какие-либо ранее собранные сообщения.</p>
|
||||
|
||||
<p>We designed a Forward Secrecy approach that withstood
|
||||
initial examination from some cryptographers and implementation experts
|
||||
but is pending a more formal write up
|
||||
to ascertain it reliably works in federated messaging and with multi-device usage,
|
||||
before it could be implemented in <a href="https://github.com/chatmail/core">chatmail core</a>,
|
||||
which would make it available in all <a href="https://chatmail.at/clients">chatmail clients</a>.</p>
|
||||
<p>Мы разработали подход к Forward Secrecy (Прямой секретности), который прошёл
|
||||
первичную проверку некоторыми криптографами и экспертами по реализации
|
||||
но требует более формального описания
|
||||
чтобы убедиться, что он надёжно работает в федеративном обмене сообщениями и при использовании нескольких устройств,
|
||||
прежде чем он может быть внедрён в <a href="https://github.com/chatmail/core">ядро chatmail</a>,
|
||||
что сделает его доступным во всех <a href="https://chatmail.at/clients">клиентах clients</a>.</p>
|
||||
|
||||
<h3 id="pqc">
|
||||
|
||||
|
||||
Does Delta Chat support Post-Quantum-Cryptography? <a href="#pqc" class="anchor"></a>
|
||||
Поддерживает ли Delta Chat Post-Quantum-Cryptography (Постквантовую криптографию)? <a href="#pqc" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Нет, пока нет.</p>
|
||||
|
||||
<p>Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
||||
We aim to add PQC support in <a href="https://github.com/chatmail/core">chatmail core</a> after the draft is finalized at the IETF
|
||||
in collaboration with other OpenPGP implementers.</p>
|
||||
<p>Delta Chat использует библиотеку OpenPGP на Rust <a href="https://github.com/rpgp/rpgp">rPGP</a>,
|
||||
которая поддерживает последний <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">черновик IETF Post-Quantum-Cryptography OpenPGP</a>.
|
||||
Мы планируем добавить поддержку PQC в <a href="https://github.com/chatmail/core">ядро chatmail</a> после того, как черновик будет окончательно утвержден в IETF
|
||||
в сотрудничестве с другими разработчиками OpenPGP.</p>
|
||||
|
||||
<h3 id="how-can-i-manually-check-encryption-information">
|
||||
<h3 id="как-можно-вручную-проверить-информацию-о-шифровании">
|
||||
|
||||
|
||||
How can I manually check encryption information? <a href="#how-can-i-manually-check-encryption-information" class="anchor"></a>
|
||||
Как можно вручную проверить информацию о шифровании? <a href="#как-можно-вручную-проверить-информацию-о-шифровании" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -1511,10 +1511,10 @@ Delta Chat</a>.</li>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Note:
|
||||
Changing email addresses is temporarily disabled
|
||||
because of ongoing changes to the DeltaChat core.
|
||||
It should be available again in a few months.</p>
|
||||
<p>Примечание:
|
||||
Смена электронных адресов временно отключена
|
||||
из-за продолжающихся изменений в ядре DeltaChat.
|
||||
Функция должна снова заработать через несколько месяцев.</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
@@ -1617,6 +1617,29 @@ It should be available again in a few months.</p>
|
||||
см. <a href="https://providers.delta.chat">Обзор провайдеров</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="я-хочу-управлять-своим-собственным-сервером-для-delta-chat-что-вы-посоветуете">
|
||||
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#aké-povolenia-potrebuje-delta-chat">Aké povolenia potrebuje Delta Chat?</a></li>
|
||||
<li><a href="#funguje-delta-chat-s-mojím-poskytovateľom-e-mailov">Funguje Delta Chat s mojím poskytovateľom e-mailov?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</a></li>
|
||||
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
|
||||
<li><a href="#prečo-musím-zadávať-svoje-e-mailové-heslo-do-delta-chat-je-to-bezpečné">Prečo musím zadávať svoje e-mailové heslo do Delta Chat? Je to bezpečné?</a></li>
|
||||
<li><a href="#ktoré-správy-sa-zobrazujú-v-delta-chate">Ktoré správy sa zobrazujú v Delta Chate?</a></li>
|
||||
@@ -408,7 +409,7 @@ who could have already replied, forwarded, saved, screenshotted or otherwise cop
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 1 minute and 5 weeks.</p>
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Until the setting is turned off again,
|
||||
each chat member’s Delta Chat app takes care
|
||||
@@ -781,8 +782,8 @@ there are no lock or similar markers on end-to-end encrypted messages, anymore.<
|
||||
it is impossible to receive or send messages without end-to-end encryption.</p>
|
||||
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages without end-to-end encryption.
|
||||
Such messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
@@ -1623,6 +1624,29 @@ Niektorí poskytovatelia však potrebujú na správne fungovanie špeciálne mo
|
||||
pozrite si <a href="https://providers.delta.chat">Prehľad poskytovateľa</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">
|
||||
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#çleje-lyp-delta-chat-i">Ç’leje lyp Delta Chat-i?</a></li>
|
||||
<li><a href="#a-funksionon-delta-chat-me-shërbimin-tim-email">A funksionon Delta Chat me shërbimin <em>tim</em> email?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</a></li>
|
||||
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
|
||||
<li><a href="#pse-më-duhet-të-jap-fjalëkalimin-e-email-it-tim-në-delta-chat-a-është-e-sigurt-kjo">Pse më duhet të jap fjalëkalimin e email-it tim në Delta Chat? A është e sigurt kjo?</a></li>
|
||||
<li><a href="#cilat-mesazhe-shfaqen-në-delta-chat">Cilat mesazhe shfaqen në Delta Chat?</a></li>
|
||||
@@ -408,7 +409,7 @@ who could have already replied, forwarded, saved, screenshotted or otherwise cop
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 1 minute and 5 weeks.</p>
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Until the setting is turned off again,
|
||||
each chat member’s Delta Chat app takes care
|
||||
@@ -782,8 +783,8 @@ there are no lock or similar markers on end-to-end encrypted messages, anymore.<
|
||||
it is impossible to receive or send messages without end-to-end encryption.</p>
|
||||
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages without end-to-end encryption.
|
||||
Such messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
@@ -1623,6 +1624,29 @@ Sidoqoftë, disa furnizues shërbimesh kanë nevojë për mundësi speciale, që
|
||||
të funksionojnë si duhet, shihni <a href="https://providers.delta.chat">Provider Overview</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">
|
||||
|
||||
|
||||
|
||||
+102
-146
@@ -40,20 +40,20 @@
|
||||
<ul>
|
||||
<li><a href="#які-стандарти-використовуються-для-наскрізного-шифрування">Які стандарти використовуються для наскрізного шифрування?</a></li>
|
||||
<li><a href="#whene2e">Як дізнатися, чи повідомлення зашифровано наскрізним шифруванням?</a></li>
|
||||
<li><a href="#can-i-still-receive-or-send-mails-without-end-to-end-encryption">Can i still receive or send mails without end-to-end encryption?</a></li>
|
||||
<li><a href="#howtoe2ee">How can I establish a chat with a new contact?</a></li>
|
||||
<li><a href="#e2eeguarantee">What does the green checkmark in a contact profile mean?</a></li>
|
||||
<li><a href="#чи-можу-я-отримувати-та-надсилати-пошту-без-наскрізного-шифрування">Чи можу я отримувати та надсилати пошту без наскрізного шифрування?</a></li>
|
||||
<li><a href="#howtoe2ee">Як створити чат з новим контактом?</a></li>
|
||||
<li><a href="#e2eeguarantee">Що означає зелена галочка в профілі контакту?</a></li>
|
||||
<li><a href="#чи-зашифровані-наскрізно-вкладення-зображення-файли-аудіо-тощо">Чи зашифровані наскрізно вкладення (зображення, файли, аудіо тощо)?</a></li>
|
||||
<li><a href="#openpgp-secure">Чи безпечний OpenPGP?</a></li>
|
||||
<li><a href="#openpgp-alternatives">Did you consider using alternatives to OpenPGP for end-to-end-encryption?</a></li>
|
||||
<li><a href="#openpgp-alternatives">Чи розглядали ви можливість використання альтернатив OpenPGP для наскрізного шифрування?</a></li>
|
||||
<li><a href="#чи-вразливий-delta-chat-до-efail">Чи вразливий Delta Chat до EFAIL?</a></li>
|
||||
<li><a href="#tls">Are messages marked with the mail icon exposed on the Internet?</a></li>
|
||||
<li><a href="#чи-повідомлення-позначені-значком-пошти-доступні-в-інтернетіtls">Чи повідомлення, позначені значком пошти, доступні в Інтернеті?{#tls}</a></li>
|
||||
<li><a href="#message-metadata">Як Delta Chat захищає метадані у повідомленнях?</a></li>
|
||||
<li><a href="#device-seizure">Як захистити метадані та контакти якщо пристрій вилучено?</a></li>
|
||||
<li><a href="#sealedsender">Does Delta Chat support “Sealed Sender”?</a></li>
|
||||
<li><a href="#sealedsender">Чи підтримує Delta Chat функцію “Запечатаний відправник”?</a></li>
|
||||
<li><a href="#pfs">Чи підтримує Delta Chat цілковиту пряму секретність (Perfect Forward Secrecy)?</a></li>
|
||||
<li><a href="#pqc">Does Delta Chat support Post-Quantum-Cryptography?</a></li>
|
||||
<li><a href="#how-can-i-manually-check-encryption-information">How can I manually check encryption information?</a></li>
|
||||
<li><a href="#pqc">Чи підтримує Delta Chat пост-квантову криптографію?</a></li>
|
||||
<li><a href="#як-я-можу-вручну-перевірити-інформацію-про-шифрування">Як я можу вручну перевірити інформацію про шифрування?</a></li>
|
||||
<li><a href="#importkey">Чи можна повторно використовувати існуючий закритий ключ?</a></li>
|
||||
<li><a href="#security-audits">Чи проходив Delta Chat незалежний аудит на наявність вразливостей у безпеці?</a></li>
|
||||
</ul>
|
||||
@@ -87,7 +87,8 @@
|
||||
<ul>
|
||||
<li><a href="#яких-дозволів-потребує-delta-chat">Яких дозволів потребує Delta Chat?</a></li>
|
||||
<li><a href="#чи-підтримує-delta-chat-роботу-з-моїм-провайдером-електронної-пошти">Чи підтримує Delta Chat роботу з <em>моїм</em> провайдером електронної пошти?</a></li>
|
||||
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</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>
|
||||
<li><a href="#чи-підтримує-delta-chat-html-листи">Чи підтримує Delta Chat HTML-листи?</a></li>
|
||||
@@ -358,7 +359,11 @@
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Увімкнути “повідомлення, що зникають” можна в налаштуваннях чату, у верхньому правому куті вікна чату, вибравши проміжок часу від 1 хвилини до 5 тижнів.</p>
|
||||
<p>You can turn on “disappearing messages”
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>Доки налаштування не буде знову вимкнено, додаток Delta Chat кожного учасника чату піклується про видалення повідомлень через вибраний проміжок часу. Проміжок часу починається коли одержувач вперше побачив повідомлення в Delta Chat. Повідомлення видаляються як з кожної поштової скриньки на сервері, так і в самому додатку.</p>
|
||||
|
||||
@@ -606,26 +611,21 @@ Push-сповіщення автоматично активуються для
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat uses a <a href="#openpgp-secure">secure subset of the OpenPGP standard</a>
|
||||
to provide automatic end-to-end encryption using these protocols:</p>
|
||||
<p>Delta Chat використовує <a href="#openpgp-secure">безпечну підмножину стандарту OpenPGP</a> для забезпечення автоматичного наскрізного шифрування за допомогою цих протоколів:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p><a href="https://securejoin.delta.chat/en/latest/new.html">Secure-Join</a>
|
||||
to exchange encryption setup information through QR-code scanning or “invite links”.</p>
|
||||
<p>Використовуйте <a href="https://securejoin.delta.chat/en/latest/new.html">Secure-Join</a> щоб обмінюватися інформацією про налаштування шифрування, через сканування QR-коду або “посилання-запрошення”.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="https://autocrypt.org">Autocrypt</a> is used for automatically
|
||||
establishing end-to-end encryption between contacts and all members of a group chat.</p>
|
||||
<p><a href="https://autocrypt.org">Autocrypt</a> використовується для автоматичного встановлення наскрізного шифрування між контактами і всіма учасниками групового чату.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Sharing a contact to a
|
||||
chat</a>
|
||||
enables receivers to use end-to-end encryption with the contact.</p>
|
||||
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Поширення контакту в чаті</a> дозволяє отримувачам використовувати наскрізне шифрування з контактом.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Delta Chat does not query, publish or interact with any OpenPGP key servers.</p>
|
||||
<p>Delta Chat не запитує, не публікує і не взаємодіє з будь-якими серверами ключів OpenPGP.</p>
|
||||
|
||||
<h3 id="whene2e">
|
||||
|
||||
@@ -635,91 +635,67 @@ enables receivers to use end-to-end encryption with the contact.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>All messages in Delta Chat are <strong>end-to-end encrypted by default</strong>.
|
||||
Since the Delta Chat Version 2 release series (July 2025)
|
||||
there are no lock or similar markers on end-to-end encrypted messages, anymore.</p>
|
||||
<p>Всі повідомлення в Delta Chat за замовчуванням <strong>наскрізно зашифровані</strong>. Починаючи з версії 2 Delta Chat (липень 2025 року) на наскрізних зашифрованих повідомленнях більше немає замків або інших подібних маркерів.</p>
|
||||
|
||||
<h3 id="can-i-still-receive-or-send-mails-without-end-to-end-encryption">
|
||||
<h3 id="чи-можу-я-отримувати-та-надсилати-пошту-без-наскрізного-шифрування">
|
||||
|
||||
|
||||
Can i still receive or send mails without end-to-end encryption? <a href="#can-i-still-receive-or-send-mails-without-end-to-end-encryption" class="anchor"></a>
|
||||
Чи можу я отримувати та надсилати пошту без наскрізного шифрування? <a href="#чи-можу-я-отримувати-та-надсилати-пошту-без-наскрізного-шифрування" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>If you use default <a href="https://chatmail.at/relays">chatmail relays</a>,
|
||||
it is impossible to receive or send messages without end-to-end encryption.</p>
|
||||
<p>Якщо ви використовуєте стандартні <a href="https://chatmail.at/relays">ретранслятори чату</a>, неможливо отримувати або надсилати повідомлення без наскрізного шифрування.</p>
|
||||
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages without end-to-end encryption.
|
||||
Such messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
|
||||
|
||||
How can I establish a chat with a new contact? <a href="#howtoe2ee" class="anchor"></a>
|
||||
Як створити чат з новим контактом? <a href="#howtoe2ee" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>You can send an invite link through another private chat,
|
||||
show an invitation QR code when next to each other or in a video call,
|
||||
or click on a “contact” that was shared in a chat.</p>
|
||||
<p>Ви можете надіслати посилання-запрошення через інший приватний чат, показати QR-код запрошення, коли ви знаходитесь поруч один з одним або під час відеодзвінка, або натиснути на “контакт”, яким ви поділилися в чаті.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Для <strong>Запрошення до групи</strong>, торкніться назви групи чату, щоб побачити список її учасників, і виберіть “QR-код запрошення”.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>For <strong>direct 1:1 chat invitations</strong>,
|
||||
tap the QR Code icon <img style="vertical-align:middle; width:1.8em; margin:1px" src="../qr-icon.png" />
|
||||
on the Delta Chat app main screen.</p>
|
||||
<p>Для <strong>прямих запрошень у чат один-на-один</strong>, торкніться іконки QR-коду <img style="vertical-align:middle; width:1.8em; margin:1px" src="../qr-icon.png" /> на головному екрані програми Delta Chat.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Ask your chat partner to scan the QR image
|
||||
with their Delta Chat app,
|
||||
or click “Copy” or “Share” to create an invite link
|
||||
and share it with your chat partner.</p>
|
||||
<p>Попросіть вашого партнера по чату відсканувати QR-зображення у своєму додатку Delta Chat, або натисніть “Копіювати” чи “Поділитися”, щоб створити посилання-запрошення і поділитися ним з вашим партнером по чату.</p>
|
||||
|
||||
<p>Now wait while <a href="https://securejoin.delta.chat/en/latest/new.html#setup-contact-protocol">end-to-end encryption is getting established</a>.</p>
|
||||
<p>Тепер зачекайте, поки встановиться <a href="https://securejoin.delta.chat/en/latest/new.html#setup-contact-protocol">наскрізне шифрування</a>.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>If both sides are online, they will soon see a (group or direct) chat
|
||||
and can start messaging securely.</p>
|
||||
<p>Якщо обидві сторони онлайн, вони незабаром побачать (груповий або прямий) чат і можуть почати безпечно обмінюватися повідомленнями.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If one side is offline or in bad network,
|
||||
the ability to chat is delayed until connectivity is restored.</p>
|
||||
<p>Якщо одна зі сторін перебуває в офлайні або в поганій мережі, можливість спілкуватися в чаті затримується до відновлення з’єднання.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Congratulations!
|
||||
You now will automatically use end-to-end encryption
|
||||
with this contact.
|
||||
If you add each other to chat groups,
|
||||
end-to-end encryption will be established among all members.</p>
|
||||
<p>Вітаємо!
|
||||
Тепер ви автоматично використовуватимете наскрізне шифрування з цим контактом. Якщо ви додасте один одного в групи чату, наскрізне шифрування буде встановлено між усіма учасниками.</p>
|
||||
|
||||
<h3 id="e2eeguarantee">
|
||||
|
||||
|
||||
What does the green checkmark in a contact profile mean? <a href="#e2eeguarantee" class="anchor"></a>
|
||||
Що означає зелена галочка в профілі контакту? <a href="#e2eeguarantee" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>A contact profile might show a green checkmark
|
||||
<img style="vertical-align:middle; width:1.5em; margin:1px" src="../green-checkmark.png" alt="green checkmark" />
|
||||
and an “Introduced by” line.
|
||||
Every green-checkmarked contact either did a direct <a href="#howtoe2ee">QR-scan</a> with you
|
||||
or was introduced by a another green-checkmarked contact.
|
||||
Introductions happen automatically when adding members to groups.
|
||||
Whoever adds a green-checkmarked contact to a group with only green-checkmarked members
|
||||
becomes an introducer.
|
||||
In a contact profile you can tap on the “Introduced by …” text repeatedly
|
||||
until you get to the one with whom you directly did a <a href="#howtoe2ee">QR-scan</a>.</p>
|
||||
<p>У профілі контакту може відображатися зелена галочка <img style="vertical-align:middle; width:1.5em; margin:1px" src="../green-checkmark.png" alt="green checkmark" /> і рядок “Представлений”. Кожен контакт із зеленою галочкою або зробив пряме <a href="#howtoe2ee">QR-сканування</a> з вами або був представлений іншим контактом, позначеним зеленою галочкою. Знайомство відбувається автоматично під час додавання учасників до груп. Той, хто додає контакт із зеленою галочкою до групи, в якій є лише учасники із зеленою галочкою стає представником. У профілі контакту ви можете кілька разів натиснути на текст “Представлений …” поки не потрапите до того, з ким ви безпосередньо зробили <a href="#howtoe2ee">QR-сканування</a>.</p>
|
||||
|
||||
<p>Для більш детального обговорення “гарантованого наскрізного шифрування” будь ласка, перегляньте <a href="https://securejoin.delta.chat/en/latest/new.html">Протоколи безпечного приєднання</a> і, зокрема, прочитайте про “Перевірені групи”, технічний термін того, що тут називається чатами з “зеленою галочкою” або “гарантованим наскрізним шифруванням”.</p>
|
||||
|
||||
@@ -743,9 +719,7 @@ until you get to the one with whom you directly did a <a href="#howtoe2ee">QR-sc
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, Delta Chat uses a secure subset of OpenPGP
|
||||
requiring the whole message to be properly encrypted and signed.
|
||||
For example, “Detached signatures” are not treated as secure.</p>
|
||||
<p>Так, Delta Chat використовує безпечну підмножину OpenPGP яка вимагає, щоб все повідомлення було належним чином зашифровано і підписано. Наприклад, “відокремлені підписи” не вважаються безпечними.</p>
|
||||
|
||||
<p>OpenPGP сам по собі не є небезпечним. Більшість публічно обговорюваних проблем безпеки OpenPGP насправді виникають через недостатню зручність використання або погану реалізацію інструментів чи програм (або обох).
|
||||
Особливо важливо розрізняти OpenPGP, стандарт шифрування IETF, і GnuPG (GPG), інструмент командного рядка, що реалізує OpenPGP.
|
||||
@@ -757,7 +731,7 @@ Delta Chat скоріше використовує реалізацію OpenPGP
|
||||
<h3 id="openpgp-alternatives">
|
||||
|
||||
|
||||
Did you consider using alternatives to OpenPGP for end-to-end-encryption? <a href="#openpgp-alternatives" class="anchor"></a>
|
||||
Чи розглядали ви можливість використання альтернатив OpenPGP для наскрізного шифрування? <a href="#openpgp-alternatives" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -778,18 +752,15 @@ Delta Chat скоріше використовує реалізацію OpenPGP
|
||||
|
||||
<p>Delta Chat також ніколи не був вразливим до EFAIL-атаки “Пряма ексфільтрація” тому що він розшифровує лише “багатокомпонентні/зашифровані” повідомлення, які містять рівно одну зашифровану і підписану частину, як визначено специфікацією Autocrypt Level 1.</p>
|
||||
|
||||
<h3 id="tls">
|
||||
<h3 id="чи-повідомлення-позначені-значком-пошти-доступні-в-інтернетіtls">
|
||||
|
||||
|
||||
Are messages marked with the mail icon exposed on the Internet? <a href="#tls" class="anchor"></a>
|
||||
Чи повідомлення, позначені значком пошти, доступні в Інтернеті?{#tls} <a href="#чи-повідомлення-позначені-значком-пошти-доступні-в-інтернетіtls" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>If you are sending or receiving e-mail messages without end-to-end encryption (using a classic e-mail server),
|
||||
they are still protected from cell or cable companies who can not read or modify your e-mail messages.
|
||||
But both your and your recipient’s e-mail providers
|
||||
may read, analyze or modify your messages, including any attachments.</p>
|
||||
<p>Якщо ви надсилаєте або отримуєте електронні листи без наскрізного шифрування (використовуючи класичний сервер електронної пошти), вони все одно захищені від мобільних або кабельних компаній, які не можуть читати чи змінювати ваші повідомлення. Однак як ваш, так і поштовий провайдер одержувача можуть читати, аналізувати або змінювати ваші листи, включаючи будь-які вкладення.</p>
|
||||
|
||||
<p>За замовчуванням Delta Chat використовує суворе <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">TLS-шифрування</a> яке захищає з’єднання між вашим пристроєм і провайдером електронної пошти. Вся робота з TLS-шифруванням Delta Chat пройшла незалежний <a href="#security-audits">аудит безпеки</a>. Крім того, з’єднання між вашим провайдером та провайдером електронної пошти одержувача зазвичай також шифрується при передачі даних. Якщо задіяні поштові сервери підтримують <a href="https://datatracker.ietf.org/doc/html/rfc8461">MTA-STS</a> то між провайдерами електронної пошти буде застосовуватися транспортне шифрування в цьому випадку повідомлення Delta Chat ніколи не будуть доступні в Інтернеті у вигляді відкритого тексту навіть якщо повідомлення не було наскрізь зашифровано.</p>
|
||||
|
||||
@@ -801,25 +772,23 @@ may read, analyze or modify your messages, including any attachments.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Unlike most other messengers,
|
||||
Delta Chat apps do not store any metadata about contacts or groups on servers, also not in encrypted form.
|
||||
Instead, all group metadata is end-to-end encrypted and stored on end-user devices, only.</p>
|
||||
<p>На відміну від більшості інших месенджерів, додатки Delta Chat не зберігають жодних метаданих про контакти чи групи на серверах, навіть у зашифрованому вигляді. Натомість усі метадані груп наскрізно зашифровані та зберігаються виключно на пристроях користувачів.</p>
|
||||
|
||||
<p>E-mail Servers can therefore only see</p>
|
||||
<p>Тому поштові сервери можуть бачити лише</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>the message date,</p>
|
||||
<p>дату повідомлення,</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>sender and receiver addresses</p>
|
||||
<p>адреси відправника та одержувача</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>and message size.</p>
|
||||
<p>і розмір повідомлення.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
||||
<p>Усі інші метадані повідомлень, контактів і груп містяться в наскрізно зашифрованій частині повідомлень.</p>
|
||||
|
||||
<h3 id="device-seizure">
|
||||
|
||||
@@ -829,36 +798,21 @@ Instead, all group metadata is end-to-end encrypted and stored on end-user devic
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Both for protecting against metadata-collecting e-mail servers
|
||||
as well as against the threat of device seizure
|
||||
we recommend to use a <a href="https://chatmail.at/relays">chatmail relay</a>
|
||||
to create chat profiles using random e-mail addresses for transport.
|
||||
Note that Delta Chat apps on all platforms support multiple profiles
|
||||
so you can easily use situation-specific profiles next to your “main” profile
|
||||
with the knowledge that all their data, along with all metadata, will be deleted.
|
||||
Moreover, if a device is seized then chat contacts using short-lived profiles
|
||||
can not be identified easily.</p>
|
||||
<p>Для захисту як від серверів електронної пошти, що збирають метадані, так і від загрози вилучення пристрою, ми рекомендуємо використовувати <a href="https://chatmail.at/relays">чатмейл-релей</a> для створення чат-профілів із випадковими адресами електронної пошти для передавання повідомлень. Зверніть увагу, що додатки Delta Chat на всіх платформах підтримують кілька профілів, тому ви можете легко користуватися профілями, створеними для конкретних ситуацій, поруч із вашим «основним» профілем, з упевненістю, що всі їхні дані, включно з усіма метаданими, буде видалено. Більше того, у разі вилучення пристрою ідентифікувати чат-контакти, які використовують короткочасні профілі, буде вкрай складно.</p>
|
||||
|
||||
<h3 id="sealedsender">
|
||||
|
||||
|
||||
Does Delta Chat support “Sealed Sender”? <a href="#sealedsender" class="anchor"></a>
|
||||
Чи підтримує Delta Chat функцію “Запечатаний відправник”? <a href="#sealedsender" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>No, not yet.</p>
|
||||
<p>Ні, поки ще ні.</p>
|
||||
|
||||
<p>The Signal messenger introduced <a href="https://signal.org/blog/sealed-sender/">“Sealed Sender” in 2018</a>
|
||||
to keep their server infrastructure ignorant of who is sending a message to a set of recipients.
|
||||
It is particularly important because the Signal server knows the mobile number of each account,
|
||||
which is usually associated with a passport identity.</p>
|
||||
<p>Месенджер Signal запровадив <a href="https://signal.org/blog/sealed-sender/">“Запечатаного відправника” у 2018 році</a> щоб їхня серверна інфраструктура не знала, хто надсилає повідомлення певній групі одержувачів. Це особливо важливо, оскільки сервер Signal знає номер мобільного телефону кожного акаунта, який зазвичай асоціюється з паспортними даними.</p>
|
||||
|
||||
<p>Even if <a href="https://chatmail.at/relays">chatmail relays</a>
|
||||
do not ask for any private data (including no phone numbers),
|
||||
it might still be worthwhile to protect relational metadata between addresses.
|
||||
We don’t foresee bigger problems in using random throw-away e-mail addresses for sealed sending
|
||||
but an implementation has not been agreed as a priority yet.</p>
|
||||
<p>Навіть якщо <a href="https://chatmail.at/relays">чат-мейл релей</a> не запитує ніяких приватних даних (в тому числі номерів телефонів), все одно може мати сенс захистити реляційні метадані між адресами. Ми не передбачаємо великих проблем у використанні випадкових одноразових адрес електронної пошти для запечатаних відправлень але реалізація такої можливості ще не є пріоритетною.</p>
|
||||
|
||||
<h3 id="pfs">
|
||||
|
||||
@@ -868,43 +822,28 @@ but an implementation has not been agreed as a priority yet.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>No, not yet.</p>
|
||||
<p>Ні, поки ще ні.</p>
|
||||
|
||||
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||
This means that if your private decryption key is leaked,
|
||||
and someone has collected your prior in-transit messages,
|
||||
they will be able to decrypt and read them using the leaked decryption key.
|
||||
Note that Forward Secrecy only increases security if you delete messages.
|
||||
Otherwise, someone obtaining your decryption keys
|
||||
is typically also able to get all your non-deleted messages
|
||||
and doesn’t even need to decrypt any previously collected messages.</p>
|
||||
<p>Delta Chat наразі не підтримує ідеальну пряму секретність (Perfect Forward Secrecy, PFS). Це означає, що якщо ваш приватний ключ для розшифрування буде скомпрометовано, а хтось заздалегідь зібрав ваші повідомлення під час передачі, він зможе розшифрувати та прочитати їх, використовуючи зламаний ключ. Зверніть увагу, що пряма секретність підвищує рівень безпеки лише в тому разі, якщо ви видаляєте повідомлення. Інакше, якщо хтось отримує доступ до ваших ключів розшифрування, він зазвичай також має доступ до всіх ваших невидалених повідомлень і навіть не потребує розшифровувати заздалегідь перехоплені дані.</p>
|
||||
|
||||
<p>We designed a Forward Secrecy approach that withstood
|
||||
initial examination from some cryptographers and implementation experts
|
||||
but is pending a more formal write up
|
||||
to ascertain it reliably works in federated messaging and with multi-device usage,
|
||||
before it could be implemented in <a href="https://github.com/chatmail/core">chatmail core</a>,
|
||||
which would make it available in all <a href="https://chatmail.at/clients">chatmail clients</a>.</p>
|
||||
<p>Ми розробили підхід Forward Secrecy, який витримав початкову експертизу від деяких криптографів та експертів з реалізації але чекає на більш офіційний звіт щоб переконатися, що він надійно працює в об’єднаних системах обміну повідомленнями та при використанні декількох пристроїв, перш ніж його можна буде реалізувати в <a href="https://github.com/chatmail/core">ядрі чату</a>, що зробить його доступним у всіх <a href="https://chatmail.at/clients">клієнтах чату</a>.</p>
|
||||
|
||||
<h3 id="pqc">
|
||||
|
||||
|
||||
Does Delta Chat support Post-Quantum-Cryptography? <a href="#pqc" class="anchor"></a>
|
||||
Чи підтримує Delta Chat пост-квантову криптографію? <a href="#pqc" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>No, not yet.</p>
|
||||
<p>Ні, поки ще ні.</p>
|
||||
|
||||
<p>Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
||||
We aim to add PQC support in <a href="https://github.com/chatmail/core">chatmail core</a> after the draft is finalized at the IETF
|
||||
in collaboration with other OpenPGP implementers.</p>
|
||||
<p>Delta Chat використовує бібліотеку Rust OpenPGP <a href="https://github.com/rpgp/rpgp">rPGP</a> яка підтримує останню версію <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>. Ми плануємо додати підтримку PQC у <a href="https://github.com/chatmail/core">chatmail core</a> після того, як проект буде завершено у IETF у співпраці з іншими розробниками OpenPGP.</p>
|
||||
|
||||
<h3 id="how-can-i-manually-check-encryption-information">
|
||||
<h3 id="як-я-можу-вручну-перевірити-інформацію-про-шифрування">
|
||||
|
||||
|
||||
How can I manually check encryption information? <a href="#how-can-i-manually-check-encryption-information" class="anchor"></a>
|
||||
Як я можу вручну перевірити інформацію про шифрування? <a href="#як-я-можу-вручну-перевірити-інформацію-про-шифрування" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -1109,16 +1048,13 @@ in collaboration with other OpenPGP implementers.</p>
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>webxdc apps can not send data to the Internet, or download anything.</li>
|
||||
<li>A webxdc app can only exchange data within a Delta Chat chat, with its
|
||||
copies on the devices of your chat partners. Other than that, it’s completely
|
||||
isolated from the Internet.</li>
|
||||
<li>The privacy a webxdc app offers is the privacy of your chat - as long as you
|
||||
trust the people you chat with, you can trust the webxdc app as well.</li>
|
||||
<li>This also means: it can be a privacy risk to open apps in chats with untrusted members.
|
||||
Just like with e-mail attachments, video calls or plain links:
|
||||
open them only from senders you trust, and not from spammers.
|
||||
Spammers can get to know any data you send to them, as well as your IP address.</li>
|
||||
<li>Додатки webxdc не можуть надсилати дані в Інтернет або завантажувати щось.</li>
|
||||
<li>Програма webxdc може обмінюватися даними лише в межах чату Delta Chat з її копіями на пристроях ваших партнерів по чату. В іншому, вона повністю ізольована від Інтернету.</li>
|
||||
<li>Конфіденційність, яку пропонує додаток webxdc, є конфіденційністю вашого чату - доки ви довіряєте людям, з якими ви спілкуєтеся, ви можете довіряти і додатку webxdc.</li>
|
||||
<li>Це також означає, що відкриття додатків у чатах з користувачами, яким ви не довіряєте, може становити ризик для конфіденційності.
|
||||
Так само, як і з вкладеннями електронної пошти, відеодзвінками або звичайними посиланнями:
|
||||
відкривайте їх лише від відправників, яким ви довіряєте, а не від спамерів.
|
||||
Спамери можуть дізнатися будь-які дані, які ви їм надсилаєте, а також вашу IP-адресу.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="де-я-можу-отримати-webxdc-додатки">
|
||||
@@ -1186,10 +1122,9 @@ Spammers can get to know any data you send to them, as well as your IP address.<
|
||||
|
||||
</h3>
|
||||
|
||||
<p>With a Broadcast List you can send a message to many recipients at once;
|
||||
the recipients cannot reply in that list.
|
||||
Broadcast lists are still highly experimental
|
||||
and will very probably be replaced by something else, stay tuned :)</p>
|
||||
<p>За допомогою списку розсилки ви можете надіслати повідомлення одразу багатьом одержувачам;
|
||||
одержувачі не можуть відповідати у цьому списку.
|
||||
Списки розсилки все ще дуже експериментальні і, ймовірно, будуть замінені чимось іншим, слідкуйте за новинами :)</p>
|
||||
|
||||
<h3 id="як-я-можу-поділитися-своїм-місцезнаходженням-зі-своїми-співрозмовниками-в-чаті">
|
||||
|
||||
@@ -1235,10 +1170,10 @@ and will very probably be replaced by something else, stay tuned :)</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Note:
|
||||
Changing email addresses is temporarily disabled
|
||||
because of ongoing changes to the DeltaChat core.
|
||||
It should be available again in a few months.</p>
|
||||
<p>Примітка:
|
||||
Зміна адреси електронної пошти тимчасово відключена
|
||||
через постійні зміни в ядрі DeltaChat.
|
||||
Ця функція буде знову доступна через кілька місяців.</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
@@ -1329,19 +1264,40 @@ It should be available again in a few months.</p>
|
||||
Проте для коректної роботи деяких провайдерів потрібні специфічні налаштування. Дивіться наш <a href="https://providers.delta.chat">огляд провайдерів</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
I want to manage my own server for Delta Chat. What do you recommend? <a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend" class="anchor"></a>
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="я-хочу-керувати-власним-сервером-для-delta-chat-що-ви-порекомендуєте">
|
||||
|
||||
|
||||
Я хочу керувати власним сервером для Delta Chat. Що ви порекомендуєте? <a href="#я-хочу-керувати-власним-сервером-для-delta-chat-що-ви-порекомендуєте" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>Most mail servers will work well. But what we personally recommend is a
|
||||
chatmail relay server, as described <a href="https://delta.chat/en/2023-12-13-chatmail">in this
|
||||
blogpost</a>.</li>
|
||||
<li>You can find an <a href="https://github.com/chatmail/relay">installation guide on GitHub</a>.</li>
|
||||
<li>Більшість поштових серверів будуть працювати добре. Але ми особисто рекомендуємо використовувати сервер ретрансляції чатової пошти, як описано <a href="https://delta.chat/en/2023-12-13-chatmail">в цій статті</a>.</li>
|
||||
<li>Ви можете знайти <a href="https://github.com/chatmail/relay">посібник зі встановлення на GitHub</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="чому-я-маю-вводити-пароль-до-моєї-електронної-пошти-у-delta-chat-чи-це-безпечно">
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
<ul>
|
||||
<li><a href="#delta-chat-需要哪些权限">Delta Chat 需要哪些权限?</a></li>
|
||||
<li><a href="#delta-chat-可用于-我的-电子邮件提供商吗">Delta Chat 可用于 <em>我的</em> 电子邮件提供商吗?</a></li>
|
||||
<li><a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">Can I use Delta Chat in parallel with other E-Mail apps?</a></li>
|
||||
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
|
||||
<li><a href="#为什么我必须在-delta-chat-中输入我的电子邮件密码-这样安全吗">为什么我必须在 Delta Chat 中输入我的电子邮件密码? 这样安全吗?</a></li>
|
||||
<li><a href="#哪些消息会在-delta-chat-中出现">哪些消息会在 Delta Chat 中出现?</a></li>
|
||||
@@ -394,7 +395,11 @@
|
||||
|
||||
</h3>
|
||||
|
||||
<p>您可以在聊天窗口右上角的聊天设置中通过选择 1 分钟到 5 周之间的时间跨度打开“消息定时销毁”。</p>
|
||||
<p>You can turn on “disappearing messages”
|
||||
in the settings of a chat,
|
||||
at the top right of the chat window,
|
||||
by selecting a time span
|
||||
between 5 minutes and 1 year.</p>
|
||||
|
||||
<p>在再次关闭该设置之前,
|
||||
每个聊天成员的 Delta Chat 应用都会负责
|
||||
@@ -744,8 +749,8 @@ there are no lock or similar markers on end-to-end encrypted messages, anymore.<
|
||||
it is impossible to receive or send messages without end-to-end encryption.</p>
|
||||
|
||||
<p>If you instead create a profile using a classic e-mail server,
|
||||
you can send and receive messages without end-to-end encryption.
|
||||
Such messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
you can send and receive messages with or without end-to-end encryption.
|
||||
Messages lacking end-to-end encryption are marked with an e-mail icon
|
||||
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
|
||||
|
||||
<h3 id="howtoe2ee">
|
||||
@@ -1540,6 +1545,29 @@ It should be available again in a few months.</p>
|
||||
不过,某些提供商需要一些特殊设置才能正常工作,请参阅<a href="https://providers.delta.chat">提供商概览</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="can-i-use-delta-chat-in-parallel-with-other-e-mail-apps">
|
||||
|
||||
|
||||
Can I use Delta Chat in parallel with other E-Mail apps? <a href="#can-i-use-delta-chat-in-parallel-with-other-e-mail-apps" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Yes, but it is not recommended.</p>
|
||||
|
||||
<p>Parallel usage with the same E-Mail address might lead to the following inconveniences:</p>
|
||||
|
||||
<ul>
|
||||
<li>Next to your Delta Chat notifications,
|
||||
you might also get notifications for (encrypted, so unreadable) chat mail messages
|
||||
in your other email app</li>
|
||||
<li>If Delta Chat is not running
|
||||
or “Advanced > Move automatically to the DeltaChat Folder” is disabled,
|
||||
encrypted Delta Chat messages might clutter the Inbox in your other E-Mail apps.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://support.delta.chat/t/sieve-rule-to-move-deltachat-mails-to-deltachat-folder/288/10">Sieve rules</a> can solve these problems.</p>
|
||||
|
||||
<h3 id="i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc;
|
||||
|
||||
import chat.delta.util.SettableFuture;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
/* Basic RPC Transport implementation */
|
||||
public abstract class BaseTransport implements Rpc.Transport {
|
||||
private final Map<Integer, SettableFuture<JsonNode>> requestFutures = new ConcurrentHashMap<>();
|
||||
private int requestId = 0;
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
private Thread worker;
|
||||
|
||||
/* Send a Request as raw JSON String to the RPC server */
|
||||
protected abstract void sendRequest(String jsonRequest);
|
||||
|
||||
/* Get next Response as raw JSON String from the RPC server */
|
||||
protected abstract String getResponse();
|
||||
|
||||
public ObjectMapper getObjectMapper() {
|
||||
return mapper;
|
||||
}
|
||||
|
||||
public void call(String method, JsonNode... params) throws RpcException {
|
||||
innerCall(method, params);
|
||||
}
|
||||
|
||||
public <T> T callForResult(TypeReference<T> resultType, String method, JsonNode... params) throws RpcException {
|
||||
try {
|
||||
JsonNode node = innerCall(method, params);
|
||||
if (node.isNull()) return null;
|
||||
return mapper.readValue(node.traverse(), resultType);
|
||||
} catch (IOException e) {
|
||||
throw new RpcException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private JsonNode innerCall(String method, JsonNode... params) throws RpcException {
|
||||
int id;
|
||||
synchronized (this) {
|
||||
id = ++requestId;
|
||||
ensureWorkerThread();
|
||||
}
|
||||
try {
|
||||
String jsonRequest = mapper.writeValueAsString(new Request(method, params, id));
|
||||
SettableFuture<JsonNode> future = new SettableFuture<>();
|
||||
requestFutures.put(id, future);
|
||||
sendRequest(jsonRequest);
|
||||
return future.get();
|
||||
} catch (ExecutionException e) {
|
||||
throw (RpcException)e.getCause();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RpcException(e.getMessage());
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RpcException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureWorkerThread() {
|
||||
if (worker != null) return;
|
||||
|
||||
worker = new Thread(() -> {
|
||||
while (true) {
|
||||
try {
|
||||
processResponse();
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, "jsonrpcThread");
|
||||
worker.start();
|
||||
}
|
||||
|
||||
private void processResponse() throws JsonProcessingException {
|
||||
String jsonResponse = getResponse();
|
||||
Response response = mapper.readValue(jsonResponse, Response.class);
|
||||
|
||||
if (response.id == 0) { // Got JSON-RPC notification/event, ignore
|
||||
return;
|
||||
}
|
||||
|
||||
SettableFuture<JsonNode> future = requestFutures.remove(response.id);
|
||||
if (future == null) { // Got a response with unknown ID, ignore
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.error != null) {
|
||||
future.setException(new RpcException(response.error.toString()));
|
||||
} else if (response.result != null) {
|
||||
future.set(response.result);
|
||||
} else {
|
||||
future.setException(new RpcException("Got JSON-RPC response without result or error: " + jsonResponse));
|
||||
}
|
||||
}
|
||||
|
||||
private static class Request {
|
||||
private final String jsonrpc = "2.0";
|
||||
public final String method;
|
||||
public final JsonNode[] params;
|
||||
public final int id;
|
||||
|
||||
public Request(String method, JsonNode[] params, int id) {
|
||||
this.method = method;
|
||||
this.params = params;
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Response {
|
||||
public String jsonrpc;
|
||||
public int id;
|
||||
public JsonNode result;
|
||||
public JsonNode error;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import chat.delta.rpc.types.*;
|
||||
|
||||
public class Rpc {
|
||||
|
||||
public interface Transport {
|
||||
void call(String method, JsonNode... params) throws RpcException;
|
||||
<T> T callForResult(TypeReference<T> resultType, String method, JsonNode... params) throws RpcException;
|
||||
ObjectMapper getObjectMapper();
|
||||
}
|
||||
|
||||
public final Transport transport;
|
||||
private final ObjectMapper mapper;
|
||||
|
||||
public Rpc(Transport transport) {
|
||||
this.transport = transport;
|
||||
this.mapper = transport.getObjectMapper();
|
||||
}
|
||||
|
||||
public Integer addAccount() throws RpcException {
|
||||
return transport.callForResult(new TypeReference<Integer>(){}, "add_account");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the order of accounts.
|
||||
* The provided list should contain all account IDs in the desired order.
|
||||
* If an account ID is missing from the list, it will be appended at the end.
|
||||
* If the list contains non-existent account IDs, they will be ignored.
|
||||
*/
|
||||
public void setAccountsOrder(java.util.List<Integer> order) throws RpcException {
|
||||
transport.call("set_accounts_order", mapper.valueToTree(order));
|
||||
}
|
||||
|
||||
/* Get the combined filesize of an account in bytes */
|
||||
public Integer getAccountFileSize(Integer accountId) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<Integer>(){}, "get_account_file_size", mapper.valueToTree(accountId));
|
||||
}
|
||||
|
||||
/**
|
||||
* If there was an error while the account was opened
|
||||
* and migrated to the current version,
|
||||
* then this function returns it.
|
||||
* <p>
|
||||
* This function is useful because the key-contacts migration could fail due to bugs
|
||||
* and then the account will not work properly.
|
||||
* <p>
|
||||
* After opening an account, the UI should call this function
|
||||
* and show the error string if one is returned.
|
||||
*/
|
||||
public String getMigrationError(Integer accountId) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<String>(){}, "get_migration_error", mapper.valueToTree(accountId));
|
||||
}
|
||||
|
||||
public Integer draftSelfReport(Integer accountId) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<Integer>(){}, "draft_self_report", mapper.valueToTree(accountId));
|
||||
}
|
||||
|
||||
/* Returns configuration value for the given key. */
|
||||
public String getConfig(Integer accountId, String key) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<String>(){}, "get_config", mapper.valueToTree(accountId), mapper.valueToTree(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a new email account using the provided parameters
|
||||
* and adds it as a transport.
|
||||
* <p>
|
||||
* If the email address is the same as an existing transport,
|
||||
* then this existing account will be reconfigured instead of a new one being added.
|
||||
* <p>
|
||||
* This function stops and starts IO as needed.
|
||||
* <p>
|
||||
* Usually it will be enough to only set `addr` and `password`,
|
||||
* and all the other settings will be autoconfigured.
|
||||
* <p>
|
||||
* During configuration, ConfigureProgress events are emitted;
|
||||
* they indicate a successful configuration as well as errors
|
||||
* and may be used to create a progress bar.
|
||||
* This function will return after configuration is finished.
|
||||
* <p>
|
||||
* If configuration is successful,
|
||||
* the working server parameters will be saved
|
||||
* and used for connecting to the server.
|
||||
* The parameters entered by the user will be saved separately
|
||||
* so that they can be prefilled when the user opens the server-configuration screen again.
|
||||
* <p>
|
||||
* See also:
|
||||
* - [Self::is_configured()] to check whether there is
|
||||
* at least one working transport.
|
||||
* - [Self::add_transport_from_qr()] to add a transport
|
||||
* from a server encoded in a QR code.
|
||||
* - [Self::list_transports()] to get a list of all configured transports.
|
||||
* - [Self::delete_transport()] to remove a transport.
|
||||
*/
|
||||
public void addOrUpdateTransport(Integer accountId, EnteredLoginParam param) throws RpcException {
|
||||
transport.call("add_or_update_transport", mapper.valueToTree(accountId), mapper.valueToTree(param));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new email account as a transport
|
||||
* using the server encoded in the QR code.
|
||||
* See [Self::add_or_update_transport].
|
||||
*/
|
||||
public void addTransportFromQr(Integer accountId, String qr) throws RpcException {
|
||||
transport.call("add_transport_from_qr", mapper.valueToTree(accountId), mapper.valueToTree(qr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new unencrypted group chat.
|
||||
* <p>
|
||||
* Same as [`Self::create_group_chat`], but the chat is unencrypted and can only have
|
||||
* address-contacts.
|
||||
*/
|
||||
public Integer createGroupChatUnencrypted(Integer accountId, String name) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<Integer>(){}, "create_group_chat_unencrypted", mapper.valueToTree(accountId), mapper.valueToTree(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new **broadcast channel**
|
||||
* (called "Channel" in the UI).
|
||||
* <p>
|
||||
* Broadcast channels are similar to groups on the sending device,
|
||||
* however, recipients get the messages in a read-only chat
|
||||
* and will not see who the other members are.
|
||||
* <p>
|
||||
* Called `broadcast` here rather than `channel`,
|
||||
* because the word "channel" already appears a lot in the code,
|
||||
* which would make it hard to grep for it.
|
||||
* <p>
|
||||
* After creation, the chat contains no recipients and is in _unpromoted_ state;
|
||||
* see [`CommandApi::create_group_chat`] for more information on the unpromoted state.
|
||||
* <p>
|
||||
* Returns the created chat's id.
|
||||
*/
|
||||
public Integer createBroadcast(Integer accountId, String chatName) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<Integer>(){}, "create_broadcast", mapper.valueToTree(accountId), mapper.valueToTree(chatName));
|
||||
}
|
||||
|
||||
/* Returns contact id of the created or existing DM chat with that contact */
|
||||
public Integer createChatByContactId(Integer accountId, Integer contactId) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<Integer>(){}, "create_chat_by_contact_id", mapper.valueToTree(accountId), mapper.valueToTree(contactId));
|
||||
}
|
||||
|
||||
/* Sets display name for existing contact. */
|
||||
public void changeContactName(Integer accountId, Integer contactId, String name) throws RpcException {
|
||||
transport.call("change_contact_name", mapper.valueToTree(accountId), mapper.valueToTree(contactId), mapper.valueToTree(name));
|
||||
}
|
||||
|
||||
|
||||
/* Parses a vCard file located at the given path. Returns contacts in their original order. */
|
||||
public java.util.List<VcardContact> parseVcard(String path) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<java.util.List<VcardContact>>(){}, "parse_vcard", mapper.valueToTree(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports contacts from a vCard file located at the given path.
|
||||
* <p>
|
||||
* Returns the ids of created/modified contacts in the order they appear in the vCard.
|
||||
*/
|
||||
public java.util.List<Integer> importVcard(Integer accountId, String path) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<java.util.List<Integer>>(){}, "import_vcard", mapper.valueToTree(accountId), mapper.valueToTree(path));
|
||||
}
|
||||
|
||||
/* Returns a vCard containing contacts with the given ids. */
|
||||
public String makeVcard(Integer accountId, java.util.List<Integer> contacts) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<String>(){}, "make_vcard", mapper.valueToTree(accountId), mapper.valueToTree(contacts));
|
||||
}
|
||||
|
||||
public void sendWebxdcRealtimeData(Integer accountId, Integer instanceMsgId, java.util.List<Integer> data) throws RpcException {
|
||||
transport.call("send_webxdc_realtime_data", mapper.valueToTree(accountId), mapper.valueToTree(instanceMsgId), mapper.valueToTree(data));
|
||||
}
|
||||
|
||||
public void sendWebxdcRealtimeAdvertisement(Integer accountId, Integer instanceMsgId) throws RpcException {
|
||||
transport.call("send_webxdc_realtime_advertisement", mapper.valueToTree(accountId), mapper.valueToTree(instanceMsgId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Leaves the gossip of the webxdc with the given message id.
|
||||
* <p>
|
||||
* NB: When this is called before closing a webxdc app in UIs, it must be guaranteed that
|
||||
* `send_webxdc_realtime_*()` functions aren't called for the given `instance_message_id`
|
||||
* anymore until the app is open again.
|
||||
*/
|
||||
public void leaveWebxdcRealtime(Integer accountId, Integer instanceMessageId) throws RpcException {
|
||||
transport.call("leave_webxdc_realtime", mapper.valueToTree(accountId), mapper.valueToTree(instanceMessageId));
|
||||
}
|
||||
|
||||
/* Starts an outgoing call. */
|
||||
public Integer placeOutgoingCall(Integer accountId, Integer chatId, String placeCallInfo) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<Integer>(){}, "place_outgoing_call", mapper.valueToTree(accountId), mapper.valueToTree(chatId), mapper.valueToTree(placeCallInfo));
|
||||
}
|
||||
|
||||
/* Accepts an incoming call. */
|
||||
public void acceptIncomingCall(Integer accountId, Integer msgId, String acceptCallInfo) throws RpcException {
|
||||
transport.call("accept_incoming_call", mapper.valueToTree(accountId), mapper.valueToTree(msgId), mapper.valueToTree(acceptCallInfo));
|
||||
}
|
||||
|
||||
/* Ends incoming or outgoing call. */
|
||||
public void endCall(Integer accountId, Integer msgId) throws RpcException {
|
||||
transport.call("end_call", mapper.valueToTree(accountId), mapper.valueToTree(msgId));
|
||||
}
|
||||
|
||||
/* Returns information about the call. */
|
||||
public CallInfo callInfo(Integer accountId, Integer msgId) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<CallInfo>(){}, "call_info", mapper.valueToTree(accountId), mapper.valueToTree(msgId));
|
||||
}
|
||||
|
||||
/* Returns JSON with ICE servers, to be used for WebRTC video calls. */
|
||||
public String iceServers(Integer accountId) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<String>(){}, "ice_servers", mapper.valueToTree(accountId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an HTTP GET request and returns a response.
|
||||
* <p>
|
||||
* `url` is the HTTP or HTTPS URL.
|
||||
*/
|
||||
public HttpResponse getHttpResponse(Integer accountId, String url) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<HttpResponse>(){}, "get_http_response", mapper.valueToTree(accountId), mapper.valueToTree(url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a reaction to message.
|
||||
* <p>
|
||||
* Reaction is a string of emojis separated by spaces. Reaction to a
|
||||
* single message can be sent multiple times. The last reaction
|
||||
* received overrides all previously received reactions. It is
|
||||
* possible to remove all reactions by sending an empty string.
|
||||
*/
|
||||
public Integer sendReaction(Integer accountId, Integer messageId, java.util.List<String> reaction) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<Integer>(){}, "send_reaction", mapper.valueToTree(accountId), mapper.valueToTree(messageId), mapper.valueToTree(reaction));
|
||||
}
|
||||
|
||||
/* Returns reactions to the message. */
|
||||
public Reactions getMessageReactions(Integer accountId, Integer messageId) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<Reactions>(){}, "get_message_reactions", mapper.valueToTree(accountId), mapper.valueToTree(messageId));
|
||||
}
|
||||
|
||||
/* Checks if messages can be sent to a given chat. */
|
||||
public Boolean canSend(Integer accountId, Integer chatId) throws RpcException {
|
||||
return transport.callForResult(new TypeReference<Boolean>(){}, "can_send", mapper.valueToTree(accountId), mapper.valueToTree(chatId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc;
|
||||
|
||||
public class RpcException extends Exception {
|
||||
|
||||
public RpcException(String message) { super(message); }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public class CallInfo {
|
||||
/* True if SDP offer has a video. */
|
||||
public Boolean hasVideo;
|
||||
/**
|
||||
* SDP offer.
|
||||
* <p>
|
||||
* Can be used to manually answer the call even if incoming call event was missed.
|
||||
*/
|
||||
public String sdpOffer;
|
||||
/**
|
||||
* Call state.
|
||||
* <p>
|
||||
* For example, if the call is accepted, active, canceled, declined etc.
|
||||
*/
|
||||
public CallState state;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
|
||||
|
||||
@JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="kind")
|
||||
@JsonSubTypes({@Type(value = CallState.Alerting.class, name="Alerting"), @Type(value = CallState.Active.class, name="Active"), @Type(value = CallState.Completed.class, name="Completed"), @Type(value = CallState.Missed.class, name="Missed"), @Type(value = CallState.Declined.class, name="Declined"), @Type(value = CallState.Canceled.class, name="Canceled")})
|
||||
public abstract class CallState {
|
||||
|
||||
/**
|
||||
* Fresh incoming or outgoing call that is still ringing.
|
||||
* <p>
|
||||
* There is no separate state for outgoing call that has been dialled but not ringing on the other side yet as we don't know whether the other side received our call.
|
||||
*/
|
||||
public static class Alerting extends CallState {
|
||||
}
|
||||
|
||||
/* Active call. */
|
||||
public static class Active extends CallState {
|
||||
}
|
||||
|
||||
/* Completed call that was once active and then was terminated for any reason. */
|
||||
public static class Completed extends CallState {
|
||||
/* Call duration in seconds. */
|
||||
public Integer duration;
|
||||
}
|
||||
|
||||
/* Incoming call that was not picked up within a timeout or was explicitly ended by the caller before we picked up. */
|
||||
public static class Missed extends CallState {
|
||||
}
|
||||
|
||||
/* Incoming call that was explicitly ended on our side before picking up or outgoing call that was declined before the timeout. */
|
||||
public static class Declined extends CallState {
|
||||
}
|
||||
|
||||
/**
|
||||
* Outgoing call that has been canceled on our side before receiving a response.
|
||||
* <p>
|
||||
* Incoming calls cannot be canceled, on the receiver side canceled calls usually result in missed calls.
|
||||
*/
|
||||
public static class Canceled extends CallState {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public enum EnteredCertificateChecks {
|
||||
/* `Automatic` means that provider database setting should be taken. If there is no provider database setting for certificate checks, check certificates strictly. */
|
||||
automatic,
|
||||
|
||||
/* Ensure that TLS certificate is valid for the server hostname. */
|
||||
strict,
|
||||
|
||||
/* Accept certificates that are expired, self-signed or otherwise not valid for the server hostname. */
|
||||
acceptInvalidCertificates,
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
/**
|
||||
* Login parameters entered by the user.
|
||||
* <p>
|
||||
* Usually it will be enough to only set `addr` and `password`, and all the other settings will be autoconfigured.
|
||||
*/
|
||||
public class EnteredLoginParam {
|
||||
/* Email address. */
|
||||
public String addr;
|
||||
/* TLS options: whether to allow invalid certificates and/or invalid hostnames. Default: Automatic */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public EnteredCertificateChecks certificateChecks;
|
||||
/* Imap server port. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer imapPort;
|
||||
/* Imap socket security. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Socket imapSecurity;
|
||||
/* Imap server hostname or IP address. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String imapServer;
|
||||
/* Imap username. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String imapUser;
|
||||
/* If true, login via OAUTH2 (not recommended anymore). Default: false */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Boolean oauth2;
|
||||
/* Password. */
|
||||
public String password;
|
||||
/**
|
||||
* SMTP Password.
|
||||
* <p>
|
||||
* Only needs to be specified if different than IMAP password.
|
||||
*/
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String smtpPassword;
|
||||
/* SMTP server port. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer smtpPort;
|
||||
/* SMTP socket security. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Socket smtpSecurity;
|
||||
/* SMTP server hostname or IP address. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String smtpServer;
|
||||
/* SMTP username. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String smtpUser;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public class HttpResponse {
|
||||
/* base64-encoded response body. */
|
||||
public String blob;
|
||||
/* Encoding, e.g. "utf-8". */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String encoding;
|
||||
/* MIME type, e.g. "text/plain" or "text/html". */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String mimetype;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
/* A single reaction emoji. */
|
||||
public class Reaction {
|
||||
/* Emoji frequency. */
|
||||
public Integer count;
|
||||
/* Emoji. */
|
||||
public String emoji;
|
||||
/* True if we reacted with this emoji. */
|
||||
public Boolean isFromSelf;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
/* Structure representing all reactions to a particular message. */
|
||||
public class Reactions {
|
||||
/* Unique reactions and their count, sorted in descending order. */
|
||||
public java.util.List<Reaction> reactions;
|
||||
/* Map from a contact to it's reaction to message. */
|
||||
public java.util.Map<String, java.util.List<String>> reactionsByContact;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public enum Socket {
|
||||
/* Unspecified socket security, select automatically. */
|
||||
automatic,
|
||||
|
||||
/* TLS connection. */
|
||||
ssl,
|
||||
|
||||
/* STARTTLS connection. */
|
||||
starttls,
|
||||
|
||||
/* No TLS, plaintext connection. */
|
||||
plain,
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public class VcardContact {
|
||||
/* Email address. */
|
||||
public String addr;
|
||||
/* Contact color as hex string. */
|
||||
public String color;
|
||||
/* The contact's name, or the email address if no name was given. */
|
||||
public String displayName;
|
||||
/* Public PGP key in Base64. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String key;
|
||||
/* Profile image in Base64. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String profileImage;
|
||||
/* Last update timestamp. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer timestamp;
|
||||
}
|
||||
+3
-2
@@ -1,4 +1,5 @@
|
||||
package com.b44t.messenger.util.concurrent;
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.util;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
@@ -10,4 +11,4 @@ public interface ListenableFuture<T> extends Future<T> {
|
||||
public void onSuccess(T result);
|
||||
public void onFailure(ExecutionException e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -1,4 +1,5 @@
|
||||
package com.b44t.messenger.util.concurrent;
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.util;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -133,4 +134,4 @@ public class SettableFuture<T> implements ListenableFuture<T> {
|
||||
if (exception != null) listener.onFailure(new ExecutionException(exception));
|
||||
else listener.onSuccess(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,4 +50,14 @@ public class DcAccounts {
|
||||
private native long getJsonrpcInstanceCPtr ();
|
||||
private native long getAccountCPtr (int accountId);
|
||||
private native long getSelectedAccountCPtr ();
|
||||
|
||||
public boolean isAllChatmail() {
|
||||
for (int accountId : getAll()) {
|
||||
DcContext dcContext = getAccount(accountId);
|
||||
if (!dcContext.isChatmail()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,10 @@ public class DcContext {
|
||||
public final static int DC_EVENT_WEBXDC_INSTANCE_DELETED = 2121;
|
||||
public final static int DC_EVENT_WEBXDC_REALTIME_DATA = 2150;
|
||||
public final static int DC_EVENT_ACCOUNTS_BACKGROUND_FETCH_DONE = 2200;
|
||||
public final static int DC_EVENT_INCOMING_CALL = 2550;
|
||||
public final static int DC_EVENT_INCOMING_CALL_ACCEPTED = 2560;
|
||||
public final static int DC_EVENT_OUTGOING_CALL_ACCEPTED = 2570;
|
||||
public final static int DC_EVENT_CALL_ENDED = 2580;
|
||||
|
||||
public final static int DC_IMEX_EXPORT_SELF_KEYS = 1;
|
||||
public final static int DC_IMEX_IMPORT_SELF_KEYS = 2;
|
||||
@@ -201,7 +205,6 @@ public class DcContext {
|
||||
public native boolean resendMsgs (int msg_ids[]);
|
||||
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);
|
||||
public native String getWebxdcStatusUpdates(int msg_id, int last_known_serial);
|
||||
public native void setWebxdcIntegration (String file);
|
||||
|
||||
@@ -18,7 +18,7 @@ public class DcMsg {
|
||||
public final static int DC_MSG_VOICE = 41;
|
||||
public final static int DC_MSG_VIDEO = 50;
|
||||
public final static int DC_MSG_FILE = 60;
|
||||
public final static int DC_MSG_VIDEOCHAT_INVITATION = 70;
|
||||
public final static int DC_MSG_CALL = 71;
|
||||
public final static int DC_MSG_WEBXDC = 80;
|
||||
public final static int DC_MSG_VCARD = 90;
|
||||
|
||||
@@ -155,8 +155,6 @@ public class DcMsg {
|
||||
public native boolean isInfo ();
|
||||
public native boolean hasHtml ();
|
||||
public native String getSetupCodeBegin ();
|
||||
public native String getVideochatUrl ();
|
||||
public native int getVideochatType ();
|
||||
public native void setText (String text);
|
||||
public native void setSubject (String text);
|
||||
public native void setHtml (String text);
|
||||
@@ -196,7 +194,7 @@ public class DcMsg {
|
||||
|
||||
public boolean canSave() {
|
||||
// saving info-messages out of context results in confusion, see https://github.com/deltachat/deltachat-ios/issues/2567
|
||||
return !isInfo() && getType() != DC_MSG_VIDEOCHAT_INVITATION;
|
||||
return !isInfo();
|
||||
}
|
||||
|
||||
public File getFileAsFile() {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.b44t.messenger;
|
||||
|
||||
import chat.delta.rpc.BaseTransport;
|
||||
|
||||
/* RPC transport over C FFI */
|
||||
public class FFITransport extends BaseTransport {
|
||||
private final DcJsonrpcInstance dcJsonrpcInstance;
|
||||
|
||||
public FFITransport(DcJsonrpcInstance dcJsonrpcInstance) {
|
||||
this.dcJsonrpcInstance = dcJsonrpcInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendRequest(String jsonRequest) {
|
||||
dcJsonrpcInstance.request(jsonRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponse() {
|
||||
return dcJsonrpcInstance.getNextResponse();
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
package com.b44t.messenger.rpc;
|
||||
|
||||
public class EnteredLoginParam {
|
||||
// Email address.
|
||||
private final String addr;
|
||||
|
||||
// Password.
|
||||
private final String password;
|
||||
|
||||
// ============ IMAP settings ============
|
||||
|
||||
// Server hostname or IP address.
|
||||
private final String imapServer;
|
||||
|
||||
// Server port.
|
||||
private final int imapPort;
|
||||
|
||||
// Socket security.
|
||||
private final SocketSecurity imapSecurity;
|
||||
|
||||
// Username.
|
||||
private final String imapUser;
|
||||
|
||||
// ============ SMTP settings ============
|
||||
|
||||
// Server hostname or IP address.
|
||||
private final String smtpServer;
|
||||
|
||||
// Server port.
|
||||
private final int smtpPort;
|
||||
|
||||
// Socket security.
|
||||
private final SocketSecurity smtpSecurity;
|
||||
|
||||
// Username.
|
||||
private final String smtpUser;
|
||||
|
||||
// SMTP Password. Only needs to be specified if different than IMAP password.
|
||||
private final String smtpPassword;
|
||||
|
||||
// TLS options: whether to allow invalid certificates and/or
|
||||
// invalid hostnames
|
||||
private final EnteredCertificateChecks certificateChecks;
|
||||
|
||||
// If true, login via OAUTH2 (not recommended anymore)
|
||||
private final boolean oauth2;
|
||||
|
||||
public EnteredLoginParam(String addr,
|
||||
String password,
|
||||
String imapServer,
|
||||
int imapPort,
|
||||
SocketSecurity imapSecurity,
|
||||
String imapUser,
|
||||
String smtpServer,
|
||||
int smtpPort,
|
||||
SocketSecurity smtpSecurity,
|
||||
String smtpUser,
|
||||
String smtpPassword,
|
||||
EnteredCertificateChecks certificateChecks,
|
||||
boolean oauth2) {
|
||||
this.addr = addr;
|
||||
this.password = password;
|
||||
this.imapServer = imapServer;
|
||||
this.imapPort = imapPort;
|
||||
this.imapSecurity = imapSecurity;
|
||||
this.imapUser = imapUser;
|
||||
this.smtpServer = smtpServer;
|
||||
this.smtpPort = smtpPort;
|
||||
this.smtpSecurity = smtpSecurity;
|
||||
this.smtpUser = smtpUser;
|
||||
this.smtpPassword = smtpPassword;
|
||||
this.certificateChecks = certificateChecks;
|
||||
this.oauth2 = oauth2;
|
||||
}
|
||||
|
||||
public String getAddr() {
|
||||
return addr;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public String getImapServer() {
|
||||
return imapServer;
|
||||
}
|
||||
|
||||
public int getImapPort() {
|
||||
return imapPort;
|
||||
}
|
||||
|
||||
public SocketSecurity getImapSecurity() {
|
||||
return imapSecurity;
|
||||
}
|
||||
|
||||
public String getImapUser() {
|
||||
return imapUser;
|
||||
}
|
||||
|
||||
public String getSmtpServer() {
|
||||
return smtpServer;
|
||||
}
|
||||
|
||||
public int getSmtpPort() {
|
||||
return smtpPort;
|
||||
}
|
||||
|
||||
public SocketSecurity getSmtpSecurity() {
|
||||
return smtpSecurity;
|
||||
}
|
||||
|
||||
public String getSmtpUser() {
|
||||
return smtpUser;
|
||||
}
|
||||
|
||||
public String getSmtpPassword() {
|
||||
return smtpPassword;
|
||||
}
|
||||
|
||||
public EnteredCertificateChecks getCertificateChecks() {
|
||||
return certificateChecks;
|
||||
}
|
||||
|
||||
public boolean isOauth2() {
|
||||
return oauth2;
|
||||
}
|
||||
|
||||
public enum EnteredCertificateChecks {
|
||||
automatic, strict, acceptInvalidCertificates,
|
||||
}
|
||||
|
||||
public static EnteredCertificateChecks certificateChecksFromInt(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return EnteredCertificateChecks.automatic;
|
||||
case 1:
|
||||
return EnteredCertificateChecks.strict;
|
||||
case 2:
|
||||
return EnteredCertificateChecks.acceptInvalidCertificates;
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid certificate position: " + position);
|
||||
}
|
||||
|
||||
public enum SocketSecurity {
|
||||
// Unspecified socket security, select automatically.
|
||||
automatic,
|
||||
|
||||
// TLS connection.
|
||||
ssl,
|
||||
|
||||
// STARTTLS connection.
|
||||
starttls,
|
||||
|
||||
// No TLS, plaintext connection.
|
||||
plain,
|
||||
}
|
||||
|
||||
public static SocketSecurity socketSecurityFromInt(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return SocketSecurity.automatic;
|
||||
case 1:
|
||||
return SocketSecurity.ssl;
|
||||
case 2:
|
||||
return SocketSecurity.starttls;
|
||||
case 3:
|
||||
return SocketSecurity.plain;
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid socketSecurity position: " + position);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package com.b44t.messenger.rpc;
|
||||
|
||||
import android.util.Base64;
|
||||
|
||||
public class HttpResponse {
|
||||
// base64-encoded response body.
|
||||
private final String blob;
|
||||
// MIME type, e.g. "text/plain" or "text/html".
|
||||
private final String mimetype;
|
||||
// Encoding, e.g. "utf-8".
|
||||
private final String encoding;
|
||||
|
||||
public HttpResponse(String blob, String mimetype, String encoding) {
|
||||
this.blob = blob;
|
||||
this.mimetype = mimetype;
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
public byte[] getBlob() {
|
||||
if (blob == null) {
|
||||
return null;
|
||||
}
|
||||
return Base64.decode(blob, Base64.NO_WRAP | Base64.NO_PADDING);
|
||||
}
|
||||
|
||||
public String getMimetype() {
|
||||
return mimetype;
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.b44t.messenger.rpc;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class Reaction {
|
||||
// The reaction emoji string.
|
||||
private final String emoji;
|
||||
// The count of users that have reacted with this reaction.
|
||||
private final int count;
|
||||
// true if self-account reacted with this reaction, false otherwise.
|
||||
private final boolean isFromSelf;
|
||||
|
||||
public Reaction(String emoji, int count, boolean isFromSelf) {
|
||||
this.emoji = emoji;
|
||||
this.count = count;
|
||||
this.isFromSelf = isFromSelf;
|
||||
}
|
||||
|
||||
public String getEmoji() {
|
||||
return emoji;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public boolean isFromSelf() {
|
||||
return isFromSelf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj instanceof Reaction) {
|
||||
Reaction reaction = (Reaction) obj;
|
||||
return emoji.equals(reaction.getEmoji()) && count == reaction.getCount() && isFromSelf == reaction.isFromSelf();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.b44t.messenger.rpc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Reactions {
|
||||
// Map from a contact to it's reaction to message.
|
||||
private final HashMap<Integer, String[]> reactionsByContact;
|
||||
// Unique reactions, sorted in descending order.
|
||||
private final ArrayList<Reaction> reactions;
|
||||
|
||||
public Reactions(HashMap<Integer, String[]> reactionsByContact, ArrayList<Reaction> reactions) {
|
||||
this.reactionsByContact = reactionsByContact;
|
||||
this.reactions = reactions;
|
||||
}
|
||||
|
||||
public Map<Integer, String[]> getReactionsByContact() {
|
||||
return reactionsByContact;
|
||||
}
|
||||
|
||||
public List<Reaction> getReactions() {
|
||||
return reactions;
|
||||
}
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
package com.b44t.messenger.rpc;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.b44t.messenger.DcJsonrpcInstance;
|
||||
import com.b44t.messenger.util.concurrent.SettableFuture;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class Rpc {
|
||||
private final static String TAG = Rpc.class.getSimpleName();
|
||||
|
||||
private final Map<Integer, SettableFuture<JsonElement>> requestFutures = new ConcurrentHashMap<>();
|
||||
private final DcJsonrpcInstance dcJsonrpcInstance;
|
||||
private int requestId = 0;
|
||||
private boolean started = false;
|
||||
private final Gson gson = new GsonBuilder().serializeNulls().create();
|
||||
|
||||
public Rpc(DcJsonrpcInstance dcJsonrpcInstance) {
|
||||
this.dcJsonrpcInstance = dcJsonrpcInstance;
|
||||
}
|
||||
|
||||
private void processResponse() throws JsonSyntaxException {
|
||||
String jsonResponse = dcJsonrpcInstance.getNextResponse();
|
||||
|
||||
Response response = gson.fromJson(jsonResponse, Response.class);
|
||||
if (response == null) {
|
||||
Log.e(TAG, "Error parsing JSON: " + jsonResponse);
|
||||
return;
|
||||
} else if (response.id == 0) {
|
||||
// Got JSON-RPC notification/event, ignore
|
||||
return;
|
||||
}
|
||||
|
||||
SettableFuture<JsonElement> future = requestFutures.remove(response.id);
|
||||
if (future == null) { // Got a response with unknown ID, ignore
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.error != null) {
|
||||
String message;
|
||||
try {
|
||||
message = response.error.getAsJsonObject().get("message").getAsString();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Can't get response error message: " + e);
|
||||
message = response.error.toString();
|
||||
}
|
||||
future.setException(new RpcException(message));
|
||||
} else if (response.result != null) {
|
||||
future.set(response.result);
|
||||
} else {
|
||||
future.setException(new RpcException("Got JSON-RPC response without result or error: " + jsonResponse));
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
started = true;
|
||||
new Thread(() -> {
|
||||
while (true) {
|
||||
try {
|
||||
processResponse();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, "jsonrpcThread").start();
|
||||
}
|
||||
|
||||
public SettableFuture<JsonElement> call(String method, Object... params) throws RpcException {
|
||||
if (!started) throw new RpcException("RPC not started yet.");
|
||||
|
||||
int id;
|
||||
synchronized (this) {
|
||||
id = ++requestId;
|
||||
}
|
||||
String jsonRequest = gson.toJson(new Request(method, params, id));
|
||||
SettableFuture<JsonElement> future = new SettableFuture<>();
|
||||
requestFutures.put(id, future);
|
||||
dcJsonrpcInstance.request(jsonRequest);
|
||||
return future;
|
||||
}
|
||||
|
||||
public JsonElement getResult(String method, Object... params) throws RpcException {
|
||||
try {
|
||||
return call(method, params).get();
|
||||
} catch (ExecutionException e) {
|
||||
throw (RpcException)e.getCause();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RpcException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
public String makeVcard(int accountId, int... contacts) throws RpcException {
|
||||
return gson.fromJson(getResult("make_vcard", accountId, contacts), String.class);
|
||||
}
|
||||
|
||||
public List<Integer> importVcard(int accountId, String path) throws RpcException {
|
||||
TypeToken<List<Integer>> listType = new TypeToken<List<Integer>>(){};
|
||||
return gson.fromJson(getResult("import_vcard", accountId, path), listType.getType());
|
||||
}
|
||||
|
||||
public HttpResponse getHttpResponse(int accountId, String url) throws RpcException {
|
||||
return gson.fromJson(getResult("get_http_response", accountId, url), HttpResponse.class);
|
||||
}
|
||||
|
||||
public Reactions getMsgReactions(int accountId, int msgId) throws RpcException {
|
||||
return gson.fromJson(getResult("get_message_reactions", accountId, msgId), Reactions.class);
|
||||
}
|
||||
|
||||
public int sendReaction(int accountId, int msgId, String... reaction) throws RpcException {
|
||||
return getResult("send_reaction", accountId, msgId, reaction).getAsInt();
|
||||
}
|
||||
|
||||
public int draftSelfReport(int accountId) throws RpcException {
|
||||
return getResult("draft_self_report", accountId).getAsInt();
|
||||
}
|
||||
|
||||
public void sendWebxdcRealtimeData(Integer accountId, Integer instanceMsgId, List<Integer> data) throws RpcException {
|
||||
getResult("send_webxdc_realtime_data", accountId, instanceMsgId, data);
|
||||
}
|
||||
|
||||
public void sendWebxdcRealtimeAdvertisement(Integer accountId, Integer instanceMsgId) throws RpcException {
|
||||
getResult("send_webxdc_realtime_advertisement", accountId, instanceMsgId);
|
||||
}
|
||||
|
||||
public void leaveWebxdcRealtime(Integer accountId, Integer instanceMessageId) throws RpcException {
|
||||
getResult("leave_webxdc_realtime", accountId, instanceMessageId);
|
||||
}
|
||||
|
||||
public int getAccountFileSize(int accountId) throws RpcException {
|
||||
return getResult("get_account_file_size", accountId).getAsInt();
|
||||
}
|
||||
|
||||
public void changeContactName(int accountId, int contactId, String name) throws RpcException {
|
||||
getResult("change_contact_name", accountId, contactId, name);
|
||||
}
|
||||
|
||||
public int addAccount() throws RpcException {
|
||||
return getResult("add_account").getAsInt();
|
||||
}
|
||||
|
||||
public void addTransportFromQr(int accountId, String qrCode) throws RpcException {
|
||||
getResult("add_transport_from_qr", accountId, qrCode);
|
||||
}
|
||||
|
||||
public void addOrUpdateTransport(int accountId, EnteredLoginParam param) throws RpcException {
|
||||
getResult("add_or_update_transport", accountId, param);
|
||||
}
|
||||
|
||||
public int createBroadcast(int accountId, String chatName) throws RpcException {
|
||||
return gson.fromJson(getResult("create_broadcast", accountId, chatName), Integer.class);
|
||||
}
|
||||
|
||||
public int createGroupChatUnencrypted(int accountId, String chatName) throws RpcException {
|
||||
return gson.fromJson(getResult("create_group_chat_unencrypted", accountId, chatName), Integer.class);
|
||||
}
|
||||
|
||||
public void setAccountsOrder(List<Integer> order) throws RpcException {
|
||||
getResult("set_accounts_order", order);
|
||||
}
|
||||
|
||||
private static class Request {
|
||||
private final String jsonrpc = "2.0";
|
||||
public final String method;
|
||||
public final Object[] params;
|
||||
public final int id;
|
||||
|
||||
public Request(String method, Object[] params, int id) {
|
||||
this.method = method;
|
||||
this.params = params;
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
public String getMigrationError(int accountId) throws RpcException {
|
||||
return gson.fromJson(getResult("get_migration_error", accountId), String.class);
|
||||
}
|
||||
|
||||
private static class Response {
|
||||
public final int id;
|
||||
public final JsonElement result;
|
||||
public final JsonElement error;
|
||||
|
||||
public Response(int id, JsonElement result, JsonElement error) {
|
||||
this.id = id;
|
||||
this.result = result;
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.b44t.messenger.rpc;
|
||||
|
||||
/**
|
||||
* An exception occurred while processing a request in ArcaneChat core.
|
||||
**/
|
||||
public class RpcException extends Exception {
|
||||
|
||||
public RpcException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package com.b44t.messenger.rpc;
|
||||
|
||||
import android.util.Base64;
|
||||
|
||||
public class VcardContact {
|
||||
// Email address.
|
||||
private final String addr;
|
||||
|
||||
// The contact's name, or the email address if no name was given.
|
||||
private final String displayName;
|
||||
|
||||
// Public PGP key in Base64.
|
||||
private final String key;
|
||||
|
||||
// Profile image in Base64.
|
||||
private final String profileImage;
|
||||
|
||||
// Contact color in HTML color format.
|
||||
private final String color;
|
||||
|
||||
// Last update timestamp.
|
||||
private final int timestamp;
|
||||
|
||||
public VcardContact(String addr, String displayName, String key, String profileImage, String color, int timestamp) {
|
||||
this.addr = addr;
|
||||
this.displayName = displayName;
|
||||
this.key = key;
|
||||
this.profileImage = profileImage;
|
||||
this.color = color;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public String getAddr() {
|
||||
return addr;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public byte[] getKey() {
|
||||
return key == null? null : Base64.decode(key, Base64.NO_WRAP | Base64.NO_PADDING);
|
||||
}
|
||||
|
||||
public boolean hasProfileImage() {
|
||||
return profileImage != null;
|
||||
}
|
||||
|
||||
public byte[] getProfileImage() {
|
||||
return profileImage == null? null : Base64.decode(profileImage, Base64.NO_WRAP | Base64.NO_PADDING);
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public int getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -221,16 +220,11 @@ public class AllMediaDocumentsFragment
|
||||
|
||||
private class ActionModeCallback implements ActionMode.Callback {
|
||||
|
||||
private int originalStatusBarColor;
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
mode.getMenuInflater().inflate(R.menu.profile_context, menu);
|
||||
mode.setTitle("1");
|
||||
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
setCorrectMenuVisibility(menu);
|
||||
return true;
|
||||
}
|
||||
@@ -279,8 +273,6 @@ public class AllMediaDocumentsFragment
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
actionMode = null;
|
||||
getListAdapter().clearSelection();
|
||||
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -212,16 +211,11 @@ public class AllMediaGalleryFragment
|
||||
|
||||
private class ActionModeCallback implements ActionMode.Callback {
|
||||
|
||||
private int originalStatusBarColor;
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
mode.getMenuInflater().inflate(R.menu.profile_context, menu);
|
||||
mode.setTitle("1");
|
||||
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
setCorrectMenuVisibility(menu);
|
||||
return true;
|
||||
}
|
||||
@@ -266,8 +260,6 @@ public class AllMediaGalleryFragment
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
actionMode = null;
|
||||
getListAdapter().clearSelection();
|
||||
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_VERIFIED_ONE_ON_ONE_CHATS;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -25,8 +23,7 @@ import com.b44t.messenger.DcAccounts;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcEvent;
|
||||
import com.b44t.messenger.DcEventEmitter;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
import com.b44t.messenger.FFITransport;
|
||||
|
||||
import org.thoughtcrime.securesms.connect.AccountManager;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
@@ -53,6 +50,9 @@ import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import chat.delta.rpc.Rpc;
|
||||
import chat.delta.rpc.RpcException;
|
||||
|
||||
public class ApplicationContext extends MultiDexApplication {
|
||||
private static final String TAG = ApplicationContext.class.getSimpleName();
|
||||
|
||||
@@ -109,8 +109,7 @@ public class ApplicationContext extends MultiDexApplication {
|
||||
System.loadLibrary("native-utils");
|
||||
|
||||
dcAccounts = new DcAccounts(new File(getFilesDir(), "accounts").getAbsolutePath());
|
||||
rpc = new Rpc(dcAccounts.getJsonrpcInstance());
|
||||
rpc.start();
|
||||
rpc = new Rpc(new FFITransport(dcAccounts.getJsonrpcInstance()));
|
||||
AccountManager.getInstance().migrateToDcAccounts(this);
|
||||
int[] allAccounts = dcAccounts.getAll();
|
||||
for (int accountId : allAccounts) {
|
||||
@@ -149,21 +148,6 @@ public class ApplicationContext extends MultiDexApplication {
|
||||
Log.i("DeltaChat", "shutting down event handler");
|
||||
}, "eventThread").start();
|
||||
|
||||
// migrating global notifications pref. to per-account config, added 10/July/24
|
||||
final String NOTIFICATION_PREF = "pref_key_enable_notifications";
|
||||
boolean isMuted = !Prefs.getBooleanPreference(this, NOTIFICATION_PREF, true);
|
||||
if (isMuted) {
|
||||
for (int accId : dcAccounts.getAll()) {
|
||||
dcAccounts.getAccount(accId).setMuted(true);
|
||||
}
|
||||
Prefs.removePreference(this, NOTIFICATION_PREF);
|
||||
}
|
||||
// /migrating global notifications
|
||||
|
||||
for (int accountId : allAccounts) {
|
||||
dcAccounts.getAccount(accountId).setConfig(CONFIG_VERIFIED_ONE_ON_ONE_CHATS, "1");
|
||||
}
|
||||
|
||||
// set translations before starting I/O to avoid sending untranslated MDNs (issue #2288)
|
||||
DcHelper.setStockTranslations(this);
|
||||
|
||||
|
||||
@@ -75,11 +75,14 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle, boolean ready) {
|
||||
setContentView(R.layout.activity_application_preferences);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
this.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
|
||||
|
||||
if (icicle == null) {
|
||||
initFragment(android.R.id.content, new ApplicationPreferenceFragment());
|
||||
initFragment(R.id.fragment, new ApplicationPreferenceFragment());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +94,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
||||
showBackupProvider();
|
||||
return;
|
||||
}
|
||||
Fragment fragment = getSupportFragmentManager().findFragmentById(android.R.id.content);
|
||||
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment);
|
||||
fragment.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@@ -271,7 +274,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
||||
|
||||
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
fragmentTransaction.replace(android.R.id.content, fragment);
|
||||
fragmentTransaction.replace(R.id.fragment, fragment);
|
||||
fragmentTransaction.addToBackStack(null);
|
||||
fragmentTransaction.commit();
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@ import android.view.MenuItem;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.view.WindowCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
@@ -31,7 +33,9 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
onPreCreate();
|
||||
EdgeToEdge.enable(this); // docs says to use: WindowCompat.enableEdgeToEdge(getWindow()); but it is not available
|
||||
super.onCreate(savedInstanceState);
|
||||
WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView()).setAppearanceLightStatusBars(false); // force white text in status bar
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -14,7 +14,6 @@ import androidx.appcompat.app.AlertDialog;
|
||||
import com.b44t.messenger.DcChat;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcMsg;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
@@ -24,6 +23,8 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import chat.delta.rpc.Rpc;
|
||||
|
||||
public abstract class BaseConversationItem extends LinearLayout
|
||||
implements BindableConversationItem
|
||||
{
|
||||
|
||||
@@ -10,9 +10,7 @@ import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.view.Menu;
|
||||
@@ -401,8 +399,6 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
||||
|
||||
mode.setTitle("1");
|
||||
|
||||
requireActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -445,10 +441,6 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
||||
actionMode = null;
|
||||
getListAdapter().initializeBatchMode(false);
|
||||
|
||||
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) {
|
||||
fab.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_add_white_24dp));
|
||||
|
||||
@@ -30,9 +30,11 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle, boolean ready) {
|
||||
setContentView(R.layout.activity_blocked_contacts);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setTitle(R.string.pref_blocked_contacts);
|
||||
initFragment(android.R.id.content, new BlockedAndShareContactsFragment(), getIntent().getExtras());
|
||||
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
|
||||
initFragment(R.id.fragment, new BlockedAndShareContactsFragment(), getIntent().getExtras());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,8 +23,6 @@ import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
@@ -35,7 +33,6 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
@@ -136,7 +133,6 @@ public class ContactSelectionListFragment extends Fragment
|
||||
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
|
||||
MenuInflater inflater = getActivity().getMenuInflater();
|
||||
inflater.inflate(R.menu.contact_list, menu);
|
||||
getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
setCorrectMenuVisibility(menu);
|
||||
actionMode.setTitle("1");
|
||||
return true;
|
||||
@@ -167,10 +163,6 @@ public class ContactSelectionListFragment extends Fragment
|
||||
public void onDestroyActionMode(ActionMode actionMode) {
|
||||
ContactSelectionListFragment.this.actionMode = null;
|
||||
getContactSelectionListAdapter().resetActionModeSelection();
|
||||
|
||||
TypedArray color = getActivity().getTheme().obtainStyledAttributes(new int[]{android.R.attr.statusBarColor});
|
||||
getActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK));
|
||||
color.recycle();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -74,10 +74,6 @@ import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcEvent;
|
||||
import com.b44t.messenger.DcMsg;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
import com.b44t.messenger.util.concurrent.ListenableFuture;
|
||||
import com.b44t.messenger.util.concurrent.SettableFuture;
|
||||
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.attachments.UriAttachment;
|
||||
@@ -122,13 +118,19 @@ import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener;
|
||||
import org.thoughtcrime.securesms.util.guava.Optional;
|
||||
import org.thoughtcrime.securesms.util.views.ProgressDialog;
|
||||
import org.thoughtcrime.securesms.video.recode.VideoRecoder;
|
||||
import org.thoughtcrime.securesms.videochat.VideochatUtil;
|
||||
import org.thoughtcrime.securesms.calls.CallUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import chat.delta.rpc.Rpc;
|
||||
import chat.delta.rpc.RpcException;
|
||||
import chat.delta.util.ListenableFuture;
|
||||
import chat.delta.util.SettableFuture;
|
||||
|
||||
/**
|
||||
* Activity for displaying a message thread, as well as
|
||||
* composing/sending a new message into that thread.
|
||||
@@ -448,7 +450,15 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
menu.findItem(R.id.menu_show_map).setVisible(false);
|
||||
}
|
||||
|
||||
if (!dcChat.canSend() || dcChat.isMailingList() ) {
|
||||
menu.findItem(R.id.menu_start_call).setVisible(
|
||||
Prefs.isCallsEnabled(this)
|
||||
&& dcChat.canSend()
|
||||
&& dcChat.isEncrypted()
|
||||
&& !dcChat.isSelfTalk()
|
||||
&& !dcChat.isMultiUser()
|
||||
);
|
||||
|
||||
if (!dcChat.isEncrypted() || !dcChat.canSend() || dcChat.isMailingList() ) {
|
||||
menu.findItem(R.id.menu_ephemeral_messages).setVisible(false);
|
||||
}
|
||||
|
||||
@@ -538,6 +548,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
} else if (itemId == R.id.menu_show_map) {
|
||||
WebxdcActivity.openMaps(this, chatId);
|
||||
return true;
|
||||
} else if (itemId == R.id.menu_start_call) {
|
||||
CallUtil.startCall(this, chatId);
|
||||
return true;
|
||||
} else if (itemId == R.id.menu_all_media) {
|
||||
handleAllMedia();
|
||||
return true;
|
||||
@@ -927,6 +940,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
supportActionBar.setCustomView(R.layout.conversation_title_view);
|
||||
supportActionBar.setDisplayShowCustomEnabled(true);
|
||||
supportActionBar.setDisplayShowTitleEnabled(false);
|
||||
supportActionBar.setElevation(0); // TODO: use custom toolbar instead
|
||||
|
||||
Toolbar parent = (Toolbar) supportActionBar.getCustomView().getParent();
|
||||
parent.setPadding(0,0,0,0);
|
||||
@@ -971,8 +985,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
AttachmentManager.selectGallery(this, PICK_GALLERY); break;
|
||||
case AttachmentTypeSelector.ADD_DOCUMENT:
|
||||
AttachmentManager.selectDocument(this, PICK_DOCUMENT); break;
|
||||
case AttachmentTypeSelector.INVITE_VIDEO_CHAT:
|
||||
new VideochatUtil().invite(this, chatId); break;
|
||||
case AttachmentTypeSelector.ADD_CONTACT_INFO:
|
||||
startContactChooserActivity(); break;
|
||||
case AttachmentTypeSelector.ADD_LOCATION:
|
||||
@@ -1011,7 +1023,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] vcard = rpc.makeVcard(dcContext.getAccountId(), contactId).getBytes();
|
||||
byte[] vcard = rpc.makeVcard(dcContext.getAccountId(), Collections.singletonList(contactId)).getBytes();
|
||||
String mimeType = "application/octet-stream";
|
||||
setMedia(PersistentBlobProvider.getInstance().create(this, vcard, mimeType, "vcard.vcf"), MediaType.DOCUMENT);
|
||||
} catch (RpcException e) {
|
||||
@@ -1463,7 +1475,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
Recipient author = new Recipient(this, dcContext.getContact(msg.getFromId()));
|
||||
|
||||
SlideDeck slideDeck = new SlideDeck();
|
||||
if (msg.getType() != DcMsg.DC_MSG_TEXT) {
|
||||
if (msg.hasFile()) {
|
||||
slideDeck.addSlide(MediaUtil.getSlideForMsg(this, msg));
|
||||
}
|
||||
|
||||
|
||||
@@ -77,9 +77,8 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
|
||||
private static final int MESSAGE_TYPE_THUMBNAIL_INCOMING = 6;
|
||||
private static final int MESSAGE_TYPE_DOCUMENT_OUTGOING = 7;
|
||||
private static final int MESSAGE_TYPE_DOCUMENT_INCOMING = 8;
|
||||
private static final int MESSAGE_TYPE_VIDEOCHAT_INVITE = 9;
|
||||
private static final int MESSAGE_TYPE_STICKER_INCOMING = 10;
|
||||
private static final int MESSAGE_TYPE_STICKER_OUTGOING = 11;
|
||||
private static final int MESSAGE_TYPE_STICKER_INCOMING = 9;
|
||||
private static final int MESSAGE_TYPE_STICKER_OUTGOING = 10;
|
||||
|
||||
private final Set<DcMsg> batchSelected = Collections.synchronizedSet(new HashSet<DcMsg>());
|
||||
|
||||
@@ -279,7 +278,6 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
|
||||
case MESSAGE_TYPE_STICKER_INCOMING:
|
||||
case MESSAGE_TYPE_INCOMING: return R.layout.conversation_item_received;
|
||||
case MESSAGE_TYPE_INFO: return R.layout.conversation_item_update;
|
||||
case MESSAGE_TYPE_VIDEOCHAT_INVITE:return R.layout.conversation_item_videochat;
|
||||
default: throw new IllegalArgumentException("unsupported item view type given to ConversationAdapter");
|
||||
}
|
||||
}
|
||||
@@ -303,9 +301,6 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
|
||||
else if (type == DcMsg.DC_MSG_STICKER) {
|
||||
return dcMsg.isOutgoing()? MESSAGE_TYPE_STICKER_OUTGOING : MESSAGE_TYPE_STICKER_INCOMING;
|
||||
}
|
||||
else if (type == DcMsg.DC_MSG_VIDEOCHAT_INVITATION) {
|
||||
return MESSAGE_TYPE_VIDEOCHAT_INVITE;
|
||||
}
|
||||
else {
|
||||
return dcMsg.isOutgoing()? MESSAGE_TYPE_OUTGOING : MESSAGE_TYPE_INCOMING;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.TextView;
|
||||
@@ -67,7 +66,7 @@ import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.views.ConversationAdaptiveActionsToolbar;
|
||||
import org.thoughtcrime.securesms.videochat.VideochatUtil;
|
||||
import org.thoughtcrime.securesms.calls.CallUtil;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
@@ -334,8 +333,7 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
menu.findItem(R.id.menu_context_share).setVisible(messageRecord.hasFile());
|
||||
boolean canReply = canReplyToMsg(messageRecord);
|
||||
menu.findItem(R.id.menu_context_reply).setVisible(chat.canSend() && canReply);
|
||||
boolean canEdit = canEditMsg(messageRecord);
|
||||
menu.findItem(R.id.menu_context_edit).setVisible(chat.canSend() && canEdit);
|
||||
menu.findItem(R.id.menu_context_edit).setVisible(chat.isEncrypted() && chat.canSend() && canEditMsg(messageRecord));
|
||||
boolean showReplyPrivately = chat.isMultiUser() && !messageRecord.isOutgoing() && canReply;
|
||||
menu.findItem(R.id.menu_context_reply_privately).setVisible(showReplyPrivately);
|
||||
menu.findItem(R.id.menu_add_to_home_screen).setVisible(messageRecord.getType() == DcMsg.DC_MSG_WEBXDC);
|
||||
@@ -369,8 +367,7 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
}
|
||||
|
||||
static boolean canReplyToMsg(DcMsg dcMsg) {
|
||||
boolean canReply = dcMsg.getType() != DcMsg.DC_MSG_VIDEOCHAT_INVITATION;
|
||||
if (canReply && dcMsg.isInfo()) {
|
||||
if (dcMsg.isInfo()) {
|
||||
switch (dcMsg.getInfoType()) {
|
||||
case DcMsg.DC_INFO_GROUP_NAME_CHANGED:
|
||||
case DcMsg.DC_INFO_GROUP_IMAGE_CHANGED:
|
||||
@@ -379,16 +376,16 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
case DcMsg.DC_INFO_LOCATIONSTREAMING_ENABLED:
|
||||
case DcMsg.DC_INFO_EPHEMERAL_TIMER_CHANGED:
|
||||
case DcMsg.DC_INFO_WEBXDC_INFO_MESSAGE:
|
||||
break;
|
||||
return true;
|
||||
default:
|
||||
canReply = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return canReply;
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean canEditMsg(DcMsg dcMsg) {
|
||||
return dcMsg.isOutgoing() && !dcMsg.isInfo() && dcMsg.getType() != DcMsg.DC_MSG_VIDEOCHAT_INVITATION && !dcMsg.hasHtml() && !dcMsg.getText().isEmpty();
|
||||
return dcMsg.isOutgoing() && !dcMsg.isInfo() && dcMsg.getType() != DcMsg.DC_MSG_CALL && !dcMsg.hasHtml() && !dcMsg.getText().isEmpty();
|
||||
}
|
||||
|
||||
public void handleClearChat() {
|
||||
@@ -760,9 +757,6 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
actionMode.setTitleOptionalHint(false); // the title represents important information, also indicating implicitly, more items can be selected
|
||||
}
|
||||
}
|
||||
else if (messageRecord.getType()==DcMsg.DC_MSG_VIDEOCHAT_INVITATION) {
|
||||
new VideochatUtil().join(getActivity(), messageRecord.getId());
|
||||
}
|
||||
else if(DozeReminder.isDozeReminderMsg(getContext(), messageRecord)) {
|
||||
DozeReminder.dozeReminderTapped(getContext());
|
||||
}
|
||||
@@ -878,8 +872,6 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
|
||||
private class ActionModeCallback implements ActionMode.Callback {
|
||||
|
||||
private int statusBarColor;
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
MenuInflater inflater = mode.getMenuInflater();
|
||||
@@ -887,10 +879,6 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
|
||||
mode.setTitle("1");
|
||||
|
||||
Window window = getActivity().getWindow();
|
||||
statusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
|
||||
Util.redMenuItem(menu, R.id.menu_context_delete_message);
|
||||
setCorrectMenuVisibility(menu);
|
||||
ConversationAdaptiveActionsToolbar.adjustMenuActions(menu, 10, requireActivity().getWindow().getDecorView().getMeasuredWidth());
|
||||
@@ -907,8 +895,6 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
((ConversationAdapter)list.getAdapter()).clearSelection();
|
||||
list.getAdapter().notifyDataSetChanged();
|
||||
|
||||
getActivity().getWindow().setStatusBarColor(statusBarColor);
|
||||
|
||||
actionMode = null;
|
||||
hideAddReactionView();
|
||||
}
|
||||
|
||||
@@ -40,14 +40,12 @@ import androidx.appcompat.app.AlertDialog;
|
||||
import com.b44t.messenger.DcChat;
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcMsg;
|
||||
import com.b44t.messenger.rpc.Reactions;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
import com.b44t.messenger.rpc.VcardContact;
|
||||
|
||||
import org.thoughtcrime.securesms.audio.AudioSlidePlayer;
|
||||
import org.thoughtcrime.securesms.components.AudioView;
|
||||
import org.thoughtcrime.securesms.components.AvatarImageView;
|
||||
import org.thoughtcrime.securesms.components.BorderlessImageView;
|
||||
import org.thoughtcrime.securesms.components.CallItemView;
|
||||
import org.thoughtcrime.securesms.components.ConversationItemFooter;
|
||||
import org.thoughtcrime.securesms.components.ConversationItemThumbnail;
|
||||
import org.thoughtcrime.securesms.components.DocumentView;
|
||||
@@ -73,10 +71,17 @@ import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.views.Stub;
|
||||
import org.thoughtcrime.securesms.calls.CallUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import chat.delta.rpc.RpcException;
|
||||
import chat.delta.rpc.types.CallInfo;
|
||||
import chat.delta.rpc.types.CallState;
|
||||
import chat.delta.rpc.types.Reactions;
|
||||
import chat.delta.rpc.types.VcardContact;
|
||||
|
||||
/**
|
||||
* A view that displays an individual conversation item within a conversation
|
||||
* thread. Used by ComposeMessageActivity's ListActivity via a ConversationAdapter.
|
||||
@@ -118,6 +123,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
private @NonNull Stub<WebxdcView> webxdcViewStub;
|
||||
private Stub<BorderlessImageView> stickerStub;
|
||||
private Stub<VcardView> vcardViewStub;
|
||||
private Stub<CallItemView> callViewStub;
|
||||
private @Nullable EventListener eventListener;
|
||||
|
||||
private int measureCalls;
|
||||
@@ -152,6 +158,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
this.webxdcViewStub = new Stub<>(findViewById(R.id.webxdc_view_stub));
|
||||
this.stickerStub = new Stub<>(findViewById(R.id.sticker_view_stub));
|
||||
this.vcardViewStub = new Stub<>(findViewById(R.id.vcard_view_stub));
|
||||
this.callViewStub = new Stub<>(findViewById(R.id.call_view_stub));
|
||||
this.groupSenderHolder = findViewById(R.id.group_sender_holder);
|
||||
this.quoteView = findViewById(R.id.quote_view);
|
||||
this.container = findViewById(R.id.container);
|
||||
@@ -322,6 +329,11 @@ public class ConversationItem extends BaseConversationItem
|
||||
vcardViewStub.get().setFocusable(!shouldInterceptClicks(messageRecord) && batchSelected.isEmpty());
|
||||
vcardViewStub.get().setClickable(batchSelected.isEmpty());
|
||||
}
|
||||
|
||||
if (callViewStub.resolved()) {
|
||||
callViewStub.get().setFocusable(!shouldInterceptClicks(messageRecord) && batchSelected.isEmpty());
|
||||
callViewStub.get().setClickable(batchSelected.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
private void setContentDescription() {
|
||||
@@ -338,6 +350,8 @@ public class ConversationItem extends BaseConversationItem
|
||||
desc += webxdcViewStub.get().getDescription() + "\n";
|
||||
} else if (vcardViewStub.resolved() && vcardViewStub.get().getVisibility() == View.VISIBLE) {
|
||||
desc += vcardViewStub.get().getDescription() + "\n";
|
||||
} else if (callViewStub.resolved() && callViewStub.get().getVisibility() == View.VISIBLE) {
|
||||
desc += callViewStub.get().getDescription() + "\n";
|
||||
} else if (mediaThumbnailStub.resolved() && mediaThumbnailStub.get().getVisibility() == View.VISIBLE) {
|
||||
desc += mediaThumbnailStub.get().getDescription() + "\n";
|
||||
} else if (stickerStub.resolved() && stickerStub.get().getVisibility() == View.VISIBLE) {
|
||||
@@ -399,7 +413,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
|
||||
String text = messageRecord.getText();
|
||||
|
||||
if (text.isEmpty()) {
|
||||
if (messageRecord.getType() == DcMsg.DC_MSG_CALL || text.isEmpty()) {
|
||||
bodyText.setVisibility(View.GONE);
|
||||
}
|
||||
else {
|
||||
@@ -490,6 +504,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
|
||||
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
int duration = messageRecord.getDuration();
|
||||
@@ -515,6 +530,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
|
||||
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
documentViewStub.get().setDocument(new DocumentSlide(context, messageRecord));
|
||||
@@ -533,6 +549,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
|
||||
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
|
||||
|
||||
webxdcViewStub.get().setWebxdc(messageRecord, context.getString(R.string.webxdc_app));
|
||||
webxdcViewStub.get().setWebxdcClickListener(new ThumbnailClickListener());
|
||||
@@ -550,6 +567,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
|
||||
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
|
||||
|
||||
vcardViewStub.get().setVcard(glideRequests, new VcardSlide(context, messageRecord), rpc);
|
||||
vcardViewStub.get().setVcardClickListener(new ThumbnailClickListener());
|
||||
@@ -561,6 +579,27 @@ public class ConversationItem extends BaseConversationItem
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
footer.setVisibility(VISIBLE);
|
||||
}
|
||||
else if (messageRecord.getType() == DcMsg.DC_MSG_CALL) {
|
||||
callViewStub.get().setVisibility(View.VISIBLE);
|
||||
if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE);
|
||||
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE);
|
||||
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
|
||||
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
|
||||
|
||||
try {
|
||||
callViewStub.get().setCallItem(messageRecord.isOutgoing(), rpc.callInfo(dcContext.getAccountId(), messageRecord.getId()));
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Error in Rpc.callInfo", e);
|
||||
}
|
||||
callViewStub.get().setCallClickListener(new CallClickListener());
|
||||
callViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
|
||||
callViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
else if (hasThumbnail(messageRecord)) {
|
||||
mediaThumbnailStub.get().setVisibility(View.VISIBLE);
|
||||
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE);
|
||||
@@ -568,6 +607,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
|
||||
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
|
||||
|
||||
Slide slide = MediaUtil.getSlideForMsg(context, messageRecord);
|
||||
|
||||
@@ -607,6 +647,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
|
||||
if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE);
|
||||
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
|
||||
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
|
||||
|
||||
bodyBubble.setBackgroundColor(Color.TRANSPARENT);
|
||||
|
||||
@@ -627,6 +668,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
|
||||
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
|
||||
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
|
||||
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -757,11 +799,11 @@ public class ConversationItem extends BaseConversationItem
|
||||
|
||||
private void setReactions(@NonNull DcMsg current) {
|
||||
try {
|
||||
Reactions reactions = rpc.getMsgReactions(dcContext.getAccountId(), current.getId());
|
||||
Reactions reactions = rpc.getMessageReactions(dcContext.getAccountId(), current.getId());
|
||||
if (reactions == null) {
|
||||
reactionsView.clear();
|
||||
} else {
|
||||
reactionsView.setReactions(reactions.getReactions());
|
||||
reactionsView.setReactions(reactions.reactions);
|
||||
reactionsView.setOnClickListener(view -> {
|
||||
if (eventListener != null && batchSelected.isEmpty()) {
|
||||
eventListener.onReactionClicked(current);
|
||||
@@ -780,6 +822,8 @@ public class ConversationItem extends BaseConversationItem
|
||||
return stickerStub.get().getFooter();
|
||||
} else if (hasOnlyThumbnail(messageRecord) && TextUtils.isEmpty(messageRecord.getText())) {
|
||||
return mediaThumbnailStub.get().getFooter();
|
||||
} else if (messageRecord.getType() == DcMsg.DC_MSG_CALL) {
|
||||
return callViewStub.get().getFooter();
|
||||
} else {
|
||||
return footer;
|
||||
}
|
||||
@@ -881,6 +925,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
else if (documentViewStub.resolved()) documentViewStub.get().performClick();
|
||||
else if (webxdcViewStub.resolved()) webxdcViewStub.get().performClick();
|
||||
else if (vcardViewStub.resolved()) vcardViewStub.get().performClick();
|
||||
else if (callViewStub.resolved()) callViewStub.get().performClick();
|
||||
}
|
||||
|
||||
/// Event handlers
|
||||
@@ -896,7 +941,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
String path = slide.asAttachment().getRealPath(context);
|
||||
VcardContact vcardContact = rpc.parseVcard(path).get(0);
|
||||
new AlertDialog.Builder(context)
|
||||
.setMessage(context.getString(R.string.ask_start_chat_with, vcardContact.getDisplayName()))
|
||||
.setMessage(context.getString(R.string.ask_start_chat_with, vcardContact.displayName))
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
try {
|
||||
List<Integer> contactIds = rpc.importVcard(dcContext.getAccountId(), path);
|
||||
@@ -942,4 +987,21 @@ public class ConversationItem extends BaseConversationItem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class CallClickListener implements CallItemView.CallClickListener {
|
||||
public void onClick(final View v, final CallInfo callInfo) {
|
||||
if (shouldInterceptClicks(messageRecord) || !batchSelected.isEmpty()) {
|
||||
performClick();
|
||||
} else {
|
||||
int accId = dcContext.getAccountId();
|
||||
int chatId = messageRecord.getChatId();
|
||||
if (!messageRecord.isOutgoing() && callInfo.state instanceof CallState.Alerting) {
|
||||
int callId = messageRecord.getId();
|
||||
CallUtil.openCall(getContext(), accId, chatId, callId, callInfo.sdpOffer);
|
||||
} else {
|
||||
CallUtil.startCall(getContext(), accId, chatId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +204,8 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
String archProperty = System.getProperty("os.arch");
|
||||
String arch;
|
||||
|
||||
if (archProperty.startsWith("armv7")) arch = "armeabi-v7a";
|
||||
// armv8l is 32 bit mode in 64 bit CPU:
|
||||
if (archProperty.startsWith("armv7") || archProperty.startsWith("armv8l")) arch = "armeabi-v7a";
|
||||
else if (archProperty.equals("aarch64")) arch = "arm64-v8a";
|
||||
else if (archProperty.equals("i686")) arch = "x86";
|
||||
else if (archProperty.equals("x86_64")) arch = "x86_64";
|
||||
|
||||
@@ -21,7 +21,9 @@ public class ConversationListArchiveActivity extends PassphraseRequiredActionBar
|
||||
{
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle, boolean ready) {
|
||||
setContentView(R.layout.activity_conversation_list_archive);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
|
||||
if (isRelayingMessageContent(this)) {
|
||||
getSupportActionBar().setTitle(isSharing(this) ? R.string.chat_share_with_title : R.string.forward_to);
|
||||
getSupportActionBar().setSubtitle(R.string.chat_archived_label);
|
||||
@@ -31,7 +33,7 @@ public class ConversationListArchiveActivity extends PassphraseRequiredActionBar
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(ConversationListFragment.ARCHIVE, true);
|
||||
initFragment(android.R.id.content, new ConversationListFragment(), bundle);
|
||||
initFragment(R.id.fragment, new ConversationListFragment(), bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,7 +35,6 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.annimon.stream.Stream;
|
||||
import com.b44t.messenger.DcChat;
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcContext;
|
||||
@@ -55,7 +54,6 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class ConversationListItem extends RelativeLayout
|
||||
@@ -134,6 +132,7 @@ public class ConversationListItem extends RelativeLayout
|
||||
this.fromView.setText(recipient, state!=DcMsg.DC_STATE_IN_FRESH);
|
||||
}
|
||||
|
||||
subjectView.setVisibility(chatId == DcChat.DC_CHAT_ID_ARCHIVED_LINK? GONE : VISIBLE);
|
||||
this.subjectView.setText(thread.getDisplayBody());
|
||||
this.subjectView.setTypeface(state==DcMsg.DC_STATE_IN_FRESH ? BOLD_TYPEFACE : LIGHT_TYPEFACE);
|
||||
this.subjectView.setTextColor(state==DcMsg.DC_STATE_IN_FRESH ? ThemeUtil.getThemedColor(getContext(), R.attr.conversation_list_item_unread_color)
|
||||
@@ -179,8 +178,8 @@ public class ConversationListItem extends RelativeLayout
|
||||
Recipient recipient = new Recipient(getContext(), contact);
|
||||
|
||||
fromView.setText(getHighlightedSpan(contact.getDisplayName(), highlightSubstring));
|
||||
fromView.setCompoundDrawablesWithIntrinsicBounds(0, 0, contact.isVerified()? R.drawable.ic_verified : 0, 0);
|
||||
subjectView.setText(getHighlightedSpan(contact.getAddr(), highlightSubstring));
|
||||
fromView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
subjectView.setVisibility(GONE);
|
||||
dateView.setText("");
|
||||
dateView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
archivedBadgeView.setVisibility(GONE);
|
||||
@@ -204,6 +203,7 @@ public class ConversationListItem extends RelativeLayout
|
||||
|
||||
fromView.setText(recipient, true);
|
||||
fromView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
subjectView.setVisibility(VISIBLE);
|
||||
subjectView.setText(getHighlightedSpan(messageResult.getSummarytext(512), highlightSubstring));
|
||||
|
||||
long timestamp = messageResult.getTimestamp();
|
||||
@@ -327,15 +327,12 @@ public class ConversationListItem extends RelativeLayout
|
||||
|
||||
String normalizedValue = value.toLowerCase(Util.getLocale());
|
||||
String normalizedTest = highlight.toLowerCase(Util.getLocale());
|
||||
List<String> testTokens;
|
||||
try (Stream<String> stream = Stream.of(normalizedTest.split(" "))) {
|
||||
testTokens = stream.filter(s -> !s.trim().isEmpty()).toList();
|
||||
}
|
||||
|
||||
Spannable spanned = new SpannableString(value);
|
||||
int searchStartIndex = 0;
|
||||
|
||||
for (String token : testTokens) {
|
||||
for (String token : normalizedTest.split(" ")) {
|
||||
if (token.trim().isEmpty()) continue;
|
||||
if (searchStartIndex >= spanned.length()) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.b44t.messenger.DcChat;
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcMsg;
|
||||
|
||||
import org.thoughtcrime.securesms.components.AvatarImageView;
|
||||
import org.thoughtcrime.securesms.components.ConversationItemFooter;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class ConversationVideochatItem extends LinearLayout
|
||||
implements BindableConversationItem
|
||||
{
|
||||
private TextView body;
|
||||
private ConversationItemFooter footer;
|
||||
private AvatarImageView contactPhoto;
|
||||
private ViewGroup contactPhotoHolder;
|
||||
private DcMsg dcMsg;
|
||||
|
||||
public ConversationVideochatItem(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public ConversationVideochatItem(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
this.body = findViewById(R.id.conversation_update_body);
|
||||
this.footer = findViewById(R.id.conversation_item_footer);
|
||||
this.contactPhoto = findViewById(R.id.contact_photo);
|
||||
this.contactPhotoHolder = findViewById(R.id.contact_photo_container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(@NonNull DcMsg dcMsg,
|
||||
@NonNull DcChat dcChat,
|
||||
@NonNull GlideRequests glideRequests,
|
||||
@NonNull Set<DcMsg> batchSelected,
|
||||
@NonNull Recipient conversationRecipient,
|
||||
boolean pulseUpdate)
|
||||
{
|
||||
this.dcMsg = dcMsg;
|
||||
DcContext dcContext = DcHelper.getContext(getContext());
|
||||
DcContact dcContact = dcContext.getContact(dcMsg.getFromId());
|
||||
|
||||
CharSequence line1 = dcMsg.isOutgoing()? getContext().getString(R.string.videochat_you_invited_hint) :
|
||||
getContext().getString(R.string.videochat_contact_invited_hint, dcContact.getDisplayName());
|
||||
CharSequence line2 = Util.getBoldedString(dcMsg.isOutgoing()? getContext().getString(R.string.videochat_tap_to_open) :
|
||||
getContext().getString(R.string.videochat_tap_to_join));
|
||||
|
||||
body.setText(TextUtils.concat(line1, "\n", line2));
|
||||
|
||||
contactPhoto.setAvatar(glideRequests, new Recipient(getContext(), dcContact), true);
|
||||
|
||||
setSelected(batchSelected.contains(dcMsg));
|
||||
setFooter(dcMsg);
|
||||
}
|
||||
|
||||
private void setFooter(@NonNull DcMsg dcMsg) {
|
||||
ViewUtil.updateLayoutParams(footer, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
|
||||
footer.setVisibility(VISIBLE);
|
||||
footer.setMessageRecord(dcMsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEventListener(@Nullable EventListener listener) {
|
||||
// No events to report yet
|
||||
}
|
||||
|
||||
@Override
|
||||
public DcMsg getMessageRecord() {
|
||||
return dcMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind() {
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,6 @@ import org.thoughtcrime.securesms.mms.AttachmentManager;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||
import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints;
|
||||
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
@@ -80,6 +79,7 @@ public class CreateProfileActivity extends BaseActionBarActivity {
|
||||
getSupportActionBar().setTitle(R.string.pref_profile_info_headline);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(!this.fromWelcome);
|
||||
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
|
||||
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
|
||||
|
||||
attachmentManager = new AttachmentManager(this, () -> {});
|
||||
avatarChanged = false;
|
||||
@@ -147,14 +147,13 @@ public class CreateProfileActivity extends BaseActionBarActivity {
|
||||
}
|
||||
|
||||
private void setAvatarView(Uri output) {
|
||||
final ProfileMediaConstraints constraints = new ProfileMediaConstraints();
|
||||
GlideApp.with(this)
|
||||
.asBitmap()
|
||||
.load(output)
|
||||
.skipMemoryCache(true)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.centerCrop()
|
||||
.override(constraints.getImageMaxWidth(this), constraints.getImageMaxHeight(this))
|
||||
.override(AvatarHelper.AVATAR_SIZE, AvatarHelper.AVATAR_SIZE)
|
||||
.into(new SimpleTarget<Bitmap>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
|
||||
|
||||
@@ -60,13 +60,12 @@ public class EphemeralMessagesDialog {
|
||||
.setPositiveButton(R.string.ok, (dialog, which) -> {
|
||||
final long burnAfter;
|
||||
switch (selectedChoice[0]) {
|
||||
case 1: burnAfter = TimeUnit.MINUTES.toSeconds(1); break;
|
||||
case 2: burnAfter = TimeUnit.MINUTES.toSeconds(5); break;
|
||||
case 3: burnAfter = TimeUnit.MINUTES.toSeconds(30); break;
|
||||
case 4: burnAfter = TimeUnit.HOURS.toSeconds(1); break;
|
||||
case 5: burnAfter = TimeUnit.DAYS.toSeconds(1); break;
|
||||
case 6: burnAfter = TimeUnit.DAYS.toSeconds(7); break;
|
||||
case 7: burnAfter = TimeUnit.DAYS.toSeconds(35); break;
|
||||
case 1: burnAfter = TimeUnit.MINUTES.toSeconds(5); break;
|
||||
case 2: burnAfter = TimeUnit.HOURS.toSeconds(1); break;
|
||||
case 3: burnAfter = TimeUnit.DAYS.toSeconds(1); break;
|
||||
case 4: burnAfter = TimeUnit.DAYS.toSeconds(7); break;
|
||||
case 5: burnAfter = TimeUnit.DAYS.toSeconds(35); break;
|
||||
case 6: burnAfter = TimeUnit.DAYS.toSeconds(365); break;
|
||||
default: burnAfter = 0; break;
|
||||
}
|
||||
listener.onTimeSelected(burnAfter);
|
||||
@@ -83,27 +82,23 @@ public class EphemeralMessagesDialog {
|
||||
if (timespan == 0) {
|
||||
return 0; // off
|
||||
}
|
||||
|
||||
// Choose timespan close to the current one out of available options.
|
||||
if (timespan < TimeUnit.MINUTES.toSeconds(5)) {
|
||||
return 1; // 1 minute
|
||||
}
|
||||
if (timespan < TimeUnit.MINUTES.toSeconds(30)) {
|
||||
return 2; // 5 minutes
|
||||
}
|
||||
if (timespan < TimeUnit.HOURS.toSeconds(1)) {
|
||||
return 3; // 30 minutes
|
||||
return 1; // 5 minutes
|
||||
}
|
||||
if (timespan < TimeUnit.DAYS.toSeconds(1)) {
|
||||
return 4; // 1 hour
|
||||
return 2; // 1 hour
|
||||
}
|
||||
if (timespan < TimeUnit.DAYS.toSeconds(7)) {
|
||||
return 5; // 1 day
|
||||
return 3; // 1 day
|
||||
}
|
||||
if (timespan < TimeUnit.DAYS.toSeconds(35)) {
|
||||
return 6; // 1 week
|
||||
return 4; // 1 week
|
||||
}
|
||||
return 7; // 5 weeks
|
||||
if (timespan < TimeUnit.DAYS.toSeconds(365)) {
|
||||
return 5; // 5 weeks
|
||||
}
|
||||
return 6; // 1 year
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,17 +13,19 @@ import android.webkit.WebView;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.rpc.HttpResponse;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.JsonUtils;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import chat.delta.rpc.Rpc;
|
||||
import chat.delta.rpc.types.HttpResponse;
|
||||
|
||||
public class FullMsgActivity extends WebViewActivity
|
||||
{
|
||||
public static final String MSG_ID_EXTRA = "msg_id";
|
||||
@@ -227,11 +229,12 @@ public class FullMsgActivity extends WebViewActivity
|
||||
throw new Exception("no url specified");
|
||||
}
|
||||
HttpResponse httpResponse = rpc.getHttpResponse(dcContext.getAccountId(), url);
|
||||
String mimeType = httpResponse.getMimetype();
|
||||
String mimeType = httpResponse.mimetype;
|
||||
if (mimeType == null) {
|
||||
mimeType = "application/octet-stream";
|
||||
}
|
||||
res = new WebResourceResponse(mimeType, httpResponse.getEncoding(), new ByteArrayInputStream(httpResponse.getBlob()));
|
||||
byte[] blob = JsonUtils.decodeBase64(httpResponse.blob);
|
||||
res = new WebResourceResponse(mimeType, httpResponse.encoding, new ByteArrayInputStream(blob));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
res = new WebResourceResponse("text/plain", "UTF-8", new ByteArrayInputStream(("Error: " + e.getMessage()).getBytes()));
|
||||
|
||||
@@ -23,7 +23,6 @@ import androidx.loader.app.LoaderManager;
|
||||
import com.b44t.messenger.DcChat;
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
@@ -33,6 +32,7 @@ import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
|
||||
import org.thoughtcrime.securesms.mms.AttachmentManager;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
|
||||
import org.thoughtcrime.securesms.util.SelectedContactsAdapter;
|
||||
@@ -44,6 +44,8 @@ import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
|
||||
import chat.delta.rpc.RpcException;
|
||||
|
||||
public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
implements ItemClickListener
|
||||
{
|
||||
@@ -54,7 +56,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
public static final String CLONE_CHAT_EXTRA = "clone_chat";
|
||||
|
||||
private static final int PICK_CONTACT = 1;
|
||||
public static final int AVATAR_SIZE = 210;
|
||||
private static final int REQUEST_CODE_AVATAR = 2759;
|
||||
|
||||
private DcContext dcContext;
|
||||
@@ -81,6 +82,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
unencrypted = getIntent().getBooleanExtra(UNENCRYPTED, false);
|
||||
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
|
||||
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
|
||||
|
||||
groupChatId = getIntent().getIntExtra(EDIT_GROUP_CHAT_ID, 0);
|
||||
attachmentManager = new AttachmentManager(this, () -> {});
|
||||
@@ -340,6 +342,12 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int reqCode, int resultCode, final Intent data) {
|
||||
super.onActivityResult(reqCode, resultCode, data);
|
||||
@@ -376,7 +384,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
.skipMemoryCache(true)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.centerCrop()
|
||||
.override(AVATAR_SIZE, AVATAR_SIZE)
|
||||
.override(AvatarHelper.AVATAR_SIZE, AvatarHelper.AVATAR_SIZE)
|
||||
.into(new CustomTarget<Bitmap>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
|
||||
|
||||
@@ -34,8 +34,6 @@ import androidx.loader.app.LoaderManager;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcEvent;
|
||||
import com.b44t.messenger.DcLot;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
@@ -51,7 +49,6 @@ import org.thoughtcrime.securesms.mms.AttachmentManager;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||
import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints;
|
||||
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
|
||||
import org.thoughtcrime.securesms.qr.RegistrationQrActivity;
|
||||
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
|
||||
@@ -65,6 +62,9 @@ import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Objects;
|
||||
|
||||
import chat.delta.rpc.Rpc;
|
||||
import chat.delta.rpc.RpcException;
|
||||
|
||||
public class InstantOnboardingActivity extends BaseActionBarActivity implements DcEventCenter.DcEventDelegate {
|
||||
|
||||
private static final String TAG = InstantOnboardingActivity.class.getSimpleName();
|
||||
@@ -90,7 +90,10 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
|
||||
private AttachmentManager attachmentManager;
|
||||
private Bitmap avatarBmp;
|
||||
|
||||
private @Nullable ProgressDialog progressDialog;
|
||||
private boolean cancelled;
|
||||
|
||||
private DcContext dcContext;
|
||||
|
||||
@Override
|
||||
@@ -101,6 +104,7 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
|
||||
Objects.requireNonNull(getSupportActionBar()).setTitle(R.string.onboarding_create_instant_account);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
|
||||
|
||||
boolean fromWelcome = getIntent().getBooleanExtra(FROM_WELCOME, false);
|
||||
if (DcHelper.getContext(this).isConfigured() == 1) {
|
||||
@@ -286,14 +290,13 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
}
|
||||
|
||||
private void setAvatarView(Uri output) {
|
||||
final ProfileMediaConstraints constraints = new ProfileMediaConstraints();
|
||||
GlideApp.with(this)
|
||||
.asBitmap()
|
||||
.load(output)
|
||||
.skipMemoryCache(true)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.centerCrop()
|
||||
.override(constraints.getImageMaxWidth(this), constraints.getImageMaxHeight(this))
|
||||
.override(AvatarHelper.AVATAR_SIZE, AvatarHelper.AVATAR_SIZE)
|
||||
.into(new CustomTarget<Bitmap>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
|
||||
@@ -423,7 +426,6 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
}
|
||||
|
||||
private void progressSuccess() {
|
||||
DcHelper.getEventCenter(this).endCaptureNextError();
|
||||
if (progressDialog != null) {
|
||||
progressDialog.dismiss();
|
||||
}
|
||||
@@ -482,11 +484,14 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
progressDialog = null;
|
||||
}
|
||||
|
||||
cancelled = false;
|
||||
|
||||
progressDialog = new ProgressDialog(this);
|
||||
progressDialog.setMessage(getResources().getString(R.string.one_moment));
|
||||
progressDialog.setCanceledOnTouchOutside(false);
|
||||
progressDialog.setCancelable(false);
|
||||
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getResources().getString(android.R.string.cancel), (dialog, which) -> {
|
||||
cancelled = true;
|
||||
dcContext.stopOngoingProcess();
|
||||
});
|
||||
progressDialog.show();
|
||||
@@ -497,9 +502,13 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
Rpc rpc = DcHelper.getRpc(this);
|
||||
try {
|
||||
rpc.addTransportFromQr(dcContext.getAccountId(), qrCode);
|
||||
DcHelper.getEventCenter(this).endCaptureNextError();
|
||||
progressSuccess();
|
||||
} catch (RpcException e) {
|
||||
Util.runOnMain(() -> progressError(e.getMessage()));
|
||||
DcHelper.getEventCenter(this).endCaptureNextError();
|
||||
if (!cancelled) {
|
||||
Util.runOnMain(() -> progressError(e.getMessage()));
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ public class LogViewActivity extends BaseActionBarActivity {
|
||||
transaction.commit();
|
||||
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -86,7 +86,7 @@ public abstract class MessageSelectorFragment
|
||||
.setCancelable(true)
|
||||
.setNeutralButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(positiveBtnLabel, (d, which) -> {
|
||||
dcContext.deleteMsgs(messageIds);
|
||||
Util.runOnAnyBackgroundThread(() -> dcContext.deleteMsgs(messageIds));
|
||||
if (actionMode != null) actionMode.finish();
|
||||
});
|
||||
|
||||
|
||||
@@ -23,8 +23,6 @@ import com.b44t.messenger.DcChat;
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcEvent;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
@@ -36,6 +34,9 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import chat.delta.rpc.Rpc;
|
||||
import chat.delta.rpc.RpcException;
|
||||
|
||||
public class ProfileActivity extends PassphraseRequiredActionBarActivity
|
||||
implements DcEventCenter.DcEventDelegate
|
||||
{
|
||||
@@ -109,7 +110,7 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
if (chatId != 0) {
|
||||
DcChat dcChat = dcContext.getChat(chatId);
|
||||
menu.findItem(R.id.menu_clone).setVisible(chatIsMultiUser && !chatIsMailingList && dcChat.isEncrypted());
|
||||
menu.findItem(R.id.menu_clone).setVisible(chatIsMultiUser && !chatIsInBroadcast && !chatIsMailingList);
|
||||
if (chatIsDeviceTalk) {
|
||||
menu.findItem(R.id.edit_name).setVisible(false);
|
||||
menu.findItem(R.id.show_encr_info).setVisible(false);
|
||||
@@ -315,12 +316,12 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity
|
||||
String profileImagePath;
|
||||
String title;
|
||||
Uri profileImageUri;
|
||||
boolean chatIsEncrypted = true;
|
||||
boolean enlargeAvatar = true;
|
||||
if(chatId!=0) {
|
||||
DcChat dcChat = dcContext.getChat(chatId);
|
||||
profileImagePath = dcChat.getProfileImage();
|
||||
title = dcChat.getName();
|
||||
chatIsEncrypted = dcChat.isEncrypted();
|
||||
enlargeAvatar = dcChat.isEncrypted() && !dcChat.isSelfTalk() && !dcChat.isDeviceTalk();
|
||||
} else {
|
||||
DcContact dcContact = dcContext.getContact(contactId);
|
||||
profileImagePath = dcContact.getProfileImage();
|
||||
@@ -329,7 +330,7 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
File file = new File(profileImagePath);
|
||||
|
||||
if (file.exists()) {
|
||||
if (enlargeAvatar && file.exists()) {
|
||||
profileImageUri = Uri.fromFile(file);
|
||||
String type = "image/" + profileImagePath.substring(profileImagePath.lastIndexOf(".") + 1);
|
||||
|
||||
@@ -338,7 +339,7 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity
|
||||
intent.putExtra(MediaPreviewActivity.ACTIVITY_TITLE_EXTRA, title);
|
||||
intent.putExtra( // show edit-button, if the user is allowed to edit the name/avatar
|
||||
MediaPreviewActivity.EDIT_AVATAR_CHAT_ID,
|
||||
(chatIsMultiUser && chatIsEncrypted && !chatIsInBroadcast && !chatIsMailingList) ? chatId : 0
|
||||
(chatIsMultiUser && !chatIsInBroadcast && !chatIsMailingList) ? chatId : 0
|
||||
);
|
||||
startActivity(intent);
|
||||
} else if (chatIsMultiUser){
|
||||
@@ -390,7 +391,12 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
private void onShare() {
|
||||
Intent composeIntent = new Intent();
|
||||
RelayUtil.setSharedContactId(composeIntent, contactId);
|
||||
DcContact dcContact = dcContext.getContact(contactId);
|
||||
if (dcContact.isKeyContact()) {
|
||||
RelayUtil.setSharedContactId(composeIntent, contactId);
|
||||
} else {
|
||||
RelayUtil.setSharedText(composeIntent, dcContact.getAddr());
|
||||
}
|
||||
ConversationListRelayingActivity.start(this, composeIntent);
|
||||
}
|
||||
|
||||
|
||||
@@ -278,6 +278,7 @@ public class ProfileAdapter extends RecyclerView.Adapter
|
||||
itemDataStatusText = "";
|
||||
isOutBroadcast = dcChat != null && dcChat.isOutBroadcast();
|
||||
boolean isMailingList = dcChat != null && dcChat.isMailingList();
|
||||
boolean isInBroadcast = dcChat != null && dcChat.isInBroadcast();
|
||||
boolean isSelfTalk = dcChat != null && dcChat.isSelfTalk();
|
||||
boolean isDeviceTalk = dcChat != null && dcChat.isDeviceTalk();
|
||||
memberCount = memberList!=null ? memberList.length : 0;
|
||||
@@ -311,7 +312,7 @@ public class ProfileAdapter extends RecyclerView.Adapter
|
||||
}
|
||||
*/
|
||||
|
||||
if (memberList!=null && !isMailingList) {
|
||||
if (memberList!=null && !isInBroadcast && !isMailingList) {
|
||||
itemData.add(new ItemData(ITEM_DIVIDER, null, 0));
|
||||
if (dcChat != null) {
|
||||
if (dcChat.canSend() && dcChat.isEncrypted()) {
|
||||
|
||||
@@ -3,14 +3,12 @@ package org.thoughtcrime.securesms;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -249,8 +247,6 @@ public class ProfileFragment extends Fragment
|
||||
|
||||
private class ActionModeCallback implements ActionMode.Callback {
|
||||
|
||||
private int originalStatusBarColor;
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
mode.getMenuInflater().inflate(R.menu.profile_context, menu);
|
||||
@@ -263,9 +259,6 @@ public class ProfileFragment extends Fragment
|
||||
menu.findItem(R.id.menu_select_all).setVisible(false);
|
||||
mode.setTitle("1");
|
||||
|
||||
Window window = requireActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -306,7 +299,6 @@ public class ProfileFragment extends Fragment
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
actionMode = null;
|
||||
adapter.clearSelection();
|
||||
requireActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,11 +46,6 @@ import androidx.constraintlayout.widget.Group;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcEvent;
|
||||
import com.b44t.messenger.DcProvider;
|
||||
import com.b44t.messenger.rpc.EnteredLoginParam;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
import com.b44t.messenger.util.concurrent.ListenableFuture;
|
||||
import com.b44t.messenger.util.concurrent.SettableFuture;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
@@ -66,6 +61,14 @@ import org.thoughtcrime.securesms.util.views.ProgressDialog;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import chat.delta.rpc.Rpc;
|
||||
import chat.delta.rpc.RpcException;
|
||||
import chat.delta.rpc.types.EnteredCertificateChecks;
|
||||
import chat.delta.rpc.types.EnteredLoginParam;
|
||||
import chat.delta.rpc.types.Socket;
|
||||
import chat.delta.util.ListenableFuture;
|
||||
import chat.delta.util.SettableFuture;
|
||||
|
||||
public class RegistrationActivity extends BaseActionBarActivity implements DcEventCenter.DcEventDelegate {
|
||||
|
||||
private enum VerificationType {
|
||||
@@ -87,6 +90,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
private Group advancedGroup;
|
||||
private ImageView advancedIcon;
|
||||
private ProgressDialog progressDialog;
|
||||
private boolean cancelled = false;
|
||||
|
||||
Spinner imapSecurity;
|
||||
Spinner smtpSecurity;
|
||||
@@ -135,6 +139,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
actionBar.setTitle(R.string.login_header);
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
|
||||
actionBar.setElevation(0); // TODO: use custom toolbar instead
|
||||
}
|
||||
|
||||
emailInput.addTextChangedListener(new TextWatcher() {
|
||||
@@ -562,6 +567,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
return;
|
||||
}
|
||||
|
||||
cancelled = false;
|
||||
setupConfig();
|
||||
|
||||
if (progressDialog != null) {
|
||||
@@ -573,7 +579,10 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
progressDialog.setMessage(getString(R.string.one_moment));
|
||||
progressDialog.setCanceledOnTouchOutside(false);
|
||||
progressDialog.setCancelable(false);
|
||||
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(android.R.string.cancel), (dialog, which) -> stopLoginProcess());
|
||||
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(android.R.string.cancel), (dialog, which) -> {
|
||||
cancelled = true;
|
||||
DcHelper.getContext(this).stopOngoingProcess();
|
||||
});
|
||||
progressDialog.show();
|
||||
}
|
||||
|
||||
@@ -583,24 +592,49 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
&& !passwordInput.getText().toString().isEmpty();
|
||||
}
|
||||
|
||||
private EnteredCertificateChecks certificateChecksFromInt(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return EnteredCertificateChecks.automatic;
|
||||
case 1:
|
||||
return EnteredCertificateChecks.strict;
|
||||
case 2:
|
||||
return EnteredCertificateChecks.acceptInvalidCertificates;
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid certificate position: " + position);
|
||||
}
|
||||
|
||||
public static Socket socketSecurityFromInt(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return Socket.automatic;
|
||||
case 1:
|
||||
return Socket.ssl;
|
||||
case 2:
|
||||
return Socket.starttls;
|
||||
case 3:
|
||||
return Socket.plain;
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid socketSecurity position: " + position);
|
||||
}
|
||||
|
||||
private void setupConfig() {
|
||||
DcHelper.getEventCenter(this).captureNextError();
|
||||
|
||||
EnteredLoginParam param = new EnteredLoginParam(
|
||||
getParam(R.id.email_text, true),
|
||||
getParam(R.id.password_text, false),
|
||||
getParam(R.id.imap_server_text, true),
|
||||
Util.objectToInt(getParam(R.id.imap_port_text, true)),
|
||||
EnteredLoginParam.socketSecurityFromInt(imapSecurity.getSelectedItemPosition()),
|
||||
getParam(R.id.imap_login_text, false),
|
||||
getParam(R.id.smtp_server_text, true),
|
||||
Util.objectToInt(getParam(R.id.smtp_port_text, true)),
|
||||
EnteredLoginParam.socketSecurityFromInt(smtpSecurity.getSelectedItemPosition()),
|
||||
getParam(R.id.smtp_login_text, false),
|
||||
getParam(R.id.smtp_password_text, false),
|
||||
EnteredLoginParam.certificateChecksFromInt(certCheck.getSelectedItemPosition()),
|
||||
authMethod.getSelectedItemPosition() == 1
|
||||
);
|
||||
EnteredLoginParam param = new EnteredLoginParam();
|
||||
param.addr = getParam(R.id.email_text, true);
|
||||
param.password = getParam(R.id.password_text, false);
|
||||
param.imapServer = getParam(R.id.imap_server_text, true);
|
||||
param.imapPort = Util.objectToInt(getParam(R.id.imap_port_text, true));
|
||||
param.imapSecurity = socketSecurityFromInt(imapSecurity.getSelectedItemPosition());
|
||||
param.imapUser = getParam(R.id.imap_login_text, false);
|
||||
param.smtpServer = getParam(R.id.smtp_server_text, true);
|
||||
param.smtpPort = Util.objectToInt(getParam(R.id.smtp_port_text, true));
|
||||
param.smtpSecurity = socketSecurityFromInt(smtpSecurity.getSelectedItemPosition());
|
||||
param.smtpUser = getParam(R.id.smtp_login_text, false);
|
||||
param.smtpPassword = getParam(R.id.smtp_password_text, false);
|
||||
param.certificateChecks = certificateChecksFromInt(certCheck.getSelectedItemPosition());
|
||||
param.oauth2 = authMethod.getSelectedItemPosition() == 1;
|
||||
|
||||
new Thread(() -> {
|
||||
Rpc rpc = DcHelper.getRpc(this);
|
||||
@@ -612,11 +646,13 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
startActivity(conversationList);
|
||||
finish();
|
||||
} catch (RpcException e) {
|
||||
Util.runOnMain(() -> {
|
||||
DcHelper.getEventCenter(this).endCaptureNextError();
|
||||
progressDialog.dismiss();
|
||||
WelcomeActivity.maybeShowConfigurationError(this, e.getMessage());
|
||||
});
|
||||
DcHelper.getEventCenter(this).endCaptureNextError();
|
||||
if (!cancelled) {
|
||||
Util.runOnMain(() -> {
|
||||
progressDialog.dismiss();
|
||||
WelcomeActivity.maybeShowConfigurationError(this, e.getMessage());
|
||||
});
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
@@ -630,10 +666,6 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
return value.isEmpty()? null : value;
|
||||
}
|
||||
|
||||
private void stopLoginProcess() {
|
||||
DcHelper.getContext(this).stopOngoingProcess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvent(@NonNull DcEvent event) {
|
||||
if (event.getId()==DcContext.DC_EVENT_CONFIGURE_PROGRESS) {
|
||||
|
||||
@@ -34,6 +34,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.pm.ShortcutManagerCompat;
|
||||
|
||||
import com.b44t.messenger.DcContext;
|
||||
|
||||
@@ -217,6 +218,16 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
|
||||
int chatId = intent.getIntExtra(EXTRA_CHAT_ID, -1);
|
||||
String msgType = intent.getStringExtra(EXTRA_MSG_TYPE);
|
||||
|
||||
// the intent coming from shortcuts in the share selector might not include the custom extras but the shortcut ID
|
||||
String shortcutId = intent.getStringExtra(ShortcutManagerCompat.EXTRA_SHORTCUT_ID);
|
||||
if ((chatId == -1 || accId == -1) && shortcutId != null && shortcutId.startsWith("chat-")) {
|
||||
String[] args = shortcutId.split("-");
|
||||
if (args.length == 3) {
|
||||
accId = Integer.parseInt(args[1]);
|
||||
chatId = Integer.parseInt(args[2]);
|
||||
}
|
||||
}
|
||||
|
||||
String[] extraEmail = getIntent().getStringArrayExtra(Intent.EXTRA_EMAIL);
|
||||
/*
|
||||
usually, external app will try to start "e-mail sharing" intent, providing it:
|
||||
|
||||
@@ -55,6 +55,7 @@ public class WebViewActivity extends PassphraseRequiredActionBarActivity
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setElevation(0); // TODO: use custom toolbar instead
|
||||
}
|
||||
|
||||
webView = findViewById(R.id.webview);
|
||||
|
||||
@@ -38,8 +38,6 @@ import com.b44t.messenger.DcChat;
|
||||
import com.b44t.messenger.DcContext;
|
||||
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;
|
||||
@@ -63,6 +61,9 @@ import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import chat.delta.rpc.Rpc;
|
||||
import chat.delta.rpc.RpcException;
|
||||
|
||||
public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcEventDelegate {
|
||||
private static final String TAG = WebxdcActivity.class.getSimpleName();
|
||||
private static final String EXTRA_ACCOUNT_ID = "accountId";
|
||||
|
||||
@@ -17,13 +17,11 @@ 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.JsonUtils;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
@@ -31,6 +29,10 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
import chat.delta.rpc.Rpc;
|
||||
import chat.delta.rpc.RpcException;
|
||||
import chat.delta.rpc.types.HttpResponse;
|
||||
|
||||
public class WebxdcStoreActivity extends PassphraseRequiredActionBarActivity {
|
||||
private static final String TAG = WebxdcStoreActivity.class.getSimpleName();
|
||||
|
||||
@@ -48,6 +50,7 @@ public class WebxdcStoreActivity extends PassphraseRequiredActionBarActivity {
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setTitle(R.string.webxdc_apps);
|
||||
actionBar.setElevation(0); // TODO: use custom toolbar instead
|
||||
}
|
||||
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
@@ -58,7 +61,8 @@ public class WebxdcStoreActivity extends PassphraseRequiredActionBarActivity {
|
||||
Util.runOnAnyBackgroundThread(() -> {
|
||||
try {
|
||||
HttpResponse httpResponse = rpc.getHttpResponse(dcContext.getAccountId(), url);
|
||||
Uri uri = PersistentBlobProvider.getInstance().create(WebxdcStoreActivity.this, httpResponse.getBlob(), "application/octet-stream", "app.xdc");
|
||||
byte[] blob = JsonUtils.decodeBase64(httpResponse.blob);
|
||||
Uri uri = PersistentBlobProvider.getInstance().create(WebxdcStoreActivity.this, blob, "application/octet-stream", "app.xdc");
|
||||
Intent intent = new Intent();
|
||||
intent.setData(uri);
|
||||
setResult(Activity.RESULT_OK, intent);
|
||||
@@ -107,13 +111,14 @@ public class WebxdcStoreActivity extends PassphraseRequiredActionBarActivity {
|
||||
throw new Exception("no url specified");
|
||||
}
|
||||
HttpResponse httpResponse = rpc.getHttpResponse(dcContext.getAccountId(), url);
|
||||
String mimeType = httpResponse.getMimetype();
|
||||
String mimeType = httpResponse.mimetype;
|
||||
if (mimeType == null) {
|
||||
mimeType = "application/octet-stream";
|
||||
}
|
||||
|
||||
ByteArrayInputStream data = new ByteArrayInputStream(httpResponse.getBlob());
|
||||
res = new WebResourceResponse(mimeType, httpResponse.getEncoding(), data);
|
||||
byte[] blob = JsonUtils.decodeBase64(httpResponse.blob);
|
||||
ByteArrayInputStream data = new ByteArrayInputStream(blob);
|
||||
res = new WebResourceResponse(mimeType, httpResponse.encoding, data);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ByteArrayInputStream data = new ByteArrayInputStream(("Could not load apps. Are you online?\n\n" + e.getMessage()).getBytes());
|
||||
|
||||
@@ -26,8 +26,6 @@ import com.b44t.messenger.DcAccounts;
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcEvent;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
|
||||
import org.thoughtcrime.securesms.ConnectivityActivity;
|
||||
import org.thoughtcrime.securesms.ConversationListActivity;
|
||||
@@ -43,6 +41,9 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import chat.delta.rpc.Rpc;
|
||||
import chat.delta.rpc.RpcException;
|
||||
|
||||
public class AccountSelectionListFragment extends DialogFragment implements DcEventCenter.DcEventDelegate
|
||||
{
|
||||
private static final String TAG = AccountSelectionListFragment.class.getSimpleName();
|
||||
|
||||
@@ -8,9 +8,6 @@ import android.util.Pair;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.b44t.messenger.util.concurrent.ListenableFuture;
|
||||
import com.b44t.messenger.util.concurrent.SettableFuture;
|
||||
|
||||
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.ThreadUtil;
|
||||
@@ -19,6 +16,9 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import chat.delta.util.ListenableFuture;
|
||||
import chat.delta.util.SettableFuture;
|
||||
|
||||
public class AudioRecorder {
|
||||
|
||||
private static final String TAG = AudioRecorder.class.getSimpleName();
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
package org.thoughtcrime.securesms.calls;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.webkit.JavascriptInterface;
|
||||
import android.webkit.PermissionRequest;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebSettings;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.b44t.messenger.DcChat;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcEvent;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.WebViewActivity;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.AvatarUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
|
||||
import chat.delta.rpc.Rpc;
|
||||
import chat.delta.rpc.RpcException;
|
||||
|
||||
public class CallActivity extends WebViewActivity implements DcEventCenter.DcEventDelegate {
|
||||
private static final String TAG = CallActivity.class.getSimpleName();
|
||||
|
||||
public static final String EXTRA_ACCOUNT_ID = "acc_id";
|
||||
public static final String EXTRA_CHAT_ID = "chat_id";
|
||||
public static final String EXTRA_CALL_ID = "call_id";
|
||||
public static final String EXTRA_HASH = "hash";
|
||||
|
||||
private DcContext dcContext;
|
||||
private Rpc rpc;
|
||||
private int accId;
|
||||
private int chatId;
|
||||
private int callId;
|
||||
private boolean ended = false;
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@Override
|
||||
protected void onCreate(Bundle state, boolean ready) {
|
||||
super.onCreate(state, ready);
|
||||
|
||||
Bundle bundle = getIntent().getExtras();
|
||||
assert bundle != null;
|
||||
String hash = bundle.getString(EXTRA_HASH, "");
|
||||
accId = bundle.getInt(EXTRA_ACCOUNT_ID, -1);
|
||||
chatId = bundle.getInt(EXTRA_CHAT_ID, 0);
|
||||
callId = bundle.getInt(EXTRA_CALL_ID, 0);
|
||||
rpc = DcHelper.getRpc(this);
|
||||
dcContext = DcHelper.getAccounts(this).getAccount(accId);
|
||||
|
||||
DcHelper.getNotificationCenter(this).removeCallNotification(accId, callId);
|
||||
|
||||
WebSettings webSettings = webView.getSettings();
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setMediaPlaybackRequiresUserGesture(false);
|
||||
webView.addJavascriptInterface(new InternalJSApi(), "calls");
|
||||
|
||||
webView.setWebChromeClient(new WebChromeClient() {
|
||||
@Override
|
||||
public void onPermissionRequest(PermissionRequest request) {
|
||||
Util.runOnMain(() -> request.grant(request.getResources()));
|
||||
}
|
||||
});
|
||||
|
||||
DcEventCenter eventCenter = DcHelper.getEventCenter(getApplicationContext());
|
||||
eventCenter.addObserver(DcContext.DC_EVENT_OUTGOING_CALL_ACCEPTED, this);
|
||||
eventCenter.addObserver(DcContext.DC_EVENT_CALL_ENDED, this);
|
||||
|
||||
Util.runOnAnyBackgroundThread(() -> {
|
||||
final DcChat chat = dcContext.getChat(chatId);
|
||||
Util.runOnMain(() -> Objects.requireNonNull(getSupportActionBar()).setTitle(chat.getName()));
|
||||
});
|
||||
|
||||
Permissions.with(this)
|
||||
.request(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
|
||||
.ifNecessary()
|
||||
.withPermanentDenialDialog(getString(R.string.perm_explain_access_to_camera_denied))
|
||||
.onAllGranted(() -> {
|
||||
String url = "file:///android_asset/calls/index.html";
|
||||
webView.loadUrl(url + hash);
|
||||
}).onAnyDenied(this::finish)
|
||||
.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
DcHelper.getEventCenter(this).removeObservers(this);
|
||||
if (callId != 0 && !ended) {
|
||||
try {
|
||||
rpc.endCall(accId, callId);
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Error", e);
|
||||
}
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
// do not call super.onPrepareOptionsMenu() as the default "Search" menu is not needed
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean openOnlineUrl(String url) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvent(@NonNull DcEvent event) {
|
||||
switch (event.getId()) {
|
||||
case DcContext.DC_EVENT_OUTGOING_CALL_ACCEPTED:
|
||||
if (event.getData1Int() == callId) {
|
||||
try {
|
||||
String base64 = Base64.encodeToString(event.getData2Str().getBytes(StandardCharsets.UTF_8), Base64.NO_WRAP);
|
||||
String hash = "#onAnswer=" + URLEncoder.encode(base64, "UTF-8");
|
||||
webView.evaluateJavascript("window.location.hash = `"+hash+"`", null);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Log.e(TAG, "Error", e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DcContext.DC_EVENT_CALL_ENDED:
|
||||
if (event.getData1Int() == callId) {
|
||||
ended = true;
|
||||
finish();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class InternalJSApi {
|
||||
@JavascriptInterface
|
||||
public String getIceServers() {
|
||||
try {
|
||||
return rpc.iceServers(accId);
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Error", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public void startCall(String payload) {
|
||||
try {
|
||||
callId = rpc.placeOutgoingCall(accId, chatId, payload);
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public void acceptCall(String payload) {
|
||||
try {
|
||||
rpc.acceptIncomingCall(accId, callId, payload);
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public void endCall() {
|
||||
finish();
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public String getAvatar() {
|
||||
final Context context = CallActivity.this;
|
||||
final DcChat dcChat = dcContext.getChat(chatId);
|
||||
if (!TextUtils.isEmpty(dcChat.getProfileImage())) {
|
||||
return AvatarUtil.asDataUri(dcChat.getProfileImage());
|
||||
} else {
|
||||
final Recipient recipient = new Recipient(context, dcChat);
|
||||
return AvatarUtil.asDataUri(recipient.getFallbackAvatarDrawable(context, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.thoughtcrime.securesms.calls;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class CallUtil {
|
||||
private static final String TAG = CallUtil.class.getSimpleName();
|
||||
|
||||
public static void startCall(Activity activity, int chatId) {
|
||||
Permissions.with(activity)
|
||||
.request(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
|
||||
.ifNecessary()
|
||||
.withPermanentDenialDialog(activity.getString(R.string.perm_explain_access_to_camera_denied))
|
||||
.onAllGranted(() -> {
|
||||
int accId = DcHelper.getContext(activity).getAccountId();
|
||||
startCall(activity, accId, chatId);
|
||||
})
|
||||
.execute();
|
||||
}
|
||||
|
||||
public static void startCall(Context context, int accId, int chatId) {
|
||||
Intent intent = new Intent(context, CallActivity.class);
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.putExtra(CallActivity.EXTRA_ACCOUNT_ID, accId);
|
||||
intent.putExtra(CallActivity.EXTRA_CHAT_ID, chatId);
|
||||
intent.putExtra(CallActivity.EXTRA_HASH, "#startCall");
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void openCall(Context context, int accId, int chatId, int callId, String payload) {
|
||||
String base64 = Base64.encodeToString(payload.getBytes(StandardCharsets.UTF_8), Base64.NO_WRAP);
|
||||
String hash = "";
|
||||
try {
|
||||
hash = "#offerIncomingCall=" + URLEncoder.encode(base64, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Log.e(TAG, "Error", e);
|
||||
}
|
||||
|
||||
Intent intent = new Intent(context, CallActivity.class);
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.putExtra(CallActivity.EXTRA_ACCOUNT_ID, accId);
|
||||
intent.putExtra(CallActivity.EXTRA_CHAT_ID, chatId);
|
||||
intent.putExtra(CallActivity.EXTRA_CALL_ID, callId);
|
||||
intent.putExtra(CallActivity.EXTRA_HASH, hash);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,19 +35,17 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
|
||||
public static final int ADD_GALLERY = 1;
|
||||
public static final int ADD_DOCUMENT = 2;
|
||||
public static final int INVITE_VIDEO_CHAT = 3;
|
||||
public static final int ADD_CONTACT_INFO = 4;
|
||||
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;
|
||||
public static final int ADD_CONTACT_INFO = 3;
|
||||
public static final int TAKE_PHOTO = 4;
|
||||
public static final int ADD_LOCATION = 5;
|
||||
public static final int RECORD_VIDEO = 6;
|
||||
public static final int ADD_WEBXDC = 7;
|
||||
|
||||
private static final int ANIMATION_DURATION = 300;
|
||||
|
||||
private final @NonNull LoaderManager loaderManager;
|
||||
private final @NonNull RecentPhotoViewRail recentRail;
|
||||
private final @NonNull ImageView imageButton;
|
||||
private final @NonNull ImageView videoChatButton;
|
||||
private final @NonNull ImageView documentButton;
|
||||
private final @NonNull ImageView contactButton;
|
||||
//private final @NonNull ImageView cameraButton;
|
||||
@@ -70,7 +68,6 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
this.chatId = chatId;
|
||||
this.recentRail = ViewUtil.findById(layout, R.id.recent_photos);
|
||||
this.imageButton = ViewUtil.findById(layout, R.id.gallery_button);
|
||||
this.videoChatButton = ViewUtil.findById(layout, R.id.invite_video_chat_button);
|
||||
this.documentButton = ViewUtil.findById(layout, R.id.document_button);
|
||||
this.contactButton = ViewUtil.findById(layout, R.id.contact_button);
|
||||
//this.cameraButton = ViewUtil.findById(layout, R.id.camera_button);
|
||||
@@ -79,7 +76,6 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
this.webxdcButton = ViewUtil.findById(layout, R.id.webxdc_button);
|
||||
|
||||
this.imageButton.setOnClickListener(new PropagatingClickListener(ADD_GALLERY));
|
||||
this.videoChatButton.setOnClickListener(new PropagatingClickListener(INVITE_VIDEO_CHAT));
|
||||
this.documentButton.setOnClickListener(new PropagatingClickListener(ADD_DOCUMENT));
|
||||
this.contactButton.setOnClickListener(new PropagatingClickListener(ADD_CONTACT_INFO));
|
||||
//this.cameraButton.setOnClickListener(new PropagatingClickListener(TAKE_PHOTO));
|
||||
@@ -137,7 +133,6 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
animateButtonIn(locationButton, ANIMATION_DURATION / 4);
|
||||
animateButtonIn(documentButton, ANIMATION_DURATION / 4);
|
||||
animateButtonIn(webxdcButton, 0);
|
||||
animateButtonIn(videoChatButton, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
package org.thoughtcrime.securesms.components;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
import chat.delta.rpc.types.CallInfo;
|
||||
import chat.delta.rpc.types.CallState;
|
||||
|
||||
public class CallItemView extends FrameLayout {
|
||||
private static final String TAG = CallItemView.class.getSimpleName();
|
||||
|
||||
private final @NonNull ImageView icon;
|
||||
private final @NonNull TextView title;
|
||||
private final @NonNull ConversationItemFooter footer;
|
||||
private CallInfo callInfo;
|
||||
private CallClickListener viewListener;
|
||||
|
||||
public CallItemView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public CallItemView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public CallItemView(final Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
inflate(context, R.layout.call_item_view, this);
|
||||
|
||||
this.icon = findViewById(R.id.call_icon);
|
||||
this.title = findViewById(R.id.title);
|
||||
this.footer = findViewById(R.id.footer);
|
||||
|
||||
setOnClickListener(v -> {
|
||||
if (viewListener != null && callInfo != null) {
|
||||
viewListener.onClick(v, callInfo);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setCallClickListener(CallClickListener listener) {
|
||||
viewListener = listener;
|
||||
}
|
||||
|
||||
public void setCallItem(boolean isOutgoing, CallInfo callInfo) {
|
||||
this.callInfo = callInfo;
|
||||
if (callInfo.state instanceof CallState.Completed) {
|
||||
footer.setCallDuration(((CallState.Completed) callInfo.state).duration);
|
||||
} else {
|
||||
footer.setCallDuration(0); // reset
|
||||
}
|
||||
|
||||
if (callInfo.state instanceof CallState.Missed) {
|
||||
title.setText(R.string.missed_call);
|
||||
} else if (callInfo.state instanceof CallState.Canceled) {
|
||||
title.setText(R.string.canceled_call);
|
||||
} else if (callInfo.state instanceof CallState.Declined) {
|
||||
title.setText(R.string.declined_call);
|
||||
} else {
|
||||
title.setText(isOutgoing? R.string.outgoing_call : R.string.incoming_call);
|
||||
}
|
||||
|
||||
int[] attrs;
|
||||
if (isOutgoing) {
|
||||
attrs = new int[]{
|
||||
R.attr.conversation_item_outgoing_text_primary_color,
|
||||
R.attr.conversation_item_outgoing_text_secondary_color,
|
||||
};
|
||||
} else {
|
||||
attrs = new int[]{
|
||||
R.attr.conversation_item_incoming_text_primary_color,
|
||||
R.attr.conversation_item_incoming_text_secondary_color,
|
||||
};
|
||||
}
|
||||
try (TypedArray ta = getContext().obtainStyledAttributes(attrs)) {
|
||||
icon.setColorFilter(ta.getColor(0, Color.BLACK));
|
||||
footer.setTextColor(ta.getColor(1, Color.BLACK));
|
||||
}
|
||||
}
|
||||
|
||||
public ConversationItemFooter getFooter() {
|
||||
return footer;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return title.getText() + "\n" + footer.getDescription();
|
||||
}
|
||||
|
||||
public interface CallClickListener {
|
||||
void onClick(View v, CallInfo callInfo);
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ public class ConversationItemFooter extends LinearLayout {
|
||||
private ImageView locationIndicatorView;
|
||||
private DeliveryStatusView deliveryStatusView;
|
||||
private Integer textColor = null;
|
||||
private int callDuration = 0;
|
||||
|
||||
public ConversationItemFooter(Context context) {
|
||||
super(context);
|
||||
@@ -54,12 +55,16 @@ public class ConversationItemFooter extends LinearLayout {
|
||||
|
||||
if (attrs != null) {
|
||||
try (TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.ConversationItemFooter, 0, 0)) {
|
||||
textColor = typedArray.getInt(R.styleable.ConversationItemFooter_footer_text_color, getResources().getColor(R.color.core_white));
|
||||
setTextColor(textColor);
|
||||
setTextColor(typedArray.getInt(R.styleable.ConversationItemFooter_footer_text_color, getResources().getColor(R.color.core_white)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Call duration in seconds. Only >0 if this is a call message */
|
||||
public void setCallDuration(int duration) {
|
||||
callDuration = duration;
|
||||
}
|
||||
|
||||
public void setMessageRecord(@NonNull DcMsg messageRecord) {
|
||||
presentDate(messageRecord);
|
||||
boolean bookmark = messageRecord.getOriginalMsgId() != 0 || messageRecord.getSavedMsgId() != 0;
|
||||
@@ -77,7 +82,8 @@ public class ConversationItemFooter extends LinearLayout {
|
||||
presentDeliveryStatus(messageRecord);
|
||||
}
|
||||
|
||||
private void setTextColor(int color) {
|
||||
public void setTextColor(int color) {
|
||||
textColor = color;
|
||||
dateView.setTextColor(color);
|
||||
editedView.setTextColor(color);
|
||||
bookmarkIndicatorView.setColorFilter(color);
|
||||
@@ -86,18 +92,29 @@ public class ConversationItemFooter extends LinearLayout {
|
||||
deliveryStatusView.setTint(color);
|
||||
}
|
||||
|
||||
private void presentDate(@NonNull DcMsg messageRecord) {
|
||||
private void presentDate(@NonNull DcMsg dcMsg) {
|
||||
dateView.forceLayout();
|
||||
dateView.setText(DateUtils.getExtendedRelativeTimeSpanString(getContext(), messageRecord.getTimestamp()));
|
||||
Context context = getContext();
|
||||
String date = dcMsg.getType() == DcMsg.DC_MSG_CALL?
|
||||
DateUtils.getExtendedTimeSpanString(context, dcMsg.getTimestamp())
|
||||
: DateUtils.getExtendedRelativeTimeSpanString(context, dcMsg.getTimestamp());
|
||||
if (callDuration > 0) {
|
||||
String duration = DateUtils.getFormattedCallDuration(context, callDuration);
|
||||
dateView.setText(context.getString(R.string.call_date_and_duration, date, duration));
|
||||
} else {
|
||||
dateView.setText(date);
|
||||
}
|
||||
}
|
||||
|
||||
private void presentDeliveryStatus(@NonNull DcMsg messageRecord) {
|
||||
// isDownloading is temporary and should be checked first.
|
||||
boolean isDownloading = messageRecord.getDownloadState() == DcMsg.DC_DOWNLOAD_IN_PROGRESS;
|
||||
boolean isCall = messageRecord.getType() == DcMsg.DC_MSG_CALL;
|
||||
|
||||
if (isDownloading) deliveryStatusView.setDownloading();
|
||||
else if (messageRecord.isPending()) deliveryStatusView.setPending();
|
||||
else if (messageRecord.isFailed()) deliveryStatusView.setFailed();
|
||||
else if (!messageRecord.isOutgoing()) deliveryStatusView.setNone();
|
||||
else if (!messageRecord.isOutgoing() || isCall) deliveryStatusView.setNone();
|
||||
else if (messageRecord.isRemoteRead()) deliveryStatusView.setRead();
|
||||
else if (messageRecord.isDelivered()) deliveryStatusView.setSent();
|
||||
else if (messageRecord.isPreparing()) deliveryStatusView.setPreparing();
|
||||
|
||||
@@ -16,8 +16,6 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.b44t.messenger.util.concurrent.ListenableFuture;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
@@ -28,6 +26,8 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import chat.delta.util.ListenableFuture;
|
||||
|
||||
public class ConversationItemThumbnail extends FrameLayout {
|
||||
|
||||
private static final Paint LIGHT_THEME_OUTLINE_PAINT = new Paint();
|
||||
|
||||
+2
-1
@@ -5,9 +5,10 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.b44t.messenger.util.concurrent.SettableFuture;
|
||||
import com.bumptech.glide.request.target.DrawableImageViewTarget;
|
||||
|
||||
import chat.delta.util.SettableFuture;
|
||||
|
||||
public class GlideDrawableListeningTarget extends DrawableImageViewTarget {
|
||||
|
||||
private final SettableFuture<Boolean> loaded;
|
||||
|
||||
@@ -23,8 +23,6 @@ import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import com.b44t.messenger.DcMsg;
|
||||
import com.b44t.messenger.util.concurrent.ListenableFuture;
|
||||
import com.b44t.messenger.util.concurrent.SettableFuture;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||
@@ -42,6 +40,9 @@ import org.thoughtcrime.securesms.util.guava.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import chat.delta.util.ListenableFuture;
|
||||
import chat.delta.util.SettableFuture;
|
||||
|
||||
public class InputPanel extends ConstraintLayout
|
||||
implements MicrophoneRecorderView.Listener,
|
||||
KeyboardAwareLinearLayout.OnKeyboardShownListener,
|
||||
|
||||
@@ -17,11 +17,8 @@ import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcMsg;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
import com.b44t.messenger.rpc.VcardContact;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
|
||||
import org.json.JSONObject;
|
||||
@@ -42,6 +39,9 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import chat.delta.rpc.RpcException;
|
||||
import chat.delta.rpc.types.VcardContact;
|
||||
|
||||
public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
|
||||
private static final String TAG = QuoteView.class.getSimpleName();
|
||||
@@ -197,18 +197,17 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
}
|
||||
|
||||
private void setQuoteAttachment(@NonNull GlideRequests glideRequests, @NonNull SlideDeck slideDeck) {
|
||||
List<Slide> thumbnailSlides = Stream.of(slideDeck.getSlides()).filter(s -> s.hasImage() || s.hasVideo() || s.hasSticker() || s.isWebxdcDocument() || s.isVcard()).limit(1).toList();
|
||||
List<Slide> audioSlides = Stream.of(slideDeck.getSlides()).filter(s -> s.hasAudio()).limit(1).toList();
|
||||
List<Slide> documentSlides = Stream.of(attachments.getSlides()).filter(Slide::hasDocument).limit(1).toList();
|
||||
List<Slide> slides = slideDeck.getSlides();
|
||||
Slide slide = slides.isEmpty()? null : slides.get(0);
|
||||
|
||||
attachmentVideoOverlayView.setVisibility(GONE);
|
||||
|
||||
if (!thumbnailSlides.isEmpty() && thumbnailSlides.get(0).getUri() != null) {
|
||||
if (slide != null && slide.hasQuoteThumbnail()) {
|
||||
thumbnailView.setVisibility(VISIBLE);
|
||||
attachmentContainerView.setVisibility(GONE);
|
||||
dismissView.setBackgroundResource(R.drawable.dismiss_background);
|
||||
|
||||
if (thumbnailSlides.get(0).isWebxdcDocument()) {
|
||||
if (slide.isWebxdcDocument()) {
|
||||
try {
|
||||
JSONObject info = quotedMsg.getWebxdcInfo();
|
||||
byte[] blob = quotedMsg.getWebxdcBlob(info.getString("icon"));
|
||||
@@ -221,7 +220,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
Log.e(TAG, "failed to get webxdc icon", e);
|
||||
thumbnailView.setVisibility(GONE);
|
||||
}
|
||||
} else if (thumbnailSlides.get(0).isVcard()) {
|
||||
} else if (slide.isVcard()) {
|
||||
try {
|
||||
VcardContact vcardContact = DcHelper.getRpc(getContext()).parseVcard(quotedMsg.getFile()).get(0);
|
||||
Recipient recipient = new Recipient(getContext(), vcardContact);
|
||||
@@ -236,22 +235,24 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
thumbnailView.setVisibility(GONE);
|
||||
}
|
||||
} else {
|
||||
Uri thumbnailUri = thumbnailSlides.get(0).getUri();
|
||||
if (thumbnailSlides.get(0).hasVideo()) {
|
||||
Uri thumbnailUri = slide.getUri();
|
||||
if (slide.hasVideo()) {
|
||||
attachmentVideoOverlayView.setVisibility(VISIBLE);
|
||||
MediaUtil.createVideoThumbnailIfNeeded(getContext(), thumbnailSlides.get(0).getUri(), thumbnailSlides.get(0).getThumbnailUri(), null);
|
||||
thumbnailUri = thumbnailSlides.get(0).getThumbnailUri();
|
||||
MediaUtil.createVideoThumbnailIfNeeded(getContext(), slide.getUri(), slide.getThumbnailUri(), null);
|
||||
thumbnailUri = slide.getThumbnailUri();
|
||||
}
|
||||
if (thumbnailUri != null) {
|
||||
glideRequests.load(new DecryptableUri(thumbnailUri))
|
||||
.centerCrop()
|
||||
.override(getContext().getResources().getDimensionPixelSize(R.dimen.quote_thumb_size))
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.into(thumbnailView);
|
||||
}
|
||||
glideRequests.load(new DecryptableUri(thumbnailUri))
|
||||
.centerCrop()
|
||||
.override(getContext().getResources().getDimensionPixelSize(R.dimen.quote_thumb_size))
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.into(thumbnailView);
|
||||
}
|
||||
} else if(!audioSlides.isEmpty()) {
|
||||
} else if(slide != null && slide.hasAudio()) {
|
||||
thumbnailView.setVisibility(GONE);
|
||||
attachmentContainerView.setVisibility(GONE);
|
||||
} else if (!documentSlides.isEmpty()) {
|
||||
} else if (slide != null && slide.hasDocument()) {
|
||||
thumbnailView.setVisibility(GONE);
|
||||
attachmentContainerView.setVisibility(VISIBLE);
|
||||
} else {
|
||||
|
||||
@@ -14,8 +14,6 @@ import android.widget.ImageView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.b44t.messenger.util.concurrent.ListenableFuture;
|
||||
import com.b44t.messenger.util.concurrent.SettableFuture;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
@@ -32,6 +30,9 @@ import java.util.Locale;
|
||||
|
||||
import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade;
|
||||
|
||||
import chat.delta.util.ListenableFuture;
|
||||
import chat.delta.util.SettableFuture;
|
||||
|
||||
public class ThumbnailView extends FrameLayout {
|
||||
|
||||
private static final String TAG = ThumbnailView.class.getSimpleName();
|
||||
|
||||
@@ -9,16 +9,16 @@ import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
import com.b44t.messenger.rpc.VcardContact;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.SlideClickListener;
|
||||
import org.thoughtcrime.securesms.mms.VcardSlide;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
import chat.delta.rpc.Rpc;
|
||||
import chat.delta.rpc.RpcException;
|
||||
import chat.delta.rpc.types.VcardContact;
|
||||
|
||||
public class VcardView extends FrameLayout {
|
||||
private static final String TAG = VcardView.class.getSimpleName();
|
||||
|
||||
@@ -60,8 +60,8 @@ public class VcardView extends FrameLayout {
|
||||
public void setVcard(@NonNull GlideRequests glideRequests, final @NonNull VcardSlide slide, final @NonNull Rpc rpc) {
|
||||
try {
|
||||
VcardContact vcardContact = rpc.parseVcard(slide.asAttachment().getRealPath(getContext())).get(0);
|
||||
name.setText(vcardContact.getDisplayName());
|
||||
address.setText(vcardContact.getAddr());
|
||||
name.setText(vcardContact.displayName);
|
||||
address.setText(vcardContact.addr);
|
||||
avatar.setAvatar(glideRequests, new Recipient(getContext(), vcardContact), false);
|
||||
this.slide = slide;
|
||||
} catch (RpcException e) {
|
||||
|
||||
@@ -109,18 +109,9 @@ public class DozeReminder {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isAllChatmail() {
|
||||
for (int accountId : ApplicationContext.dcAccounts.getAll()) {
|
||||
DcContext context = ApplicationContext.dcAccounts.getAccount(accountId);
|
||||
if (!context.isChatmail()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isPushAvailableAndSufficient() {
|
||||
return isAllChatmail() && FcmReceiveService.getToken() != null;
|
||||
return ApplicationContext.dcAccounts.isAllChatmail()
|
||||
&& FcmReceiveService.getToken() != null;
|
||||
}
|
||||
|
||||
public static void maybeAskDirectly(Context context) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user