mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| deb4e356bd | |||
| 88d6992a9e | |||
| 5e6b09031a | |||
| 115ebf52b6 |
@@ -8,7 +8,7 @@ ArcaneChat is a Delta Chat Android client built on top of the official Delta Cha
|
|||||||
- **Language:** Java (Java 8 compatibility)
|
- **Language:** Java (Java 8 compatibility)
|
||||||
- **Build System:** Gradle with Android Gradle Plugin 8.11.1
|
- **Build System:** Gradle with Android Gradle Plugin 8.11.1
|
||||||
- **Min SDK:** 21 (Android 5.0)
|
- **Min SDK:** 21 (Android 5.0)
|
||||||
- **Target SDK:** 36 (Android 16)
|
- **Target SDK:** 35 (Android 15)
|
||||||
- **NDK Version:** 27.0.12077973
|
- **NDK Version:** 27.0.12077973
|
||||||
- **Native Components:** Rust (deltachat-core-rust submodule)
|
- **Native Components:** Rust (deltachat-core-rust submodule)
|
||||||
- **UI Framework:** Android SDK, Material Design Components
|
- **UI Framework:** Android SDK, Material Design Components
|
||||||
@@ -17,23 +17,13 @@ ArcaneChat is a Delta Chat Android client built on top of the official Delta Cha
|
|||||||
## Repository Structure
|
## Repository Structure
|
||||||
|
|
||||||
- `src/main/` - Main application source code
|
- `src/main/` - Main application source code
|
||||||
- `src/main/java/org/thoughtcrime/securesms/` - Main UI components
|
|
||||||
- `src/main/java/com/b44t/messenger/` - Delta Chat core integration
|
|
||||||
- `src/main/java/chat/delta/rpc/` - JSON-RPC bindings (generated, don't edit manually)
|
|
||||||
- `src/main/res/` - Android resources (layouts, strings, drawables)
|
|
||||||
- `src/androidTest/` - Instrumented tests (UI tests, benchmarks)
|
- `src/androidTest/` - Instrumented tests (UI tests, benchmarks)
|
||||||
- `src/androidTest/java/com/b44t/messenger/uitests/` - UI tests
|
|
||||||
- `src/androidTest/java/com/b44t/messenger/uibenchmarks/` - Performance benchmarks
|
|
||||||
- `src/gplay/` - Google Play flavor-specific code
|
- `src/gplay/` - Google Play flavor-specific code
|
||||||
- `src/foss/` - F-Droid/FOSS flavor-specific code
|
- `src/foss/` - F-Droid/FOSS flavor-specific code
|
||||||
- `jni/deltachat-core-rust/` - Native Rust core library (submodule, **don't edit directly**)
|
- `jni/deltachat-core-rust/` - Native Rust core library (submodule)
|
||||||
- `scripts/` - Build and helper scripts
|
- `scripts/` - Build and helper scripts
|
||||||
- `scripts/ndk-make.sh` - Build native libraries
|
|
||||||
- `scripts/install-toolchains.sh` - Install Rust cross-compilation toolchains
|
|
||||||
- `scripts/generate-rpc-bindings.sh` - Generate JSON-RPC bindings
|
|
||||||
- `docs/` - Documentation
|
- `docs/` - Documentation
|
||||||
- `fastlane/` - App store metadata and screenshots
|
- `fastlane/` - App store metadata and screenshots
|
||||||
- `.github/workflows/` - CI/CD workflows (GitHub Actions)
|
|
||||||
|
|
||||||
## Build Instructions
|
## Build Instructions
|
||||||
|
|
||||||
@@ -43,36 +33,17 @@ ArcaneChat is a Delta Chat Android client built on top of the official Delta Cha
|
|||||||
```bash
|
```bash
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
```
|
```
|
||||||
This MUST be done first before any build attempts.
|
|
||||||
|
|
||||||
2. **Set up environment variables:**
|
2. **Build native libraries:**
|
||||||
```bash
|
|
||||||
export ANDROID_NDK_ROOT=/path/to/ndk/27.0.12077973
|
|
||||||
export PATH=${PATH}:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/:${ANDROID_NDK_ROOT}
|
|
||||||
```
|
|
||||||
Note: Path format varies by OS (linux-x86_64, darwin-x86_64, etc.)
|
|
||||||
|
|
||||||
3. **Install Rust toolchains:**
|
|
||||||
```bash
|
|
||||||
scripts/install-toolchains.sh
|
|
||||||
```
|
|
||||||
Required for building the native Rust components.
|
|
||||||
|
|
||||||
4. **Build native libraries:**
|
|
||||||
```bash
|
```bash
|
||||||
scripts/ndk-make.sh
|
scripts/ndk-make.sh
|
||||||
```
|
```
|
||||||
**IMPORTANT:** First run takes 30-60 minutes as it builds for all architectures (armeabi-v7a, arm64-v8a, x86, x86_64).
|
Note: First run may take significant time as it builds for all architectures (armeabi-v7a, arm64-v8a, x86, x86_64)
|
||||||
For faster development builds, build for a single architecture:
|
|
||||||
```bash
|
|
||||||
scripts/ndk-make.sh armeabi-v7a
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **Build APK:**
|
3. **Build APK:**
|
||||||
```bash
|
```bash
|
||||||
./gradlew assembleDebug
|
./gradlew assembleDebug
|
||||||
```
|
```
|
||||||
Build time: ~2-5 minutes after native libraries are built.
|
|
||||||
|
|
||||||
### Build Flavors
|
### Build Flavors
|
||||||
|
|
||||||
@@ -84,24 +55,6 @@ ArcaneChat is a Delta Chat Android client built on top of the official Delta Cha
|
|||||||
- Debug APKs: `build/outputs/apk/gplay/debug/` and `build/outputs/apk/fat/debug/`
|
- Debug APKs: `build/outputs/apk/gplay/debug/` and `build/outputs/apk/fat/debug/`
|
||||||
- Release APKs require signing configuration in `~/.gradle/gradle.properties`
|
- Release APKs require signing configuration in `~/.gradle/gradle.properties`
|
||||||
|
|
||||||
### Common Build Issues
|
|
||||||
|
|
||||||
1. **Missing NDK or incorrect version:**
|
|
||||||
- Error: `ANDROID_NDK_ROOT not set` or native library missing
|
|
||||||
- Solution: Install NDK 27.0.12077973 and set ANDROID_NDK_ROOT environment variable
|
|
||||||
|
|
||||||
2. **Submodules not initialized:**
|
|
||||||
- Error: Missing deltachat-core-rust files
|
|
||||||
- Solution: Run `git submodule update --init --recursive`
|
|
||||||
|
|
||||||
3. **Gradle wrapper validation:**
|
|
||||||
- Always validate gradle wrapper before building: `./gradlew wrapper --gradle-version=current`
|
|
||||||
- Wrapper is validated in CI via `gradle/actions/wrapper-validation@v4`
|
|
||||||
|
|
||||||
4. **Clean build issues:**
|
|
||||||
- If build fails, try: `./gradlew clean && scripts/ndk-make.sh && ./gradlew assembleDebug`
|
|
||||||
- Remove `build/` directory if clean doesn't work
|
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
### Running Unit Tests
|
### Running Unit Tests
|
||||||
@@ -109,19 +62,16 @@ ArcaneChat is a Delta Chat Android client built on top of the official Delta Cha
|
|||||||
```bash
|
```bash
|
||||||
./gradlew test
|
./gradlew test
|
||||||
```
|
```
|
||||||
Expected duration: 1-3 minutes
|
|
||||||
|
|
||||||
### Running Instrumented Tests
|
### Running Instrumented Tests
|
||||||
|
|
||||||
1. **Disable animations** on your device/emulator:
|
1. **Disable animations** on your device/emulator:
|
||||||
- Developer Options → Set "Window animation scale", "Transition animation scale", and "Animator duration scale" to 0x
|
- Developer Options → Set "Window animation scale", "Transition animation scale", and "Animator duration scale" to 0x
|
||||||
- **CRITICAL:** Tests will fail if animations are enabled
|
|
||||||
|
|
||||||
2. **Run tests:**
|
2. **Run tests:**
|
||||||
```bash
|
```bash
|
||||||
./gradlew connectedAndroidTest
|
./gradlew connectedAndroidTest
|
||||||
```
|
```
|
||||||
Expected duration: 10-30 minutes depending on device/emulator
|
|
||||||
|
|
||||||
### Online Tests
|
### Online Tests
|
||||||
|
|
||||||
@@ -179,14 +129,6 @@ TEST_MAIL_PW=yourpassword
|
|||||||
- Java bindings are in `src/main/java/com/b44t/messenger/Dc*.java`
|
- Java bindings are in `src/main/java/com/b44t/messenger/Dc*.java`
|
||||||
- JSON-RPC bindings in `chat.delta.rpc.*` package (generated via dcrpcgen)
|
- JSON-RPC bindings in `chat.delta.rpc.*` package (generated via dcrpcgen)
|
||||||
|
|
||||||
### Generating JSON-RPC Bindings
|
|
||||||
|
|
||||||
To regenerate JSON-RPC bindings after core changes:
|
|
||||||
```bash
|
|
||||||
./scripts/generate-rpc-bindings.sh
|
|
||||||
```
|
|
||||||
**Note:** Requires Rust tooling and [dcrpcgen tool](https://github.com/chatmail/dcrpcgen) installed
|
|
||||||
|
|
||||||
### Working with Translations
|
### Working with Translations
|
||||||
|
|
||||||
- Translations managed via Transifex (not in repository)
|
- Translations managed via Transifex (not in repository)
|
||||||
@@ -200,43 +142,6 @@ Decode crash symbols:
|
|||||||
$ANDROID_NDK_ROOT/ndk-stack --sym obj/local/armeabi-v7a --dump crash.txt > decoded.txt
|
$ANDROID_NDK_ROOT/ndk-stack --sym obj/local/armeabi-v7a --dump crash.txt > decoded.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
## Validation and Quality Checks
|
|
||||||
|
|
||||||
### Pre-commit Checks
|
|
||||||
|
|
||||||
Before committing changes, always run:
|
|
||||||
|
|
||||||
1. **Gradle wrapper validation:**
|
|
||||||
```bash
|
|
||||||
./gradlew wrapper --gradle-version=current
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Build verification:**
|
|
||||||
```bash
|
|
||||||
./gradlew assembleDebug
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Unit tests:**
|
|
||||||
```bash
|
|
||||||
./gradlew test
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Code style:** Match existing code style in modified files (no automatic formatter configured)
|
|
||||||
|
|
||||||
### When to Rebuild Native Libraries
|
|
||||||
|
|
||||||
Rebuild native libraries (`scripts/ndk-make.sh`) when:
|
|
||||||
- Updating deltachat-core-rust submodule
|
|
||||||
- Modifying anything in `jni/` directory
|
|
||||||
- Changing NDK version
|
|
||||||
- After `git clean -fdx` or fresh clone
|
|
||||||
|
|
||||||
**DO NOT** rebuild native libraries for:
|
|
||||||
- Pure Java/Kotlin code changes
|
|
||||||
- Resource file changes
|
|
||||||
- Gradle configuration changes (unless changing native library linking)
|
|
||||||
- Documentation updates
|
|
||||||
|
|
||||||
## WebXDC Support
|
## WebXDC Support
|
||||||
|
|
||||||
ArcaneChat has extended WebXDC support:
|
ArcaneChat has extended WebXDC support:
|
||||||
@@ -247,24 +152,12 @@ ArcaneChat has extended WebXDC support:
|
|||||||
|
|
||||||
## Important Files
|
## Important Files
|
||||||
|
|
||||||
- `build.gradle` - Main build configuration (Android Gradle Plugin 8.11.1, Java 8 compatibility)
|
- `build.gradle` - Main build configuration
|
||||||
- `CONTRIBUTING.md` - Contribution guidelines
|
- `CONTRIBUTING.md` - Contribution guidelines
|
||||||
- `BUILDING.md` - Detailed build setup instructions
|
- `BUILDING.md` - Detailed build setup
|
||||||
- `RELEASE.md` - Release process
|
- `RELEASE.md` - Release process
|
||||||
- `proguard-rules.pro` - ProGuard configuration (enabled for both debug and release)
|
- `proguard-rules.pro` - ProGuard configuration
|
||||||
- `google-services.json` - Firebase configuration (gplay flavor only)
|
- `google-services.json` - Firebase configuration (gplay flavor)
|
||||||
- `settings.gradle` - Gradle settings
|
|
||||||
- `.github/workflows/` - CI/CD configuration
|
|
||||||
|
|
||||||
## Dependencies and Constraints
|
|
||||||
|
|
||||||
- **Java Version:** Java 8 compatibility (do not use Java 9+ features)
|
|
||||||
- **Gradle:** Use wrapper (`./gradlew`) to ensure correct Gradle version
|
|
||||||
- **NDK:** Must use version 27.0.12077973 (specified in build.gradle)
|
|
||||||
- **Min SDK:** 21 (Android 5.0) - code must be compatible
|
|
||||||
- **Target SDK:** 36 (Android 16) - test on this API level when possible
|
|
||||||
- **ProGuard:** Always enabled - ensure ProGuard rules are correct for new dependencies
|
|
||||||
- **Multi-dex:** Enabled - app exceeds 65k method limit
|
|
||||||
|
|
||||||
## Package Structure
|
## Package Structure
|
||||||
|
|
||||||
@@ -280,35 +173,3 @@ ArcaneChat has extended WebXDC support:
|
|||||||
- Native library must be rebuilt after core changes
|
- Native library must be rebuilt after core changes
|
||||||
- ProGuard is enabled in both debug and release builds
|
- ProGuard is enabled in both debug and release builds
|
||||||
- Multi-dex is enabled due to app size
|
- Multi-dex is enabled due to app size
|
||||||
|
|
||||||
## CI/CD Workflows
|
|
||||||
|
|
||||||
### Preview APK Workflow (.github/workflows/preview-apk.yml)
|
|
||||||
|
|
||||||
Runs on every pull request to build and upload a preview APK:
|
|
||||||
|
|
||||||
1. **Setup steps:**
|
|
||||||
- Checks out repository with submodules
|
|
||||||
- Validates Fastlane metadata
|
|
||||||
- Sets up Rust cache (working-directory: jni/deltachat-core-rust)
|
|
||||||
- Sets up Java 17 (Temurin distribution)
|
|
||||||
- Sets up Android SDK
|
|
||||||
- Caches Gradle dependencies
|
|
||||||
- Sets up NDK r27
|
|
||||||
|
|
||||||
2. **Build process:**
|
|
||||||
```bash
|
|
||||||
scripts/install-toolchains.sh && scripts/ndk-make.sh armeabi-v7a
|
|
||||||
./gradlew --no-daemon -PABI_FILTER=armeabi-v7a assembleFossDebug
|
|
||||||
```
|
|
||||||
Note: Builds only armeabi-v7a for faster CI builds
|
|
||||||
|
|
||||||
3. **Output:** Uploads APK artifact to GitHub Actions
|
|
||||||
|
|
||||||
### Important CI Considerations
|
|
||||||
|
|
||||||
- Always validate Gradle wrapper before committing changes
|
|
||||||
- Fastlane metadata must be valid (validated in CI)
|
|
||||||
- Use `--no-daemon` flag for Gradle in CI environments
|
|
||||||
- CI builds use FOSS flavor to avoid Google Services dependencies
|
|
||||||
- Expected CI build time: 15-25 minutes for full workflow
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
name: add artifact links to pull request
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: ["Upload Preview APK"]
|
||||||
|
types: [completed]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
artifacts-url-comments:
|
||||||
|
name: add artifact links to pull request
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||||
|
steps:
|
||||||
|
- name: add artifact links to pull request
|
||||||
|
uses: tonyhallett/artifacts-url-comments@v1.1.0
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
prefix: "**To test the changes in this pull request, install this apk:**"
|
||||||
|
format: "[📦 {name}]({url})"
|
||||||
|
addTo: pull
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
name: Core Cache
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
paths:
|
|
||||||
- 'jni/deltachat-core-rust'
|
|
||||||
- 'jni/Android.mk'
|
|
||||||
- 'jni/Application.mk'
|
|
||||||
- 'jni/dc_wrapper.c'
|
|
||||||
- 'scripts/ndk-make.sh'
|
|
||||||
|
|
||||||
permissions: {}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
persist-credentials: false
|
|
||||||
|
|
||||||
- uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1
|
|
||||||
- uses: nttld/setup-ndk@ed92fe6cadad69be94a966a7ee3271275e62f779 # v1.6.0
|
|
||||||
id: setup-ndk
|
|
||||||
with:
|
|
||||||
ndk-version: "r29"
|
|
||||||
|
|
||||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
|
||||||
with:
|
|
||||||
workspaces: jni/deltachat-core-rust
|
|
||||||
|
|
||||||
- name: Get deltachat-core-rust submodule hash
|
|
||||||
id: core-hash
|
|
||||||
run: echo "hash=$(git rev-parse HEAD:jni/deltachat-core-rust)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Cache compiled core
|
|
||||||
id: cache-core
|
|
||||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
jni/arm64-v8a
|
|
||||||
libs/arm64-v8a
|
|
||||||
key: core-arm64-v8a-${{ steps.core-hash.outputs.hash }}-${{ hashFiles('jni/Android.mk', 'jni/Application.mk', 'jni/dc_wrapper.c', 'scripts/ndk-make.sh') }}-ndk-r27
|
|
||||||
|
|
||||||
- name: Compile core
|
|
||||||
if: steps.cache-core.outputs.cache-hit != 'true'
|
|
||||||
env:
|
|
||||||
ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
|
|
||||||
run: |
|
|
||||||
export PATH="${PATH}:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/"
|
|
||||||
scripts/install-toolchains.sh && scripts/ndk-make.sh arm64-v8a
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
name: Code Format
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
permissions: {}
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
spotless:
|
|
||||||
name: Check code format (Spotless)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
|
||||||
with:
|
|
||||||
java-version: 17
|
|
||||||
distribution: temurin
|
|
||||||
- name: Restore Gradle cache
|
|
||||||
id: gradle-cache
|
|
||||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-gradle-
|
|
||||||
- name: Validate Gradle Wrapper
|
|
||||||
uses: gradle/actions/wrapper-validation@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
|
|
||||||
- name: Check formatting
|
|
||||||
run: ./gradlew spotlessCheck
|
|
||||||
- name: Save Gradle cache
|
|
||||||
if: github.event_name == 'push' && steps.gradle-cache.outputs.cache-hit != 'true'
|
|
||||||
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
|
||||||
@@ -6,30 +6,25 @@ concurrency:
|
|||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||||
|
|
||||||
permissions: {}
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Upload Preview APK
|
name: Upload Preview APK
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
persist-credentials: false
|
|
||||||
|
|
||||||
- name: Validate Fastlane Metadata
|
- name: Validate Fastlane Metadata
|
||||||
uses: ashutoshgngwr/validate-fastlane-supply-metadata@c8857fdbbd3e00f9a5cbe8604bcecfa95ce8fef8 # v2.1.0
|
uses: ashutoshgngwr/validate-fastlane-supply-metadata@v2
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
with:
|
||||||
|
working-directory: jni/deltachat-core-rust
|
||||||
|
- uses: actions/setup-java@v5
|
||||||
with:
|
with:
|
||||||
java-version: 17
|
java-version: 17
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
|
- uses: android-actions/setup-android@v3
|
||||||
- uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
@@ -37,63 +32,26 @@ jobs:
|
|||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-gradle-
|
${{ runner.os }}-gradle-
|
||||||
|
- uses: nttld/setup-ndk@v1
|
||||||
- name: Validate Gradle Wrapper
|
|
||||||
uses: gradle/actions/wrapper-validation@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
|
|
||||||
|
|
||||||
- uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1
|
|
||||||
- uses: nttld/setup-ndk@ed92fe6cadad69be94a966a7ee3271275e62f779 # v1.6.0
|
|
||||||
id: setup-ndk
|
id: setup-ndk
|
||||||
with:
|
with:
|
||||||
ndk-version: "r29"
|
ndk-version: r27
|
||||||
|
|
||||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
- name: Validate Gradle Wrapper
|
||||||
with:
|
uses: gradle/actions/wrapper-validation@v4
|
||||||
workspaces: jni/deltachat-core-rust
|
|
||||||
|
|
||||||
- name: Get deltachat-core-rust submodule hash
|
|
||||||
id: core-hash
|
|
||||||
run: echo "hash=$(git rev-parse HEAD:jni/deltachat-core-rust)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Restore compiled core
|
|
||||||
id: core-cache
|
|
||||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
jni/arm64-v8a
|
|
||||||
libs/arm64-v8a
|
|
||||||
key: core-arm64-v8a-${{ steps.core-hash.outputs.hash }}-${{ hashFiles('jni/Android.mk', 'jni/Application.mk', 'jni/dc_wrapper.c', 'scripts/ndk-make.sh') }}-ndk-r27
|
|
||||||
|
|
||||||
- name: Compile core
|
- name: Compile core
|
||||||
if: steps.core-cache.outputs.cache-hit != 'true'
|
|
||||||
env:
|
env:
|
||||||
ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
|
ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
|
||||||
run: |
|
run: |
|
||||||
export PATH="${PATH}:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/"
|
export PATH="${PATH}:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/"
|
||||||
scripts/install-toolchains.sh && scripts/ndk-make.sh arm64-v8a
|
scripts/install-toolchains.sh && scripts/ndk-make.sh armeabi-v7a
|
||||||
|
|
||||||
- name: Build APK
|
- name: Build APK
|
||||||
run: ./gradlew --no-daemon -PABI_FILTER=arm64-v8a assembleFossDebug
|
run: ./gradlew --no-daemon -PABI_FILTER=armeabi-v7a assembleFossDebug
|
||||||
|
|
||||||
- name: Upload APK
|
- name: Upload APK
|
||||||
id: upload
|
uses: actions/upload-artifact@v4
|
||||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
||||||
with:
|
with:
|
||||||
name: app-preview.apk
|
name: app-preview.apk
|
||||||
path: 'build/outputs/apk/foss/debug/*.apk'
|
path: 'build/outputs/apk/foss/debug/*.apk'
|
||||||
|
|
||||||
- name: Add artifact links to PR
|
|
||||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
|
||||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
||||||
env:
|
|
||||||
ARTIFACT_URL: ${{ steps.upload.outputs.artifact-url }}
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const url = process.env.ARTIFACT_URL;
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: context.issue.number,
|
|
||||||
body: `**To test the changes in this pull request, install this apk:**\n\n[📦 app-preview.apk](${url})`,
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -23,18 +23,18 @@ jobs:
|
|||||||
name: Upload Release APK
|
name: Upload Release APK
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
- uses: Swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
working-directory: jni/deltachat-core-rust
|
working-directory: jni/deltachat-core-rust
|
||||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
- uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 17
|
java-version: 17
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
- uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1
|
- uses: android-actions/setup-android@v3
|
||||||
- uses: nttld/setup-ndk@ed92fe6cadad69be94a966a7ee3271275e62f779 # v1.6.0
|
- uses: nttld/setup-ndk@v1
|
||||||
id: setup-ndk
|
id: setup-ndk
|
||||||
with:
|
with:
|
||||||
ndk-version: r27
|
ndk-version: r27
|
||||||
@@ -63,7 +63,7 @@ jobs:
|
|||||||
mv build/outputs/mapping/gplayRelease/mapping.txt build/outputs/mapping/fossRelease/mapping-gplay.txt
|
mv build/outputs/mapping/gplayRelease/mapping.txt build/outputs/mapping/fossRelease/mapping-gplay.txt
|
||||||
|
|
||||||
- name: Release on GitHub
|
- name: Release on GitHub
|
||||||
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
token: "${{ secrets.GITHUB_TOKEN }}"
|
token: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
body: '[<img src="store/get-it-on-gplay.png" alt="Get it on Google Play" height="48">](https://play.google.com/store/apps/details?id=com.github.arcanechat) [<img src="store/get-it-on-fdroid.png" alt="Get it on F-Droid" height="48">](https://f-droid.org/packages/chat.delta.lite) [<img src="store/get-it-on-github.png" alt="Get it on GitHub" height="48">](https://github.com/ArcaneChat/android/releases/latest/download/ArcaneChat-gplay.apk)'
|
body: '[<img src="store/get-it-on-gplay.png" alt="Get it on Google Play" height="48">](https://play.google.com/store/apps/details?id=com.github.arcanechat) [<img src="store/get-it-on-fdroid.png" alt="Get it on F-Droid" height="48">](https://f-droid.org/packages/chat.delta.lite) [<img src="store/get-it-on-github.png" alt="Get it on GitHub" height="48">](https://github.com/ArcaneChat/android/releases/latest/download/ArcaneChat-gplay.apk)'
|
||||||
@@ -72,3 +72,14 @@ jobs:
|
|||||||
files: |
|
files: |
|
||||||
build/outputs/apk/foss/release/*.apk
|
build/outputs/apk/foss/release/*.apk
|
||||||
build/outputs/mapping/fossRelease/mapping-*.txt
|
build/outputs/mapping/fossRelease/mapping-*.txt
|
||||||
|
|
||||||
|
- name: Release on ZapStore
|
||||||
|
run: |
|
||||||
|
export CHECKSUM=6e2c7cf6da53c3f1a78b523a6aacd6316dce3d74ace6f859c2676729ee439990
|
||||||
|
curl -sL https://cdn.zapstore.dev/$CHECKSUM -o zapstore
|
||||||
|
if echo "$CHECKSUM zapstore" | sha256sum -c --status; then
|
||||||
|
chmod +x zapstore
|
||||||
|
SIGN_WITH=${{ secrets.NOSTR_KEY }} ./zapstore publish --indexer-mode
|
||||||
|
else
|
||||||
|
echo "ERROR: checksum doesn't match!"
|
||||||
|
fi
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
name: GitHub Actions Security Analysis with zizmor
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: ["main"]
|
|
||||||
pull_request:
|
|
||||||
branches: ["**"]
|
|
||||||
|
|
||||||
permissions: {}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
zizmor:
|
|
||||||
name: Run zizmor
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files.
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
|
|
||||||
- name: Run zizmor
|
|
||||||
uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
rules:
|
|
||||||
unpinned-uses:
|
|
||||||
config:
|
|
||||||
policies:
|
|
||||||
actions/*: ref-pin
|
|
||||||
dependabot/*: ref-pin
|
|
||||||
+6
-18
@@ -27,7 +27,7 @@ install Rust tooling (read sections below) and the [dcrpcgen tool](https://githu
|
|||||||
then generate the code running the script:
|
then generate the code running the script:
|
||||||
|
|
||||||
```
|
```
|
||||||
./scripts/update-rpc-bindings.sh
|
./scripts/generate-rpc-bindings.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## Build Using Nix
|
## Build Using Nix
|
||||||
@@ -47,7 +47,7 @@ Nix development environment contains Rust with cross-compilation toolchains and
|
|||||||
|
|
||||||
To [build an APK](https://developer.android.com/studio/build/building-cmdline) run the following 2 steps.
|
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
|
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](./scripts/ndk-make.sh)
|
[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.
|
for pointers on how to build for a specific architecture.
|
||||||
```
|
```
|
||||||
$ scripts/ndk-make.sh
|
$ scripts/ndk-make.sh
|
||||||
@@ -56,7 +56,7 @@ $ ./gradlew assembleDebug
|
|||||||
|
|
||||||
Resulting APK files can be found in
|
Resulting APK files can be found in
|
||||||
`build/outputs/apk/gplay/debug/` and
|
`build/outputs/apk/gplay/debug/` and
|
||||||
`build/outputs/apk/foss/debug/`.
|
`build/outputs/apk/fat/debug/`.
|
||||||
|
|
||||||
## Build Using Dockerfile
|
## Build Using Dockerfile
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ deltachat@6012dcb974fe:/home/app$ ./gradlew assembleDebug
|
|||||||
|
|
||||||
In /etc/containers/storage.conf, replace the line: `driver = ""` with: `driver = "overlay"`.
|
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_.
|
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/main/docs/containers-storage.conf.5.md#storage-table).
|
[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
|
## <a name="setup-podman"></a>Setup Podman
|
||||||
|
|
||||||
@@ -135,8 +135,8 @@ See https://wiki.archlinux.org/index.php/Podman#Rootless_Podman for more informa
|
|||||||
|
|
||||||
To setup build environment manually:
|
To setup build environment manually:
|
||||||
- _Either_, in Android Studio, go to "Tools / SDK Manager / SDK Tools", enable "Show Package Details",
|
- _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](./Dockerfile)), hit "Apply".
|
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](./Dockerfile) and mimic what it does.
|
- _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/)
|
Then, in both cases, install Rust using [rustup](https://rustup.rs/)
|
||||||
and Rust toolchains for cross-compilation by executing `scripts/install-toolchains.sh`.
|
and Rust toolchains for cross-compilation by executing `scripts/install-toolchains.sh`.
|
||||||
@@ -243,15 +243,3 @@ $ANDROID_NDK_ROOT/ndk-stack --sym obj/local/armeabi-v7a --dump crash.txt > decod
|
|||||||
`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/
|
`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)
|
Replace `armeabi-v7a` by the correct architecture the logs come from (can be guessed by trial and error)
|
||||||
|
|
||||||
|
|
||||||
### Deobfuscating Java Stack Traces
|
|
||||||
|
|
||||||
Because the app uses code minification (ProGuard/R8), Java stack traces in crash reports are obfuscated.
|
|
||||||
To decode them, use `retrace` with the `mapping.txt` file that is included in the symbols zip:
|
|
||||||
|
|
||||||
```
|
|
||||||
retrace mapping.txt crash.txt > decoded-crash.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
`mapping.txt` is extracted from the same `deltachat-gplay-release-X.X.X.apk-symbols.zip` file available at https://download.delta.chat/android/symbols/
|
|
||||||
|
|||||||
+1
-128
@@ -2,122 +2,6 @@
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
* Allow to select multiple files for sending
|
|
||||||
* Add notifications for missed calls
|
|
||||||
* Video call preview now accurately shows what is sent to remote
|
|
||||||
* Fix: properly hide draft attachment during in-chat search
|
|
||||||
* Fix: close mini-apps and chats if they are deleted
|
|
||||||
* Fix: cancel in-chat search when back is pressed, instead of directly returning to chatlist
|
|
||||||
|
|
||||||
## v2.53.0
|
|
||||||
2026-06
|
|
||||||
|
|
||||||
* Use message style notifications for longer message previews
|
|
||||||
* Remove notification after audio playback ends
|
|
||||||
* Fix: do not allow blocked contacts to use our invite links
|
|
||||||
* Fix sending mini-app that was used/prepared before sending
|
|
||||||
* Some more small fixes and updated translations
|
|
||||||
* Update to core 2.53.0
|
|
||||||
|
|
||||||
## v2.52.0
|
|
||||||
2026-06
|
|
||||||
|
|
||||||
* Fix: avoid crashes in Media preview sometimes
|
|
||||||
* Fix: Incorrect total time when attaching audio files as draft
|
|
||||||
* Fix: Audio files in draft showing total time from wrong file
|
|
||||||
* Fix: Update the channel title after joining if the QR code had an outdated title
|
|
||||||
* Voice recording will be automatically saved as draft when interrupted
|
|
||||||
* Update to core 2.52.0
|
|
||||||
|
|
||||||
## v2.51.0
|
|
||||||
2026-06
|
|
||||||
|
|
||||||
* Better incoming call system integration
|
|
||||||
* Calls are not experimental anymore and don't need to be manually enabled
|
|
||||||
* Calls can be answered by tapping messages
|
|
||||||
* Notify the user when they try to make a call while the device is offline
|
|
||||||
* Channels are no longer experimental and are available by default
|
|
||||||
* Display a permanent notification when doing location streaming and get rid of dangerous "Access Location in Background" permission
|
|
||||||
* Autoplay all voice messages in a chat
|
|
||||||
* Allow to share location for 24 hours
|
|
||||||
* Allow mini-apps to play audio without user interaction
|
|
||||||
* Allow to paste and open invitation links from search
|
|
||||||
* Mark chats as unread (long tap a chat and select the corresponding option from the three-dot-menu)
|
|
||||||
* Add "Mark all as read" option to profile menu in the profile switcher
|
|
||||||
* Fix process of upgrading from a very old version of the app
|
|
||||||
* Show more recent added stickers at the top of the sticker picker
|
|
||||||
* Allow to open links in messages via actions in TalkBack menu
|
|
||||||
* Allow to open map if user clicks "Location streaming enabled" system message
|
|
||||||
* Allow to disable incoming calls notifications
|
|
||||||
* Add an option to process unencrypted messages; by default, only encrypted messages can be sent or received
|
|
||||||
* Fix: do not accidentally set draft in chats that don't allow sending messages
|
|
||||||
* Fix swipe navigation between tabs in RTL languages
|
|
||||||
* Remove "Move to DeltaChat folder", in case you are using the option, a device message shows how to proceed
|
|
||||||
* Remove "Only fetch from DeltaChat folder" option, the functionality is preserved for existing profiles
|
|
||||||
* Remove "Delete Messages from Server" option, this is now up to the server:
|
|
||||||
Chatmail handles that automatically, classic email servers used as relay often have lots of storage or options themselves
|
|
||||||
* Remove "Show Email" options, all messages are shown by default, shared usage of email account is not supported
|
|
||||||
* Allow otherwise invalid TLS connections if the key is unchanged
|
|
||||||
* Adapt quota warning to automatic cleanup.
|
|
||||||
* Don't show non-delivery-notfications in broadcast channels
|
|
||||||
* Resend the last 10 messages to new broadcast channel member
|
|
||||||
* Enable PQC (Post-Quantum Cryptography) support. We do not generate PQC keys yet, this step is needed for forward compatibility
|
|
||||||
* Improve avatar quality
|
|
||||||
* Add new webxdc.isAppSender and webxdc.isBroadcast APIs for mini-apps
|
|
||||||
* Fix: avoid invalid empty "~" notifications when some peer is streaming location
|
|
||||||
* Fix: Improve detection of stickers
|
|
||||||
* Fix text direction issues for RTL languages in "Show full message" view
|
|
||||||
* Fix: Reconnect when removing a relay
|
|
||||||
* Fix: Location streaming now works correctly with multiple accounts
|
|
||||||
* Fix debouncing in chatlist and search
|
|
||||||
* Fix sharing contact across profiles
|
|
||||||
* Fix: Reset scroll location after switching account
|
|
||||||
* Update to core 2.51.0
|
|
||||||
|
|
||||||
## v2.49.0
|
|
||||||
2026-04
|
|
||||||
|
|
||||||
* Fix file sharing to certain apps (e.g. Material Files, etc.)
|
|
||||||
* Fix problem with calls when microphone permission is not granted
|
|
||||||
* Fix taking pictures and videos in devices with SD cards
|
|
||||||
* Fix flipped orientation for some images
|
|
||||||
* Fix: avoid empty contact request chats when using invite links in a multi-device setup
|
|
||||||
* Remove proxy toggle from profile editing to avoid confusion
|
|
||||||
* Updated translations
|
|
||||||
* Update to core 2.49.0
|
|
||||||
|
|
||||||
## v2.48.0
|
|
||||||
2026-03
|
|
||||||
|
|
||||||
* Add a warning when editing relays
|
|
||||||
* Fix message reordering problems in multi-relay setups
|
|
||||||
* Some more bug fixes and updated translations
|
|
||||||
* Update to core 2.48.0
|
|
||||||
|
|
||||||
## v2.47.0
|
|
||||||
2026-03
|
|
||||||
|
|
||||||
* Allow to set chat description
|
|
||||||
* Unified date display in call bubbles
|
|
||||||
* Explain at "Settings / Chats / Outgoing Media Quality" how to send original quality
|
|
||||||
* Add a basic sticker picker
|
|
||||||
* Leave groups and channels before deletion
|
|
||||||
* Further minimize metadata in messages and while getting in contact.
|
|
||||||
* Increase resilience of multi-relay usage: if on relay goes down, messages are still received in the others.
|
|
||||||
* Allow to hide a relay from contacts instead of removing, allowing smoother relay changes
|
|
||||||
* HTML emails: allow to review and copy links before opening them
|
|
||||||
* Mark call message as seen when accepting/declining a call
|
|
||||||
* Fix: keep original sent timestamp for resent messages
|
|
||||||
* Fix: make clicking on broadcast member-added messages work always
|
|
||||||
* Fix: remove notification when a message is deleted by sender
|
|
||||||
* Fix: avoid "reply privately" not quoting the selected message sometimes
|
|
||||||
* Fix: properly hide the calls button
|
|
||||||
* Some more bug fixes and updated translations
|
|
||||||
* Update to core 2.47.0
|
|
||||||
|
|
||||||
## v2.43.0
|
|
||||||
2026-02
|
|
||||||
|
|
||||||
* Improve switch speed when changing profiles
|
* Improve switch speed when changing profiles
|
||||||
* Allow to switch profile when sharing or forwarding
|
* Allow to switch profile when sharing or forwarding
|
||||||
* Display message views count for channel owners
|
* Display message views count for channel owners
|
||||||
@@ -128,24 +12,13 @@
|
|||||||
* Mark external links with " ↗" to make them clear
|
* Mark external links with " ↗" to make them clear
|
||||||
* Make QR code larger on "Add Second Device" screen
|
* Make QR code larger on "Add Second Device" screen
|
||||||
* Add indication for blocked contacts in user profile
|
* Add indication for blocked contacts in user profile
|
||||||
* Allow to start calls with video disabled
|
|
||||||
* Show hint for empty contact search results
|
* Show hint for empty contact search results
|
||||||
* Add background playing for voice messages and other audio files
|
|
||||||
* Allow scanning Invitation Code when creating a new profile
|
|
||||||
* Add context menu in long-pressing relays items instead of showing buttons
|
|
||||||
* Enhanced video player UI
|
|
||||||
* Fix: Show dialog if pasted QR codes are invalid
|
* Fix: Show dialog if pasted QR codes are invalid
|
||||||
* Fix: Refresh chat list when returning from conversation if selected profile changed
|
* Fix: Refresh chat list when returning from conversation if selected profile changed
|
||||||
* Fix: Update menu when using "select all" in contact selection
|
* Fix: Update menu when using "select all" in contact selection
|
||||||
* Fix: Avoid empty profiles after using "add as second device" from welcome screen
|
* Fix: Avoid empty profiles after using "add as second device" from welcome screen
|
||||||
* Fix: Remove from group deselected members in the contact selection list
|
|
||||||
* Fix multi-device seen messages synchronization when using multiple relays
|
* Fix multi-device seen messages synchronization when using multiple relays
|
||||||
* Fix mailto handling
|
* Update to core 2.39.0
|
||||||
* Fix layout problems inside in-chat apps
|
|
||||||
* Fix real-time for in-chat apps that need it
|
|
||||||
* Avoid crash when the app is minimized with profile switcher or reactions dialogs open
|
|
||||||
* Remove "trash icon" option from contact selection list when adding members to group
|
|
||||||
* Update to core 2.43.0
|
|
||||||
|
|
||||||
## v2.35.0
|
## v2.35.0
|
||||||
2026-01
|
2026-01
|
||||||
|
|||||||
+8
-5
@@ -73,15 +73,18 @@ esp. before/after screenshots.
|
|||||||
|
|
||||||
### Coding Conventions
|
### Coding Conventions
|
||||||
|
|
||||||
Project language is Java.
|
Source files are partly derived from different other open source projects
|
||||||
|
and may follow different coding styles and conventions.
|
||||||
|
|
||||||
Code formatting is enforced via [Spotless](https://github.com/diffplug/spotless) Gradle plugin.
|
If you do a PR fixing a bug or adding a feature,
|
||||||
Auto-format all files by running `./gradlew spotlessApply` before opening a PR.
|
please embrace the coding convention you see in the corresponding files,
|
||||||
CI will fail if files are not formatted correctly so make sure to run the formatter before pushing.
|
so that the result fits well together.
|
||||||
|
|
||||||
If you do a PR fixing a bug or adding a feature, do not refactor or rename things in the same PR
|
Do not refactor or rename things in the same PR
|
||||||
to make the diff small and the PR easy to review.
|
to make the diff small and the PR easy to review.
|
||||||
|
|
||||||
|
Project language is Java.
|
||||||
|
|
||||||
By using [Delta Chat Core](https://github.com/deltachat/deltachat-core-rust)
|
By using [Delta Chat Core](https://github.com/deltachat/deltachat-core-rust)
|
||||||
there is already a strong separation between "UI" and "Model".
|
there is already a strong separation between "UI" and "Model".
|
||||||
Further separations and abstraction layers are often not helpful
|
Further separations and abstraction layers are often not helpful
|
||||||
|
|||||||
+22
-70
@@ -1,7 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application' version '8.11.1'
|
id 'com.android.application' version '8.11.1'
|
||||||
id 'com.google.gms.google-services' version '4.4.1'
|
id 'com.google.gms.google-services' version '4.4.1'
|
||||||
id 'com.diffplug.spotless' version '8.3.0'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@@ -34,8 +33,8 @@ android {
|
|||||||
useLibrary 'org.apache.http.legacy'
|
useLibrary 'org.apache.http.legacy'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
versionCode 30000746
|
versionCode 30000736
|
||||||
versionName "2.53.0"
|
versionName "2.36.0"
|
||||||
|
|
||||||
applicationId "chat.delta.lite"
|
applicationId "chat.delta.lite"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
@@ -73,20 +72,10 @@ android {
|
|||||||
packagingOptions {
|
packagingOptions {
|
||||||
jniLibs {
|
jniLibs {
|
||||||
doNotStrip '**/*.so'
|
doNotStrip '**/*.so'
|
||||||
keepDebugSymbols += [
|
keepDebugSymbols += ['*/mips/*.so', '*/mips64/*.so']
|
||||||
'*/mips/*.so',
|
|
||||||
'*/mips64/*.so'
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
resources {
|
resources {
|
||||||
excludes += [
|
excludes += ['LICENSE.txt', 'LICENSE', 'NOTICE', 'asm-license.txt', 'META-INF/LICENSE', 'META-INF/NOTICE']
|
||||||
'LICENSE.txt',
|
|
||||||
'LICENSE',
|
|
||||||
'NOTICE',
|
|
||||||
'asm-license.txt',
|
|
||||||
'META-INF/LICENSE',
|
|
||||||
'META-INF/NOTICE'
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,14 +154,14 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!project.hasProperty("ABI_FILTER")) {
|
if(!project.hasProperty("ABI_FILTER")) {
|
||||||
splits {
|
splits {
|
||||||
abi {
|
abi {
|
||||||
enable true
|
enable true
|
||||||
reset()
|
reset()
|
||||||
include "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
include "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||||
universalApk true
|
universalApk true
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
project.ext.versionCodes = ['armeabi-v7a': 1, 'arm64-v8a': 2, 'x86': 3, 'x86_64': 4]
|
project.ext.versionCodes = ['armeabi-v7a': 1, 'arm64-v8a': 2, 'x86': 3, 'x86_64': 4]
|
||||||
@@ -180,16 +169,16 @@ android {
|
|||||||
android.applicationVariants.all { variant ->
|
android.applicationVariants.all { variant ->
|
||||||
variant.outputs.all { output ->
|
variant.outputs.all { output ->
|
||||||
output.outputFileName = output.outputFileName
|
output.outputFileName = output.outputFileName
|
||||||
.replace("android", "ArcaneChat")
|
.replace("android", "ArcaneChat")
|
||||||
.replace("-release", "")
|
.replace("-release", "")
|
||||||
.replace(".apk", "-${variant.versionName}.apk")
|
.replace(".apk", "-${variant.versionName}.apk")
|
||||||
if(project.hasProperty("ABI_FILTER")) {
|
if(project.hasProperty("ABI_FILTER")) {
|
||||||
output.versionCodeOverride =
|
output.versionCodeOverride =
|
||||||
variant.versionCode * 10 + project.ext.versionCodes.get(ABI_FILTER)
|
variant.versionCode * 10 + project.ext.versionCodes.get(ABI_FILTER)
|
||||||
} else {
|
} else {
|
||||||
output.versionCodeOverride =
|
output.versionCodeOverride =
|
||||||
variant.versionCode * 10 + project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 4)
|
variant.versionCode * 10 + project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,31 +199,7 @@ android {
|
|||||||
renderScript true
|
renderScript true
|
||||||
aidl true
|
aidl true
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
spotless {
|
|
||||||
java {
|
|
||||||
target 'src/*/java/**/*.java'
|
|
||||||
targetExclude 'src/main/java/chat/delta/**' // ignore auto-generated code
|
|
||||||
googleJavaFormat() // Google style = 2-space indent, matches Android Studio defaults
|
|
||||||
removeUnusedImports()
|
|
||||||
trimTrailingWhitespace()
|
|
||||||
endWithNewline()
|
|
||||||
}
|
|
||||||
format 'xml', {
|
|
||||||
target 'src/*/res/**/*.xml', 'src/*/AndroidManifest.xml'
|
|
||||||
targetExclude 'src/*/res/values*/strings*.xml' // line-break changes invalidate translations
|
|
||||||
eclipseWtp('xml').configFile('spotless/eclipse-wtp-xml.prefs')
|
|
||||||
trimTrailingWhitespace()
|
|
||||||
endWithNewline()
|
|
||||||
}
|
|
||||||
groovyGradle {
|
|
||||||
target '*.gradle'
|
|
||||||
greclipse()
|
|
||||||
leadingTabsToSpaces(4)
|
|
||||||
trimTrailingWhitespace()
|
|
||||||
endWithNewline()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final def markwon_version = '4.6.2'
|
final def markwon_version = '4.6.2'
|
||||||
@@ -246,14 +211,7 @@ dependencies {
|
|||||||
implementation "io.noties.markwon:inline-parser:$markwon_version"
|
implementation "io.noties.markwon:inline-parser:$markwon_version"
|
||||||
implementation 'com.airbnb.android:lottie:4.2.2' // Lottie animations support.
|
implementation 'com.airbnb.android:lottie:4.2.2' // Lottie animations support.
|
||||||
|
|
||||||
def media3_version = "1.8.0" // 1.9.0 need minSdkVersion 23
|
|
||||||
|
|
||||||
implementation 'androidx.concurrent:concurrent-futures:1.3.0'
|
implementation 'androidx.concurrent:concurrent-futures:1.3.0'
|
||||||
implementation 'androidx.core:core:1.17.0'
|
|
||||||
implementation 'androidx.core:core-telecom:1.0.1'
|
|
||||||
implementation 'im.conversations.webrtc:webrtc-android:129.0.0'
|
|
||||||
// For Kotlin->Java interpolation
|
|
||||||
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.9.4'
|
|
||||||
implementation 'androidx.sharetarget:sharetarget:1.2.0'
|
implementation 'androidx.sharetarget:sharetarget:1.2.0'
|
||||||
implementation 'androidx.webkit:webkit:1.14.0'
|
implementation 'androidx.webkit:webkit:1.14.0'
|
||||||
implementation 'androidx.multidex:multidex:2.0.1'
|
implementation 'androidx.multidex:multidex:2.0.1'
|
||||||
@@ -273,11 +231,8 @@ dependencies {
|
|||||||
implementation 'androidx.work:work-runtime:2.9.1'
|
implementation 'androidx.work:work-runtime:2.9.1'
|
||||||
implementation 'androidx.emoji2:emoji2-emojipicker:1.5.0'
|
implementation 'androidx.emoji2:emoji2-emojipicker:1.5.0'
|
||||||
implementation 'com.google.guava:guava:31.1-android'
|
implementation 'com.google.guava:guava:31.1-android'
|
||||||
implementation 'com.google.android.exoplayer:exoplayer-core:2.19.1' // FIXME: exoplayer dependencies kept for Video, but we shall migrate them at some point
|
implementation 'com.google.android.exoplayer:exoplayer-core:2.19.1' // plays video and audio
|
||||||
implementation 'com.google.android.exoplayer:exoplayer-ui:2.19.1'
|
implementation 'com.google.android.exoplayer:exoplayer-ui:2.19.1'
|
||||||
implementation "androidx.media3:media3-exoplayer:$media3_version"
|
|
||||||
implementation "androidx.media3:media3-session:$media3_version"
|
|
||||||
implementation "androidx.media3:media3-ui:$media3_version"
|
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
|
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
|
||||||
implementation 'com.google.zxing:core:3.3.0' // fixed version to support SDK<24
|
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.journeyapps:zxing-android-embedded:4.3.0') { transitive = false } // QR Code scanner
|
||||||
@@ -291,8 +246,7 @@ dependencies {
|
|||||||
implementation 'com.github.amulyakhare:TextDrawable:558677ea31' // number of unread messages,
|
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.
|
// 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.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.10.0') {
|
implementation ('com.davemorrissey.labs:subsampling-scale-image-view:3.10.0') { // for the zooming on photos / media
|
||||||
// for the zooming on photos / media
|
|
||||||
exclude group: 'com.android.support', module: 'support-annotations'
|
exclude group: 'com.android.support', module: 'support-annotations'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,13 +255,11 @@ dependencies {
|
|||||||
// <https://github.com/cketti/SafeContentResolver>
|
// <https://github.com/cketti/SafeContentResolver>
|
||||||
implementation 'de.cketti.safecontentresolver:safe-content-resolver-v21:1.0.0'
|
implementation 'de.cketti.safecontentresolver:safe-content-resolver-v21:1.0.0'
|
||||||
|
|
||||||
gplayImplementation('com.google.firebase:firebase-messaging:24.1.2') {
|
gplayImplementation('com.google.firebase:firebase-messaging:24.1.2') { // for PUSH notifications, don't upgrade: v25.0.0 requires minSdk>=23
|
||||||
// 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-core'
|
||||||
exclude group: 'com.google.firebase', module: 'firebase-analytics'
|
exclude group: 'com.google.firebase', module: 'firebase-analytics'
|
||||||
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
|
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
|
||||||
}
|
}
|
||||||
gplayImplementation 'com.google.android.gms:play-services-location:21.3.0'
|
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
testImplementation 'org.assertj:assertj-core:3.27.3'
|
testImplementation 'org.assertj:assertj-core:3.27.3'
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
ArcaneChat is a decentralized and secure instant messenger that is easy to use for friends and family.
|
ArcaneChat is a decentralized and secure instant messenger that is easy to use for friends and family.
|
||||||
|
|
||||||
• Private. Instant on-boarding without a phone number or other private data.
|
• Anonymous. Instant onboarding without a phone number, e-mail or other private data.
|
||||||
|
|
||||||
• Friends & Family: Only chat with people you know. Unknown users cannot message or follow you without mutual consent.
|
|
||||||
|
|
||||||
• Flexible. Supports multiple chat profiles and is easy to setup on multiple devices.
|
• Flexible. Supports multiple chat profiles and is easy to setup on multiple devices.
|
||||||
|
|
||||||
@@ -25,7 +23,7 @@ ArcaneChat is a Delta Chat client and was created with a focus on usability, goo
|
|||||||
<li>Multiple color themes/skins</li>
|
<li>Multiple color themes/skins</li>
|
||||||
<li>It is possible to disable profiles to completely disconnect them saving data/bandwidth</li>
|
<li>It is possible to disable profiles to completely disconnect them saving data/bandwidth</li>
|
||||||
<li>You can easily see the connection status of all your profiles in the profile switcher</li>
|
<li>You can easily see the connection status of all your profiles in the profile switcher</li>
|
||||||
<li>Extra option to share location for 24 hours</li>
|
<li>Extra option to share location for 12 hours</li>
|
||||||
<li>Clicking on a message with a POI location, will open the POI on the map</li>
|
<li>Clicking on a message with a POI location, will open the POI on the map</li>
|
||||||
<li>Last-seen status of contacts is shown in your contact list, like in WhatsApp, Telegram, etc.</li>
|
<li>Last-seen status of contacts is shown in your contact list, like in WhatsApp, Telegram, etc.</li>
|
||||||
<li>Videos are played in loop, useful for short GIF videos</li>
|
<li>Videos are played in loop, useful for short GIF videos</li>
|
||||||
|
|||||||
Generated
+15
-15
@@ -7,11 +7,11 @@
|
|||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1775939535,
|
"lastModified": 1756239746,
|
||||||
"narHash": "sha256-Zq1U7Vhw5ctvhJQy+3ShqIv7Mplf3XkgJY+QJnhfUGQ=",
|
"narHash": "sha256-0ibN685tT+u/Nbmbrrq9G3mRUzct2Votyv/a7Wwv26s=",
|
||||||
"owner": "tadfisher",
|
"owner": "tadfisher",
|
||||||
"repo": "android-nixpkgs",
|
"repo": "android-nixpkgs",
|
||||||
"rev": "d2e16192309bf3101e4998ffa62e914819dee077",
|
"rev": "256631d162ec883b2341ee59621516e1f65f0f6b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -28,11 +28,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1768818222,
|
"lastModified": 1741473158,
|
||||||
"narHash": "sha256-460jc0+CZfyaO8+w8JNtlClB2n4ui1RbHfPTLkpwhU8=",
|
"narHash": "sha256-kWNaq6wQUbUMlPgw8Y+9/9wP0F8SHkjy24/mN3UAppg=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "devshell",
|
"repo": "devshell",
|
||||||
"rev": "255a2b1725a20d060f566e4755dbf571bbbb5f76",
|
"rev": "7c9e793ebe66bcba8292989a68c0419b737a22a0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -79,11 +79,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1775710090,
|
"lastModified": 1756125398,
|
||||||
"narHash": "sha256-ar3rofg+awPB8QXDaFJhJ2jJhu+KqN/PRCXeyuXR76E=",
|
"narHash": "sha256-XexyKZpf46cMiO5Vbj+dWSAXOnr285GHsMch8FBoHbc=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "4c1018dae018162ec878d42fec712642d214fdfa",
|
"rev": "3b9f00d7a7bf68acd4c4abb9d43695afb04e03a5",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -95,11 +95,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1775823930,
|
"lastModified": 1756159630,
|
||||||
"narHash": "sha256-ALT447J7FcxP/97J01A/gp/hgdO5lXRsm+zLMt+gIjc=",
|
"narHash": "sha256-ohMvsjtSVdT/bruXf5ClBh8ZYXRmD4krmjKrXhEvwMg=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "8c11f88bb9573a10a7d6bf87161ef08455ac70b9",
|
"rev": "84c256e42600cb0fdf25763b48d28df2f25a0c8b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -138,11 +138,11 @@
|
|||||||
"nixpkgs": "nixpkgs_3"
|
"nixpkgs": "nixpkgs_3"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1775877051,
|
"lastModified": 1763347184,
|
||||||
"narHash": "sha256-wpSQm2PD/w4uRo2wb8utk0b5hOBkkg/CZ1xICY+qB7M=",
|
"narHash": "sha256-6QH8hpCYJxifvyHEYg+Da0BotUn03BwLIvYo3JAxuqQ=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "08b4f3633471874c8894632ade1b78d75dbda002",
|
"rev": "08895cce80433978d5bfd668efa41c5e24578cbd",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
buildInputs = [
|
buildInputs = [
|
||||||
android-sdk
|
android-sdk
|
||||||
pkgs.openjdk17
|
pkgs.openjdk17
|
||||||
pkgs.perl
|
|
||||||
(pkgs.buildPackages.rust-bin.stable."${rust-version}".minimal.override {
|
(pkgs.buildPackages.rust-bin.stable."${rust-version}".minimal.override {
|
||||||
targets = [
|
targets = [
|
||||||
"armv7-linux-androideabi"
|
"armv7-linux-androideabi"
|
||||||
|
|||||||
+29
-39
@@ -153,42 +153,6 @@ static uint32_t* jintArray2uint32Pointer(JNIEnv* env, jintArray ja, int* ret_icn
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************
|
|
||||||
* DcEventChannel
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
static dc_event_channel_t* get_dc_event_channel(JNIEnv *env, jobject obj)
|
|
||||||
{
|
|
||||||
static jfieldID fid = 0;
|
|
||||||
if (fid==0) {
|
|
||||||
jclass cls = (*env)->GetObjectClass(env, obj);
|
|
||||||
fid = (*env)->GetFieldID(env, cls, "eventChannelCPtr", "J" /*Signature, J=long*/);
|
|
||||||
}
|
|
||||||
if (fid) {
|
|
||||||
return (dc_event_channel_t*)(*env)->GetLongField(env, obj, fid);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT jlong Java_com_b44t_messenger_DcEventChannel_createEventChannelCPtr(JNIEnv *env, jobject obj)
|
|
||||||
{
|
|
||||||
return (jlong)dc_event_channel_new();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT void Java_com_b44t_messenger_DcEventChannel_unrefEventChannelCPtr(JNIEnv *env, jobject obj)
|
|
||||||
{
|
|
||||||
dc_event_channel_unref(get_dc_event_channel(env, obj));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT jlong Java_com_b44t_messenger_DcEventChannel_getEventEmitterCPtr(JNIEnv *env, jobject obj)
|
|
||||||
{
|
|
||||||
return (jlong)dc_event_channel_get_event_emitter(get_dc_event_channel(env, obj));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* DcAccounts
|
* DcAccounts
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@@ -208,11 +172,11 @@ static dc_accounts_t* get_dc_accounts(JNIEnv *env, jobject obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT jlong Java_com_b44t_messenger_DcAccounts_createAccountsCPtr(JNIEnv *env, jobject obj, jstring dir, jobject chanObj)
|
JNIEXPORT jlong Java_com_b44t_messenger_DcAccounts_createAccountsCPtr(JNIEnv *env, jobject obj, jstring dir)
|
||||||
{
|
{
|
||||||
CHAR_REF(dir);
|
CHAR_REF(dir);
|
||||||
int writable = 1;
|
int writable = 1;
|
||||||
jlong accountsCPtr = (jlong)dc_accounts_new_with_event_channel(dirPtr, writable, get_dc_event_channel(env, chanObj));
|
jlong accountsCPtr = (jlong)dc_accounts_new(dirPtr, writable);
|
||||||
CHAR_UNREF(dir);
|
CHAR_UNREF(dir);
|
||||||
return accountsCPtr;
|
return accountsCPtr;
|
||||||
}
|
}
|
||||||
@@ -946,6 +910,18 @@ JNIEXPORT jstring Java_com_b44t_messenger_DcContext_getContactEncrInfo(JNIEnv *e
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JNIEXPORT jstring Java_com_b44t_messenger_DcContext_initiateKeyTransfer(JNIEnv *env, jobject obj)
|
||||||
|
{
|
||||||
|
jstring setup_code = NULL;
|
||||||
|
char* temp = dc_initiate_key_transfer(get_dc_context(env, obj));
|
||||||
|
if (temp) {
|
||||||
|
setup_code = JSTRING_NEW(temp);
|
||||||
|
dc_str_unref(temp);
|
||||||
|
}
|
||||||
|
return setup_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_imex(JNIEnv *env, jobject obj, jint what, jstring dir)
|
JNIEXPORT void Java_com_b44t_messenger_DcContext_imex(JNIEnv *env, jobject obj, jint what, jstring dir)
|
||||||
{
|
{
|
||||||
CHAR_REF(dir);
|
CHAR_REF(dir);
|
||||||
@@ -1393,7 +1369,6 @@ JNIEXPORT jint Java_com_b44t_messenger_DcMsg_getId(JNIEnv *env, jobject obj)
|
|||||||
return dc_msg_get_id(get_dc_msg(env, obj));
|
return dc_msg_get_id(get_dc_msg(env, obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getText(JNIEnv *env, jobject obj)
|
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getText(JNIEnv *env, jobject obj)
|
||||||
{
|
{
|
||||||
char* temp = dc_msg_get_text(get_dc_msg(env, obj));
|
char* temp = dc_msg_get_text(get_dc_msg(env, obj));
|
||||||
@@ -1619,6 +1594,15 @@ JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_hasHtml(JNIEnv *env, jobject ob
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getSetupCodeBegin(JNIEnv *env, jobject obj)
|
||||||
|
{
|
||||||
|
char* temp = dc_msg_get_setupcodebegin(get_dc_msg(env, obj));
|
||||||
|
jstring ret = JSTRING_NEW(temp);
|
||||||
|
dc_str_unref(temp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT void Java_com_b44t_messenger_DcMsg_setSubject(JNIEnv *env, jobject obj, jstring text)
|
JNIEXPORT void Java_com_b44t_messenger_DcMsg_setSubject(JNIEnv *env, jobject obj, jstring text)
|
||||||
{
|
{
|
||||||
CHAR_REF(text);
|
CHAR_REF(text);
|
||||||
@@ -1643,6 +1627,12 @@ JNIEXPORT void Java_com_b44t_messenger_DcMsg_setHtml(JNIEnv *env, jobject obj, j
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JNIEXPORT void Java_com_b44t_messenger_DcMsg_forceSticker(JNIEnv *env, jobject obj)
|
||||||
|
{
|
||||||
|
dc_msg_force_sticker(get_dc_msg(env, obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getPOILocation(JNIEnv *env, jobject obj)
|
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getPOILocation(JNIEnv *env, jobject obj)
|
||||||
{
|
{
|
||||||
char* temp = dc_msg_get_poi_location(get_dc_msg(env, obj));
|
char* temp = dc_msg_get_poi_location(get_dc_msg(env, obj));
|
||||||
|
|||||||
+1
-1
Submodule jni/deltachat-core-rust updated: 9435042594...8b2e88f45a
Vendored
-5
@@ -13,8 +13,3 @@
|
|||||||
-keep class org.thoughtcrime.securesms.crypto.KeyStoreHelper* { *; }
|
-keep class org.thoughtcrime.securesms.crypto.KeyStoreHelper* { *; }
|
||||||
|
|
||||||
-dontwarn com.google.firebase.analytics.connector.AnalyticsConnector
|
-dontwarn com.google.firebase.analytics.connector.AnalyticsConnector
|
||||||
|
|
||||||
# Keep WebRTC classes
|
|
||||||
-keep class org.webrtc.** { *; }
|
|
||||||
-keepclassmembers class org.webrtc.** { *; }
|
|
||||||
-keepattributes InnerClasses
|
|
||||||
|
|||||||
@@ -9,4 +9,3 @@ cd "$ROOT_DIR"
|
|||||||
|
|
||||||
# generate code
|
# generate code
|
||||||
dcrpcgen java --schema schema.json -o ./src/main/java/
|
dcrpcgen java --schema schema.json -o ./src/main/java/
|
||||||
rm schema.json
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ cd ../..
|
|||||||
SYMBOLS_ZIP="$APK-symbols.zip"
|
SYMBOLS_ZIP="$APK-symbols.zip"
|
||||||
rm $SYMBOLS_ZIP
|
rm $SYMBOLS_ZIP
|
||||||
zip -r $SYMBOLS_ZIP obj
|
zip -r $SYMBOLS_ZIP obj
|
||||||
zip $SYMBOLS_ZIP build/outputs/mapping/gplayRelease/mapping.txt
|
|
||||||
ls -l $SYMBOLS_ZIP
|
ls -l $SYMBOLS_ZIP
|
||||||
rsync --progress $SYMBOLS_ZIP jekyll@download.delta.chat:/var/www/html/download/android/symbols/
|
rsync --progress $SYMBOLS_ZIP jekyll@download.delta.chat:/var/www/html/download/android/symbols/
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
eclipse.preferences.version=1
|
|
||||||
lineWidth=100
|
|
||||||
splitMultiAttrs=true
|
|
||||||
indentMultipleAttributes=true
|
|
||||||
indentationChar=space
|
|
||||||
indentationSize=4
|
|
||||||
spaceBeforeEmptyCloseTag=true
|
|
||||||
@@ -11,6 +11,7 @@ import android.content.ComponentName;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.test.espresso.NoMatchingViewException;
|
import androidx.test.espresso.NoMatchingViewException;
|
||||||
import androidx.test.espresso.UiController;
|
import androidx.test.espresso.UiController;
|
||||||
@@ -18,6 +19,7 @@ import androidx.test.espresso.ViewAction;
|
|||||||
import androidx.test.espresso.ViewInteraction;
|
import androidx.test.espresso.ViewInteraction;
|
||||||
import androidx.test.espresso.util.TreeIterables;
|
import androidx.test.espresso.util.TreeIterables;
|
||||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||||
|
|
||||||
import org.hamcrest.Matcher;
|
import org.hamcrest.Matcher;
|
||||||
import org.thoughtcrime.securesms.ConversationListActivity;
|
import org.thoughtcrime.securesms.ConversationListActivity;
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
@@ -58,12 +60,10 @@ public class TestUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static ActivityScenarioRule<ConversationListActivity> getOfflineActivityRule(
|
public static ActivityScenarioRule<ConversationListActivity> getOfflineActivityRule(boolean useExistingChats) {
|
||||||
boolean useExistingChats) {
|
|
||||||
Intent intent =
|
Intent intent =
|
||||||
Intent.makeMainActivity(
|
Intent.makeMainActivity(
|
||||||
new ComponentName(
|
new ComponentName(getInstrumentation().getTargetContext(), ConversationListActivity.class));
|
||||||
getInstrumentation().getTargetContext(), ConversationListActivity.class));
|
|
||||||
if (!useExistingChats) {
|
if (!useExistingChats) {
|
||||||
createOfflineAccount();
|
createOfflineAccount();
|
||||||
}
|
}
|
||||||
@@ -72,22 +72,18 @@ public class TestUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static <T extends Activity> ActivityScenarioRule<T> getOnlineActivityRule(
|
public static <T extends Activity> ActivityScenarioRule<T> getOnlineActivityRule(Class<T> activityClass) {
|
||||||
Class<T> activityClass) {
|
|
||||||
Context context = getInstrumentation().getTargetContext();
|
Context context = getInstrumentation().getTargetContext();
|
||||||
AccountManager.getInstance().beginAccountCreation(context);
|
AccountManager.getInstance().beginAccountCreation(context);
|
||||||
prepare();
|
prepare();
|
||||||
return new ActivityScenarioRule<>(
|
return new ActivityScenarioRule<>(new Intent(getInstrumentation().getTargetContext(), activityClass));
|
||||||
new Intent(getInstrumentation().getTargetContext(), activityClass));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void prepare() {
|
private static void prepare() {
|
||||||
Prefs.setBooleanPreference(
|
Prefs.setBooleanPreference(getInstrumentation().getTargetContext(), Prefs.DOZE_ASKED_DIRECTLY, true);
|
||||||
getInstrumentation().getTargetContext(), Prefs.DOZE_ASKED_DIRECTLY, true);
|
|
||||||
if (!AccessibilityUtil.areAnimationsDisabled(getInstrumentation().getTargetContext())) {
|
if (!AccessibilityUtil.areAnimationsDisabled(getInstrumentation().getTargetContext())) {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException("To run the tests, disable animations at Developer options' " +
|
||||||
"To run the tests, disable animations at Developer options' "
|
"-> 'Window/Transition/Animator animation scale' -> Set all 3 to 'off'");
|
||||||
+ "-> 'Window/Transition/Animator animation scale' -> Set all 3 to 'off'");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,22 +116,26 @@ public class TestUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
throw new NoMatchingViewException.Builder()
|
throw new NoMatchingViewException.Builder()
|
||||||
.withRootView(view)
|
.withRootView(view)
|
||||||
.withViewMatcher(matcher)
|
.withViewMatcher(matcher)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform action of implicitly waiting for a certain view. This differs from
|
* Perform action of implicitly waiting for a certain view.
|
||||||
* EspressoExtensions.searchFor in that, upon failure to locate an element, it will fetch a new
|
* This differs from EspressoExtensions.searchFor in that,
|
||||||
* root view in which to traverse searching for our @param match
|
* upon failure to locate an element, it will fetch a new root view
|
||||||
|
* in which to traverse searching for our @param match
|
||||||
*
|
*
|
||||||
* @param viewMatcher ViewMatcher used to find our view
|
* @param viewMatcher ViewMatcher used to find our view
|
||||||
*/
|
*/
|
||||||
public static ViewInteraction waitForView(
|
public static ViewInteraction waitForView(
|
||||||
Matcher<View> viewMatcher, int waitMillis, int waitMillisPerTry) {
|
Matcher<View> viewMatcher,
|
||||||
|
int waitMillis,
|
||||||
|
int waitMillisPerTry
|
||||||
|
) {
|
||||||
|
|
||||||
// Derive the max tries
|
// Derive the max tries
|
||||||
int maxTries = (int) (waitMillis / waitMillisPerTry);
|
int maxTries = (int) (waitMillis / waitMillisPerTry);
|
||||||
@@ -164,11 +164,12 @@ public class TestUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normally, you would do onView(withId(R.id.send_button)).perform(click()); to send the draft
|
* Normally, you would do
|
||||||
* message. However, in order to change the send button to the attach button while there is no
|
* onView(withId(R.id.send_button)).perform(click());
|
||||||
* draft, the send button is made invisible and the attach button is made visible instead. This
|
* to send the draft message. However, in order to change the send button to the attach button
|
||||||
* confuses the test framework.<br>
|
* while there is no draft, the send button is made invisible and the attach button is made
|
||||||
* <br>
|
* visible instead. This confuses the test framework.<br/><br/>
|
||||||
|
*
|
||||||
* So, this is a workaround for pressing the send button.
|
* So, this is a workaround for pressing the send button.
|
||||||
*/
|
*/
|
||||||
public static void pressSend() {
|
public static void pressSend() {
|
||||||
|
|||||||
@@ -10,11 +10,14 @@ import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
|||||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.test.espresso.contrib.RecyclerViewActions;
|
import androidx.test.espresso.contrib.RecyclerViewActions;
|
||||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import androidx.test.filters.LargeTest;
|
import androidx.test.filters.LargeTest;
|
||||||
|
|
||||||
import com.b44t.messenger.TestUtils;
|
import com.b44t.messenger.TestUtils;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
@@ -31,19 +34,18 @@ public class EnterChatsBenchmark {
|
|||||||
// ==============================================================================================
|
// ==============================================================================================
|
||||||
// Set this to true if you already have at least 10 chats on your existing DeltaChat installation
|
// Set this to true if you already have at least 10 chats on your existing DeltaChat installation
|
||||||
// and want to traverse through them instead of 10 newly created chats
|
// and want to traverse through them instead of 10 newly created chats
|
||||||
private static final boolean USE_EXISTING_CHATS = false;
|
private final static boolean USE_EXISTING_CHATS = false;
|
||||||
// ==============================================================================================
|
// ==============================================================================================
|
||||||
private static final int GO_THROUGH_ALL_CHATS_N_TIMES = 8;
|
private final static int GO_THROUGH_ALL_CHATS_N_TIMES = 8;
|
||||||
|
|
||||||
// ==============================================================================================
|
// ==============================================================================================
|
||||||
// PLEASE BACKUP YOUR ACCOUNT BEFORE RUNNING THIS!
|
// PLEASE BACKUP YOUR ACCOUNT BEFORE RUNNING THIS!
|
||||||
// ==============================================================================================
|
// ==============================================================================================
|
||||||
|
|
||||||
private static final String TAG = "EnterChatsBenchmark";
|
private final static String TAG = EnterChatsBenchmark.class.getSimpleName();
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public ActivityScenarioRule<ConversationListActivity> activityRule =
|
public ActivityScenarioRule<ConversationListActivity> activityRule = TestUtils.getOfflineActivityRule(USE_EXISTING_CHATS);
|
||||||
TestUtils.getOfflineActivityRule(USE_EXISTING_CHATS);
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createAndEnter10FilledChats() {
|
public void createAndEnter10FilledChats() {
|
||||||
@@ -53,9 +55,7 @@ public class EnterChatsBenchmark {
|
|||||||
for (int i = 0; i < GO_THROUGH_ALL_CHATS_N_TIMES; i++) {
|
for (int i = 0; i < GO_THROUGH_ALL_CHATS_N_TIMES; i++) {
|
||||||
times[i] = "" + timeGoToNChats(10); // 10 group chats were created
|
times[i] = "" + timeGoToNChats(10); // 10 group chats were created
|
||||||
}
|
}
|
||||||
Log.i(
|
Log.i(TAG, "MEASURED RESULTS (Benchmark) - Going thorough all 10 chats: " + String.join(",", times));
|
||||||
TAG,
|
|
||||||
"MEASURED RESULTS (Benchmark) - Going thorough all 10 chats: " + String.join(",", times));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -66,17 +66,13 @@ public class EnterChatsBenchmark {
|
|||||||
for (int i = 0; i < GO_THROUGH_ALL_CHATS_N_TIMES; i++) {
|
for (int i = 0; i < GO_THROUGH_ALL_CHATS_N_TIMES; i++) {
|
||||||
times[i] = "" + timeGoToNChats(1);
|
times[i] = "" + timeGoToNChats(1);
|
||||||
}
|
}
|
||||||
Log.i(
|
Log.i(TAG, "MEASURED RESULTS (Benchmark) - Entering and leaving 1 empty chat: " + String.join(",", times));
|
||||||
TAG,
|
|
||||||
"MEASURED RESULTS (Benchmark) - Entering and leaving 1 empty chat: "
|
|
||||||
+ String.join(",", times));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void enterFilledChat() {
|
public void enterFilledChat() {
|
||||||
if (!USE_EXISTING_CHATS) {
|
if (!USE_EXISTING_CHATS) {
|
||||||
createChatAndGoBack(
|
createChatAndGoBack("Group #1", true, "Hello!", "Some links: https://testrun.org", "And a command: /help");
|
||||||
"Group #1", true, "Hello!", "Some links: https://testrun.org", "And a command: /help");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] times = new String[50];
|
String[] times = new String[50];
|
||||||
@@ -86,18 +82,7 @@ public class EnterChatsBenchmark {
|
|||||||
long end = System.currentTimeMillis();
|
long end = System.currentTimeMillis();
|
||||||
long diff = end - start;
|
long diff = end - start;
|
||||||
pressBack();
|
pressBack();
|
||||||
Log.i(
|
Log.i(TAG, "Measured (Benchmark) " + (i+1) + "/" + times.length + ": Entering 1 filled chat took " + diff + "ms " + "(going back took " + (System.currentTimeMillis() - end) + "ms)");
|
||||||
TAG,
|
|
||||||
"Measured (Benchmark) "
|
|
||||||
+ (i + 1)
|
|
||||||
+ "/"
|
|
||||||
+ times.length
|
|
||||||
+ ": Entering 1 filled chat took "
|
|
||||||
+ diff
|
|
||||||
+ "ms "
|
|
||||||
+ "(going back took "
|
|
||||||
+ (System.currentTimeMillis() - end)
|
|
||||||
+ "ms)");
|
|
||||||
|
|
||||||
times[i] = "" + diff;
|
times[i] = "" + diff;
|
||||||
}
|
}
|
||||||
@@ -106,37 +91,16 @@ public class EnterChatsBenchmark {
|
|||||||
|
|
||||||
private void create10Chats(boolean fillWithMsgs) {
|
private void create10Chats(boolean fillWithMsgs) {
|
||||||
if (!USE_EXISTING_CHATS) {
|
if (!USE_EXISTING_CHATS) {
|
||||||
createChatAndGoBack(
|
createChatAndGoBack("Group #1", fillWithMsgs, "Hello!", "Some links: https://testrun.org", "And a command: /help");
|
||||||
"Group #1",
|
createChatAndGoBack("Group #2", fillWithMsgs, "example.org, alice@example.org", "aaaaaaa", "bbbbbb");
|
||||||
fillWithMsgs,
|
createChatAndGoBack("Group #3", fillWithMsgs, repeat("Some string ", 600), repeat("Another string", 200), "Hi!!!");
|
||||||
"Hello!",
|
|
||||||
"Some links: https://testrun.org",
|
|
||||||
"And a command: /help");
|
|
||||||
createChatAndGoBack(
|
|
||||||
"Group #2", fillWithMsgs, "example.org, alice@example.org", "aaaaaaa", "bbbbbb");
|
|
||||||
createChatAndGoBack(
|
|
||||||
"Group #3",
|
|
||||||
fillWithMsgs,
|
|
||||||
repeat("Some string ", 600),
|
|
||||||
repeat("Another string", 200),
|
|
||||||
"Hi!!!");
|
|
||||||
createChatAndGoBack("Group #4", fillWithMsgs, "xyzabc", "Hi!!!!", "Let's meet!");
|
createChatAndGoBack("Group #4", fillWithMsgs, "xyzabc", "Hi!!!!", "Let's meet!");
|
||||||
createChatAndGoBack(
|
createChatAndGoBack("Group #5", fillWithMsgs, repeat("aaaa", 40), "bbbbbbbbbbbbbbbbbb", "ccccccccccccccc");
|
||||||
"Group #5", fillWithMsgs, repeat("aaaa", 40), "bbbbbbbbbbbbbbbbbb", "ccccccccccccccc");
|
createChatAndGoBack("Group #6", fillWithMsgs, "aaaaaaaaaaa", repeat("Hi! ", 1000), "bbbbbbbbbb");
|
||||||
createChatAndGoBack(
|
createChatAndGoBack("Group #7", fillWithMsgs, repeat("abcdefg ", 500), repeat("xxxxx", 100), "yrrrrrrrrrrrrr");
|
||||||
"Group #6", fillWithMsgs, "aaaaaaaaaaa", repeat("Hi! ", 1000), "bbbbbbbbbb");
|
createChatAndGoBack("Group #8", fillWithMsgs, "and a number: 037362/384756", "ccccc", "Nice!");
|
||||||
createChatAndGoBack(
|
createChatAndGoBack("Group #9", fillWithMsgs, "ddddddddddddddddd", "zuuuuuuuuuuuuuuuu", "ccccc");
|
||||||
"Group #7",
|
createChatAndGoBack("Group #10", fillWithMsgs, repeat("xxxxxxyyyyy", 100), repeat("String!!", 10), "abcd");
|
||||||
fillWithMsgs,
|
|
||||||
repeat("abcdefg ", 500),
|
|
||||||
repeat("xxxxx", 100),
|
|
||||||
"yrrrrrrrrrrrrr");
|
|
||||||
createChatAndGoBack(
|
|
||||||
"Group #8", fillWithMsgs, "and a number: 037362/384756", "ccccc", "Nice!");
|
|
||||||
createChatAndGoBack(
|
|
||||||
"Group #9", fillWithMsgs, "ddddddddddddddddd", "zuuuuuuuuuuuuuuuu", "ccccc");
|
|
||||||
createChatAndGoBack(
|
|
||||||
"Group #10", fillWithMsgs, repeat("xxxxxxyyyyy", 100), repeat("String!!", 10), "abcd");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,10 +130,10 @@ public class EnterChatsBenchmark {
|
|||||||
onView(withContentDescription(R.string.group_create_button)).perform(click());
|
onView(withContentDescription(R.string.group_create_button)).perform(click());
|
||||||
|
|
||||||
if (fillWithMsgs) {
|
if (fillWithMsgs) {
|
||||||
for (String t : texts) {
|
for (String t: texts) {
|
||||||
sendText(t);
|
sendText(t);
|
||||||
}
|
}
|
||||||
for (String t : texts) {
|
for (String t: texts) {
|
||||||
sendText(t);
|
sendText(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ import androidx.test.espresso.contrib.RecyclerViewActions;
|
|||||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import androidx.test.filters.LargeTest;
|
import androidx.test.filters.LargeTest;
|
||||||
|
|
||||||
import com.b44t.messenger.DcContact;
|
import com.b44t.messenger.DcContact;
|
||||||
import com.b44t.messenger.DcContext;
|
import com.b44t.messenger.DcContext;
|
||||||
import com.b44t.messenger.TestUtils;
|
import com.b44t.messenger.TestUtils;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
@@ -28,6 +29,8 @@ import org.thoughtcrime.securesms.ConversationListActivity;
|
|||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@LargeTest
|
@LargeTest
|
||||||
public class ForwardingTest {
|
public class ForwardingTest {
|
||||||
@@ -40,8 +43,7 @@ public class ForwardingTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public final ActivityScenarioRule<ConversationListActivity> activityRule =
|
public final ActivityScenarioRule<ConversationListActivity> activityRule = TestUtils.getOfflineActivityRule(false);
|
||||||
TestUtils.getOfflineActivityRule(false);
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void createChats() {
|
public void createChats() {
|
||||||
@@ -49,13 +51,10 @@ public class ForwardingTest {
|
|||||||
dcContext.createChatByContactId(DcContact.DC_CONTACT_ID_SELF);
|
dcContext.createChatByContactId(DcContact.DC_CONTACT_ID_SELF);
|
||||||
// Disable bcc_self so that DC doesn't try to send messages to the server.
|
// Disable bcc_self so that DC doesn't try to send messages to the server.
|
||||||
// If we didn't do this, messages would stay in DC_STATE_OUT_PENDING forever.
|
// If we didn't do this, messages would stay in DC_STATE_OUT_PENDING forever.
|
||||||
// The thing is, DC_STATE_OUT_PENDING show a rotating circle animation, and Espresso doesn't
|
// The thing is, DC_STATE_OUT_PENDING show a rotating circle animation, and Espresso doesn't work
|
||||||
// work
|
|
||||||
// with animations, and the tests would hang and never finish.
|
// with animations, and the tests would hang and never finish.
|
||||||
dcContext.setConfig("bcc_self", "0");
|
dcContext.setConfig("bcc_self", "0");
|
||||||
activityRule
|
activityRule.getScenario().onActivity(a -> createdGroupId = DcHelper.getContext(a).createGroupChat( "group"));
|
||||||
.getScenario()
|
|
||||||
.onActivity(a -> createdGroupId = DcHelper.getContext(a).createGroupChat("group"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -69,8 +68,7 @@ public class ForwardingTest {
|
|||||||
// The group is at position 0, self chat is at position 1, device talk is at position 2
|
// The group is at position 0, self chat is at position 1, device talk is at position 2
|
||||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(2, click()));
|
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(2, click()));
|
||||||
onView(withId(R.id.title)).check(matches(withText(R.string.device_talk)));
|
onView(withId(R.id.title)).check(matches(withText(R.string.device_talk)));
|
||||||
onView(withId(android.R.id.list))
|
onView(withId(android.R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(0, longClick()));
|
||||||
.perform(RecyclerViewActions.actionOnItemAtPosition(0, longClick()));
|
|
||||||
onView(withId(R.id.menu_context_forward)).perform(click());
|
onView(withId(R.id.menu_context_forward)).perform(click());
|
||||||
// Send it to self chat (which is sorted to the top because we're forwarding)
|
// Send it to self chat (which is sorted to the top because we're forwarding)
|
||||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
|
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
|
||||||
@@ -79,13 +77,11 @@ public class ForwardingTest {
|
|||||||
|
|
||||||
pressBack();
|
pressBack();
|
||||||
|
|
||||||
onView(withId(R.id.toolbar_title))
|
onView(withId(R.id.toolbar_title)).check(matches(withText(R.string.connectivity_not_connected)));
|
||||||
.check(matches(withText(R.string.connectivity_not_connected)));
|
|
||||||
// Self chat moved up because we sent a message there
|
// Self chat moved up because we sent a message there
|
||||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
|
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
|
||||||
onView(withId(R.id.title)).check(matches(withText(R.string.saved_messages)));
|
onView(withId(R.id.title)).check(matches(withText(R.string.saved_messages)));
|
||||||
onView(withId(android.R.id.list))
|
onView(withId(android.R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(0, longClick()));
|
||||||
.perform(RecyclerViewActions.actionOnItemAtPosition(0, longClick()));
|
|
||||||
onView(withId(R.id.menu_context_forward)).perform(click());
|
onView(withId(R.id.menu_context_forward)).perform(click());
|
||||||
// Send it to the group
|
// Send it to the group
|
||||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(1, click()));
|
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(1, click()));
|
||||||
@@ -93,7 +89,6 @@ public class ForwardingTest {
|
|||||||
onView(withId(R.id.title)).check(matches(withText("group")));
|
onView(withId(R.id.title)).check(matches(withText("group")));
|
||||||
|
|
||||||
pressBack();
|
pressBack();
|
||||||
onView(withId(R.id.toolbar_title))
|
onView(withId(R.id.toolbar_title)).check(matches(withText(R.string.connectivity_not_connected)));
|
||||||
.check(matches(withText(R.string.connectivity_not_connected)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,13 +14,15 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat
|
|||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import androidx.test.espresso.contrib.RecyclerViewActions;
|
import androidx.test.espresso.contrib.RecyclerViewActions;
|
||||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import androidx.test.filters.LargeTest;
|
import androidx.test.filters.LargeTest;
|
||||||
|
|
||||||
import com.b44t.messenger.DcContext;
|
import com.b44t.messenger.DcContext;
|
||||||
import com.b44t.messenger.TestUtils;
|
import com.b44t.messenger.TestUtils;
|
||||||
import java.io.File;
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
@@ -32,6 +34,9 @@ import org.thoughtcrime.securesms.R;
|
|||||||
import org.thoughtcrime.securesms.ShareActivity;
|
import org.thoughtcrime.securesms.ShareActivity;
|
||||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@LargeTest
|
@LargeTest
|
||||||
public class SharingTest {
|
public class SharingTest {
|
||||||
@@ -43,34 +48,26 @@ public class SharingTest {
|
|||||||
private static int createdSingleChatId;
|
private static int createdSingleChatId;
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public final ActivityScenarioRule<ConversationListActivity> activityRule =
|
public final ActivityScenarioRule<ConversationListActivity> activityRule = TestUtils.getOfflineActivityRule(false);
|
||||||
TestUtils.getOfflineActivityRule(false);
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void createGroup() {
|
public void createGroup() {
|
||||||
activityRule
|
activityRule.getScenario().onActivity(a -> createdGroupId = DcHelper.getContext(a).createGroupChat( "group"));
|
||||||
.getScenario()
|
|
||||||
.onActivity(a -> createdGroupId = DcHelper.getContext(a).createGroupChat("group"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void createSingleChat() {
|
public void createSingleChat() {
|
||||||
activityRule
|
activityRule.getScenario().onActivity(a -> {
|
||||||
.getScenario()
|
int contactId = DcHelper.getContext(a).createContact("", "abc@example.org");
|
||||||
.onActivity(
|
createdSingleChatId = DcHelper.getContext(a).createChatByContactId(contactId);
|
||||||
a -> {
|
});
|
||||||
int contactId = DcHelper.getContext(a).createContact("", "abc@example.org");
|
|
||||||
createdSingleChatId = DcHelper.getContext(a).createChatByContactId(contactId);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNormalSharing() {
|
public void testNormalSharing() {
|
||||||
Intent i = new Intent(Intent.ACTION_SEND);
|
Intent i = new Intent(Intent.ACTION_SEND);
|
||||||
i.putExtra(Intent.EXTRA_TEXT, "Hello!");
|
i.putExtra(Intent.EXTRA_TEXT, "Hello!");
|
||||||
i.setComponent(
|
i.setComponent(new ComponentName(getInstrumentation().getTargetContext().getApplicationContext(), ShareActivity.class));
|
||||||
new ComponentName(
|
|
||||||
getInstrumentation().getTargetContext().getApplicationContext(), ShareActivity.class));
|
|
||||||
activityRule.getScenario().onActivity(a -> a.startActivity(i));
|
activityRule.getScenario().onActivity(a -> a.startActivity(i));
|
||||||
|
|
||||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
|
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
|
||||||
@@ -80,9 +77,9 @@ public class SharingTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test direct sharing from a screenshot. Also, this is the regression test for
|
* Test direct sharing from a screenshot.
|
||||||
* https://github.com/deltachat/deltachat-android/issues/2040 where network changes during sharing
|
* Also, this is the regression test for https://github.com/deltachat/deltachat-android/issues/2040
|
||||||
* lead to a bug
|
* where network changes during sharing lead to a bug
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testShareFromScreenshot() {
|
public void testShareFromScreenshot() {
|
||||||
@@ -95,25 +92,20 @@ public class SharingTest {
|
|||||||
pngImage = file;
|
pngImage = file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Uri uri =
|
Uri uri = Uri.parse("content://" + BuildConfig.APPLICATION_ID + ".attachments/" + Uri.encode(pngImage));
|
||||||
Uri.parse(
|
|
||||||
"content://" + BuildConfig.APPLICATION_ID + ".attachments/" + Uri.encode(pngImage));
|
|
||||||
DcHelper.sharedFiles.put(pngImage, "image/png");
|
DcHelper.sharedFiles.put(pngImage, "image/png");
|
||||||
|
|
||||||
Intent i = new Intent(Intent.ACTION_SEND);
|
Intent i = new Intent(Intent.ACTION_SEND);
|
||||||
i.setType("image/png");
|
i.setType("image/png");
|
||||||
i.putExtra(Intent.EXTRA_SUBJECT, "Screenshot (Sep 27, 2021 00:00:00");
|
i.putExtra(Intent.EXTRA_SUBJECT, "Screenshot (Sep 27, 2021 00:00:00");
|
||||||
i.setFlags(
|
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
|
||||||
Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
|
|
||||||
| Intent.FLAG_ACTIVITY_FORWARD_RESULT
|
| Intent.FLAG_ACTIVITY_FORWARD_RESULT
|
||||||
| Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP
|
| Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP
|
||||||
| Intent.FLAG_RECEIVER_FOREGROUND
|
| Intent.FLAG_RECEIVER_FOREGROUND
|
||||||
| Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
| Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
i.putExtra(Intent.EXTRA_STREAM, uri);
|
i.putExtra(Intent.EXTRA_STREAM, uri);
|
||||||
i.putExtra(ShareActivity.EXTRA_CHAT_ID, createdGroupId);
|
i.putExtra(ShareActivity.EXTRA_CHAT_ID, createdGroupId);
|
||||||
i.setComponent(
|
i.setComponent(new ComponentName(getInstrumentation().getTargetContext().getApplicationContext(), ShareActivity.class));
|
||||||
new ComponentName(
|
|
||||||
getInstrumentation().getTargetContext().getApplicationContext(), ShareActivity.class));
|
|
||||||
activityRule.getScenario().onActivity(a -> a.startActivity(i));
|
activityRule.getScenario().onActivity(a -> a.startActivity(i));
|
||||||
|
|
||||||
TestUtils.waitForView(withId(R.id.send_button), 10000, 50);
|
TestUtils.waitForView(withId(R.id.send_button), 10000, 50);
|
||||||
@@ -129,32 +121,16 @@ public class SharingTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests
|
* Tests https://github.com/deltachat/interface/blob/master/user-testing/mailto-links.md#mailto-links:
|
||||||
* https://github.com/deltachat/interface/blob/master/user-testing/mailto-links.md#mailto-links:
|
|
||||||
*
|
*
|
||||||
* <ul dir="auto">
|
* <ul dir="auto">
|
||||||
* <li><a href="mailto:abc@example.org">Just an email address</a> - should open a chat with
|
* <li><a href="mailto:abc@example.org">Just an email address</a> - should open a chat with <code>abc@example.org</code> (and maybe ask whether a chat should be created if it does not exist already)</li>
|
||||||
* <code>abc@example.org</code> (and maybe ask whether a chat should be created if it does
|
* <li><a href="mailto:abc@example.org?subject=testing%20mailto%20uris">email address with subject</a> - should open a chat with <code>abc@example.org</code> and fill <code>testing mailto uris</code>; as we created the chat in the previous step, it should not ask <code>Chat with …</code> but directly open the chat</li>
|
||||||
* not exist already)
|
* <li><a href="mailto:abc@example.org?body=this%20is%20a%20test">email address with body</a> - should open a chat with <code>abc@example.org</code>, draft <code>this is a test</code></li>
|
||||||
* <li><a href="mailto:abc@example.org?subject=testing%20mailto%20uris">email address with
|
* <li><a href="mailto:abc@example.org?subject=testing%20mailto%20uris&body=this%20is%20a%20test">email address with subject and body</a> - should open a chat with <code>abc@example.org</code>, draft <code>testing mailto uris</code> <newline> <code>this is a test</code></li>
|
||||||
* subject</a> - should open a chat with <code>abc@example.org</code> and fill <code>
|
* <li><a href="mailto:%20info@example.org">HTML encoding</a> - should open a chat with <code>info@example.org</code></li>
|
||||||
* testing mailto uris</code>; as we created the chat in the previous step, it should not
|
* <li><a href="mailto:simplebot@example.org?body=!web%20https%3A%2F%2Fduckduckgo.com%2Flite%3Fq%3Dduck%2520it">more HTML encoding</a> - should open a chat with <code>simplebot@example.org</code>, draft <code>!web https://duckduckgo.com/lite?q=duck%20it</code></li>
|
||||||
* ask <code>Chat with …</code> but directly open the chat
|
* <li><a href="mailto:?subject=bla&body=blub">no email, just subject&body</a> - this should let you choose a chat and create a draft <code>bla</code> <newline> <code>blub</code> there</li>
|
||||||
* <li><a href="mailto:abc@example.org?body=this%20is%20a%20test">email address with body</a> -
|
|
||||||
* should open a chat with <code>abc@example.org</code>, draft <code>this is a test</code>
|
|
||||||
* <li><a
|
|
||||||
* href="mailto:abc@example.org?subject=testing%20mailto%20uris&body=this%20is%20a%20test">email
|
|
||||||
* address with subject and body</a> - should open a chat with <code>abc@example.org</code>,
|
|
||||||
* draft <code>testing mailto uris</code> <newline> <code>this is a test</code>
|
|
||||||
* <li><a href="mailto:%20info@example.org">HTML encoding</a> - should open a chat with <code>
|
|
||||||
* info@example.org</code>
|
|
||||||
* <li><a
|
|
||||||
* href="mailto:simplebot@example.org?body=!web%20https%3A%2F%2Fduckduckgo.com%2Flite%3Fq%3Dduck%2520it">more
|
|
||||||
* HTML encoding</a> - should open a chat with <code>simplebot@example.org</code>, draft
|
|
||||||
* <code>!web https://duckduckgo.com/lite?q=duck%20it</code>
|
|
||||||
* <li><a href="mailto:?subject=bla&body=blub">no email, just subject&body</a> - this
|
|
||||||
* should let you choose a chat and create a draft <code>bla</code> <newline> <code>
|
|
||||||
* blub</code> there
|
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@@ -164,8 +140,7 @@ public class SharingTest {
|
|||||||
|
|
||||||
openLink("mailto:abc@example.org?subject=testing%20mailto%20uris");
|
openLink("mailto:abc@example.org?subject=testing%20mailto%20uris");
|
||||||
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
||||||
onView(withHint(R.string.chat_input_placeholder))
|
onView(withHint(R.string.chat_input_placeholder)).check(matches(withText("testing mailto uris")));
|
||||||
.check(matches(withText("testing mailto uris")));
|
|
||||||
|
|
||||||
openLink("mailto:abc@example.org?body=this%20is%20a%20test");
|
openLink("mailto:abc@example.org?body=this%20is%20a%20test");
|
||||||
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
||||||
@@ -173,22 +148,17 @@ public class SharingTest {
|
|||||||
|
|
||||||
openLink("mailto:abc@example.org?subject=testing%20mailto%20uris&body=this%20is%20a%20test");
|
openLink("mailto:abc@example.org?subject=testing%20mailto%20uris&body=this%20is%20a%20test");
|
||||||
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
||||||
onView(withHint(R.string.chat_input_placeholder))
|
onView(withHint(R.string.chat_input_placeholder)).check(matches(withText("testing mailto uris\nthis is a test")));
|
||||||
.check(matches(withText("testing mailto uris\nthis is a test")));
|
|
||||||
|
|
||||||
openLink("mailto:%20abc@example.org");
|
openLink("mailto:%20abc@example.org");
|
||||||
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
||||||
|
|
||||||
openLink(
|
openLink("mailto:abc@example.org?body=!web%20https%3A%2F%2Fduckduckgo.com%2Flite%3Fq%3Dduck%2520it");
|
||||||
"mailto:abc@example.org?body=!web%20https%3A%2F%2Fduckduckgo.com%2Flite%3Fq%3Dduck%2520it");
|
|
||||||
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
||||||
onView(withHint(R.string.chat_input_placeholder))
|
onView(withHint(R.string.chat_input_placeholder)).check(matches(withText("!web https://duckduckgo.com/lite?q=duck%20it")));
|
||||||
.check(matches(withText("!web https://duckduckgo.com/lite?q=duck%20it")));
|
|
||||||
|
|
||||||
openLink("mailto:?subject=bla&body=blub");
|
openLink("mailto:?subject=bla&body=blub");
|
||||||
onView(withId(R.id.list))
|
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
||||||
.perform(
|
|
||||||
RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
|
||||||
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
||||||
onView(withHint(R.string.chat_input_placeholder)).check(matches(withText("bla\nblub")));
|
onView(withHint(R.string.chat_input_placeholder)).check(matches(withText("bla\nblub")));
|
||||||
}
|
}
|
||||||
@@ -200,61 +170,49 @@ public class SharingTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
*
|
|
||||||
* <ul dir="auto">
|
* <ul dir="auto">
|
||||||
* <li>Open Saved Messages chat (could be any other chat too)
|
* <li>Open Saved Messages chat (could be any other chat too)</li>
|
||||||
* <li>Go to another app and share some text to DC
|
* <li>Go to another app and share some text to DC</li>
|
||||||
* <li>In DC select Saved Messages. Edit the shared text if you like. <em>Don't</em> hit the
|
* <li>In DC select Saved Messages. Edit the shared text if you like. <em>Don't</em> hit the Send button.</li>
|
||||||
* Send button.
|
* <li>Leave DC</li>
|
||||||
* <li>Leave DC
|
* <li>Open DC again from the "Recent apps"</li>
|
||||||
* <li>Open DC again from the "Recent apps"
|
* <li>Check that your draft is still there</li>
|
||||||
* <li>Check that your draft is still there
|
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testOpenAgainFromRecents() {
|
public void testOpenAgainFromRecents() {
|
||||||
// Open a chat
|
// Open a chat
|
||||||
onView(withId(R.id.list))
|
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
||||||
.perform(
|
|
||||||
RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
|
||||||
|
|
||||||
// Share some text to DC
|
// Share some text to DC
|
||||||
Intent i = new Intent(Intent.ACTION_SEND);
|
Intent i = new Intent(Intent.ACTION_SEND);
|
||||||
i.putExtra(Intent.EXTRA_TEXT, "Veeery important draft");
|
i.putExtra(Intent.EXTRA_TEXT, "Veeery important draft");
|
||||||
i.setComponent(
|
i.setComponent(new ComponentName(getInstrumentation().getTargetContext().getApplicationContext(), ShareActivity.class));
|
||||||
new ComponentName(
|
|
||||||
getInstrumentation().getTargetContext().getApplicationContext(), ShareActivity.class));
|
|
||||||
activityRule.getScenario().onActivity(a -> a.startActivity(i));
|
activityRule.getScenario().onActivity(a -> a.startActivity(i));
|
||||||
|
|
||||||
// In DC, select the same chat you opened before
|
// In DC, select the same chat you opened before
|
||||||
onView(withId(R.id.list))
|
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
||||||
.perform(
|
|
||||||
RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
|
||||||
|
|
||||||
// Leave DC and go back to the previous activity
|
// Leave DC and go back to the previous activity
|
||||||
pressBack();
|
pressBack();
|
||||||
|
|
||||||
// Here, we can't exactly replicate the "steps to reproduce". Previously, the other activity
|
// Here, we can't exactly replicate the "steps to reproduce". Previously, the other activity
|
||||||
// stayed open in the background, but since it doesn't anymore, we need to open it again:
|
// stayed open in the background, but since it doesn't anymore, we need to open it again:
|
||||||
onView(withId(R.id.list))
|
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
||||||
.perform(
|
|
||||||
RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
|
||||||
|
|
||||||
// Check that the draft is still there
|
// Check that the draft is still there
|
||||||
// Util.sleep(2000); // Uncomment for debugging
|
// Util.sleep(2000); // Uncomment for debugging
|
||||||
onView(withHint(R.string.chat_input_placeholder))
|
onView(withHint(R.string.chat_input_placeholder)).check(matches(withText("Veeery important draft")));
|
||||||
.check(matches(withText("Veeery important draft")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regression test:
|
* Regression test:
|
||||||
*
|
*
|
||||||
* <p>If you save your contacts's emails in the contacts app of the phone, there are buttons to
|
* If you save your contacts's emails in the contacts app of the phone, there are buttons to call
|
||||||
* call them and also to write an email to them.
|
* them and also to write an email to them.
|
||||||
*
|
*
|
||||||
* <p>If you click the email button, Delta Chat opened but instead of opening a chat with that
|
* If you click the email button, ArcaneChat opened but instead of opening a chat with that contact,
|
||||||
* contact, the chat list was show and "share with" was displayed at the top
|
* the chat list was show and "share with" was displayed at the top
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testOpenChatFromContacts() {
|
public void testOpenChatFromContacts() {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.b44t.messenger.uitests.online;
|
package com.b44t.messenger.uitests.online;
|
||||||
|
|
||||||
|
|
||||||
import static androidx.test.espresso.Espresso.onView;
|
import static androidx.test.espresso.Espresso.onView;
|
||||||
import static androidx.test.espresso.action.ViewActions.click;
|
import static androidx.test.espresso.action.ViewActions.click;
|
||||||
import static androidx.test.espresso.action.ViewActions.replaceText;
|
import static androidx.test.espresso.action.ViewActions.replaceText;
|
||||||
@@ -10,10 +11,13 @@ import static androidx.test.espresso.matcher.ViewMatchers.withHint;
|
|||||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import androidx.test.filters.LargeTest;
|
import androidx.test.filters.LargeTest;
|
||||||
|
|
||||||
import com.b44t.messenger.TestUtils;
|
import com.b44t.messenger.TestUtils;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -26,16 +30,14 @@ import org.thoughtcrime.securesms.WelcomeActivity;
|
|||||||
@LargeTest
|
@LargeTest
|
||||||
public class OnboardingTest {
|
public class OnboardingTest {
|
||||||
@Rule
|
@Rule
|
||||||
public ActivityScenarioRule<WelcomeActivity> activityRule =
|
public ActivityScenarioRule<WelcomeActivity> activityRule = TestUtils.getOnlineActivityRule(WelcomeActivity.class);
|
||||||
TestUtils.getOnlineActivityRule(WelcomeActivity.class);
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAccountCreation() {
|
public void testAccountCreation() {
|
||||||
if (TextUtils.isEmpty(BuildConfig.TEST_ADDR) || TextUtils.isEmpty(BuildConfig.TEST_MAIL_PW)) {
|
if (TextUtils.isEmpty(BuildConfig.TEST_ADDR) || TextUtils.isEmpty(BuildConfig.TEST_MAIL_PW)) {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException("You need to set TEST_ADDR and TEST_MAIL_PW; " +
|
||||||
"You need to set TEST_ADDR and TEST_MAIL_PW; "
|
"either in gradle.properties or via an environment variable. " +
|
||||||
+ "either in gradle.properties or via an environment variable. "
|
"See README.md for more details.");
|
||||||
+ "See README.md for more details.");
|
|
||||||
}
|
}
|
||||||
onView(withText(R.string.scan_invitation_code)).check(matches(isClickable()));
|
onView(withText(R.string.scan_invitation_code)).check(matches(isClickable()));
|
||||||
onView(withText(R.string.import_backup_title)).check(matches(isClickable()));
|
onView(withText(R.string.import_backup_title)).check(matches(isClickable()));
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
<vector
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="228"
|
|
||||||
android:viewportHeight="280">
|
|
||||||
<group
|
|
||||||
android:scaleX="0.35014287"
|
|
||||||
android:scaleY="0.43"
|
|
||||||
android:translateX="74.08372"
|
|
||||||
android:translateY="79.8">
|
|
||||||
<path
|
|
||||||
android:pathData="m10.03,234.14c0.3,-0.01 0.6,-0.02 0.9,-0.04 -0.07,-0.49 -0.14,-0.97 -0.2,-1.46 -0.15,-1.34 -0.26,-2.69 -0.25,-4.04 -0.02,-0.86 -0.05,-1.71 -0.07,-2.57 -0.09,-0.06 -0.18,-0.13 -0.27,-0.19 -0.02,-0.02 -0.04,-0.03 -0.07,-0.05zM44.87,232.95c11.71,-8.35 26.86,-14.79 46.21,-15.9 0,0 39.93,-0.27 47.91,-3.53 7.98,-3.26 68.68,-14.69 82.94,-98.43 14.26,-83.74 -1.06,-115.09 -1.06,-115.09 0,0 -21.14,55.68 -81.02,59.81 0,0 -14.5,1.03 -38.82,1.42 -24.32,0.39 -75.77,20.65 -90.55,85.62l-0.22,43.44c2.5,4.22 5.49,8.12 8.91,11.66 3.99,4.11 8.11,8.12 12.79,11.45 2.26,1.65 4.65,3.2 6.51,5.33 1.94,2.34 3.33,5 4.2,7.93 0.71,2.1 1.45,4.2 2.2,6.28z"
|
|
||||||
android:fillColor="@color/ic_launcher_background" />
|
|
||||||
<path
|
|
||||||
android:pathData="m217.97,45.86c-0.3,0.01 -0.6,0.02 -0.9,0.04 0.07,0.49 0.14,0.97 0.2,1.46 0.15,1.34 0.26,2.69 0.25,4.04 0.02,0.86 0.05,1.71 0.07,2.57 0.09,0.06 0.18,0.13 0.27,0.19 0.02,0.02 0.04,0.03 0.07,0.05zM183.13,47.05c-11.71,8.35 -26.86,14.79 -46.21,15.9 0,0 -39.93,0.27 -47.91,3.53 -7.98,3.26 -68.68,14.69 -82.94,98.43 -14.26,83.74 1.06,115.09 1.06,115.09 0,0 21.14,-55.68 81.02,-59.81 0,0 14.5,-1.03 38.82,-1.42 24.32,-0.39 75.77,-20.65 90.55,-85.62l0.22,-43.44c-2.5,-4.22 -5.49,-8.12 -8.91,-11.66 -3.99,-4.11 -8.11,-8.12 -12.79,-11.45 -2.26,-1.65 -4.65,-3.2 -6.51,-5.33 -1.94,-2.34 -3.33,-5 -4.2,-7.93 -0.71,-2.1 -1.45,-4.2 -2.2,-6.28z"
|
|
||||||
android:fillColor="@color/ic_launcher_background" />
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@color/white" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@color/white" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
|
||||||
@@ -1,16 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
|
|
||||||
<uses-permission
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||||
android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
|
||||||
|
|
||||||
<application>
|
<application>
|
||||||
<service
|
<service
|
||||||
android:name=".connect.KeepAliveService"
|
android:name=".connect.KeepAliveService"
|
||||||
android:foregroundServiceType="specialUse"
|
android:foregroundServiceType="specialUse"
|
||||||
android:enabled="true" />
|
android:enabled="true" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.geolocation;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/** Non-GMS, always uses the platform LocationManager. */
|
|
||||||
public final class LocationSourceFactory {
|
|
||||||
|
|
||||||
private static final String TAG = "LocationSourceFactory";
|
|
||||||
|
|
||||||
private LocationSourceFactory() {}
|
|
||||||
|
|
||||||
public static LocationSource create(Context context) {
|
|
||||||
Log.i(TAG, "Non-GMS build, Using platform LocationManager");
|
|
||||||
return new PlatformLocationSource();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.notifications;
|
package org.thoughtcrime.securesms.notifications;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -9,11 +10,6 @@ import androidx.annotation.Nullable;
|
|||||||
*/
|
*/
|
||||||
public class FcmReceiveService {
|
public class FcmReceiveService {
|
||||||
public static void register(Context context) {}
|
public static void register(Context context) {}
|
||||||
|
|
||||||
public static void waitForRegisterFinished() {}
|
public static void waitForRegisterFinished() {}
|
||||||
|
@Nullable public static String getToken() { return null; }
|
||||||
@Nullable
|
|
||||||
public static String getToken() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,34 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
|
|
||||||
<meta-data
|
<!-- force compiling emojipicker on sdk<21 and firebase on sdk<19; runtime checks are required then -->
|
||||||
android:name="firebase_analytics_collection_deactivated"
|
<uses-sdk tools:overrideLibrary="androidx.emoji2.emojipicker, com.google.firebase.messaging, com.google.android.gms.cloudmessaging"/>
|
||||||
android:value="true" />
|
|
||||||
<meta-data
|
|
||||||
android:name="google_analytics_adid_collection_enabled"
|
|
||||||
android:value="false" />
|
|
||||||
<meta-data
|
|
||||||
android:name="firebase_messaging_auto_init_enabled"
|
|
||||||
android:value="false" />
|
|
||||||
|
|
||||||
<application>
|
<meta-data android:name="firebase_analytics_collection_deactivated" android:value="true" />
|
||||||
<service
|
<meta-data android:name="google_analytics_adid_collection_enabled" android:value="false" />
|
||||||
android:name=".connect.KeepAliveService"
|
<meta-data android:name="firebase_messaging_auto_init_enabled" android:value="false" />
|
||||||
android:foregroundServiceType="dataSync"
|
|
||||||
android:enabled="true" />
|
|
||||||
|
|
||||||
<service
|
<application>
|
||||||
android:name=".notifications.FcmReceiveService"
|
<service
|
||||||
android:foregroundServiceType="dataSync"
|
android:name=".connect.KeepAliveService"
|
||||||
android:exported="true">
|
android:foregroundServiceType="dataSync"
|
||||||
<intent-filter>
|
android:enabled="true" />
|
||||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
|
||||||
</intent-filter>
|
|
||||||
</service>
|
|
||||||
|
|
||||||
<provider
|
<service
|
||||||
android:name="com.google.firebase.provider.FirebaseInitProvider"
|
android:name=".notifications.FcmReceiveService"
|
||||||
android:authorities="${applicationId}.firebaseinitprovider"
|
android:foregroundServiceType="dataSync"
|
||||||
tools:node="remove">
|
android:exported="true">
|
||||||
</provider>
|
<intent-filter>
|
||||||
</application>
|
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name="com.google.firebase.provider.FirebaseInitProvider"
|
||||||
|
android:authorities="${applicationId}.firebaseinitprovider"
|
||||||
|
tools:node="remove">
|
||||||
|
</provider>
|
||||||
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.geolocation;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.location.Location;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.util.Log;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import com.google.android.gms.location.FusedLocationProviderClient;
|
|
||||||
import com.google.android.gms.location.LocationCallback;
|
|
||||||
import com.google.android.gms.location.LocationRequest;
|
|
||||||
import com.google.android.gms.location.LocationResult;
|
|
||||||
import com.google.android.gms.location.LocationServices;
|
|
||||||
import com.google.android.gms.location.Priority;
|
|
||||||
|
|
||||||
public class GmsLocationSource implements LocationSource {
|
|
||||||
|
|
||||||
private static final String TAG = "GmsLocationSource";
|
|
||||||
private static final long UPDATE_INTERVAL_MS = 3_000;
|
|
||||||
private static final long FASTEST_INTERVAL_MS = 1_000;
|
|
||||||
|
|
||||||
private FusedLocationProviderClient client;
|
|
||||||
private LocationCallback locationCallback;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startUpdates(@NonNull Context context, @NonNull Callback callback) {
|
|
||||||
client = LocationServices.getFusedLocationProviderClient(context);
|
|
||||||
|
|
||||||
LocationRequest request =
|
|
||||||
new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, UPDATE_INTERVAL_MS)
|
|
||||||
.setMinUpdateIntervalMillis(FASTEST_INTERVAL_MS)
|
|
||||||
.setMinUpdateDistanceMeters(0)
|
|
||||||
.setWaitForAccurateLocation(false)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
locationCallback =
|
|
||||||
new LocationCallback() {
|
|
||||||
@Override
|
|
||||||
public void onLocationResult(@NonNull LocationResult result) {
|
|
||||||
Location loc = result.getLastLocation();
|
|
||||||
if (loc != null) {
|
|
||||||
callback.onLocationUpdate(loc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
client.requestLocationUpdates(request, locationCallback, Looper.getMainLooper());
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
Log.e(TAG, "Missing location permission", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopUpdates() {
|
|
||||||
if (client != null && locationCallback != null) {
|
|
||||||
client.removeLocationUpdates(locationCallback);
|
|
||||||
client = null;
|
|
||||||
locationCallback = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.geolocation;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Log;
|
|
||||||
import com.google.android.gms.common.ConnectionResult;
|
|
||||||
import com.google.android.gms.common.GoogleApiAvailability;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prefers FusedLocationProviderClient, falls back to platform LocationManager if Play Services are
|
|
||||||
* somehow unavailable.
|
|
||||||
*/
|
|
||||||
public final class LocationSourceFactory {
|
|
||||||
|
|
||||||
private static final String TAG = "LocationSourceFactory";
|
|
||||||
|
|
||||||
private LocationSourceFactory() {}
|
|
||||||
|
|
||||||
public static LocationSource create(Context context) {
|
|
||||||
if (isGmsAvailable(context)) {
|
|
||||||
Log.i(TAG, "Using FusedLocationProviderClient");
|
|
||||||
return new GmsLocationSource();
|
|
||||||
}
|
|
||||||
Log.i(TAG, "GMS unavailable, falling back to LocationManager");
|
|
||||||
return new PlatformLocationSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isGmsAvailable(Context context) {
|
|
||||||
try {
|
|
||||||
return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
|
|
||||||
== ConnectionResult.SUCCESS;
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +1,27 @@
|
|||||||
package org.thoughtcrime.securesms.notifications;
|
package org.thoughtcrime.securesms.notifications;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Build;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.WorkerThread;
|
import androidx.annotation.WorkerThread;
|
||||||
|
|
||||||
import com.google.android.gms.tasks.Tasks;
|
import com.google.android.gms.tasks.Tasks;
|
||||||
import com.google.firebase.FirebaseApp;
|
import com.google.firebase.FirebaseApp;
|
||||||
import com.google.firebase.messaging.FirebaseMessaging;
|
import com.google.firebase.messaging.FirebaseMessaging;
|
||||||
import com.google.firebase.messaging.FirebaseMessagingService;
|
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||||
import com.google.firebase.messaging.RemoteMessage;
|
import com.google.firebase.messaging.RemoteMessage;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
import org.thoughtcrime.securesms.BuildConfig;
|
import org.thoughtcrime.securesms.BuildConfig;
|
||||||
import org.thoughtcrime.securesms.service.FetchForegroundService;
|
import org.thoughtcrime.securesms.service.FetchForegroundService;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
|
||||||
public class FcmReceiveService extends FirebaseMessagingService {
|
public class FcmReceiveService extends FirebaseMessagingService {
|
||||||
private static final String TAG = "FcmReceiveService";
|
private static final String TAG = FcmReceiveService.class.getSimpleName();
|
||||||
private static final Object INIT_LOCK = new Object();
|
private static final Object INIT_LOCK = new Object();
|
||||||
private static boolean initialized;
|
private static boolean initialized;
|
||||||
private static volatile boolean triedRegistering;
|
private static volatile boolean triedRegistering;
|
||||||
@@ -31,38 +35,36 @@ public class FcmReceiveService extends FirebaseMessagingService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Util.runOnAnyBackgroundThread(
|
Util.runOnAnyBackgroundThread(() -> {
|
||||||
() -> {
|
final String rawToken;
|
||||||
final String rawToken;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
synchronized (INIT_LOCK) {
|
synchronized (INIT_LOCK) {
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
// manual init: read tokens from `./google-services.json`;
|
// manual init: read tokens from `./google-services.json`;
|
||||||
// automatic init disabled in AndroidManifest.xml to skip FCM code completely.
|
// automatic init disabled in AndroidManifest.xml to skip FCM code completely.
|
||||||
FirebaseApp.initializeApp(context);
|
FirebaseApp.initializeApp(context);
|
||||||
}
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
rawToken = Tasks.await(FirebaseMessaging.getInstance().getToken());
|
|
||||||
} catch (Exception e) {
|
|
||||||
// we're here usually when FCM is not available and initializeApp() or getToken()
|
|
||||||
// failed.
|
|
||||||
Log.w(TAG, "cannot get FCM token for " + BuildConfig.APPLICATION_ID + ": " + e);
|
|
||||||
triedRegistering = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (TextUtils.isEmpty(rawToken)) {
|
|
||||||
Log.w(TAG, "got empty FCM token for " + BuildConfig.APPLICATION_ID);
|
|
||||||
triedRegistering = true;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
rawToken = Tasks.await(FirebaseMessaging.getInstance().getToken());
|
||||||
|
} catch (Exception e) {
|
||||||
|
// we're here usually when FCM is not available and initializeApp() or getToken() failed.
|
||||||
|
Log.w(TAG, "cannot get FCM token for " + BuildConfig.APPLICATION_ID + ": " + e);
|
||||||
|
triedRegistering = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (TextUtils.isEmpty(rawToken)) {
|
||||||
|
Log.w(TAG, "got empty FCM token for " + BuildConfig.APPLICATION_ID);
|
||||||
|
triedRegistering = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
prefixedToken = addPrefix(rawToken);
|
prefixedToken = addPrefix(rawToken);
|
||||||
Log.i(TAG, "FCM token: " + prefixedToken);
|
Log.i(TAG, "FCM token: " + prefixedToken);
|
||||||
ApplicationContext.getDcAccounts().setPushDeviceToken(prefixedToken);
|
ApplicationContext.getDcAccounts().setPushDeviceToken(prefixedToken);
|
||||||
triedRegistering = true;
|
triedRegistering = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait a until FCM registration got a token or not.
|
// wait a until FCM registration got a token or not.
|
||||||
@@ -96,8 +98,7 @@ public class FcmReceiveService extends FirebaseMessagingService {
|
|||||||
// ForegroundServiceStartNotAllowedException.
|
// ForegroundServiceStartNotAllowedException.
|
||||||
// So, it's recommended to check the result of RemoteMessage.getPriority() and
|
// So, it's recommended to check the result of RemoteMessage.getPriority() and
|
||||||
// confirm it's PRIORITY_HIGH() before attempting to start a foreground service.
|
// confirm it's PRIORITY_HIGH() before attempting to start a foreground service.
|
||||||
// source:
|
// source: https://developer.android.com/develop/background-work/services/fgs/restrictions-bg-start
|
||||||
// https://developer.android.com/develop/background-work/services/fgs/restrictions-bg-start
|
|
||||||
if (remoteMessage.getPriority() == RemoteMessage.PRIORITY_HIGH) {
|
if (remoteMessage.getPriority() == RemoteMessage.PRIORITY_HIGH) {
|
||||||
FetchForegroundService.start(this);
|
FetchForegroundService.start(this);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+451
-562
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -5,6 +5,7 @@
|
|||||||
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
||||||
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
||||||
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
||||||
|
<li><a href="#podporuje-delta-chat-obrázky-videa-a-jiné-přílohy">Podporuje Delta Chat obrázky, videa a jiné přílohy?</a></li>
|
||||||
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
||||||
<li><a href="#kdo-uvidí-můj-profilový-obrázek">Kdo uvidí můj profilový obrázek?</a></li>
|
<li><a href="#kdo-uvidí-můj-profilový-obrázek">Kdo uvidí můj profilový obrázek?</a></li>
|
||||||
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
<li><a href="#what-does-the-green-dot-mean">What does the green dot mean?</a></li>
|
<li><a href="#what-does-the-green-dot-mean">What does the green dot mean?</a></li>
|
||||||
<li><a href="#what-do-the-ticks-shown-beside-outgoing-messages-mean">What do the ticks shown beside outgoing messages mean?</a></li>
|
<li><a href="#what-do-the-ticks-shown-beside-outgoing-messages-mean">What do the ticks shown beside outgoing messages mean?</a></li>
|
||||||
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
||||||
<li><a href="#mediaquality">How is media quality handled?</a></li>
|
|
||||||
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
||||||
<li><a href="#delold">What happens if I turn on “Delete Messages from Device”?</a></li>
|
<li><a href="#delold">What happens if I turn on “Delete Messages from Device”?</a></li>
|
||||||
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
||||||
@@ -29,21 +29,6 @@
|
|||||||
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#channels">Channels</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#subscribe-to-a-channel">Subscribe to a channel</a></li>
|
|
||||||
<li><a href="#create-a-channel">Create a channel</a></li>
|
|
||||||
<li><a href="#how-many-subscribers-can-a-channel-have">How many subscribers can a channel have?</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#calls">Calls</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#place-a-call">Place a call</a></li>
|
|
||||||
<li><a href="#accept-or-reject-a-call">Accept or reject a call</a></li>
|
|
||||||
<li><a href="#during-a-call">During a call</a></li>
|
|
||||||
<li><a href="#missed-calls-and-notifications">Missed calls and notifications</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#webxdc">In-chat apps</a>
|
<li><a href="#webxdc">In-chat apps</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
||||||
@@ -233,6 +218,19 @@ You can also add a little introduction message.</p>
|
|||||||
<p>The second contact will receive a <strong>card</strong> then
|
<p>The second contact will receive a <strong>card</strong> then
|
||||||
and can tap it to start chatting with the first contact.</p>
|
and can tap it to start chatting with the first contact.</p>
|
||||||
|
|
||||||
|
<h3 id="podporuje-delta-chat-obrázky-videa-a-jiné-přílohy">
|
||||||
|
|
||||||
|
|
||||||
|
Podporuje Delta Chat obrázky, videa a jiné přílohy? <a href="#podporuje-delta-chat-obrázky-videa-a-jiné-přílohy" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Yes. Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment-</strong>
|
||||||
|
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons</p>
|
||||||
|
|
||||||
|
<p>For performance, images are optimized and sent at a smaller size by default, but you can send it as a “file” to preserve the original.</p>
|
||||||
|
|
||||||
<h3 id="multiple-accounts">
|
<h3 id="multiple-accounts">
|
||||||
|
|
||||||
|
|
||||||
@@ -414,32 +412,6 @@ Notifications are not sent and there is no time limit.</p>
|
|||||||
<p>Note, that the original message may still be received by chat members
|
<p>Note, that the original message may still be received by chat members
|
||||||
who could have already replied, forwarded, saved, screenshotted or otherwise copied the message.</p>
|
who could have already replied, forwarded, saved, screenshotted or otherwise copied the message.</p>
|
||||||
|
|
||||||
<h3 id="mediaquality">
|
|
||||||
|
|
||||||
|
|
||||||
How is media quality handled? <a href="#mediaquality" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach-</strong>
|
|
||||||
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>By default, compression ensures <strong>fast, efficient delivery</strong> that respects everyone’s data limits and storage.
|
|
||||||
This is ideal for everyday communication.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>In regions with worse connectivity,
|
|
||||||
you can choose higher compression at <strong>Settings → Chats → Outgoing Media Quality</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>If you specifically need to send media in its <strong>original quality</strong>, use <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach → File</strong> in the chat.
|
|
||||||
Please use this method sparingly, as sending original files will significantly increase data usage for you and all recipients in the chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="ephemeralmsgs">
|
<h3 id="ephemeralmsgs">
|
||||||
|
|
||||||
|
|
||||||
@@ -643,197 +615,6 @@ but more than 150 is not recommended.</p>
|
|||||||
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
||||||
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
||||||
|
|
||||||
<h2 id="channels">
|
|
||||||
|
|
||||||
|
|
||||||
Channels <a href="#channels" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Channels are a one-to-many tool for broadcasting messages.</p>
|
|
||||||
|
|
||||||
<h3 id="subscribe-to-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Subscribe to a channel <a href="#subscribe-to-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Scan the <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>QR code</strong>
|
|
||||||
or tap the <strong>invite link</strong> you got from the channel owner.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>That’s all!
|
|
||||||
You will receive a few of the messages from the channel history
|
|
||||||
and, from that point on, all new messages from the channel.</p>
|
|
||||||
|
|
||||||
<p><strong>Don’t worry,</strong> if that does not happen immediately.
|
|
||||||
Once the channel owner comes online, your join request will be processed.</p>
|
|
||||||
|
|
||||||
<p>As all of Delta Chat, also Channels are private and decentralized,
|
|
||||||
there is no public discovery.</p>
|
|
||||||
|
|
||||||
<p>Other channel subscribers will not see that you subscribed and cannot message you.
|
|
||||||
The channel owner, however, can message you.
|
|
||||||
They will also see that you read a message unless you have read receipts disabled.</p>
|
|
||||||
|
|
||||||
<p>If you do not want to share your main profile,
|
|
||||||
you can also create a <a href="#multiple-accounts">dedicated profile</a> for joining a channel.</p>
|
|
||||||
|
|
||||||
<h3 id="create-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Create a channel <a href="#create-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>New Chat</strong> and choose <strong>New Channel</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Enter a <strong>name</strong>, optionally set an <strong>image</strong> and <strong>description</strong>, and hit the <strong>Create</strong> button.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can now send and manage messages as usual.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>From the channel’s profile, <strong>share the QR code or invite link with others</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Subscribers will receive your messages,
|
|
||||||
but they cannot send messages in your channel.
|
|
||||||
When subscribing, they will receive <strong>a few of the latest messages of the channel history</strong>.</p>
|
|
||||||
|
|
||||||
<p>You can see the <strong>view count</strong> beside each message.
|
|
||||||
Note that this only counts subscribers who have read receipts enabled,
|
|
||||||
so the real view count may be larger.</p>
|
|
||||||
|
|
||||||
<h3 id="how-many-subscribers-can-a-channel-have">
|
|
||||||
|
|
||||||
|
|
||||||
How many subscribers can a channel have? <a href="#how-many-subscribers-can-a-channel-have" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Channels are designed for much larger audiences than <a href="#groups">groups</a>.</p>
|
|
||||||
|
|
||||||
<p>The practical limit depends on the used <a href="#relays">relay</a>,
|
|
||||||
so there is no single fixed number that applies everywhere.</p>
|
|
||||||
|
|
||||||
<p>For really large channels with several tens of thousands of subscribers,
|
|
||||||
we recommend using a <a href="#multiple-accounts">dedicated profile</a> for the channel
|
|
||||||
and checking whether the relay is suitable.</p>
|
|
||||||
|
|
||||||
<p>But don’t be too hesitant: Delta Chat is designed to be relay-agnostic,
|
|
||||||
so you can change your relay at any point easily -
|
|
||||||
your existing subscribers will not even notice.
|
|
||||||
You only have to update the invite link you share with new subscribers in that case.</p>
|
|
||||||
|
|
||||||
<h2 id="calls">
|
|
||||||
|
|
||||||
|
|
||||||
Calls <a href="#calls" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Delta Chat supports one-to-one <strong>audio calls</strong> and <strong>video calls</strong>.</p>
|
|
||||||
|
|
||||||
<p>Calls are supported on Desktop, Ubuntu Touch, iOS and Android 8 and newer.</p>
|
|
||||||
|
|
||||||
<h3 id="place-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Place a call <a href="#place-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>In a one-to-one chat, tap the 📞 <strong>call icon</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>This opens a small menu
|
|
||||||
where you can choose whether to place an <strong>Audio Call</strong> or a <strong>Video Call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="accept-or-reject-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Accept or reject a call <a href="#accept-or-reject-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>When someone calls you,
|
|
||||||
Delta Chat shows an <strong>incoming call screen</strong> or notification.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>Accept</strong> to answer
|
|
||||||
or <strong>Decline</strong> to reject the call.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="during-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
During a call <a href="#during-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>mute</strong> your microphone.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>enable or disable your camera</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>On mobile, you can <strong>switch between front and back cameras</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Depending on the device, you can also select the audio output or use picture-in-picture.
|
|
||||||
On desktop, the call is using a dedicated window
|
|
||||||
and you can continue using the main Delta Chat window as usual.</p>
|
|
||||||
|
|
||||||
<h3 id="missed-calls-and-notifications">
|
|
||||||
|
|
||||||
|
|
||||||
Missed calls and notifications <a href="#missed-calls-and-notifications" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>If you do not answer, do not hear the ringing, or do not have your device at hand,
|
|
||||||
the call appears as a <strong>missed call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><strong>Only your accepted contacts</strong> can make your device ring.
|
|
||||||
Contact requests will appear as usual and will not ring.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>At <strong>Settings → Notifications → Calls</strong>,
|
|
||||||
you can disable the special call ringing screen completely.
|
|
||||||
If you do so, you will not be disturbed by any ringing notification,
|
|
||||||
you can still pick up the call by tapping the incoming call message bubble in its chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="webxdc">
|
<h2 id="webxdc">
|
||||||
|
|
||||||
|
|
||||||
@@ -1249,26 +1030,22 @@ Relays are operated by different groups and people.</p>
|
|||||||
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
||||||
so you do not need to care about that.
|
so you do not need to care about that.
|
||||||
However, if you want to,
|
However, if you want to,
|
||||||
you can configure relays at <strong>Settings → Advanced → Relays</strong>:</p>
|
you can configure relays at At <strong>Settings → Advanced → Relays</strong>:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
||||||
<a href="https://chatmail.at/relays">chatmail.at/relays</a> shows some known ones.
|
<a href="https://chatmail.at/relays">https://chatmail.at/relays</a> shows some known ones.
|
||||||
If you have multiple relays, you will receive messages on all of them.
|
If you have multiple relays, you will receive messages on all of them.</p>
|
||||||
Contacts learn your current relays automatically when you message them.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Tap on a relay to set it as <strong>used for sending</strong>.</p>
|
<p>The <strong>default</strong> defines the one where your chat partners send future messages to.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>If you <strong>remove</strong> a relay,
|
<p>If you <strong>remove</strong> a relay,
|
||||||
contacts who only know this relay may not reach you until you message them again.
|
make sure another default relay was used for a sufficient amount of time.
|
||||||
To stay reachable in the meantime, choose <strong>Hide from Contacts</strong> in the confirmation dialog
|
Otherwise, messages from your chat partners won’t reach you.
|
||||||
instead of removing it right away.</p>
|
If in doubt, remove later.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>To <strong>show</strong> a hidden relay again, tap on it.</p>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -1411,10 +1188,6 @@ to exchange encryption setup information through QR-code scanning or “invite l
|
|||||||
<li>
|
<li>
|
||||||
<p><a href="https://autocrypt.org">Autocrypt</a> is used for automatically
|
<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>
|
establishing end-to-end encryption between contacts and all members of a group chat.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
|
||||||
will bring post-quantum resistant encryption and forward secrecy.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<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
|
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Sharing a contact to a
|
||||||
@@ -1599,10 +1372,12 @@ Instead, all group metadata is end-to-end encrypted and stored on end-user devic
|
|||||||
<p>Servers can therefore only see:</p>
|
<p>Servers can therefore only see:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Sender and receiver addresses, randomly generated by default</li>
|
<li>the sender and receiver addresses</li>
|
||||||
<li>Message size</li>
|
<li>and the message size.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>By default, the addresses are randomly generated.</p>
|
||||||
|
|
||||||
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
||||||
|
|
||||||
<h3 id="device-seizure">
|
<h3 id="device-seizure">
|
||||||
@@ -1631,20 +1406,23 @@ can not be identified easily.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>The used <a href="#relays">relays</a> need to know your IP Address,
|
<p>The used <a href="#relays">relay</a> needs to know your IP Address,
|
||||||
as well as sometimes your contact’s devices if you have a <a href="#calls">call</a>
|
as well as sometimes your contact’s devices if you have a <a href="#experiments">call</a>
|
||||||
or use <a href="#webxdc">apps</a> together.</p>
|
or use <a href="#webxdc">apps</a> together.</p>
|
||||||
|
|
||||||
<p>IP Addresses are needed for connectivity and efficiency.
|
<p>IP Addresses are needed for connectivity and efficiency.
|
||||||
Delta Chat neither persists nor exposes them.
|
They are neither persisted nor exposed.
|
||||||
Note that IP Addresses
|
Note that the IP Address
|
||||||
are not like an address you give to a delivery service,
|
is not like a detailed address you give to a delivery service,
|
||||||
but typically less precise, often defining city or region only.</p>
|
but much more coarse, often defining region or country only.</p>
|
||||||
|
|
||||||
<p>If you see your IP Address as a risk,
|
<p>As this is just how the internet and other messengers work by default,
|
||||||
we recommend to use a VPN for the whole system.
|
we do not offer options here or ask upfront questions.</p>
|
||||||
Per-app options leave gaps across your system.
|
|
||||||
For example, tapping a link can expose IP Addresses to unknown parties, which is by far the larger risk.</p>
|
<p>If you see your IP Address as a security or privacy risk,
|
||||||
|
we recommend to use a VPN, in combination with system lockdown mode.
|
||||||
|
Hunting down options in all apps on your system will leave gaps.
|
||||||
|
For example, tapping a link exposes IP Addresses to unknown parties and is the by far larger risk here.</p>
|
||||||
|
|
||||||
<h3 id="sealedsender">
|
<h3 id="sealedsender">
|
||||||
|
|
||||||
@@ -1675,7 +1453,7 @@ but an implementation has not been agreed as a priority yet.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||||
This means that if your private decryption key is leaked,
|
This means that if your private decryption key is leaked,
|
||||||
@@ -1686,9 +1464,12 @@ Otherwise, someone obtaining your decryption keys
|
|||||||
is typically also able to get all your non-deleted messages
|
is typically also able to get all your non-deleted messages
|
||||||
and doesn’t even need to decrypt any previously collected messages.</p>
|
and doesn’t even need to decrypt any previously collected messages.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>We designed a Forward Secrecy approach that withstood
|
||||||
will provide reliable deletion (forward secrecy) through automatic key rotation.
|
initial examination from some cryptographers and implementation experts
|
||||||
This approach is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
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>
|
||||||
|
|
||||||
<h3 id="pqc">
|
<h3 id="pqc">
|
||||||
|
|
||||||
@@ -1698,13 +1479,12 @@ This approach is specified in the <a href="https://datatracker.ietf.org/doc/draf
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||||
will bring post-quantum resistant encryption to protect against quantum computer attacks.
|
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
||||||
Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</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
|
||||||
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
in collaboration with other OpenPGP implementers.</p>
|
||||||
The implementation is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
|
||||||
|
|
||||||
<h3 id="how-can-i-manually-check-encryption-information">
|
<h3 id="how-can-i-manually-check-encryption-information">
|
||||||
|
|
||||||
@@ -1781,7 +1561,7 @@ See <a href="https://delta.chat/en/2023-05-22-webxdc-security">here for the full
|
|||||||
<li>
|
<li>
|
||||||
<p>2023 March, <a href="https://cure53.de">Cure53</a> analyzed both the transport encryption of
|
<p>2023 March, <a href="https://cure53.de">Cure53</a> analyzed both the transport encryption of
|
||||||
Delta Chat’s network connections and a reproducible mail server setup as
|
Delta Chat’s network connections and a reproducible mail server setup as
|
||||||
<a href="https://delta.chat/serverguide">recommended on this site</a>.
|
<a href="https://delta.chat/cs/serverguide">recommended on this site</a>.
|
||||||
You can read more about the audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">on our blog</a>
|
You can read more about the audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">on our blog</a>
|
||||||
or read the <a href="https://delta.chat/assets/blog/MER-01-report.pdf">full report here</a>.</p>
|
or read the <a href="https://delta.chat/assets/blog/MER-01-report.pdf">full report here</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
+129
-330
@@ -5,6 +5,7 @@
|
|||||||
<li><a href="#howtoe2ee">Wie finde ich Leute, mit denen ich chatten kann?</a></li>
|
<li><a href="#howtoe2ee">Wie finde ich Leute, mit denen ich chatten kann?</a></li>
|
||||||
<li><a href="#warum-ist-ein-chat-als-anfrage-markiert">Warum ist ein Chat als “Anfrage” markiert?</a></li>
|
<li><a href="#warum-ist-ein-chat-als-anfrage-markiert">Warum ist ein Chat als “Anfrage” markiert?</a></li>
|
||||||
<li><a href="#wie-kann-ich-zwei-meiner-freunde-miteinander-in-kontakt-bringen">Wie kann ich zwei meiner Freunde miteinander in Kontakt bringen?</a></li>
|
<li><a href="#wie-kann-ich-zwei-meiner-freunde-miteinander-in-kontakt-bringen">Wie kann ich zwei meiner Freunde miteinander in Kontakt bringen?</a></li>
|
||||||
|
<li><a href="#unterstützt-delta-chat-bilder-videos-und-dateianhänge">Unterstützt Delta Chat Bilder, Videos und Dateianhänge?</a></li>
|
||||||
<li><a href="#multiple-accounts">Was sind Profile? Wie kann ich zwischen ihnen wechseln?</a></li>
|
<li><a href="#multiple-accounts">Was sind Profile? Wie kann ich zwischen ihnen wechseln?</a></li>
|
||||||
<li><a href="#wer-sieht-mein-profilbild">Wer sieht mein Profilbild?</a></li>
|
<li><a href="#wer-sieht-mein-profilbild">Wer sieht mein Profilbild?</a></li>
|
||||||
<li><a href="#signature">Kann ich einen Status festlegen?</a></li>
|
<li><a href="#signature">Kann ich einen Status festlegen?</a></li>
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
<li><a href="#was-bedeutet-der-grüne-punkt">Was bedeutet der grüne Punkt?</a></li>
|
<li><a href="#was-bedeutet-der-grüne-punkt">Was bedeutet der grüne Punkt?</a></li>
|
||||||
<li><a href="#was-bedeuten-die-häkchen-neben-den-ausgehenden-nachrichten">Was bedeuten die Häkchen neben den ausgehenden Nachrichten?</a></li>
|
<li><a href="#was-bedeuten-die-häkchen-neben-den-ausgehenden-nachrichten">Was bedeuten die Häkchen neben den ausgehenden Nachrichten?</a></li>
|
||||||
<li><a href="#edit">Schreibfehler korrigieren und Nachrichten nach dem Senden löschen</a></li>
|
<li><a href="#edit">Schreibfehler korrigieren und Nachrichten nach dem Senden löschen</a></li>
|
||||||
<li><a href="#mediaquality">Medienqualität und Datenverbrauch</a></li>
|
|
||||||
<li><a href="#ephemeralmsgs">Wie funktionieren “Verschwindende Nachrichten”?</a></li>
|
<li><a href="#ephemeralmsgs">Wie funktionieren “Verschwindende Nachrichten”?</a></li>
|
||||||
<li><a href="#delold">Was passiert, wenn ich “Nachrichten vom Gerät löschen” aktiviere?</a></li>
|
<li><a href="#delold">Was passiert, wenn ich “Nachrichten vom Gerät löschen” aktiviere?</a></li>
|
||||||
<li><a href="#remove-account">Wie kann ich mein Chat-Profil löschen?</a></li>
|
<li><a href="#remove-account">Wie kann ich mein Chat-Profil löschen?</a></li>
|
||||||
@@ -29,21 +29,6 @@
|
|||||||
<li><a href="#wie-viele-mitglieder-können-in-einer-einzelnen-gruppe-sein">Wie viele Mitglieder können in einer einzelnen Gruppe sein?</a></li>
|
<li><a href="#wie-viele-mitglieder-können-in-einer-einzelnen-gruppe-sein">Wie viele Mitglieder können in einer einzelnen Gruppe sein?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#channels">Kanäle</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#einem-kanal-beitreten">Einem Kanal beitreten</a></li>
|
|
||||||
<li><a href="#einen-kanal-erstellen">Einen Kanal erstellen</a></li>
|
|
||||||
<li><a href="#wie-viele-empfänger-kann-ein-kanal-haben">Wie viele Empfänger kann ein Kanal haben?</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#calls">Anrufe</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#jemanden-anrufen">Jemanden anrufen</a></li>
|
|
||||||
<li><a href="#einen-anruf-annehmen-oder-ablehnen">Einen Anruf annehmen oder ablehnen</a></li>
|
|
||||||
<li><a href="#während-des-anrufs">Während des Anrufs</a></li>
|
|
||||||
<li><a href="#verpasste-anrufe-und-benachrichtigungen">Verpasste Anrufe und Benachrichtigungen</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#webxdc">In-Chat-Apps</a>
|
<li><a href="#webxdc">In-Chat-Apps</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#wo-bekomme-ich-in-chat-apps">Wo bekomme ich In-Chat-Apps?</a></li>
|
<li><a href="#wo-bekomme-ich-in-chat-apps">Wo bekomme ich In-Chat-Apps?</a></li>
|
||||||
@@ -124,7 +109,7 @@
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Einfache Erstellung von <strong>privaten Chat-Profilen</strong> mit sicheren, schnellen und interoperablen <a href="https://chatmail.at/relays">Chatmail-Servern</a>,
|
<p>Einfache Erstellung von <strong>privaten Chat-Profile</strong> mit sicheren, schnellen und interoperablen <a href="https://chatmail.at/relays">Chatmail-Servern</a>,
|
||||||
die sofortige Push-Benachrichtigungen für iOS- und Android-Geräte bieten.</p>
|
die sofortige Push-Benachrichtigungen für iOS- und Android-Geräte bieten.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@@ -152,17 +137,17 @@ basierend auf <a href="https://github.com/chatmail/core/blob/main/standards.md#s
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Beachte zunächst, dass Delta Chat ein privater Messenger ist.
|
<p>Beachte zunächst, dass Delta Chat ein privater Messenger ist.
|
||||||
Es gibt kein öffentliches Verzeichnis, du entscheidest selbst über deine Kontakte.</p>
|
Es gibt keine öffentliches Verzeichnis, du entscheiden selbst über deine Kontakte.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Wenn du <strong>persönlich</strong> mit deinen Freunden oder Familie zusammen bist,
|
<p>Wenn du <strong>persönlich</strong> mit deinen Freunden oder Familie zusammen bist,
|
||||||
tippe auf das <strong>QR-Code</strong>-Symbol <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" />
|
tippe auf das <strong>QR-Code</strong>-Symbol <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" />
|
||||||
auf dem Hauptbildschirm.<br />
|
auf dem Hauptbildschirm.<br />
|
||||||
Bitte dann deinen Chatpartner den QR-Code mit Delta Chat zu <strong>scannen</strong>.</p>
|
Bitte deinen Chatpartner den QR-Code mit Delta Chat zu <strong>scannen</strong>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Für eine Kontaktaufnahme <strong>aus der Ferne</strong> klicke im selben Bildschirm auf “Kopieren” oder “Teilen” und sende den <strong>Einladungslink</strong> über einen anderen privaten Chat.</p>
|
<p>Für eine Kontaktaufnahme <strong>aus der Ferne</strong>, klicke im selben Bildschirm auf “Kopieren” oder “Teilen” und sende den <strong>Einladungslink</strong> über einen anderen privaten Chat.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -192,7 +177,7 @@ wird eine Ende-zu-Ende-Verschlüsselung zwischen allen Mitgliedern eingerichtet.
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Da Delta Chat ein privater Messenger ist, können dir zunächst nur Freunde und Familienmitglieder schreiben, denen du deinen <a href="#howtoe2ee">QR-Code oder Einladungslink</a> schickst.</p>
|
<p>Da Delta Chat ein privater Messenger ist, können dir zunächst nur Freunde und Familienmitglieder, denen du deinen <a href="#howtoe2ee">QR-Code oder Einladungslink</a> schickst, schreiben.</p>
|
||||||
|
|
||||||
<p>Deine Freunde können deine Kontaktdaten dann mit anderen Freunden teilen. Dies wird als <b style="border: 1px solid currentColor; padding: 0 3px; font-size:90%">Anfrage</b> angezeigt.</p>
|
<p>Deine Freunde können deine Kontaktdaten dann mit anderen Freunden teilen. Dies wird als <b style="border: 1px solid currentColor; padding: 0 3px; font-size:90%">Anfrage</b> angezeigt.</p>
|
||||||
|
|
||||||
@@ -201,12 +186,12 @@ wird eine Ende-zu-Ende-Verschlüsselung zwischen allen Mitgliedern eingerichtet.
|
|||||||
<p>Du musst die Anfrage <strong>akzeptieren</strong>, bevor du antworten kannst.</p>
|
<p>Du musst die Anfrage <strong>akzeptieren</strong>, bevor du antworten kannst.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Du kannst sie auch “löschen”, wenn du vorerst nicht mit dieser Person chatten möchtest.</p>
|
<p>Du kannst sie auch “löschen”, wenn du vorerst nicht mit ihm chatten möchten.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Wenn du eine Anfrage löschst, werden zukünftige Nachrichten von diesem Kontakt weiterhin
|
<p>If you delete a request, future messages from that contact will still appear
|
||||||
als Nachrichtenanfrage angezeigt, sodass du deine Meinung ändern kannst. Wenn du wirklich keine
|
as message request, so you can change your mind. If you really don’t want to
|
||||||
Nachrichten von dieser Person erhalten möchtest, solltest du sie <strong>blockieren</strong>.</p>
|
receive messages from this person, consider <strong>blocking</strong> them.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -224,6 +209,19 @@ Du kannst auch eine kurze Nachricht hinzufügen.</p>
|
|||||||
<p>Der zweite Kontakt erhält dann die <strong>Kontaktdaten</strong> und
|
<p>Der zweite Kontakt erhält dann die <strong>Kontaktdaten</strong> und
|
||||||
kann darauf tippen, um mit dem ersten Kontakt zu chatten.</p>
|
kann darauf tippen, um mit dem ersten Kontakt zu chatten.</p>
|
||||||
|
|
||||||
|
<h3 id="unterstützt-delta-chat-bilder-videos-und-dateianhänge">
|
||||||
|
|
||||||
|
|
||||||
|
Unterstützt Delta Chat Bilder, Videos und Dateianhänge? <a href="#unterstützt-delta-chat-bilder-videos-und-dateianhänge" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Ja. Bilder, Videos, Dateien, Sprachnachrichten und mehr können über die <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Anhang-</strong>
|
||||||
|
bzw. <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Sprachnachricht</strong>-Buttons hinzugefügt werden</p>
|
||||||
|
|
||||||
|
<p>Um die Leistung zu verbessern, werden die Bilder standardmäßig optimiert und in einer kleineren Größe gesendet, aber du kannst sie auch als “Datei” senden, um das Original zu erhalten.</p>
|
||||||
|
|
||||||
<h3 id="multiple-accounts">
|
<h3 id="multiple-accounts">
|
||||||
|
|
||||||
|
|
||||||
@@ -243,7 +241,7 @@ oder <strong>Profile zu wechseln</strong>.</p>
|
|||||||
|
|
||||||
<p>Du kannst separate Profile für politische, familiäre oder berufliche Aktivitäten verwenden.</p>
|
<p>Du kannst separate Profile für politische, familiäre oder berufliche Aktivitäten verwenden.</p>
|
||||||
|
|
||||||
<p>Vielleicht möchtest du auch erfahren, wie du <a href="#multiclient">Profile auf mehreren Geräten verwenden kannst</a>.</p>
|
<p>Vielleicht möchtest due auch erfahren, wie du <a href="#multiclient">Profile auf mehreren Geräten verwenden kannst</a>.</p>
|
||||||
|
|
||||||
<h3 id="wer-sieht-mein-profilbild">
|
<h3 id="wer-sieht-mein-profilbild">
|
||||||
|
|
||||||
@@ -281,7 +279,7 @@ Sobald du eine Nachricht an einen Kontakt sendest, kann dieser deine Signatur in
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p><strong>Angeheftete Chats</strong> bleiben immer ganz oben in der Chatliste. So kannst du schnell auf deine Lieblingschats zugreifen oder du verwendest vorübergehend angeheftete Chats, um Dinge nicht zu vergessen.</p>
|
<p><strong>Angeheftete Chats</strong> bleiben immer ganz oben in der Chatliste. So kannst du schnell auf deine Lieblingschats zugreifen oder du verwendest vorübergehend angeheftete Chats um Dinge nicht zu vergessen.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><strong>Stummgeschaltete Chats</strong> erhalten keine Benachrichtigungen, bleiben ansonsten aber an ihrem Platz. Du kannst auch stummgeschaltete Chats anheften.</p>
|
<p><strong>Stummgeschaltete Chats</strong> erhalten keine Benachrichtigungen, bleiben ansonsten aber an ihrem Platz. Du kannst auch stummgeschaltete Chats anheften.</p>
|
||||||
@@ -294,7 +292,7 @@ Sobald du eine Nachricht an einen Kontakt sendest, kann dieser deine Signatur in
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Um die Funktionen zu nutzen, tippe lang auf einen Chat in der Chatliste oder klicke den Chat mit der rechten Maustaste an.</p>
|
<p>Um die Funktionen zu nutzen, lang auf einen Chat in der Chatliste tippen oder den Chat mit der rechten Maustaste anklicken.</p>
|
||||||
|
|
||||||
<h3 id="save">
|
<h3 id="save">
|
||||||
|
|
||||||
@@ -304,11 +302,11 @@ Sobald du eine Nachricht an einen Kontakt sendest, kann dieser deine Signatur in
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p><strong>Gespeicherte Nachrichten</strong> ist ein Chat, den du verwenden kannst, um dir Nachrichten zu merken und sie wiederzufinden.</p>
|
<p><strong>Gespeicherte Nachrichten</strong> ist ein Chat, den du verwenden kannst, um dir Nachrichten zu merken und wiederzufinden.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Tippe im Chat lange auf eine Nachricht oder klicke mit der rechten Maustaste darauf und wähle <strong>Speichern</strong>.</p>
|
<p>Tippen in einem beliebigen Chat lange auf eine Nachricht oder klicken mit der rechten Maustaste darauf und wähle <strong>Speichern</strong>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Gespeicherte Nachrichten werden mit dem Symbol
|
<p>Gespeicherte Nachrichten werden mit dem Symbol
|
||||||
@@ -321,7 +319,7 @@ Durch Tippen auf <img style="vertical-align:middle; width:1.2em; margin:1px" src
|
|||||||
kannst du zu der ursprünglichen Nachricht im ursprünglichen Chat zurückkehren</p>
|
kannst du zu der ursprünglichen Nachricht im ursprünglichen Chat zurückkehren</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Schließlich kannst du auch „Gespeicherte Nachrichten“ verwenden, um <strong>persönliche Notizen</strong> zu machen. Öffne den Chat, gib etwas ein, fügen ein Foto oder eine Sprachnachricht hinzu usw.</p>
|
<p>Schließlich kannst du auch „Gespeicherte Nachrichten“ verwenden, um <strong>persönliche Notizen</strong> zu machen - öffnen den Chat, gib etwas ein, fügen ein Foto oder eine Sprachnachricht hinzu usw.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Da „Gespeicherte Nachrichten“ synchronisiert werden, können sie sehr praktisch für die Übertragung von Daten zwischen Geräten sein</p>
|
<p>Da „Gespeicherte Nachrichten“ synchronisiert werden, können sie sehr praktisch für die Übertragung von Daten zwischen Geräten sein</p>
|
||||||
@@ -362,7 +360,7 @@ sei es durch den <a href="#edit">Absender</a>, durch <a href="#delold">Automatis
|
|||||||
|
|
||||||
<p>In <a href="#groups">Gruppen</a> bedeutet das zweite Häkchen, dass die Nachricht von mindestens einem Mitglied gelesen wurde.</p>
|
<p>In <a href="#groups">Gruppen</a> bedeutet das zweite Häkchen, dass die Nachricht von mindestens einem Mitglied gelesen wurde.</p>
|
||||||
|
|
||||||
<p>Du erhältst nur dann das zweite Häkchen, wenn sowohl du als auch einer der Empfänger, die die Nachricht gelesen haben, <strong>Einstellungen → Chats → Lesebestätigungen</strong> aktiviert haben.</p>
|
<p>Du erhälst nur dann das zweite Häkchen, wenn sowohl du als auch einer der Empfänger, die die Nachricht gelesen haben, <strong>Einstellungen → Chats → Lesebestätigungen</strong> aktiviert haben.</p>
|
||||||
|
|
||||||
<h3 id="edit">
|
<h3 id="edit">
|
||||||
|
|
||||||
@@ -390,31 +388,6 @@ Es werden keine Benachrichtigungen verschickt und es gibt kein Zeitlimit.</p>
|
|||||||
<p>Beachten, dass die ursprüngliche Nachricht dennoch von Chatteilnehmern empfangen worden sein könnte,
|
<p>Beachten, dass die ursprüngliche Nachricht dennoch von Chatteilnehmern empfangen worden sein könnte,
|
||||||
die die Nachricht bereits beantwortet, weitergeleitet, gespeichert, mit einem Screenshot versehen oder anderweitig kopiert haben könnten.</p>
|
die die Nachricht bereits beantwortet, weitergeleitet, gespeichert, mit einem Screenshot versehen oder anderweitig kopiert haben könnten.</p>
|
||||||
|
|
||||||
<h3 id="mediaquality">
|
|
||||||
|
|
||||||
|
|
||||||
Medienqualität und Datenverbrauch <a href="#mediaquality" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Bilder, Videos, Dateien, Sprachnachrichten und mehr können über die <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Anhang-</strong>
|
|
||||||
bzw. <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Sprachnachricht</strong>-Buttons hinzugefügt werden.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Standardmäßig sorgt Komprimierung für eine <strong>schnelle, effiziente Übertragung</strong>, die die Datenlimits und Speicherplatzkapazitäten aller Beteiligten berücksichtigt.
|
|
||||||
Dies ist ideal für die tägliche Kommunikation.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>In Regionen mit schlechter Verbindung können Sie unter <strong>Einstellungen → Chats → Medienqualität beim Senden</strong> eine höhere Komprimierung wählen.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Wenn Sie Medien ausdrücklich in ihrer <strong>Originalqualität</strong> senden müssen, verwende im Chat die Option <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Anhängen → Datei</strong>.
|
|
||||||
Verwende diese Methode nur sparsam, da das Senden von Originaldateien den Datenverbrauch für dich und alle Empfänger im Chat erheblich erhöht.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="ephemeralmsgs">
|
<h3 id="ephemeralmsgs">
|
||||||
|
|
||||||
|
|
||||||
@@ -530,7 +503,7 @@ und seine <a href="#edit">eigenen Nachrichten von Geräten der Mitglieder lösch
|
|||||||
<p>Wenn das Mitglied noch nicht in deiner Kontaktliste ist, sie sich aber <strong>persönlich</strong> treffen, wählen Sie dort <strong>QR-Einladungscode</strong> an. Dein Chat-Partner kann nun den QR-Code mit seiner Delta Chat-App <strong>scannen</strong> indem er auf <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> auf dem Hauptbildschirm tippt.</p>
|
<p>Wenn das Mitglied noch nicht in deiner Kontaktliste ist, sie sich aber <strong>persönlich</strong> treffen, wählen Sie dort <strong>QR-Einladungscode</strong> an. Dein Chat-Partner kann nun den QR-Code mit seiner Delta Chat-App <strong>scannen</strong> indem er auf <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> auf dem Hauptbildschirm tippt.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Für eine Kontaktaufnahme <strong>aus der Ferne</strong> tippe dort “Kopieren” oder “Teilen” und sende den Einladungslink über einen anderen privaten Chat zum neuen Mitglied.</p>
|
<p>Für eine Kontaktaufnahme <strong>aus der Ferne</strong>, tippe dort “Kopieren” oder “Teilen” und sende den Einladungslink über einen anderen privaten Chat zum neuen Mitglied.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -560,7 +533,7 @@ Kein Problem, bitte einfach ein anderes Gruppenmitglied in einem normalen Chat,
|
|||||||
Wenn du der Gruppe später erneut beitreten möchtest, bitten ein anderes Gruppenmitglied, dich hinzuzufügen.</li>
|
Wenn du der Gruppe später erneut beitreten möchtest, bitten ein anderes Gruppenmitglied, dich hinzuzufügen.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Alternativ kannst du eine Gruppe auch “stummschalten” - dies bedeutet, dass du weiterhin alle Nachrichten erhältst und neue schreiben kannst, aber nicht mehr über neue Nachrichten informiert wirst.</p>
|
<p>Alternativ kannst du eine Gruppe auch “stummschalten” - dies bedeutet, dass du weiterhin alle Nachrichten erhälst und neue schreiben kannst, aber nicht mehr über neue Nachrichten informiert wirst.</p>
|
||||||
|
|
||||||
<h3 id="eine-gruppe-klonen">
|
<h3 id="eine-gruppe-klonen">
|
||||||
|
|
||||||
@@ -599,197 +572,6 @@ aber mehr als 150 sind nicht empfohlen.</p>
|
|||||||
|
|
||||||
<p>Wenn Gruppen größer werden, können sie sozial instabil werden und benötigen möglicherweise eine Hierarchie - und Delta Chat ist ein privater Messenger für Chats mit <a href="#groups">gleichen Rechten</a>. Vgl. <a href="https://de.wikipedia.org/wiki/Dunbar-Zahl">Dunbar-Zahl</a>.</p>
|
<p>Wenn Gruppen größer werden, können sie sozial instabil werden und benötigen möglicherweise eine Hierarchie - und Delta Chat ist ein privater Messenger für Chats mit <a href="#groups">gleichen Rechten</a>. Vgl. <a href="https://de.wikipedia.org/wiki/Dunbar-Zahl">Dunbar-Zahl</a>.</p>
|
||||||
|
|
||||||
<h2 id="channels">
|
|
||||||
|
|
||||||
|
|
||||||
Kanäle <a href="#channels" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Kanäle dienen der Verbreitung von Nachrichten an viele Empfänger.</p>
|
|
||||||
|
|
||||||
<h3 id="einem-kanal-beitreten">
|
|
||||||
|
|
||||||
|
|
||||||
Einem Kanal beitreten <a href="#einem-kanal-beitreten" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Scan the <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>QR code</strong>
|
|
||||||
or tap the <strong>invite link</strong> you got from the channel owner.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>That’s all!
|
|
||||||
You will receive a few of the messages from the channel history
|
|
||||||
and, from that point on, all new messages from the channel.</p>
|
|
||||||
|
|
||||||
<p><strong>Don’t worry,</strong> if that does not happen immediately.
|
|
||||||
Once the channel owner comes online, your join request will be processed.</p>
|
|
||||||
|
|
||||||
<p>As all of Delta Chat, also Channels are private and decentralized,
|
|
||||||
there is no public discovery.</p>
|
|
||||||
|
|
||||||
<p>Other channel subscribers will not see that you subscribed and cannot message you.
|
|
||||||
The channel owner, however, can message you.
|
|
||||||
They will also see that you read a message unless you have read receipts disabled.</p>
|
|
||||||
|
|
||||||
<p>If you do not want to share your main profile,
|
|
||||||
you can also create a <a href="#multiple-accounts">dedicated profile</a> for joining a channel.</p>
|
|
||||||
|
|
||||||
<h3 id="einen-kanal-erstellen">
|
|
||||||
|
|
||||||
|
|
||||||
Einen Kanal erstellen <a href="#einen-kanal-erstellen" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>New Chat</strong> and choose <strong>New Channel</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Enter a <strong>name</strong>, optionally set an <strong>image</strong> and <strong>description</strong>, and hit the <strong>Create</strong> button.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can now send and manage messages as usual.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>From the channel’s profile, <strong>share the QR code or invite link with others</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Subscribers will receive your messages,
|
|
||||||
but they cannot send messages in your channel.
|
|
||||||
When subscribing, they will receive <strong>a few of the latest messages of the channel history</strong>.</p>
|
|
||||||
|
|
||||||
<p>You can see the <strong>view count</strong> beside each message.
|
|
||||||
Note that this only counts subscribers who have read receipts enabled,
|
|
||||||
so the real view count may be larger.</p>
|
|
||||||
|
|
||||||
<h3 id="wie-viele-empfänger-kann-ein-kanal-haben">
|
|
||||||
|
|
||||||
|
|
||||||
Wie viele Empfänger kann ein Kanal haben? <a href="#wie-viele-empfänger-kann-ein-kanal-haben" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Channels are designed for much larger audiences than <a href="#groups">groups</a>.</p>
|
|
||||||
|
|
||||||
<p>The practical limit depends on the used <a href="#relays">relay</a>,
|
|
||||||
so there is no single fixed number that applies everywhere.</p>
|
|
||||||
|
|
||||||
<p>For really large channels with several tens of thousands of subscribers,
|
|
||||||
we recommend using a <a href="#multiple-accounts">dedicated profile</a> for the channel
|
|
||||||
and checking whether the relay is suitable.</p>
|
|
||||||
|
|
||||||
<p>But don’t be too hesitant: Delta Chat is designed to be relay-agnostic,
|
|
||||||
so you can change your relay at any point easily -
|
|
||||||
your existing subscribers will not even notice.
|
|
||||||
You only have to update the invite link you share with new subscribers in that case.</p>
|
|
||||||
|
|
||||||
<h2 id="calls">
|
|
||||||
|
|
||||||
|
|
||||||
Anrufe <a href="#calls" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Delta Chat supports one-to-one <strong>audio calls</strong> and <strong>video calls</strong>.</p>
|
|
||||||
|
|
||||||
<p>Calls are supported on Desktop, Ubuntu Touch, iOS and Android 8 and newer.</p>
|
|
||||||
|
|
||||||
<h3 id="jemanden-anrufen">
|
|
||||||
|
|
||||||
|
|
||||||
Jemanden anrufen <a href="#jemanden-anrufen" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>In a one-to-one chat, tap the 📞 <strong>call icon</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>This opens a small menu
|
|
||||||
where you can choose whether to place an <strong>Audio Call</strong> or a <strong>Video Call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="einen-anruf-annehmen-oder-ablehnen">
|
|
||||||
|
|
||||||
|
|
||||||
Einen Anruf annehmen oder ablehnen <a href="#einen-anruf-annehmen-oder-ablehnen" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>When someone calls you,
|
|
||||||
Delta Chat shows an <strong>incoming call screen</strong> or notification.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>Accept</strong> to answer
|
|
||||||
or <strong>Decline</strong> to reject the call.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="während-des-anrufs">
|
|
||||||
|
|
||||||
|
|
||||||
Während des Anrufs <a href="#während-des-anrufs" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>mute</strong> your microphone.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>enable or disable your camera</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>On mobile, you can <strong>switch between front and back cameras</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Depending on the device, you can also select the audio output or use picture-in-picture.
|
|
||||||
On desktop, the call is using a dedicated window
|
|
||||||
and you can continue using the main Delta Chat window as usual.</p>
|
|
||||||
|
|
||||||
<h3 id="verpasste-anrufe-und-benachrichtigungen">
|
|
||||||
|
|
||||||
|
|
||||||
Verpasste Anrufe und Benachrichtigungen <a href="#verpasste-anrufe-und-benachrichtigungen" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>If you do not answer, do not hear the ringing, or do not have your device at hand,
|
|
||||||
the call appears as a <strong>missed call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><strong>Only your accepted contacts</strong> can make your device ring.
|
|
||||||
Contact requests will appear as usual and will not ring.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>At <strong>Settings → Notifications → Calls</strong>,
|
|
||||||
you can disable the special call ringing screen completely.
|
|
||||||
If you do so, you will not be disturbed by any ringing notification,
|
|
||||||
you can still pick up the call by tapping the incoming call message bubble in its chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="webxdc">
|
<h2 id="webxdc">
|
||||||
|
|
||||||
|
|
||||||
@@ -1176,16 +958,18 @@ kannst du jedoch unter <strong>Einstellungen → Erweitert → Relays</strong>
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Du kannst ein Relay <strong>hinzufügen</strong>, indem du einen QR-Code scannst, z.B. von <a href="https://chatmail.at/relays">chatmail.at/relays</a>. Bei mehreren Relays, empfängst du die Nachrichten von allen Relays. Deine Kontakte lernen deine Relays automatisch, sobald du ihnen schreibst.</p>
|
<p>Du kannst ein Relay <strong>hinzufügen</strong>, indem du einen QR-Code scannst,
|
||||||
|
z.B. von <a href="https://chatmail.at/relays">https://chatmail.at/relays</a>.
|
||||||
|
Bei mehreren Relays, empfängst du die Nachrichten von allen Relays.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Tippe ein Relay an, um es <strong>Zum Senden zu verwenden</strong></p>
|
<p><strong>Standard</strong> legt das Relay fest, an das deine Chatpartner zukünftig Nachrichten senden.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Wenn du ein Relay <strong>entfernst</strong>, können Kontakte, die nur dieses Relay kennen, dich nicht erreichen, bis du ihnen wieder schreibst. Um erreichbar zu bleiben, wähle <strong>Vor Kontakten verstecken</strong> im Bestätigungsdialog anstelle das Relay direkt zu löschen.</p>
|
<p>Wenn du ein Relay <strong>entfernst</strong>,
|
||||||
</li>
|
stelle sicher, dass ein anderes Standard-Relay ausreichend lange verwendet wurde.
|
||||||
<li>
|
Andernfalls erreichen dich keine Nachrichten von deinen Kontakten.
|
||||||
<p>Um ein verstecktes Relay wieder <strong>anzuzeigen</strong> tippe es an.</p>
|
Im Zweifelsfall entferne das Relay später.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -1261,31 +1045,31 @@ für die <a href="https://chatmail.at/clients">Chatmail-Clients</a> umfasst, von
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Wir möchten Delta Chat mit deiner Hilfe verbessern.
|
<p>We would like to improve Delta Chat with your help,
|
||||||
Deshalb fragt Delta Chat für Android, ob du
|
which is why Delta Chat for Android asks whether you want
|
||||||
anonyme Nutzungsstatistiken senden möchtest.</p>
|
to send anonymous usage statistics.</p>
|
||||||
|
|
||||||
<p>Du kannst dies unter
|
<p>You can turn it on and off at
|
||||||
<strong>Einstellungen → Erweitert → Statistik an Delta Chat Entwickler senden</strong> ein- und ausschalten.</p>
|
<strong>Settings → Advanced → Send statistics to Delta Chat’s developers</strong>.</p>
|
||||||
|
|
||||||
<p>Wenn eingeschaltet,
|
<p>When you turn it on,
|
||||||
werden wöchentlich Statistiken automatisch an einen Bot gesendet.</p>
|
weekly statistics will be automatically sent to a bot.</p>
|
||||||
|
|
||||||
<p>Wir sind beispielsweise an folgenden Statistiken interessiert:</p>
|
<p>We are interested e.g. in statistics like:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Wie viele Kontakte werden durch das persönliche Scannen eines QR-Codes hergestellt?</p>
|
<p>How many contacts are introduced by personally scanning a QR code?</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Welche Versionen von Delta Chat werden verwendet?</p>
|
<p>Which versions of Delta Chat are being used?</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Welche Fehler treten bei Benutzern auf?</p>
|
<p>What errors occur for users?</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Wir werden <em>keinerlei</em> personenbezogene Daten über dich sammeln.</p>
|
<p>We will <em>not</em> collect any personally identifiable information about you.</p>
|
||||||
|
|
||||||
<h3 id="ich-bin-an-technischen-details-interessiert-gibt-es-hierzu-weitere-infos">
|
<h3 id="ich-bin-an-technischen-details-interessiert-gibt-es-hierzu-weitere-infos">
|
||||||
|
|
||||||
@@ -1323,10 +1107,6 @@ zum Austausch von Verschlüsselungsinformationen durch Scannen von QR-Codes oder
|
|||||||
<li>
|
<li>
|
||||||
<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>
|
<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>
|
||||||
<li>
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, dessen vollständige Implementierung für 2026 geplant ist,
|
|
||||||
wir post-quantum-resistente Verschlüsselung und Forward Secrecy einführen.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Teilen eines Kontakts im Chat</a>
|
<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>
|
ermöglicht es den Empfängern, eine Ende-zu-Ende-Verschlüsselung mit dem Kontakt zu verwenden.</p>
|
||||||
@@ -1500,13 +1280,15 @@ selbst wenn die Nachricht nicht Ende-zu-Ende-verschlüsselt war.</p>
|
|||||||
speichern Delta-Chat-Apps keine Metadaten über Kontakte oder Gruppen auf Servern. Auch nicht in verschlüsselter Form.
|
speichern Delta-Chat-Apps keine Metadaten über Kontakte oder Gruppen auf Servern. Auch nicht in verschlüsselter Form.
|
||||||
Stattdessen werden alle Gruppen-Metadaten durchgängig verschlüsselt und ausschließlich auf den Endgeräten der Nutzer gespeichert.</p>
|
Stattdessen werden alle Gruppen-Metadaten durchgängig verschlüsselt und ausschließlich auf den Endgeräten der Nutzer gespeichert.</p>
|
||||||
|
|
||||||
<p>Server können daher nur das folgende sehen:</p>
|
<p>Servers can therefore only see:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Absender- und Empfängeradressen, standardmäßig zufällig generiert</li>
|
<li>the sender and receiver addresses</li>
|
||||||
<li>Größe der Nachricht</li>
|
<li>and the message size.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>By default, the addresses are randomly generated.</p>
|
||||||
|
|
||||||
<p>Alle anderen Metadaten zu Nachrichten, Kontakten und Gruppen befinden sich im Ende-zu-Ende-verschlüsselten Teil der Nachrichten.</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">
|
<h3 id="device-seizure">
|
||||||
@@ -1517,15 +1299,15 @@ Stattdessen werden alle Gruppen-Metadaten durchgängig verschlüsselt und aussch
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Sowohl zum Schutz vor Servern, die Metadaten sammeln,
|
<p>Both for protecting against metadata-collecting servers
|
||||||
als auch als Schutz bei Beschlagnahmung von Geräten
|
as well as against the threat of device seizure
|
||||||
empfehlen wir die Verwendung eines <a href="https://chatmail.at/relays">Chatmail-Relays</a>,
|
we recommend to use a <a href="https://chatmail.at/relays">chatmail relay</a>
|
||||||
um Chat-Profile mit zufälligen Adressen für den Transport zu erstellen.
|
to create chat profiles using random addresses for transport.
|
||||||
Beachte, dass Delta-Chat-Apps mehrere Profile unterstützen,
|
Note that Delta Chat apps on all platforms support multiple profiles
|
||||||
sodass du neben deinem „Hauptprofil” ganz einfach situationsspezifische Profile verwenden kannst,
|
so you can easily use situation-specific profiles next to your “main” profile
|
||||||
mit der Gewissheit, dass alle Daten sowie alle Metadaten gelöscht werden.
|
with the knowledge that all their data, along with all metadata, will be deleted.
|
||||||
Darüber hinaus können Chat-Kontakte, die kurzlebige Profile verwenden,
|
Moreover, if a device is seized then chat contacts using short-lived profiles
|
||||||
im Falle einer Beschlagnahmung des Geräts nicht ohne Weiteres identifiziert werden.</p>
|
can not be identified easily.</p>
|
||||||
|
|
||||||
<h3 id="wer-sieht-meine-ip-adresse">
|
<h3 id="wer-sieht-meine-ip-adresse">
|
||||||
|
|
||||||
@@ -1535,16 +1317,23 @@ im Falle einer Beschlagnahmung des Geräts nicht ohne Weiteres identifiziert wer
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Die verwendeten <a href="#relays">Relays</a> müssen deine IP-Adresse kennen,
|
<p>Das verwendete <a href="#relays">Relay</a> muss Ihre IP-Adresse kennen,
|
||||||
sowie manchmal auch die Geräte deiner Kontakte, wenn du einen <a href="#calls">Anruf</a> tätigst
|
sowie manchmal auch die Geräte Ihrer Kontakte, wenn Sie einen <a href="#experiments">Anruf</a> tätigen
|
||||||
oder ihr gemeinsam <a href="#webxdc">Apps</a> verwendet.</p>
|
oder gemeinsam <a href="#webxdc">Apps</a> verwenden.</p>
|
||||||
|
|
||||||
<p>IP-Adressen sind für Verbindungen und für Effizienz erforderlich.
|
<p>IP-Adressen sind für Verbindungen und für Effizienz erforderlich.
|
||||||
Sie werden von Delta Chat weder gespeichert noch offengelegt.
|
Sie werden weder gespeichert noch offengelegt.
|
||||||
IP-Adressen sind nicht mit einer Adresse, die du einem Lieferdienst gibst, vergleichbar - sondern viel gröber und oft nur die Stadt oder die Region beschreibend.</p>
|
Beachten Sie, dass die IP-Adresse
|
||||||
|
nicht mit einer Adresse, die Sie einem Lieferdienst geben, vergleichbar ist -
|
||||||
|
sondern viel gröber ist und oft nur die Region oder das Land angibt.</p>
|
||||||
|
|
||||||
<p>Wenn du deine IP-Adresse als Risiko betrachtest, empfehlen wir, ein VPN für das gesamte System zu verwenden.
|
<p>Da dies die Standardfunktion des Internets und anderer Messenger ist,
|
||||||
Einstellungen auf App-Ebene hinterlassen Lücken überall im System. Wenn man beispielsweise auf einen Link tippt, können IP-Adressen an Unbekannte weitergegeben werden, was bei weitem das größere Risiko darstellt</p>
|
bieten wir hier keine Optionen an und stellen auch keine Fragen im Voraus.</p>
|
||||||
|
|
||||||
|
<p>Wenn Sie Ihre IP-Adresse als Sicherheits- oder Datenschutzrisiko betrachten,
|
||||||
|
empfehlen wir Ihnen, ein VPN in Kombination mit dem System-Lockdown-Modus zu verwenden.
|
||||||
|
Alle einzelnen Apps auf Ihrem System nach IP-Optionen abzusuchen wird nicht zufriedenstellen sein;
|
||||||
|
beispielsweise legt das Antippen eines Links IP-Adressen gegenüber unbekannten Parteien offen und stellt hier das weitaus größere Risiko dar.</p>
|
||||||
|
|
||||||
<h3 id="sealedsender">
|
<h3 id="sealedsender">
|
||||||
|
|
||||||
@@ -1561,10 +1350,11 @@ um seine Serverinfrastruktur darüber im Unklaren zu lassen, wer eine Nachricht
|
|||||||
Dies ist besonders wichtig, weil der Signal-Server die Handynummer jedes Kontos kennt,
|
Dies ist besonders wichtig, weil der Signal-Server die Handynummer jedes Kontos kennt,
|
||||||
die in der Regel mit einer Passidentität verbunden ist.</p>
|
die in der Regel mit einer Passidentität verbunden ist.</p>
|
||||||
|
|
||||||
<p>Auch wenn <a href="https://chatmail.at/relays">Chatmail-Relays</a>
|
<p>Even if <a href="https://chatmail.at/relays">chatmail relays</a>
|
||||||
keine privaten Daten (einschließlich Telefonnummern) abfragen,
|
do not ask for any private data (including no phone numbers),
|
||||||
könnte es dennoch sinnvoll sein, Metadaten zwischen Adressen zu schützen.
|
it might still be worthwhile to protect relational metadata between addresses.
|
||||||
Wir sehen keine größeren Probleme bei der Verwendung von zufälligen Wegwerfadressen für aber eine Umsetzung wurde noch nicht als priorisiert.</p>
|
We don’t foresee bigger problems in using random throw-away addresses for sealed sending
|
||||||
|
but an implementation has not been agreed as a priority yet.</p>
|
||||||
|
|
||||||
<h3 id="pfs">
|
<h3 id="pfs">
|
||||||
|
|
||||||
@@ -1574,20 +1364,23 @@ Wir sehen keine größeren Probleme bei der Verwendung von zufälligen Wegwerfad
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Noch nicht, aber es kommt mit <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>Nein, noch nicht.</p>
|
||||||
|
|
||||||
<p>Delta Chat unterstützt derzeit keine Perfect Forward Secrecy (PFS).
|
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||||
Das bedeutet, dass, wenn Ihr privater Schlüssel offengelegt wird
|
This means that if your private decryption key is leaked,
|
||||||
und jemand Ihre früheren Nachrichten während der Übertragung gesammelt hat,
|
and someone has collected your prior in-transit messages,
|
||||||
diese mit dem offengelegten Schlüssel entschlüsselt und gelesen werden können.
|
they will be able to decrypt and read them using the leaked decryption key.
|
||||||
Beachten Sie, dass Forward Secrecy die Sicherheit nur erhöht, wenn du Nachrichten löschst.
|
Note that Forward Secrecy only increases security if you delete messages.
|
||||||
Andernfalls kann jemand, der deinen Schlüssel erhält,
|
Otherwise, someone obtaining your decryption keys
|
||||||
in der Regel auch alle deine nicht gelöschten Nachrichten abrufen
|
is typically also able to get all your non-deleted messages
|
||||||
und muss zuvor gesammelte Nachrichten nicht einmal entschlüsseln.</p>
|
and doesn’t even need to decrypt any previously collected messages.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, dessen vollständige Implementierung für 2026 geplant ist,
|
<p>We designed a Forward Secrecy approach that withstood
|
||||||
wird durch automatische Schlüsselrotation eine zuverlässige Löschung (Forward Secrecy) gewährleisten.
|
initial examination from some cryptographers and implementation experts
|
||||||
Dieser Ansatz ist im Entwurf <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> festgelegt.</p>
|
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>
|
||||||
|
|
||||||
<h3 id="pqc">
|
<h3 id="pqc">
|
||||||
|
|
||||||
@@ -1597,13 +1390,11 @@ Dieser Ansatz ist im Entwurf <a href="https://datatracker.ietf.org/doc/draft-aut
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Noch nicht, aber es kommt mit <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>Nein, noch nicht.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, dessen vollständige Implementierung für 2026 geplant ist,
|
<p>Delta Chat verwendet die Rust OpenPGP-Bibliothek <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||||
wird eine post-quantum-resistente Verschlüsselung zum Schutz vor Angriffen durch Quantencomputer bieten.
|
die den neuesten <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP Entwurf</a> unterstützt.
|
||||||
Delta Chat verwendet die Rust-OpenPGP-Bibliothek <a href="https://github.com/rpgp/rpgp">rPGP</a>,
|
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>
|
||||||
die den neuesten <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Kryptografie OpenPGP Entfurf</a> unterstützt.
|
|
||||||
Die Implementierung ist in <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> festgelegt.</p>
|
|
||||||
|
|
||||||
<h3 id="wie-kann-ich-die-verschlüsselung-manuell-überprüfen">
|
<h3 id="wie-kann-ich-die-verschlüsselung-manuell-überprüfen">
|
||||||
|
|
||||||
@@ -1629,11 +1420,12 @@ ist die Verbindung sicher.</p>
|
|||||||
|
|
||||||
<p>Nein.</p>
|
<p>Nein.</p>
|
||||||
|
|
||||||
<p>Delta Chat generiert sichere OpenPGP-Schlüssel gemäß der Autocrypt-Spezifikation 1.1.
|
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
|
||||||
Wir bieten Benutzern keine manuelle Schlüsselverwaltung an, noch empfehlen diese.
|
We do not recommend or offer users to perform manual key management.
|
||||||
Wir wollen sicherstellen, dass sich Sicherheitsüberprüfungen auf einige wenige bewährte kryptografische Algorithmen konzentrieren können,
|
We want to ensure that security audits can focus on a few proven cryptographic algorithms
|
||||||
anstatt auf die gesamte Bandbreite der mit OpenPGP zulässigen Algorithmen.
|
instead of the full breadth of possible algorithms allowed with OpenPGP.
|
||||||
Wenn Sie Ihren OpenPGP-Schlüssel extrahieren möchten, gibt es nur eine Methode für Experten: Sie müssen ihn in der SQLite-Tabelle „keypairs” des Backups nachschlagen.</p>
|
If you want to extract your OpenPGP key, there only is an expert method:
|
||||||
|
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
|
||||||
|
|
||||||
<h3 id="security-audits">
|
<h3 id="security-audits">
|
||||||
|
|
||||||
@@ -1667,7 +1459,7 @@ Weitere Informationen findest du in unserem Blogbeitrag über <a href="https://d
|
|||||||
<p>Im April 2023 haben wir Sicherheits- und Datenschutzprobleme mit dem “In Chats geteilten Apps”-Feature behoben, die mit Fehlern beim Sandboxing, insbesondere mit Chromium zusammenhängen. Wir haben daraufhin eine unabhängige Sicherheitsprüfung von Cure53 durchführen lassen, und alle gefundenen Probleme wurden mit den im April 2023 veröffentlichten 1.36 Releases behoben. Siehe <a href="https://delta.chat/en/2023-05-22-webxdc-security">hier für die vollständige Hintergrundgeschichte</a>.</p>
|
<p>Im April 2023 haben wir Sicherheits- und Datenschutzprobleme mit dem “In Chats geteilten Apps”-Feature behoben, die mit Fehlern beim Sandboxing, insbesondere mit Chromium zusammenhängen. Wir haben daraufhin eine unabhängige Sicherheitsprüfung von Cure53 durchführen lassen, und alle gefundenen Probleme wurden mit den im April 2023 veröffentlichten 1.36 Releases behoben. Siehe <a href="https://delta.chat/en/2023-05-22-webxdc-security">hier für die vollständige Hintergrundgeschichte</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Im März 2023 analysierte <a href="https://cure53.de">Cure53</a> sowohl die Transportverschlüsselung von Delta Chats Netzwerkverbindungen als auch das reproduzierbare Mailserver-Setup wie <a href="https://delta.chat/serverguide">auf dieser Seite empfohlen</a>. Du kannst mehr über das Audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">in unserem Blog</a> lesen oder du liest den <a href="https://delta.chat/assets/blog/MER-01-report.pdf">vollständigen Bericht hier</a>.</p>
|
<p>Im März 2023 analysierte <a href="https://cure53.de">Cure53</a> sowohl die Transportverschlüsselung von Delta Chats Netzwerkverbindungen als auch das reproduzierbare Mailserver-Setup wie <a href="https://delta.chat/de/serverguide">auf dieser Seite empfohlen</a>. Du kannst mehr über das Audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">in unserem Blog</a> lesen oder du liest den <a href="https://delta.chat/assets/blog/MER-01-report.pdf">vollständigen Bericht hier</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Im Jahr 2020 analysierte <a href="https://includesecurity.com">Include Security</a> Delta Chats Rust <a href="https://github.com/deltachat/deltachat-core-rust/">core</a>, <a href="https://github.com/async-email/async-imap">IMAP</a>,<a href="https://github.com/async-email/async-smtp">SMTP</a>, und <a href="https://github.com/async-email/async-native-tls">TLS</a> Bibliotheken.
|
<p>Im Jahr 2020 analysierte <a href="https://includesecurity.com">Include Security</a> Delta Chats Rust <a href="https://github.com/deltachat/deltachat-core-rust/">core</a>, <a href="https://github.com/async-email/async-imap">IMAP</a>,<a href="https://github.com/async-email/async-smtp">SMTP</a>, und <a href="https://github.com/async-email/async-native-tls">TLS</a> Bibliotheken.
|
||||||
@@ -1743,24 +1535,31 @@ Wir nutzen vielmehr öffentliche Finanzierungsquellen, die bisher aus der EU und
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>2023 und 2024 wurden wir in das Next-Generation-Internet-Programm (NGI)
|
<p>In 2023 and 2024 we got accepted in the Next Generation Internet (NGI)
|
||||||
für unsere Arbeit an <a href="https://nlnet.nl/project/WebXDC-Push/">Webxdc-PUSH</a> aufgenommen,
|
program for our work in <a href="https://nlnet.nl/project/WebXDC-Push/">webxdc PUSH</a>,
|
||||||
zusammen mit Kooperationspartnern, die an
|
along with collaboration partners working on
|
||||||
<a href="https://nlnet.nl/project/Webxdc-Evolve/">Webxdc-Evolve</a>,
|
<a href="https://nlnet.nl/project/Webxdc-Evolve/">webxdc evolve</a>,
|
||||||
<a href="https://nlnet.nl/project/WebXDC-XMPP/">Webxdc-XMPP</a>,
|
<a href="https://nlnet.nl/project/WebXDC-XMPP/">webxdc XMPP</a>,
|
||||||
<a href="https://nlnet.nl/project/DeltaTouch/">DeltaTouch</a> und
|
<a href="https://nlnet.nl/project/DeltaTouch/">DeltaTouch</a> and
|
||||||
<a href="https://nlnet.nl/project/DeltaTauri/">DeltaTauri</a>.
|
<a href="https://nlnet.nl/project/DeltaTauri/">DeltaTauri</a>.
|
||||||
Alle diese Projekte sind teilweise abgeschlossen oder sollen Anfang 2025 abgeschlossen werden.</p>
|
All of these projects are partially completed or to be completed in early 2025.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Im Jahr 2021 erhielten wir weitere EU-Mittel für zwei “Next-Generation-Internet”-Anträge, nämlich für <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - E-Mail-Provider-Portabilitätsverzeichnis</a> (~97K EUR) und <a href="https://nlnet.nl/project/EmailPorting/">AEAP - E-Mail-Adressportierung</a> (~90K EUR). Ziel sind bessere Unterstützung von Mehrfachkonten, verbesserten QR-Code-Kontakt- und -Gruppen-Setups sowie Netzwerkverbesserungen auf allen Plattformen.</p>
|
<p>Im Jahr 2021 erhielten wir weitere EU-Mittel für zwei “Next-Generation-Internet”-Anträge, nämlich für <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - E-Mail-Provider-Portabilitätsverzeichnis</a> (~97K EUR) und <a href="https://nlnet.nl/project/EmailPorting/">AEAP - E-Mail-Adressportierung</a> (~90K EUR). Ziel sind bessere Unterstützung von Mehrfachkonten, verbesserten QR-Code-Kontakt- und -Gruppen-Setups sowie Netzwerkverbesserungen auf allen Plattformen.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Die <a href="https://nlnet.nl/">NLnet-Stiftung</a> bewilligte 2019/2020 46K EUR für die Fertigstellung von Rust-/Python-Bindungs und die Einrichtung eines Chat-Bot-Ökosystems.</p>
|
<p>The <a href="https://nlnet.nl/">NLnet foundation</a> granted in 2019/2020 EUR 46K for
|
||||||
|
completing Rust/Python bindings and instigating a Chat-bot eco-system.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Der <a href="https://opentechfund.org">Open Technology Fund</a> hat Delta Chat erstmals 2018/2019 bezuschusst; mit dieser Förderung (~$200K) wurden hauptsächlich die Android-App verbessert sowie das Release der Desktop-App in einer Betaversion ermöglicht. Basierend auf Nutzererfahrungen im Menschenrechtskontext wurden zudem verschiedene Funktionen entwickelt, siehe unseren Bericht <a href="https://delta.chat/en/2019-07-19-uxreport">Needfinding and UX report</a>.
|
<p>The <a href="https://opentechfund.org">Open Technology Fund</a> gave us a
|
||||||
Die zweite Förderung 2019/2020 (~$300K) half uns bei der Erstellung der iOS-Version, unsere Kernbibliothek in die Programmiersprache “Rust” zu konvertieren und neue Funktionen für alle Plattformen bereitzustellen.</p>
|
first 2018/2019 grant (~$200K) during which we majorly improved the Android app
|
||||||
|
and released a first Desktop app beta version, and which moreover
|
||||||
|
moored our feature developments in UX research in human rights contexts,
|
||||||
|
see our concluding <a href="https://delta.chat/en/2019-07-19-uxreport">Needfinding and UX report</a>.
|
||||||
|
The second 2019/2020 grant (~$300K) helped us to
|
||||||
|
release Delta/iOS versions, to convert our core library to Rust, and
|
||||||
|
to provide new features for all platforms.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Das EU-Projekt <a href="https://nextleap.eu">NEXTLEAP</a> finanzierte 2017 und 2018 die Entwicklung und Implementierung von “Verifizierten Gruppen” und “Setup Kontakt” und half auch bei der Integration der Ende-zu-Ende-Verschlüsselung durch <a href="https://autocrypt.org">Autocrypt</a>.</p>
|
<p>Das EU-Projekt <a href="https://nextleap.eu">NEXTLEAP</a> finanzierte 2017 und 2018 die Entwicklung und Implementierung von “Verifizierten Gruppen” und “Setup Kontakt” und half auch bei der Integration der Ende-zu-Ende-Verschlüsselung durch <a href="https://autocrypt.org">Autocrypt</a>.</p>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
||||||
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
||||||
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
||||||
|
<li><a href="#does-delta-chat-support-images-videos-and-other-attachments">Does Delta Chat support images, videos and other attachments?</a></li>
|
||||||
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
||||||
<li><a href="#who-sees-my-profile-picture">Who sees my profile picture?</a></li>
|
<li><a href="#who-sees-my-profile-picture">Who sees my profile picture?</a></li>
|
||||||
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
<li><a href="#what-does-the-green-dot-mean">What does the green dot mean?</a></li>
|
<li><a href="#what-does-the-green-dot-mean">What does the green dot mean?</a></li>
|
||||||
<li><a href="#what-do-the-ticks-shown-beside-outgoing-messages-mean">What do the ticks shown beside outgoing messages mean?</a></li>
|
<li><a href="#what-do-the-ticks-shown-beside-outgoing-messages-mean">What do the ticks shown beside outgoing messages mean?</a></li>
|
||||||
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
||||||
<li><a href="#mediaquality">How is media quality handled?</a></li>
|
|
||||||
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
||||||
<li><a href="#delold">What happens if I turn on “Delete Messages from Device”?</a></li>
|
<li><a href="#delold">What happens if I turn on “Delete Messages from Device”?</a></li>
|
||||||
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
||||||
@@ -29,21 +29,6 @@
|
|||||||
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#channels">Channels</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#subscribe-to-a-channel">Subscribe to a channel</a></li>
|
|
||||||
<li><a href="#create-a-channel">Create a channel</a></li>
|
|
||||||
<li><a href="#how-many-subscribers-can-a-channel-have">How many subscribers can a channel have?</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#calls">Calls</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#place-a-call">Place a call</a></li>
|
|
||||||
<li><a href="#accept-or-reject-a-call">Accept or reject a call</a></li>
|
|
||||||
<li><a href="#during-a-call">During a call</a></li>
|
|
||||||
<li><a href="#missed-calls-and-notifications">Missed calls and notifications</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#webxdc">In-chat apps</a>
|
<li><a href="#webxdc">In-chat apps</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
||||||
@@ -233,6 +218,19 @@ You can also add a little introduction message.</p>
|
|||||||
<p>The second contact will receive a <strong>card</strong> then
|
<p>The second contact will receive a <strong>card</strong> then
|
||||||
and can tap it to start chatting with the first contact.</p>
|
and can tap it to start chatting with the first contact.</p>
|
||||||
|
|
||||||
|
<h3 id="does-delta-chat-support-images-videos-and-other-attachments">
|
||||||
|
|
||||||
|
|
||||||
|
Does Delta Chat support images, videos and other attachments? <a href="#does-delta-chat-support-images-videos-and-other-attachments" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Yes. Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment-</strong>
|
||||||
|
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons</p>
|
||||||
|
|
||||||
|
<p>For performance, images are optimized and sent at a smaller size by default, but you can send it as a “file” to preserve the original.</p>
|
||||||
|
|
||||||
<h3 id="multiple-accounts">
|
<h3 id="multiple-accounts">
|
||||||
|
|
||||||
|
|
||||||
@@ -413,32 +411,6 @@ Notifications are not sent and there is no time limit.</p>
|
|||||||
<p>Note, that the original message may still be received by chat members
|
<p>Note, that the original message may still be received by chat members
|
||||||
who could have already replied, forwarded, saved, screenshotted or otherwise copied the message.</p>
|
who could have already replied, forwarded, saved, screenshotted or otherwise copied the message.</p>
|
||||||
|
|
||||||
<h3 id="mediaquality">
|
|
||||||
|
|
||||||
|
|
||||||
How is media quality handled? <a href="#mediaquality" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach-</strong>
|
|
||||||
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>By default, compression ensures <strong>fast, efficient delivery</strong> that respects everyone’s data limits and storage.
|
|
||||||
This is ideal for everyday communication.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>In regions with worse connectivity,
|
|
||||||
you can choose higher compression at <strong>Settings → Chats → Outgoing Media Quality</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>If you specifically need to send media in its <strong>original quality</strong>, use <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach → File</strong> in the chat.
|
|
||||||
Please use this method sparingly, as sending original files will significantly increase data usage for you and all recipients in the chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="ephemeralmsgs">
|
<h3 id="ephemeralmsgs">
|
||||||
|
|
||||||
|
|
||||||
@@ -642,197 +614,6 @@ but more than 150 is not recommended.</p>
|
|||||||
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
||||||
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
||||||
|
|
||||||
<h2 id="channels">
|
|
||||||
|
|
||||||
|
|
||||||
Channels <a href="#channels" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Channels are a one-to-many tool for broadcasting messages.</p>
|
|
||||||
|
|
||||||
<h3 id="subscribe-to-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Subscribe to a channel <a href="#subscribe-to-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Scan the <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>QR code</strong>
|
|
||||||
or tap the <strong>invite link</strong> you got from the channel owner.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>That’s all!
|
|
||||||
You will receive a few of the messages from the channel history
|
|
||||||
and, from that point on, all new messages from the channel.</p>
|
|
||||||
|
|
||||||
<p><strong>Don’t worry,</strong> if that does not happen immediately.
|
|
||||||
Once the channel owner comes online, your join request will be processed.</p>
|
|
||||||
|
|
||||||
<p>As all of Delta Chat, also Channels are private and decentralized,
|
|
||||||
there is no public discovery.</p>
|
|
||||||
|
|
||||||
<p>Other channel subscribers will not see that you subscribed and cannot message you.
|
|
||||||
The channel owner, however, can message you.
|
|
||||||
They will also see that you read a message unless you have read receipts disabled.</p>
|
|
||||||
|
|
||||||
<p>If you do not want to share your main profile,
|
|
||||||
you can also create a <a href="#multiple-accounts">dedicated profile</a> for joining a channel.</p>
|
|
||||||
|
|
||||||
<h3 id="create-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Create a channel <a href="#create-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>New Chat</strong> and choose <strong>New Channel</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Enter a <strong>name</strong>, optionally set an <strong>image</strong> and <strong>description</strong>, and hit the <strong>Create</strong> button.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can now send and manage messages as usual.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>From the channel’s profile, <strong>share the QR code or invite link with others</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Subscribers will receive your messages,
|
|
||||||
but they cannot send messages in your channel.
|
|
||||||
When subscribing, they will receive <strong>a few of the latest messages of the channel history</strong>.</p>
|
|
||||||
|
|
||||||
<p>You can see the <strong>view count</strong> beside each message.
|
|
||||||
Note that this only counts subscribers who have read receipts enabled,
|
|
||||||
so the real view count may be larger.</p>
|
|
||||||
|
|
||||||
<h3 id="how-many-subscribers-can-a-channel-have">
|
|
||||||
|
|
||||||
|
|
||||||
How many subscribers can a channel have? <a href="#how-many-subscribers-can-a-channel-have" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Channels are designed for much larger audiences than <a href="#groups">groups</a>.</p>
|
|
||||||
|
|
||||||
<p>The practical limit depends on the used <a href="#relays">relay</a>,
|
|
||||||
so there is no single fixed number that applies everywhere.</p>
|
|
||||||
|
|
||||||
<p>For really large channels with several tens of thousands of subscribers,
|
|
||||||
we recommend using a <a href="#multiple-accounts">dedicated profile</a> for the channel
|
|
||||||
and checking whether the relay is suitable.</p>
|
|
||||||
|
|
||||||
<p>But don’t be too hesitant: Delta Chat is designed to be relay-agnostic,
|
|
||||||
so you can change your relay at any point easily -
|
|
||||||
your existing subscribers will not even notice.
|
|
||||||
You only have to update the invite link you share with new subscribers in that case.</p>
|
|
||||||
|
|
||||||
<h2 id="calls">
|
|
||||||
|
|
||||||
|
|
||||||
Calls <a href="#calls" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Delta Chat supports one-to-one <strong>audio calls</strong> and <strong>video calls</strong>.</p>
|
|
||||||
|
|
||||||
<p>Calls are supported on Desktop, Ubuntu Touch, iOS and Android 8 and newer.</p>
|
|
||||||
|
|
||||||
<h3 id="place-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Place a call <a href="#place-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>In a one-to-one chat, tap the 📞 <strong>call icon</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>This opens a small menu
|
|
||||||
where you can choose whether to place an <strong>Audio Call</strong> or a <strong>Video Call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="accept-or-reject-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Accept or reject a call <a href="#accept-or-reject-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>When someone calls you,
|
|
||||||
Delta Chat shows an <strong>incoming call screen</strong> or notification.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>Accept</strong> to answer
|
|
||||||
or <strong>Decline</strong> to reject the call.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="during-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
During a call <a href="#during-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>mute</strong> your microphone.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>enable or disable your camera</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>On mobile, you can <strong>switch between front and back cameras</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Depending on the device, you can also select the audio output or use picture-in-picture.
|
|
||||||
On desktop, the call is using a dedicated window
|
|
||||||
and you can continue using the main Delta Chat window as usual.</p>
|
|
||||||
|
|
||||||
<h3 id="missed-calls-and-notifications">
|
|
||||||
|
|
||||||
|
|
||||||
Missed calls and notifications <a href="#missed-calls-and-notifications" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>If you do not answer, do not hear the ringing, or do not have your device at hand,
|
|
||||||
the call appears as a <strong>missed call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><strong>Only your accepted contacts</strong> can make your device ring.
|
|
||||||
Contact requests will appear as usual and will not ring.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>At <strong>Settings → Notifications → Calls</strong>,
|
|
||||||
you can disable the special call ringing screen completely.
|
|
||||||
If you do so, you will not be disturbed by any ringing notification,
|
|
||||||
you can still pick up the call by tapping the incoming call message bubble in its chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="webxdc">
|
<h2 id="webxdc">
|
||||||
|
|
||||||
|
|
||||||
@@ -1249,26 +1030,22 @@ Relays are operated by different groups and people.</p>
|
|||||||
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
||||||
so you do not need to care about that.
|
so you do not need to care about that.
|
||||||
However, if you want to,
|
However, if you want to,
|
||||||
you can configure relays at <strong>Settings → Advanced → Relays</strong>:</p>
|
you can configure relays at At <strong>Settings → Advanced → Relays</strong>:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
||||||
<a href="https://chatmail.at/relays">chatmail.at/relays</a> shows some known ones.
|
<a href="https://chatmail.at/relays">https://chatmail.at/relays</a> shows some known ones.
|
||||||
If you have multiple relays, you will receive messages on all of them.
|
If you have multiple relays, you will receive messages on all of them.</p>
|
||||||
Contacts learn your current relays automatically when you message them.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Tap on a relay to set it as <strong>used for sending</strong>.</p>
|
<p>The <strong>default</strong> defines the one where your chat partners send future messages to.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>If you <strong>remove</strong> a relay,
|
<p>If you <strong>remove</strong> a relay,
|
||||||
contacts who only know this relay may not reach you until you message them again.
|
make sure another default relay was used for a sufficient amount of time.
|
||||||
To stay reachable in the meantime, choose <strong>Hide from Contacts</strong> in the confirmation dialog
|
Otherwise, messages from your chat partners won’t reach you.
|
||||||
instead of removing it right away.</p>
|
If in doubt, remove later.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>To <strong>show</strong> a hidden relay again, tap on it.</p>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -1411,10 +1188,6 @@ to exchange encryption setup information through QR-code scanning or “invite l
|
|||||||
<li>
|
<li>
|
||||||
<p><a href="https://autocrypt.org">Autocrypt</a> is used for automatically
|
<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>
|
establishing end-to-end encryption between contacts and all members of a group chat.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
|
||||||
will bring post-quantum resistant encryption and forward secrecy.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<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
|
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Sharing a contact to a
|
||||||
@@ -1599,10 +1372,12 @@ Instead, all group metadata is end-to-end encrypted and stored on end-user devic
|
|||||||
<p>Servers can therefore only see:</p>
|
<p>Servers can therefore only see:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Sender and receiver addresses, randomly generated by default</li>
|
<li>the sender and receiver addresses</li>
|
||||||
<li>Message size</li>
|
<li>and the message size.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>By default, the addresses are randomly generated.</p>
|
||||||
|
|
||||||
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
||||||
|
|
||||||
<h3 id="device-seizure">
|
<h3 id="device-seizure">
|
||||||
@@ -1631,20 +1406,23 @@ can not be identified easily.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>The used <a href="#relays">relays</a> need to know your IP Address,
|
<p>The used <a href="#relays">relay</a> needs to know your IP Address,
|
||||||
as well as sometimes your contact’s devices if you have a <a href="#calls">call</a>
|
as well as sometimes your contact’s devices if you have a <a href="#experiments">call</a>
|
||||||
or use <a href="#webxdc">apps</a> together.</p>
|
or use <a href="#webxdc">apps</a> together.</p>
|
||||||
|
|
||||||
<p>IP Addresses are needed for connectivity and efficiency.
|
<p>IP Addresses are needed for connectivity and efficiency.
|
||||||
Delta Chat neither persists nor exposes them.
|
They are neither persisted nor exposed.
|
||||||
Note that IP Addresses
|
Note that the IP Address
|
||||||
are not like an address you give to a delivery service,
|
is not like a detailed address you give to a delivery service,
|
||||||
but typically less precise, often defining city or region only.</p>
|
but much more coarse, often defining region or country only.</p>
|
||||||
|
|
||||||
<p>If you see your IP Address as a risk,
|
<p>As this is just how the internet and other messengers work by default,
|
||||||
we recommend to use a VPN for the whole system.
|
we do not offer options here or ask upfront questions.</p>
|
||||||
Per-app options leave gaps across your system.
|
|
||||||
For example, tapping a link can expose IP Addresses to unknown parties, which is by far the larger risk.</p>
|
<p>If you see your IP Address as a security or privacy risk,
|
||||||
|
we recommend to use a VPN, in combination with system lockdown mode.
|
||||||
|
Hunting down options in all apps on your system will leave gaps.
|
||||||
|
For example, tapping a link exposes IP Addresses to unknown parties and is the by far larger risk here.</p>
|
||||||
|
|
||||||
<h3 id="sealedsender">
|
<h3 id="sealedsender">
|
||||||
|
|
||||||
@@ -1675,7 +1453,7 @@ but an implementation has not been agreed as a priority yet.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||||
This means that if your private decryption key is leaked,
|
This means that if your private decryption key is leaked,
|
||||||
@@ -1686,9 +1464,12 @@ Otherwise, someone obtaining your decryption keys
|
|||||||
is typically also able to get all your non-deleted messages
|
is typically also able to get all your non-deleted messages
|
||||||
and doesn’t even need to decrypt any previously collected messages.</p>
|
and doesn’t even need to decrypt any previously collected messages.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>We designed a Forward Secrecy approach that withstood
|
||||||
will provide reliable deletion (forward secrecy) through automatic key rotation.
|
initial examination from some cryptographers and implementation experts
|
||||||
This approach is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
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>
|
||||||
|
|
||||||
<h3 id="pqc">
|
<h3 id="pqc">
|
||||||
|
|
||||||
@@ -1698,13 +1479,12 @@ This approach is specified in the <a href="https://datatracker.ietf.org/doc/draf
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||||
will bring post-quantum resistant encryption to protect against quantum computer attacks.
|
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
||||||
Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</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
|
||||||
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
in collaboration with other OpenPGP implementers.</p>
|
||||||
The implementation is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
|
||||||
|
|
||||||
<h3 id="how-can-i-manually-check-encryption-information">
|
<h3 id="how-can-i-manually-check-encryption-information">
|
||||||
|
|
||||||
@@ -1781,7 +1561,7 @@ See <a href="https://delta.chat/en/2023-05-22-webxdc-security">here for the full
|
|||||||
<li>
|
<li>
|
||||||
<p>2023 March, <a href="https://cure53.de">Cure53</a> analyzed both the transport encryption of
|
<p>2023 March, <a href="https://cure53.de">Cure53</a> analyzed both the transport encryption of
|
||||||
Delta Chat’s network connections and a reproducible mail server setup as
|
Delta Chat’s network connections and a reproducible mail server setup as
|
||||||
<a href="https://delta.chat/serverguide">recommended on this site</a>.
|
<a href="https://delta.chat/en/serverguide">recommended on this site</a>.
|
||||||
You can read more about the audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">on our blog</a>
|
You can read more about the audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">on our blog</a>
|
||||||
or read the <a href="https://delta.chat/assets/blog/MER-01-report.pdf">full report here</a>.</p>
|
or read the <a href="https://delta.chat/assets/blog/MER-01-report.pdf">full report here</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
+249
-465
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+200
-344
@@ -2,48 +2,33 @@
|
|||||||
<html lang="fr"><head><meta charset="UTF-8" /><meta name="viewport" content="initial-scale=1.0" /><link rel="stylesheet" href="../help.css" /></head><body><ul id="top">
|
<html lang="fr"><head><meta charset="UTF-8" /><meta name="viewport" content="initial-scale=1.0" /><link rel="stylesheet" href="../help.css" /></head><body><ul id="top">
|
||||||
<li><a href="#quest-ce-que-delta-chat-">Qu’est-ce que Delta Chat ?</a>
|
<li><a href="#quest-ce-que-delta-chat-">Qu’est-ce que Delta Chat ?</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#howtoe2ee">Comment trouver des personnes avec qui discuter ?</a></li>
|
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
||||||
<li><a href="#pourquoi-une-discussion-est-marquée-comme-invitation-">Pourquoi une discussion est marquée comme “invitation” ?</a></li>
|
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
||||||
<li><a href="#comment-mettre-deux-personnes-en-relation-entre-elles-">Comment mettre deux personnes en relation entre elles ?</a></li>
|
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
||||||
<li><a href="#multiple-accounts">À quoi correspondent les profils ? Comment est-ce que je peux passer de l’un à l’autre ?</a></li>
|
<li><a href="#delta-chat-prend-il-en-charge-les-images-vidéos-et-autres-pièces-jointes-">Delta Chat prend-il en charge les images, vidéos et autres pièces jointes ?</a></li>
|
||||||
|
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
||||||
<li><a href="#qui-peut-voir-ma-photo-de-profil-">Qui peut voir ma photo de profil ?</a></li>
|
<li><a href="#qui-peut-voir-ma-photo-de-profil-">Qui peut voir ma photo de profil ?</a></li>
|
||||||
<li><a href="#signature">Est-il possible de définir une Bio/un Statut avec Delta Chat ?</a></li>
|
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
||||||
<li><a href="#que-signifient-épingler-sourdine-et-archiver-">Que signifient “épingler”, “sourdine” et “archiver” ?</a></li>
|
<li><a href="#que-signifient-épingler-sourdine-et-archiver-">Que signifient “épingler”, “sourdine” et “archiver” ?</a></li>
|
||||||
<li><a href="#save">Comment fonctionnent les “Messages enregistrés” ?</a></li>
|
<li><a href="#save">How do “Saved Messages” work?</a></li>
|
||||||
<li><a href="#que-signifie-le-point-vert-">Que signifie le point vert ?</a></li>
|
<li><a href="#que-signifie-le-point-vert-">Que signifie le point vert ?</a></li>
|
||||||
<li><a href="#que-signifient-les-coches-affichées-à-côté-des-messages-sortants-">Que signifient les coches affichées à côté des messages sortants ?</a></li>
|
<li><a href="#que-signifient-les-coches-affichées-à-côté-des-messages-sortants-">Que signifient les coches affichées à côté des messages sortants ?</a></li>
|
||||||
<li><a href="#edit">Corriger des fautes et supprimer des messages après les avoir envoyés</a></li>
|
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
||||||
<li><a href="#mediaquality">Comment est gérée la qualité des médias envoyés ?</a></li>
|
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
||||||
<li><a href="#ephemeralmsgs">Comment fonctionnent les messages éphémères ?</a></li>
|
|
||||||
<li><a href="#delold">Que se passe-t-il si j’active l’option “Supprimer les anciens messages de l’appareil” ?</a></li>
|
<li><a href="#delold">Que se passe-t-il si j’active l’option “Supprimer les anciens messages de l’appareil” ?</a></li>
|
||||||
<li><a href="#remove-account">Comment puis-je supprimer un profil de discussion ?</a></li>
|
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#groups">Groupes</a>
|
<li><a href="#groups">Groups</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#création-dun-groupe">Création d’un groupe</a></li>
|
<li><a href="#création-dun-groupe">Création d’un groupe</a></li>
|
||||||
<li><a href="#addmembers">Ajouter et supprimer des membres</a></li>
|
<li><a href="#addmembers">Add and remove members</a></li>
|
||||||
<li><a href="#jai-quitté-un-groupe-par-accident">J’ai quitté un groupe par accident.</a></li>
|
<li><a href="#jai-quitté-un-groupe-par-accident">J’ai quitté un groupe par accident.</a></li>
|
||||||
<li><a href="#je-ne-souhaite-plus-recevoir-les-messages-dun-groupe">Je ne souhaite plus recevoir les messages d’un groupe.</a></li>
|
<li><a href="#je-ne-souhaite-plus-recevoir-les-messages-dun-groupe">Je ne souhaite plus recevoir les messages d’un groupe.</a></li>
|
||||||
<li><a href="#cloning-a-group">Cloning a group</a></li>
|
<li><a href="#cloning-a-group">Cloning a group</a></li>
|
||||||
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#channels">Channels</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#subscribe-to-a-channel">Subscribe to a channel</a></li>
|
|
||||||
<li><a href="#create-a-channel">Create a channel</a></li>
|
|
||||||
<li><a href="#how-many-subscribers-can-a-channel-have">How many subscribers can a channel have?</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#calls">Calls</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#place-a-call">Place a call</a></li>
|
|
||||||
<li><a href="#accept-or-reject-a-call">Accept or reject a call</a></li>
|
|
||||||
<li><a href="#during-a-call">During a call</a></li>
|
|
||||||
<li><a href="#missed-calls-and-notifications">Missed calls and notifications</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#webxdc">In-chat apps</a>
|
<li><a href="#webxdc">In-chat apps</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
||||||
@@ -120,71 +105,90 @@
|
|||||||
|
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>Delta Chat est une application de messagerie fiable, décentralisée et sécurisée, disponible pour smartphones et ordinateurs de bureau.</p>
|
<p>Delta Chat is a reliable, decentralized and secure instant messaging app,
|
||||||
|
available for mobile and desktop platforms.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Création à la volée de <strong>profils de discussion privés</strong> grâce à des <a href="https://chatmail.at/relays">relais chatmail</a> sécurisés et interopérables qui permettent des échanges instantanés et des notifications Push pour les appareils iOS et Android.</p>
|
<p>Instant creation of <strong>private chat profiles</strong>
|
||||||
|
with secure and interoperable <a href="https://chatmail.at/relays">chatmail relays</a>
|
||||||
|
that offer instant message delivery, and Push Notifications for iOS and Android devices.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Fonctionne en <a href="#multiple-accounts">multi-profils</a> et <a href="#multiclient">multi-appareils</a> sur toutes les plateformes et quelque soit <a href="https://chatmail.at/clients">l’application chatmail</a> utilisée.</p>
|
<p>Pervasive <a href="#multiple-accounts">multi-profile</a> and
|
||||||
|
<a href="#multiclient">multi-device</a> support on all platforms
|
||||||
|
and between different <a href="https://chatmail.at/clients">chatmail apps</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><a href="#webxdc">Applications</a> interactives permettant de jouer et collaborer au sein des discussions.</p>
|
<p>Interactive <a href="#webxdc">in-chat apps</a> for gaming and collaboration</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><a href="#security-audits">Chiffrement de bout-en-bout audité</a> protégé contre les attaques réseaux et de serveurs.</p>
|
<p><a href="#security-audits">Audited end-to-end encryption</a>
|
||||||
|
safe against network and server attacks.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Logiciel libre et gratuit, autant côté serveur que côté application, développé autour des <a href="https://github.com/chatmail/core/blob/main/standards.md#standards-used-in-delta-chat">standards d’internet</a>.</p>
|
<p>Free and Open Source software, both app and server side,
|
||||||
|
built on <a href="https://github.com/chatmail/core/blob/main/standards.md#standards-used-in-delta-chat">Internet Standards</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3 id="howtoe2ee">
|
<h3 id="howtoe2ee">
|
||||||
|
|
||||||
|
|
||||||
Comment trouver des personnes avec qui discuter ? <a href="#howtoe2ee" class="anchor"></a>
|
How can I find people to chat with? <a href="#howtoe2ee" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Delta Chat est une application de messagerie privée. Il n’y a pas de mécanisme de découverte publique des utilisateurs et utilisatrices. <em>Vous</em> décidez avec qui vous échangez dans Delta Chat.</p>
|
<p>First, note that Delta Chat is a private messenger.
|
||||||
|
There is no public discovery, <em>you</em> decide about your contacts.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>En <strong>présence physique</strong> de vos amis ou de membres de votre famille, appuyez sur l’icône <strong>QR code</strong> <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> sur l’écran principal. Demandez à votre contact de <strong>scanner</strong> le QR code avec leur application Delta Chat.</p>
|
<p>If you are <strong>face to face</strong> with your friend or family,
|
||||||
|
tap the <strong>QR Code</strong> icon <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" />
|
||||||
|
on the main screen.<br />
|
||||||
|
Ask your chat partner to <strong>scan</strong> the QR image
|
||||||
|
with their Delta Chat app.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Pour la mise en place d’un échange <strong>à distance</strong>, cliquez sur l’icône <strong>QR code</strong> sur l’écran principal, puis sur le bouton “Lien”, puis sur “Copier” ou “Partager” et envoyez le lien d’invitation via une autre messagerie privée.</p>
|
<p>For a <strong>remote</strong> contact setup,
|
||||||
|
from the same screen,
|
||||||
|
click “Copy” or “Share” and send the <strong>invite link</strong>
|
||||||
|
through another private chat.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Il suffit ensuite d’attendre que la connexion soit établie.</p>
|
<p>Now wait while connection gets established.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Si les deux contacts sont en ligne, ils verront rapidement apparaître une nouvelle discussion et pourront tout de suite commencer une discussion sécurisée.</p>
|
<p>If both sides are online, they will soon see a chat
|
||||||
|
and can start messaging securely.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Si l’un des contacts n’est pas en ligne ou a des problèmes de réseau, la possibilité de démarrer la discussion aura lieu dès que la connectivité sera rétablie.</p>
|
<p>If one side is offline or in bad network,
|
||||||
|
the ability to chat is delayed until connectivity is restored.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Félicitations !
|
<p>Congratulations!
|
||||||
Vous utiliserez désormais le <a href="#e2ee">chiffrement de bout-en-bout</a> avec ce contact.
|
You now will automatically use <a href="#e2ee">end-to-end encryption</a> with this contact.
|
||||||
Si vous vous ajoutez à des discussions de <a href="#groups">groupe</a> le chiffrement de bout-en-bout sera établi entre tous les membres de la discussion.</p>
|
If you add each other to <a href="#groups">groups</a>, end-to-end encryption will be established among all members.</p>
|
||||||
|
|
||||||
<h3 id="pourquoi-une-discussion-est-marquée-comme-invitation-">
|
<h3 id="why-is-a-chat-marked-as-request">
|
||||||
|
|
||||||
|
|
||||||
Pourquoi une discussion est marquée comme “invitation” ? <a href="#pourquoi-une-discussion-est-marquée-comme-invitation-" class="anchor"></a>
|
Why is a chat marked as “Request”? <a href="#why-is-a-chat-marked-as-request" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Delta Chat étant une messagerie privée, seules les personnes avec qui vous <a href="#howtoe2ee">partagez votre QR code ou lien d’invitation</a> peuvent vous écrire.</p>
|
<p>As being a private messenger,
|
||||||
|
only friends and family you <a href="#howtoe2ee">share your QR code or invite link with</a> can write to you.</p>
|
||||||
|
|
||||||
<p>Vos contacts peuvent cependant partager votre profil avec d’autres personnes, ce qui apparaît alors comme une <b style="border: 1px solid currentColor; padding: 0 3px; font-size:90%">invitation</b>.</p>
|
<p>Your friends may share your contact with other friends,
|
||||||
|
this appears as <b style="border: 1px solid currentColor; padding: 0 3px; font-size:90%">Request</b></p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@@ -200,37 +204,53 @@ recevoir de messages de cette personne, nous vous conseillons de la <strong>bloq
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3 id="comment-mettre-deux-personnes-en-relation-entre-elles-">
|
<h3 id="how-can-i-put-two-of-my-friends-in-contact-with-each-other">
|
||||||
|
|
||||||
|
|
||||||
Comment mettre deux personnes en relation entre elles ? <a href="#comment-mettre-deux-personnes-en-relation-entre-elles-" class="anchor"></a>
|
How can I put two of my friends in contact with each other? <a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Joignez le premier contact à votre discussion avec le second en utilisant <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Bouton pièce jointe → Contact</strong>.
|
<p>Attach the first contact to the chat of the second using <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment Button → Contact</strong>.
|
||||||
Profitez-en pour ajouter un message de présentation.</p>
|
You can also add a little introduction message.</p>
|
||||||
|
|
||||||
<p>Le deuxième contact recevra une <strong>carte</strong> qu’il pourra cliquer pour commencer une discussion avec le premier.</p>
|
<p>The second contact will receive a <strong>card</strong> then
|
||||||
|
and can tap it to start chatting with the first contact.</p>
|
||||||
|
|
||||||
|
<h3 id="delta-chat-prend-il-en-charge-les-images-vidéos-et-autres-pièces-jointes-">
|
||||||
|
|
||||||
|
|
||||||
|
Delta Chat prend-il en charge les images, vidéos et autres pièces jointes ? <a href="#delta-chat-prend-il-en-charge-les-images-vidéos-et-autres-pièces-jointes-" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Oui. Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment-</strong>
|
||||||
|
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons</p>
|
||||||
|
|
||||||
|
<p>Pour améliorer les performances, les images sont redimensionnées et envoyées en taille réduite par défaut ; mais vous pouvez les envoyer en tant que “fichier” pour en conserver la taille originale.</p>
|
||||||
|
|
||||||
<h3 id="multiple-accounts">
|
<h3 id="multiple-accounts">
|
||||||
|
|
||||||
|
|
||||||
À quoi correspondent les profils ? Comment est-ce que je peux passer de l’un à l’autre ? <a href="#multiple-accounts" class="anchor"></a>
|
What are profiles? How can I switch between them? <a href="#multiple-accounts" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Un profil est <strong>un nom, une photo</strong> et quelques informations supplémentaires pour chiffrer des messages.
|
<p>A profile is <strong>a name, a picture</strong> and some additional information for encrypting messages.
|
||||||
Un profil n’est présent que sur votre appareil/vos appareils et utilise le serveur seulement pour relayer les messages vers vos contacts.</p>
|
A profile lives on your device(s) only
|
||||||
|
and uses the server only to relay messages.</p>
|
||||||
|
|
||||||
<p>Lors de la première installation de Delta Chat un premier profil est créé.</p>
|
<p>On first installation of Delta Chat a first profile is created.</p>
|
||||||
|
|
||||||
<p>Par la suite vous pourrez cliquer sur votre image de profil en haut à gauche de l’écran principal pour <strong>Ajouter un profil</strong> ou <strong>Changer de profil</strong>.</p>
|
<p>Later, you can tap your profile image in the upper left corner to <strong>Add Profiles</strong>
|
||||||
|
or to <strong>Switch Profiles</strong>.</p>
|
||||||
|
|
||||||
<p>Vous souhaiterez peut être utiliser des profils différents pour vos activités familiales, professionnelles ou politiques.</p>
|
<p>You may want to use separate profiles for political, family or work related activities.</p>
|
||||||
|
|
||||||
<p>Vous souhaiterez peut être aussi apprendre <a href="#multiclient">comment utiliser le même profil sur plusieurs appareils</a>.</p>
|
<p>You may also wish to learn <a href="#multiclient">how to use the same profile on multiple devices</a>.</p>
|
||||||
|
|
||||||
<h3 id="qui-peut-voir-ma-photo-de-profil-">
|
<h3 id="qui-peut-voir-ma-photo-de-profil-">
|
||||||
|
|
||||||
@@ -247,13 +267,15 @@ Un profil n’est présent que sur votre appareil/vos appareils et utilise le se
|
|||||||
<h3 id="signature">
|
<h3 id="signature">
|
||||||
|
|
||||||
|
|
||||||
Est-il possible de définir une Bio/un Statut avec Delta Chat ? <a href="#signature" class="anchor"></a>
|
Can I set a Bio/Status with Delta Chat? <a href="#signature" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Oui, vous pouvez le faire dans <strong>Paramètres → Profil → Signature</strong>.
|
<p>Yes,
|
||||||
À partir du moment ou vous échangez avec quelqu’un, cette personne pourra voir votre Signature en regardant les détails de votre profil.</p>
|
you can do so under <strong>Settings → Profile → Bio</strong>.
|
||||||
|
Once you sent a message to a contact,
|
||||||
|
they will see it when they view your contact details.</p>
|
||||||
|
|
||||||
<h3 id="que-signifient-épingler-sourdine-et-archiver-">
|
<h3 id="que-signifient-épingler-sourdine-et-archiver-">
|
||||||
|
|
||||||
@@ -287,33 +309,37 @@ pour mettre une discussion en sourdine, ouvrez le menu de la conversation (Andro
|
|||||||
<h3 id="save">
|
<h3 id="save">
|
||||||
|
|
||||||
|
|
||||||
Comment fonctionnent les “Messages enregistrés” ? <a href="#save" class="anchor"></a>
|
How do “Saved Messages” work? <a href="#save" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p><strong>Messages enregistrés</strong> est une discussion que vous pouvez utiliser pour sauvegarder et retrouver facilement des messages.</p>
|
<p><strong>Saved Messages</strong> is a chat that you can use to easily remember and find messages.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Dans n’importe quelle discussion, touchez <img style="vertical-align:middle; width:1.2em; margin:1px;" src="../saved-icon.png" alt="Saved icon" /> ou faites un clic droit sur un message et sélectionnez <strong>Enregistrer</strong>.</p>
|
<p>In any chat, long tap or right click a message and select <strong>Save</strong></p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Les messages enregistrés sont identifiés par le symbole <img style="vertical-align:middle; width:1.2em; margin:1px" src="../saved-icon.png" alt="Saved icon" /> à côté de l’horodatage du message.</p>
|
<p>Saved messages are marked by the symbol
|
||||||
|
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../saved-icon.png" alt="Saved icon" />
|
||||||
|
next to the timestamp</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Par la suite vous pourrez retrouver tous ces messages dans la discussion “Messages enregistrés”.
|
<p>Later, open the “Saved Messages” chat - and you will see the saved messages there.
|
||||||
En touchant <img style="vertical-align:middle; width:1.2em; margin:1px" src="../go-to-original.png" alt="Arrow-right icon" /> vous retrouverez le message dans sa discussion d’origine.</p>
|
By tapping <img style="vertical-align:middle; width:1.2em; margin:1px" src="../go-to-original.png" alt="Arrow-right icon" />,
|
||||||
|
you can go back to the original message in the original chat</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Enfin vous pouvez aussi utiliser la discussion “Messages enregistrés” pour prendre des <strong>notes privées</strong> - ouvrez la discussion, écrivez votre message, ajoutez une photo, un message vocal, etc.</p>
|
<p>Finally, you can also use “Saved Messages” to take <strong>personal notes</strong> - open the chat, type something, add a photo or a voice message etc.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>La discussion “Messages enregistrés” étant synchronisée elle peut être très pratique pour transférer des informations d’un appareil à un autre.</p>
|
<p>As “Saved Message” are synced, they can become very handy for transferring data between devices</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Les messages restent enregistrés même lorsqu’ils sont édités ou supprimés, que ça soit par <a href="#edit">l’expéditeur⋅rice</a>, par <a href="#delold">suppression des anciens messages de l’appareil</a> ou par <a href="#ephemeralmsgs">disparition des messages éphémères au sein d’une discussion</a>.</p>
|
<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>
|
||||||
|
|
||||||
<h3 id="que-signifie-le-point-vert-">
|
<h3 id="que-signifie-le-point-vert-">
|
||||||
|
|
||||||
@@ -323,10 +349,13 @@ En touchant <img style="vertical-align:middle; width:1.2em; margin:1px" src="../
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Vous pourrez parfois voir un <strong>point vert</strong> <img style="vertical-align:middle; width:1.2em; margin:1px" src="../green-dot.png" alt="" /> sur le profil d’un contact.
|
<p>You can sometimes see a <strong>green dot</strong> <img style="vertical-align:middle; width:1.2em; margin:1px" src="../green-dot.png" alt="" />
|
||||||
Cela veut dire que vous avez <strong>récemment vu</strong> le contact dans les 10 dernières minutes, par exemple parce que vous avez échangé avec ce contact, ou que vous avez reçu un accusé de lecture.</p>
|
next to the avatar of a contact.
|
||||||
|
It means they were <strong>recently seen by you</strong> in the last 10 minutes,
|
||||||
|
e.g. because they messaged you or sent a read receipt.</p>
|
||||||
|
|
||||||
<p>Ceci n’est donc pas un indicateur temps réel de présence en ligne et vos contacts ne pourront donc pas toujours voir si vous êtes en ligne ou non.</p>
|
<p>So this is not a real time online status
|
||||||
|
and others will as well not always see that you are “online”.</p>
|
||||||
|
|
||||||
<h3 id="que-signifient-les-coches-affichées-à-côté-des-messages-sortants-">
|
<h3 id="que-signifient-les-coches-affichées-à-côté-des-messages-sortants-">
|
||||||
|
|
||||||
@@ -338,75 +367,79 @@ Cela veut dire que vous avez <strong>récemment vu</strong> le contact dans les
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p><strong>Une marque</strong> <img style="vertical-align:middle; width:1.5em; margin:1px" src="../tick1.png" alt="" /> veut dire que le message a été envoyé correctement au <a href="#relays">relai</a>.</p>
|
<p><strong>One tick</strong> <img style="vertical-align:middle; width:1.5em; margin:1px" src="../tick1.png" alt="" />
|
||||||
|
means that the message was sent successfully to the <a href="#relays">relay</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><strong>Deux marques</strong> <img style="vertical-align:middle; width:1.5em; margin:1px" src="../tick2.png" alt="" /> indiquent que votre contact a lu le message.</p>
|
<p><strong>Two ticks</strong> <img style="vertical-align:middle; width:1.5em; margin:1px" src="../tick2.png" alt="" />
|
||||||
|
indicate your contact has read the message.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Au sein des <a href="#groups">groupes</a> la seconde marque veut dire qu’au moins un membre du groupe a pu lire le message.</p>
|
<p>In <a href="#groups">groups</a> the second tick means that at least one member has reported back having read the message.</p>
|
||||||
|
|
||||||
<p>La seconde marque ne peut s’afficher que si vous et l’un de vos destinataires du message avez activé <strong>Paramètres → Discussions → Accusés de lecture</strong>.</p>
|
<p>You will only get the second tick if both you and one of the recipients who read the message
|
||||||
|
has <strong>Settings → Chats → Read Receipts</strong> enabled.</p>
|
||||||
|
|
||||||
<h3 id="edit">
|
<h3 id="edit">
|
||||||
|
|
||||||
|
|
||||||
Corriger des fautes et supprimer des messages après les avoir envoyés <a href="#edit" class="anchor"></a>
|
Correct typos and delete messages after sending <a href="#edit" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Vous pouvez éditer le texte de votre message après l’avoir envoyé. Pour cela, appuyer longtemps ou faire clic droit sur le message et choisir <strong>Modifier</strong> ou <img style="vertical-align:middle; width:1.2em; margin:1px" src="../edit-icon.png" alt="Edit icon" />.</p>
|
<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>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Si vous avez envoyé un message par erreur vous pouvez le supprimer depuis le même menu en choisissant <strong>Supprimer le message</strong> puis <strong>Supprimer pour moi</strong> ou <strong>Supprimer pour tout le monde</strong>.</p>
|
<p>If you have sent a message accidentally,
|
||||||
|
from the same menu, select <strong>Delete</strong> and then <strong>Delete for Everyone</strong>.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Les messages modifiés seront indiqués par le mot “Modifié” à côté de l’horodatage du message, tandis que les messages supprimés le sont sans notification, ni dans la discussion, ni sur l’appareil, et peuvent l’être sans limite dans le temps.</p>
|
<p>While edited messages will have the word “Edited” next to the timestamp,
|
||||||
|
deleted messages will be removed without a marker in the chat.
|
||||||
|
Notifications are not sent and there is no time limit.</p>
|
||||||
|
|
||||||
<p>Remarque : le message original peut toutefois encore exister s’il a déjà été transféré, enregistré, ou si l’un des membres de la discussion en a fait une copie ou une capture d’écran.</p>
|
<p>Note, that the original message may still be received by chat members
|
||||||
|
who could have already replied, forwarded, saved, screenshotted or otherwise copied the message.</p>
|
||||||
<h3 id="mediaquality">
|
|
||||||
|
|
||||||
|
|
||||||
Comment est gérée la qualité des médias envoyés ? <a href="#mediaquality" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Images, vidéos, fichiers, messages vocaux etc. peuvent être envoyé avec les boutons <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Pièce jointe</strong> ou <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Message vocal</strong>.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Par défaut le niveau de compression choisi permet un <strong>envoi rapide et efficace</strong> des messages en respectant les limites de données et de stockage de tout le monde. C’est un réglage idéal pour des échanges standards.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Dans les régions avec une connectivité limitée il est possible de choisir une compression plus forte dans <strong>Paramètres → Discussions → Qualité du média en sortie</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Si vous souhaitez absolument transmettre un fichier en <strong>qualité originale</strong>, utilisez <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Pièce jointe → Fichier</strong> dans la discussion. Pensez à utiliser cette fonctionnalité avec parcimonie pour limiter l’utilisation des données par toutes les personnes dans la discussion.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="ephemeralmsgs">
|
<h3 id="ephemeralmsgs">
|
||||||
|
|
||||||
|
|
||||||
Comment fonctionnent les messages éphémères ? <a href="#ephemeralmsgs" class="anchor"></a>
|
How do disappearing messages work? <a href="#ephemeralmsgs" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Vous pouvez activer les “Messages éphémères” dans les paramètres d’une discussion, dans le menu en haut à droite, en choisissant une durée prédéfinie entre 5 min et 1 an.</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>Tant que le paramètre reste activé, les applications de chacun des membres se chargent de supprimer les messages qui dépassent la durée définie. La durée est comptabilisée à partir du moment où le message est vu pour la première fois, et le message est supprimé au sein de l’application et sur le serveur.</p>
|
<p>Until the setting is turned off again,
|
||||||
|
each chat member’s Delta Chat app takes care
|
||||||
|
of deleting the messages
|
||||||
|
after the selected time span.
|
||||||
|
The time span begins
|
||||||
|
when the receiver first sees the message in Delta Chat.
|
||||||
|
The messages are deleted both,
|
||||||
|
on the servers,
|
||||||
|
and in the apps itself.</p>
|
||||||
|
|
||||||
<p>Remarque : ne faites confiance au réglage “Messages éphémères” que si vous faites confiance aux membres de la discussion. Des membres mal intentionné⋅es peuvent très bien prendre des photos, copier, sauvegarder, transférer un message avant qu’il ne soit supprimé.</p>
|
<p>Note that you can rely on disappearing messages
|
||||||
|
only as long as you trust your chat partners;
|
||||||
|
malicious chat partners can take photos,
|
||||||
|
or otherwise save, copy or forward messages before deletion.</p>
|
||||||
|
|
||||||
<p>Enfin, si l’un⋅e des membres d’une discussion désinstalle l’application Delta Chat, les messages (chiffrés, pour rappel) peuvent rester plus longtemps sur le serveur avant d’être supprimés.</p>
|
<p>Apart from that,
|
||||||
|
if one chat partner uninstalls Delta Chat,
|
||||||
|
the (anyway encrypted) messages may take longer to get deleted from their server.</p>
|
||||||
|
|
||||||
<h3 id="delold">
|
<h3 id="delold">
|
||||||
|
|
||||||
@@ -423,28 +456,39 @@ Cela veut dire que vous avez <strong>récemment vu</strong> le contact dans les
|
|||||||
<h3 id="remove-account">
|
<h3 id="remove-account">
|
||||||
|
|
||||||
|
|
||||||
Comment puis-je supprimer un profil de discussion ? <a href="#remove-account" class="anchor"></a>
|
How can I delete my chat profile? <a href="#remove-account" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Si vous utilisez plus d’un profil dans l’application, vous pouvez supprimer un profil spécifique via le menu (en haut sur Android et iOS), ou dans la barre latérale (sur l’application de bureau) permettant de passer d’un profil à un autre. Les profils ne sont toujours supprimés que sur l’appareil en question. Les profils continueront donc d’exister sur les autres appareils le cas échéant.</p>
|
<p>If you are using more than one chat profile,
|
||||||
|
you can remove single ones in the top profile switcher menu (on Android and iOS),
|
||||||
|
or in the sidebar with a right click (in the Desktop app).
|
||||||
|
Chat profiles are only removed on the device where deletion was triggered.
|
||||||
|
Chat profiles on other devices will continue to fully function.</p>
|
||||||
|
|
||||||
<p>Si vous n’utilisez qu’un seul profil vous pouvez tout simplement désinstaller l’application. Cela déclenchera la suppression des données liées au profil en question sur le serveur chatmail. Pour plus d’informations voir <a href="https://nine.testrun.org/info.html#account-deletion">Account deletion sur nine.testrun.org</a> ou la page respective du <a href="https://chatmail.at/relays">serveur chatmail</a> que vous utilisez.</p>
|
<p>If you use a single default chat profile you can simply uninstall the app.
|
||||||
|
This will still automatically trigger deletion of all associated address data on the chatmail server.
|
||||||
|
For more info, please refer to <a href="https://nine.testrun.org/info.html#account-deletion">nine.testrun.org address-deletion</a>
|
||||||
|
or the respective page from your chosen <a href="https://chatmail.at/relays">3rd party chatmail server</a>.</p>
|
||||||
|
|
||||||
<h2 id="groups">
|
<h2 id="groups">
|
||||||
|
|
||||||
|
|
||||||
Groupes <a href="#groups" class="anchor"></a>
|
Groups <a href="#groups" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>Les groupes permettent à plusieurs personnes d’avoir une discussion. Chaque membre du groupe à les <strong>même droits</strong>.</p>
|
<p>Groups let several people chat together privately with <strong>equal rights</strong>.</p>
|
||||||
|
|
||||||
<p>Chaque membre du groupe peut changer le nom du groupe ou l’avatar, <a href="#addmembers">ajouter ou supprimer des membres</a>, activer/désactiver <a href="#ephemeralmsgs">les messages éphémères</a>, et <a href="#edit">supprimer leurs propres messages</a> sur tous les appareils des membres de la discussion.</p>
|
<p>Anyone can
|
||||||
|
change the group name or avatar,
|
||||||
|
<a href="#addmembers">add or remove members</a>,
|
||||||
|
set <a href="#ephemeralmsgs">disappearing messages</a>,
|
||||||
|
and <a href="#edit">delete their own messages</a> from all member’s devices.</p>
|
||||||
|
|
||||||
<p>Puisque tous les membres d’une discussion ont les mêmes droits, les groupes fonctionnent mieux avec des <strong>personnes de confiance et la famille</strong>.</p>
|
<p>Because all members have the same rights, groups work best among <strong>trusted friends and family</strong>.</p>
|
||||||
|
|
||||||
<h3 id="création-dun-groupe">
|
<h3 id="création-dun-groupe">
|
||||||
|
|
||||||
@@ -469,7 +513,7 @@ Cela veut dire que vous avez <strong>récemment vu</strong> le contact dans les
|
|||||||
<h3 id="addmembers">
|
<h3 id="addmembers">
|
||||||
|
|
||||||
|
|
||||||
Ajouter et supprimer des membres <a href="#addmembers" class="anchor"></a>
|
Add and remove members <a href="#addmembers" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
@@ -562,197 +606,6 @@ but more than 150 is not recommended.</p>
|
|||||||
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
||||||
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
||||||
|
|
||||||
<h2 id="channels">
|
|
||||||
|
|
||||||
|
|
||||||
Channels <a href="#channels" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Channels are a one-to-many tool for broadcasting messages.</p>
|
|
||||||
|
|
||||||
<h3 id="subscribe-to-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Subscribe to a channel <a href="#subscribe-to-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Scan the <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>QR code</strong>
|
|
||||||
or tap the <strong>invite link</strong> you got from the channel owner.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>That’s all!
|
|
||||||
You will receive a few of the messages from the channel history
|
|
||||||
and, from that point on, all new messages from the channel.</p>
|
|
||||||
|
|
||||||
<p><strong>Don’t worry,</strong> if that does not happen immediately.
|
|
||||||
Once the channel owner comes online, your join request will be processed.</p>
|
|
||||||
|
|
||||||
<p>As all of Delta Chat, also Channels are private and decentralized,
|
|
||||||
there is no public discovery.</p>
|
|
||||||
|
|
||||||
<p>Other channel subscribers will not see that you subscribed and cannot message you.
|
|
||||||
The channel owner, however, can message you.
|
|
||||||
They will also see that you read a message unless you have read receipts disabled.</p>
|
|
||||||
|
|
||||||
<p>If you do not want to share your main profile,
|
|
||||||
you can also create a <a href="#multiple-accounts">dedicated profile</a> for joining a channel.</p>
|
|
||||||
|
|
||||||
<h3 id="create-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Create a channel <a href="#create-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>New Chat</strong> and choose <strong>New Channel</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Enter a <strong>name</strong>, optionally set an <strong>image</strong> and <strong>description</strong>, and hit the <strong>Create</strong> button.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can now send and manage messages as usual.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>From the channel’s profile, <strong>share the QR code or invite link with others</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Subscribers will receive your messages,
|
|
||||||
but they cannot send messages in your channel.
|
|
||||||
When subscribing, they will receive <strong>a few of the latest messages of the channel history</strong>.</p>
|
|
||||||
|
|
||||||
<p>You can see the <strong>view count</strong> beside each message.
|
|
||||||
Note that this only counts subscribers who have read receipts enabled,
|
|
||||||
so the real view count may be larger.</p>
|
|
||||||
|
|
||||||
<h3 id="how-many-subscribers-can-a-channel-have">
|
|
||||||
|
|
||||||
|
|
||||||
How many subscribers can a channel have? <a href="#how-many-subscribers-can-a-channel-have" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Channels are designed for much larger audiences than <a href="#groups">groups</a>.</p>
|
|
||||||
|
|
||||||
<p>The practical limit depends on the used <a href="#relays">relay</a>,
|
|
||||||
so there is no single fixed number that applies everywhere.</p>
|
|
||||||
|
|
||||||
<p>For really large channels with several tens of thousands of subscribers,
|
|
||||||
we recommend using a <a href="#multiple-accounts">dedicated profile</a> for the channel
|
|
||||||
and checking whether the relay is suitable.</p>
|
|
||||||
|
|
||||||
<p>But don’t be too hesitant: Delta Chat is designed to be relay-agnostic,
|
|
||||||
so you can change your relay at any point easily -
|
|
||||||
your existing subscribers will not even notice.
|
|
||||||
You only have to update the invite link you share with new subscribers in that case.</p>
|
|
||||||
|
|
||||||
<h2 id="calls">
|
|
||||||
|
|
||||||
|
|
||||||
Calls <a href="#calls" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Delta Chat supports one-to-one <strong>audio calls</strong> and <strong>video calls</strong>.</p>
|
|
||||||
|
|
||||||
<p>Calls are supported on Desktop, Ubuntu Touch, iOS and Android 8 and newer.</p>
|
|
||||||
|
|
||||||
<h3 id="place-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Place a call <a href="#place-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>In a one-to-one chat, tap the 📞 <strong>call icon</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>This opens a small menu
|
|
||||||
where you can choose whether to place an <strong>Audio Call</strong> or a <strong>Video Call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="accept-or-reject-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Accept or reject a call <a href="#accept-or-reject-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>When someone calls you,
|
|
||||||
Delta Chat shows an <strong>incoming call screen</strong> or notification.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>Accept</strong> to answer
|
|
||||||
or <strong>Decline</strong> to reject the call.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="during-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
During a call <a href="#during-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>mute</strong> your microphone.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>enable or disable your camera</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>On mobile, you can <strong>switch between front and back cameras</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Depending on the device, you can also select the audio output or use picture-in-picture.
|
|
||||||
On desktop, the call is using a dedicated window
|
|
||||||
and you can continue using the main Delta Chat window as usual.</p>
|
|
||||||
|
|
||||||
<h3 id="missed-calls-and-notifications">
|
|
||||||
|
|
||||||
|
|
||||||
Missed calls and notifications <a href="#missed-calls-and-notifications" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>If you do not answer, do not hear the ringing, or do not have your device at hand,
|
|
||||||
the call appears as a <strong>missed call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><strong>Only your accepted contacts</strong> can make your device ring.
|
|
||||||
Contact requests will appear as usual and will not ring.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>At <strong>Settings → Notifications → Calls</strong>,
|
|
||||||
you can disable the special call ringing screen completely.
|
|
||||||
If you do so, you will not be disturbed by any ringing notification,
|
|
||||||
you can still pick up the call by tapping the incoming call message bubble in its chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="webxdc">
|
<h2 id="webxdc">
|
||||||
|
|
||||||
|
|
||||||
@@ -1163,26 +1016,22 @@ Relays are operated by different groups and people.</p>
|
|||||||
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
||||||
so you do not need to care about that.
|
so you do not need to care about that.
|
||||||
However, if you want to,
|
However, if you want to,
|
||||||
you can configure relays at <strong>Settings → Advanced → Relays</strong>:</p>
|
you can configure relays at At <strong>Settings → Advanced → Relays</strong>:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
||||||
<a href="https://chatmail.at/relays">chatmail.at/relays</a> shows some known ones.
|
<a href="https://chatmail.at/relays">https://chatmail.at/relays</a> shows some known ones.
|
||||||
If you have multiple relays, you will receive messages on all of them.
|
If you have multiple relays, you will receive messages on all of them.</p>
|
||||||
Contacts learn your current relays automatically when you message them.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Tap on a relay to set it as <strong>used for sending</strong>.</p>
|
<p>The <strong>default</strong> defines the one where your chat partners send future messages to.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>If you <strong>remove</strong> a relay,
|
<p>If you <strong>remove</strong> a relay,
|
||||||
contacts who only know this relay may not reach you until you message them again.
|
make sure another default relay was used for a sufficient amount of time.
|
||||||
To stay reachable in the meantime, choose <strong>Hide from Contacts</strong> in the confirmation dialog
|
Otherwise, messages from your chat partners won’t reach you.
|
||||||
instead of removing it right away.</p>
|
If in doubt, remove later.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>To <strong>show</strong> a hidden relay again, tap on it.</p>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -1326,9 +1175,6 @@ to exchange encryption setup information through QR-code scanning or “invite l
|
|||||||
<p><a href="https://autocrypt.org">Autocrypt</a> is used for automatically
|
<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>
|
establishing end-to-end encryption between contacts and all members of a group chat.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, qui est prévu pour 2026, amènera un chiffrement avec résistance post-quantique ainsi que la confidentialité persistante (“forward secrecy”).</p>
|
|
||||||
</li>
|
|
||||||
<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
|
<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>
|
chat</a>
|
||||||
@@ -1512,10 +1358,12 @@ Instead, all group metadata is end-to-end encrypted and stored on end-user devic
|
|||||||
<p>Servers can therefore only see:</p>
|
<p>Servers can therefore only see:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Sender and receiver addresses, randomly generated by default</li>
|
<li>the sender and receiver addresses</li>
|
||||||
<li>Message size</li>
|
<li>and the message size.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>By default, the addresses are randomly generated.</p>
|
||||||
|
|
||||||
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
||||||
|
|
||||||
<h3 id="device-seizure">
|
<h3 id="device-seizure">
|
||||||
@@ -1544,20 +1392,23 @@ can not be identified easily.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>The used <a href="#relays">relays</a> need to know your IP Address,
|
<p>The used <a href="#relays">relay</a> needs to know your IP Address,
|
||||||
as well as sometimes your contact’s devices if you have a <a href="#calls">call</a>
|
as well as sometimes your contact’s devices if you have a <a href="#experiments">call</a>
|
||||||
or use <a href="#webxdc">apps</a> together.</p>
|
or use <a href="#webxdc">apps</a> together.</p>
|
||||||
|
|
||||||
<p>IP Addresses are needed for connectivity and efficiency.
|
<p>IP Addresses are needed for connectivity and efficiency.
|
||||||
Delta Chat neither persists nor exposes them.
|
They are neither persisted nor exposed.
|
||||||
Note that IP Addresses
|
Note that the IP Address
|
||||||
are not like an address you give to a delivery service,
|
is not like a detailed address you give to a delivery service,
|
||||||
but typically less precise, often defining city or region only.</p>
|
but much more coarse, often defining region or country only.</p>
|
||||||
|
|
||||||
<p>If you see your IP Address as a risk,
|
<p>As this is just how the internet and other messengers work by default,
|
||||||
we recommend to use a VPN for the whole system.
|
we do not offer options here or ask upfront questions.</p>
|
||||||
Per-app options leave gaps across your system.
|
|
||||||
For example, tapping a link can expose IP Addresses to unknown parties, which is by far the larger risk.</p>
|
<p>If you see your IP Address as a security or privacy risk,
|
||||||
|
we recommend to use a VPN, in combination with system lockdown mode.
|
||||||
|
Hunting down options in all apps on your system will leave gaps.
|
||||||
|
For example, tapping a link exposes IP Addresses to unknown parties and is the by far larger risk here.</p>
|
||||||
|
|
||||||
<h3 id="sealedsender">
|
<h3 id="sealedsender">
|
||||||
|
|
||||||
@@ -1567,7 +1418,7 @@ For example, tapping a link can expose IP Addresses to unknown parties, which is
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Non, pas encore.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p>The Signal messenger introduced <a href="https://signal.org/blog/sealed-sender/">“Sealed Sender” in 2018</a>
|
<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.
|
to keep their server infrastructure ignorant of who is sending a message to a set of recipients.
|
||||||
@@ -1588,7 +1439,7 @@ but an implementation has not been agreed as a priority yet.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Pas encore mais cela arrive avec <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||||
This means that if your private decryption key is leaked,
|
This means that if your private decryption key is leaked,
|
||||||
@@ -1599,8 +1450,12 @@ Otherwise, someone obtaining your decryption keys
|
|||||||
is typically also able to get all your non-deleted messages
|
is typically also able to get all your non-deleted messages
|
||||||
and doesn’t even need to decrypt any previously collected messages.</p>
|
and doesn’t even need to decrypt any previously collected messages.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, prévu pour 2026, permettra la suppression fiable (forward secrecy) grâce à une rotation automatique des clefs.
|
<p>We designed a Forward Secrecy approach that withstood
|
||||||
Cette approche est détaillée dans le brouillon du <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">certificat Autocrypt v2 OpenPGP</a>.</p>
|
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>
|
||||||
|
|
||||||
<h3 id="pqc">
|
<h3 id="pqc">
|
||||||
|
|
||||||
@@ -1610,11 +1465,12 @@ Cette approche est détaillée dans le brouillon du <a href="https://datatracke
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Pas encore mais cela arrive avec <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, prévu pour 2026, amènera un chiffrement avec résistance post-quantique pour protéger contre les attaques effectuées par des ordinateurs quantiques.
|
<p>Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||||
Delta Chat utilise la librairie Rust OpenPGP <a href="https://github.com/rpgp/rpgp">rPGP</a> qui supporte les dernières <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
||||||
L’implémentation est détaillée dans le brouillon du <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">certificat Autocrypt v2 OpenPGP</a>.</p>
|
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>
|
||||||
|
|
||||||
<h3 id="how-can-i-manually-check-encryption-information">
|
<h3 id="how-can-i-manually-check-encryption-information">
|
||||||
|
|
||||||
@@ -1686,7 +1542,7 @@ research paper published afterwards.</p>
|
|||||||
Vous trouverez <a href="https://delta.chat/en/2023-05-22-webxdc-security">ici un article de fond complet à propos de la sécurité du chiffrement de bout-en-bout sur internet</a>.</p>
|
Vous trouverez <a href="https://delta.chat/en/2023-05-22-webxdc-security">ici un article de fond complet à propos de la sécurité du chiffrement de bout-en-bout sur internet</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Début 2023, <a href="https://cure53.de">Cure53</a> a analysé le chiffrement d’acheminement des connexions réseau de Delta Chat et testé une configuration de serveur de courriel reproductible, telle que <a href="https://delta.chat/serverguide">recommandée sur ce site</a>.
|
<p>Début 2023, <a href="https://cure53.de">Cure53</a> a analysé le chiffrement d’acheminement des connexions réseau de Delta Chat et testé une configuration de serveur de courriel reproductible, telle que <a href="https://delta.chat/fr/serverguide">recommandée sur ce site</a>.
|
||||||
Vous trouverez plus d’informations sur cet audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">sur notre blog</a> ou dans <a href="https://delta.chat/assets/blog/MER-01-report.pdf">le rapport complet ici</a>.</p>
|
Vous trouverez plus d’informations sur cet audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">sur notre blog</a> ou dans <a href="https://delta.chat/assets/blog/MER-01-report.pdf">le rapport complet ici</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
||||||
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
||||||
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
||||||
|
<li><a href="#apakah-delta-chat-mendukung-gambar-vidio-dan-lampiran-lainnya">Apakah Delta Chat mendukung gambar, vidio dan lampiran lainnya?</a></li>
|
||||||
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
||||||
<li><a href="#siapa-yang-dapat-melihat-foto-profil-saya">Siapa yang dapat melihat Foto Profil saya?</a></li>
|
<li><a href="#siapa-yang-dapat-melihat-foto-profil-saya">Siapa yang dapat melihat Foto Profil saya?</a></li>
|
||||||
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
<li><a href="#what-does-the-green-dot-mean">What does the green dot mean?</a></li>
|
<li><a href="#what-does-the-green-dot-mean">What does the green dot mean?</a></li>
|
||||||
<li><a href="#what-do-the-ticks-shown-beside-outgoing-messages-mean">What do the ticks shown beside outgoing messages mean?</a></li>
|
<li><a href="#what-do-the-ticks-shown-beside-outgoing-messages-mean">What do the ticks shown beside outgoing messages mean?</a></li>
|
||||||
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
||||||
<li><a href="#mediaquality">How is media quality handled?</a></li>
|
|
||||||
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
||||||
<li><a href="#delold">What happens if I turn on “Delete Messages from Device”?</a></li>
|
<li><a href="#delold">What happens if I turn on “Delete Messages from Device”?</a></li>
|
||||||
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
||||||
@@ -29,21 +29,6 @@
|
|||||||
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#channels">Channels</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#subscribe-to-a-channel">Subscribe to a channel</a></li>
|
|
||||||
<li><a href="#create-a-channel">Create a channel</a></li>
|
|
||||||
<li><a href="#how-many-subscribers-can-a-channel-have">How many subscribers can a channel have?</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#calls">Calls</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#place-a-call">Place a call</a></li>
|
|
||||||
<li><a href="#accept-or-reject-a-call">Accept or reject a call</a></li>
|
|
||||||
<li><a href="#during-a-call">During a call</a></li>
|
|
||||||
<li><a href="#missed-calls-and-notifications">Missed calls and notifications</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#webxdc">In-chat apps</a>
|
<li><a href="#webxdc">In-chat apps</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
||||||
@@ -233,6 +218,19 @@ You can also add a little introduction message.</p>
|
|||||||
<p>The second contact will receive a <strong>card</strong> then
|
<p>The second contact will receive a <strong>card</strong> then
|
||||||
and can tap it to start chatting with the first contact.</p>
|
and can tap it to start chatting with the first contact.</p>
|
||||||
|
|
||||||
|
<h3 id="apakah-delta-chat-mendukung-gambar-vidio-dan-lampiran-lainnya">
|
||||||
|
|
||||||
|
|
||||||
|
Apakah Delta Chat mendukung gambar, vidio dan lampiran lainnya? <a href="#apakah-delta-chat-mendukung-gambar-vidio-dan-lampiran-lainnya" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Yes. Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment-</strong>
|
||||||
|
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons</p>
|
||||||
|
|
||||||
|
<p>For performance, images are optimized and sent at a smaller size by default, but you can send it as a “file” to preserve the original.</p>
|
||||||
|
|
||||||
<h3 id="multiple-accounts">
|
<h3 id="multiple-accounts">
|
||||||
|
|
||||||
|
|
||||||
@@ -413,32 +411,6 @@ Notifications are not sent and there is no time limit.</p>
|
|||||||
<p>Note, that the original message may still be received by chat members
|
<p>Note, that the original message may still be received by chat members
|
||||||
who could have already replied, forwarded, saved, screenshotted or otherwise copied the message.</p>
|
who could have already replied, forwarded, saved, screenshotted or otherwise copied the message.</p>
|
||||||
|
|
||||||
<h3 id="mediaquality">
|
|
||||||
|
|
||||||
|
|
||||||
How is media quality handled? <a href="#mediaquality" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach-</strong>
|
|
||||||
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>By default, compression ensures <strong>fast, efficient delivery</strong> that respects everyone’s data limits and storage.
|
|
||||||
This is ideal for everyday communication.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>In regions with worse connectivity,
|
|
||||||
you can choose higher compression at <strong>Settings → Chats → Outgoing Media Quality</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>If you specifically need to send media in its <strong>original quality</strong>, use <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach → File</strong> in the chat.
|
|
||||||
Please use this method sparingly, as sending original files will significantly increase data usage for you and all recipients in the chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="ephemeralmsgs">
|
<h3 id="ephemeralmsgs">
|
||||||
|
|
||||||
|
|
||||||
@@ -642,197 +614,6 @@ but more than 150 is not recommended.</p>
|
|||||||
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
||||||
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
||||||
|
|
||||||
<h2 id="channels">
|
|
||||||
|
|
||||||
|
|
||||||
Channels <a href="#channels" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Channels are a one-to-many tool for broadcasting messages.</p>
|
|
||||||
|
|
||||||
<h3 id="subscribe-to-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Subscribe to a channel <a href="#subscribe-to-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Scan the <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>QR code</strong>
|
|
||||||
or tap the <strong>invite link</strong> you got from the channel owner.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>That’s all!
|
|
||||||
You will receive a few of the messages from the channel history
|
|
||||||
and, from that point on, all new messages from the channel.</p>
|
|
||||||
|
|
||||||
<p><strong>Don’t worry,</strong> if that does not happen immediately.
|
|
||||||
Once the channel owner comes online, your join request will be processed.</p>
|
|
||||||
|
|
||||||
<p>As all of Delta Chat, also Channels are private and decentralized,
|
|
||||||
there is no public discovery.</p>
|
|
||||||
|
|
||||||
<p>Other channel subscribers will not see that you subscribed and cannot message you.
|
|
||||||
The channel owner, however, can message you.
|
|
||||||
They will also see that you read a message unless you have read receipts disabled.</p>
|
|
||||||
|
|
||||||
<p>If you do not want to share your main profile,
|
|
||||||
you can also create a <a href="#multiple-accounts">dedicated profile</a> for joining a channel.</p>
|
|
||||||
|
|
||||||
<h3 id="create-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Create a channel <a href="#create-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>New Chat</strong> and choose <strong>New Channel</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Enter a <strong>name</strong>, optionally set an <strong>image</strong> and <strong>description</strong>, and hit the <strong>Create</strong> button.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can now send and manage messages as usual.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>From the channel’s profile, <strong>share the QR code or invite link with others</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Subscribers will receive your messages,
|
|
||||||
but they cannot send messages in your channel.
|
|
||||||
When subscribing, they will receive <strong>a few of the latest messages of the channel history</strong>.</p>
|
|
||||||
|
|
||||||
<p>You can see the <strong>view count</strong> beside each message.
|
|
||||||
Note that this only counts subscribers who have read receipts enabled,
|
|
||||||
so the real view count may be larger.</p>
|
|
||||||
|
|
||||||
<h3 id="how-many-subscribers-can-a-channel-have">
|
|
||||||
|
|
||||||
|
|
||||||
How many subscribers can a channel have? <a href="#how-many-subscribers-can-a-channel-have" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Channels are designed for much larger audiences than <a href="#groups">groups</a>.</p>
|
|
||||||
|
|
||||||
<p>The practical limit depends on the used <a href="#relays">relay</a>,
|
|
||||||
so there is no single fixed number that applies everywhere.</p>
|
|
||||||
|
|
||||||
<p>For really large channels with several tens of thousands of subscribers,
|
|
||||||
we recommend using a <a href="#multiple-accounts">dedicated profile</a> for the channel
|
|
||||||
and checking whether the relay is suitable.</p>
|
|
||||||
|
|
||||||
<p>But don’t be too hesitant: Delta Chat is designed to be relay-agnostic,
|
|
||||||
so you can change your relay at any point easily -
|
|
||||||
your existing subscribers will not even notice.
|
|
||||||
You only have to update the invite link you share with new subscribers in that case.</p>
|
|
||||||
|
|
||||||
<h2 id="calls">
|
|
||||||
|
|
||||||
|
|
||||||
Calls <a href="#calls" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Delta Chat supports one-to-one <strong>audio calls</strong> and <strong>video calls</strong>.</p>
|
|
||||||
|
|
||||||
<p>Calls are supported on Desktop, Ubuntu Touch, iOS and Android 8 and newer.</p>
|
|
||||||
|
|
||||||
<h3 id="place-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Place a call <a href="#place-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>In a one-to-one chat, tap the 📞 <strong>call icon</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>This opens a small menu
|
|
||||||
where you can choose whether to place an <strong>Audio Call</strong> or a <strong>Video Call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="accept-or-reject-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Accept or reject a call <a href="#accept-or-reject-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>When someone calls you,
|
|
||||||
Delta Chat shows an <strong>incoming call screen</strong> or notification.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>Accept</strong> to answer
|
|
||||||
or <strong>Decline</strong> to reject the call.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="during-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
During a call <a href="#during-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>mute</strong> your microphone.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>enable or disable your camera</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>On mobile, you can <strong>switch between front and back cameras</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Depending on the device, you can also select the audio output or use picture-in-picture.
|
|
||||||
On desktop, the call is using a dedicated window
|
|
||||||
and you can continue using the main Delta Chat window as usual.</p>
|
|
||||||
|
|
||||||
<h3 id="missed-calls-and-notifications">
|
|
||||||
|
|
||||||
|
|
||||||
Missed calls and notifications <a href="#missed-calls-and-notifications" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>If you do not answer, do not hear the ringing, or do not have your device at hand,
|
|
||||||
the call appears as a <strong>missed call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><strong>Only your accepted contacts</strong> can make your device ring.
|
|
||||||
Contact requests will appear as usual and will not ring.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>At <strong>Settings → Notifications → Calls</strong>,
|
|
||||||
you can disable the special call ringing screen completely.
|
|
||||||
If you do so, you will not be disturbed by any ringing notification,
|
|
||||||
you can still pick up the call by tapping the incoming call message bubble in its chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="webxdc">
|
<h2 id="webxdc">
|
||||||
|
|
||||||
|
|
||||||
@@ -1249,26 +1030,22 @@ Relays are operated by different groups and people.</p>
|
|||||||
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
||||||
so you do not need to care about that.
|
so you do not need to care about that.
|
||||||
However, if you want to,
|
However, if you want to,
|
||||||
you can configure relays at <strong>Settings → Advanced → Relays</strong>:</p>
|
you can configure relays at At <strong>Settings → Advanced → Relays</strong>:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
||||||
<a href="https://chatmail.at/relays">chatmail.at/relays</a> shows some known ones.
|
<a href="https://chatmail.at/relays">https://chatmail.at/relays</a> shows some known ones.
|
||||||
If you have multiple relays, you will receive messages on all of them.
|
If you have multiple relays, you will receive messages on all of them.</p>
|
||||||
Contacts learn your current relays automatically when you message them.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Tap on a relay to set it as <strong>used for sending</strong>.</p>
|
<p>The <strong>default</strong> defines the one where your chat partners send future messages to.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>If you <strong>remove</strong> a relay,
|
<p>If you <strong>remove</strong> a relay,
|
||||||
contacts who only know this relay may not reach you until you message them again.
|
make sure another default relay was used for a sufficient amount of time.
|
||||||
To stay reachable in the meantime, choose <strong>Hide from Contacts</strong> in the confirmation dialog
|
Otherwise, messages from your chat partners won’t reach you.
|
||||||
instead of removing it right away.</p>
|
If in doubt, remove later.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>To <strong>show</strong> a hidden relay again, tap on it.</p>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -1411,10 +1188,6 @@ to exchange encryption setup information through QR-code scanning or “invite l
|
|||||||
<li>
|
<li>
|
||||||
<p><a href="https://autocrypt.org">Autocrypt</a> is used for automatically
|
<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>
|
establishing end-to-end encryption between contacts and all members of a group chat.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
|
||||||
will bring post-quantum resistant encryption and forward secrecy.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<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
|
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Sharing a contact to a
|
||||||
@@ -1599,10 +1372,12 @@ Instead, all group metadata is end-to-end encrypted and stored on end-user devic
|
|||||||
<p>Servers can therefore only see:</p>
|
<p>Servers can therefore only see:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Sender and receiver addresses, randomly generated by default</li>
|
<li>the sender and receiver addresses</li>
|
||||||
<li>Message size</li>
|
<li>and the message size.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>By default, the addresses are randomly generated.</p>
|
||||||
|
|
||||||
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
||||||
|
|
||||||
<h3 id="device-seizure">
|
<h3 id="device-seizure">
|
||||||
@@ -1631,20 +1406,23 @@ can not be identified easily.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>The used <a href="#relays">relays</a> need to know your IP Address,
|
<p>The used <a href="#relays">relay</a> needs to know your IP Address,
|
||||||
as well as sometimes your contact’s devices if you have a <a href="#calls">call</a>
|
as well as sometimes your contact’s devices if you have a <a href="#experiments">call</a>
|
||||||
or use <a href="#webxdc">apps</a> together.</p>
|
or use <a href="#webxdc">apps</a> together.</p>
|
||||||
|
|
||||||
<p>IP Addresses are needed for connectivity and efficiency.
|
<p>IP Addresses are needed for connectivity and efficiency.
|
||||||
Delta Chat neither persists nor exposes them.
|
They are neither persisted nor exposed.
|
||||||
Note that IP Addresses
|
Note that the IP Address
|
||||||
are not like an address you give to a delivery service,
|
is not like a detailed address you give to a delivery service,
|
||||||
but typically less precise, often defining city or region only.</p>
|
but much more coarse, often defining region or country only.</p>
|
||||||
|
|
||||||
<p>If you see your IP Address as a risk,
|
<p>As this is just how the internet and other messengers work by default,
|
||||||
we recommend to use a VPN for the whole system.
|
we do not offer options here or ask upfront questions.</p>
|
||||||
Per-app options leave gaps across your system.
|
|
||||||
For example, tapping a link can expose IP Addresses to unknown parties, which is by far the larger risk.</p>
|
<p>If you see your IP Address as a security or privacy risk,
|
||||||
|
we recommend to use a VPN, in combination with system lockdown mode.
|
||||||
|
Hunting down options in all apps on your system will leave gaps.
|
||||||
|
For example, tapping a link exposes IP Addresses to unknown parties and is the by far larger risk here.</p>
|
||||||
|
|
||||||
<h3 id="sealedsender">
|
<h3 id="sealedsender">
|
||||||
|
|
||||||
@@ -1675,7 +1453,7 @@ but an implementation has not been agreed as a priority yet.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||||
This means that if your private decryption key is leaked,
|
This means that if your private decryption key is leaked,
|
||||||
@@ -1686,9 +1464,12 @@ Otherwise, someone obtaining your decryption keys
|
|||||||
is typically also able to get all your non-deleted messages
|
is typically also able to get all your non-deleted messages
|
||||||
and doesn’t even need to decrypt any previously collected messages.</p>
|
and doesn’t even need to decrypt any previously collected messages.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>We designed a Forward Secrecy approach that withstood
|
||||||
will provide reliable deletion (forward secrecy) through automatic key rotation.
|
initial examination from some cryptographers and implementation experts
|
||||||
This approach is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
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>
|
||||||
|
|
||||||
<h3 id="pqc">
|
<h3 id="pqc">
|
||||||
|
|
||||||
@@ -1698,13 +1479,12 @@ This approach is specified in the <a href="https://datatracker.ietf.org/doc/draf
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||||
will bring post-quantum resistant encryption to protect against quantum computer attacks.
|
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
||||||
Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</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
|
||||||
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
in collaboration with other OpenPGP implementers.</p>
|
||||||
The implementation is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
|
||||||
|
|
||||||
<h3 id="how-can-i-manually-check-encryption-information">
|
<h3 id="how-can-i-manually-check-encryption-information">
|
||||||
|
|
||||||
@@ -1781,7 +1561,7 @@ See <a href="https://delta.chat/en/2023-05-22-webxdc-security">here for the full
|
|||||||
<li>
|
<li>
|
||||||
<p>2023 March, <a href="https://cure53.de">Cure53</a> analyzed both the transport encryption of
|
<p>2023 March, <a href="https://cure53.de">Cure53</a> analyzed both the transport encryption of
|
||||||
Delta Chat’s network connections and a reproducible mail server setup as
|
Delta Chat’s network connections and a reproducible mail server setup as
|
||||||
<a href="https://delta.chat/serverguide">recommended on this site</a>.
|
<a href="https://delta.chat/id/serverguide">recommended on this site</a>.
|
||||||
You can read more about the audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">on our blog</a>
|
You can read more about the audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">on our blog</a>
|
||||||
or read the <a href="https://delta.chat/assets/blog/MER-01-report.pdf">full report here</a>.</p>
|
or read the <a href="https://delta.chat/assets/blog/MER-01-report.pdf">full report here</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<li><a href="#howtoe2ee">Come posso trovare persone con cui chattare?</a></li>
|
<li><a href="#howtoe2ee">Come posso trovare persone con cui chattare?</a></li>
|
||||||
<li><a href="#perché-una-chat-è-contrassegnata-come-richiesta">Perché una chat è contrassegnata come “Richiesta”?</a></li>
|
<li><a href="#perché-una-chat-è-contrassegnata-come-richiesta">Perché una chat è contrassegnata come “Richiesta”?</a></li>
|
||||||
<li><a href="#come-posso-mettere-in-contatto-due-miei-amici">Come posso mettere in contatto due miei amici?</a></li>
|
<li><a href="#come-posso-mettere-in-contatto-due-miei-amici">Come posso mettere in contatto due miei amici?</a></li>
|
||||||
|
<li><a href="#delta-chat-supporta-immagini-video-e-altri-allegati">Delta Chat supporta immagini, video e altri allegati?</a></li>
|
||||||
<li><a href="#multiple-accounts">Cosa sono i profili? Come posso passare dall’uno all’altro?</a></li>
|
<li><a href="#multiple-accounts">Cosa sono i profili? Come posso passare dall’uno all’altro?</a></li>
|
||||||
<li><a href="#chi-vede-la-mia-immagine-del-profilo">Chi vede la mia immagine del profilo?</a></li>
|
<li><a href="#chi-vede-la-mia-immagine-del-profilo">Chi vede la mia immagine del profilo?</a></li>
|
||||||
<li><a href="#signature">Posso impostare una Biografia/Stato con Delta Chat?</a></li>
|
<li><a href="#signature">Posso impostare una Biografia/Stato con Delta Chat?</a></li>
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
<li><a href="#cosa-significa-il-punto-verde">Cosa significa il punto verde?</a></li>
|
<li><a href="#cosa-significa-il-punto-verde">Cosa significa il punto verde?</a></li>
|
||||||
<li><a href="#cosa-significano-i-segni-di-spunta-visualizzati-accanto-ai-messaggi-in-uscita">Cosa significano i segni di spunta visualizzati accanto ai messaggi in uscita?</a></li>
|
<li><a href="#cosa-significano-i-segni-di-spunta-visualizzati-accanto-ai-messaggi-in-uscita">Cosa significano i segni di spunta visualizzati accanto ai messaggi in uscita?</a></li>
|
||||||
<li><a href="#edit">Correggi gli errori e cancella i messaggi dopo averli inviati</a></li>
|
<li><a href="#edit">Correggi gli errori e cancella i messaggi dopo averli inviati</a></li>
|
||||||
<li><a href="#mediaquality">Come viene gestita la qualità dei media?</a></li>
|
|
||||||
<li><a href="#ephemeralmsgs">Come funzionano i messaggi a scomparsa?</a></li>
|
<li><a href="#ephemeralmsgs">Come funzionano i messaggi a scomparsa?</a></li>
|
||||||
<li><a href="#delold">Cosa succede se attivo “Elimina Messaggi dal Dispositivo”?</a></li>
|
<li><a href="#delold">Cosa succede se attivo “Elimina Messaggi dal Dispositivo”?</a></li>
|
||||||
<li><a href="#remove-account">Come posso eliminare il mio profilo chat?</a></li>
|
<li><a href="#remove-account">Come posso eliminare il mio profilo chat?</a></li>
|
||||||
@@ -29,21 +29,6 @@
|
|||||||
<li><a href="#quanti-membri-possono-partecipare-a-un-singolo-gruppo">Quanti membri possono partecipare a un singolo gruppo?</a></li>
|
<li><a href="#quanti-membri-possono-partecipare-a-un-singolo-gruppo">Quanti membri possono partecipare a un singolo gruppo?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#canali">Canali</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#iscriversi-a-un-canale">Iscriversi a un canale</a></li>
|
|
||||||
<li><a href="#creare-un-canale">Creare un canale</a></li>
|
|
||||||
<li><a href="#quanti-iscritti-può-avere-un-canale">Quanti iscritti può avere un canale?</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#calls">Chiamate</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#place-a-call">Place a call</a></li>
|
|
||||||
<li><a href="#accept-or-reject-a-call">Accept or reject a call</a></li>
|
|
||||||
<li><a href="#during-a-call">During a call</a></li>
|
|
||||||
<li><a href="#missed-calls-and-notifications">Missed calls and notifications</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#webxdc">Apps in chat</a>
|
<li><a href="#webxdc">Apps in chat</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#dove-posso-trovare-le-apps-in-chat">Dove posso trovare le apps in chat?</a></li>
|
<li><a href="#dove-posso-trovare-le-apps-in-chat">Dove posso trovare le apps in chat?</a></li>
|
||||||
@@ -232,6 +217,19 @@ Puoi anche aggiungere un breve messaggio di presentazione.</p>
|
|||||||
<p>Il secondo contatto riceverà una <strong>scheda</strong>
|
<p>Il secondo contatto riceverà una <strong>scheda</strong>
|
||||||
e potrà toccarla per iniziare a chattare con il primo contatto.</p>
|
e potrà toccarla per iniziare a chattare con il primo contatto.</p>
|
||||||
|
|
||||||
|
<h3 id="delta-chat-supporta-immagini-video-e-altri-allegati">
|
||||||
|
|
||||||
|
|
||||||
|
Delta Chat supporta immagini, video e altri allegati? <a href="#delta-chat-supporta-immagini-video-e-altri-allegati" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Sì. Immagini, video, files, messaggi vocali ecc. possono essere inviati utilizzando <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Allegato-</strong>
|
||||||
|
o <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> pulsanti <strong>Messaggio Vocale</strong></p>
|
||||||
|
|
||||||
|
<p>Per le prestazioni, le immagini sono ottimizzate e inviate in dimensioni inferiori per impostazione predefinita, ma è possibile inviarle come “file” per preservare l’originale.</p>
|
||||||
|
|
||||||
<h3 id="multiple-accounts">
|
<h3 id="multiple-accounts">
|
||||||
|
|
||||||
|
|
||||||
@@ -411,32 +409,6 @@ Non vengono inviate notifiche e non c’è limite di tempo.</p>
|
|||||||
<p>Nota che il messaggio originale potrebbe essere ancora sui dispositivi dei membri della chat
|
<p>Nota che il messaggio originale potrebbe essere ancora sui dispositivi dei membri della chat
|
||||||
che avrebbero già potuto rispondere, inoltrare, salvare, scattare una schermata o copiare il messaggio in altri modi.</p>
|
che avrebbero già potuto rispondere, inoltrare, salvare, scattare una schermata o copiare il messaggio in altri modi.</p>
|
||||||
|
|
||||||
<h3 id="mediaquality">
|
|
||||||
|
|
||||||
|
|
||||||
Come viene gestita la qualità dei media? <a href="#mediaquality" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Immagini, video, files, messaggi vocali ecc. possono essere inviati utilizzando <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Allegato-</strong>
|
|
||||||
o <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> pulsanti <strong>Messaggio Vocale</strong></p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Per impostazione predefinita, la compressione garantisce una <strong>consegna rapida ed efficiente</strong> che rispetta i limiti di dati e di spazio di archiviazione di tutti.
|
|
||||||
Questa soluzione è ideale per la comunicazione quotidiana.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Nelle regioni con connettività peggiore,
|
|
||||||
è possibile scegliere una compressione più elevata in <strong>Impostazioni → Chat → Qualità Media in Uscita</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Se hai bisogno di inviare i file multimediali nella loro <strong>qualità originale</strong>, usa <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Allega → File</strong> nella chat.
|
|
||||||
Si prega di utilizzare questo metodo con parsimonia, poiché l’invio di file originali aumenterà significativamente il consumo di dati per te e per tutti i destinatari della chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="ephemeralmsgs">
|
<h3 id="ephemeralmsgs">
|
||||||
|
|
||||||
|
|
||||||
@@ -635,196 +607,6 @@ ma non è consigliabile superare i 150.</p>
|
|||||||
dove Delta Chat è un servizio di messaggistica privato per chattare con <a href="#groups">uguali diritti</a>.
|
dove Delta Chat è un servizio di messaggistica privato per chattare con <a href="#groups">uguali diritti</a>.
|
||||||
Vedi <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">numero di Dunbar</a> per ulteriori approfondimenti.</p>
|
Vedi <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">numero di Dunbar</a> per ulteriori approfondimenti.</p>
|
||||||
|
|
||||||
<h2 id="canali">
|
|
||||||
|
|
||||||
|
|
||||||
Canali <a href="#canali" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>I canali sono uno strumento da uno a molti per la trasmissione di messaggi.</p>
|
|
||||||
|
|
||||||
<h3 id="iscriversi-a-un-canale">
|
|
||||||
|
|
||||||
|
|
||||||
Iscriversi a un canale <a href="#iscriversi-a-un-canale" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Scansiona il <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>Codice QR</strong>
|
|
||||||
oppure tocca il <strong>collegamento di invito</strong> che hai ricevuto dal proprietario del canale.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Ecco fatto!
|
|
||||||
Riceverai alcuni dei messaggi dalla cronologia del canale
|
|
||||||
e, da quel momento in poi, tutti i nuovi messaggi dal canale.</p>
|
|
||||||
|
|
||||||
<p><strong>Non preoccuparti,</strong> se non accade immediatamente.
|
|
||||||
Non appena il proprietario del canale si connetterà, la tua richiesta di iscrizione verrà elaborata.</p>
|
|
||||||
|
|
||||||
<p>Poiché tutti i Canali di Delta Chat sono privati e decentralizzati,
|
|
||||||
non esiste una funzione di ricerca pubblica.</p>
|
|
||||||
|
|
||||||
<p>Gli altri iscritti al canale non vedranno che ti sei iscritto e non potranno inviarti messaggi.
|
|
||||||
Il proprietario del canale, tuttavia, potrà inviarti messaggi.
|
|
||||||
Inoltre, vedrà che hai letto un messaggio, a meno che tu non abbia disabilitato le conferme di lettura.</p>
|
|
||||||
|
|
||||||
<p>Se non desideri condividere il tuo profilo principale,
|
|
||||||
puoi anche creare un <a href="#multiple-accounts">profilo dedicato</a> per unirti a un canale.</p>
|
|
||||||
|
|
||||||
<h3 id="creare-un-canale">
|
|
||||||
|
|
||||||
|
|
||||||
Creare un canale <a href="#creare-un-canale" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Tocca <strong>Nuova Chat</strong> e scegli <strong>Nuovo Canale</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Inserisci un <strong>nome</strong>, imposta facoltativamente un’<strong>immagine</strong> e una <strong>descrizione</strong>, e fai clic sul pulsante <strong>Crea</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Ora puoi inviare e gestire i messaggi come di consueto.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Dal profilo del canale, <strong>condividi il codice QR o il collegamento di invito con altri</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Gli iscritti riceveranno i tuoi messaggi,
|
|
||||||
ma non potranno inviare messaggi nel tuo canale.
|
|
||||||
Al momento dell’iscrizione, riceveranno <strong>alcuni degli ultimi messaggi della cronologia del canale</strong>.</p>
|
|
||||||
|
|
||||||
<p>Accanto a ciascun messaggio puoi vedere il <strong>numero di visualizzazioni</strong>.
|
|
||||||
Tieni presente che questo conteggio si riferisce solo agli abbonati che hanno attivato le conferme di lettura,
|
|
||||||
quindi il numero reale di visualizzazioni potrebbe essere superiore.</p>
|
|
||||||
|
|
||||||
<h3 id="quanti-iscritti-può-avere-un-canale">
|
|
||||||
|
|
||||||
|
|
||||||
Quanti iscritti può avere un canale? <a href="#quanti-iscritti-può-avere-un-canale" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>I canali sono progettati per un pubblico molto più ampio rispetto ai <a href="#groups">gruppi</a>.</p>
|
|
||||||
|
|
||||||
<p>Il limite pratico dipende dal numero di <a href="#relays">ripetitori</a> utilizzati, quindi non esiste un singolo numero fisso valido ovunque.</p>
|
|
||||||
|
|
||||||
<p>Per canali molto grandi con diverse decine di migliaia di iscritti,
|
|
||||||
consigliamo di utilizzare un <a href="#multiple-accounts">profilo dedicato</a> per il canale
|
|
||||||
e di verificare se il ripetitore è adatto.</p>
|
|
||||||
|
|
||||||
<p>Ma non esitare troppo: Delta Chat è progettato per essere indipendente dal ripetitore,
|
|
||||||
quindi puoi cambiare il tuo ripetitore in qualsiasi momento con facilità -
|
|
||||||
i tuoi iscritti esistenti non se ne accorgeranno nemmeno.
|
|
||||||
In tal caso, dovrai solo aggiornare il collegamento di invito che condividi con i nuovi iscritti.</p>
|
|
||||||
|
|
||||||
<h2 id="calls">
|
|
||||||
|
|
||||||
|
|
||||||
Chiamate <a href="#calls" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Delta Chat supports one-to-one <strong>audio calls</strong> and <strong>video calls</strong>.</p>
|
|
||||||
|
|
||||||
<p>Calls are supported on Desktop, Ubuntu Touch, iOS and Android 8 and newer.</p>
|
|
||||||
|
|
||||||
<h3 id="place-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Place a call <a href="#place-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>In a one-to-one chat, tap the 📞 <strong>call icon</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>This opens a small menu
|
|
||||||
where you can choose whether to place an <strong>Audio Call</strong> or a <strong>Video Call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="accept-or-reject-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Accept or reject a call <a href="#accept-or-reject-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>When someone calls you,
|
|
||||||
Delta Chat shows an <strong>incoming call screen</strong> or notification.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>Accept</strong> to answer
|
|
||||||
or <strong>Decline</strong> to reject the call.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="during-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
During a call <a href="#during-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>mute</strong> your microphone.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>enable or disable your camera</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>On mobile, you can <strong>switch between front and back cameras</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Depending on the device, you can also select the audio output or use picture-in-picture.
|
|
||||||
On desktop, the call is using a dedicated window
|
|
||||||
and you can continue using the main Delta Chat window as usual.</p>
|
|
||||||
|
|
||||||
<h3 id="missed-calls-and-notifications">
|
|
||||||
|
|
||||||
|
|
||||||
Missed calls and notifications <a href="#missed-calls-and-notifications" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>If you do not answer, do not hear the ringing, or do not have your device at hand,
|
|
||||||
the call appears as a <strong>missed call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><strong>Only your accepted contacts</strong> can make your device ring.
|
|
||||||
Contact requests will appear as usual and will not ring.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>At <strong>Settings → Notifications → Calls</strong>,
|
|
||||||
you can disable the special call ringing screen completely.
|
|
||||||
If you do so, you will not be disturbed by any ringing notification,
|
|
||||||
you can still pick up the call by tapping the incoming call message bubble in its chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="webxdc">
|
<h2 id="webxdc">
|
||||||
|
|
||||||
|
|
||||||
@@ -1239,22 +1021,16 @@ Tuttavia, se lo si desidera,
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Puoi <strong>aggiungere</strong> un ripetitore scansionando il suo codice QR;
|
<p>Puoi <strong>aggiungere</strong> un ripetitore scansionando il suo codice QR;<a href="https://chatmail.at/relays">https://chatmail.at/relays</a> ne mostra alcuni noti.
|
||||||
<a href="https://chatmail.at/relays">chatmail.at/relays</a> mostra alcuni ripetitori noti.
|
Se hai più ripetitori, riceverai messaggi su tutti.</p>
|
||||||
Se hai più ripetitori, riceverai i messaggi su tutti.
|
|
||||||
I contatti vengono a conoscenza automaticamente dei tuoi ripetitori attuali quando invii loro un messaggio.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Tocca un ripetitore per impostarlo come <strong>utilizzato per l’invio</strong>.</p>
|
<p>L’opzione <strong>predefinita</strong> definisce quella a cui i tuoi partner di chat invieranno messaggi futuri.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Se <strong>rimuovi</strong> un ripetitore,
|
<p>Se <strong>rimuovi</strong> un ripetitore,
|
||||||
i contatti che conoscono solo quel ripetitore potrebbero non raggiungerti finché non invierai loro un nuovo messaggio.
|
assicurati che un altro ripetitore predefinito sia stato utilizzato per un periodo di tempo sufficiente.
|
||||||
Per rimanere raggiungibile nel frattempo, seleziona <strong>Nascondi dai Contatti</strong> nella finestra di dialogo di conferma
|
In caso contrario, i messaggi dei tuoi interlocutori di chat non ti arriveranno.In caso di dubbio, rimuovilo in seguito.</p>
|
||||||
invece di rimuoverlo immediatamente.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Per <strong>visualizzare</strong> nuovamente un ripetitore nascosto, toccalo.</p>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -1397,10 +1173,6 @@ per scambiare informazioni sulla configurazione della crittografia tramite la sc
|
|||||||
<li>
|
<li>
|
||||||
<p><a href="https://autocrypt.org">Autocrypt</a> viene utilizzato per stabilire
|
<p><a href="https://autocrypt.org">Autocrypt</a> viene utilizzato per stabilire
|
||||||
automaticamente la crittografia end-to-end tra i contatti e tutti i membri di una chat di gruppo.</p>
|
automaticamente la crittografia end-to-end tra i contatti e tutti i membri di una chat di gruppo.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, la cui piena implementazione è prevista per il 2026,
|
|
||||||
introdurrà una crittografia post-quantistica resistente e una segretezza avanzata.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Condivisione di un contatto con una
|
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Condivisione di un contatto con una
|
||||||
@@ -1617,20 +1389,23 @@ non possono essere identificati facilmente.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>The used <a href="#relays">relays</a> need to know your IP Address,
|
<p>Il <a href="#relays">ripetitore</a> utilizzato deve conoscere il tuo indirizzo IP,
|
||||||
as well as sometimes your contact’s devices if you have a <a href="#calls">call</a>
|
e talvolta anche i dispositivi dei tuoi contatti se avete una <a href="#experiments">chiamata</a>
|
||||||
or use <a href="#webxdc">apps</a> together.</p>
|
o utilizzate <a href="#webxdc">apps</a> insieme.</p>
|
||||||
|
|
||||||
<p>IP Addresses are needed for connectivity and efficiency.
|
<p>Gli indirizzi IP sono necessari per la connettività e l’efficienza.
|
||||||
Delta Chat neither persists nor exposes them.
|
Non sono né persistenti né esposti.
|
||||||
Note that IP Addresses
|
Si noti che l’indirizzo IP
|
||||||
are not like an address you give to a delivery service,
|
non è come un indirizzo dettagliato che si fornisce a un servizio di consegna,
|
||||||
but typically less precise, often defining city or region only.</p>
|
ma molto più generico, che spesso definisce solo la regione o il paese.</p>
|
||||||
|
|
||||||
<p>If you see your IP Address as a risk,
|
<p>Poiché questo è il modo in cui Internet e altri servizi di messaggistica funzionano di default,
|
||||||
we recommend to use a VPN for the whole system.
|
non offriamo opzioni né poniamo domande in anticipo.</p>
|
||||||
Per-app options leave gaps across your system.
|
|
||||||
For example, tapping a link can expose IP Addresses to unknown parties, which is by far the larger risk.</p>
|
<p>Se ritieni che il tuo indirizzo IP rappresenti un rischio per la sicurezza o la privacy,
|
||||||
|
ti consigliamo di utilizzare una VPN, in combinazione con la modalità di blocco del sistema.
|
||||||
|
Esplorare le opzioni in tutte le app del tuo sistema lascerà delle lacune.
|
||||||
|
Ad esempio, cliccare su un link espone gli indirizzi IP a sconosciuti e rappresenta il rischio di gran lunga maggiore.</p>
|
||||||
|
|
||||||
<h3 id="sealedsender">
|
<h3 id="sealedsender">
|
||||||
|
|
||||||
@@ -1661,7 +1436,7 @@ ma un’implementazione non è stata ancora concordata come priorità.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Non ancora, ma arriverà con <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, non ancora.</p>
|
||||||
|
|
||||||
<p>Delta Chat al momento non supporta la tecnologia Perfect Forward Secrecy (PFS).
|
<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
|
Ciò significa che se la tua chiave di decrittazione privata viene divulgata
|
||||||
@@ -1672,9 +1447,12 @@ In caso contrario, chi ottiene le tue chiavi di decrittazione
|
|||||||
in genere è in grado di ottenere anche tutti i tuoi messaggi non eliminati
|
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>
|
e non ha nemmeno bisogno di decifrare i messaggi raccolti in precedenza.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">autocrypt v2</a>, la cui piena implementazione è prevista per il 2026,
|
<p>Abbiamo progettato un approccio Forward Secrecy che ha superato
|
||||||
garantirà un’eliminazione affidabile (segretezza in avanti) tramite rotazione automatica delle chiavi.
|
l’esame iniziale di alcuni crittografi ed esperti di implementazione
|
||||||
Questo approccio è specificato nella bozza dei <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">certificati OpenPGP di Autocrypt v2</a>.</p>
|
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">
|
<h3 id="pqc">
|
||||||
|
|
||||||
@@ -1684,13 +1462,12 @@ Questo approccio è specificato nella bozza dei <a href="https://datatracker.iet
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Non ancora, ma arriverà con <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, non ancora.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, la cui piena implementazione è prevista per il 2026,
|
<p>Delta Chat utilizza la libreria Rust OpenPGP <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||||
offrirà una crittografia post-quantistica resistente per proteggere dagli attacchi ai computer quantistici.
|
|
||||||
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>.
|
che supporta l’ultima <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">bozza IETF Post-Quantum-Cryptography OpenPGP</a>.
|
||||||
L’implementazione è specificata nella bozza dei <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Certificati OpenPGP Autocrypt v2</a>.</p>
|
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="come-posso-controllare-manualmente-le-informazioni-di-crittografia">
|
<h3 id="come-posso-controllare-manualmente-le-informazioni-di-crittografia">
|
||||||
|
|
||||||
@@ -1768,7 +1545,7 @@ Vedi <a href="https://delta.chat/en/2023-05-22-webxdc-security">qui per la stori
|
|||||||
<li>
|
<li>
|
||||||
<p>A partire dal 2023, <a href="https://cure53.de">Cure53</a> ha analizzato sia la crittografia del trasporto delle
|
<p>A partire dal 2023, <a href="https://cure53.de">Cure53</a> ha analizzato sia la crittografia del trasporto delle
|
||||||
Connessioni di rete di Delta Chat e una configurazione del server di posta riproducibile come
|
Connessioni di rete di Delta Chat e una configurazione del server di posta riproducibile come
|
||||||
<a href="https://delta.chat/serverguide">consigliato su questo sito</a>.
|
<a href="https://delta.chat/it/serverguide">consigliato su questo sito</a>.
|
||||||
Puoi leggere ulteriori informazioni sull’audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">sul nostro blog</a>
|
Puoi leggere ulteriori informazioni sull’audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">sul nostro blog</a>
|
||||||
o leggere il <a href="https://delta.chat/assets/blog/MER-01-report.pdf">rapporto completo qui</a>.</p>
|
o leggere il <a href="https://delta.chat/assets/blog/MER-01-report.pdf">rapporto completo qui</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
@@ -1870,31 +1647,31 @@ ordinate cronologicamente:</p>
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Nel 2023 e nel 2024 siamo stati accettati nel programma Next Generation Internet (NGI)
|
<p>In 2023 and 2024 we got accepted in the Next Generation Internet (NGI)
|
||||||
per il nostro lavoro in <a href="https://nlnet.nl/project/WebXDC-Push/">webxdc PUSH</a>,
|
program for our work in <a href="https://nlnet.nl/project/WebXDC-Push/">webxdc PUSH</a>,
|
||||||
insieme ai partner di collaborazione che lavorano su
|
along with collaboration partners working on
|
||||||
<a href="https://nlnet.nl/project/Webxdc-Evolve/">webxdc evolve</a>,
|
<a href="https://nlnet.nl/project/Webxdc-Evolve/">webxdc evolve</a>,
|
||||||
<a href="https://nlnet.nl/project/WebXDC-XMPP/">webxdc XMPP</a>,
|
<a href="https://nlnet.nl/project/WebXDC-XMPP/">webxdc XMPP</a>,
|
||||||
<a href="https://nlnet.nl/project/DeltaTouch/">DeltaTouch</a> e
|
<a href="https://nlnet.nl/project/DeltaTouch/">DeltaTouch</a> and
|
||||||
<a href="https://nlnet.nl/project/DeltaTauri/">DeltaTauri</a>.
|
<a href="https://nlnet.nl/project/DeltaTauri/">DeltaTauri</a>.
|
||||||
Tutti questi progetti sono parzialmente completati o saranno completati all’inizio del 2025.</p>
|
All of these projects are partially completed or to be completed in early 2025.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Nel 2021 abbiamo ricevuto ulteriori finanziamenti dall’UE per due proposte di Next-Generation-Internet, ovvero per <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - directory di portabilità dei provider di posta elettronica</a> (~97.000 EUR) e <a href="https://nlnet.nl/project/EmailPorting/">AEAP - portabilità degli indirizzi email</a> (~90.000 EUR), che hanno portato a un migliore supporto multi-profilo, a un miglioramento delle impostazioni di contatto e di gruppo tramite codice QR e a numerosi miglioramenti di rete su tutte le piattaforme.</p>
|
<p>Nel 2021 abbiamo ricevuto ulteriori finanziamenti dall’UE per due proposte di Next-Generation-Internet, ovvero per <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - directory di portabilità dei provider di posta elettronica</a> (~97.000 EUR) e <a href="https://nlnet.nl/project/EmailPorting/">AEAP - portabilità degli indirizzi email</a> (~90.000 EUR), che hanno portato a un migliore supporto multi-profilo, a un miglioramento delle impostazioni di contatto e di gruppo tramite codice QR e a numerosi miglioramenti di rete su tutte le piattaforme.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>La <a href="https://nlnet.nl/">fondazione NLnet</a> ha concesso nel 2019/2020 46.000 EUR per
|
<p>The <a href="https://nlnet.nl/">NLnet foundation</a> granted in 2019/2020 EUR 46K for
|
||||||
completando i collegamenti Rust/Python e avviando un ecosistema Chat-bot.</p>
|
completing Rust/Python bindings and instigating a Chat-bot eco-system.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>L’<a href="https://opentechfund.org">Open Technology Fund</a> ci ha dato una
|
<p>The <a href="https://opentechfund.org">Open Technology Fund</a> gave us a
|
||||||
prima sovvenzione 2018/2019 (~$200K) durante la quale abbiamo notevolmente migliorato l’app Android
|
first 2018/2019 grant (~$200K) during which we majorly improved the Android app
|
||||||
e ha rilasciato una prima versione beta dell’app desktop, e che inoltre
|
and released a first Desktop app beta version, and which moreover
|
||||||
ancorato i nostri sviluppi delle funzionalità nella ricerca sulla UX nei contesti dei diritti umani,
|
moored our feature developments in UX research in human rights contexts,
|
||||||
vedete il nostro <a href="https://delta.chat/en/2019-07-19-uxreport">Rapporto Needfinding e UX</a> conclusivo.
|
see our concluding <a href="https://delta.chat/en/2019-07-19-uxreport">Needfinding and UX report</a>.
|
||||||
La seconda sovvenzione 2019/2020 (~$300K) ci ha aiutato a farlo
|
The second 2019/2020 grant (~$300K) helped us to
|
||||||
rilasciare nelle versioni Delta/iOS, per convertire la nostra libreria principale in Rust, e
|
release Delta/iOS versions, to convert our core library to Rust, and
|
||||||
per fornire nuove funzionalità per tutte le piattaforme.</p>
|
to provide new features for all platforms.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Il progetto UE <a href="https://nextleap.eu">NEXTLEAP</a> ha finanziato la ricerca
|
<p>Il progetto UE <a href="https://nextleap.eu">NEXTLEAP</a> ha finanziato la ricerca
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
||||||
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
||||||
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
||||||
|
<li><a href="#ondersteunt-delta-chat-afbeeldingen-videos-en-ander-soort-bijlagen">Ondersteunt Delta Chat afbeeldingen, video’s en ander soort bijlagen?</a></li>
|
||||||
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
||||||
<li><a href="#wie-kan-mijn-profielfoto-zien">Wie kan mijn profielfoto zien?</a></li>
|
<li><a href="#wie-kan-mijn-profielfoto-zien">Wie kan mijn profielfoto zien?</a></li>
|
||||||
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
<li><a href="#wat-betekent-die-groene-stip">Wat betekent die groene stip?</a></li>
|
<li><a href="#wat-betekent-die-groene-stip">Wat betekent die groene stip?</a></li>
|
||||||
<li><a href="#wat-betekenen-de-vinkjes-naast-verzonden-berichten">Wat betekenen de vinkjes naast verzonden berichten?</a></li>
|
<li><a href="#wat-betekenen-de-vinkjes-naast-verzonden-berichten">Wat betekenen de vinkjes naast verzonden berichten?</a></li>
|
||||||
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
||||||
<li><a href="#mediaquality">How is media quality handled?</a></li>
|
|
||||||
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
||||||
<li><a href="#delold">Wat gebeurt er als ik ‘Oude berichten van server verwijderen’ inschakel?</a></li>
|
<li><a href="#delold">Wat gebeurt er als ik ‘Oude berichten van server verwijderen’ inschakel?</a></li>
|
||||||
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
||||||
@@ -29,21 +29,6 @@
|
|||||||
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#channels">Channels</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#subscribe-to-a-channel">Subscribe to a channel</a></li>
|
|
||||||
<li><a href="#create-a-channel">Create a channel</a></li>
|
|
||||||
<li><a href="#how-many-subscribers-can-a-channel-have">How many subscribers can a channel have?</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#calls">Calls</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#place-a-call">Place a call</a></li>
|
|
||||||
<li><a href="#accept-or-reject-a-call">Accept or reject a call</a></li>
|
|
||||||
<li><a href="#during-a-call">During a call</a></li>
|
|
||||||
<li><a href="#missed-calls-and-notifications">Missed calls and notifications</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#webxdc">In-chat apps</a>
|
<li><a href="#webxdc">In-chat apps</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
||||||
@@ -233,6 +218,19 @@ You can also add a little introduction message.</p>
|
|||||||
<p>The second contact will receive a <strong>card</strong> then
|
<p>The second contact will receive a <strong>card</strong> then
|
||||||
and can tap it to start chatting with the first contact.</p>
|
and can tap it to start chatting with the first contact.</p>
|
||||||
|
|
||||||
|
<h3 id="ondersteunt-delta-chat-afbeeldingen-videos-en-ander-soort-bijlagen">
|
||||||
|
|
||||||
|
|
||||||
|
Ondersteunt Delta Chat afbeeldingen, video’s en ander soort bijlagen? <a href="#ondersteunt-delta-chat-afbeeldingen-videos-en-ander-soort-bijlagen" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Yes. Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment-</strong>
|
||||||
|
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons</p>
|
||||||
|
|
||||||
|
<p>Om de prestaties te verhogen, worden afbeeldingen standaard geoptimaliseerd en verkleind verstuurd, maar je kunt ze als een bestand verzenden om het origineel te sturen.</p>
|
||||||
|
|
||||||
<h3 id="multiple-accounts">
|
<h3 id="multiple-accounts">
|
||||||
|
|
||||||
|
|
||||||
@@ -412,32 +410,6 @@ Notifications are not sent and there is no time limit.</p>
|
|||||||
<p>Note, that the original message may still be received by chat members
|
<p>Note, that the original message may still be received by chat members
|
||||||
who could have already replied, forwarded, saved, screenshotted or otherwise copied the message.</p>
|
who could have already replied, forwarded, saved, screenshotted or otherwise copied the message.</p>
|
||||||
|
|
||||||
<h3 id="mediaquality">
|
|
||||||
|
|
||||||
|
|
||||||
How is media quality handled? <a href="#mediaquality" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach-</strong>
|
|
||||||
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>By default, compression ensures <strong>fast, efficient delivery</strong> that respects everyone’s data limits and storage.
|
|
||||||
This is ideal for everyday communication.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>In regions with worse connectivity,
|
|
||||||
you can choose higher compression at <strong>Settings → Chats → Outgoing Media Quality</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>If you specifically need to send media in its <strong>original quality</strong>, use <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach → File</strong> in the chat.
|
|
||||||
Please use this method sparingly, as sending original files will significantly increase data usage for you and all recipients in the chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="ephemeralmsgs">
|
<h3 id="ephemeralmsgs">
|
||||||
|
|
||||||
|
|
||||||
@@ -637,197 +609,6 @@ but more than 150 is not recommended.</p>
|
|||||||
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
||||||
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
||||||
|
|
||||||
<h2 id="channels">
|
|
||||||
|
|
||||||
|
|
||||||
Channels <a href="#channels" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Channels are a one-to-many tool for broadcasting messages.</p>
|
|
||||||
|
|
||||||
<h3 id="subscribe-to-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Subscribe to a channel <a href="#subscribe-to-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Scan the <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>QR code</strong>
|
|
||||||
or tap the <strong>invite link</strong> you got from the channel owner.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>That’s all!
|
|
||||||
You will receive a few of the messages from the channel history
|
|
||||||
and, from that point on, all new messages from the channel.</p>
|
|
||||||
|
|
||||||
<p><strong>Don’t worry,</strong> if that does not happen immediately.
|
|
||||||
Once the channel owner comes online, your join request will be processed.</p>
|
|
||||||
|
|
||||||
<p>As all of Delta Chat, also Channels are private and decentralized,
|
|
||||||
there is no public discovery.</p>
|
|
||||||
|
|
||||||
<p>Other channel subscribers will not see that you subscribed and cannot message you.
|
|
||||||
The channel owner, however, can message you.
|
|
||||||
They will also see that you read a message unless you have read receipts disabled.</p>
|
|
||||||
|
|
||||||
<p>If you do not want to share your main profile,
|
|
||||||
you can also create a <a href="#multiple-accounts">dedicated profile</a> for joining a channel.</p>
|
|
||||||
|
|
||||||
<h3 id="create-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Create a channel <a href="#create-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>New Chat</strong> and choose <strong>New Channel</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Enter a <strong>name</strong>, optionally set an <strong>image</strong> and <strong>description</strong>, and hit the <strong>Create</strong> button.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can now send and manage messages as usual.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>From the channel’s profile, <strong>share the QR code or invite link with others</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Subscribers will receive your messages,
|
|
||||||
but they cannot send messages in your channel.
|
|
||||||
When subscribing, they will receive <strong>a few of the latest messages of the channel history</strong>.</p>
|
|
||||||
|
|
||||||
<p>You can see the <strong>view count</strong> beside each message.
|
|
||||||
Note that this only counts subscribers who have read receipts enabled,
|
|
||||||
so the real view count may be larger.</p>
|
|
||||||
|
|
||||||
<h3 id="how-many-subscribers-can-a-channel-have">
|
|
||||||
|
|
||||||
|
|
||||||
How many subscribers can a channel have? <a href="#how-many-subscribers-can-a-channel-have" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Channels are designed for much larger audiences than <a href="#groups">groups</a>.</p>
|
|
||||||
|
|
||||||
<p>The practical limit depends on the used <a href="#relays">relay</a>,
|
|
||||||
so there is no single fixed number that applies everywhere.</p>
|
|
||||||
|
|
||||||
<p>For really large channels with several tens of thousands of subscribers,
|
|
||||||
we recommend using a <a href="#multiple-accounts">dedicated profile</a> for the channel
|
|
||||||
and checking whether the relay is suitable.</p>
|
|
||||||
|
|
||||||
<p>But don’t be too hesitant: Delta Chat is designed to be relay-agnostic,
|
|
||||||
so you can change your relay at any point easily -
|
|
||||||
your existing subscribers will not even notice.
|
|
||||||
You only have to update the invite link you share with new subscribers in that case.</p>
|
|
||||||
|
|
||||||
<h2 id="calls">
|
|
||||||
|
|
||||||
|
|
||||||
Calls <a href="#calls" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Delta Chat supports one-to-one <strong>audio calls</strong> and <strong>video calls</strong>.</p>
|
|
||||||
|
|
||||||
<p>Calls are supported on Desktop, Ubuntu Touch, iOS and Android 8 and newer.</p>
|
|
||||||
|
|
||||||
<h3 id="place-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Place a call <a href="#place-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>In a one-to-one chat, tap the 📞 <strong>call icon</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>This opens a small menu
|
|
||||||
where you can choose whether to place an <strong>Audio Call</strong> or a <strong>Video Call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="accept-or-reject-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Accept or reject a call <a href="#accept-or-reject-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>When someone calls you,
|
|
||||||
Delta Chat shows an <strong>incoming call screen</strong> or notification.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>Accept</strong> to answer
|
|
||||||
or <strong>Decline</strong> to reject the call.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="during-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
During a call <a href="#during-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>mute</strong> your microphone.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>enable or disable your camera</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>On mobile, you can <strong>switch between front and back cameras</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Depending on the device, you can also select the audio output or use picture-in-picture.
|
|
||||||
On desktop, the call is using a dedicated window
|
|
||||||
and you can continue using the main Delta Chat window as usual.</p>
|
|
||||||
|
|
||||||
<h3 id="missed-calls-and-notifications">
|
|
||||||
|
|
||||||
|
|
||||||
Missed calls and notifications <a href="#missed-calls-and-notifications" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>If you do not answer, do not hear the ringing, or do not have your device at hand,
|
|
||||||
the call appears as a <strong>missed call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><strong>Only your accepted contacts</strong> can make your device ring.
|
|
||||||
Contact requests will appear as usual and will not ring.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>At <strong>Settings → Notifications → Calls</strong>,
|
|
||||||
you can disable the special call ringing screen completely.
|
|
||||||
If you do so, you will not be disturbed by any ringing notification,
|
|
||||||
you can still pick up the call by tapping the incoming call message bubble in its chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="webxdc">
|
<h2 id="webxdc">
|
||||||
|
|
||||||
|
|
||||||
@@ -1243,26 +1024,22 @@ Relays are operated by different groups and people.</p>
|
|||||||
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
||||||
so you do not need to care about that.
|
so you do not need to care about that.
|
||||||
However, if you want to,
|
However, if you want to,
|
||||||
you can configure relays at <strong>Settings → Advanced → Relays</strong>:</p>
|
you can configure relays at At <strong>Settings → Advanced → Relays</strong>:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
||||||
<a href="https://chatmail.at/relays">chatmail.at/relays</a> shows some known ones.
|
<a href="https://chatmail.at/relays">https://chatmail.at/relays</a> shows some known ones.
|
||||||
If you have multiple relays, you will receive messages on all of them.
|
If you have multiple relays, you will receive messages on all of them.</p>
|
||||||
Contacts learn your current relays automatically when you message them.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Tap on a relay to set it as <strong>used for sending</strong>.</p>
|
<p>The <strong>default</strong> defines the one where your chat partners send future messages to.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>If you <strong>remove</strong> a relay,
|
<p>If you <strong>remove</strong> a relay,
|
||||||
contacts who only know this relay may not reach you until you message them again.
|
make sure another default relay was used for a sufficient amount of time.
|
||||||
To stay reachable in the meantime, choose <strong>Hide from Contacts</strong> in the confirmation dialog
|
Otherwise, messages from your chat partners won’t reach you.
|
||||||
instead of removing it right away.</p>
|
If in doubt, remove later.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>To <strong>show</strong> a hidden relay again, tap on it.</p>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -1405,10 +1182,6 @@ to exchange encryption setup information through QR-code scanning or “invite l
|
|||||||
<li>
|
<li>
|
||||||
<p><a href="https://autocrypt.org">Autocrypt</a> is used for automatically
|
<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>
|
establishing end-to-end encryption between contacts and all members of a group chat.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
|
||||||
will bring post-quantum resistant encryption and forward secrecy.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<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
|
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Sharing a contact to a
|
||||||
@@ -1593,10 +1366,12 @@ Instead, all group metadata is end-to-end encrypted and stored on end-user devic
|
|||||||
<p>Servers can therefore only see:</p>
|
<p>Servers can therefore only see:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Sender and receiver addresses, randomly generated by default</li>
|
<li>the sender and receiver addresses</li>
|
||||||
<li>Message size</li>
|
<li>and the message size.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>By default, the addresses are randomly generated.</p>
|
||||||
|
|
||||||
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
||||||
|
|
||||||
<h3 id="device-seizure">
|
<h3 id="device-seizure">
|
||||||
@@ -1625,20 +1400,23 @@ can not be identified easily.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>The used <a href="#relays">relays</a> need to know your IP Address,
|
<p>The used <a href="#relays">relay</a> needs to know your IP Address,
|
||||||
as well as sometimes your contact’s devices if you have a <a href="#calls">call</a>
|
as well as sometimes your contact’s devices if you have a <a href="#experiments">call</a>
|
||||||
or use <a href="#webxdc">apps</a> together.</p>
|
or use <a href="#webxdc">apps</a> together.</p>
|
||||||
|
|
||||||
<p>IP Addresses are needed for connectivity and efficiency.
|
<p>IP Addresses are needed for connectivity and efficiency.
|
||||||
Delta Chat neither persists nor exposes them.
|
They are neither persisted nor exposed.
|
||||||
Note that IP Addresses
|
Note that the IP Address
|
||||||
are not like an address you give to a delivery service,
|
is not like a detailed address you give to a delivery service,
|
||||||
but typically less precise, often defining city or region only.</p>
|
but much more coarse, often defining region or country only.</p>
|
||||||
|
|
||||||
<p>If you see your IP Address as a risk,
|
<p>As this is just how the internet and other messengers work by default,
|
||||||
we recommend to use a VPN for the whole system.
|
we do not offer options here or ask upfront questions.</p>
|
||||||
Per-app options leave gaps across your system.
|
|
||||||
For example, tapping a link can expose IP Addresses to unknown parties, which is by far the larger risk.</p>
|
<p>If you see your IP Address as a security or privacy risk,
|
||||||
|
we recommend to use a VPN, in combination with system lockdown mode.
|
||||||
|
Hunting down options in all apps on your system will leave gaps.
|
||||||
|
For example, tapping a link exposes IP Addresses to unknown parties and is the by far larger risk here.</p>
|
||||||
|
|
||||||
<h3 id="sealedsender">
|
<h3 id="sealedsender">
|
||||||
|
|
||||||
@@ -1669,7 +1447,7 @@ but an implementation has not been agreed as a priority yet.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||||
This means that if your private decryption key is leaked,
|
This means that if your private decryption key is leaked,
|
||||||
@@ -1680,9 +1458,12 @@ Otherwise, someone obtaining your decryption keys
|
|||||||
is typically also able to get all your non-deleted messages
|
is typically also able to get all your non-deleted messages
|
||||||
and doesn’t even need to decrypt any previously collected messages.</p>
|
and doesn’t even need to decrypt any previously collected messages.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>We designed a Forward Secrecy approach that withstood
|
||||||
will provide reliable deletion (forward secrecy) through automatic key rotation.
|
initial examination from some cryptographers and implementation experts
|
||||||
This approach is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
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>
|
||||||
|
|
||||||
<h3 id="pqc">
|
<h3 id="pqc">
|
||||||
|
|
||||||
@@ -1692,13 +1473,12 @@ This approach is specified in the <a href="https://datatracker.ietf.org/doc/draf
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||||
will bring post-quantum resistant encryption to protect against quantum computer attacks.
|
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
||||||
Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</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
|
||||||
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
in collaboration with other OpenPGP implementers.</p>
|
||||||
The implementation is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
|
||||||
|
|
||||||
<h3 id="how-can-i-manually-check-encryption-information">
|
<h3 id="how-can-i-manually-check-encryption-information">
|
||||||
|
|
||||||
@@ -1775,7 +1555,7 @@ Lees <a href="https://delta.chat/en/2023-05-22-webxdc-security">hier het volledi
|
|||||||
<li>
|
<li>
|
||||||
<p>Aan het begin van 2023 heeft <a href="https://cure53.de">Cure53</a> de transportversleuteling van
|
<p>Aan het begin van 2023 heeft <a href="https://cure53.de">Cure53</a> de transportversleuteling van
|
||||||
Delta Chats netwerkverbindingen getest, evenals de e-mailserveropzet zoals
|
Delta Chats netwerkverbindingen getest, evenals de e-mailserveropzet zoals
|
||||||
<a href="https://delta.chat/serverguide">beschreven op onze site</a>.
|
<a href="https://delta.chat/nl/serverguide">beschreven op onze site</a>.
|
||||||
Meer informatie over deze test is te lezen <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">op ons blog</a>
|
Meer informatie over deze test is te lezen <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">op ons blog</a>
|
||||||
of in het <a href="https://delta.chat/assets/blog/MER-01-report.pdf">volledige verslag</a>.</p>
|
of in het <a href="https://delta.chat/assets/blog/MER-01-report.pdf">volledige verslag</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
+216
-326
@@ -2,46 +2,31 @@
|
|||||||
<html lang="pl"><head><meta charset="UTF-8" /><meta name="viewport" content="initial-scale=1.0" /><link rel="stylesheet" href="../help.css" /></head><body><ul id="top">
|
<html lang="pl"><head><meta charset="UTF-8" /><meta name="viewport" content="initial-scale=1.0" /><link rel="stylesheet" href="../help.css" /></head><body><ul id="top">
|
||||||
<li><a href="#czym-jest-delta-chat">Czym jest Delta Chat?</a>
|
<li><a href="#czym-jest-delta-chat">Czym jest Delta Chat?</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#howtoe2ee">Jak znaleźć osoby do czatu?</a></li>
|
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
||||||
<li><a href="#dlaczego-czat-jest-oznaczony-jako-prośba">Dlaczego czat jest oznaczony jako „Prośba”?</a></li>
|
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
||||||
<li><a href="#jak-mogę-skontaktować-ze-sobą-dwóch-znajomych">Jak mogę skontaktować ze sobą dwóch znajomych?</a></li>
|
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
||||||
|
<li><a href="#czy-delta-chat-obsługuje-obrazy-filmy-i-inne-załączniki">Czy Delta Chat obsługuje obrazy, filmy i inne załączniki?</a></li>
|
||||||
<li><a href="#multiple-accounts">Czym są profile? Jak mogę przełączać się między nimi?</a></li>
|
<li><a href="#multiple-accounts">Czym są profile? Jak mogę przełączać się między nimi?</a></li>
|
||||||
<li><a href="#kto-widzi-moje-zdjęcie-profilowe">Kto widzi moje zdjęcie profilowe?</a></li>
|
<li><a href="#kto-widzi-moje-zdjęcie-profilowe">Kto widzi moje zdjęcie profilowe?</a></li>
|
||||||
<li><a href="#signature">Czy w Delta Chat mogę ustawić biografię/status?</a></li>
|
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
||||||
<li><a href="#co-oznacza-przypinanie-wyciszanie-i-archiwizowanie">Co oznacza przypinanie, wyciszanie i archiwizowanie?</a></li>
|
<li><a href="#co-oznacza-przypinanie-wyciszanie-i-archiwizowanie">Co oznacza przypinanie, wyciszanie i archiwizowanie?</a></li>
|
||||||
<li><a href="#save">Jak działają „Zapisane wiadomości”?</a></li>
|
<li><a href="#save">Jak działają „Zapisane wiadomości”?</a></li>
|
||||||
<li><a href="#co-oznacza-zielona-kropka">Co oznacza zielona kropka?</a></li>
|
<li><a href="#co-oznacza-zielona-kropka">Co oznacza zielona kropka?</a></li>
|
||||||
<li><a href="#co-oznaczają-znaczniki-wyświetlane-obok-wiadomości-wychodzących">Co oznaczają znaczniki wyświetlane obok wiadomości wychodzących?</a></li>
|
<li><a href="#co-oznaczają-znaczniki-wyświetlane-obok-wiadomości-wychodzących">Co oznaczają znaczniki wyświetlane obok wiadomości wychodzących?</a></li>
|
||||||
<li><a href="#edit">Poprawianie literówek i usuwanie wiadomości po wysłaniu</a></li>
|
<li><a href="#edit">Poprawianie literówek i usuwanie wiadomości po wysłaniu</a></li>
|
||||||
<li><a href="#mediaquality">Jak obsługiwana jest jakość multimediów?</a></li>
|
|
||||||
<li><a href="#ephemeralmsgs">Jak działają znikające wiadomości?</a></li>
|
<li><a href="#ephemeralmsgs">Jak działają znikające wiadomości?</a></li>
|
||||||
<li><a href="#delold">Co się stanie, jeśli włączę opcję „Usuń wiadomości z urządzenia”?</a></li>
|
<li><a href="#delold">Co się stanie, jeśli włączę opcję „Usuń wiadomości z urządzenia”?</a></li>
|
||||||
<li><a href="#remove-account">Jak mogę usunąć swój profil czatu?</a></li>
|
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#groups">Grupy</a>
|
<li><a href="#groups">Groups</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#tworzenie-grupy">Tworzenie grupy</a></li>
|
<li><a href="#tworzenie-grupy">Tworzenie grupy</a></li>
|
||||||
<li><a href="#addmembers">Dodawanie i usuwanie członków</a></li>
|
<li><a href="#addmembers">Add and remove members</a></li>
|
||||||
<li><a href="#usunąłem-się-przez-przypadek">Usunąłem się przez przypadek.</a></li>
|
<li><a href="#usunąłem-się-przez-przypadek">Usunąłem się przez przypadek.</a></li>
|
||||||
<li><a href="#nie-chcę-już-otrzymywać-wiadomości-od-grupy">Nie chcę już otrzymywać wiadomości od grupy.</a></li>
|
<li><a href="#nie-chcę-już-otrzymywać-wiadomości-od-grupy">Nie chcę już otrzymywać wiadomości od grupy.</a></li>
|
||||||
<li><a href="#klonowanie-grupy">Klonowanie grupy</a></li>
|
<li><a href="#cloning-a-group">Cloning a group</a></li>
|
||||||
<li><a href="#ilu-członków-może-należeć-do-jednej-grupy">Ilu członków może należeć do jednej grupy?</a></li>
|
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#channels">Kanały</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#subskrybowanie-kanału">Subskrybowanie kanału</a></li>
|
|
||||||
<li><a href="#tworzenie-kanału">Tworzenie kanału</a></li>
|
|
||||||
<li><a href="#ilu-subskrybentów-może-mieć-kanał">Ilu subskrybentów może mieć kanał?</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#calls">Połączenia</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#nawiązywanie-połączenia">Nawiązywanie połączenia</a></li>
|
|
||||||
<li><a href="#odbieranie-lub-odrzucanie-połączenia">Odbieranie lub odrzucanie połączenia</a></li>
|
|
||||||
<li><a href="#w-trakcie-połączenia">W trakcie połączenia</a></li>
|
|
||||||
<li><a href="#nieodebrane-połączenia-i-powiadomienia">Nieodebrane połączenia i powiadomienia</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#webxdc">In-chat apps</a>
|
<li><a href="#webxdc">In-chat apps</a>
|
||||||
@@ -122,67 +107,87 @@
|
|||||||
|
|
||||||
<p>Delta Chat to niezawodna, zdecentralizowana i bezpieczna aplikacja do błyskawicznego przesyłania wiadomości, dostępna na platformy mobilne i stacjonarne.</p>
|
<p>Delta Chat to niezawodna, zdecentralizowana i bezpieczna aplikacja do błyskawicznego przesyłania wiadomości, dostępna na platformy mobilne i stacjonarne.</p>
|
||||||
|
|
||||||
<p>Natychmiastowe tworzenie <strong>prywatnych profili czatu</strong> z bezpiecznymi i interoperacyjnymi <a href="https://chatmail.at/relays">przekaźnikami chatmail</a>, które oferują natychmiastowe dostarczanie wiadomości oraz powiadomienia push dla urządzeń z systemem iOS i Android.</p>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Wszechstronna obsługa <a href="#multiple-accounts">wielu profili</a> i <a href="#multiclient">wielu urządzeń</a> na wszystkich platformach i między różnymi <a href="https://chatmail.at/clients">aplikacjami chatmail</a>.</p>
|
<p>Instant creation of <strong>private chat profiles</strong>
|
||||||
|
with secure and interoperable <a href="https://chatmail.at/relays">chatmail relays</a>
|
||||||
|
that offer instant message delivery, and Push Notifications for iOS and Android devices.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Interaktywne <a href="#webxdc">aplikacje do czatu</a> w grach i do współpracy</p>
|
<p>Pervasive <a href="#multiple-accounts">multi-profile</a> and
|
||||||
|
<a href="#multiclient">multi-device</a> support on all platforms
|
||||||
|
and between different <a href="https://chatmail.at/clients">chatmail apps</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><a href="#security-audits">Audytowne szyfrowanie end-to-end</a> zabezpieczające przed atakami sieciowymi i serwerowymi.</p>
|
<p>Interactive <a href="#webxdc">in-chat apps</a> for gaming and collaboration</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Bezpłatne i otwartoźródłowe oprogramowanie zarówno po stronie aplikacji, jak i serwera, stworzone w oparciu o <a href="https://github.com/chatmail/core/blob/main/standards.md#standards-used-in-delta-chat">standardy internetowe</a>.</p>
|
<p><a href="#security-audits">Audited end-to-end encryption</a>
|
||||||
|
safe against network and server attacks.</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Free and Open Source software, both app and server side,
|
||||||
|
built on <a href="https://github.com/chatmail/core/blob/main/standards.md#standards-used-in-delta-chat">Internet Standards</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3 id="howtoe2ee">
|
<h3 id="howtoe2ee">
|
||||||
|
|
||||||
|
|
||||||
Jak znaleźć osoby do czatu? <a href="#howtoe2ee" class="anchor"></a>
|
How can I find people to chat with? <a href="#howtoe2ee" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Najpierw pamiętaj, że Delta Chat to prywatny komunikator. Nie ma możliwości publicznego wyszukiwania, sam decydujesz o swoich kontaktach.</p>
|
<p>First, note that Delta Chat is a private messenger.
|
||||||
|
There is no public discovery, <em>you</em> decide about your contacts.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Jeśli jesteś twarzą w twarz ze znajomym lub rodziną, dotknij ikony <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>kodu QR</strong> na ekranie głównym.
|
<p>If you are <strong>face to face</strong> with your friend or family,
|
||||||
Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą aplikacji Delta Chat.</p>
|
tap the <strong>QR Code</strong> icon <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" />
|
||||||
|
on the main screen.<br />
|
||||||
|
Ask your chat partner to <strong>scan</strong> the QR image
|
||||||
|
with their Delta Chat app.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Aby skonfigurować kontakt <strong>zdalny</strong>, na tym samym ekranie naciśnij „Kopiuj” lub „Udostępnij” i wyślij <strong>link zaproszenia</strong> za pośrednictwem innego prywatnego czatu.</p>
|
<p>For a <strong>remote</strong> contact setup,
|
||||||
|
from the same screen,
|
||||||
|
click “Copy” or “Share” and send the <strong>invite link</strong>
|
||||||
|
through another private chat.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Poczekaj, aż połączenie zostanie nawiązane.</p>
|
<p>Now wait while connection gets established.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Jeśli obie strony są online, wkrótce zobaczą czat i będą mogły bezpiecznie wysyłać wiadomości.</p>
|
<p>If both sides are online, they will soon see a chat
|
||||||
|
and can start messaging securely.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Jeśli jedna ze stron jest offline lub ma słaby zasięg, możliwość czatowania zostanie wstrzymana do czasu przywrócenia połączenia.</p>
|
<p>If one side is offline or in bad network,
|
||||||
|
the ability to chat is delayed until connectivity is restored.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Gratulacje! Teraz będziesz automatycznie korzystać z <a href="#e2ee">szyfrowania typu end-to-end</a> dla tego kontaktu. Jeśli dodacie się nawzajem do <a href="#groups">grup</a>, szyfrowanie typu end-to-end zostanie nawiązane między wszystkimi członkami.</p>
|
<p>Congratulations!
|
||||||
|
You now will automatically use <a href="#e2ee">end-to-end encryption</a> with this contact.
|
||||||
|
If you add each other to <a href="#groups">groups</a>, end-to-end encryption will be established among all members.</p>
|
||||||
|
|
||||||
<h3 id="dlaczego-czat-jest-oznaczony-jako-prośba">
|
<h3 id="why-is-a-chat-marked-as-request">
|
||||||
|
|
||||||
|
|
||||||
Dlaczego czat jest oznaczony jako „Prośba”? <a href="#dlaczego-czat-jest-oznaczony-jako-prośba" class="anchor"></a>
|
Why is a chat marked as “Request”? <a href="#why-is-a-chat-marked-as-request" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Ponieważ jest to prywatny komunikator, tylko znajomi i rodzina, którym <a href="#howtoe2ee">udostępnisz swój kod QR lub link zaproszenia</a>, mogą do ciebie pisać.</p>
|
<p>As being a private messenger,
|
||||||
|
only friends and family you <a href="#howtoe2ee">share your QR code or invite link with</a> can write to you.</p>
|
||||||
|
|
||||||
<p>Twoi znajomi mogą udostępniać twoje dane kontaktowe innym znajomym, co jest oznaczone jako <b style="border: 1px solid currentColor; padding: 0 3px; font-size:90%">Prośba</b></p>
|
<p>Your friends may share your contact with other friends,
|
||||||
|
this appears as <b style="border: 1px solid currentColor; padding: 0 3px; font-size:90%">Request</b></p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@@ -196,17 +201,32 @@ Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą apli
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3 id="jak-mogę-skontaktować-ze-sobą-dwóch-znajomych">
|
<h3 id="how-can-i-put-two-of-my-friends-in-contact-with-each-other">
|
||||||
|
|
||||||
|
|
||||||
Jak mogę skontaktować ze sobą dwóch znajomych? <a href="#jak-mogę-skontaktować-ze-sobą-dwóch-znajomych" class="anchor"></a>
|
How can I put two of my friends in contact with each other? <a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Dołącz pierwszy kontakt do czatu drugiego, używając przycisku <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Dołączania → Kontakt</strong>. Możesz również dodać krótką wiadomość powitalną.</p>
|
<p>Attach the first contact to the chat of the second using <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment Button → Contact</strong>.
|
||||||
|
You can also add a little introduction message.</p>
|
||||||
|
|
||||||
<p>Drugi kontakt otrzyma wtedy <strong>kartkę</strong> i może ją nacisnąć, aby rozpocząć czat z pierwszym kontaktem.</p>
|
<p>The second contact will receive a <strong>card</strong> then
|
||||||
|
and can tap it to start chatting with the first contact.</p>
|
||||||
|
|
||||||
|
<h3 id="czy-delta-chat-obsługuje-obrazy-filmy-i-inne-załączniki">
|
||||||
|
|
||||||
|
|
||||||
|
Czy Delta Chat obsługuje obrazy, filmy i inne załączniki? <a href="#czy-delta-chat-obsługuje-obrazy-filmy-i-inne-załączniki" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Tak. Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment-</strong>
|
||||||
|
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons</p>
|
||||||
|
|
||||||
|
<p>Ze względu na wydajność obrazy są domyślnie optymalizowane i wysyłane w mniejszym rozmiarze, ale można je wysłać jako „plik”, aby zachować oryginał.</p>
|
||||||
|
|
||||||
<h3 id="multiple-accounts">
|
<h3 id="multiple-accounts">
|
||||||
|
|
||||||
@@ -216,13 +236,15 @@ Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą apli
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Profil składa się z <strong>nazwy, zdjęcia</strong> i dodatkowych informacji służących do szyfrowania wiadomości. Profil jest dostępny tylko na twoim urządzeniu (urządzeniach) i korzysta z serwera wyłącznie do przekazywania wiadomości.</p>
|
<p>A profile is <strong>a name, a picture</strong> and some additional information for encrypting messages.
|
||||||
|
A profile lives on your device(s) only
|
||||||
|
and uses the server only to relay messages.</p>
|
||||||
|
|
||||||
<p>Podczas pierwszej instalacji Delta Chat tworzony jest pierwszy profil.</p>
|
<p>Podczas pierwszej instalacji Delta Chat tworzony jest pierwszy profil.</p>
|
||||||
|
|
||||||
<p>Później możesz dotknąć swojego zdjęcia profilowego w lewym górnym rogu, aby <strong>Dodać profile</strong> lub <strong>Przełączyć profile</strong>.</p>
|
<p>Później możesz dotknąć swojego zdjęcia profilowego w lewym górnym rogu, aby <strong>Dodać profile</strong> lub <strong>Przełączyć profile</strong>.</p>
|
||||||
|
|
||||||
<p>Możesz używać osobnych profili dla aktywności politycznych, rodzinnych lub zawodowych.</p>
|
<p>You may want to use separate profiles for political, family or work related activities.</p>
|
||||||
|
|
||||||
<p>Możesz także dowiedzieć się, <a href="#multiclient">jak używać tego samego profilu na wielu urządzeniach</a>.</p>
|
<p>Możesz także dowiedzieć się, <a href="#multiclient">jak używać tego samego profilu na wielu urządzeniach</a>.</p>
|
||||||
|
|
||||||
@@ -234,19 +256,22 @@ Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą apli
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Możesz dodać zdjęcie profilowe w swoich ustawieniach. Jeśli napiszesz do swoich kontaktów lub dodasz je za pomocą kodu QR, automatycznie zobaczą je jako twoje zdjęcie profilowe.</p>
|
<p>Możesz dodać zdjęcie profilowe w swoich ustawieniach. Jeśli napiszesz do swoich kontaktów lub dodasz je za pomocą kodu QR, automatycznie zobaczą je jako Twoje zdjęcie profilowe.</p>
|
||||||
|
|
||||||
<p>Ze względów prywatności nikt nie widzi twojego zdjęcia profilowego, dopóki nie napiszesz do niego wiadomości.</p>
|
<p>Ze względów prywatności nikt nie widzi Twojego zdjęcia profilowego, dopóki nie napiszesz do niego wiadomości.</p>
|
||||||
|
|
||||||
<h3 id="signature">
|
<h3 id="signature">
|
||||||
|
|
||||||
|
|
||||||
Czy w Delta Chat mogę ustawić biografię/status? <a href="#signature" class="anchor"></a>
|
Can I set a Bio/Status with Delta Chat? <a href="#signature" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Tak, możesz to zrobić w <strong>Ustawieniach → Profil → Biografia</strong>. Po wysłaniu wiadomości do kontaktu zostanie ona wyświetlona, gdy będzie on przeglądał twoje dane kontaktowe.</p>
|
<p>Yes,
|
||||||
|
you can do so under <strong>Settings → Profile → Bio</strong>.
|
||||||
|
Once you sent a message to a contact,
|
||||||
|
they will see it when they view your contact details.</p>
|
||||||
|
|
||||||
<h3 id="co-oznacza-przypinanie-wyciszanie-i-archiwizowanie">
|
<h3 id="co-oznacza-przypinanie-wyciszanie-i-archiwizowanie">
|
||||||
|
|
||||||
@@ -266,7 +291,7 @@ Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą apli
|
|||||||
<p><strong>Wycisz czaty</strong>, jeśli nie chcesz otrzymywać z nich powiadomień. Wyciszone czaty pozostają na swoim miejscu i możesz też przypiąć wyciszony czat.</p>
|
<p><strong>Wycisz czaty</strong>, jeśli nie chcesz otrzymywać z nich powiadomień. Wyciszone czaty pozostają na swoim miejscu i możesz też przypiąć wyciszony czat.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><strong>Archiwizuj czaty</strong>, jeśli nie chcesz ich już widzieć na liście czatów. Pozostają dostępne nad listą czatów lub poprzez wyszukiwanie i są oznaczone jako <b style="border: 1px solid currentColor; padding: 0 3px; font-size:90%">Zarchiwizowane</b></p>
|
<p><strong>Archiwizuj czaty</strong>, jeśli nie chcesz ich już widzieć na liście czatów. Zarchiwizowane czaty pozostają dostępne nad listą czatów lub poprzez wyszukiwanie.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Gdy zarchiwizowany czat otrzyma nową wiadomość, o ile nie zostanie wyciszony, <strong>wyskoczy z archiwum</strong> i wróci na twoją listę czatów.
|
<p>Gdy zarchiwizowany czat otrzyma nową wiadomość, o ile nie zostanie wyciszony, <strong>wyskoczy z archiwum</strong> i wróci na twoją listę czatów.
|
||||||
@@ -297,7 +322,7 @@ Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą apli
|
|||||||
<p>Później otwórz czat „Zapisane wiadomości” — zobaczysz tam zapisane wiadomości. Naciskając <img style="vertical-align:middle; width:1.2em; margin:1px" src="../go-to-original.png" alt="ikona strzałki w prawo" />, możesz wrócić do oryginalnej wiadomości w oryginalnym czacie</p>
|
<p>Później otwórz czat „Zapisane wiadomości” — zobaczysz tam zapisane wiadomości. Naciskając <img style="vertical-align:middle; width:1.2em; margin:1px" src="../go-to-original.png" alt="ikona strzałki w prawo" />, możesz wrócić do oryginalnej wiadomości w oryginalnym czacie</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Na koniec możesz również użyć „Zapisanych wiadomości”, aby robić <strong>osobiste notatki</strong> — otwórz czat, wpisz coś, dodaj zdjęcie lub wiadomość głosową itp.</p>
|
<p>Na koniec możesz również użyć „Zapisz wiadomości”, aby robić <strong>osobiste notatki</strong> — otwórz czat, wpisz coś, dodaj zdjęcie lub wiadomość głosową itp.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Ponieważ „Zapisane wiadomości” są zsynchronizowane, mogą być bardzo przydatne do przesyłania danych między urządzeniami</p>
|
<p>Ponieważ „Zapisane wiadomości” są zsynchronizowane, mogą być bardzo przydatne do przesyłania danych między urządzeniami</p>
|
||||||
@@ -314,9 +339,13 @@ Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą apli
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Czasami można zobaczyć <strong>zieloną kropkę</strong> <img style="vertical-align:middle; width:1.2em; margin:1px" src="../green-dot.png" alt="" /> obok awatara kontaktu. Oznacza to, że był on <strong>niedawno widziany przez ciebie</strong> w ciągu ostatnich 10 minut, np. wysłał ci wiadomość lub potwierdzenie odczytu.</p>
|
<p>You can sometimes see a <strong>green dot</strong> <img style="vertical-align:middle; width:1.2em; margin:1px" src="../green-dot.png" alt="" />
|
||||||
|
next to the avatar of a contact.
|
||||||
|
It means they were <strong>recently seen by you</strong> in the last 10 minutes,
|
||||||
|
e.g. because they messaged you or sent a read receipt.</p>
|
||||||
|
|
||||||
<p>Nie jest to więc status online w czasie rzeczywistym i inni również nie zawsze zobaczą, że jesteś „online”.</p>
|
<p>So this is not a real time online status
|
||||||
|
and others will as well not always see that you are “online”.</p>
|
||||||
|
|
||||||
<h3 id="co-oznaczają-znaczniki-wyświetlane-obok-wiadomości-wychodzących">
|
<h3 id="co-oznaczają-znaczniki-wyświetlane-obok-wiadomości-wychodzących">
|
||||||
|
|
||||||
@@ -328,16 +357,19 @@ Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą apli
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p><strong>Jeden znacznik</strong> <img style="vertical-align:middle; width:1.5em; margin:1px" src="../tick1.png" alt="" /> oznacza, że wiadomość została pomyślnie wysłana do <a href="#relays">przekaźnika</a>.</p>
|
<p><strong>One tick</strong> <img style="vertical-align:middle; width:1.5em; margin:1px" src="../tick1.png" alt="" />
|
||||||
|
means that the message was sent successfully to the <a href="#relays">relay</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><strong>Dwa znaczniki</strong> <img style="vertical-align:middle; width:1.5em; margin:1px" src="../tick2.png" alt="" /> oznaczają, że twój kontakt przeczytał wiadomość.</p>
|
<p><strong>Two ticks</strong> <img style="vertical-align:middle; width:1.5em; margin:1px" src="../tick2.png" alt="" />
|
||||||
|
indicate your contact has read the message.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>W <a href="#groups">grupach</a> drugi znacznik oznacza, że co najmniej jeden członek potwierdził przeczytanie wiadomości.</p>
|
<p>In <a href="#groups">groups</a> the second tick means that at least one member has reported back having read the message.</p>
|
||||||
|
|
||||||
<p>Drugi znacznik pojawi się tylko wtedy, gdy ty i jeden z odbiorców, którzy przeczytali wiadomość, macie włączoną opcję <strong>Ustawienia → Czaty → Potwierdzenie odczytu</strong>.</p>
|
<p>You will only get the second tick if both you and one of the recipients who read the message
|
||||||
|
has <strong>Settings → Chats → Read Receipts</strong> enabled.</p>
|
||||||
|
|
||||||
<h3 id="edit">
|
<h3 id="edit">
|
||||||
|
|
||||||
@@ -360,28 +392,6 @@ Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą apli
|
|||||||
|
|
||||||
<p>Pamiętaj, że oryginalną wiadomość nadal mogą otrzymać członkowie czatu, którzy mogli już odpowiedzieć, przesłać dalej, zapisać, wykonać zrzut ekranu lub w inny sposób skopiować wiadomość.</p>
|
<p>Pamiętaj, że oryginalną wiadomość nadal mogą otrzymać członkowie czatu, którzy mogli już odpowiedzieć, przesłać dalej, zapisać, wykonać zrzut ekranu lub w inny sposób skopiować wiadomość.</p>
|
||||||
|
|
||||||
<h3 id="mediaquality">
|
|
||||||
|
|
||||||
|
|
||||||
Jak obsługiwana jest jakość multimediów? <a href="#mediaquality" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Obrazy, filmy, pliki, wiadomości głosowe itp. można wysyłać za pomocą przycisków: <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Załącz</strong> lub <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /><strong>Wiadomość głosowa</strong>.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Domyślnie kompresja zapewnia <strong>szybką i wydajną dostawę</strong>, respektując limity danych i pamięci wszystkich użytkowników. Jest to idealne rozwiązanie do codziennej komunikacji.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>W regionach o słabszej łączności można wybrać wyższą kompresję w <strong>Ustawieniach → Czaty → Jakość mediów wychodzących</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Jeśli chcesz wysłać multimedia w <strong>oryginalnej jakości</strong>, użyj w czacie opcji <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Załącz → Plik</strong>. Używaj tej metody oszczędnie, ponieważ wysyłanie oryginalnych plików znacznie zwiększy zużycie danych przez ciebie i wszystkich odbiorców na czacie.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="ephemeralmsgs">
|
<h3 id="ephemeralmsgs">
|
||||||
|
|
||||||
|
|
||||||
@@ -392,11 +402,21 @@ Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą apli
|
|||||||
|
|
||||||
<p>Możesz włączyć „znikające wiadomości” w ustawieniach czatu, w prawym górnym rogu okna czatu, wybierając przedział czasu od 5 minut do 1 roku.</p>
|
<p>Możesz włączyć „znikające wiadomości” w ustawieniach czatu, w prawym górnym rogu okna czatu, wybierając przedział czasu od 5 minut do 1 roku.</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 serwerze, jak i w samej aplikacji.</p>
|
<p>Until the setting is turned off again,
|
||||||
|
each chat member’s Delta Chat app takes care
|
||||||
|
of deleting the messages
|
||||||
|
after the selected time span.
|
||||||
|
The time span begins
|
||||||
|
when the receiver first sees the message in Delta Chat.
|
||||||
|
The messages are deleted both,
|
||||||
|
on the servers,
|
||||||
|
and in the apps itself.</p>
|
||||||
|
|
||||||
<p>Pamiętaj, że na znikających wiadomościach możesz polegać tylko wtedy, gdy ufasz swoim partnerom czatu; złośliwi partnerzy czatu mogą robić zdjęcia lub w inny sposób zapisywać, kopiować lub przesyłać dalej wiadomości przed usunięciem.</p>
|
<p>Pamiętaj, że na znikających wiadomościach możesz polegać tylko wtedy, gdy ufasz swoim partnerom czatu; złośliwi partnerzy czatu mogą robić zdjęcia lub w inny sposób zapisywać, kopiować lub przesyłać dalej wiadomości przed usunięciem.</p>
|
||||||
|
|
||||||
<p>Poza tym, jeśli jeden z uczestników czatu odinstaluje aplikację Delta Chat, usunięcie (i tak zaszyfrowanych) wiadomości z jego serwera może potrwać dłużej.</p>
|
<p>Apart from that,
|
||||||
|
if one chat partner uninstalls Delta Chat,
|
||||||
|
the (anyway encrypted) messages may take longer to get deleted from their server.</p>
|
||||||
|
|
||||||
<h3 id="delold">
|
<h3 id="delold">
|
||||||
|
|
||||||
@@ -406,35 +426,46 @@ Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą apli
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Jeśli chcesz zaoszczędzić miejsce na swoim urządzeniu, możesz wybrać opcję automatycznego usuwania starych wiadomości.</p>
|
<p>Jeśli chcesz zaoszczędzić miejsce na urządzeniu, możesz wybrać opcję automatycznego usuwania starych wiadomości.</p>
|
||||||
|
|
||||||
<p>Aby ją włączyć, przejdź do <strong>Ustawienia → Czaty → Usuń wiadomości z urządzenia</strong> . Możesz ustawić przedział czasowy pomiędzy „po 1 godzinie” a „po 1 roku”; w ten sposób <em>wszystkie</em> wiadomości zostaną usunięte z urządzenia, gdy tylko staną się starsze.</p>
|
<p>Aby ją włączyć, przejdź do „Usuń wiadomości z urządzenia” w ustawieniach w sekcji „Czaty i media”. Możesz ustawić przedział czasowy pomiędzy „po 1 godzinie” a „po 1 roku”; w ten sposób <em>wszystkie</em> wiadomości zostaną usunięte z urządzenia, gdy tylko staną się starsze.</p>
|
||||||
|
|
||||||
<h3 id="remove-account">
|
<h3 id="remove-account">
|
||||||
|
|
||||||
|
|
||||||
Jak mogę usunąć swój profil czatu? <a href="#remove-account" class="anchor"></a>
|
How can I delete my chat profile? <a href="#remove-account" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Jeśli używasz więcej niż jednego profilu czatu, możesz usunąć pojedyncze profile w górnym menu przełączania profili (na Androidzie i iOS) lub w pasku bocznym, klikając prawym przyciskiem myszy (w aplikacji na komputery). Profile czatu są usuwane tylko na urządzeniu, na którym nastąpiło usunięcie. Profile czatu na innych urządzeniach będą nadal w pełni działać.</p>
|
<p>If you are using more than one chat profile,
|
||||||
|
you can remove single ones in the top profile switcher menu (on Android and iOS),
|
||||||
|
or in the sidebar with a right click (in the Desktop app).
|
||||||
|
Chat profiles are only removed on the device where deletion was triggered.
|
||||||
|
Chat profiles on other devices will continue to fully function.</p>
|
||||||
|
|
||||||
<p>Jeśli używasz jednego domyślnego profilu czatu, możesz po prostu odinstalować aplikację. Spowoduje to automatyczne usunięcie wszystkich powiązanych danych adresowych na serwerze czatu. Aby uzyskać więcej informacji, zapoznaj się z informacjami o <a href="https://nine.testrun.org/info.html#account-deletion">usuwaniu adresów na stronie nine.testrun.org</a> lub odpowiednią stroną wybranego <a href="https://chatmail.at/relays">serwera czatu innej firmy</a>.</p>
|
<p>If you use a single default chat profile you can simply uninstall the app.
|
||||||
|
This will still automatically trigger deletion of all associated address data on the chatmail server.
|
||||||
|
For more info, please refer to <a href="https://nine.testrun.org/info.html#account-deletion">nine.testrun.org address-deletion</a>
|
||||||
|
or the respective page from your chosen <a href="https://chatmail.at/relays">3rd party chatmail server</a>.</p>
|
||||||
|
|
||||||
<h2 id="groups">
|
<h2 id="groups">
|
||||||
|
|
||||||
|
|
||||||
Grupy <a href="#groups" class="anchor"></a>
|
Groups <a href="#groups" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>Grupy pozwalają kilku osobom na prywatną rozmowę na <strong>równych prawach</strong>.</p>
|
<p>Groups let several people chat together privately with <strong>equal rights</strong>.</p>
|
||||||
|
|
||||||
<p>Każdy może zmienić nazwę grupy lub awatar, <a href="#addmembers">dodawać lub usuwać członków</a>, ustawiać <a href="#ephemeralmsgs">znikające wiadomości</a> oraz <a href="#edit">usuwać własne wiadomości</a> z urządzeń wszystkich członków.</p>
|
<p>Anyone can
|
||||||
|
change the group name or avatar,
|
||||||
|
<a href="#addmembers">add or remove members</a>,
|
||||||
|
set <a href="#ephemeralmsgs">disappearing messages</a>,
|
||||||
|
and <a href="#edit">delete their own messages</a> from all member’s devices.</p>
|
||||||
|
|
||||||
<p>Ponieważ wszyscy członkowie mają te same uprawnienia, grupy najlepiej sprawdzają się w gronie <strong>zaufanych przyjaciół i rodziny</strong>.</p>
|
<p>Because all members have the same rights, groups work best among <strong>trusted friends and family</strong>.</p>
|
||||||
|
|
||||||
<h3 id="tworzenie-grupy">
|
<h3 id="tworzenie-grupy">
|
||||||
|
|
||||||
@@ -449,37 +480,43 @@ Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą apli
|
|||||||
<p>Wybierz <strong>Nowy czat</strong>, a następnie <strong>Nowa grupa</strong> z menu w prawym górnym rogu lub naciśnij odpowiedni przycisk na Androidzie / iOS.</p>
|
<p>Wybierz <strong>Nowy czat</strong>, a następnie <strong>Nowa grupa</strong> z menu w prawym górnym rogu lub naciśnij odpowiedni przycisk na Androidzie / iOS.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Na następnym ekranie wybierz <strong>członków grupy</strong> i zdefiniuj <strong>nazwę grupy</strong>. Możesz też wybrać <strong>awatar grupy</strong>.</p>
|
<p>Na następnym ekranie wybierz <strong>członków grupy</strong> i zdefiniuj <strong>nazwę grupy</strong>. Możesz też wybrać awatar <strong>grupy</strong>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Gdy tylko napiszesz <strong>pierwszą wiadomość</strong> w grupie, wszyscy członkowie zostaną poinformowani o nowej grupie i będą mogli odpowiadać w grupie (dopóki nie napiszesz wiadomości w grupie, grupa będzie niewidoczna dla członków).</p>
|
<p>Zaraz po napisaniu pierwszej wiadomości w grupie wszyscy członkowie zostaną poinformowani o nowej grupie i mogą odpowiedzieć w grupie (jeżeli nie napiszesz wiadomości w grupie, grupa jest niewidoczna dla członków).</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3 id="addmembers">
|
<h3 id="addmembers">
|
||||||
|
|
||||||
|
|
||||||
Dodawanie i usuwanie członków <a href="#addmembers" class="anchor"></a>
|
Add and remove members <a href="#addmembers" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Wszyscy członkowie grupy mają <strong>takie same uprawnienia</strong>. Z tego powodu każdy może usunąć dowolnego członka lub dodać nowych.</p>
|
<p>All group members have the <strong>same rights</strong>.
|
||||||
|
For this reason, everyone can delete any member or add new ones.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Aby <strong>dodać lub usunąć członków</strong>, dotknij nazwę grupy na czacie i wybierz członka, którego chcesz dodać lub usunąć.</p>
|
<p>To <strong>add or delete members</strong>, tap the group name in the chat and select the member to add or remove.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Jeśli członek nie znajduje się jeszcze na twojej liście kontaktów, ale rozmawiasz z nim <strong>twarzą w twarz</strong>, na tym samym ekranie pokaż mu <strong>kod QR</strong>.
|
<p>If the member is not yet in your contact list, but <strong>face to face</strong> with you,
|
||||||
Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą aplikacji Delta Chat, dotykając <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> na ekranie głównym.</p>
|
from the same screen, show a <strong>QR code</strong>.<br />
|
||||||
|
Ask your chat partner to <strong>scan</strong> the QR image with their Delta Chat app by tapping
|
||||||
|
<img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> on the main screen.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Aby dodać członka <strong>zdalnie</strong>, naciśnij „Kopiuj” lub „Udostępnij” i wyślij <strong>link zaproszenia</strong> nowemu członkowi za pośrednictwem innego prywatnego czatu.</p>
|
<p>For a <strong>remote</strong> member addition,
|
||||||
|
click “Copy” or “Share” and send the <strong>invite link</strong>
|
||||||
|
through another private chat to the new member.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Kod QR i link zaproszenia można wykorzystać do dodania kilku członków. Ponieważ jednak grupy są <a href="#groups">przeznaczone dla zaufanych osób</a>, unikaj udostępniania ich publicznie.</p>
|
<p>QR code and invite link can be used to add several members.
|
||||||
|
However, since groups are <a href="#groups">meant for trusted people</a>, avoid sharing them publicly.</p>
|
||||||
|
|
||||||
<h3 id="usunąłem-się-przez-przypadek">
|
<h3 id="usunąłem-się-przez-przypadek">
|
||||||
|
|
||||||
@@ -489,7 +526,8 @@ Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą apli
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Ponieważ nie jesteś członkiem grupy, nie możesz dodać siebie ponownie. Jednak nie ma problemu, po prostu poproś dowolnego członka grupy na normalnym czacie, aby dodał cię ponownie.</p>
|
<p>Ponieważ nie jesteś członkiem grupy, nie możesz dodać siebie ponownie.
|
||||||
|
Jednak nie ma problemu, po prostu poproś dowolnego członka grupy na normalnym czacie, aby dodał cię ponownie.</p>
|
||||||
|
|
||||||
<h3 id="nie-chcę-już-otrzymywać-wiadomości-od-grupy">
|
<h3 id="nie-chcę-już-otrzymywać-wiadomości-od-grupy">
|
||||||
|
|
||||||
@@ -504,203 +542,47 @@ Poproś partnera czatu o <strong>zeskanowanie</strong> obrazu QR za pomocą apli
|
|||||||
Jeśli później będziesz chciał ponownie dołączyć do grupy, poproś innego członka grupy, aby dodał cię do grupy.</li>
|
Jeśli później będziesz chciał ponownie dołączyć do grupy, poproś innego członka grupy, aby dodał cię do grupy.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Alternatywnie możesz też „Wyłączyć powiadomienia” dla grupy, dzięki temu otrzymasz wszystkie wiadomości i nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych nowych wiadomościach.</p>
|
<p>Alternatywnie możesz też „Wyłączyć powiadomienia” dla grupy dzięki temu otrzymasz wszystkie wiadomości i
|
||||||
|
nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych nowych wiadomościach.</p>
|
||||||
|
|
||||||
<h3 id="klonowanie-grupy">
|
<h3 id="cloning-a-group">
|
||||||
|
|
||||||
|
|
||||||
Klonowanie grupy <a href="#klonowanie-grupy" class="anchor"></a>
|
Cloning a group <a href="#cloning-a-group" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Możesz zduplikować grupę, aby rozpocząć osobną dyskusję lub wykluczyć członków bez ich wiedzy.</p>
|
<p>You can duplicate a group to start a separate discussion
|
||||||
|
or to exclude members without them noticing.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Otwórz profil grupy i dotknij opcji <strong>Klonuj czat</strong> (Android/iOS) lub kliknij prawym przyciskiem myszy grupę na liście czatów (komputer).</p>
|
<p>Open the group profile and tap <strong>Clone Chat</strong> (Android/iOS),
|
||||||
|
or right-click the group in the chat list (Desktop).</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Ustaw nową nazwę, wybierz awatar i w razie potrzeby dostosuj listę członków.</p>
|
<p>Set a new name, choose an avatar, and adjust the member list if needed.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Nowa grupa jest <strong>w pełni niezależna</strong> od oryginalnej, która nadal działa jak dotychczas.</p>
|
<p>The new group is <strong>fully independent</strong> from the original,
|
||||||
|
which continues to work as before.</p>
|
||||||
|
|
||||||
<h3 id="ilu-członków-może-należeć-do-jednej-grupy">
|
<h3 id="how-many-members-can-participate-in-a-single-group">
|
||||||
|
|
||||||
|
|
||||||
Ilu członków może należeć do jednej grupy? <a href="#ilu-członków-może-należeć-do-jednej-grupy" class="anchor"></a>
|
How many members can participate in a single group? <a href="#how-many-members-can-participate-in-a-single-group" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Nie ma ścisłego limitu technicznego, ale nie zaleca się przekraczania 150 osób.</p>
|
<p>There is no strict technical limit,
|
||||||
|
but more than 150 is not recommended.</p>
|
||||||
|
|
||||||
<p>W miarę jak grupy się rozrastają, mogą stawać się niestabilne społecznie i wymagać hierarchii – gdzie Delta Chat pełni rolę prywatnego komunikatora do czatowania na <a href="#groups">równych prawach</a>. Więcej informacji znajdziesz w artykule <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Liczba Dunbara</a>.</p>
|
<p>As groups get larger, they can become socially unstable and may need a hierarchy -
|
||||||
|
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
||||||
<h2 id="channels">
|
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
||||||
|
|
||||||
|
|
||||||
Kanały <a href="#channels" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Kanały to narzędzie typu jeden do wielu, służące do nadawania wiadomości.</p>
|
|
||||||
|
|
||||||
<h3 id="subskrybowanie-kanału">
|
|
||||||
|
|
||||||
|
|
||||||
Subskrybowanie kanału <a href="#subskrybowanie-kanału" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Zeskanuj <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>kod QR</strong> lub naciśnij link zaproszenia otrzymany od właściciela kanału.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>To wszystko! Otrzymasz kilka wiadomości z historii kanału, a od tego momentu wszystkie nowe wiadomości z kanału.</p>
|
|
||||||
|
|
||||||
<p><strong>Nie martw się</strong>, jeśli to nie nastąpi od razu. Gdy właściciel kanału będzie online, twoja prośba o dołączenie zostanie przetworzona.</p>
|
|
||||||
|
|
||||||
<p>Podobnie jak cała platforma Delta Chat, również kanały są prywatne i zdecentralizowane, dlatego nie ma możliwości publicznego ujawnienia.</p>
|
|
||||||
|
|
||||||
<p>Inni subskrybenci kanału nie zobaczą, że go subskrybujesz i nie będą mogli wysyłać ci wiadomości. Właściciel kanału może jednak napisać do ciebie. Zobaczy również, że przeczytałeś wiadomość, chyba że masz wyłączone potwierdzenia odczytu.</p>
|
|
||||||
|
|
||||||
<p>Jeśli nie chcesz udostępniać swojego głównego profilu, możesz również utworzyć <a href="#multiple-accounts">dedykowany profil</a> do dołączenia do kanału.</p>
|
|
||||||
|
|
||||||
<h3 id="tworzenie-kanału">
|
|
||||||
|
|
||||||
|
|
||||||
Tworzenie kanału <a href="#tworzenie-kanału" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Naciśnij <strong>Nowy cza</strong> i wybierz <strong>Nowy kanał</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Wprowadź <strong>nazwę</strong>, opcjonalnie ustaw <strong>obraz</strong> i <strong>opis</strong>, a następnie naciśnij przycisk <strong>Utwórz</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Możesz teraz wysyłać i zarządzać wiadomościami jak zwykle.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Z profilu kanału <strong>udostępnij kod QR lub link zaproszenia innym osobom</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Subskrybenci będą otrzymywać twoje wiadomości, ale nie będą mogli wysyłać wiadomości na twoim kanale. Po zasubskrybowaniu otrzymają <strong>kilka najnowszych wiadomości z historii kanału</strong>.</p>
|
|
||||||
|
|
||||||
<p>Obok każdej wiadomości jest widoczna <strong>liczba wyświetleń</strong>. Pamiętaj, że uwzględnia ona tylko subskrybentów z włączonymi potwierdzeniami odczytu, więc rzeczywista liczba wyświetleń może być wyższa.</p>
|
|
||||||
|
|
||||||
<h3 id="ilu-subskrybentów-może-mieć-kanał">
|
|
||||||
|
|
||||||
|
|
||||||
Ilu subskrybentów może mieć kanał? <a href="#ilu-subskrybentów-może-mieć-kanał" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Kanały są przeznaczone dla znacznie większej publiczności niż <a href="#groups">grupy</a>.</p>
|
|
||||||
|
|
||||||
<p>Praktyczny limit zależy od używanego <a href="#relays">przekaźnika</a>, więc nie ma jednej, stałej liczby, która obowiązywałaby wszędzie.</p>
|
|
||||||
|
|
||||||
<p>W przypadku naprawdę dużych kanałów z dziesiątkami tysięcy subskrybentów zalecamy użycie <a href="#multiple-accounts">dedykowanego profilu</a> dla kanału i sprawdzenie, czy przekaźnik jest odpowiedni.</p>
|
|
||||||
|
|
||||||
<p>Ale nie wahaj się zbytnio: Delta Chat został zaprojektowany tak, aby nie był zależny od przekaźnika, więc możesz go łatwo zmienić w dowolnym momencie – twoi obecni subskrybenci nawet tego nie zauważą. W takim przypadku wystarczy zaktualizować link zaproszenia udostępniany nowym subskrybentom.</p>
|
|
||||||
|
|
||||||
<h2 id="calls">
|
|
||||||
|
|
||||||
|
|
||||||
Połączenia <a href="#calls" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Delta Chat umożliwia indywidualne <strong>połączenia audio i wideo</strong>.</p>
|
|
||||||
|
|
||||||
<p>Połączenia są obsługiwane na komputerach stacjonarnych, Ubuntu Touch, iOS oraz Androidzie 8 i nowszych.</p>
|
|
||||||
|
|
||||||
<h3 id="nawiązywanie-połączenia">
|
|
||||||
|
|
||||||
|
|
||||||
Nawiązywanie połączenia <a href="#nawiązywanie-połączenia" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>W czacie indywidualnym dotknij <strong>ikony połączenia</strong> 📞.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Otworzy się małe menu, w którym możesz wybrać, czy chcesz nawiązać <strong>połączenie audio</strong>, czy <strong>wideo</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="odbieranie-lub-odrzucanie-połączenia">
|
|
||||||
|
|
||||||
|
|
||||||
Odbieranie lub odrzucanie połączenia <a href="#odbieranie-lub-odrzucanie-połączenia" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Gdy ktoś do ciebie dzwoni, Delta Chat wyświetla <strong>ekran połączenia przychodzącego</strong> lub powiadomienie.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Dotknij <strong>Akceptuj</strong>, aby odebrać, lub <strong>Odrzuć</strong>, aby odrzucić połączenie.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="w-trakcie-połączenia">
|
|
||||||
|
|
||||||
|
|
||||||
W trakcie połączenia <a href="#w-trakcie-połączenia" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Możesz <strong>wyciszyć</strong> mikrofon.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Możesz <strong>włączyć lub wyłączyć kamerę</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Na urządzeniach mobilnych możesz <strong>przełączać się między przednią i tylną kamerą</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>W zależności od urządzenia możesz również wybrać wyjście audio lub skorzystać z trybu obrazu w obrazie. Na komputerach stacjonarnych połączenie jest wyświetlane w dedykowanym oknie i możesz kontynuować korzystanie z głównego okna Delta Chat jak zwykle.</p>
|
|
||||||
|
|
||||||
<h3 id="nieodebrane-połączenia-i-powiadomienia">
|
|
||||||
|
|
||||||
|
|
||||||
Nieodebrane połączenia i powiadomienia <a href="#nieodebrane-połączenia-i-powiadomienia" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Jeśli nie odbierzesz, nie usłyszysz dzwonka lub nie będziesz mieć urządzenia pod ręką, połączenie zostanie oznaczone jako <strong>nieodebrane</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><strong>Tylko zaakceptowane przez ciebie kontakty</strong> mogą wywołać dzwonek na urządzeniu. Prośby o kontakt będą wyświetlane normalnie i nie będą dzwonić.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>W <strong>Ustawienia → Powiadomienia → Połączenia</strong> możesz całkowicie wyłączyć specjalny ekran dzwonka. Jeśli to zrobisz, nie będzie ci przeszkadzał żaden dzwonek, a połączenie nadal będzie można odebrać, dotykając w czacie dymku wiadomości o przychodzącym połączeniu.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="webxdc">
|
<h2 id="webxdc">
|
||||||
|
|
||||||
@@ -954,7 +836,8 @@ Welcome to the power of the interoperable chatmail relay network :)</p>
|
|||||||
<p>Sprawdź dokładnie, czy oba urządzenia są w tym <strong>samym Wi-Fi lub tej samej sieci</strong></p>
|
<p>Sprawdź dokładnie, czy oba urządzenia są w tym <strong>samym Wi-Fi lub tej samej sieci</strong></p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Na <strong>Windowsie</strong>, przejdź do „Panel sterowania / Sieć i internet” i upewnij się, że <strong>Sieć prywatna</strong> jest wybrana jako „Typ profilu sieci” (po przeniesieniu możesz wrócić do pierwotnej wartości)</p>
|
<p>Na <strong>Windowsie</strong>, przejdź do “Panel sterowania / Sieć i internet” i upewnij się, że <strong>Sieć prywatna</strong> jest wybrana jako “Typ profilu sieci”
|
||||||
|
(po przeniesieniu możesz wrócić do pierwotnej wartości)</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>W systemie <strong>iOS</strong> upewnij się, że jest przydzielony dostęp do opcji „Ustawienia » Aplikacje » Delta Chat » <strong>Sieć lokalna</strong>”</p>
|
<p>W systemie <strong>iOS</strong> upewnij się, że jest przydzielony dostęp do opcji „Ustawienia » Aplikacje » Delta Chat » <strong>Sieć lokalna</strong>”</p>
|
||||||
@@ -998,14 +881,15 @@ Welcome to the power of the interoperable chatmail relay network :)</p>
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Na starym urządzeniu przejdź do <strong>Ustawienia → Czaty → Eksport kopii zapasowej</strong>. Wprowadź swój PIN odblokowania ekranu, wzór lub hasło. Następnie możesz nacisnąć „Utwórz kopię”. Spowoduje to zapisanie pliku kopii zapasowej na urządzeniu. Teraz musisz jakoś przenieść go na inne urządzenie.</p>
|
<p>Na starym urządzeniu przejdź do <strong>Ustawienia → Czaty i media → Eksport kopii zapasowej</strong>. Wprowadź swój PIN odblokowania ekranu, wzór lub hasło. Następnie możesz nacisnąć „Utwórz kopię”. Spowoduje to zapisanie pliku kopii zapasowej na urządzeniu. Teraz musisz jakoś przenieść go na inne urządzenie.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Na nowym urządzeniu wybierz: <strong>Mam już profil → Przywróć z kopii zapasowej</strong>. Jeśli korzystasz z iOS i napotykasz trudności, może <a href="https://support.delta.chat/t/import-backup-to-ios/1628">ten poradnik</a> ci pomoże.</p>
|
<p>Na nowym urządzeniu, na ekranie logowania, zamiast logować się na swoje konto e-mail, wybierz <strong>Przywróć z kopii zapasowej</strong>. Po zaimportowaniu Twoje rozmowy, klucze szyfrujące i multimedia powinny zostać skopiowane na nowe urządzenie.
|
||||||
|
Jeśli korzystasz z iOS i napotykasz trudności, może <a href="https://support.delta.chat/t/import-backup-to-ios/1628">ten poradnik</a> Ci pomoże.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Jesteś teraz zsynchronizowany i w komunikacji ze swoimi partnerami możesz używać obu urządzeń do wysyłania i odbierania wiadomości zaszyfrowanych metodą end-to-end.</p>
|
<p>Jesteś teraz zsynchronizowany i możesz używać obu urządzeń do wysyłania i odbierania wiadomości zaszyfrowanych end-to-end w komunikacji ze swoimi partnerami.</p>
|
||||||
|
|
||||||
<h3 id="czy-są-jakieś-plany-wprowadzenia-klienta-web-delta-chat">
|
<h3 id="czy-są-jakieś-plany-wprowadzenia-klienta-web-delta-chat">
|
||||||
|
|
||||||
@@ -1062,26 +946,22 @@ Relays are operated by different groups and people.</p>
|
|||||||
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
||||||
so you do not need to care about that.
|
so you do not need to care about that.
|
||||||
However, if you want to,
|
However, if you want to,
|
||||||
you can configure relays at <strong>Settings → Advanced → Relays</strong>:</p>
|
you can configure relays at At <strong>Settings → Advanced → Relays</strong>:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
||||||
<a href="https://chatmail.at/relays">chatmail.at/relays</a> shows some known ones.
|
<a href="https://chatmail.at/relays">https://chatmail.at/relays</a> shows some known ones.
|
||||||
If you have multiple relays, you will receive messages on all of them.
|
If you have multiple relays, you will receive messages on all of them.</p>
|
||||||
Contacts learn your current relays automatically when you message them.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Tap on a relay to set it as <strong>used for sending</strong>.</p>
|
<p>The <strong>default</strong> defines the one where your chat partners send future messages to.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>If you <strong>remove</strong> a relay,
|
<p>If you <strong>remove</strong> a relay,
|
||||||
contacts who only know this relay may not reach you until you message them again.
|
make sure another default relay was used for a sufficient amount of time.
|
||||||
To stay reachable in the meantime, choose <strong>Hide from Contacts</strong> in the confirmation dialog
|
Otherwise, messages from your chat partners won’t reach you.
|
||||||
instead of removing it right away.</p>
|
If in doubt, remove later.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>To <strong>show</strong> a hidden relay again, tap on it.</p>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -1222,10 +1102,6 @@ weekly statistics will be automatically sent to a bot.</p>
|
|||||||
<li>
|
<li>
|
||||||
<p><a href="https://autocrypt.org">Autocrypt</a> służy do automatycznego ustanawiania szyfrowania typu end-to-end między kontaktami a wszystkimi członkami czatu grupowego.</p>
|
<p><a href="https://autocrypt.org">Autocrypt</a> służy do automatycznego ustanawiania szyfrowania typu end-to-end między kontaktami a wszystkimi członkami czatu grupowego.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
|
||||||
will bring post-quantum resistant encryption and forward secrecy.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Udostępnienie kontaktu na czacie</a> umożliwia odbiorcom korzystanie z szyfrowania typu end-to-end z tym kontaktem.</p>
|
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Udostępnienie kontaktu na czacie</a> umożliwia odbiorcom korzystanie z szyfrowania typu end-to-end z tym kontaktem.</p>
|
||||||
</li>
|
</li>
|
||||||
@@ -1360,10 +1236,12 @@ even if the message was not end-to-end encrypted.</p>
|
|||||||
<p>Servers can therefore only see:</p>
|
<p>Servers can therefore only see:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Sender and receiver addresses, randomly generated by default</li>
|
<li>the sender and receiver addresses</li>
|
||||||
<li>Message size</li>
|
<li>and the message size.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>By default, the addresses are randomly generated.</p>
|
||||||
|
|
||||||
<p>Wszystkie pozostałe metadane dotyczące wiadomości, kontaktów i grup znajdują się w zaszyfrowanej metodą end-to-end części wiadomości.</p>
|
<p>Wszystkie pozostałe metadane dotyczące wiadomości, kontaktów i grup znajdują się w zaszyfrowanej metodą end-to-end części wiadomości.</p>
|
||||||
|
|
||||||
<h3 id="device-seizure">
|
<h3 id="device-seizure">
|
||||||
@@ -1392,20 +1270,23 @@ can not be identified easily.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>The used <a href="#relays">relays</a> need to know your IP Address,
|
<p>The used <a href="#relays">relay</a> needs to know your IP Address,
|
||||||
as well as sometimes your contact’s devices if you have a <a href="#calls">call</a>
|
as well as sometimes your contact’s devices if you have a <a href="#experiments">call</a>
|
||||||
or use <a href="#webxdc">apps</a> together.</p>
|
or use <a href="#webxdc">apps</a> together.</p>
|
||||||
|
|
||||||
<p>IP Addresses are needed for connectivity and efficiency.
|
<p>IP Addresses are needed for connectivity and efficiency.
|
||||||
Delta Chat neither persists nor exposes them.
|
They are neither persisted nor exposed.
|
||||||
Note that IP Addresses
|
Note that the IP Address
|
||||||
are not like an address you give to a delivery service,
|
is not like a detailed address you give to a delivery service,
|
||||||
but typically less precise, often defining city or region only.</p>
|
but much more coarse, often defining region or country only.</p>
|
||||||
|
|
||||||
<p>If you see your IP Address as a risk,
|
<p>As this is just how the internet and other messengers work by default,
|
||||||
we recommend to use a VPN for the whole system.
|
we do not offer options here or ask upfront questions.</p>
|
||||||
Per-app options leave gaps across your system.
|
|
||||||
For example, tapping a link can expose IP Addresses to unknown parties, which is by far the larger risk.</p>
|
<p>If you see your IP Address as a security or privacy risk,
|
||||||
|
we recommend to use a VPN, in combination with system lockdown mode.
|
||||||
|
Hunting down options in all apps on your system will leave gaps.
|
||||||
|
For example, tapping a link exposes IP Addresses to unknown parties and is the by far larger risk here.</p>
|
||||||
|
|
||||||
<h3 id="sealedsender">
|
<h3 id="sealedsender">
|
||||||
|
|
||||||
@@ -1433,13 +1314,11 @@ but an implementation has not been agreed as a priority yet.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>Nie, jeszcze nie.</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>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><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<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>
|
||||||
will provide reliable deletion (forward secrecy) through automatic key rotation.
|
|
||||||
This approach is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
|
||||||
|
|
||||||
<h3 id="pqc">
|
<h3 id="pqc">
|
||||||
|
|
||||||
@@ -1449,13 +1328,9 @@ This approach is specified in the <a href="https://datatracker.ietf.org/doc/draf
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>Nie, jeszcze nie.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<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>
|
||||||
will bring post-quantum resistant encryption to protect against quantum computer attacks.
|
|
||||||
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>.
|
|
||||||
The implementation is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
|
||||||
|
|
||||||
<h3 id="jak-mogę-ręcznie-sprawdzić-informacje-o-szyfrowaniu">
|
<h3 id="jak-mogę-ręcznie-sprawdzić-informacje-o-szyfrowaniu">
|
||||||
|
|
||||||
@@ -1513,7 +1388,7 @@ od najnowszych do najstarszych:</p>
|
|||||||
<p>W kwietniu 2023 r. naprawiliśmy problemy z bezpieczeństwem i prywatnością w funkcji „aplikacje internetowe udostępniane na czacie”, związane z awariami piaskownicy, szczególnie w przypadku Chromium. Następnie przeprowadziliśmy niezależny audyt bezpieczeństwa od Cure53 i wszystkie wykryte problemy zostały naprawione w aplikacji z serii 1.36 wydanej w kwietniu 2023 r. <a href="https://delta.chat/en/2023-05-22-webxdc-security">Pełną historię bezpieczeństwa end-to-end w sieci można znaleźć tutaj</a>.</p>
|
<p>W kwietniu 2023 r. naprawiliśmy problemy z bezpieczeństwem i prywatnością w funkcji „aplikacje internetowe udostępniane na czacie”, związane z awariami piaskownicy, szczególnie w przypadku Chromium. Następnie przeprowadziliśmy niezależny audyt bezpieczeństwa od Cure53 i wszystkie wykryte problemy zostały naprawione w aplikacji z serii 1.36 wydanej w kwietniu 2023 r. <a href="https://delta.chat/en/2023-05-22-webxdc-security">Pełną historię bezpieczeństwa end-to-end w sieci można znaleźć tutaj</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>W marcu 2023 r. firma <a href="https://cure53.de">Cure53</a> przeanalizowała zarówno szyfrowanie transportu połączeń sieciowych Delta Chat, jak i powtarzalną konfigurację serwera pocztowego zgodnie z <a href="https://delta.chat/serverguide">zaleceniami na tej stronie</a>. Możesz przeczytać więcej o audycie <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">na naszym blogu</a> lub przeczytać pełny raport <a href="https://delta.chat/assets/blog/MER-01-report.pdf">tutaj</a>.</p>
|
<p>W marcu 2023 r. firma <a href="https://cure53.de">Cure53</a> przeanalizowała zarówno szyfrowanie transportu połączeń sieciowych Delta Chat, jak i powtarzalną konfigurację serwera pocztowego zgodnie z <a href="https://delta.chat/pl/serverguide">zaleceniami na tej stronie</a>. Możesz przeczytać więcej o audycie <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">na naszym blogu</a> lub przeczytać pełny raport <a href="https://delta.chat/assets/blog/MER-01-report.pdf">tutaj</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>W 2020 r. firma <a href="https://includesecurity.com">Include Security</a> przeanalizowała biblioteki Rust <a href="https://github.com/deltachat/deltachat-core-rust/">core</a>, <a href="https://github.com/async-email/async-imap">IMAP</a>, <a href="https://github.com/async-email/async-smtp">SMTP</a> i <a href="https://github.com/async-email/async-native-tls">TLS</a> Delta Chat. Nie znalazła żadnych problemów krytycznych ani poważnych. W raporcie zwrócono uwagę na kilka słabych punktów o średniej wadze – same w sobie nie stanowią zagrożenia dla użytkowników Delta Chat, ponieważ zależą od środowiska, w którym używany jest Delta Chat. Ze względu na użyteczność i kompatybilność nie możemy złagodzić wszystkich z nich i zdecydowaliśmy się przedstawić zalecenia dotyczące bezpieczeństwa zagrożonym użytkownikom. Pełny raport można przeczytać <a href="https://delta.chat/assets/blog/2020-second-security-review.pdf">tutaj</a>.</p>
|
<p>W 2020 r. firma <a href="https://includesecurity.com">Include Security</a> przeanalizowała biblioteki Rust <a href="https://github.com/deltachat/deltachat-core-rust/">core</a>, <a href="https://github.com/async-email/async-imap">IMAP</a>, <a href="https://github.com/async-email/async-smtp">SMTP</a> i <a href="https://github.com/async-email/async-native-tls">TLS</a> Delta Chat. Nie znalazła żadnych problemów krytycznych ani poważnych. W raporcie zwrócono uwagę na kilka słabych punktów o średniej wadze – same w sobie nie stanowią zagrożenia dla użytkowników Delta Chat, ponieważ zależą od środowiska, w którym używany jest Delta Chat. Ze względu na użyteczność i kompatybilność nie możemy złagodzić wszystkich z nich i zdecydowaliśmy się przedstawić zalecenia dotyczące bezpieczeństwa zagrożonym użytkownikom. Pełny raport można przeczytać <a href="https://delta.chat/assets/blog/2020-second-security-review.pdf">tutaj</a>.</p>
|
||||||
@@ -1588,17 +1463,32 @@ Raczej korzystamy z publicznych źródeł finansowania, jak dotąd pochodzących
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>W latach 2023 i 2024 zostaliśmy przyjęci do programu Next Generation Internet (NGI) za naszą pracę w <a href="https://nlnet.nl/project/WebXDC-Push/">webxdc PUSH</a>, wraz z partnerami współpracującymi pracującymi nad <a href="https://nlnet.nl/project/Webxdc-Evolve/">webxdc evolve</a>, <a href="https://nlnet.nl/project/WebXDC-XMPP/">webxdc XMPP</a>, <a href="https://nlnet.nl/project/DeltaTouch/">DeltaTouch</a> i <a href="https://nlnet.nl/project/DeltaTauri/">DeltaTauri</a>. Wszystkie te projekty są częściowo ukończone lub zostaną ukończone na początku 2025 r.</p>
|
<p>In 2023 and 2024 we got accepted in the Next Generation Internet (NGI)
|
||||||
|
program for our work in <a href="https://nlnet.nl/project/WebXDC-Push/">webxdc PUSH</a>,
|
||||||
|
along with collaboration partners working on
|
||||||
|
<a href="https://nlnet.nl/project/Webxdc-Evolve/">webxdc evolve</a>,
|
||||||
|
<a href="https://nlnet.nl/project/WebXDC-XMPP/">webxdc XMPP</a>,
|
||||||
|
<a href="https://nlnet.nl/project/DeltaTouch/">DeltaTouch</a> and
|
||||||
|
<a href="https://nlnet.nl/project/DeltaTauri/">DeltaTauri</a>.
|
||||||
|
All of these projects are partially completed or to be completed in early 2025.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>W 2021 r. otrzymaliśmy kolejne dofinansowanie z UE na dwie propozycje dotyczące Internetu nowej generacji, a mianowicie na <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD – katalog przenośności dostawcy poczty e-mail</a> ( ~97 tys. EUR) i <a href="https://nlnet.nl/project/EmailPorting/">AEAP – przenoszenie adresu e-mail</a> (~90 tys. EUR), co zaowocowało lepszą obsługą wielu kont, ulepszonymi kontaktami i ustawieniami grup za pomocą kodów QR oraz wieloma ulepszeniami sieciowymi na wszystkich platformach.</p>
|
<p>In 2021 we received further EU funding for two Next-Generation-Internet
|
||||||
|
proposals, namely for <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - email provider portability directory</a> (~97K EUR) and <a href="https://nlnet.nl/project/EmailPorting/">AEAP - email address porting</a> (~90K EUR) which resulted in better multi-profile support, improved QR-code contact and group setups and many networking improvements on all platforms.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><a href="https://nlnet.nl/">Fundacja NLnet</a> przekazała w latach 2019/2020 kwotę 46 tys. EUR na wykonanie wiązań Rust/Python i uruchomienie ekosystemu Chat-bot.</p>
|
<p>The <a href="https://nlnet.nl/">NLnet foundation</a> granted in 2019/2020 EUR 46K for
|
||||||
|
completing Rust/Python bindings and instigating a Chat-bot eco-system.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><a href="https://opentechfund.org">Open Technology Fund</a> przyznał nam pierwszy grant w 2018/2019 (~200 000 $), dzięki któremu znacznie ulepszyliśmy aplikację na Androida i wydaliśmy pierwszą wersję beta aplikacji na komputery stacjonarne, a także ugruntował rozwój naszych funkcji w badaniach UX w kontekście praw człowieka, zobacz nasz końcowy raport <a href="https://delta.chat/en/2019-07-19-uxreport">Needfinding and UX</a>.
|
<p>The <a href="https://opentechfund.org">Open Technology Fund</a> gave us a
|
||||||
Druga dotacja w 2019/2020 (~300 000 4) pomogła nam wydać wersje Delta/iOS, przekonwertować naszą podstawową bibliotekę na Rust i zapewnić nowe funkcje dla wszystkich platform.</p>
|
first 2018/2019 grant (~$200K) during which we majorly improved the Android app
|
||||||
|
and released a first Desktop app beta version, and which moreover
|
||||||
|
moored our feature developments in UX research in human rights contexts,
|
||||||
|
see our concluding <a href="https://delta.chat/en/2019-07-19-uxreport">Needfinding and UX report</a>.
|
||||||
|
The second 2019/2020 grant (~$300K) helped us to
|
||||||
|
release Delta/iOS versions, to convert our core library to Rust, and
|
||||||
|
to provide new features for all platforms.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Unijny projekt <a href="https://nextleap.eu">NEXTLEAP</a> sfinansował badania i wdrożenie zweryfikowanych grup i ustawień protokołów kontaktowych w latach 2017 i 2018, a także pomógł zintegrować szyfrowanie end-to-end poprzez <a href="https://autocrypt.org">Autocrypt</a>.</p>
|
<p>Unijny projekt <a href="https://nextleap.eu">NEXTLEAP</a> sfinansował badania i wdrożenie zweryfikowanych grup i ustawień protokołów kontaktowych w latach 2017 i 2018, a także pomógł zintegrować szyfrowanie end-to-end poprzez <a href="https://autocrypt.org">Autocrypt</a>.</p>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<li><a href="#howtoe2ee">Como posso encontrar pessoas para conversar?</a></li>
|
<li><a href="#howtoe2ee">Como posso encontrar pessoas para conversar?</a></li>
|
||||||
<li><a href="#por-que-um-chat-está-marcado-como-solicitação">Por que um chat está marcado como “Solicitação”?</a></li>
|
<li><a href="#por-que-um-chat-está-marcado-como-solicitação">Por que um chat está marcado como “Solicitação”?</a></li>
|
||||||
<li><a href="#como-posso-colocar-dois-dos-meus-amigos-em-contato-um-com-o-outro">Como posso colocar dois dos meus amigos em contato um com o outro?</a></li>
|
<li><a href="#como-posso-colocar-dois-dos-meus-amigos-em-contato-um-com-o-outro">Como posso colocar dois dos meus amigos em contato um com o outro?</a></li>
|
||||||
|
<li><a href="#dá-para-mandar-imagens-vídeos-e-outros-anexos-pelo-delta-chat">Dá para mandar imagens, vídeos e outros anexos pelo Delta Chat?</a></li>
|
||||||
<li><a href="#multiple-accounts">O que são perfis? Como posso alternar entre eles?</a></li>
|
<li><a href="#multiple-accounts">O que são perfis? Como posso alternar entre eles?</a></li>
|
||||||
<li><a href="#quem-consegue-ver-a-imagem-do-meu-perfil">Quem consegue ver a imagem do meu perfil?</a></li>
|
<li><a href="#quem-consegue-ver-a-imagem-do-meu-perfil">Quem consegue ver a imagem do meu perfil?</a></li>
|
||||||
<li><a href="#signature">Posso definir uma Bio/Assinatura com o Delta Chat?</a></li>
|
<li><a href="#signature">Posso definir uma Bio/Assinatura com o Delta Chat?</a></li>
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
<li><a href="#o-que-significa-o-ponto-verde">O que significa o ponto verde?</a></li>
|
<li><a href="#o-que-significa-o-ponto-verde">O que significa o ponto verde?</a></li>
|
||||||
<li><a href="#o-que-significam-os-carrapatos-mostrados-ao-lado-das-mensagens-de-saída">O que significam os carrapatos mostrados ao lado das mensagens de saída?</a></li>
|
<li><a href="#o-que-significam-os-carrapatos-mostrados-ao-lado-das-mensagens-de-saída">O que significam os carrapatos mostrados ao lado das mensagens de saída?</a></li>
|
||||||
<li><a href="#edit">Corrigir erros de digitação e excluir mensagens após o envio</a></li>
|
<li><a href="#edit">Corrigir erros de digitação e excluir mensagens após o envio</a></li>
|
||||||
<li><a href="#mediaquality">How is media quality handled?</a></li>
|
|
||||||
<li><a href="#ephemeralmsgs">Como funcionam as mensagens efêmeras?</a></li>
|
<li><a href="#ephemeralmsgs">Como funcionam as mensagens efêmeras?</a></li>
|
||||||
<li><a href="#delold">O que acontece se eu ativar a opção “Apagar mensagens do dispositivo”?</a></li>
|
<li><a href="#delold">O que acontece se eu ativar a opção “Apagar mensagens do dispositivo”?</a></li>
|
||||||
<li><a href="#remove-account">Como posso excluir minha conta?</a></li>
|
<li><a href="#remove-account">Como posso excluir minha conta?</a></li>
|
||||||
@@ -29,21 +29,6 @@
|
|||||||
<li><a href="#quantos-membros-podem-participar-em-um-único-grupo">Quantos membros podem participar em um único grupo?</a></li>
|
<li><a href="#quantos-membros-podem-participar-em-um-único-grupo">Quantos membros podem participar em um único grupo?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#channels">Channels</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#subscribe-to-a-channel">Subscribe to a channel</a></li>
|
|
||||||
<li><a href="#create-a-channel">Create a channel</a></li>
|
|
||||||
<li><a href="#how-many-subscribers-can-a-channel-have">How many subscribers can a channel have?</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#calls">Calls</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#place-a-call">Place a call</a></li>
|
|
||||||
<li><a href="#accept-or-reject-a-call">Accept or reject a call</a></li>
|
|
||||||
<li><a href="#during-a-call">During a call</a></li>
|
|
||||||
<li><a href="#missed-calls-and-notifications">Missed calls and notifications</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#webxdc">Aplicativos embutidos</a>
|
<li><a href="#webxdc">Aplicativos embutidos</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#onde-posso-obter-aplicativos-embutidos">Onde posso obter aplicativos embutidos?</a></li>
|
<li><a href="#onde-posso-obter-aplicativos-embutidos">Onde posso obter aplicativos embutidos?</a></li>
|
||||||
@@ -233,6 +218,19 @@ Você também pode adicionar uma pequena mensagem de apresentação.</p>
|
|||||||
<p>O segundo contato receberá um <strong>cartão</strong>
|
<p>O segundo contato receberá um <strong>cartão</strong>
|
||||||
e poderá tocar nele para começar a conversar com o primeiro contato.</p>
|
e poderá tocar nele para começar a conversar com o primeiro contato.</p>
|
||||||
|
|
||||||
|
<h3 id="dá-para-mandar-imagens-vídeos-e-outros-anexos-pelo-delta-chat">
|
||||||
|
|
||||||
|
|
||||||
|
Dá para mandar imagens, vídeos e outros anexos pelo Delta Chat? <a href="#dá-para-mandar-imagens-vídeos-e-outros-anexos-pelo-delta-chat" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Sim. Imagens, vídeos, arquivos, mensagens de voz etc. podem ser enviados usando os botões de<img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Anexo-</strong>
|
||||||
|
ou <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Mensagem de Voz</strong></p>
|
||||||
|
|
||||||
|
<p>Para fins de desempenho, as imagens são otimizadas e enviadas em um tamanho menor por padrão, mas você pode enviá-las como um “arquivo” para preservar o original.</p>
|
||||||
|
|
||||||
<h3 id="multiple-accounts">
|
<h3 id="multiple-accounts">
|
||||||
|
|
||||||
|
|
||||||
@@ -411,32 +409,6 @@ Não são enviadas notificações e não há limite de tempo.</p>
|
|||||||
<p>Observe que a mensagem original ainda pode ser recebida pelos membros do conversa
|
<p>Observe que a mensagem original ainda pode ser recebida pelos membros do conversa
|
||||||
que podem ter respondido, encaminhado, salvo, capturado a tela ou copiado a mensagem.</p>
|
que podem ter respondido, encaminhado, salvo, capturado a tela ou copiado a mensagem.</p>
|
||||||
|
|
||||||
<h3 id="mediaquality">
|
|
||||||
|
|
||||||
|
|
||||||
How is media quality handled? <a href="#mediaquality" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Imagens, vídeos, arquivos, mensagens de voz etc. podem ser enviados usando os botões de<img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Anexo-</strong>
|
|
||||||
ou <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Mensagem de Voz</strong></p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>By default, compression ensures <strong>fast, efficient delivery</strong> that respects everyone’s data limits and storage.
|
|
||||||
This is ideal for everyday communication.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>In regions with worse connectivity,
|
|
||||||
you can choose higher compression at <strong>Settings → Chats → Outgoing Media Quality</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>If you specifically need to send media in its <strong>original quality</strong>, use <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach → File</strong> in the chat.
|
|
||||||
Please use this method sparingly, as sending original files will significantly increase data usage for you and all recipients in the chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="ephemeralmsgs">
|
<h3 id="ephemeralmsgs">
|
||||||
|
|
||||||
|
|
||||||
@@ -637,197 +609,6 @@ mas não é recomendável mais de 150.</p>
|
|||||||
mas o Delta Chat é um mensageiro privado para conversar com <a href="#groups">direitos iguais</a>.
|
mas o Delta Chat é um mensageiro privado para conversar com <a href="#groups">direitos iguais</a>.
|
||||||
Consulte o <a href="https://pt.wikipedia.org/wiki/N%C3%BAmero_de_Dunbar">Número de Dunbar</a> para obter mais informações.</p>
|
Consulte o <a href="https://pt.wikipedia.org/wiki/N%C3%BAmero_de_Dunbar">Número de Dunbar</a> para obter mais informações.</p>
|
||||||
|
|
||||||
<h2 id="channels">
|
|
||||||
|
|
||||||
|
|
||||||
Channels <a href="#channels" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Channels are a one-to-many tool for broadcasting messages.</p>
|
|
||||||
|
|
||||||
<h3 id="subscribe-to-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Subscribe to a channel <a href="#subscribe-to-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Scan the <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>QR code</strong>
|
|
||||||
or tap the <strong>invite link</strong> you got from the channel owner.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>That’s all!
|
|
||||||
You will receive a few of the messages from the channel history
|
|
||||||
and, from that point on, all new messages from the channel.</p>
|
|
||||||
|
|
||||||
<p><strong>Don’t worry,</strong> if that does not happen immediately.
|
|
||||||
Once the channel owner comes online, your join request will be processed.</p>
|
|
||||||
|
|
||||||
<p>As all of Delta Chat, also Channels are private and decentralized,
|
|
||||||
there is no public discovery.</p>
|
|
||||||
|
|
||||||
<p>Other channel subscribers will not see that you subscribed and cannot message you.
|
|
||||||
The channel owner, however, can message you.
|
|
||||||
They will also see that you read a message unless you have read receipts disabled.</p>
|
|
||||||
|
|
||||||
<p>If you do not want to share your main profile,
|
|
||||||
you can also create a <a href="#multiple-accounts">dedicated profile</a> for joining a channel.</p>
|
|
||||||
|
|
||||||
<h3 id="create-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Create a channel <a href="#create-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>New Chat</strong> and choose <strong>New Channel</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Enter a <strong>name</strong>, optionally set an <strong>image</strong> and <strong>description</strong>, and hit the <strong>Create</strong> button.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can now send and manage messages as usual.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>From the channel’s profile, <strong>share the QR code or invite link with others</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Subscribers will receive your messages,
|
|
||||||
but they cannot send messages in your channel.
|
|
||||||
When subscribing, they will receive <strong>a few of the latest messages of the channel history</strong>.</p>
|
|
||||||
|
|
||||||
<p>You can see the <strong>view count</strong> beside each message.
|
|
||||||
Note that this only counts subscribers who have read receipts enabled,
|
|
||||||
so the real view count may be larger.</p>
|
|
||||||
|
|
||||||
<h3 id="how-many-subscribers-can-a-channel-have">
|
|
||||||
|
|
||||||
|
|
||||||
How many subscribers can a channel have? <a href="#how-many-subscribers-can-a-channel-have" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Channels are designed for much larger audiences than <a href="#groups">groups</a>.</p>
|
|
||||||
|
|
||||||
<p>The practical limit depends on the used <a href="#relays">relay</a>,
|
|
||||||
so there is no single fixed number that applies everywhere.</p>
|
|
||||||
|
|
||||||
<p>For really large channels with several tens of thousands of subscribers,
|
|
||||||
we recommend using a <a href="#multiple-accounts">dedicated profile</a> for the channel
|
|
||||||
and checking whether the relay is suitable.</p>
|
|
||||||
|
|
||||||
<p>But don’t be too hesitant: Delta Chat is designed to be relay-agnostic,
|
|
||||||
so you can change your relay at any point easily -
|
|
||||||
your existing subscribers will not even notice.
|
|
||||||
You only have to update the invite link you share with new subscribers in that case.</p>
|
|
||||||
|
|
||||||
<h2 id="calls">
|
|
||||||
|
|
||||||
|
|
||||||
Calls <a href="#calls" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Delta Chat supports one-to-one <strong>audio calls</strong> and <strong>video calls</strong>.</p>
|
|
||||||
|
|
||||||
<p>Calls are supported on Desktop, Ubuntu Touch, iOS and Android 8 and newer.</p>
|
|
||||||
|
|
||||||
<h3 id="place-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Place a call <a href="#place-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>In a one-to-one chat, tap the 📞 <strong>call icon</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>This opens a small menu
|
|
||||||
where you can choose whether to place an <strong>Audio Call</strong> or a <strong>Video Call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="accept-or-reject-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Accept or reject a call <a href="#accept-or-reject-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>When someone calls you,
|
|
||||||
Delta Chat shows an <strong>incoming call screen</strong> or notification.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>Accept</strong> to answer
|
|
||||||
or <strong>Decline</strong> to reject the call.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="during-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
During a call <a href="#during-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>mute</strong> your microphone.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>enable or disable your camera</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>On mobile, you can <strong>switch between front and back cameras</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Depending on the device, you can also select the audio output or use picture-in-picture.
|
|
||||||
On desktop, the call is using a dedicated window
|
|
||||||
and you can continue using the main Delta Chat window as usual.</p>
|
|
||||||
|
|
||||||
<h3 id="missed-calls-and-notifications">
|
|
||||||
|
|
||||||
|
|
||||||
Missed calls and notifications <a href="#missed-calls-and-notifications" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>If you do not answer, do not hear the ringing, or do not have your device at hand,
|
|
||||||
the call appears as a <strong>missed call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><strong>Only your accepted contacts</strong> can make your device ring.
|
|
||||||
Contact requests will appear as usual and will not ring.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>At <strong>Settings → Notifications → Calls</strong>,
|
|
||||||
you can disable the special call ringing screen completely.
|
|
||||||
If you do so, you will not be disturbed by any ringing notification,
|
|
||||||
you can still pick up the call by tapping the incoming call message bubble in its chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="webxdc">
|
<h2 id="webxdc">
|
||||||
|
|
||||||
|
|
||||||
@@ -1244,26 +1025,22 @@ Relays are operated by different groups and people.</p>
|
|||||||
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
||||||
so you do not need to care about that.
|
so you do not need to care about that.
|
||||||
However, if you want to,
|
However, if you want to,
|
||||||
you can configure relays at <strong>Settings → Advanced → Relays</strong>:</p>
|
you can configure relays at At <strong>Settings → Advanced → Relays</strong>:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
||||||
<a href="https://chatmail.at/relays">chatmail.at/relays</a> shows some known ones.
|
<a href="https://chatmail.at/relays">https://chatmail.at/relays</a> shows some known ones.
|
||||||
If you have multiple relays, you will receive messages on all of them.
|
If you have multiple relays, you will receive messages on all of them.</p>
|
||||||
Contacts learn your current relays automatically when you message them.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Tap on a relay to set it as <strong>used for sending</strong>.</p>
|
<p>The <strong>default</strong> defines the one where your chat partners send future messages to.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>If you <strong>remove</strong> a relay,
|
<p>If you <strong>remove</strong> a relay,
|
||||||
contacts who only know this relay may not reach you until you message them again.
|
make sure another default relay was used for a sufficient amount of time.
|
||||||
To stay reachable in the meantime, choose <strong>Hide from Contacts</strong> in the confirmation dialog
|
Otherwise, messages from your chat partners won’t reach you.
|
||||||
instead of removing it right away.</p>
|
If in doubt, remove later.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>To <strong>show</strong> a hidden relay again, tap on it.</p>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -1406,10 +1183,6 @@ to exchange encryption setup information through QR-code scanning or “invite l
|
|||||||
<li>
|
<li>
|
||||||
<p><a href="https://autocrypt.org">Autocrypt</a> is used for automatically
|
<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>
|
establishing end-to-end encryption between contacts and all members of a group chat.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
|
||||||
will bring post-quantum resistant encryption and forward secrecy.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<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
|
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Sharing a contact to a
|
||||||
@@ -1594,10 +1367,12 @@ Instead, all group metadata is end-to-end encrypted and stored on end-user devic
|
|||||||
<p>Servers can therefore only see:</p>
|
<p>Servers can therefore only see:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Sender and receiver addresses, randomly generated by default</li>
|
<li>the sender and receiver addresses</li>
|
||||||
<li>Message size</li>
|
<li>and the message size.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>By default, the addresses are randomly generated.</p>
|
||||||
|
|
||||||
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
||||||
|
|
||||||
<h3 id="device-seizure">
|
<h3 id="device-seizure">
|
||||||
@@ -1626,20 +1401,23 @@ can not be identified easily.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>The used <a href="#relays">relays</a> need to know your IP Address,
|
<p>The used <a href="#relays">relay</a> needs to know your IP Address,
|
||||||
as well as sometimes your contact’s devices if you have a <a href="#calls">call</a>
|
as well as sometimes your contact’s devices if you have a <a href="#experiments">call</a>
|
||||||
or use <a href="#webxdc">apps</a> together.</p>
|
or use <a href="#webxdc">apps</a> together.</p>
|
||||||
|
|
||||||
<p>IP Addresses are needed for connectivity and efficiency.
|
<p>IP Addresses are needed for connectivity and efficiency.
|
||||||
Delta Chat neither persists nor exposes them.
|
They are neither persisted nor exposed.
|
||||||
Note that IP Addresses
|
Note that the IP Address
|
||||||
are not like an address you give to a delivery service,
|
is not like a detailed address you give to a delivery service,
|
||||||
but typically less precise, often defining city or region only.</p>
|
but much more coarse, often defining region or country only.</p>
|
||||||
|
|
||||||
<p>If you see your IP Address as a risk,
|
<p>As this is just how the internet and other messengers work by default,
|
||||||
we recommend to use a VPN for the whole system.
|
we do not offer options here or ask upfront questions.</p>
|
||||||
Per-app options leave gaps across your system.
|
|
||||||
For example, tapping a link can expose IP Addresses to unknown parties, which is by far the larger risk.</p>
|
<p>If you see your IP Address as a security or privacy risk,
|
||||||
|
we recommend to use a VPN, in combination with system lockdown mode.
|
||||||
|
Hunting down options in all apps on your system will leave gaps.
|
||||||
|
For example, tapping a link exposes IP Addresses to unknown parties and is the by far larger risk here.</p>
|
||||||
|
|
||||||
<h3 id="sealedsender">
|
<h3 id="sealedsender">
|
||||||
|
|
||||||
@@ -1670,7 +1448,7 @@ but an implementation has not been agreed as a priority yet.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||||
This means that if your private decryption key is leaked,
|
This means that if your private decryption key is leaked,
|
||||||
@@ -1681,9 +1459,12 @@ Otherwise, someone obtaining your decryption keys
|
|||||||
is typically also able to get all your non-deleted messages
|
is typically also able to get all your non-deleted messages
|
||||||
and doesn’t even need to decrypt any previously collected messages.</p>
|
and doesn’t even need to decrypt any previously collected messages.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>We designed a Forward Secrecy approach that withstood
|
||||||
will provide reliable deletion (forward secrecy) through automatic key rotation.
|
initial examination from some cryptographers and implementation experts
|
||||||
This approach is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
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>
|
||||||
|
|
||||||
<h3 id="pqc">
|
<h3 id="pqc">
|
||||||
|
|
||||||
@@ -1693,13 +1474,12 @@ This approach is specified in the <a href="https://datatracker.ietf.org/doc/draf
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||||
will bring post-quantum resistant encryption to protect against quantum computer attacks.
|
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
||||||
Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</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
|
||||||
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
in collaboration with other OpenPGP implementers.</p>
|
||||||
The implementation is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
|
||||||
|
|
||||||
<h3 id="how-can-i-manually-check-encryption-information">
|
<h3 id="how-can-i-manually-check-encryption-information">
|
||||||
|
|
||||||
@@ -1776,7 +1556,7 @@ See <a href="https://delta.chat/en/2023-05-22-webxdc-security">here for the full
|
|||||||
<li>
|
<li>
|
||||||
<p>2023 March, <a href="https://cure53.de">Cure53</a> analyzed both the transport encryption of
|
<p>2023 March, <a href="https://cure53.de">Cure53</a> analyzed both the transport encryption of
|
||||||
Delta Chat’s network connections and a reproducible mail server setup as
|
Delta Chat’s network connections and a reproducible mail server setup as
|
||||||
<a href="https://delta.chat/serverguide">recommended on this site</a>.
|
<a href="https://delta.chat/pt/serverguide">recommended on this site</a>.
|
||||||
You can read more about the audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">on our blog</a>
|
You can read more about the audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">on our blog</a>
|
||||||
or read the <a href="https://delta.chat/assets/blog/MER-01-report.pdf">full report here</a>.</p>
|
or read the <a href="https://delta.chat/assets/blog/MER-01-report.pdf">full report here</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<li><a href="#howtoe2ee">Как найти людей для общения?</a></li>
|
<li><a href="#howtoe2ee">Как найти людей для общения?</a></li>
|
||||||
<li><a href="#почему-чат-помечен-как-запрос">Почему чат помечен как “Запрос”?</a></li>
|
<li><a href="#почему-чат-помечен-как-запрос">Почему чат помечен как “Запрос”?</a></li>
|
||||||
<li><a href="#как-я-могу-связать-двух-своих-друзей-друг-с-другом">Как я могу связать двух своих друзей друг с другом?</a></li>
|
<li><a href="#как-я-могу-связать-двух-своих-друзей-друг-с-другом">Как я могу связать двух своих друзей друг с другом?</a></li>
|
||||||
|
<li><a href="#поддерживает-ли-delta-chat-изображения-видео-и-другие-вложения">Поддерживает ли Delta Chat изображения, видео и другие вложения?</a></li>
|
||||||
<li><a href="#multiple-accounts">Что такое профили? Как я могу переключатся между ними?</a></li>
|
<li><a href="#multiple-accounts">Что такое профили? Как я могу переключатся между ними?</a></li>
|
||||||
<li><a href="#кто-видит-изображение-моего-профиля">Кто видит изображение моего профиля?</a></li>
|
<li><a href="#кто-видит-изображение-моего-профиля">Кто видит изображение моего профиля?</a></li>
|
||||||
<li><a href="#signature">Могу ли я установить статус/подпись в Delta Chat?</a></li>
|
<li><a href="#signature">Могу ли я установить статус/подпись в Delta Chat?</a></li>
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
<li><a href="#что-означает-зеленая-точка">Что означает зеленая точка?</a></li>
|
<li><a href="#что-означает-зеленая-точка">Что означает зеленая точка?</a></li>
|
||||||
<li><a href="#что-означают-галочки-рядом-с-исходящими-сообщениями">Что означают галочки рядом с исходящими сообщениями?</a></li>
|
<li><a href="#что-означают-галочки-рядом-с-исходящими-сообщениями">Что означают галочки рядом с исходящими сообщениями?</a></li>
|
||||||
<li><a href="#edit">Исправление опечаток и удаление сообщений после отправки</a></li>
|
<li><a href="#edit">Исправление опечаток и удаление сообщений после отправки</a></li>
|
||||||
<li><a href="#mediaquality">Как обеспечивается качество мультимедиа?</a></li>
|
|
||||||
<li><a href="#ephemeralmsgs">Как работают исчезающие сообщения?</a></li>
|
<li><a href="#ephemeralmsgs">Как работают исчезающие сообщения?</a></li>
|
||||||
<li><a href="#delold">Что произойдет, если я включу функцию “Удалять сообщения с устройства”?</a></li>
|
<li><a href="#delold">Что произойдет, если я включу функцию “Удалять сообщения с устройства”?</a></li>
|
||||||
<li><a href="#remove-account">Как удалить свой профиль в чате?</a></li>
|
<li><a href="#remove-account">Как удалить свой профиль в чате?</a></li>
|
||||||
@@ -29,21 +29,6 @@
|
|||||||
<li><a href="#сколько-участников-может-быть-в-одной-группе">Сколько участников может быть в одной группе?</a></li>
|
<li><a href="#сколько-участников-может-быть-в-одной-группе">Сколько участников может быть в одной группе?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#channels">Каналы</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#подписка-на-канал">Подписка на канал</a></li>
|
|
||||||
<li><a href="#создание-канала">Создание канала</a></li>
|
|
||||||
<li><a href="#какое-максимальное-количество-подписчиков-может-быть-у-канала">Какое максимальное количество подписчиков может быть у канала?</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#calls">Звонки</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#как-сделать-звонок">Как сделать звонок</a></li>
|
|
||||||
<li><a href="#принять-или-отклонить-вызов">Принять или отклонить вызов</a></li>
|
|
||||||
<li><a href="#во-время-звонка">Во время звонка</a></li>
|
|
||||||
<li><a href="#пропущенные-вызовы-и-уведомления">Пропущенные вызовы и уведомления</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#webxdc">Встроенные приложения чата</a>
|
<li><a href="#webxdc">Встроенные приложения чата</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#где-можно-найти-встроенные-приложения">Где можно найти встроенные приложения?</a></li>
|
<li><a href="#где-можно-найти-встроенные-приложения">Где можно найти встроенные приложения?</a></li>
|
||||||
@@ -229,6 +214,19 @@
|
|||||||
<p>Второй контакт получит <strong>карточку</strong>
|
<p>Второй контакт получит <strong>карточку</strong>
|
||||||
на которую можно нажать, чтобы начать общение с первым контактом.</p>
|
на которую можно нажать, чтобы начать общение с первым контактом.</p>
|
||||||
|
|
||||||
|
<h3 id="поддерживает-ли-delta-chat-изображения-видео-и-другие-вложения">
|
||||||
|
|
||||||
|
|
||||||
|
Поддерживает ли Delta Chat изображения, видео и другие вложения? <a href="#поддерживает-ли-delta-chat-изображения-видео-и-другие-вложения" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Да. Изображения, видео, файлы, голосовые сообщения и т.д. можно отправлять с помощью кнопок <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Вложение</strong>
|
||||||
|
или <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Голосовое сообщение</strong>.</p>
|
||||||
|
|
||||||
|
<p>Для повышения производительности, изображения оптимизируются и отправляются по умолчанию в уменьшенном размере, но вы можете отправить их как “файл”, чтобы сохранить оригинал.</p>
|
||||||
|
|
||||||
<h3 id="multiple-accounts">
|
<h3 id="multiple-accounts">
|
||||||
|
|
||||||
|
|
||||||
@@ -408,32 +406,6 @@
|
|||||||
<p>Обратите внимание, что исходное сообщение все еще может быть получено участниками чата
|
<p>Обратите внимание, что исходное сообщение все еще может быть получено участниками чата
|
||||||
которые могли уже ответить, переслать, сохранить, сделать скриншот или иным образом скопировать сообщение.</p>
|
которые могли уже ответить, переслать, сохранить, сделать скриншот или иным образом скопировать сообщение.</p>
|
||||||
|
|
||||||
<h3 id="mediaquality">
|
|
||||||
|
|
||||||
|
|
||||||
Как обеспечивается качество мультимедиа? <a href="#mediaquality" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Изображения, видео, файлы, голосовые сообщения и т.д. можно отправлять с помощью кнопок <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Вложение</strong>
|
|
||||||
или <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Голосовое сообщение</strong>.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>По умолчанию сжатие обеспечивает <strong>быструю и эффективную доставку</strong> сообщений, учитывая ограничения по объему данных и хранилищу у всех пользователей.
|
|
||||||
Это идеально подходит для повседневного общения.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>В регионах с плохим качеством связи,
|
|
||||||
вы можете выбрать более высокую степень сжатия в меню <strong>Настройки → Чаты → Качество отправляемых медиафайлов</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Если вам необходимо отправить мультимедийный файл в <strong>исходном качестве</strong>, используйте значок <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Прикрепить → Файл</strong> в чате.
|
|
||||||
Используйте этот метод с осторожностью, так как отправка файлов в исходном качестве значительно увеличит объем трафика как для вас, так и для всех участников чата.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="ephemeralmsgs">
|
<h3 id="ephemeralmsgs">
|
||||||
|
|
||||||
|
|
||||||
@@ -637,197 +609,6 @@
|
|||||||
в то время как Delta Chat - это приватный мессенджер для общения на <a href="#groups">равных правах</a>.
|
в то время как Delta Chat - это приватный мессенджер для общения на <a href="#groups">равных правах</a>.
|
||||||
Смотрите <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">число Данбара</a> для более глубокого понимания.</p>
|
Смотрите <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">число Данбара</a> для более глубокого понимания.</p>
|
||||||
|
|
||||||
<h2 id="channels">
|
|
||||||
|
|
||||||
|
|
||||||
Каналы <a href="#channels" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Каналы представляют собой инструмент типа “один-ко-многим” для трансляции сообщений.</p>
|
|
||||||
|
|
||||||
<h3 id="подписка-на-канал">
|
|
||||||
|
|
||||||
|
|
||||||
Подписка на канал <a href="#подписка-на-канал" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Отсканируйте <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>QR-код</strong>
|
|
||||||
или нажмите на ссылку-приглашение, которую вы получили от владельца канала.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Всё готово!
|
|
||||||
Сначала вы получите несколько сообщений из истории канала,
|
|
||||||
а затем — все новые сообщения, поступающие в него.</p>
|
|
||||||
|
|
||||||
<p><strong>Не беспокойтесь,</strong> если это произойдет не сразу.
|
|
||||||
Как только владелец канала выйдет в сеть, ваш запрос на вступление будет обработан.</p>
|
|
||||||
|
|
||||||
<p>Как и весь Delta Chat, каналы являются приватными и децентрализованными,
|
|
||||||
поэтому возможность публичного поиска каналов отсутствует.</p>
|
|
||||||
|
|
||||||
<p>Другие подписчики канала не увидят факта вашей подписки и не смогут отправлять вам сообщения.
|
|
||||||
Однако, владелец канала сможет отправить вам сообщение.
|
|
||||||
Также он будет видеть, что вы прочитали сообщение, если только вы не отключите подтверждение о прочтении.</p>
|
|
||||||
|
|
||||||
<p>Если вы не хотите использовать свой основной профиль,
|
|
||||||
вы можете создать <a href="#multiple-accounts">специальный профиль</a> для подписки на канал.</p>
|
|
||||||
|
|
||||||
<h3 id="создание-канала">
|
|
||||||
|
|
||||||
|
|
||||||
Создание канала <a href="#создание-канала" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Нажмите <strong>Новый чат</strong> и выберите <strong>Новый канал</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Введите <strong>название</strong>, по желанию добавьте <strong>изображение</strong> и <strong>описание</strong>, а затем нажмите кнопку <strong>Создать</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Теперь вы можете отправлять сообщения и управлять ими в обычном режиме.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>В профиле канала вы можете <strong>поделиться QR-кодом или ссылкой-приглашением с другими пользователями</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Подписчики будут получать ваши сообщения,
|
|
||||||
но не смогут отправлять сообщения в вашем канале.
|
|
||||||
При подписке они получат <strong>несколько последних сообщений из истории канала</strong>.</p>
|
|
||||||
|
|
||||||
<p>Рядом с каждым сообщением вы можете увидеть <strong>количество просмотров</strong>.
|
|
||||||
Обратите внимание, что учитываются только те подписчики, у которых включены уведомления о прочтении,
|
|
||||||
поэтому реальное количество просмотров может быть больше.</p>
|
|
||||||
|
|
||||||
<h3 id="какое-максимальное-количество-подписчиков-может-быть-у-канала">
|
|
||||||
|
|
||||||
|
|
||||||
Какое максимальное количество подписчиков может быть у канала? <a href="#какое-максимальное-количество-подписчиков-может-быть-у-канала" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Каналы предназначены для гораздо более широкой аудитории, чем <a href="#groups">группы</a>.</p>
|
|
||||||
|
|
||||||
<p>Практический предел зависит от используемого <a href="#relays">релея</a>,
|
|
||||||
поэтому не существует единого фиксированного значения, применимого во всех случаях.</p>
|
|
||||||
|
|
||||||
<p>Для крайне крупных каналов с десятками тысяч подписчиков,
|
|
||||||
мы рекомендуем использовать <a href="#multiple-accounts">специальный профиль</a> для управления каналом,
|
|
||||||
а также предварительно проверить пригодность релея.</p>
|
|
||||||
|
|
||||||
<p>Не стоит опасаться: архитектура Delta Chat позволяет использовать любой релей (relay-agnostic),
|
|
||||||
поэтому вы можете легко изменить его в любой момент -
|
|
||||||
ваши текущие подписчики этого даже не заметят.
|
|
||||||
В этом случае достаточно будет обновить ссылку-приглашение, которую вы передаёте новым пользователям.</p>
|
|
||||||
|
|
||||||
<h2 id="calls">
|
|
||||||
|
|
||||||
|
|
||||||
Звонки <a href="#calls" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Delta Chat поддерживает <strong>аудио-</strong> и <strong>видеозвонки</strong> в режиме “один-на-один”.</p>
|
|
||||||
|
|
||||||
<p>Звонки работают на ПК, Ubuntu Touch, iOS и Android версии 8 и новее.</p>
|
|
||||||
|
|
||||||
<h3 id="как-сделать-звонок">
|
|
||||||
|
|
||||||
|
|
||||||
Как сделать звонок <a href="#как-сделать-звонок" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>В чате “один-на-один” нажмите на 📞 <strong>значок вызова</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Откроется небольшое меню
|
|
||||||
в котором вы сможете выбрать вид связи <strong>аудио-</strong> или <strong>видеозвонок</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="принять-или-отклонить-вызов">
|
|
||||||
|
|
||||||
|
|
||||||
Принять или отклонить вызов <a href="#принять-или-отклонить-вызов" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>При входящем звонке,
|
|
||||||
Delta Chat показывает <strong>экран входящего вызова</strong> или уведомление.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Нажмите <strong>Принять</strong> чтобы ответить
|
|
||||||
или <strong>Отклонить</strong> чтобы сбросить звонок.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="во-время-звонка">
|
|
||||||
|
|
||||||
|
|
||||||
Во время звонка <a href="#во-время-звонка" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Вы можете <strong>отключить</strong> звук микрофона.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Вы можете <strong>включить или выключить камеру</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>На мобильных устройствах можно <strong>переключаться между фронтальной и основной камерами</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>В зависимости от устройства вы можете выбрать источник аудиовыхода или использовать режим “картинка в картинке”.
|
|
||||||
В приложении для ПК звонок осуществляется в отдельном окне,
|
|
||||||
что позволяет продолжать работу в основном окне Delta Chat в обычном режиме.</p>
|
|
||||||
|
|
||||||
<h3 id="пропущенные-вызовы-и-уведомления">
|
|
||||||
|
|
||||||
|
|
||||||
Пропущенные вызовы и уведомления <a href="#пропущенные-вызовы-и-уведомления" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Если вы не ответите на звонок, не услышите сигнал или ваше устройство будет недоступно,
|
|
||||||
вызов отобразится как <strong>пропущенный</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><strong>Только ваши подтвержденные контакты</strong> могут заставить ваше устройство звонить.
|
|
||||||
Запросы на добавление в контакты будут приходить как обычно, но вызова не будет.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>В разделе <strong>Настройки → Уведомления → Звонки</strong>,
|
|
||||||
вы можете полностью отключить специальный экран входящего вызова.
|
|
||||||
Если вы это сделаете, никакие уведомления о звонках не будут вас беспокоить;
|
|
||||||
при этом вы всё равно сможете принять звонок, нажав на иконку сообщения о входящем звонке в соответствующем чате.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="webxdc">
|
<h2 id="webxdc">
|
||||||
|
|
||||||
|
|
||||||
@@ -1243,26 +1024,22 @@ PIN-код разблокировки экрана, графический кл
|
|||||||
<p>По умолчанию, после установки, релей <strong>настраивается автоматически</strong>,
|
<p>По умолчанию, после установки, релей <strong>настраивается автоматически</strong>,
|
||||||
поэтому вам не нужно об этом волноваться.
|
поэтому вам не нужно об этом волноваться.
|
||||||
Однако, если хотите,
|
Однако, если хотите,
|
||||||
вы можете настроить релеи в меню <strong>Настройки → Дополнительно → Релеи</strong>:</p>
|
вы можете настроить релеи в <strong>Настройки → Дополнительно → Релеи</strong>:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Вы можете <strong>добавить</strong> релей, отсканировав его QR-код;
|
<p>Вы можете <strong>добавить</strong> релей, отсканировав его QR-код;
|
||||||
на сайте <a href="https://chatmail.at/relays">chatmail.at/relays</a> представлен список известных.
|
<a href="https://chatmail.at/relays">https://chatmail.at/relays</a> содержит список известных релеев.
|
||||||
Если у вас настроено несколько релеев, сообщения будут доставляться через все из них.
|
Если у вас несколько релеев, вы будете получать сообщения на все из них.</p>
|
||||||
Ваши контакты автоматически узнают о текущих используемых вами релеях при обмене сообщениями.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Нажмите на релей, чтобы установить его как <strong>используемый для отправки</strong>.</p>
|
<p><strong>По умолчанию</strong> определяет релей, на который ваши собеседники будут отправлять будущие сообщения.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Если вы <strong>удалите</strong> релей,
|
<p>Если вы <strong>удаляете</strong> релей,
|
||||||
контакты, которые знают только этот релей, не смогут связаться с вами до тех пор, пока вы снова не напишите им.
|
убедитесь, что другой релей по умолчанию использовался в течение достаточного количества времени.
|
||||||
Чтобы оставаться на связи в это время, выберите опцию <strong>Скрыть из контактов</strong> во всплывающем окне
|
В противном случае сообщения от ваших собеседников не будут доходить до вас.
|
||||||
вместо того, чтобы удалять его сразу.</p>
|
Если сомневаетесь, удалите его позже.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Чтобы снова <strong>показать</strong> скрытый релей, нажмите на него.</p>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -1404,10 +1181,6 @@ Chatmail использует INBOX по умолчанию для ретран
|
|||||||
<li>
|
<li>
|
||||||
<p><a href="https://autocrypt.org">Autocrypt</a> используется для автоматической
|
<p><a href="https://autocrypt.org">Autocrypt</a> используется для автоматической
|
||||||
настройки сквозного шифрования между контактами и всеми членами группового чата.</p>
|
настройки сквозного шифрования между контактами и всеми членами группового чата.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, полное внедрение которого запланировано на 2026 год,
|
|
||||||
обеспечит поддержку постквантового шифрования и прямой секретности.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Обмен контактом в
|
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Обмен контактом в
|
||||||
@@ -1592,10 +1365,12 @@ Delta Chat вместо этого использует реализацию Ope
|
|||||||
<p>Таким образом, серверы могут видеть только:</p>
|
<p>Таким образом, серверы могут видеть только:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Адреса отправителя и получателя, по умолчанию генерируются случайным образом</li>
|
<li>адрес отправителя и получателя</li>
|
||||||
<li>Размер сообщения</li>
|
<li>а также размер сообщения.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>По умолчанию адреса генерируются случайным образом.</p>
|
||||||
|
|
||||||
<p>Все прочие метаданные сообщений, контактов и групп содержатся в части сообщений, защищённой сквозным шифрованием.</p>
|
<p>Все прочие метаданные сообщений, контактов и групп содержатся в части сообщений, защищённой сквозным шифрованием.</p>
|
||||||
|
|
||||||
<h3 id="device-seizure">
|
<h3 id="device-seizure">
|
||||||
@@ -1624,20 +1399,25 @@ Delta Chat вместо этого использует реализацию Ope
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Используемым <a href="#relays">релеям</a> необходимо знать ваш IP-адрес,
|
<p>Используемый <a href="#relays">релей</a> должен знать ваш IP-адрес,
|
||||||
а в некоторых случаях — данные устройств ваших контактов, если вы совершаете <a href="#calls">вызов</a>
|
а также иногда устройства ваших контактов, если вы проводите совместные <a href="#experiments">звонки</a>
|
||||||
или совместно используете <a href="#webxdc">приложения</a>.</p>
|
или используете <a href="#webxdc">приложения</a>.</p>
|
||||||
|
|
||||||
<p>IP-адреса необходимы для обеспечения связи и эффективной работы.
|
<p>IP-адреса необходимы для обеспечения соединения и эффективности.
|
||||||
Delta Chat не сохраняет их и не раскрывает третьим лицам.
|
Они не сохраняются и не передаются третьим лицам.
|
||||||
Обратите внимание, что IP-адрес
|
Обратите внимание, что IP-адрес</p>
|
||||||
— это не тот же адрес, который вы указываете службе доставки,
|
<ul>
|
||||||
он, как правило, менее точен и зачастую позволяет определить лишь город или регион.</p>
|
<li>это не подробный адрес, который вы указываете службе доставки,
|
||||||
|
а скорее приблизительный, обычно определяющий регион или страну.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<p>Если вы считаете свой IP-адрес зоной риска,
|
<p>Поскольку именно так по умолчанию работает интернет и другие мессенджеры,
|
||||||
мы рекомендуем использовать VPN для всей системы.
|
мы не предлагаем здесь никаких настроек и не задаём предварительных вопросов</p>
|
||||||
Настройка VPN для отдельных приложений оставляет уязвимости в общей защите устройства.
|
|
||||||
Например, нажатие на ссылку может раскрыть ваш IP-адрес неизвестным сторонам, что представляет собой гораздо больший риск.</p>
|
<p>Если вы считаете свой IP-адрес угрозой безопасности или конфиденциальности,
|
||||||
|
мы рекомендуем использовать VPN в сочетании с режимом блокировки системы.
|
||||||
|
Поиск настроек во всех приложениях на вашем устройстве оставит уязвимости.
|
||||||
|
Например, нажатие на ссылку раскрывает IP-адрес неизвестным лицам и представляет собой гораздо больший риск в данном случае.</p>
|
||||||
|
|
||||||
<h3 id="sealedsender">
|
<h3 id="sealedsender">
|
||||||
|
|
||||||
@@ -1647,7 +1427,7 @@ Delta Chat не сохраняет их и не раскрывает треть
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Нет, пока нет.</p>
|
<p>Нет, еще нет.</p>
|
||||||
|
|
||||||
<p>Мессенджер Signal внедрил функцию <a href="https://signal.org/blog/sealed-sender/">“Sealed Sender” (Засекреченный отправитель) в 2018 году</a>,
|
<p>Мессенджер Signal внедрил функцию <a href="https://signal.org/blog/sealed-sender/">“Sealed Sender” (Засекреченный отправитель) в 2018 году</a>,
|
||||||
чтобы их серверная инфраструктура не имела информации о том, кто отправляет сообщение группе получателей.
|
чтобы их серверная инфраструктура не имела информации о том, кто отправляет сообщение группе получателей.
|
||||||
@@ -1668,7 +1448,7 @@ Delta Chat не сохраняет их и не раскрывает треть
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Пока нет, но это будет реализовано в <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>Нет, еще нет.</p>
|
||||||
|
|
||||||
<p>На данный момент, Delta Chat не поддерживает Perfect Forward Secrecy (PFS) (Совершенную прямую секретность).
|
<p>На данный момент, Delta Chat не поддерживает Perfect Forward Secrecy (PFS) (Совершенную прямую секретность).
|
||||||
Это означает, что если ваш приватный ключ дешифрования будет скомпрометирован,
|
Это означает, что если ваш приватный ключ дешифрования будет скомпрометирован,
|
||||||
@@ -1679,9 +1459,12 @@ Delta Chat не сохраняет их и не раскрывает треть
|
|||||||
также может получить все ваши не удалённые сообщения
|
также может получить все ваши не удалённые сообщения
|
||||||
и ему даже не нужно расшифровывать какие-либо ранее собранные сообщения.</p>
|
и ему даже не нужно расшифровывать какие-либо ранее собранные сообщения.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, полное внедрение которого запланировано на 2026 год,
|
<p>Мы разработали подход к Forward Secrecy (Прямой секретности), который прошёл
|
||||||
обеспечит надёжное удаление (прямую секретность) за счёт автоматической ротации ключей.
|
первичную проверку некоторыми криптографами и экспертами по реализации
|
||||||
Этот подход описан в черновике спецификации <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a>.</p>
|
но требует более формального описания
|
||||||
|
чтобы убедиться, что он надёжно работает в федеративном обмене сообщениями и при использовании нескольких устройств,
|
||||||
|
прежде чем он может быть внедрён в <a href="https://github.com/chatmail/core">ядро chatmail</a>,
|
||||||
|
что сделает его доступным во всех <a href="https://chatmail.at/clients">клиентах clients</a>.</p>
|
||||||
|
|
||||||
<h3 id="pqc">
|
<h3 id="pqc">
|
||||||
|
|
||||||
@@ -1691,13 +1474,12 @@ Delta Chat не сохраняет их и не раскрывает треть
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Пока нет, но эта возможность появится в <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>Нет, еще нет.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, полное внедрение которого запланировано на 2026 год,
|
<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>.
|
||||||
Delta Chat использует Rust-библиотеку OpenPGP <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
Мы планируем добавить поддержку PQC в <a href="https://github.com/chatmail/core">ядро chatmail</a> после того, как черновик будет окончательно утвержден в IETF
|
||||||
которая поддерживает актуальный черновик IETF <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP</a>.
|
в сотрудничестве с другими разработчиками OpenPGP.</p>
|
||||||
Особенности реализации описаны в черновике спецификации <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a>.</p>
|
|
||||||
|
|
||||||
<h3 id="как-можно-вручную-проверить-информацию-о-шифровании">
|
<h3 id="как-можно-вручную-проверить-информацию-о-шифровании">
|
||||||
|
|
||||||
@@ -1772,10 +1554,11 @@ Applied Cryptography в ETH Цюрихе и устранили все выявл
|
|||||||
См. здесь <a href="https://delta.chat/en/2023-05-22-webxdc-security">полную информацию о безопасности сквозного шифрования в Интернете</a>.</p>
|
См. здесь <a href="https://delta.chat/en/2023-05-22-webxdc-security">полную информацию о безопасности сквозного шифрования в Интернете</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>В марте 2023 года компания <a href="https://cure53.de">Cure53</a> провела анализ шифрования транспортного уровня сетевых соединений Delta Chat, а также проверку воспроизводимой конфигурации почтового сервера,
|
<p>В Марте 2023 года, <a href="https://cure53.de">Cure53</a> проанализировал как протокол защиты транспортного уровня
|
||||||
<a href="https://delta.chat/serverguide">рекомендованной на этом сайте</a>.
|
сетевого соединения Delta Chat, так и воспроизводимую установку почтового сервера,
|
||||||
Подробнее об аудите можно узнать <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">в нашем блоге</a>,
|
<a href="https://delta.chat/ru/serverguide">рекомендуемую на этом сайте</a>.
|
||||||
а <a href="https://delta.chat/assets/blog/MER-01-report.pdf">полный отчет доступен по этой ссылке</a>.</p>
|
Подробнее об аудите можно узнать <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">в нашем блоге</a>
|
||||||
|
или прочитать <a href="https://delta.chat/assets/blog/MER-01-report.pdf">полный отчёт здесь</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>2020 год, <a href="https://includesecurity.com">Include Security</a> проанализировала Delta
|
<p>2020 год, <a href="https://includesecurity.com">Include Security</a> проанализировала Delta
|
||||||
@@ -1875,32 +1658,32 @@ Google Play Store, F-Droid, Huawei App Gallery, iOS и macOS App Store, Microsof
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>В 2023 и 2024 годах мы были приняты в программу Next Generation Internet (NGI)
|
<p>In 2023 and 2024 we got accepted in the Next Generation Internet (NGI)
|
||||||
за нашу работу над <a href="https://nlnet.nl/project/WebXDC-Push/">webxdc PUSH</a>,
|
program for our work in <a href="https://nlnet.nl/project/WebXDC-Push/">webxdc PUSH</a>,
|
||||||
в сотрудничестве с партнерами, работающими над
|
along with collaboration partners working on
|
||||||
<a href="https://nlnet.nl/project/Webxdc-Evolve/">webxdc evolve</a>,
|
<a href="https://nlnet.nl/project/Webxdc-Evolve/">webxdc evolve</a>,
|
||||||
<a href="https://nlnet.nl/project/WebXDC-XMPP/">webxdc XMPP</a>,
|
<a href="https://nlnet.nl/project/WebXDC-XMPP/">webxdc XMPP</a>,
|
||||||
<a href="https://nlnet.nl/project/DeltaTouch/">DeltaTouch</a> и
|
<a href="https://nlnet.nl/project/DeltaTouch/">DeltaTouch</a> and
|
||||||
<a href="https://nlnet.nl/project/DeltaTauri/">DeltaTauri</a>.
|
<a href="https://nlnet.nl/project/DeltaTauri/">DeltaTauri</a>.
|
||||||
Все эти проекты частично завершены или будут завершены в начале 2025 года.</p>
|
All of these projects are partially completed or to be completed in early 2025.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>В 2021 г. мы получили дополнительное финансирование из ЕС для двух Next-Generation-Internet
|
<p>В 2021 г. мы получили дополнительное финансирование из ЕС для двух Next-Generation-Internet
|
||||||
целей, а именно для <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - e-mail provider portability directory</a> (~97 тыс. евро) и <a href="https://nlnet.nl/project/EmailPorting/">AEAP - email address porting</a> (~90 тыс. евро). Это привело к улучшению поддержки нескольких профилей, улучшению настройки контактов и групп с помощью QR-кода и многим улучшениям в сетевом взаимодействии на всех платформах.</p>
|
целей, а именно для <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - e-mail provider portability directory</a> (~97 тыс. евро) и <a href="https://nlnet.nl/project/EmailPorting/">AEAP - email address porting</a> (~90 тыс. евро). Это привело к улучшению поддержки нескольких профилей, улучшению настройки контактов и групп с помощью QR-кода и многим улучшениям в сетевом взаимодействии на всех платформах.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Фонд <a href="https://nlnet.nl/">NLnet Foundation</a> выделил в 2019/2020 году 46 тысяч евро на
|
<p>The <a href="https://nlnet.nl/">NLnet foundation</a> granted in 2019/2020 EUR 46K for
|
||||||
доработку связки Rust/Python и создание экосистемы чат-ботов..</p>
|
completing Rust/Python bindings and instigating a Chat-bot eco-system.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Фонд <a href="https://opentechfund.org">Open Technology Fund</a> предоставил нам
|
<p>The <a href="https://opentechfund.org">Open Technology Fund</a> gave us a
|
||||||
первый грант в 2018/2019 году (~$200 тыс.), благодаря которому мы существенно улучшили приложение для Android
|
first 2018/2019 grant (~$200K) during which we majorly improved the Android app
|
||||||
и выпустили первую бета-версию приложения для настольных систем, а также провели
|
and released a first Desktop app beta version, and which moreover
|
||||||
исследования в области UX в контексте прав человека,
|
moored our feature developments in UX research in human rights contexts,
|
||||||
см. наш заключительный отчет <a href="https://delta.chat/en/2019-07-19-uxreport">Needfinding and UX report</a>.
|
see our concluding <a href="https://delta.chat/en/2019-07-19-uxreport">Needfinding and UX report</a>.
|
||||||
Второй грант, полученный в 2019/2020 году (~$300 тыс.), помог нам
|
The second 2019/2020 grant (~$300K) helped us to
|
||||||
выпустить версии Delta/iOS, перевести наш основной код на Rust и
|
release Delta/iOS versions, to convert our core library to Rust, and
|
||||||
предоставить новые функции для всех платформ.</p>
|
to provide new features for all platforms.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Проект ЕС <a href="https://nextleap.eu">NEXTLEAP</a> финансировал исследование
|
<p>Проект ЕС <a href="https://nextleap.eu">NEXTLEAP</a> финансировал исследование
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
||||||
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
||||||
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
||||||
|
<li><a href="#podporuje-delta-chat-obrázky-videá-a-iné-prílohy">Podporuje Delta Chat obrázky, videá a iné prílohy?</a></li>
|
||||||
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
||||||
<li><a href="#kto-vidí-moju-profilovú-fotku">Kto vidí moju profilovú fotku?</a></li>
|
<li><a href="#kto-vidí-moju-profilovú-fotku">Kto vidí moju profilovú fotku?</a></li>
|
||||||
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
<li><a href="#what-does-the-green-dot-mean">What does the green dot mean?</a></li>
|
<li><a href="#what-does-the-green-dot-mean">What does the green dot mean?</a></li>
|
||||||
<li><a href="#čo-znamenajú-zaškrtnutia-zobrazené-vedľa-odchádzajúcich-správ">Čo znamenajú zaškrtnutia zobrazené vedľa odchádzajúcich správ?</a></li>
|
<li><a href="#čo-znamenajú-zaškrtnutia-zobrazené-vedľa-odchádzajúcich-správ">Čo znamenajú zaškrtnutia zobrazené vedľa odchádzajúcich správ?</a></li>
|
||||||
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
||||||
<li><a href="#mediaquality">How is media quality handled?</a></li>
|
|
||||||
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
||||||
<li><a href="#delold">What happens if I turn on “Delete Messages from Device”?</a></li>
|
<li><a href="#delold">What happens if I turn on “Delete Messages from Device”?</a></li>
|
||||||
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
||||||
@@ -29,21 +29,6 @@
|
|||||||
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#channels">Channels</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#subscribe-to-a-channel">Subscribe to a channel</a></li>
|
|
||||||
<li><a href="#create-a-channel">Create a channel</a></li>
|
|
||||||
<li><a href="#how-many-subscribers-can-a-channel-have">How many subscribers can a channel have?</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#calls">Calls</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#place-a-call">Place a call</a></li>
|
|
||||||
<li><a href="#accept-or-reject-a-call">Accept or reject a call</a></li>
|
|
||||||
<li><a href="#during-a-call">During a call</a></li>
|
|
||||||
<li><a href="#missed-calls-and-notifications">Missed calls and notifications</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#webxdc">In-chat apps</a>
|
<li><a href="#webxdc">In-chat apps</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
||||||
@@ -233,6 +218,19 @@ You can also add a little introduction message.</p>
|
|||||||
<p>The second contact will receive a <strong>card</strong> then
|
<p>The second contact will receive a <strong>card</strong> then
|
||||||
and can tap it to start chatting with the first contact.</p>
|
and can tap it to start chatting with the first contact.</p>
|
||||||
|
|
||||||
|
<h3 id="podporuje-delta-chat-obrázky-videá-a-iné-prílohy">
|
||||||
|
|
||||||
|
|
||||||
|
Podporuje Delta Chat obrázky, videá a iné prílohy? <a href="#podporuje-delta-chat-obrázky-videá-a-iné-prílohy" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Yes. Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment-</strong>
|
||||||
|
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons</p>
|
||||||
|
|
||||||
|
<p>For performance, images are optimized and sent at a smaller size by default, but you can send it as a “file” to preserve the original.</p>
|
||||||
|
|
||||||
<h3 id="multiple-accounts">
|
<h3 id="multiple-accounts">
|
||||||
|
|
||||||
|
|
||||||
@@ -413,32 +411,6 @@ Notifications are not sent and there is no time limit.</p>
|
|||||||
<p>Note, that the original message may still be received by chat members
|
<p>Note, that the original message may still be received by chat members
|
||||||
who could have already replied, forwarded, saved, screenshotted or otherwise copied the message.</p>
|
who could have already replied, forwarded, saved, screenshotted or otherwise copied the message.</p>
|
||||||
|
|
||||||
<h3 id="mediaquality">
|
|
||||||
|
|
||||||
|
|
||||||
How is media quality handled? <a href="#mediaquality" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach-</strong>
|
|
||||||
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>By default, compression ensures <strong>fast, efficient delivery</strong> that respects everyone’s data limits and storage.
|
|
||||||
This is ideal for everyday communication.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>In regions with worse connectivity,
|
|
||||||
you can choose higher compression at <strong>Settings → Chats → Outgoing Media Quality</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>If you specifically need to send media in its <strong>original quality</strong>, use <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach → File</strong> in the chat.
|
|
||||||
Please use this method sparingly, as sending original files will significantly increase data usage for you and all recipients in the chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="ephemeralmsgs">
|
<h3 id="ephemeralmsgs">
|
||||||
|
|
||||||
|
|
||||||
@@ -642,197 +614,6 @@ but more than 150 is not recommended.</p>
|
|||||||
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
||||||
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
||||||
|
|
||||||
<h2 id="channels">
|
|
||||||
|
|
||||||
|
|
||||||
Channels <a href="#channels" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Channels are a one-to-many tool for broadcasting messages.</p>
|
|
||||||
|
|
||||||
<h3 id="subscribe-to-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Subscribe to a channel <a href="#subscribe-to-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Scan the <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>QR code</strong>
|
|
||||||
or tap the <strong>invite link</strong> you got from the channel owner.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>That’s all!
|
|
||||||
You will receive a few of the messages from the channel history
|
|
||||||
and, from that point on, all new messages from the channel.</p>
|
|
||||||
|
|
||||||
<p><strong>Don’t worry,</strong> if that does not happen immediately.
|
|
||||||
Once the channel owner comes online, your join request will be processed.</p>
|
|
||||||
|
|
||||||
<p>As all of Delta Chat, also Channels are private and decentralized,
|
|
||||||
there is no public discovery.</p>
|
|
||||||
|
|
||||||
<p>Other channel subscribers will not see that you subscribed and cannot message you.
|
|
||||||
The channel owner, however, can message you.
|
|
||||||
They will also see that you read a message unless you have read receipts disabled.</p>
|
|
||||||
|
|
||||||
<p>If you do not want to share your main profile,
|
|
||||||
you can also create a <a href="#multiple-accounts">dedicated profile</a> for joining a channel.</p>
|
|
||||||
|
|
||||||
<h3 id="create-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Create a channel <a href="#create-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>New Chat</strong> and choose <strong>New Channel</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Enter a <strong>name</strong>, optionally set an <strong>image</strong> and <strong>description</strong>, and hit the <strong>Create</strong> button.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can now send and manage messages as usual.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>From the channel’s profile, <strong>share the QR code or invite link with others</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Subscribers will receive your messages,
|
|
||||||
but they cannot send messages in your channel.
|
|
||||||
When subscribing, they will receive <strong>a few of the latest messages of the channel history</strong>.</p>
|
|
||||||
|
|
||||||
<p>You can see the <strong>view count</strong> beside each message.
|
|
||||||
Note that this only counts subscribers who have read receipts enabled,
|
|
||||||
so the real view count may be larger.</p>
|
|
||||||
|
|
||||||
<h3 id="how-many-subscribers-can-a-channel-have">
|
|
||||||
|
|
||||||
|
|
||||||
How many subscribers can a channel have? <a href="#how-many-subscribers-can-a-channel-have" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Channels are designed for much larger audiences than <a href="#groups">groups</a>.</p>
|
|
||||||
|
|
||||||
<p>The practical limit depends on the used <a href="#relays">relay</a>,
|
|
||||||
so there is no single fixed number that applies everywhere.</p>
|
|
||||||
|
|
||||||
<p>For really large channels with several tens of thousands of subscribers,
|
|
||||||
we recommend using a <a href="#multiple-accounts">dedicated profile</a> for the channel
|
|
||||||
and checking whether the relay is suitable.</p>
|
|
||||||
|
|
||||||
<p>But don’t be too hesitant: Delta Chat is designed to be relay-agnostic,
|
|
||||||
so you can change your relay at any point easily -
|
|
||||||
your existing subscribers will not even notice.
|
|
||||||
You only have to update the invite link you share with new subscribers in that case.</p>
|
|
||||||
|
|
||||||
<h2 id="calls">
|
|
||||||
|
|
||||||
|
|
||||||
Calls <a href="#calls" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Delta Chat supports one-to-one <strong>audio calls</strong> and <strong>video calls</strong>.</p>
|
|
||||||
|
|
||||||
<p>Calls are supported on Desktop, Ubuntu Touch, iOS and Android 8 and newer.</p>
|
|
||||||
|
|
||||||
<h3 id="place-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Place a call <a href="#place-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>In a one-to-one chat, tap the 📞 <strong>call icon</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>This opens a small menu
|
|
||||||
where you can choose whether to place an <strong>Audio Call</strong> or a <strong>Video Call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="accept-or-reject-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Accept or reject a call <a href="#accept-or-reject-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>When someone calls you,
|
|
||||||
Delta Chat shows an <strong>incoming call screen</strong> or notification.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>Accept</strong> to answer
|
|
||||||
or <strong>Decline</strong> to reject the call.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="during-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
During a call <a href="#during-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>mute</strong> your microphone.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>enable or disable your camera</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>On mobile, you can <strong>switch between front and back cameras</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Depending on the device, you can also select the audio output or use picture-in-picture.
|
|
||||||
On desktop, the call is using a dedicated window
|
|
||||||
and you can continue using the main Delta Chat window as usual.</p>
|
|
||||||
|
|
||||||
<h3 id="missed-calls-and-notifications">
|
|
||||||
|
|
||||||
|
|
||||||
Missed calls and notifications <a href="#missed-calls-and-notifications" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>If you do not answer, do not hear the ringing, or do not have your device at hand,
|
|
||||||
the call appears as a <strong>missed call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><strong>Only your accepted contacts</strong> can make your device ring.
|
|
||||||
Contact requests will appear as usual and will not ring.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>At <strong>Settings → Notifications → Calls</strong>,
|
|
||||||
you can disable the special call ringing screen completely.
|
|
||||||
If you do so, you will not be disturbed by any ringing notification,
|
|
||||||
you can still pick up the call by tapping the incoming call message bubble in its chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="webxdc">
|
<h2 id="webxdc">
|
||||||
|
|
||||||
|
|
||||||
@@ -1249,26 +1030,22 @@ Relays are operated by different groups and people.</p>
|
|||||||
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
||||||
so you do not need to care about that.
|
so you do not need to care about that.
|
||||||
However, if you want to,
|
However, if you want to,
|
||||||
you can configure relays at <strong>Settings → Advanced → Relays</strong>:</p>
|
you can configure relays at At <strong>Settings → Advanced → Relays</strong>:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
||||||
<a href="https://chatmail.at/relays">chatmail.at/relays</a> shows some known ones.
|
<a href="https://chatmail.at/relays">https://chatmail.at/relays</a> shows some known ones.
|
||||||
If you have multiple relays, you will receive messages on all of them.
|
If you have multiple relays, you will receive messages on all of them.</p>
|
||||||
Contacts learn your current relays automatically when you message them.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Tap on a relay to set it as <strong>used for sending</strong>.</p>
|
<p>The <strong>default</strong> defines the one where your chat partners send future messages to.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>If you <strong>remove</strong> a relay,
|
<p>If you <strong>remove</strong> a relay,
|
||||||
contacts who only know this relay may not reach you until you message them again.
|
make sure another default relay was used for a sufficient amount of time.
|
||||||
To stay reachable in the meantime, choose <strong>Hide from Contacts</strong> in the confirmation dialog
|
Otherwise, messages from your chat partners won’t reach you.
|
||||||
instead of removing it right away.</p>
|
If in doubt, remove later.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>To <strong>show</strong> a hidden relay again, tap on it.</p>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -1411,10 +1188,6 @@ to exchange encryption setup information through QR-code scanning or “invite l
|
|||||||
<li>
|
<li>
|
||||||
<p><a href="https://autocrypt.org">Autocrypt</a> is used for automatically
|
<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>
|
establishing end-to-end encryption between contacts and all members of a group chat.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
|
||||||
will bring post-quantum resistant encryption and forward secrecy.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<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
|
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Sharing a contact to a
|
||||||
@@ -1599,10 +1372,12 @@ Instead, all group metadata is end-to-end encrypted and stored on end-user devic
|
|||||||
<p>Servers can therefore only see:</p>
|
<p>Servers can therefore only see:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Sender and receiver addresses, randomly generated by default</li>
|
<li>the sender and receiver addresses</li>
|
||||||
<li>Message size</li>
|
<li>and the message size.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>By default, the addresses are randomly generated.</p>
|
||||||
|
|
||||||
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
||||||
|
|
||||||
<h3 id="device-seizure">
|
<h3 id="device-seizure">
|
||||||
@@ -1631,20 +1406,23 @@ can not be identified easily.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>The used <a href="#relays">relays</a> need to know your IP Address,
|
<p>The used <a href="#relays">relay</a> needs to know your IP Address,
|
||||||
as well as sometimes your contact’s devices if you have a <a href="#calls">call</a>
|
as well as sometimes your contact’s devices if you have a <a href="#experiments">call</a>
|
||||||
or use <a href="#webxdc">apps</a> together.</p>
|
or use <a href="#webxdc">apps</a> together.</p>
|
||||||
|
|
||||||
<p>IP Addresses are needed for connectivity and efficiency.
|
<p>IP Addresses are needed for connectivity and efficiency.
|
||||||
Delta Chat neither persists nor exposes them.
|
They are neither persisted nor exposed.
|
||||||
Note that IP Addresses
|
Note that the IP Address
|
||||||
are not like an address you give to a delivery service,
|
is not like a detailed address you give to a delivery service,
|
||||||
but typically less precise, often defining city or region only.</p>
|
but much more coarse, often defining region or country only.</p>
|
||||||
|
|
||||||
<p>If you see your IP Address as a risk,
|
<p>As this is just how the internet and other messengers work by default,
|
||||||
we recommend to use a VPN for the whole system.
|
we do not offer options here or ask upfront questions.</p>
|
||||||
Per-app options leave gaps across your system.
|
|
||||||
For example, tapping a link can expose IP Addresses to unknown parties, which is by far the larger risk.</p>
|
<p>If you see your IP Address as a security or privacy risk,
|
||||||
|
we recommend to use a VPN, in combination with system lockdown mode.
|
||||||
|
Hunting down options in all apps on your system will leave gaps.
|
||||||
|
For example, tapping a link exposes IP Addresses to unknown parties and is the by far larger risk here.</p>
|
||||||
|
|
||||||
<h3 id="sealedsender">
|
<h3 id="sealedsender">
|
||||||
|
|
||||||
@@ -1675,7 +1453,7 @@ but an implementation has not been agreed as a priority yet.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||||
This means that if your private decryption key is leaked,
|
This means that if your private decryption key is leaked,
|
||||||
@@ -1686,9 +1464,12 @@ Otherwise, someone obtaining your decryption keys
|
|||||||
is typically also able to get all your non-deleted messages
|
is typically also able to get all your non-deleted messages
|
||||||
and doesn’t even need to decrypt any previously collected messages.</p>
|
and doesn’t even need to decrypt any previously collected messages.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>We designed a Forward Secrecy approach that withstood
|
||||||
will provide reliable deletion (forward secrecy) through automatic key rotation.
|
initial examination from some cryptographers and implementation experts
|
||||||
This approach is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
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>
|
||||||
|
|
||||||
<h3 id="pqc">
|
<h3 id="pqc">
|
||||||
|
|
||||||
@@ -1698,13 +1479,12 @@ This approach is specified in the <a href="https://datatracker.ietf.org/doc/draf
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||||
will bring post-quantum resistant encryption to protect against quantum computer attacks.
|
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
||||||
Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</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
|
||||||
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
in collaboration with other OpenPGP implementers.</p>
|
||||||
The implementation is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
|
||||||
|
|
||||||
<h3 id="how-can-i-manually-check-encryption-information">
|
<h3 id="how-can-i-manually-check-encryption-information">
|
||||||
|
|
||||||
@@ -1781,7 +1561,7 @@ See <a href="https://delta.chat/en/2023-05-22-webxdc-security">here for the full
|
|||||||
<li>
|
<li>
|
||||||
<p>2023 March, <a href="https://cure53.de">Cure53</a> analyzed both the transport encryption of
|
<p>2023 March, <a href="https://cure53.de">Cure53</a> analyzed both the transport encryption of
|
||||||
Delta Chat’s network connections and a reproducible mail server setup as
|
Delta Chat’s network connections and a reproducible mail server setup as
|
||||||
<a href="https://delta.chat/serverguide">recommended on this site</a>.
|
<a href="https://delta.chat/sk/serverguide">recommended on this site</a>.
|
||||||
You can read more about the audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">on our blog</a>
|
You can read more about the audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">on our blog</a>
|
||||||
or read the <a href="https://delta.chat/assets/blog/MER-01-report.pdf">full report here</a>.</p>
|
or read the <a href="https://delta.chat/assets/blog/MER-01-report.pdf">full report here</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
|
||||||
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
||||||
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
||||||
|
<li><a href="#a-mbulon-delta-chat-i-figura-video-dhe-bashkëngjitje-të-tjera">A mbulon Delta Chat-i figura, video dhe bashkëngjitje të tjera?</a></li>
|
||||||
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
|
||||||
<li><a href="#kush-e-sheh-profilin-tim">Kush e sheh profilin tim?</a></li>
|
<li><a href="#kush-e-sheh-profilin-tim">Kush e sheh profilin tim?</a></li>
|
||||||
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
<li><a href="#çdo-të-thotë-pika-e-gjelbër">Ç’do të thotë pika e gjelbër?</a></li>
|
<li><a href="#çdo-të-thotë-pika-e-gjelbër">Ç’do të thotë pika e gjelbër?</a></li>
|
||||||
<li><a href="#çduan-të-thonë-shenjat-e-shfaqura-pas-mesazheve-që-dërgohen">Ç’duan të thonë shenjat e shfaqura pas mesazheve që dërgohen?</a></li>
|
<li><a href="#çduan-të-thonë-shenjat-e-shfaqura-pas-mesazheve-që-dërgohen">Ç’duan të thonë shenjat e shfaqura pas mesazheve që dërgohen?</a></li>
|
||||||
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
<li><a href="#edit">Correct typos and delete messages after sending</a></li>
|
||||||
<li><a href="#mediaquality">How is media quality handled?</a></li>
|
|
||||||
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
|
||||||
<li><a href="#delold">Ç’ndodh, nëse aktivizoj “Fshi prej pajisjes mesazhe të vjetër”?</a></li>
|
<li><a href="#delold">Ç’ndodh, nëse aktivizoj “Fshi prej pajisjes mesazhe të vjetër”?</a></li>
|
||||||
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
|
||||||
@@ -29,21 +29,6 @@
|
|||||||
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#channels">Channels</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#subscribe-to-a-channel">Subscribe to a channel</a></li>
|
|
||||||
<li><a href="#create-a-channel">Create a channel</a></li>
|
|
||||||
<li><a href="#how-many-subscribers-can-a-channel-have">How many subscribers can a channel have?</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#calls">Calls</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#place-a-call">Place a call</a></li>
|
|
||||||
<li><a href="#accept-or-reject-a-call">Accept or reject a call</a></li>
|
|
||||||
<li><a href="#during-a-call">During a call</a></li>
|
|
||||||
<li><a href="#missed-calls-and-notifications">Missed calls and notifications</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#webxdc">In-chat apps</a>
|
<li><a href="#webxdc">In-chat apps</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
||||||
@@ -233,6 +218,19 @@ You can also add a little introduction message.</p>
|
|||||||
<p>The second contact will receive a <strong>card</strong> then
|
<p>The second contact will receive a <strong>card</strong> then
|
||||||
and can tap it to start chatting with the first contact.</p>
|
and can tap it to start chatting with the first contact.</p>
|
||||||
|
|
||||||
|
<h3 id="a-mbulon-delta-chat-i-figura-video-dhe-bashkëngjitje-të-tjera">
|
||||||
|
|
||||||
|
|
||||||
|
A mbulon Delta Chat-i figura, video dhe bashkëngjitje të tjera? <a href="#a-mbulon-delta-chat-i-figura-video-dhe-bashkëngjitje-të-tjera" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Po Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment-</strong>
|
||||||
|
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons</p>
|
||||||
|
|
||||||
|
<p>Si parazgjedhje, për funksionim më të mirë, figurat optimizohen dhe dërgohen në madhësi më të vogël, por mund ta dërgoni si një “kartelë”, që të ruhet origjinali.</p>
|
||||||
|
|
||||||
<h3 id="multiple-accounts">
|
<h3 id="multiple-accounts">
|
||||||
|
|
||||||
|
|
||||||
@@ -412,32 +410,6 @@ Notifications are not sent and there is no time limit.</p>
|
|||||||
<p>Note, that the original message may still be received by chat members
|
<p>Note, that the original message may still be received by chat members
|
||||||
who could have already replied, forwarded, saved, screenshotted or otherwise copied the message.</p>
|
who could have already replied, forwarded, saved, screenshotted or otherwise copied the message.</p>
|
||||||
|
|
||||||
<h3 id="mediaquality">
|
|
||||||
|
|
||||||
|
|
||||||
How is media quality handled? <a href="#mediaquality" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach-</strong>
|
|
||||||
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>By default, compression ensures <strong>fast, efficient delivery</strong> that respects everyone’s data limits and storage.
|
|
||||||
This is ideal for everyday communication.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>In regions with worse connectivity,
|
|
||||||
you can choose higher compression at <strong>Settings → Chats → Outgoing Media Quality</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>If you specifically need to send media in its <strong>original quality</strong>, use <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach → File</strong> in the chat.
|
|
||||||
Please use this method sparingly, as sending original files will significantly increase data usage for you and all recipients in the chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="ephemeralmsgs">
|
<h3 id="ephemeralmsgs">
|
||||||
|
|
||||||
|
|
||||||
@@ -642,197 +614,6 @@ but more than 150 is not recommended.</p>
|
|||||||
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
||||||
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
||||||
|
|
||||||
<h2 id="channels">
|
|
||||||
|
|
||||||
|
|
||||||
Channels <a href="#channels" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Channels are a one-to-many tool for broadcasting messages.</p>
|
|
||||||
|
|
||||||
<h3 id="subscribe-to-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Subscribe to a channel <a href="#subscribe-to-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Scan the <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>QR code</strong>
|
|
||||||
or tap the <strong>invite link</strong> you got from the channel owner.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>That’s all!
|
|
||||||
You will receive a few of the messages from the channel history
|
|
||||||
and, from that point on, all new messages from the channel.</p>
|
|
||||||
|
|
||||||
<p><strong>Don’t worry,</strong> if that does not happen immediately.
|
|
||||||
Once the channel owner comes online, your join request will be processed.</p>
|
|
||||||
|
|
||||||
<p>As all of Delta Chat, also Channels are private and decentralized,
|
|
||||||
there is no public discovery.</p>
|
|
||||||
|
|
||||||
<p>Other channel subscribers will not see that you subscribed and cannot message you.
|
|
||||||
The channel owner, however, can message you.
|
|
||||||
They will also see that you read a message unless you have read receipts disabled.</p>
|
|
||||||
|
|
||||||
<p>If you do not want to share your main profile,
|
|
||||||
you can also create a <a href="#multiple-accounts">dedicated profile</a> for joining a channel.</p>
|
|
||||||
|
|
||||||
<h3 id="create-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Create a channel <a href="#create-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>New Chat</strong> and choose <strong>New Channel</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Enter a <strong>name</strong>, optionally set an <strong>image</strong> and <strong>description</strong>, and hit the <strong>Create</strong> button.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can now send and manage messages as usual.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>From the channel’s profile, <strong>share the QR code or invite link with others</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Subscribers will receive your messages,
|
|
||||||
but they cannot send messages in your channel.
|
|
||||||
When subscribing, they will receive <strong>a few of the latest messages of the channel history</strong>.</p>
|
|
||||||
|
|
||||||
<p>You can see the <strong>view count</strong> beside each message.
|
|
||||||
Note that this only counts subscribers who have read receipts enabled,
|
|
||||||
so the real view count may be larger.</p>
|
|
||||||
|
|
||||||
<h3 id="how-many-subscribers-can-a-channel-have">
|
|
||||||
|
|
||||||
|
|
||||||
How many subscribers can a channel have? <a href="#how-many-subscribers-can-a-channel-have" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Channels are designed for much larger audiences than <a href="#groups">groups</a>.</p>
|
|
||||||
|
|
||||||
<p>The practical limit depends on the used <a href="#relays">relay</a>,
|
|
||||||
so there is no single fixed number that applies everywhere.</p>
|
|
||||||
|
|
||||||
<p>For really large channels with several tens of thousands of subscribers,
|
|
||||||
we recommend using a <a href="#multiple-accounts">dedicated profile</a> for the channel
|
|
||||||
and checking whether the relay is suitable.</p>
|
|
||||||
|
|
||||||
<p>But don’t be too hesitant: Delta Chat is designed to be relay-agnostic,
|
|
||||||
so you can change your relay at any point easily -
|
|
||||||
your existing subscribers will not even notice.
|
|
||||||
You only have to update the invite link you share with new subscribers in that case.</p>
|
|
||||||
|
|
||||||
<h2 id="calls">
|
|
||||||
|
|
||||||
|
|
||||||
Calls <a href="#calls" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Delta Chat supports one-to-one <strong>audio calls</strong> and <strong>video calls</strong>.</p>
|
|
||||||
|
|
||||||
<p>Calls are supported on Desktop, Ubuntu Touch, iOS and Android 8 and newer.</p>
|
|
||||||
|
|
||||||
<h3 id="place-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Place a call <a href="#place-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>In a one-to-one chat, tap the 📞 <strong>call icon</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>This opens a small menu
|
|
||||||
where you can choose whether to place an <strong>Audio Call</strong> or a <strong>Video Call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="accept-or-reject-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Accept or reject a call <a href="#accept-or-reject-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>When someone calls you,
|
|
||||||
Delta Chat shows an <strong>incoming call screen</strong> or notification.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>Accept</strong> to answer
|
|
||||||
or <strong>Decline</strong> to reject the call.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="during-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
During a call <a href="#during-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>mute</strong> your microphone.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>enable or disable your camera</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>On mobile, you can <strong>switch between front and back cameras</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Depending on the device, you can also select the audio output or use picture-in-picture.
|
|
||||||
On desktop, the call is using a dedicated window
|
|
||||||
and you can continue using the main Delta Chat window as usual.</p>
|
|
||||||
|
|
||||||
<h3 id="missed-calls-and-notifications">
|
|
||||||
|
|
||||||
|
|
||||||
Missed calls and notifications <a href="#missed-calls-and-notifications" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>If you do not answer, do not hear the ringing, or do not have your device at hand,
|
|
||||||
the call appears as a <strong>missed call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><strong>Only your accepted contacts</strong> can make your device ring.
|
|
||||||
Contact requests will appear as usual and will not ring.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>At <strong>Settings → Notifications → Calls</strong>,
|
|
||||||
you can disable the special call ringing screen completely.
|
|
||||||
If you do so, you will not be disturbed by any ringing notification,
|
|
||||||
you can still pick up the call by tapping the incoming call message bubble in its chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="webxdc">
|
<h2 id="webxdc">
|
||||||
|
|
||||||
|
|
||||||
@@ -1251,26 +1032,22 @@ Relays are operated by different groups and people.</p>
|
|||||||
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
||||||
so you do not need to care about that.
|
so you do not need to care about that.
|
||||||
However, if you want to,
|
However, if you want to,
|
||||||
you can configure relays at <strong>Settings → Advanced → Relays</strong>:</p>
|
you can configure relays at At <strong>Settings → Advanced → Relays</strong>:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
||||||
<a href="https://chatmail.at/relays">chatmail.at/relays</a> shows some known ones.
|
<a href="https://chatmail.at/relays">https://chatmail.at/relays</a> shows some known ones.
|
||||||
If you have multiple relays, you will receive messages on all of them.
|
If you have multiple relays, you will receive messages on all of them.</p>
|
||||||
Contacts learn your current relays automatically when you message them.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Tap on a relay to set it as <strong>used for sending</strong>.</p>
|
<p>The <strong>default</strong> defines the one where your chat partners send future messages to.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>If you <strong>remove</strong> a relay,
|
<p>If you <strong>remove</strong> a relay,
|
||||||
contacts who only know this relay may not reach you until you message them again.
|
make sure another default relay was used for a sufficient amount of time.
|
||||||
To stay reachable in the meantime, choose <strong>Hide from Contacts</strong> in the confirmation dialog
|
Otherwise, messages from your chat partners won’t reach you.
|
||||||
instead of removing it right away.</p>
|
If in doubt, remove later.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>To <strong>show</strong> a hidden relay again, tap on it.</p>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -1413,10 +1190,6 @@ to exchange encryption setup information through QR-code scanning or “invite l
|
|||||||
<li>
|
<li>
|
||||||
<p><a href="https://autocrypt.org">Autocrypt</a> is used for automatically
|
<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>
|
establishing end-to-end encryption between contacts and all members of a group chat.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
|
||||||
will bring post-quantum resistant encryption and forward secrecy.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<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
|
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Sharing a contact to a
|
||||||
@@ -1601,10 +1374,12 @@ Instead, all group metadata is end-to-end encrypted and stored on end-user devic
|
|||||||
<p>Servers can therefore only see:</p>
|
<p>Servers can therefore only see:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Sender and receiver addresses, randomly generated by default</li>
|
<li>the sender and receiver addresses</li>
|
||||||
<li>Message size</li>
|
<li>and the message size.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>By default, the addresses are randomly generated.</p>
|
||||||
|
|
||||||
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
<p>All other message, contact and group metadata resides in the end-to-end encrypted part of messages.</p>
|
||||||
|
|
||||||
<h3 id="device-seizure">
|
<h3 id="device-seizure">
|
||||||
@@ -1633,20 +1408,23 @@ can not be identified easily.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>The used <a href="#relays">relays</a> need to know your IP Address,
|
<p>The used <a href="#relays">relay</a> needs to know your IP Address,
|
||||||
as well as sometimes your contact’s devices if you have a <a href="#calls">call</a>
|
as well as sometimes your contact’s devices if you have a <a href="#experiments">call</a>
|
||||||
or use <a href="#webxdc">apps</a> together.</p>
|
or use <a href="#webxdc">apps</a> together.</p>
|
||||||
|
|
||||||
<p>IP Addresses are needed for connectivity and efficiency.
|
<p>IP Addresses are needed for connectivity and efficiency.
|
||||||
Delta Chat neither persists nor exposes them.
|
They are neither persisted nor exposed.
|
||||||
Note that IP Addresses
|
Note that the IP Address
|
||||||
are not like an address you give to a delivery service,
|
is not like a detailed address you give to a delivery service,
|
||||||
but typically less precise, often defining city or region only.</p>
|
but much more coarse, often defining region or country only.</p>
|
||||||
|
|
||||||
<p>If you see your IP Address as a risk,
|
<p>As this is just how the internet and other messengers work by default,
|
||||||
we recommend to use a VPN for the whole system.
|
we do not offer options here or ask upfront questions.</p>
|
||||||
Per-app options leave gaps across your system.
|
|
||||||
For example, tapping a link can expose IP Addresses to unknown parties, which is by far the larger risk.</p>
|
<p>If you see your IP Address as a security or privacy risk,
|
||||||
|
we recommend to use a VPN, in combination with system lockdown mode.
|
||||||
|
Hunting down options in all apps on your system will leave gaps.
|
||||||
|
For example, tapping a link exposes IP Addresses to unknown parties and is the by far larger risk here.</p>
|
||||||
|
|
||||||
<h3 id="sealedsender">
|
<h3 id="sealedsender">
|
||||||
|
|
||||||
@@ -1677,7 +1455,7 @@ but an implementation has not been agreed as a priority yet.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
<p>Delta Chat today doesn’t support Perfect Forward Secrecy (PFS).
|
||||||
This means that if your private decryption key is leaked,
|
This means that if your private decryption key is leaked,
|
||||||
@@ -1688,9 +1466,12 @@ Otherwise, someone obtaining your decryption keys
|
|||||||
is typically also able to get all your non-deleted messages
|
is typically also able to get all your non-deleted messages
|
||||||
and doesn’t even need to decrypt any previously collected messages.</p>
|
and doesn’t even need to decrypt any previously collected messages.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>We designed a Forward Secrecy approach that withstood
|
||||||
will provide reliable deletion (forward secrecy) through automatic key rotation.
|
initial examination from some cryptographers and implementation experts
|
||||||
This approach is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
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>
|
||||||
|
|
||||||
<h3 id="pqc">
|
<h3 id="pqc">
|
||||||
|
|
||||||
@@ -1700,13 +1481,12 @@ This approach is specified in the <a href="https://datatracker.ietf.org/doc/draf
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>No, not yet.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</a>
|
||||||
will bring post-quantum resistant encryption to protect against quantum computer attacks.
|
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
||||||
Delta Chat uses the Rust OpenPGP library <a href="https://github.com/rpgp/rpgp">rPGP</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
|
||||||
which supports the latest <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-pqc/">IETF Post-Quantum-Cryptography OpenPGP draft</a>.
|
in collaboration with other OpenPGP implementers.</p>
|
||||||
The implementation is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
|
||||||
|
|
||||||
<h3 id="how-can-i-manually-check-encryption-information">
|
<h3 id="how-can-i-manually-check-encryption-information">
|
||||||
|
|
||||||
@@ -1784,7 +1564,7 @@ Shihni <a href="https://delta.chat/en/2023-05-22-webxdc-security">këtu, për sh
|
|||||||
<li>
|
<li>
|
||||||
<p>Në fillim të 2023-it, <a href="https://cure53.de">Cure53</a> analizoi qoftë fshehtëzimin
|
<p>Në fillim të 2023-it, <a href="https://cure53.de">Cure53</a> analizoi qoftë fshehtëzimin
|
||||||
e transporteve për lidhje rrjeti të Delta Chat-it, qoftë një formësim të riprodhueshëm
|
e transporteve për lidhje rrjeti të Delta Chat-it, qoftë një formësim të riprodhueshëm
|
||||||
shërbyesi poste si <a href="https://delta.chat/serverguide">të rekomanduarin në këtë sajt</a>.
|
shërbyesi poste si <a href="https://delta.chat/sq/serverguide">të rekomanduarin në këtë sajt</a>.
|
||||||
Mund të lexoni më tepër rreth auditimit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">në blogun tonë</a>,
|
Mund të lexoni më tepër rreth auditimit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">në blogun tonë</a>,
|
||||||
ose të lexoni <a href="https://delta.chat/assets/blog/MER-01-report.pdf">raportin e plotë këtu</a>.</p>
|
ose të lexoni <a href="https://delta.chat/assets/blog/MER-01-report.pdf">raportin e plotë këtu</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
@@ -1895,31 +1675,28 @@ along with collaboration partners working on
|
|||||||
All of these projects are partially completed or to be completed in early 2025.</p>
|
All of these projects are partially completed or to be completed in early 2025.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Më 2021-n morëm financime të mëtejshme nga BE për dy propozime që shtrihen në
|
<p>In 2021 we received further EU funding for two Next-Generation-Internet
|
||||||
“Internetin e Brezit Tjetër”, konkretisht për <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - e-mail provider portability directory</a> (~97K euro) dhe <a href="https://nlnet.nl/project/EmailPorting/">AEAP - email address porting</a> (~90K euro) që sollën mbulim më të mirë për përdorues me shumë
|
proposals, namely for <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - email provider portability directory</a> (~97K EUR) and <a href="https://nlnet.nl/project/EmailPorting/">AEAP - email address porting</a> (~90K EUR) which resulted in better multi-profile support, improved QR-code contact and group setups and many networking improvements on all platforms.</p>
|
||||||
llogari, përmirësim të gjërave për kontakte me kod QR dhe grupe, si dhe mjaft
|
|
||||||
përmirësime në punën në rrjet për krejt platformat.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><a href="https://nlnet.nl/">Fondacioni NLnet</a> dhuroi 46K euro gjatë 2019/2020 për
|
<p>The <a href="https://nlnet.nl/">NLnet foundation</a> granted in 2019/2020 EUR 46K for
|
||||||
plotësimin e <em>Rust/Python bindings</em> dhe për t’i dhënë udhë një ekosistemi
|
completing Rust/Python bindings and instigating a Chat-bot eco-system.</p>
|
||||||
Chat-bot.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><a href="https://opentechfund.org">Open Technology Fund</a> na dha grantin e parë
|
<p>The <a href="https://opentechfund.org">Open Technology Fund</a> gave us a
|
||||||
për 2018/2019 (~200 mijë dollarë) me të cilin përmirësuam ndjeshëm aplikacionin
|
first 2018/2019 grant (~$200K) during which we majorly improved the Android app
|
||||||
për Android dhe hodhëm në qarkullim një version të parë beta aplikacioni për Desktop,
|
and released a first Desktop app beta version, and which moreover
|
||||||
si dhe i afroi më tepër zhvillimet tona për veçori me kërkime UX në kontekste të drejtash të njeriut,
|
moored our feature developments in UX research in human rights contexts,
|
||||||
shihni <a href="https://delta.chat/en/2019-07-19-uxreport">raportin tonë përfundimtar “Needfinding and UX”</a>.
|
see our concluding <a href="https://delta.chat/en/2019-07-19-uxreport">Needfinding and UX report</a>.
|
||||||
Granti i dytë për 2019/2020 (~$300K) na ndihmoi të hedhim në qarkullim
|
The second 2019/2020 grant (~$300K) helped us to
|
||||||
versione Delta/iOS, për të shndërruar bibliotekën tonë bazë në Rust, si dhe
|
release Delta/iOS versions, to convert our core library to Rust, and
|
||||||
për të sjellë veçori të reja për krejt platformat.</p>
|
to provide new features for all platforms.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Projekti <a href="https://nextleap.eu">NEXTLEAP</a> i BE-së financoi kërkimin
|
<p>The <a href="https://nextleap.eu">NEXTLEAP</a> EU project funded the research
|
||||||
për dhe sendërtimin e grupeve të verifikuara dhe protokolleve të
|
and implementation of verified groups and setup contact protocols
|
||||||
ujdisjes së kontakteve më 2017-n dhe 2018-n dhe ndihmoi gjithashtu
|
in 2017 and 2018 and also helped to integrate end-to-end Encryption
|
||||||
të integrohet Fshehtëzim Skaj-më-Skaj përmes <a href="https://autocrypt.org">Autocrypt</a>.</p>
|
through <a href="https://autocrypt.org">Autocrypt</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Ndonjëherë marrim dhurime unike nga individë privatë.
|
<p>Ndonjëherë marrim dhurime unike nga individë privatë.
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
<li><a href="#що-таке-delta-chat">Що таке Delta Chat?</a>
|
<li><a href="#що-таке-delta-chat">Що таке Delta Chat?</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#howtoe2ee">Як мені знайти людей для спілкування?</a></li>
|
<li><a href="#howtoe2ee">Як мені знайти людей для спілкування?</a></li>
|
||||||
<li><a href="#чому-чат-позначений-як-запит">Чому чат позначений як «Запит»?</a></li>
|
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
|
||||||
<li><a href="#як-я-можу-познайомити-двох-своїх-друзів-один-з-одним">Як я можу познайомити двох своїх друзів один з одним?</a></li>
|
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
|
||||||
|
<li><a href="#чи-підтримує-delta-chat-вкладення-у-вигляді-фото-відео-тощо">Чи підтримує Delta Chat вкладення у вигляді фото, відео тощо?</a></li>
|
||||||
<li><a href="#multiple-accounts">Що таке профілі? Як я можу перемикатися між ними?</a></li>
|
<li><a href="#multiple-accounts">Що таке профілі? Як я можу перемикатися між ними?</a></li>
|
||||||
<li><a href="#хто-бачить-моє-зображення-профілю">Хто бачить моє зображення профілю?</a></li>
|
<li><a href="#хто-бачить-моє-зображення-профілю">Хто бачить моє зображення профілю?</a></li>
|
||||||
<li><a href="#signature">Чи можу я встановити біографію/статус у Delta Chat?</a></li>
|
<li><a href="#signature">Чи можу я встановити біографію/статус у Delta Chat?</a></li>
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
<li><a href="#що-означає-зелена-точка">Що означає зелена точка?</a></li>
|
<li><a href="#що-означає-зелена-точка">Що означає зелена точка?</a></li>
|
||||||
<li><a href="#що-означають-галочки-біля-вихідних-повідомлень">Що означають галочки біля вихідних повідомлень?</a></li>
|
<li><a href="#що-означають-галочки-біля-вихідних-повідомлень">Що означають галочки біля вихідних повідомлень?</a></li>
|
||||||
<li><a href="#edit">Виправлення помилок та видалення повідомлень після надсилання</a></li>
|
<li><a href="#edit">Виправлення помилок та видалення повідомлень після надсилання</a></li>
|
||||||
<li><a href="#mediaquality">How is media quality handled?</a></li>
|
|
||||||
<li><a href="#ephemeralmsgs">Як працюють повідомлення, що зникають?</a></li>
|
<li><a href="#ephemeralmsgs">Як працюють повідомлення, що зникають?</a></li>
|
||||||
<li><a href="#delold">Що станеться, якщо я ввімкну «Видаляти старі повідомлення з пристрою»?</a></li>
|
<li><a href="#delold">Що станеться, якщо я ввімкну «Видаляти старі повідомлення з пристрою»?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -28,21 +28,6 @@
|
|||||||
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
<li><a href="#how-many-members-can-participate-in-a-single-group">How many members can participate in a single group?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#channels">Channels</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#subscribe-to-a-channel">Subscribe to a channel</a></li>
|
|
||||||
<li><a href="#create-a-channel">Create a channel</a></li>
|
|
||||||
<li><a href="#how-many-subscribers-can-a-channel-have">How many subscribers can a channel have?</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#calls">Calls</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#place-a-call">Place a call</a></li>
|
|
||||||
<li><a href="#accept-or-reject-a-call">Accept or reject a call</a></li>
|
|
||||||
<li><a href="#during-a-call">During a call</a></li>
|
|
||||||
<li><a href="#missed-calls-and-notifications">Missed calls and notifications</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#webxdc">In-chat apps</a>
|
<li><a href="#webxdc">In-chat apps</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
|
||||||
@@ -155,10 +140,17 @@
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Якщо ви перебуваєте <strong>віч-на-віч</strong> зі своїм другом або родиною, торкніться піктограми <strong>QR-код</strong> на головному екрані <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> на головному екрані. Попросіть вашого партнера по чату <strong>сканувати</strong> QR-зображення за допомогою їхнього застосунку Delta Chat.</p>
|
<p>If you are <strong>face to face</strong> with your friend or family,
|
||||||
|
tap the <strong>QR Code</strong> icon <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" />
|
||||||
|
on the main screen.<br />
|
||||||
|
Ask your chat partner to <strong>scan</strong> the QR image
|
||||||
|
with their Delta Chat app.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Для <strong>віддаленого</strong> налаштування контакту, на тому ж самому екрані, натисніть “Копіювати” або “Поділитися” і відправте <strong>запрошувальне посилання</strong> через інший приватний чат.</p>
|
<p>For a <strong>remote</strong> contact setup,
|
||||||
|
from the same screen,
|
||||||
|
click “Copy” or “Share” and send the <strong>invite link</strong>
|
||||||
|
through another private chat.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -166,7 +158,8 @@
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Якщо обидві сторони перебувають у мережі, незабаром з’явиться вікно чату, і вони зможуть безпечно обмінюватися повідомленнями.</p>
|
<p>If both sides are online, they will soon see a chat
|
||||||
|
and can start messaging securely.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>If one side is offline or in bad network,
|
<p>If one side is offline or in bad network,
|
||||||
@@ -178,17 +171,19 @@ the ability to chat is delayed until connectivity is restored.</p>
|
|||||||
Тепер Ви автоматично використовуватимете <a href="#e2ee">наскрізне шифрування</a> з цим контактом.
|
Тепер Ви автоматично використовуватимете <a href="#e2ee">наскрізне шифрування</a> з цим контактом.
|
||||||
Якщо ви додасте один одного у <a href="#groups">групи</a>, наскрізне шифрування буде встановлено між усіма учасниками.</p>
|
Якщо ви додасте один одного у <a href="#groups">групи</a>, наскрізне шифрування буде встановлено між усіма учасниками.</p>
|
||||||
|
|
||||||
<h3 id="чому-чат-позначений-як-запит">
|
<h3 id="why-is-a-chat-marked-as-request">
|
||||||
|
|
||||||
|
|
||||||
Чому чат позначений як «Запит»? <a href="#чому-чат-позначений-як-запит" class="anchor"></a>
|
Why is a chat marked as “Request”? <a href="#why-is-a-chat-marked-as-request" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Оскільки це приватний месенджер, лише друзі та родичі, яким ви <a href="#howtoe2ee">надіслали свій QR-код або посилання-запрошення</a>, можуть вам писати.</p>
|
<p>As being a private messenger,
|
||||||
|
only friends and family you <a href="#howtoe2ee">share your QR code or invite link with</a> can write to you.</p>
|
||||||
|
|
||||||
<p>Ваші друзі можуть поділитися вашими контактними даними з іншими друзями, це відображається як <b style="border: 1px solid currentColor; padding: 0 3px; font-size:90%">Запит</b></p>
|
<p>Your friends may share your contact with other friends,
|
||||||
|
this appears as <b style="border: 1px solid currentColor; padding: 0 3px; font-size:90%">Request</b></p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@@ -202,17 +197,32 @@ the ability to chat is delayed until connectivity is restored.</p>
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3 id="як-я-можу-познайомити-двох-своїх-друзів-один-з-одним">
|
<h3 id="how-can-i-put-two-of-my-friends-in-contact-with-each-other">
|
||||||
|
|
||||||
|
|
||||||
Як я можу познайомити двох своїх друзів один з одним? <a href="#як-я-можу-познайомити-двох-своїх-друзів-один-з-одним" class="anchor"></a>
|
How can I put two of my friends in contact with each other? <a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Додайте перший контакт до чату другого, скориставшись функцією <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Кнопка «Додати» → Контакт</strong>. Ви також можете додати коротке повідомлення-представлення.</p>
|
<p>Attach the first contact to the chat of the second using <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment Button → Contact</strong>.
|
||||||
|
You can also add a little introduction message.</p>
|
||||||
|
|
||||||
<p>Тоді другий контакт отримає <strong>картку</strong> і зможе натиснути на неї, щоб почати чат із першим контактом.</p>
|
<p>The second contact will receive a <strong>card</strong> then
|
||||||
|
and can tap it to start chatting with the first contact.</p>
|
||||||
|
|
||||||
|
<h3 id="чи-підтримує-delta-chat-вкладення-у-вигляді-фото-відео-тощо">
|
||||||
|
|
||||||
|
|
||||||
|
Чи підтримує Delta Chat вкладення у вигляді фото, відео тощо? <a href="#чи-підтримує-delta-chat-вкладення-у-вигляді-фото-відео-тощо" class="anchor"></a>
|
||||||
|
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Так. Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment-</strong>
|
||||||
|
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons</p>
|
||||||
|
|
||||||
|
<p>З міркувань продуктивності, зображення оптимізовані та надсилаються в меншому розмірі за замовчуванням, але ви можете надіслати їх як «файл», щоб зберегти оригінал.</p>
|
||||||
|
|
||||||
<h3 id="multiple-accounts">
|
<h3 id="multiple-accounts">
|
||||||
|
|
||||||
@@ -222,7 +232,9 @@ the ability to chat is delayed until connectivity is restored.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Профіль — це <strong>ім’я, зображення</strong> та деяка додаткова інформація для шифрування повідомлень. Профіль зберігається виключно на вашому пристрої (пристроях) і використовує сервер лише для передачі повідомлень.</p>
|
<p>A profile is <strong>a name, a picture</strong> and some additional information for encrypting messages.
|
||||||
|
A profile lives on your device(s) only
|
||||||
|
and uses the server only to relay messages.</p>
|
||||||
|
|
||||||
<p>Під час першого встановлення Delta Chat створюється перший профіль.</p>
|
<p>Під час першого встановлення Delta Chat створюється перший профіль.</p>
|
||||||
|
|
||||||
@@ -252,7 +264,10 @@ the ability to chat is delayed until connectivity is restored.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Так, ви можете це зробити в розділі <strong>Налаштування → Профіль → Опис</strong>. Після того як ви надішлете повідомлення контакту, він побачить його, переглянувши ваші контактні дані.</p>
|
<p>Yes,
|
||||||
|
you can do so under <strong>Settings → Profile → Bio</strong>.
|
||||||
|
Once you sent a message to a contact,
|
||||||
|
they will see it when they view your contact details.</p>
|
||||||
|
|
||||||
<h3 id="що-значить-закріплення-приглушення-архівування">
|
<h3 id="що-значить-закріплення-приглушення-архівування">
|
||||||
|
|
||||||
@@ -320,7 +335,10 @@ the ability to chat is delayed until connectivity is restored.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Іноді біля аватара контакту можна побачити <strong>зелену крапку</strong> <img style="vertical-align:middle; width:1.2em; margin:1px" src="../green-dot.png" alt="" />. Це означає, що ви <strong>нещодавно бачили його</strong> протягом останніх 10 хвилин, наприклад, тому що він надіслав вам повідомлення або підтвердження прочитання.</p>
|
<p>You can sometimes see a <strong>green dot</strong> <img style="vertical-align:middle; width:1.2em; margin:1px" src="../green-dot.png" alt="" />
|
||||||
|
next to the avatar of a contact.
|
||||||
|
It means they were <strong>recently seen by you</strong> in the last 10 minutes,
|
||||||
|
e.g. because they messaged you or sent a read receipt.</p>
|
||||||
|
|
||||||
<p>So this is not a real time online status
|
<p>So this is not a real time online status
|
||||||
and others will as well not always see that you are “online”.</p>
|
and others will as well not always see that you are “online”.</p>
|
||||||
@@ -370,32 +388,6 @@ has <strong>Settings → Chats → Read Receipts</strong> enabled.</p>
|
|||||||
|
|
||||||
<p>Зауважте, що початкове повідомлення все ще може бути отримане учасниками чату які могли вже відповісти, переслати, зберегти, зробити знімок екрану або іншим чином скопіювати повідомлення.</p>
|
<p>Зауважте, що початкове повідомлення все ще може бути отримане учасниками чату які могли вже відповісти, переслати, зберегти, зробити знімок екрану або іншим чином скопіювати повідомлення.</p>
|
||||||
|
|
||||||
<h3 id="mediaquality">
|
|
||||||
|
|
||||||
|
|
||||||
How is media quality handled? <a href="#mediaquality" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach-</strong>
|
|
||||||
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>By default, compression ensures <strong>fast, efficient delivery</strong> that respects everyone’s data limits and storage.
|
|
||||||
This is ideal for everyday communication.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>In regions with worse connectivity,
|
|
||||||
you can choose higher compression at <strong>Settings → Chats → Outgoing Media Quality</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>If you specifically need to send media in its <strong>original quality</strong>, use <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attach → File</strong> in the chat.
|
|
||||||
Please use this method sparingly, as sending original files will significantly increase data usage for you and all recipients in the chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="ephemeralmsgs">
|
<h3 id="ephemeralmsgs">
|
||||||
|
|
||||||
|
|
||||||
@@ -584,197 +576,6 @@ but more than 150 is not recommended.</p>
|
|||||||
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
where Delta Chat is a private messenger for chatting with <a href="#groups">equal rights</a>.
|
||||||
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
See <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s number</a> for more insights.</p>
|
||||||
|
|
||||||
<h2 id="channels">
|
|
||||||
|
|
||||||
|
|
||||||
Channels <a href="#channels" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Channels are a one-to-many tool for broadcasting messages.</p>
|
|
||||||
|
|
||||||
<h3 id="subscribe-to-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Subscribe to a channel <a href="#subscribe-to-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Scan the <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> <strong>QR code</strong>
|
|
||||||
or tap the <strong>invite link</strong> you got from the channel owner.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>That’s all!
|
|
||||||
You will receive a few of the messages from the channel history
|
|
||||||
and, from that point on, all new messages from the channel.</p>
|
|
||||||
|
|
||||||
<p><strong>Don’t worry,</strong> if that does not happen immediately.
|
|
||||||
Once the channel owner comes online, your join request will be processed.</p>
|
|
||||||
|
|
||||||
<p>As all of Delta Chat, also Channels are private and decentralized,
|
|
||||||
there is no public discovery.</p>
|
|
||||||
|
|
||||||
<p>Other channel subscribers will not see that you subscribed and cannot message you.
|
|
||||||
The channel owner, however, can message you.
|
|
||||||
They will also see that you read a message unless you have read receipts disabled.</p>
|
|
||||||
|
|
||||||
<p>If you do not want to share your main profile,
|
|
||||||
you can also create a <a href="#multiple-accounts">dedicated profile</a> for joining a channel.</p>
|
|
||||||
|
|
||||||
<h3 id="create-a-channel">
|
|
||||||
|
|
||||||
|
|
||||||
Create a channel <a href="#create-a-channel" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>New Chat</strong> and choose <strong>New Channel</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Enter a <strong>name</strong>, optionally set an <strong>image</strong> and <strong>description</strong>, and hit the <strong>Create</strong> button.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can now send and manage messages as usual.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>From the channel’s profile, <strong>share the QR code or invite link with others</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Subscribers will receive your messages,
|
|
||||||
but they cannot send messages in your channel.
|
|
||||||
When subscribing, they will receive <strong>a few of the latest messages of the channel history</strong>.</p>
|
|
||||||
|
|
||||||
<p>You can see the <strong>view count</strong> beside each message.
|
|
||||||
Note that this only counts subscribers who have read receipts enabled,
|
|
||||||
so the real view count may be larger.</p>
|
|
||||||
|
|
||||||
<h3 id="how-many-subscribers-can-a-channel-have">
|
|
||||||
|
|
||||||
|
|
||||||
How many subscribers can a channel have? <a href="#how-many-subscribers-can-a-channel-have" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p>Channels are designed for much larger audiences than <a href="#groups">groups</a>.</p>
|
|
||||||
|
|
||||||
<p>The practical limit depends on the used <a href="#relays">relay</a>,
|
|
||||||
so there is no single fixed number that applies everywhere.</p>
|
|
||||||
|
|
||||||
<p>For really large channels with several tens of thousands of subscribers,
|
|
||||||
we recommend using a <a href="#multiple-accounts">dedicated profile</a> for the channel
|
|
||||||
and checking whether the relay is suitable.</p>
|
|
||||||
|
|
||||||
<p>But don’t be too hesitant: Delta Chat is designed to be relay-agnostic,
|
|
||||||
so you can change your relay at any point easily -
|
|
||||||
your existing subscribers will not even notice.
|
|
||||||
You only have to update the invite link you share with new subscribers in that case.</p>
|
|
||||||
|
|
||||||
<h2 id="calls">
|
|
||||||
|
|
||||||
|
|
||||||
Calls <a href="#calls" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>Delta Chat supports one-to-one <strong>audio calls</strong> and <strong>video calls</strong>.</p>
|
|
||||||
|
|
||||||
<p>Calls are supported on Desktop, Ubuntu Touch, iOS and Android 8 and newer.</p>
|
|
||||||
|
|
||||||
<h3 id="place-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Place a call <a href="#place-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>In a one-to-one chat, tap the 📞 <strong>call icon</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>This opens a small menu
|
|
||||||
where you can choose whether to place an <strong>Audio Call</strong> or a <strong>Video Call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="accept-or-reject-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
Accept or reject a call <a href="#accept-or-reject-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>When someone calls you,
|
|
||||||
Delta Chat shows an <strong>incoming call screen</strong> or notification.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Tap <strong>Accept</strong> to answer
|
|
||||||
or <strong>Decline</strong> to reject the call.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="during-a-call">
|
|
||||||
|
|
||||||
|
|
||||||
During a call <a href="#during-a-call" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>mute</strong> your microphone.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>You can <strong>enable or disable your camera</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>On mobile, you can <strong>switch between front and back cameras</strong>.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Depending on the device, you can also select the audio output or use picture-in-picture.
|
|
||||||
On desktop, the call is using a dedicated window
|
|
||||||
and you can continue using the main Delta Chat window as usual.</p>
|
|
||||||
|
|
||||||
<h3 id="missed-calls-and-notifications">
|
|
||||||
|
|
||||||
|
|
||||||
Missed calls and notifications <a href="#missed-calls-and-notifications" class="anchor"></a>
|
|
||||||
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>If you do not answer, do not hear the ringing, or do not have your device at hand,
|
|
||||||
the call appears as a <strong>missed call</strong>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><strong>Only your accepted contacts</strong> can make your device ring.
|
|
||||||
Contact requests will appear as usual and will not ring.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>At <strong>Settings → Notifications → Calls</strong>,
|
|
||||||
you can disable the special call ringing screen completely.
|
|
||||||
If you do so, you will not be disturbed by any ringing notification,
|
|
||||||
you can still pick up the call by tapping the incoming call message bubble in its chat.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="webxdc">
|
<h2 id="webxdc">
|
||||||
|
|
||||||
|
|
||||||
@@ -1138,26 +939,22 @@ Relays are operated by different groups and people.</p>
|
|||||||
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
<p>By default, after installation, a relay is <strong>automatically set up</strong>,
|
||||||
so you do not need to care about that.
|
so you do not need to care about that.
|
||||||
However, if you want to,
|
However, if you want to,
|
||||||
you can configure relays at <strong>Settings → Advanced → Relays</strong>:</p>
|
you can configure relays at At <strong>Settings → Advanced → Relays</strong>:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
<p>You can <strong>add</strong> a relay by scanning its QR code;
|
||||||
<a href="https://chatmail.at/relays">chatmail.at/relays</a> shows some known ones.
|
<a href="https://chatmail.at/relays">https://chatmail.at/relays</a> shows some known ones.
|
||||||
If you have multiple relays, you will receive messages on all of them.
|
If you have multiple relays, you will receive messages on all of them.</p>
|
||||||
Contacts learn your current relays automatically when you message them.</p>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Tap on a relay to set it as <strong>used for sending</strong>.</p>
|
<p>The <strong>default</strong> defines the one where your chat partners send future messages to.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>If you <strong>remove</strong> a relay,
|
<p>If you <strong>remove</strong> a relay,
|
||||||
contacts who only know this relay may not reach you until you message them again.
|
make sure another default relay was used for a sufficient amount of time.
|
||||||
To stay reachable in the meantime, choose <strong>Hide from Contacts</strong> in the confirmation dialog
|
Otherwise, messages from your chat partners won’t reach you.
|
||||||
instead of removing it right away.</p>
|
If in doubt, remove later.</p>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>To <strong>show</strong> a hidden relay again, tap on it.</p>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -1298,10 +1095,6 @@ to send anonymous usage statistics.</p>
|
|||||||
<li>
|
<li>
|
||||||
<p><a href="https://autocrypt.org">Autocrypt</a> використовується для автоматичного встановлення наскрізного шифрування між контактами і всіма учасниками групового чату.</p>
|
<p><a href="https://autocrypt.org">Autocrypt</a> використовується для автоматичного встановлення наскрізного шифрування між контактами і всіма учасниками групового чату.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
|
||||||
will bring post-quantum resistant encryption and forward secrecy.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Поширення контакту в чаті</a> дозволяє отримувачам використовувати наскрізне шифрування з контактом.</p>
|
<p><a href="https://github.com/chatmail/core/blob/main/spec.md#attaching-a-contact-to-a-message">Поширення контакту в чаті</a> дозволяє отримувачам використовувати наскрізне шифрування з контактом.</p>
|
||||||
</li>
|
</li>
|
||||||
@@ -1461,20 +1254,23 @@ can not be identified easily.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>The used <a href="#relays">relays</a> need to know your IP Address,
|
<p>The used <a href="#relays">relay</a> needs to know your IP Address,
|
||||||
as well as sometimes your contact’s devices if you have a <a href="#calls">call</a>
|
as well as sometimes your contact’s devices if you have a <a href="#experiments">call</a>
|
||||||
or use <a href="#webxdc">apps</a> together.</p>
|
or use <a href="#webxdc">apps</a> together.</p>
|
||||||
|
|
||||||
<p>IP Addresses are needed for connectivity and efficiency.
|
<p>IP Addresses are needed for connectivity and efficiency.
|
||||||
Delta Chat neither persists nor exposes them.
|
They are neither persisted nor exposed.
|
||||||
Note that IP Addresses
|
Note that the IP Address
|
||||||
are not like an address you give to a delivery service,
|
is not like a detailed address you give to a delivery service,
|
||||||
but typically less precise, often defining city or region only.</p>
|
but much more coarse, often defining region or country only.</p>
|
||||||
|
|
||||||
<p>If you see your IP Address as a risk,
|
<p>As this is just how the internet and other messengers work by default,
|
||||||
we recommend to use a VPN for the whole system.
|
we do not offer options here or ask upfront questions.</p>
|
||||||
Per-app options leave gaps across your system.
|
|
||||||
For example, tapping a link can expose IP Addresses to unknown parties, which is by far the larger risk.</p>
|
<p>If you see your IP Address as a security or privacy risk,
|
||||||
|
we recommend to use a VPN, in combination with system lockdown mode.
|
||||||
|
Hunting down options in all apps on your system will leave gaps.
|
||||||
|
For example, tapping a link exposes IP Addresses to unknown parties and is the by far larger risk here.</p>
|
||||||
|
|
||||||
<h3 id="sealedsender">
|
<h3 id="sealedsender">
|
||||||
|
|
||||||
@@ -1502,13 +1298,11 @@ but an implementation has not been agreed as a priority yet.</p>
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>Ні, поки ще ні.</p>
|
||||||
|
|
||||||
<p>Delta Chat наразі не підтримує ідеальну пряму секретність (Perfect Forward Secrecy, PFS). Це означає, що якщо ваш приватний ключ для розшифрування буде скомпрометовано, а хтось заздалегідь зібрав ваші повідомлення під час передачі, він зможе розшифрувати та прочитати їх, використовуючи зламаний ключ. Зверніть увагу, що пряма секретність підвищує рівень безпеки лише в тому разі, якщо ви видаляєте повідомлення. Інакше, якщо хтось отримує доступ до ваших ключів розшифрування, він зазвичай також має доступ до всіх ваших невидалених повідомлень і навіть не потребує розшифровувати заздалегідь перехоплені дані.</p>
|
<p>Delta Chat наразі не підтримує ідеальну пряму секретність (Perfect Forward Secrecy, PFS). Це означає, що якщо ваш приватний ключ для розшифрування буде скомпрометовано, а хтось заздалегідь зібрав ваші повідомлення під час передачі, він зможе розшифрувати та прочитати їх, використовуючи зламаний ключ. Зверніть увагу, що пряма секретність підвищує рівень безпеки лише в тому разі, якщо ви видаляєте повідомлення. Інакше, якщо хтось отримує доступ до ваших ключів розшифрування, він зазвичай також має доступ до всіх ваших невидалених повідомлень і навіть не потребує розшифровувати заздалегідь перехоплені дані.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<p>Ми розробили підхід Forward Secrecy, який витримав початкову експертизу від деяких криптографів та експертів з реалізації але чекає на більш офіційний звіт щоб переконатися, що він надійно працює в об’єднаних системах обміну повідомленнями та при використанні декількох пристроїв, перш ніж його можна буде реалізувати в <a href="https://github.com/chatmail/core">ядрі чату</a>, що зробить його доступним у всіх <a href="https://chatmail.at/clients">клієнтах чату</a>.</p>
|
||||||
will provide reliable deletion (forward secrecy) through automatic key rotation.
|
|
||||||
This approach is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
|
||||||
|
|
||||||
<h3 id="pqc">
|
<h3 id="pqc">
|
||||||
|
|
||||||
@@ -1518,13 +1312,9 @@ This approach is specified in the <a href="https://datatracker.ietf.org/doc/draf
|
|||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>Not yet, but it’s coming with <a href="https://autocrypt2.org">Autocrypt v2</a>.</p>
|
<p>Ні, поки ще ні.</p>
|
||||||
|
|
||||||
<p><a href="https://autocrypt2.org">Autocrypt v2</a>, scheduled for full implementation in 2026,
|
<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>
|
||||||
will bring post-quantum resistant encryption to protect against quantum computer attacks.
|
|
||||||
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>.
|
|
||||||
The implementation is specified in the <a href="https://datatracker.ietf.org/doc/draft-autocrypt-openpgp-v2-cert/">Autocrypt v2 OpenPGP Certificates</a> draft.</p>
|
|
||||||
|
|
||||||
<h3 id="як-я-можу-вручну-перевірити-інформацію-про-шифрування">
|
<h3 id="як-я-можу-вручну-перевірити-інформацію-про-шифрування">
|
||||||
|
|
||||||
@@ -1581,7 +1371,7 @@ you need to look it up in the “keypairs” SQLite table of a profile backup ta
|
|||||||
<p>Починаючи з 2023 року, ми виправили проблеми з безпекою та конфіденційністю у функції “веб застосунків, що поширені у чаті”, пов’язані зі збоями в роботі пісочниці особливо в Chromium. Згодом ми отримали незалежний аудит безпеки аудит безпеки від Cure53, і всі знайдені проблеми були виправлені в серії додатків 1.36, випущених у квітні 2023 року. Повну історію про наскрізну безпеку в Інтернеті дивіться <a href="https://delta.chat/en/2023-05-22-webxdc-security">тут</a>.</p>
|
<p>Починаючи з 2023 року, ми виправили проблеми з безпекою та конфіденційністю у функції “веб застосунків, що поширені у чаті”, пов’язані зі збоями в роботі пісочниці особливо в Chromium. Згодом ми отримали незалежний аудит безпеки аудит безпеки від Cure53, і всі знайдені проблеми були виправлені в серії додатків 1.36, випущених у квітні 2023 року. Повну історію про наскрізну безпеку в Інтернеті дивіться <a href="https://delta.chat/en/2023-05-22-webxdc-security">тут</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Починаючи з 2023 року <a href="https://cure53.de">Cure53</a> проаналізував транспортне шифрування мережевих з’єднань Delta Chat і відтворюване налаштування поштового сервера як <a href="https://delta.chat/serverguide">рекомендовано на цьому сайті</a>. Ви можете прочитати більше про аудит <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">у нашому блозі</a> або прочитайте <a href="https://delta.chat/assets/blog/MER-01-report.pdf">повний звіт тут</a>.</p>
|
<p>Починаючи з 2023 року <a href="https://cure53.de">Cure53</a> проаналізував транспортне шифрування мережевих з’єднань Delta Chat і відтворюване налаштування поштового сервера як <a href="https://delta.chat/uk/serverguide">рекомендовано на цьому сайті</a>. Ви можете прочитати більше про аудит <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">у нашому блозі</a> або прочитайте <a href="https://delta.chat/assets/blog/MER-01-report.pdf">повний звіт тут</a>.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>У 2020 році <a href="https://includesecurity.com">Include Security</a> проаналізувала Rust-<a href="https://github.com/deltachat/deltachat-core-rust/">ядро</a> Delta Chat і бібліотеки <a href="https://github.com/async-email/async-imap">IMAP</a>, <a href="https://github.com/async-email/async-smtp">SMTP</a> та <a href="https://github.com/async-email/async-native-tls">TLS</a>. Він не виявив критичних або серйозних проблем. У звіті виявлено кілька слабких місць середнього ступеня тяжкості – вони самі по собі не становлять загрози для користувачів Delta Chat оскільки вони залежать від середовища, у якому використовується Delta Chat. З міркувань зручності використання та сумісності ми не можемо пом’якшити їх усі тому вирішили надати рекомендації щодо безпеки користувачам, яким загрожує небезпека. Ви можете прочитати <a href="https://delta.chat/assets/blog/2020-second-security-review.pdf">повний звіт тут</a>.</p>
|
<p>У 2020 році <a href="https://includesecurity.com">Include Security</a> проаналізувала Rust-<a href="https://github.com/deltachat/deltachat-core-rust/">ядро</a> Delta Chat і бібліотеки <a href="https://github.com/async-email/async-imap">IMAP</a>, <a href="https://github.com/async-email/async-smtp">SMTP</a> та <a href="https://github.com/async-email/async-native-tls">TLS</a>. Він не виявив критичних або серйозних проблем. У звіті виявлено кілька слабких місць середнього ступеня тяжкості – вони самі по собі не становлять загрози для користувачів Delta Chat оскільки вони залежать від середовища, у якому використовується Delta Chat. З міркувань зручності використання та сумісності ми не можемо пом’якшити їх усі тому вирішили надати рекомендації щодо безпеки користувачам, яким загрожує небезпека. Ви можете прочитати <a href="https://delta.chat/assets/blog/2020-second-security-review.pdf">повний звіт тут</a>.</p>
|
||||||
@@ -1655,24 +1445,32 @@ Google Play Store, F-Droid, Huawei App Gallery, iOS and macOS App Store, Microso
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>У 2023 та 2024 роках нас прийняли до програми Next Generation Internet (NGI) за нашу роботу над <a href="https://nlnet.nl/project/WebXDC-Push/">webxdc PUSH</a>, а також у співпраці з партнерами, які працюють над <a href="https://nlnet.nl/project/Webxdc-Evolve/">webxdc evolve</a>, <a href="https://nlnet.nl/project/WebXDC-XMPP/">webxdc XMPP</a>, <a href="https://nlnet.nl/project/DeltaTouch/">DeltaTouch</a> та <a href="https://nlnet.nl/project/DeltaTauri/">DeltaTauri</a>. Усі ці проєкти частково завершені або будуть завершені на початку 2025 року.</p>
|
<p>In 2023 and 2024 we got accepted in the Next Generation Internet (NGI)
|
||||||
|
program for our work in <a href="https://nlnet.nl/project/WebXDC-Push/">webxdc PUSH</a>,
|
||||||
|
along with collaboration partners working on
|
||||||
|
<a href="https://nlnet.nl/project/Webxdc-Evolve/">webxdc evolve</a>,
|
||||||
|
<a href="https://nlnet.nl/project/WebXDC-XMPP/">webxdc XMPP</a>,
|
||||||
|
<a href="https://nlnet.nl/project/DeltaTouch/">DeltaTouch</a> and
|
||||||
|
<a href="https://nlnet.nl/project/DeltaTauri/">DeltaTauri</a>.
|
||||||
|
All of these projects are partially completed or to be completed in early 2025.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>У 2021 році ми отримали подальше фінансування від ЄС на дві пропозиції щодо Інтернету наступного покоління а саме на <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - каталог перенесення провайдерів електронної пошти</a> (~97 тис. євро) та <a href="https://nlnet.nl/project/EmailPorting/">AEAP - перенесення адрес електронної пошти</a> (~90 тис. євро), що дозволило нам покращити багатопрофільну підтримку, вдосконалити налаштування контактів та груп за допомогою QR-коду та багато інших мережевих покращень на всіх платформах.</p>
|
<p>In 2021 we received further EU funding for two Next-Generation-Internet
|
||||||
|
proposals, namely for <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - email provider portability directory</a> (~97K EUR) and <a href="https://nlnet.nl/project/EmailPorting/">AEAP - email address porting</a> (~90K EUR) which resulted in better multi-profile support, improved QR-code contact and group setups and many networking improvements on all platforms.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Фонд <a href="https://nlnet.nl/">NLnet</a> виділив у 2019/2020 роках 46 тисяч євро на
|
<p>The <a href="https://nlnet.nl/">NLnet foundation</a> granted in 2019/2020 EUR 46K for
|
||||||
завершення прив’язок Rust/Python та запуск екосистеми чат-ботів.</p>
|
completing Rust/Python bindings and instigating a Chat-bot eco-system.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><a href="https://opentechfund.org">Open Technology Fund</a> надав нам два гранти.
|
<p>The <a href="https://opentechfund.org">Open Technology Fund</a> gave us a
|
||||||
Перший грант 2018/2019 року (~$200K), допоміг значно покращили додаток для Android
|
first 2018/2019 grant (~$200K) during which we majorly improved the Android app
|
||||||
і випустили першу бета-версію додатка для ПК, і який до того ж
|
and released a first Desktop app beta version, and which moreover
|
||||||
закріпив наші розробки функцій у дослідженнях UX у контексті прав людини,
|
moored our feature developments in UX research in human rights contexts,
|
||||||
дивіться наш підсумковий звіт <a href="https://delta.chat/en/2019-07-19-uxreport">Needfinding and UX report</a>.
|
see our concluding <a href="https://delta.chat/en/2019-07-19-uxreport">Needfinding and UX report</a>.
|
||||||
Другий грант 2019/2020 року (~$300K) допоміг нам
|
The second 2019/2020 grant (~$300K) helped us to
|
||||||
випустити Delta/iOS версію, конвертувати нашу основному бібліотеку на Rust,
|
release Delta/iOS versions, to convert our core library to Rust, and
|
||||||
і додати нові функції для всіх платформ.</p>
|
to provide new features for all platforms.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Проект ЄС <a href="https://nextleap.eu">NEXTLEAP</a> фінансував дослідження та впровадження верифікованих груп і протоколів встановлення контактів у 2017 та 2018 роках, а також допоміг інтегрувати наскрізне шифрування через <a href="https://autocrypt.org">Autocrypt</a>.</p>
|
<p>Проект ЄС <a href="https://nextleap.eu">NEXTLEAP</a> фінансував дослідження та впровадження верифікованих груп і протоколів встановлення контактів у 2017 та 2018 роках, а також допоміг інтегрувати наскрізне шифрування через <a href="https://autocrypt.org">Autocrypt</a>.</p>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -14,7 +14,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
/* Basic RPC Transport implementation */
|
/* Basic RPC Transport implementation */
|
||||||
public abstract class BaseRpcTransport implements Rpc.RpcTransport {
|
public abstract class BaseTransport implements Rpc.Transport {
|
||||||
private final Map<Integer, SettableFuture<JsonNode>> requestFutures = new ConcurrentHashMap<>();
|
private final Map<Integer, SettableFuture<JsonNode>> requestFutures = new ConcurrentHashMap<>();
|
||||||
private int requestId = 0;
|
private int requestId = 0;
|
||||||
private final ObjectMapper mapper = new ObjectMapper();
|
private final ObjectMapper mapper = new ObjectMapper();
|
||||||
@@ -9,16 +9,16 @@ import chat.delta.rpc.types.*;
|
|||||||
|
|
||||||
public class Rpc {
|
public class Rpc {
|
||||||
|
|
||||||
public interface RpcTransport {
|
public interface Transport {
|
||||||
void call(String method, JsonNode... params) throws RpcException;
|
void call(String method, JsonNode... params) throws RpcException;
|
||||||
<T> T callForResult(TypeReference<T> resultType, String method, JsonNode... params) throws RpcException;
|
<T> T callForResult(TypeReference<T> resultType, String method, JsonNode... params) throws RpcException;
|
||||||
ObjectMapper getObjectMapper();
|
ObjectMapper getObjectMapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final RpcTransport transport;
|
public final Transport transport;
|
||||||
private final ObjectMapper mapper;
|
private final ObjectMapper mapper;
|
||||||
|
|
||||||
public Rpc(RpcTransport transport) {
|
public Rpc(Transport transport) {
|
||||||
this.transport = transport;
|
this.transport = transport;
|
||||||
this.mapper = transport.getObjectMapper();
|
this.mapper = transport.getObjectMapper();
|
||||||
}
|
}
|
||||||
@@ -53,11 +53,6 @@ public class Rpc {
|
|||||||
return transport.callForResult(new TypeReference<Event>(){}, "get_next_event");
|
return transport.callForResult(new TypeReference<Event>(){}, "get_next_event");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Waits for at least one event and return a batch of events. */
|
|
||||||
public java.util.List<Event> getNextEventBatch() throws RpcException {
|
|
||||||
return transport.callForResult(new TypeReference<java.util.List<Event>>(){}, "get_next_event_batch");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer addAccount() throws RpcException {
|
public Integer addAccount() throws RpcException {
|
||||||
return transport.callForResult(new TypeReference<Integer>(){}, "add_account");
|
return transport.callForResult(new TypeReference<Integer>(){}, "add_account");
|
||||||
}
|
}
|
||||||
@@ -289,7 +284,6 @@ public class Rpc {
|
|||||||
* from a server encoded in a QR code.
|
* from a server encoded in a QR code.
|
||||||
* - [Self::list_transports()] to get a list of all configured transports.
|
* - [Self::list_transports()] to get a list of all configured transports.
|
||||||
* - [Self::delete_transport()] to remove a transport.
|
* - [Self::delete_transport()] to remove a transport.
|
||||||
* - [Self::set_transport_unpublished()] to set whether contacts see this transport.
|
|
||||||
*/
|
*/
|
||||||
public void addOrUpdateTransport(Integer accountId, EnteredLoginParam param) throws RpcException {
|
public void addOrUpdateTransport(Integer accountId, EnteredLoginParam param) throws RpcException {
|
||||||
transport.call("add_or_update_transport", mapper.valueToTree(accountId), mapper.valueToTree(param));
|
transport.call("add_or_update_transport", mapper.valueToTree(accountId), mapper.valueToTree(param));
|
||||||
@@ -313,22 +307,11 @@ public class Rpc {
|
|||||||
* Returns the list of all email accounts that are used as a transport in the current profile.
|
* Returns the list of all email accounts that are used as a transport in the current profile.
|
||||||
* Use [Self::add_or_update_transport()] to add or change a transport
|
* Use [Self::add_or_update_transport()] to add or change a transport
|
||||||
* and [Self::delete_transport()] to delete a transport.
|
* and [Self::delete_transport()] to delete a transport.
|
||||||
* Use [Self::list_transports_ex()] to additionally query
|
|
||||||
* whether the transports are marked as 'unpublished'.
|
|
||||||
*/
|
*/
|
||||||
public java.util.List<EnteredLoginParam> listTransports(Integer accountId) throws RpcException {
|
public java.util.List<EnteredLoginParam> listTransports(Integer accountId) throws RpcException {
|
||||||
return transport.callForResult(new TypeReference<java.util.List<EnteredLoginParam>>(){}, "list_transports", mapper.valueToTree(accountId));
|
return transport.callForResult(new TypeReference<java.util.List<EnteredLoginParam>>(){}, "list_transports", mapper.valueToTree(accountId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of all email accounts that are used as a transport in the current profile.
|
|
||||||
* Use [Self::add_or_update_transport()] to add or change a transport
|
|
||||||
* and [Self::delete_transport()] to delete a transport.
|
|
||||||
*/
|
|
||||||
public java.util.List<TransportListEntry> listTransportsEx(Integer accountId) throws RpcException {
|
|
||||||
return transport.callForResult(new TypeReference<java.util.List<TransportListEntry>>(){}, "list_transports_ex", mapper.valueToTree(accountId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the transport with the specified email address
|
* Removes the transport with the specified email address
|
||||||
* (i.e. [EnteredLoginParam::addr]).
|
* (i.e. [EnteredLoginParam::addr]).
|
||||||
@@ -337,22 +320,6 @@ public class Rpc {
|
|||||||
transport.call("delete_transport", mapper.valueToTree(accountId), mapper.valueToTree(addr));
|
transport.call("delete_transport", mapper.valueToTree(accountId), mapper.valueToTree(addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Change whether the transport is unpublished.
|
|
||||||
* <p>
|
|
||||||
* Unpublished transports are not advertised to contacts,
|
|
||||||
* and self-sent messages are not sent there,
|
|
||||||
* so that we don't cause extra messages to the corresponding inbox,
|
|
||||||
* but can still receive messages from contacts who don't know our new transport addresses yet.
|
|
||||||
* <p>
|
|
||||||
* The default is false, but when the user updates from a version that didn't have this flag,
|
|
||||||
* existing secondary transports are set to unpublished,
|
|
||||||
* so that an existing transport address doesn't suddenly get spammed with a lot of messages.
|
|
||||||
*/
|
|
||||||
public void setTransportUnpublished(Integer accountId, String addr, Boolean unpublished) throws RpcException {
|
|
||||||
transport.call("set_transport_unpublished", mapper.valueToTree(accountId), mapper.valueToTree(addr), mapper.valueToTree(unpublished));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Signal an ongoing process to stop. */
|
/** Signal an ongoing process to stop. */
|
||||||
public void stopOngoingProcess(Integer accountId) throws RpcException {
|
public void stopOngoingProcess(Integer accountId) throws RpcException {
|
||||||
transport.call("stop_ongoing_process", mapper.valueToTree(accountId));
|
transport.call("stop_ongoing_process", mapper.valueToTree(accountId));
|
||||||
@@ -396,7 +363,7 @@ public class Rpc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (deprecated) Gets messages to be processed by the bot and returns their IDs.
|
* Gets messages to be processed by the bot and returns their IDs.
|
||||||
* <p>
|
* <p>
|
||||||
* Only messages with database ID higher than `last_msg_id` config value
|
* Only messages with database ID higher than `last_msg_id` config value
|
||||||
* are returned. After processing the messages, the bot should
|
* are returned. After processing the messages, the bot should
|
||||||
@@ -404,13 +371,6 @@ public class Rpc {
|
|||||||
* or manually updating the value to avoid getting already
|
* or manually updating the value to avoid getting already
|
||||||
* processed messages.
|
* processed messages.
|
||||||
* <p>
|
* <p>
|
||||||
* Deprecated 2026-04: This returns the message's id as soon as the first part arrives,
|
|
||||||
* even if it is not fully downloaded yet.
|
|
||||||
* The bot needs to wait for the message to be fully downloaded.
|
|
||||||
* Since this is usually not the desired behavior,
|
|
||||||
* bots should instead use the #DC_EVENT_INCOMING_MSG / [`types::events::EventType::IncomingMsg`]
|
|
||||||
* event for getting notified about new messages.
|
|
||||||
* <p>
|
|
||||||
* [`markseen_msgs`]: Self::markseen_msgs
|
* [`markseen_msgs`]: Self::markseen_msgs
|
||||||
*/
|
*/
|
||||||
public java.util.List<Integer> getNextMsgs(Integer accountId) throws RpcException {
|
public java.util.List<Integer> getNextMsgs(Integer accountId) throws RpcException {
|
||||||
@@ -418,7 +378,7 @@ public class Rpc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (deprecated) Waits for messages to be processed by the bot and returns their IDs.
|
* Waits for messages to be processed by the bot and returns their IDs.
|
||||||
* <p>
|
* <p>
|
||||||
* This function is similar to [`get_next_msgs`],
|
* This function is similar to [`get_next_msgs`],
|
||||||
* but waits for internal new message notification before returning.
|
* but waits for internal new message notification before returning.
|
||||||
@@ -429,13 +389,6 @@ public class Rpc {
|
|||||||
* To shutdown the bot, stopping I/O can be used to interrupt
|
* To shutdown the bot, stopping I/O can be used to interrupt
|
||||||
* pending or next `wait_next_msgs` call.
|
* pending or next `wait_next_msgs` call.
|
||||||
* <p>
|
* <p>
|
||||||
* Deprecated 2026-04: This returns the message's id as soon as the first part arrives,
|
|
||||||
* even if it is not fully downloaded yet.
|
|
||||||
* The bot needs to wait for the message to be fully downloaded.
|
|
||||||
* Since this is usually not the desired behavior,
|
|
||||||
* bots should instead use the #DC_EVENT_INCOMING_MSG / [`types::events::EventType::IncomingMsg`]
|
|
||||||
* event for getting notified about new messages.
|
|
||||||
* <p>
|
|
||||||
* [`get_next_msgs`]: Self::get_next_msgs
|
* [`get_next_msgs`]: Self::get_next_msgs
|
||||||
*/
|
*/
|
||||||
public java.util.List<Integer> waitNextMsgs(Integer accountId) throws RpcException {
|
public java.util.List<Integer> waitNextMsgs(Integer accountId) throws RpcException {
|
||||||
@@ -443,24 +396,23 @@ public class Rpc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Estimates the number of messages that will be deleted
|
* Estimate the number of messages that will be deleted
|
||||||
* by the `set_config()`-option `delete_device_after`.
|
* by the set_config()-options `delete_device_after` or `delete_server_after`.
|
||||||
* <p>
|
|
||||||
* This is typically used to show the estimated impact to the user
|
* This is typically used to show the estimated impact to the user
|
||||||
* before actually enabling deletion of old messages.
|
* before actually enabling deletion of old messages.
|
||||||
* <p>
|
|
||||||
* Messages in the "Saved Messages" chat are not counted as they will not be deleted automatically.
|
|
||||||
* <p>
|
|
||||||
* Parameters:
|
|
||||||
* - `from_server`: Deprecated, pass `false` here
|
|
||||||
* - `seconds`: Count messages older than the given number of seconds.
|
|
||||||
* <p>
|
|
||||||
* Returns the number of messages that are older than the given number of seconds.
|
|
||||||
*/
|
*/
|
||||||
public Integer estimateAutoDeletionCount(Integer accountId, Boolean fromServer, Integer seconds) throws RpcException {
|
public Integer estimateAutoDeletionCount(Integer accountId, Boolean fromServer, Integer seconds) throws RpcException {
|
||||||
return transport.callForResult(new TypeReference<Integer>(){}, "estimate_auto_deletion_count", mapper.valueToTree(accountId), mapper.valueToTree(fromServer), mapper.valueToTree(seconds));
|
return transport.callForResult(new TypeReference<Integer>(){}, "estimate_auto_deletion_count", mapper.valueToTree(accountId), mapper.valueToTree(fromServer), mapper.valueToTree(seconds));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String initiateAutocryptKeyTransfer(Integer accountId) throws RpcException {
|
||||||
|
return transport.callForResult(new TypeReference<String>(){}, "initiate_autocrypt_key_transfer", mapper.valueToTree(accountId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void continueAutocryptKeyTransfer(Integer accountId, Integer messageId, String setupCode) throws RpcException {
|
||||||
|
transport.call("continue_autocrypt_key_transfer", mapper.valueToTree(accountId), mapper.valueToTree(messageId), mapper.valueToTree(setupCode));
|
||||||
|
}
|
||||||
|
|
||||||
public java.util.List<Integer> getChatlistEntries(Integer accountId, Integer listFlags, String queryString, Integer queryContactId) throws RpcException {
|
public java.util.List<Integer> getChatlistEntries(Integer accountId, Integer listFlags, String queryString, Integer queryContactId) throws RpcException {
|
||||||
return transport.callForResult(new TypeReference<java.util.List<Integer>>(){}, "get_chatlist_entries", mapper.valueToTree(accountId), mapper.valueToTree(listFlags), mapper.valueToTree(queryString), mapper.valueToTree(queryContactId));
|
return transport.callForResult(new TypeReference<java.util.List<Integer>>(){}, "get_chatlist_entries", mapper.valueToTree(accountId), mapper.valueToTree(listFlags), mapper.valueToTree(queryString), mapper.valueToTree(queryContactId));
|
||||||
}
|
}
|
||||||
@@ -552,8 +504,6 @@ public class Rpc {
|
|||||||
* if `checkQr()` returns `askVerifyContact` or `askVerifyGroup`
|
* if `checkQr()` returns `askVerifyContact` or `askVerifyGroup`
|
||||||
* an out-of-band-verification can be joined using `secure_join()`
|
* an out-of-band-verification can be joined using `secure_join()`
|
||||||
* <p>
|
* <p>
|
||||||
* @deprecated as of 2026-03; use create_qr_svg(get_chat_securejoin_qr_code()) instead.
|
|
||||||
* <p>
|
|
||||||
* chat_id: If set to a group-chat-id,
|
* chat_id: If set to a group-chat-id,
|
||||||
* the Verified-Group-Invite protocol is offered in the QR code;
|
* the Verified-Group-Invite protocol is offered in the QR code;
|
||||||
* works for protected groups as well as for normal groups.
|
* works for protected groups as well as for normal groups.
|
||||||
@@ -719,6 +669,9 @@ public class Rpc {
|
|||||||
* because the word "channel" already appears a lot in the code,
|
* because the word "channel" already appears a lot in the code,
|
||||||
* which would make it hard to grep for it.
|
* which would make it hard to grep for it.
|
||||||
* <p>
|
* <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.
|
* Returns the created chat's id.
|
||||||
*/
|
*/
|
||||||
public Integer createBroadcast(Integer accountId, String chatName) throws RpcException {
|
public Integer createBroadcast(Integer accountId, String chatName) throws RpcException {
|
||||||
@@ -729,8 +682,7 @@ public class Rpc {
|
|||||||
* Set group name.
|
* Set group name.
|
||||||
* <p>
|
* <p>
|
||||||
* If the group is already _promoted_ (any message was sent to the group),
|
* If the group is already _promoted_ (any message was sent to the group),
|
||||||
* or if this is a brodacast channel,
|
* all group members are informed by a special status message that is sent automatically by this function.
|
||||||
* all members are informed by a special status message that is sent automatically by this function.
|
|
||||||
* <p>
|
* <p>
|
||||||
* Sends out #DC_EVENT_CHAT_MODIFIED and #DC_EVENT_MSGS_CHANGED if a status message was sent.
|
* Sends out #DC_EVENT_CHAT_MODIFIED and #DC_EVENT_MSGS_CHANGED if a status message was sent.
|
||||||
*/
|
*/
|
||||||
@@ -738,37 +690,11 @@ public class Rpc {
|
|||||||
transport.call("set_chat_name", mapper.valueToTree(accountId), mapper.valueToTree(chatId), mapper.valueToTree(newName));
|
transport.call("set_chat_name", mapper.valueToTree(accountId), mapper.valueToTree(chatId), mapper.valueToTree(newName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set group or broadcast channel description.
|
|
||||||
* <p>
|
|
||||||
* If the group is already _promoted_ (any message was sent to the group),
|
|
||||||
* or if this is a brodacast channel,
|
|
||||||
* all members are informed by a special status message that is sent automatically by this function.
|
|
||||||
* <p>
|
|
||||||
* Sends out #DC_EVENT_CHAT_MODIFIED and #DC_EVENT_MSGS_CHANGED if a status message was sent.
|
|
||||||
* <p>
|
|
||||||
* See also [`Self::get_chat_description`] / `getChatDescription()`.
|
|
||||||
*/
|
|
||||||
public void setChatDescription(Integer accountId, Integer chatId, String description) throws RpcException {
|
|
||||||
transport.call("set_chat_description", mapper.valueToTree(accountId), mapper.valueToTree(chatId), mapper.valueToTree(description));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the chat description from the database.
|
|
||||||
* <p>
|
|
||||||
* UIs show this in the profile page of the chat,
|
|
||||||
* it is settable by [`Self::set_chat_description`] / `setChatDescription()`.
|
|
||||||
*/
|
|
||||||
public String getChatDescription(Integer accountId, Integer chatId) throws RpcException {
|
|
||||||
return transport.callForResult(new TypeReference<String>(){}, "get_chat_description", mapper.valueToTree(accountId), mapper.valueToTree(chatId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set group profile image.
|
* Set group profile image.
|
||||||
* <p>
|
* <p>
|
||||||
* If the group is already _promoted_ (any message was sent to the group),
|
* If the group is already _promoted_ (any message was sent to the group),
|
||||||
* or if this is a brodacast channel,
|
* all group members are informed by a special status message that is sent automatically by this function.
|
||||||
* all members are informed by a special status message that is sent automatically by this function.
|
|
||||||
* <p>
|
* <p>
|
||||||
* Sends out #DC_EVENT_CHAT_MODIFIED and #DC_EVENT_MSGS_CHANGED if a status message was sent.
|
* Sends out #DC_EVENT_CHAT_MODIFIED and #DC_EVENT_MSGS_CHANGED if a status message was sent.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -840,16 +766,6 @@ public class Rpc {
|
|||||||
transport.call("marknoticed_chat", mapper.valueToTree(accountId), mapper.valueToTree(chatId));
|
transport.call("marknoticed_chat", mapper.valueToTree(accountId), mapper.valueToTree(chatId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks the last incoming message in the chat as _fresh_.
|
|
||||||
* <p>
|
|
||||||
* UI can use this to offer a "mark unread" option,
|
|
||||||
* so that already noticed chats get a badge counter again.
|
|
||||||
*/
|
|
||||||
public void markfreshChat(Integer accountId, Integer chatId) throws RpcException {
|
|
||||||
transport.call("markfresh_chat", mapper.valueToTree(accountId), mapper.valueToTree(chatId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the message that is immediately followed by the last seen
|
* Returns the message that is immediately followed by the last seen
|
||||||
* message.
|
* message.
|
||||||
@@ -919,22 +835,8 @@ public class Rpc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all message IDs belonging to a chat.
|
* Returns all messages of a particular chat.
|
||||||
* <p>
|
* <p>
|
||||||
* The list is already sorted and starts with the oldest message.
|
|
||||||
* Clients should not try to re-sort the list as this would be an expensive action
|
|
||||||
* and would result in inconsistencies between clients.
|
|
||||||
* Note that the messages are not necessarily sorted by their ID or by their displayed timestamp;
|
|
||||||
* UIs need to handle both the case of descending message IDs
|
|
||||||
* and of decreasing timestamps.
|
|
||||||
* <p>
|
|
||||||
* Optionally, 'daymarkers' added to the ID array may help to
|
|
||||||
* implement virtual lists.
|
|
||||||
* <p>
|
|
||||||
* Parameters:
|
|
||||||
* <p>
|
|
||||||
* * chat_id The chat ID of which the messages IDs should be queried.
|
|
||||||
* * _info_only: Deprecated, pass `false` here.
|
|
||||||
* * `add_daymarker` - If `true`, add day markers as `DC_MSG_ID_DAYMARKER` to the result,
|
* * `add_daymarker` - If `true`, add day markers as `DC_MSG_ID_DAYMARKER` to the result,
|
||||||
* e.g. [1234, 1237, 9, 1239]. The day marker timestamp is the midnight one for the
|
* e.g. [1234, 1237, 9, 1239]. The day marker timestamp is the midnight one for the
|
||||||
* corresponding (following) day in the local timezone.
|
* corresponding (following) day in the local timezone.
|
||||||
@@ -952,14 +854,6 @@ public class Rpc {
|
|||||||
return transport.callForResult(new TypeReference<java.util.List<Integer>>(){}, "get_existing_msg_ids", mapper.valueToTree(accountId), mapper.valueToTree(msgIds));
|
return transport.callForResult(new TypeReference<java.util.List<Integer>>(){}, "get_existing_msg_ids", mapper.valueToTree(accountId), mapper.valueToTree(msgIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all messages belonging to a chat.
|
|
||||||
* <p>
|
|
||||||
* Similar to `get_message_ids` / `getMessageIds`,
|
|
||||||
* see that function for details.
|
|
||||||
* The difference is that this function here returns a list of `MessageListItem`,
|
|
||||||
* which is an enum of a message or a daymarker.
|
|
||||||
*/
|
|
||||||
public java.util.List<MessageListItem> getMessageListItems(Integer accountId, Integer chatId, Boolean infoOnly, Boolean addDaymarker) throws RpcException {
|
public java.util.List<MessageListItem> getMessageListItems(Integer accountId, Integer chatId, Boolean infoOnly, Boolean addDaymarker) throws RpcException {
|
||||||
return transport.callForResult(new TypeReference<java.util.List<MessageListItem>>(){}, "get_message_list_items", mapper.valueToTree(accountId), mapper.valueToTree(chatId), mapper.valueToTree(infoOnly), mapper.valueToTree(addDaymarker));
|
return transport.callForResult(new TypeReference<java.util.List<MessageListItem>>(){}, "get_message_list_items", mapper.valueToTree(accountId), mapper.valueToTree(chatId), mapper.valueToTree(infoOnly), mapper.valueToTree(addDaymarker));
|
||||||
}
|
}
|
||||||
@@ -1209,6 +1103,11 @@ public class Rpc {
|
|||||||
return transport.callForResult(new TypeReference<String>(){}, "make_vcard", mapper.valueToTree(accountId), mapper.valueToTree(contacts));
|
return transport.callForResult(new TypeReference<String>(){}, "make_vcard", mapper.valueToTree(accountId), mapper.valueToTree(contacts));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sets vCard containing the given contacts to the message draft. */
|
||||||
|
public void setDraftVcard(Integer accountId, Integer msgId, java.util.List<Integer> contacts) throws RpcException {
|
||||||
|
transport.call("set_draft_vcard", mapper.valueToTree(accountId), mapper.valueToTree(msgId), mapper.valueToTree(contacts));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the [`ChatId`] for the 1:1 chat with `contact_id` if it exists.
|
* Returns the [`ChatId`] for the 1:1 chat with `contact_id` if it exists.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -1280,19 +1179,12 @@ public class Rpc {
|
|||||||
* even if there is no concurrent call to [`CommandApi::provide_backup`],
|
* even if there is no concurrent call to [`CommandApi::provide_backup`],
|
||||||
* but will fail after 60 seconds to avoid deadlocks.
|
* but will fail after 60 seconds to avoid deadlocks.
|
||||||
* <p>
|
* <p>
|
||||||
* @deprecated as of 2026-03; use `create_qr_svg(get_backup_qr())` instead.
|
|
||||||
* <p>
|
|
||||||
* Returns the QR code rendered as an SVG image.
|
* Returns the QR code rendered as an SVG image.
|
||||||
*/
|
*/
|
||||||
public String getBackupQrSvg(Integer accountId) throws RpcException {
|
public String getBackupQrSvg(Integer accountId) throws RpcException {
|
||||||
return transport.callForResult(new TypeReference<String>(){}, "get_backup_qr_svg", mapper.valueToTree(accountId));
|
return transport.callForResult(new TypeReference<String>(){}, "get_backup_qr_svg", mapper.valueToTree(accountId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Renders the given text as a QR code SVG image. */
|
|
||||||
public String createQrSvg(String text) throws RpcException {
|
|
||||||
return transport.callForResult(new TypeReference<String>(){}, "create_qr_svg", mapper.valueToTree(text));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a backup from a remote provider.
|
* Gets a backup from a remote provider.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -1351,47 +1243,10 @@ public class Rpc {
|
|||||||
return transport.callForResult(new TypeReference<String>(){}, "get_connectivity_html", mapper.valueToTree(accountId));
|
return transport.callForResult(new TypeReference<String>(){}, "get_connectivity_html", mapper.valueToTree(accountId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets current location.
|
|
||||||
* <p>
|
|
||||||
* Returns true if location streaming is currently
|
|
||||||
* enabled and locations should be updated.
|
|
||||||
* <p>
|
|
||||||
* Location is represented as latitude and longitude in degrees
|
|
||||||
* and horizontal accuracy in meters.
|
|
||||||
*/
|
|
||||||
public Boolean setLocation(Float latitude, Float longitude, Float accuracy) throws RpcException {
|
|
||||||
return transport.callForResult(new TypeReference<Boolean>(){}, "set_location", mapper.valueToTree(latitude), mapper.valueToTree(longitude), mapper.valueToTree(accuracy));
|
|
||||||
}
|
|
||||||
|
|
||||||
public java.util.List<Location> getLocations(Integer accountId, Integer chatId, Integer contactId, Integer timestampBegin, Integer timestampEnd) throws RpcException {
|
public java.util.List<Location> getLocations(Integer accountId, Integer chatId, Integer contactId, Integer timestampBegin, Integer timestampEnd) throws RpcException {
|
||||||
return transport.callForResult(new TypeReference<java.util.List<Location>>(){}, "get_locations", mapper.valueToTree(accountId), mapper.valueToTree(chatId), mapper.valueToTree(contactId), mapper.valueToTree(timestampBegin), mapper.valueToTree(timestampEnd));
|
return transport.callForResult(new TypeReference<java.util.List<Location>>(){}, "get_locations", mapper.valueToTree(accountId), mapper.valueToTree(chatId), mapper.valueToTree(contactId), mapper.valueToTree(timestampBegin), mapper.valueToTree(timestampEnd));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables location streaming in chat identified by `chat_id` for `seconds` seconds.
|
|
||||||
* <p>
|
|
||||||
* Pass 0 as the number of seconds to disable location streaming in the chat.
|
|
||||||
*/
|
|
||||||
public void sendLocationsToChat(Integer accountId, Integer chatId, Integer seconds) throws RpcException {
|
|
||||||
transport.call("send_locations_to_chat", mapper.valueToTree(accountId), mapper.valueToTree(chatId), mapper.valueToTree(seconds));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns whether any chat is sending locations. */
|
|
||||||
public Boolean isSendingLocations(Integer accountId) throws RpcException {
|
|
||||||
return transport.callForResult(new TypeReference<Boolean>(){}, "is_sending_locations", mapper.valueToTree(accountId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns whether `chat_id` is sending locations. */
|
|
||||||
public Boolean isSendingLocationsToChat(Integer accountId, Integer chatId) throws RpcException {
|
|
||||||
return transport.callForResult(new TypeReference<Boolean>(){}, "is_sending_locations_to_chat", mapper.valueToTree(accountId), mapper.valueToTree(chatId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Stops sending locations to all chats. */
|
|
||||||
public void stopSendingLocations() throws RpcException {
|
|
||||||
transport.call("stop_sending_locations");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendWebxdcStatusUpdate(Integer accountId, Integer instanceMsgId, String updateStr, String descr) throws RpcException {
|
public void sendWebxdcStatusUpdate(Integer accountId, Integer instanceMsgId, String updateStr, String descr) throws RpcException {
|
||||||
transport.call("send_webxdc_status_update", mapper.valueToTree(accountId), mapper.valueToTree(instanceMsgId), mapper.valueToTree(updateStr), mapper.valueToTree(descr));
|
transport.call("send_webxdc_status_update", mapper.valueToTree(accountId), mapper.valueToTree(instanceMsgId), mapper.valueToTree(updateStr), mapper.valueToTree(descr));
|
||||||
}
|
}
|
||||||
@@ -1460,8 +1315,8 @@ public class Rpc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Starts an outgoing call. */
|
/** Starts an outgoing call. */
|
||||||
public Integer placeOutgoingCall(Integer accountId, Integer chatId, String placeCallInfo, Boolean hasVideo) throws RpcException {
|
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), mapper.valueToTree(hasVideo));
|
return transport.callForResult(new TypeReference<Integer>(){}, "place_outgoing_call", mapper.valueToTree(accountId), mapper.valueToTree(chatId), mapper.valueToTree(placeCallInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Accepts an incoming call. */
|
/** Accepts an incoming call. */
|
||||||
@@ -1527,18 +1382,17 @@ public class Rpc {
|
|||||||
transport.call("resend_messages", mapper.valueToTree(accountId), mapper.valueToTree(messageIds));
|
transport.call("resend_messages", mapper.valueToTree(accountId), mapper.valueToTree(messageIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @deprecated as of 2026-04; use `send_msg` with `Viewtype::Sticker` instead. */
|
|
||||||
public Integer sendSticker(Integer accountId, Integer chatId, String stickerPath) throws RpcException {
|
public Integer sendSticker(Integer accountId, Integer chatId, String stickerPath) throws RpcException {
|
||||||
return transport.callForResult(new TypeReference<Integer>(){}, "send_sticker", mapper.valueToTree(accountId), mapper.valueToTree(chatId), mapper.valueToTree(stickerPath));
|
return transport.callForResult(new TypeReference<Integer>(){}, "send_sticker", mapper.valueToTree(accountId), mapper.valueToTree(chatId), mapper.valueToTree(stickerPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a reaction to message.
|
* Send a reaction to message.
|
||||||
* <p>
|
* <p>
|
||||||
* A reaction is a string that represents an emoji.
|
* Reaction is a string of emojis separated by spaces. Reaction to a
|
||||||
* You can call this function again to change the emoji;
|
* single message can be sent multiple times. The last reaction
|
||||||
* the last sent reaction overrides all previously sent reactions.
|
* received overrides all previously received reactions. It is
|
||||||
* It is possible to remove the reaction by sending an empty string.
|
* possible to remove all reactions by sending an empty string.
|
||||||
*/
|
*/
|
||||||
public Integer sendReaction(Integer accountId, Integer messageId, java.util.List<String> reaction) throws RpcException {
|
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));
|
return transport.callForResult(new TypeReference<Integer>(){}, "send_reaction", mapper.valueToTree(accountId), mapper.valueToTree(messageId), mapper.valueToTree(reaction));
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
package chat.delta.rpc.types;
|
package chat.delta.rpc.types;
|
||||||
|
|
||||||
public class CallInfo {
|
public class CallInfo {
|
||||||
/** True if the call is started as a video call. */
|
/** True if SDP offer has a video. */
|
||||||
public Boolean hasVideo;
|
public Boolean hasVideo;
|
||||||
/**
|
/**
|
||||||
* SDP offer.
|
* SDP offer.
|
||||||
|
|||||||
@@ -12,13 +12,6 @@ public class EnteredLoginParam {
|
|||||||
/** TLS options: whether to allow invalid certificates and/or invalid hostnames. Default: Automatic */
|
/** 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)
|
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||||
public EnteredCertificateChecks certificateChecks;
|
public EnteredCertificateChecks certificateChecks;
|
||||||
/**
|
|
||||||
* IMAP server folder.
|
|
||||||
* <p>
|
|
||||||
* Defaults to "INBOX" if not set. Should not be an empty string.
|
|
||||||
*/
|
|
||||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
|
||||||
public String imapFolder;
|
|
||||||
/** Imap server port. */
|
/** Imap server port. */
|
||||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||||
public Integer imapPort;
|
public Integer imapPort;
|
||||||
|
|||||||
@@ -387,8 +387,6 @@ public abstract class EventType {
|
|||||||
public static class IncomingCallAccepted extends EventType {
|
public static class IncomingCallAccepted extends EventType {
|
||||||
/** ID of the chat which the message belongs to. */
|
/** ID of the chat which the message belongs to. */
|
||||||
public Integer chat_id;
|
public Integer chat_id;
|
||||||
/** The call was accepted from this device (process). */
|
|
||||||
public Boolean from_this_device;
|
|
||||||
/** ID of the info message referring to the call. */
|
/** ID of the info message referring to the call. */
|
||||||
public Integer msg_id;
|
public Integer msg_id;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public class Message {
|
|||||||
public Boolean isEdited;
|
public Boolean isEdited;
|
||||||
public Boolean isForwarded;
|
public Boolean isForwarded;
|
||||||
public Boolean isInfo;
|
public Boolean isInfo;
|
||||||
|
public Boolean isSetupmessage;
|
||||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||||
public Integer originalMsgId;
|
public Integer originalMsgId;
|
||||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||||
@@ -46,6 +47,8 @@ public class Message {
|
|||||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||||
public Integer savedMessageId;
|
public Integer savedMessageId;
|
||||||
public Contact sender;
|
public Contact sender;
|
||||||
|
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||||
|
public String setupCodeBegin;
|
||||||
/**
|
/**
|
||||||
* True if the message was correctly encrypted&signed, false otherwise. Historically, UIs showed a small padlock on the message then.
|
* True if the message was correctly encrypted&signed, false otherwise. Historically, UIs showed a small padlock on the message then.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public abstract class MessageLoadResult {
|
|||||||
public Boolean isEdited;
|
public Boolean isEdited;
|
||||||
public Boolean isForwarded;
|
public Boolean isForwarded;
|
||||||
public Boolean isInfo;
|
public Boolean isInfo;
|
||||||
|
public Boolean isSetupmessage;
|
||||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||||
public Integer originalMsgId;
|
public Integer originalMsgId;
|
||||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||||
@@ -56,6 +57,8 @@ public abstract class MessageLoadResult {
|
|||||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||||
public Integer savedMessageId;
|
public Integer savedMessageId;
|
||||||
public Contact sender;
|
public Contact sender;
|
||||||
|
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||||
|
public String setupCodeBegin;
|
||||||
/**
|
/**
|
||||||
* True if the message was correctly encrypted&signed, false otherwise. Historically, UIs showed a small padlock on the message then.
|
* True if the message was correctly encrypted&signed, false otherwise. Historically, UIs showed a small padlock on the message then.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ public abstract class Qr {
|
|||||||
public String fingerprint;
|
public String fingerprint;
|
||||||
/** Invite number. */
|
/** Invite number. */
|
||||||
public String invitenumber;
|
public String invitenumber;
|
||||||
/** Whether the inviter supports the new Securejoin v3 protocol */
|
|
||||||
public Boolean is_v3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ask the user whether to join the group. */
|
/** Ask the user whether to join the group. */
|
||||||
@@ -43,8 +41,6 @@ public abstract class Qr {
|
|||||||
public String grpname;
|
public String grpname;
|
||||||
/** Invite number. */
|
/** Invite number. */
|
||||||
public String invitenumber;
|
public String invitenumber;
|
||||||
/** Whether the inviter supports the new Securejoin v3 protocol */
|
|
||||||
public Boolean is_v3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ask the user whether to join the broadcast channel. */
|
/** Ask the user whether to join the broadcast channel. */
|
||||||
@@ -59,8 +55,6 @@ public abstract class Qr {
|
|||||||
public String grpid;
|
public String grpid;
|
||||||
/** Invite number. */
|
/** Invite number. */
|
||||||
public String invitenumber;
|
public String invitenumber;
|
||||||
/** Whether the inviter supports the new Securejoin v3 protocol */
|
|
||||||
public Boolean is_v3;
|
|
||||||
/** The user-visible name of this broadcast channel */
|
/** The user-visible name of this broadcast channel */
|
||||||
public String name;
|
public String name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ package chat.delta.rpc.types;
|
|||||||
public class Reactions {
|
public class Reactions {
|
||||||
/** Unique reactions and their count, sorted in descending order. */
|
/** Unique reactions and their count, sorted in descending order. */
|
||||||
public java.util.List<Reaction> reactions;
|
public java.util.List<Reaction> reactions;
|
||||||
/** Map from a contact to it's reaction to message. There is only a single reaction per contact, but this contains a list of reactions for historical reasons. */
|
/** Map from a contact to it's reaction to message. */
|
||||||
public java.util.Map<String, java.util.List<String>> reactionsByContact;
|
public java.util.Map<String, java.util.List<String>> reactionsByContact;
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,6 @@ package chat.delta.rpc.types;
|
|||||||
public enum SystemMessageType {
|
public enum SystemMessageType {
|
||||||
Unknown,
|
Unknown,
|
||||||
GroupNameChanged,
|
GroupNameChanged,
|
||||||
GroupDescriptionChanged,
|
|
||||||
GroupImageChanged,
|
GroupImageChanged,
|
||||||
MemberAddedToGroup,
|
MemberAddedToGroup,
|
||||||
MemberRemovedFromGroup,
|
MemberRemovedFromGroup,
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
/* Autogenerated file, do not edit manually */
|
|
||||||
package chat.delta.rpc.types;
|
|
||||||
|
|
||||||
public class TransportListEntry {
|
|
||||||
/** Whether this transport is set to 'unpublished'. See `set_transport_unpublished` / `setTransportUnpublished` for details. */
|
|
||||||
public Boolean isUnpublished;
|
|
||||||
/** The login data entered by the user. */
|
|
||||||
public EnteredLoginParam param;
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,7 @@ public enum Viewtype {
|
|||||||
Gif,
|
Gif,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message containing a sticker, similar to image.
|
* Message containing a sticker, similar to image. NB: When sending, the message viewtype may be changed to `Image` by some heuristics like checking for transparent pixels. Use `Message::force_sticker()` to disable them.
|
||||||
* <p>
|
* <p>
|
||||||
* If possible, the ui should display the image without borders in a transparent way. A click on a sticker will offer to install the sticker set in some future.
|
* If possible, the ui should display the image without borders in a transparent way. A click on a sticker will offer to install the sticker set in some future.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
package chat.delta.rpc.types;
|
package chat.delta.rpc.types;
|
||||||
|
|
||||||
public class WebxdcMessageInfo {
|
public class WebxdcMessageInfo {
|
||||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
|
||||||
public String orientation;
|
|
||||||
/** if the Webxdc represents a document, then this is the name of the document */
|
/** if the Webxdc represents a document, then this is the name of the document */
|
||||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||||
public String document;
|
public String document;
|
||||||
@@ -17,10 +15,6 @@ public class WebxdcMessageInfo {
|
|||||||
public String icon;
|
public String icon;
|
||||||
/** True if full internet access should be granted to the app. */
|
/** True if full internet access should be granted to the app. */
|
||||||
public Boolean internetAccess;
|
public Boolean internetAccess;
|
||||||
/** Define if the local user is the one who initially shared the webxdc application in the chat. */
|
|
||||||
public Boolean isAppSender;
|
|
||||||
/** Define if the app runs in a broadcasting context. */
|
|
||||||
public Boolean isBroadcast;
|
|
||||||
/**
|
/**
|
||||||
* The name of the app.
|
* The name of the app.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -2,92 +2,64 @@ package com.b44t.messenger;
|
|||||||
|
|
||||||
public class DcAccounts {
|
public class DcAccounts {
|
||||||
|
|
||||||
public DcAccounts(String dir, DcEventChannel channel) {
|
public DcAccounts(String dir) {
|
||||||
accountsCPtr = createAccountsCPtr(dir, channel);
|
accountsCPtr = createAccountsCPtr(dir);
|
||||||
if (accountsCPtr == 0) throw new RuntimeException("createAccountsCPtr() returned null pointer");
|
if (accountsCPtr == 0) throw new RuntimeException("createAccountsCPtr() returned null pointer");
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
unref();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unref() {
|
|
||||||
if (accountsCPtr != 0) {
|
|
||||||
unrefAccountsCPtr();
|
|
||||||
accountsCPtr = 0;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public DcEventEmitter getEventEmitter() {
|
@Override
|
||||||
return new DcEventEmitter(getEventEmitterCPtr());
|
protected void finalize() throws Throwable {
|
||||||
}
|
super.finalize();
|
||||||
|
unref();
|
||||||
public DcJsonrpcInstance getJsonrpcInstance() {
|
|
||||||
return new DcJsonrpcInstance(getJsonrpcInstanceCPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startIo() {
|
|
||||||
for (int accountId : getAll()) {
|
|
||||||
DcContext acc = getAccount(accountId);
|
|
||||||
if (acc.isEnabled()) {
|
|
||||||
acc.startIo();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
public native void startIo2();
|
public void unref() {
|
||||||
|
if (accountsCPtr != 0) {
|
||||||
public native void stopIo();
|
unrefAccountsCPtr();
|
||||||
|
accountsCPtr = 0;
|
||||||
public native void maybeNetwork();
|
}
|
||||||
|
}
|
||||||
public native void setPushDeviceToken(String token);
|
|
||||||
|
public DcEventEmitter getEventEmitter () { return new DcEventEmitter(getEventEmitterCPtr()); }
|
||||||
public native boolean backgroundFetch(int timeoutSeconds);
|
public DcJsonrpcInstance getJsonrpcInstance () { return new DcJsonrpcInstance(getJsonrpcInstanceCPtr()); }
|
||||||
|
public void startIo () {
|
||||||
public native void stopBackgroundFetch();
|
for (int accountId : getAll()) {
|
||||||
|
DcContext acc = getAccount(accountId);
|
||||||
public native int migrateAccount(String dbfile);
|
if (acc.isEnabled()) {
|
||||||
|
acc.startIo();
|
||||||
public native boolean removeAccount(int accountId);
|
}
|
||||||
|
}
|
||||||
public native int[] getAll();
|
};
|
||||||
|
public native void startIo2 ();
|
||||||
public DcContext getAccount(int accountId) {
|
public native void stopIo ();
|
||||||
return new DcContext(getAccountCPtr(accountId));
|
public native void maybeNetwork ();
|
||||||
}
|
public native void setPushDeviceToken (String token);
|
||||||
|
public native boolean backgroundFetch (int timeoutSeconds);
|
||||||
public DcContext getSelectedAccount() {
|
public native void stopBackgroundFetch ();
|
||||||
return new DcContext(getSelectedAccountCPtr());
|
|
||||||
}
|
public native int migrateAccount (String dbfile);
|
||||||
|
public native boolean removeAccount (int accountId);
|
||||||
public native boolean selectAccount(int accountId);
|
public native int[] getAll ();
|
||||||
|
public DcContext getAccount (int accountId) { return new DcContext(getAccountCPtr(accountId)); }
|
||||||
// working with raw c-data
|
public DcContext getSelectedAccount () { return new DcContext(getSelectedAccountCPtr()); }
|
||||||
private long accountsCPtr; // CAVE: the name is referenced in the JNI
|
public native boolean selectAccount (int accountId);
|
||||||
|
|
||||||
private native long createAccountsCPtr(String dir, DcEventChannel channel);
|
// working with raw c-data
|
||||||
|
private long accountsCPtr; // CAVE: the name is referenced in the JNI
|
||||||
private native void unrefAccountsCPtr();
|
private native long createAccountsCPtr (String dir);
|
||||||
|
private native void unrefAccountsCPtr ();
|
||||||
private native long getEventEmitterCPtr();
|
private native long getEventEmitterCPtr ();
|
||||||
|
private native long getJsonrpcInstanceCPtr ();
|
||||||
private native long getJsonrpcInstanceCPtr();
|
private native long getAccountCPtr (int accountId);
|
||||||
|
private native long getSelectedAccountCPtr ();
|
||||||
private native long getAccountCPtr(int accountId);
|
|
||||||
|
public boolean isAllChatmail() {
|
||||||
private native long getSelectedAccountCPtr();
|
for (int accountId : getAll()) {
|
||||||
|
DcContext dcContext = getAccount(accountId);
|
||||||
public boolean isAllChatmail() {
|
if (!dcContext.isChatmail()) {
|
||||||
for (int accountId : getAll()) {
|
return false;
|
||||||
DcContext dcContext = getAccount(accountId);
|
}
|
||||||
if (dcContext.getConfigInt("is_chatmail") == 0) {
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,35 +2,31 @@ package com.b44t.messenger;
|
|||||||
|
|
||||||
public class DcBackupProvider {
|
public class DcBackupProvider {
|
||||||
|
|
||||||
public DcBackupProvider(long backupProviderCPtr) {
|
public DcBackupProvider(long backupProviderCPtr) {
|
||||||
this.backupProviderCPtr = backupProviderCPtr;
|
this.backupProviderCPtr = backupProviderCPtr;
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOk() {
|
|
||||||
return backupProviderCPtr != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
unref();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unref() {
|
|
||||||
if (backupProviderCPtr != 0) {
|
|
||||||
unrefBackupProviderCPtr();
|
|
||||||
backupProviderCPtr = 0;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public native String getQr();
|
public boolean isOk() {
|
||||||
|
return backupProviderCPtr != 0;
|
||||||
|
}
|
||||||
|
|
||||||
public native String getQrSvg();
|
@Override protected void finalize() throws Throwable {
|
||||||
|
super.finalize();
|
||||||
|
unref();
|
||||||
|
}
|
||||||
|
|
||||||
public native void waitForReceiver();
|
public void unref() {
|
||||||
|
if (backupProviderCPtr != 0) {
|
||||||
|
unrefBackupProviderCPtr();
|
||||||
|
backupProviderCPtr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// working with raw c-data
|
public native String getQr ();
|
||||||
private long backupProviderCPtr; // CAVE: the name is referenced in the JNI
|
public native String getQrSvg ();
|
||||||
|
public native void waitForReceiver ();
|
||||||
|
|
||||||
private native void unrefBackupProviderCPtr();
|
// working with raw c-data
|
||||||
|
private long backupProviderCPtr; // CAVE: the name is referenced in the JNI
|
||||||
|
private native void unrefBackupProviderCPtr();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,109 +1,76 @@
|
|||||||
package com.b44t.messenger;
|
package com.b44t.messenger;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
|
||||||
|
|
||||||
public class DcChat {
|
public class DcChat {
|
||||||
|
|
||||||
public static final int DC_CHAT_TYPE_UNDEFINED = 0;
|
public static final int DC_CHAT_TYPE_UNDEFINED = 0;
|
||||||
public static final int DC_CHAT_TYPE_SINGLE = 100;
|
public static final int DC_CHAT_TYPE_SINGLE = 100;
|
||||||
public static final int DC_CHAT_TYPE_GROUP = 120;
|
public static final int DC_CHAT_TYPE_GROUP = 120;
|
||||||
public static final int DC_CHAT_TYPE_MAILINGLIST = 140;
|
public static final int DC_CHAT_TYPE_MAILINGLIST = 140;
|
||||||
public static final int DC_CHAT_TYPE_OUT_BROADCAST = 160;
|
public static final int DC_CHAT_TYPE_OUT_BROADCAST = 160;
|
||||||
public static final int DC_CHAT_TYPE_IN_BROADCAST = 165;
|
public static final int DC_CHAT_TYPE_IN_BROADCAST = 165;
|
||||||
|
|
||||||
public static final int DC_CHAT_NO_CHAT = 0;
|
public static final int DC_CHAT_NO_CHAT = 0;
|
||||||
public static final int DC_CHAT_ID_ARCHIVED_LINK = 6;
|
public final static int DC_CHAT_ID_ARCHIVED_LINK = 6;
|
||||||
public static final int DC_CHAT_ID_ALLDONE_HINT = 7;
|
public final static int DC_CHAT_ID_ALLDONE_HINT = 7;
|
||||||
public static final int DC_CHAT_ID_LAST_SPECIAL = 9;
|
public final static int DC_CHAT_ID_LAST_SPECIAL = 9;
|
||||||
|
|
||||||
public static final int DC_CHAT_VISIBILITY_NORMAL = 0;
|
public final static int DC_CHAT_VISIBILITY_NORMAL = 0;
|
||||||
public static final int DC_CHAT_VISIBILITY_ARCHIVED = 1;
|
public final static int DC_CHAT_VISIBILITY_ARCHIVED = 1;
|
||||||
public static final int DC_CHAT_VISIBILITY_PINNED = 2;
|
public final static int DC_CHAT_VISIBILITY_PINNED = 2;
|
||||||
|
|
||||||
private int accountId;
|
private int accountId;
|
||||||
|
|
||||||
public DcChat(int accountId, long chatCPtr) {
|
public DcChat(int accountId, long chatCPtr) {
|
||||||
this.accountId = accountId;
|
this.accountId = accountId;
|
||||||
this.chatCPtr = chatCPtr;
|
this.chatCPtr = chatCPtr;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
unrefChatCPtr();
|
|
||||||
chatCPtr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAccountId() {
|
|
||||||
return accountId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public native int getId();
|
|
||||||
|
|
||||||
public native int getType();
|
|
||||||
|
|
||||||
public native int getVisibility();
|
|
||||||
|
|
||||||
public native String getName();
|
|
||||||
|
|
||||||
public native String getMailinglistAddr();
|
|
||||||
|
|
||||||
public native String getProfileImage();
|
|
||||||
|
|
||||||
public native int getColor();
|
|
||||||
|
|
||||||
public native boolean isEncrypted();
|
|
||||||
|
|
||||||
public native boolean isUnpromoted();
|
|
||||||
|
|
||||||
public native boolean isSelfTalk();
|
|
||||||
|
|
||||||
public native boolean isDeviceTalk();
|
|
||||||
|
|
||||||
public native boolean canSend();
|
|
||||||
|
|
||||||
public native boolean isSendingLocations();
|
|
||||||
|
|
||||||
public native boolean isMuted();
|
|
||||||
|
|
||||||
public native boolean isContactRequest();
|
|
||||||
|
|
||||||
// aliases and higher-level tools
|
|
||||||
|
|
||||||
public boolean isMultiUser() {
|
|
||||||
int type = getType();
|
|
||||||
return type != DC_CHAT_TYPE_SINGLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shallLeaveBeforeDelete(DcContext dcContext) {
|
|
||||||
if (isInBroadcast()) {
|
|
||||||
final int[] members = dcContext.getChatContacts(getId());
|
|
||||||
return Util.contains(members, DcContact.DC_CONTACT_ID_SELF);
|
|
||||||
} else if (isMultiUser() && isEncrypted() && canSend() && !isOutBroadcast()) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMailingList() {
|
@Override protected void finalize() throws Throwable {
|
||||||
return getType() == DC_CHAT_TYPE_MAILINGLIST;
|
super.finalize();
|
||||||
}
|
unrefChatCPtr();
|
||||||
|
chatCPtr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isInBroadcast() {
|
public int getAccountId () { return accountId; }
|
||||||
return getType() == DC_CHAT_TYPE_IN_BROADCAST;
|
public native int getId ();
|
||||||
}
|
public native int getType ();
|
||||||
|
public native int getVisibility ();
|
||||||
|
public native String getName ();
|
||||||
|
public native String getMailinglistAddr();
|
||||||
|
public native String getProfileImage ();
|
||||||
|
public native int getColor ();
|
||||||
|
public native boolean isEncrypted ();
|
||||||
|
public native boolean isUnpromoted ();
|
||||||
|
public native boolean isSelfTalk ();
|
||||||
|
public native boolean isDeviceTalk ();
|
||||||
|
public native boolean canSend ();
|
||||||
|
public native boolean isSendingLocations();
|
||||||
|
public native boolean isMuted ();
|
||||||
|
public native boolean isContactRequest ();
|
||||||
|
|
||||||
public boolean isOutBroadcast() {
|
|
||||||
return getType() == DC_CHAT_TYPE_OUT_BROADCAST;
|
|
||||||
}
|
|
||||||
|
|
||||||
// working with raw c-data
|
// aliases and higher-level tools
|
||||||
|
|
||||||
private long chatCPtr; // CAVE: the name is referenced in the JNI
|
public boolean isMultiUser() {
|
||||||
|
int type = getType();
|
||||||
|
return type != DC_CHAT_TYPE_SINGLE;
|
||||||
|
}
|
||||||
|
|
||||||
private native void unrefChatCPtr();
|
public boolean isMailingList() {
|
||||||
|
return getType() == DC_CHAT_TYPE_MAILINGLIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInBroadcast() {
|
||||||
|
return getType() == DC_CHAT_TYPE_IN_BROADCAST;
|
||||||
|
}
|
||||||
|
public boolean isOutBroadcast() {
|
||||||
|
return getType() == DC_CHAT_TYPE_OUT_BROADCAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// working with raw c-data
|
||||||
|
|
||||||
|
private long chatCPtr; // CAVE: the name is referenced in the JNI
|
||||||
|
private native void unrefChatCPtr();
|
||||||
|
public long getChatCPtr () { return chatCPtr; }
|
||||||
|
|
||||||
public long getChatCPtr() {
|
|
||||||
return chatCPtr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,64 +2,45 @@ package com.b44t.messenger;
|
|||||||
|
|
||||||
public class DcChatlist {
|
public class DcChatlist {
|
||||||
|
|
||||||
private int accountId;
|
private int accountId;
|
||||||
|
|
||||||
public DcChatlist(int accountId, long chatlistCPtr) {
|
public DcChatlist(int accountId, long chatlistCPtr) {
|
||||||
this.accountId = accountId;
|
this.accountId = accountId;
|
||||||
this.chatlistCPtr = chatlistCPtr;
|
this.chatlistCPtr = chatlistCPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override protected void finalize() throws Throwable {
|
||||||
protected void finalize() throws Throwable {
|
super.finalize();
|
||||||
super.finalize();
|
unrefChatlistCPtr();
|
||||||
unrefChatlistCPtr();
|
chatlistCPtr = 0;
|
||||||
chatlistCPtr = 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public int getAccountId() {
|
public int getAccountId() { return accountId; }
|
||||||
return accountId;
|
public native int getCnt ();
|
||||||
}
|
public native int getChatId (int index);
|
||||||
|
public DcChat getChat (int index) { return new DcChat(accountId, getChatCPtr(index)); }
|
||||||
|
public native int getMsgId (int index);
|
||||||
|
public DcMsg getMsg (int index) { return new DcMsg(getMsgCPtr(index)); }
|
||||||
|
public DcLot getSummary(int index, DcChat chat) { return new DcLot(getSummaryCPtr(index, chat==null? 0 : chat.getChatCPtr())); }
|
||||||
|
|
||||||
public native int getCnt();
|
public class Item {
|
||||||
|
public DcLot summary;
|
||||||
|
public int msgId;
|
||||||
|
public int chatId;
|
||||||
|
}
|
||||||
|
|
||||||
public native int getChatId(int index);
|
public Item getItem(int index) {
|
||||||
|
Item item = new Item();
|
||||||
|
item.summary = getSummary(index, null);
|
||||||
|
item.msgId = getMsgId(index);
|
||||||
|
item.chatId = getChatId(index);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
public DcChat getChat(int index) {
|
// working with raw c-data
|
||||||
return new DcChat(accountId, getChatCPtr(index));
|
private long chatlistCPtr; // CAVE: the name is referenced in the JNI
|
||||||
}
|
private native void unrefChatlistCPtr();
|
||||||
|
private native long getChatCPtr (int index);
|
||||||
public native int getMsgId(int index);
|
private native long getMsgCPtr (int index);
|
||||||
|
private native long getSummaryCPtr (int index, long chatCPtr);
|
||||||
public DcMsg getMsg(int index) {
|
|
||||||
return new DcMsg(getMsgCPtr(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
public DcLot getSummary(int index, DcChat chat) {
|
|
||||||
return new DcLot(getSummaryCPtr(index, chat == null ? 0 : chat.getChatCPtr()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Item {
|
|
||||||
public DcLot summary;
|
|
||||||
public int msgId;
|
|
||||||
public int chatId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Item getItem(int index) {
|
|
||||||
Item item = new Item();
|
|
||||||
item.summary = getSummary(index, null);
|
|
||||||
item.msgId = getMsgId(index);
|
|
||||||
item.chatId = getChatId(index);
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
// working with raw c-data
|
|
||||||
private long chatlistCPtr; // CAVE: the name is referenced in the JNI
|
|
||||||
|
|
||||||
private native void unrefChatlistCPtr();
|
|
||||||
|
|
||||||
private native long getChatCPtr(int index);
|
|
||||||
|
|
||||||
private native long getMsgCPtr(int index);
|
|
||||||
|
|
||||||
private native long getSummaryCPtr(int index, long chatCPtr);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,82 +2,67 @@ package com.b44t.messenger;
|
|||||||
|
|
||||||
public class DcContact {
|
public class DcContact {
|
||||||
|
|
||||||
public static final int DC_CONTACT_ID_SELF = 1;
|
public final static int DC_CONTACT_ID_SELF = 1;
|
||||||
public static final int DC_CONTACT_ID_INFO = 2;
|
public final static int DC_CONTACT_ID_INFO = 2;
|
||||||
public static final int DC_CONTACT_ID_DEVICE = 5;
|
public final static int DC_CONTACT_ID_DEVICE = 5;
|
||||||
public static final int DC_CONTACT_ID_LAST_SPECIAL = 9;
|
public final static int DC_CONTACT_ID_LAST_SPECIAL = 9;
|
||||||
public static final int DC_CONTACT_ID_NEW_CLASSIC_CONTACT =
|
public final static int DC_CONTACT_ID_NEW_CLASSIC_CONTACT= -1; // used by the UI, not valid to the core
|
||||||
-1; // used by the UI, not valid to the core
|
public final static int DC_CONTACT_ID_NEW_GROUP = -2; // - " -
|
||||||
public static final int DC_CONTACT_ID_NEW_GROUP = -2; // - " -
|
public final static int DC_CONTACT_ID_ADD_MEMBER = -3; // - " -
|
||||||
public static final int DC_CONTACT_ID_ADD_MEMBER = -3; // - " -
|
public final static int DC_CONTACT_ID_QR_INVITE = -4; // - " -
|
||||||
public static final int DC_CONTACT_ID_QR_INVITE = -4; // - " -
|
public final static int DC_CONTACT_ID_NEW_BROADCAST = -5; // - " -
|
||||||
public static final int DC_CONTACT_ID_NEW_BROADCAST = -5; // - " -
|
public final static int DC_CONTACT_ID_ADD_ACCOUNT = -6; // - " -
|
||||||
public static final int DC_CONTACT_ID_ADD_ACCOUNT = -6; // - " -
|
public final static int DC_CONTACT_ID_NEW_UNENCRYPTED_GROUP = -7; // - " -
|
||||||
public static final int DC_CONTACT_ID_NEW_UNENCRYPTED_GROUP = -7; // - " -
|
|
||||||
|
|
||||||
public DcContact(long contactCPtr) {
|
public DcContact(long contactCPtr) {
|
||||||
this.contactCPtr = contactCPtr;
|
this.contactCPtr = contactCPtr;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
unrefContactCPtr();
|
|
||||||
contactCPtr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (other == null || !(other instanceof DcContact)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DcContact that = (DcContact) other;
|
@Override
|
||||||
return this.getId() == that.getId();
|
protected void finalize() throws Throwable {
|
||||||
}
|
super.finalize();
|
||||||
|
unrefContactCPtr();
|
||||||
|
contactCPtr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return this.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public boolean equals(Object other) {
|
||||||
return getAddr();
|
if (other == null || !(other instanceof DcContact)) {
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public native int getId();
|
DcContact that = (DcContact) other;
|
||||||
|
return this.getId()==that.getId();
|
||||||
|
}
|
||||||
|
|
||||||
public native String getName();
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.getId();
|
||||||
|
}
|
||||||
|
|
||||||
public native String getAuthName();
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getAddr();
|
||||||
|
}
|
||||||
|
|
||||||
public native String getDisplayName();
|
public native int getId ();
|
||||||
|
public native String getName ();
|
||||||
|
public native String getAuthName ();
|
||||||
|
public native String getDisplayName ();
|
||||||
|
public native String getAddr ();
|
||||||
|
public native String getProfileImage();
|
||||||
|
public native int getColor ();
|
||||||
|
public native String getStatus ();
|
||||||
|
public native long getLastSeen ();
|
||||||
|
public native boolean wasSeenRecently();
|
||||||
|
public native boolean isBlocked ();
|
||||||
|
public native boolean isVerified ();
|
||||||
|
public native boolean isKeyContact ();
|
||||||
|
public native int getVerifierId ();
|
||||||
|
public native boolean isBot ();
|
||||||
|
|
||||||
public native String getAddr();
|
// working with raw c-data
|
||||||
|
private long contactCPtr; // CAVE: the name is referenced in the JNI
|
||||||
public native String getProfileImage();
|
private native void unrefContactCPtr();
|
||||||
|
|
||||||
public native int getColor();
|
|
||||||
|
|
||||||
public native String getStatus();
|
|
||||||
|
|
||||||
public native long getLastSeen();
|
|
||||||
|
|
||||||
public native boolean wasSeenRecently();
|
|
||||||
|
|
||||||
public native boolean isBlocked();
|
|
||||||
|
|
||||||
public native boolean isVerified();
|
|
||||||
|
|
||||||
public native boolean isKeyContact();
|
|
||||||
|
|
||||||
public native int getVerifierId();
|
|
||||||
|
|
||||||
public native boolean isBot();
|
|
||||||
|
|
||||||
// working with raw c-data
|
|
||||||
private long contactCPtr; // CAVE: the name is referenced in the JNI
|
|
||||||
|
|
||||||
private native void unrefContactCPtr();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,409 +2,288 @@ package com.b44t.messenger;
|
|||||||
|
|
||||||
public class DcContext {
|
public class DcContext {
|
||||||
|
|
||||||
public static final int DC_EVENT_INFO = 100;
|
public final static int DC_EVENT_INFO = 100;
|
||||||
public static final int DC_EVENT_WARNING = 300;
|
public final static int DC_EVENT_WARNING = 300;
|
||||||
public static final int DC_EVENT_ERROR = 400;
|
public final static int DC_EVENT_ERROR = 400;
|
||||||
public static final int DC_EVENT_ERROR_SELF_NOT_IN_GROUP = 410;
|
public final static int DC_EVENT_ERROR_SELF_NOT_IN_GROUP = 410;
|
||||||
public static final int DC_EVENT_MSGS_CHANGED = 2000;
|
public final static int DC_EVENT_MSGS_CHANGED = 2000;
|
||||||
public static final int DC_EVENT_REACTIONS_CHANGED = 2001;
|
public final static int DC_EVENT_REACTIONS_CHANGED = 2001;
|
||||||
public static final int DC_EVENT_INCOMING_REACTION = 2002;
|
public final static int DC_EVENT_INCOMING_REACTION = 2002;
|
||||||
public static final int DC_EVENT_INCOMING_WEBXDC_NOTIFY = 2003;
|
public final static int DC_EVENT_INCOMING_WEBXDC_NOTIFY = 2003;
|
||||||
public static final int DC_EVENT_INCOMING_MSG = 2005;
|
public final static int DC_EVENT_INCOMING_MSG = 2005;
|
||||||
public static final int DC_EVENT_MSGS_NOTICED = 2008;
|
public final static int DC_EVENT_MSGS_NOTICED = 2008;
|
||||||
public static final int DC_EVENT_MSG_DELIVERED = 2010;
|
public final static int DC_EVENT_MSG_DELIVERED = 2010;
|
||||||
public static final int DC_EVENT_MSG_FAILED = 2012;
|
public final static int DC_EVENT_MSG_FAILED = 2012;
|
||||||
public static final int DC_EVENT_MSG_READ = 2015;
|
public final static int DC_EVENT_MSG_READ = 2015;
|
||||||
public static final int DC_EVENT_MSG_DELETED = 2016;
|
public final static int DC_EVENT_CHAT_MODIFIED = 2020;
|
||||||
public static final int DC_EVENT_CHAT_MODIFIED = 2020;
|
public final static int DC_EVENT_CHAT_EPHEMERAL_TIMER_MODIFIED = 2021;
|
||||||
public static final int DC_EVENT_CHAT_EPHEMERAL_TIMER_MODIFIED = 2021;
|
public final static int DC_EVENT_CHAT_DELETED = 2023;
|
||||||
public static final int DC_EVENT_CHAT_DELETED = 2023;
|
public final static int DC_EVENT_CONTACTS_CHANGED = 2030;
|
||||||
public static final int DC_EVENT_CONTACTS_CHANGED = 2030;
|
public final static int DC_EVENT_LOCATION_CHANGED = 2035;
|
||||||
public static final int DC_EVENT_LOCATION_CHANGED = 2035;
|
public final static int DC_EVENT_CONFIGURE_PROGRESS = 2041;
|
||||||
public static final int DC_EVENT_CONFIGURE_PROGRESS = 2041;
|
public final static int DC_EVENT_IMEX_PROGRESS = 2051;
|
||||||
public static final int DC_EVENT_IMEX_PROGRESS = 2051;
|
public final static int DC_EVENT_IMEX_FILE_WRITTEN = 2052;
|
||||||
public static final int DC_EVENT_IMEX_FILE_WRITTEN = 2052;
|
public final static int DC_EVENT_SECUREJOIN_INVITER_PROGRESS = 2060;
|
||||||
public static final int DC_EVENT_SECUREJOIN_INVITER_PROGRESS = 2060;
|
public final static int DC_EVENT_SECUREJOIN_JOINER_PROGRESS = 2061;
|
||||||
public static final int DC_EVENT_SECUREJOIN_JOINER_PROGRESS = 2061;
|
public final static int DC_EVENT_CONNECTIVITY_CHANGED = 2100;
|
||||||
public static final int DC_EVENT_CONNECTIVITY_CHANGED = 2100;
|
public final static int DC_EVENT_SELFAVATAR_CHANGED = 2110;
|
||||||
public static final int DC_EVENT_SELFAVATAR_CHANGED = 2110;
|
public final static int DC_EVENT_WEBXDC_STATUS_UPDATE = 2120;
|
||||||
public static final int DC_EVENT_WEBXDC_STATUS_UPDATE = 2120;
|
public final static int DC_EVENT_WEBXDC_INSTANCE_DELETED = 2121;
|
||||||
public static final int DC_EVENT_WEBXDC_INSTANCE_DELETED = 2121;
|
public final static int DC_EVENT_WEBXDC_REALTIME_DATA = 2150;
|
||||||
public static final int DC_EVENT_WEBXDC_REALTIME_DATA = 2150;
|
public final static int DC_EVENT_ACCOUNTS_BACKGROUND_FETCH_DONE = 2200;
|
||||||
public static final int DC_EVENT_ACCOUNTS_BACKGROUND_FETCH_DONE = 2200;
|
public final static int DC_EVENT_INCOMING_CALL = 2550;
|
||||||
public static final int DC_EVENT_INCOMING_CALL = 2550;
|
public final static int DC_EVENT_INCOMING_CALL_ACCEPTED = 2560;
|
||||||
public static final int DC_EVENT_INCOMING_CALL_ACCEPTED = 2560;
|
public final static int DC_EVENT_OUTGOING_CALL_ACCEPTED = 2570;
|
||||||
public static final int DC_EVENT_OUTGOING_CALL_ACCEPTED = 2570;
|
public final static int DC_EVENT_CALL_ENDED = 2580;
|
||||||
public static final int DC_EVENT_CALL_ENDED = 2580;
|
public final static int DC_EVENT_TRANSPORTS_MODIFIED = 2600;
|
||||||
public static final int DC_EVENT_TRANSPORTS_MODIFIED = 2600;
|
|
||||||
|
|
||||||
public static final int DC_IMEX_EXPORT_SELF_KEYS = 1;
|
public final static int DC_IMEX_EXPORT_SELF_KEYS = 1;
|
||||||
public static final int DC_IMEX_IMPORT_SELF_KEYS = 2;
|
public final static int DC_IMEX_IMPORT_SELF_KEYS = 2;
|
||||||
public static final int DC_IMEX_EXPORT_BACKUP = 11;
|
public final static int DC_IMEX_EXPORT_BACKUP = 11;
|
||||||
public static final int DC_IMEX_IMPORT_BACKUP = 12;
|
public final static int DC_IMEX_IMPORT_BACKUP = 12;
|
||||||
|
|
||||||
public static final int DC_GCL_VERIFIED_ONLY = 1;
|
public final static int DC_GCL_VERIFIED_ONLY = 1;
|
||||||
public static final int DC_GCL_ADD_SELF = 2;
|
public final static int DC_GCL_ADD_SELF = 2;
|
||||||
public static final int DC_GCL_ADDRESS = 0x04;
|
public final static int DC_GCL_ADDRESS = 0x04;
|
||||||
public static final int DC_GCL_ARCHIVED_ONLY = 0x01;
|
public final static int DC_GCL_ARCHIVED_ONLY = 0x01;
|
||||||
public static final int DC_GCL_NO_SPECIALS = 0x02;
|
public final static int DC_GCL_NO_SPECIALS = 0x02;
|
||||||
public static final int DC_GCL_ADD_ALLDONE_HINT = 0x04;
|
public final static int DC_GCL_ADD_ALLDONE_HINT = 0x04;
|
||||||
public static final int DC_GCL_FOR_FORWARDING = 0x08;
|
public final static int DC_GCL_FOR_FORWARDING = 0x08;
|
||||||
|
|
||||||
public static final int DC_GCM_ADDDAYMARKER = 0x01;
|
public final static int DC_GCM_ADDDAYMARKER = 0x01;
|
||||||
|
|
||||||
public static final int DC_QR_ASK_VERIFYCONTACT = 200;
|
public final static int DC_QR_ASK_VERIFYCONTACT = 200;
|
||||||
public static final int DC_QR_ASK_VERIFYGROUP = 202;
|
public final static int DC_QR_ASK_VERIFYGROUP = 202;
|
||||||
public static final int DC_QR_ASK_JOIN_BROADCAST = 204;
|
public final static int DC_QR_ASK_JOIN_BROADCAST= 204;
|
||||||
public static final int DC_QR_FPR_OK = 210;
|
public final static int DC_QR_FPR_OK = 210;
|
||||||
public static final int DC_QR_FPR_MISMATCH = 220;
|
public final static int DC_QR_FPR_MISMATCH = 220;
|
||||||
public static final int DC_QR_FPR_WITHOUT_ADDR = 230;
|
public final static int DC_QR_FPR_WITHOUT_ADDR = 230;
|
||||||
public static final int DC_QR_ACCOUNT = 250;
|
public final static int DC_QR_ACCOUNT = 250;
|
||||||
public static final int DC_QR_BACKUP2 = 252;
|
public final static int DC_QR_BACKUP2 = 252;
|
||||||
public static final int DC_QR_BACKUP_TOO_NEW = 255;
|
public final static int DC_QR_BACKUP_TOO_NEW = 255;
|
||||||
public static final int DC_QR_WEBRTC = 260;
|
public final static int DC_QR_WEBRTC = 260;
|
||||||
public static final int DC_QR_PROXY = 271;
|
public final static int DC_QR_PROXY = 271;
|
||||||
public static final int DC_QR_ADDR = 320;
|
public final static int DC_QR_ADDR = 320;
|
||||||
public static final int DC_QR_TEXT = 330;
|
public final static int DC_QR_TEXT = 330;
|
||||||
public static final int DC_QR_URL = 332;
|
public final static int DC_QR_URL = 332;
|
||||||
public static final int DC_QR_ERROR = 400;
|
public final static int DC_QR_ERROR = 400;
|
||||||
public static final int DC_QR_WITHDRAW_VERIFYCONTACT = 500;
|
public final static int DC_QR_WITHDRAW_VERIFYCONTACT = 500;
|
||||||
public static final int DC_QR_WITHDRAW_VERIFYGROUP = 502;
|
public final static int DC_QR_WITHDRAW_VERIFYGROUP = 502;
|
||||||
public static final int DC_QR_WITHDRAW_JOINBROADCAST = 504;
|
public final static int DC_QR_WITHDRAW_JOINBROADCAST = 504;
|
||||||
public static final int DC_QR_REVIVE_VERIFYCONTACT = 510;
|
public final static int DC_QR_REVIVE_VERIFYCONTACT = 510;
|
||||||
public static final int DC_QR_REVIVE_VERIFYGROUP = 512;
|
public final static int DC_QR_REVIVE_VERIFYGROUP = 512;
|
||||||
public static final int DC_QR_REVIVE_JOINBROADCAST = 514;
|
public final static int DC_QR_REVIVE_JOINBROADCAST = 514;
|
||||||
public static final int DC_QR_LOGIN = 520;
|
public final static int DC_QR_LOGIN = 520;
|
||||||
|
|
||||||
public static final int DC_SOCKET_AUTO = 0;
|
public final static int DC_SOCKET_AUTO = 0;
|
||||||
public static final int DC_SOCKET_SSL = 1;
|
public final static int DC_SOCKET_SSL = 1;
|
||||||
public static final int DC_SOCKET_STARTTLS = 2;
|
public final static int DC_SOCKET_STARTTLS = 2;
|
||||||
public static final int DC_SOCKET_PLAIN = 3;
|
public final static int DC_SOCKET_PLAIN = 3;
|
||||||
|
|
||||||
public static final int DC_SHOW_EMAILS_OFF = 0;
|
public final static int DC_SHOW_EMAILS_OFF = 0;
|
||||||
public static final int DC_SHOW_EMAILS_ACCEPTED_CONTACTS = 1;
|
public final static int DC_SHOW_EMAILS_ACCEPTED_CONTACTS = 1;
|
||||||
public static final int DC_SHOW_EMAILS_ALL = 2;
|
public final static int DC_SHOW_EMAILS_ALL = 2;
|
||||||
|
|
||||||
public static final int DC_MEDIA_QUALITY_BALANCED = 0;
|
public final static int DC_MEDIA_QUALITY_BALANCED = 0;
|
||||||
public static final int DC_MEDIA_QUALITY_WORSE = 1;
|
public final static int DC_MEDIA_QUALITY_WORSE = 1;
|
||||||
|
|
||||||
public static final int DC_CONNECTIVITY_NOT_CONNECTED = 1000;
|
public final static int DC_CONNECTIVITY_NOT_CONNECTED = 1000;
|
||||||
public static final int DC_CONNECTIVITY_CONNECTING = 2000;
|
public final static int DC_CONNECTIVITY_CONNECTING = 2000;
|
||||||
public static final int DC_CONNECTIVITY_WORKING = 3000;
|
public final static int DC_CONNECTIVITY_WORKING = 3000;
|
||||||
public static final int DC_CONNECTIVITY_CONNECTED = 4000;
|
public final static int DC_CONNECTIVITY_CONNECTED = 4000;
|
||||||
|
|
||||||
private static final String CONFIG_ACCOUNT_ENABLED = "ui.enabled";
|
private static final String CONFIG_ACCOUNT_ENABLED = "ui.enabled";
|
||||||
private static final String CONFIG_MUTE_MENTIONS_IF_MUTED = "ui.mute_mentions_if_muted";
|
private static final String CONFIG_MUTE_MENTIONS_IF_MUTED = "ui.mute_mentions_if_muted";
|
||||||
|
|
||||||
// when using DcAccounts, use Rpc.addAccount() instead
|
// when using DcAccounts, use Rpc.addAccount() instead
|
||||||
public DcContext(String osName, String dbfile) {
|
public DcContext(String osName, String dbfile) {
|
||||||
contextCPtr = createContextCPtr(osName, dbfile);
|
contextCPtr = createContextCPtr(osName, dbfile);
|
||||||
}
|
|
||||||
|
|
||||||
public DcContext(long contextCPtr) {
|
|
||||||
this.contextCPtr = contextCPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOk() {
|
|
||||||
return contextCPtr != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
if (contextCPtr != 0) {
|
|
||||||
unrefContextCPtr();
|
|
||||||
contextCPtr = 0;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public native int getAccountId();
|
public DcContext(long contextCPtr) {
|
||||||
|
this.contextCPtr = contextCPtr;
|
||||||
// when using DcAccounts, use DcAccounts.getEventEmitter() instead
|
|
||||||
public DcEventEmitter getEventEmitter() {
|
|
||||||
return new DcEventEmitter(getEventEmitterCPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
public native void setStockTranslation(int stockId, String translation);
|
|
||||||
|
|
||||||
public native String getBlobdir();
|
|
||||||
|
|
||||||
public native String getLastError();
|
|
||||||
|
|
||||||
public native void stopOngoingProcess();
|
|
||||||
|
|
||||||
public native int isConfigured();
|
|
||||||
|
|
||||||
public native boolean open(String passphrase);
|
|
||||||
|
|
||||||
public native boolean isOpen();
|
|
||||||
|
|
||||||
// when using DcAccounts, use DcAccounts.startIo() instead
|
|
||||||
public native void startIo();
|
|
||||||
|
|
||||||
// when using DcAccounts, use DcAccounts.stopIo() instead
|
|
||||||
public native void stopIo();
|
|
||||||
|
|
||||||
// when using DcAccounts, use DcAccounts.maybeNetwork() instead
|
|
||||||
public native void maybeNetwork();
|
|
||||||
|
|
||||||
public native void setConfig(String key, String value);
|
|
||||||
|
|
||||||
public void setConfigInt(String key, int value) {
|
|
||||||
setConfig(key, Integer.toString(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public native boolean setConfigFromQr(String qr);
|
|
||||||
|
|
||||||
public native String getConfig(String key);
|
|
||||||
|
|
||||||
public int getConfigInt(String key) {
|
|
||||||
return getConfigInt(key, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getConfigInt(String key, int defValue) {
|
|
||||||
try {
|
|
||||||
return Integer.parseInt(getConfig(key));
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
}
|
||||||
return defValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public native String getInfo();
|
public boolean isOk() {
|
||||||
|
return contextCPtr != 0;
|
||||||
public native int getConnectivity();
|
}
|
||||||
|
|
||||||
public native String getConnectivityHtml();
|
@Override
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
public native void imex(int what, String dir);
|
super.finalize();
|
||||||
|
if (contextCPtr != 0) {
|
||||||
public native String imexHasBackup(String dir);
|
unrefContextCPtr();
|
||||||
|
contextCPtr = 0;
|
||||||
public DcBackupProvider newBackupProvider() {
|
}
|
||||||
return new DcBackupProvider(newBackupProviderCPtr());
|
}
|
||||||
}
|
|
||||||
|
public native int getAccountId ();
|
||||||
public native boolean receiveBackup(String qr);
|
|
||||||
|
// when using DcAccounts, use DcAccounts.getEventEmitter() instead
|
||||||
public native boolean mayBeValidAddr(String addr);
|
public DcEventEmitter getEventEmitter () { return new DcEventEmitter(getEventEmitterCPtr()); }
|
||||||
|
|
||||||
public native int lookupContactIdByAddr(String addr);
|
public native void setStockTranslation (int stockId, String translation);
|
||||||
|
public native String getBlobdir ();
|
||||||
public native int[] getContacts(int flags, String query);
|
public native String getLastError ();
|
||||||
|
public native void stopOngoingProcess ();
|
||||||
public native int[] getBlockedContacts();
|
public native int isConfigured ();
|
||||||
|
public native boolean open (String passphrase);
|
||||||
public DcContact getContact(int contact_id) {
|
public native boolean isOpen ();
|
||||||
return new DcContact(getContactCPtr(contact_id));
|
|
||||||
}
|
// when using DcAccounts, use DcAccounts.startIo() instead
|
||||||
|
public native void startIo ();
|
||||||
public native int createContact(String name, String addr);
|
|
||||||
|
// when using DcAccounts, use DcAccounts.stopIo() instead
|
||||||
public native void blockContact(int id, int block);
|
public native void stopIo ();
|
||||||
|
|
||||||
public native String getContactEncrInfo(int contact_id);
|
// when using DcAccounts, use DcAccounts.maybeNetwork() instead
|
||||||
|
public native void maybeNetwork ();
|
||||||
public native boolean deleteContact(int id);
|
|
||||||
|
public native void setConfig (String key, String value);
|
||||||
public native int addAddressBook(String adrbook);
|
public void setConfigInt (String key, int value) { setConfig(key, Integer.toString(value)); }
|
||||||
|
public native boolean setConfigFromQr (String qr);
|
||||||
public DcChatlist getChatlist(int listflags, String query, int queryId) {
|
public native String getConfig (String key);
|
||||||
return new DcChatlist(getAccountId(), getChatlistCPtr(listflags, query, queryId));
|
public int getConfigInt (String key) { return getConfigInt(key, 0); }
|
||||||
}
|
public int getConfigInt (String key, int defValue) { try{return Integer.parseInt(getConfig(key));} catch(Exception e) {} return defValue; }
|
||||||
|
public native String getInfo ();
|
||||||
public DcChat getChat(int chat_id) {
|
public native int getConnectivity ();
|
||||||
return new DcChat(getAccountId(), getChatCPtr(chat_id));
|
public native String getConnectivityHtml ();
|
||||||
}
|
public native String initiateKeyTransfer ();
|
||||||
|
public native void imex (int what, String dir);
|
||||||
public native String getChatEncrInfo(int chat_id);
|
public native String imexHasBackup (String dir);
|
||||||
|
public DcBackupProvider newBackupProvider () { return new DcBackupProvider(newBackupProviderCPtr()); }
|
||||||
public native void markseenMsgs(int msg_ids[]);
|
public native boolean receiveBackup (String qr);
|
||||||
|
public native boolean mayBeValidAddr (String addr);
|
||||||
public native void marknoticedChat(int chat_id);
|
public native int lookupContactIdByAddr(String addr);
|
||||||
|
public native int[] getContacts (int flags, String query);
|
||||||
public native void setChatVisibility(int chat_id, int visibility);
|
public native int[] getBlockedContacts ();
|
||||||
|
public DcContact getContact (int contact_id) { return new DcContact(getContactCPtr(contact_id)); }
|
||||||
public native int getChatIdByContactId(int contact_id);
|
public native int createContact (String name, String addr);
|
||||||
|
public native void blockContact (int id, int block);
|
||||||
public native int createChatByContactId(int contact_id);
|
public native String getContactEncrInfo (int contact_id);
|
||||||
|
public native boolean deleteContact (int id);
|
||||||
public native int createGroupChat(String name);
|
public native int addAddressBook (String adrbook);
|
||||||
|
public DcChatlist getChatlist (int listflags, String query, int queryId) { return new DcChatlist(getAccountId(), getChatlistCPtr(listflags, query, queryId)); }
|
||||||
public native int createBroadcastList();
|
public DcChat getChat (int chat_id) { return new DcChat(getAccountId(), getChatCPtr(chat_id)); }
|
||||||
|
public native String getChatEncrInfo (int chat_id);
|
||||||
public native boolean isContactInChat(int chat_id, int contact_id);
|
public native void markseenMsgs (int msg_ids[]);
|
||||||
|
public native void marknoticedChat (int chat_id);
|
||||||
public native int addContactToChat(int chat_id, int contact_id);
|
public native void setChatVisibility (int chat_id, int visibility);
|
||||||
|
public native int getChatIdByContactId (int contact_id);
|
||||||
public native int removeContactFromChat(int chat_id, int contact_id);
|
public native int createChatByContactId(int contact_id);
|
||||||
|
public native int createGroupChat (String name);
|
||||||
public native void setDraft(int chat_id, DcMsg msg /*null=delete*/);
|
public native int createBroadcastList ();
|
||||||
|
public native boolean isContactInChat (int chat_id, int contact_id);
|
||||||
public DcMsg getDraft(int chat_id) {
|
public native int addContactToChat (int chat_id, int contact_id);
|
||||||
return new DcMsg(getDraftCPtr(chat_id));
|
public native int removeContactFromChat(int chat_id, int contact_id);
|
||||||
}
|
public native void setDraft (int chat_id, DcMsg msg/*null=delete*/);
|
||||||
|
public DcMsg getDraft (int chat_id) { return new DcMsg(getDraftCPtr(chat_id)); }
|
||||||
public native int setChatName(int chat_id, String name);
|
public native int setChatName (int chat_id, String name);
|
||||||
|
public native int setChatProfileImage (int chat_id, String name);
|
||||||
public native int setChatProfileImage(int chat_id, String name);
|
public native int[] getChatMsgs (int chat_id, int flags, int marker1before);
|
||||||
|
public native int[] searchMsgs (int chat_id, String query);
|
||||||
public native int[] getChatMsgs(int chat_id, int flags, int marker1before);
|
public native int[] getFreshMsgs ();
|
||||||
|
public native int[] getChatMedia (int chat_id, int type1, int type2, int type3);
|
||||||
public native int[] searchMsgs(int chat_id, String query);
|
public native int[] getChatContacts (int chat_id);
|
||||||
|
public native int getChatEphemeralTimer (int chat_id);
|
||||||
public native int[] getFreshMsgs();
|
public native boolean setChatEphemeralTimer (int chat_id, int timer);
|
||||||
|
public native boolean setChatMuteDuration (int chat_id, long duration);
|
||||||
public native int[] getChatMedia(int chat_id, int type1, int type2, int type3);
|
public native void deleteChat (int chat_id);
|
||||||
|
public native void blockChat (int chat_id);
|
||||||
public native int[] getChatContacts(int chat_id);
|
public native void acceptChat (int chat_id);
|
||||||
|
public DcMsg getMsg (int msg_id) { return new DcMsg(getMsgCPtr(msg_id)); }
|
||||||
public native int getChatEphemeralTimer(int chat_id);
|
public native void sendEditRequest (int msg_id, String text);
|
||||||
|
public native String getMsgInfo (int id);
|
||||||
public native boolean setChatEphemeralTimer(int chat_id, int timer);
|
public native String getMsgHtml (int msg_id);
|
||||||
|
public native void downloadFullMsg (int msg_id);
|
||||||
public native boolean setChatMuteDuration(int chat_id, long duration);
|
public native int getFreshMsgCount (int chat_id);
|
||||||
|
public native int estimateDeletionCount(boolean from_server, long seconds);
|
||||||
public native void deleteChat(int chat_id);
|
public native void deleteMsgs (int msg_ids[]);
|
||||||
|
public native void sendDeleteRequest (int msg_ids[]);
|
||||||
public native void blockChat(int chat_id);
|
public native void forwardMsgs (int msg_ids[], int chat_id);
|
||||||
|
public native void saveMsgs (int msg_ids[]);
|
||||||
public native void acceptChat(int chat_id);
|
public native boolean resendMsgs (int msg_ids[]);
|
||||||
|
public native int sendMsg (int chat_id, DcMsg msg);
|
||||||
public DcMsg getMsg(int msg_id) {
|
public native int sendTextMsg (int chat_id, String text);
|
||||||
return new DcMsg(getMsgCPtr(msg_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);
|
||||||
public native void sendEditRequest(int msg_id, String text);
|
public native int initWebxdcIntegration(int chat_id);
|
||||||
|
public native int addDeviceMsg (String label, DcMsg msg);
|
||||||
public native String getMsgInfo(int id);
|
public native boolean wasDeviceMsgEverAdded(String label);
|
||||||
|
public DcLot checkQr (String qr) { return new DcLot(checkQrCPtr(qr)); }
|
||||||
public native String getMsgHtml(int msg_id);
|
public native String getSecurejoinQr (int chat_id);
|
||||||
|
public native String getSecurejoinQrSvg (int chat_id);
|
||||||
public native void downloadFullMsg(int msg_id);
|
public native String createQrSvg (String payload);
|
||||||
|
public native int joinSecurejoin (String qr);
|
||||||
public native int getFreshMsgCount(int chat_id);
|
public native void sendLocationsToChat (int chat_id, int seconds);
|
||||||
|
public native boolean isSendingLocationsToChat(int chat_id);
|
||||||
public native int estimateDeletionCount(boolean from_server, long seconds);
|
public DcProvider getProviderFromEmailWithDns (String email) { long cptr = getProviderFromEmailWithDnsCPtr(email); return cptr!=0 ? new DcProvider(cptr) : null; }
|
||||||
|
|
||||||
public native void deleteMsgs(int msg_ids[]);
|
public boolean isEnabled() {
|
||||||
|
return !"0".equals(getConfig(CONFIG_ACCOUNT_ENABLED));
|
||||||
public native void sendDeleteRequest(int msg_ids[]);
|
}
|
||||||
|
|
||||||
public native void forwardMsgs(int msg_ids[], int chat_id);
|
public void setEnabled(boolean enabled) {
|
||||||
|
setConfigInt(CONFIG_ACCOUNT_ENABLED, enabled? 1 : 0);
|
||||||
public native void saveMsgs(int msg_ids[]);
|
if (enabled) {
|
||||||
|
startIo();
|
||||||
public native boolean resendMsgs(int msg_ids[]);
|
} else {
|
||||||
|
stopIo();
|
||||||
public native int sendMsg(int chat_id, DcMsg msg);
|
}
|
||||||
|
}
|
||||||
public native int sendTextMsg(int chat_id, String text);
|
|
||||||
|
public boolean isMentionsEnabled() {
|
||||||
public native boolean sendWebxdcStatusUpdate(int msg_id, String payload);
|
return getConfigInt(CONFIG_MUTE_MENTIONS_IF_MUTED) != 1;
|
||||||
|
}
|
||||||
public native String getWebxdcStatusUpdates(int msg_id, int last_known_serial);
|
|
||||||
|
public void setMentionsEnabled(boolean enabled) {
|
||||||
public native void setWebxdcIntegration(String file);
|
setConfigInt(CONFIG_MUTE_MENTIONS_IF_MUTED, enabled? 0 : 1);
|
||||||
|
}
|
||||||
public native int initWebxdcIntegration(int chat_id);
|
|
||||||
|
public String getName() {
|
||||||
public native int addDeviceMsg(String label, DcMsg msg);
|
String displayname = getConfig("displayname");
|
||||||
|
if (displayname.isEmpty()) {
|
||||||
public native boolean wasDeviceMsgEverAdded(String label);
|
displayname = getContact(DcContact.DC_CONTACT_ID_SELF).getAddr();
|
||||||
|
}
|
||||||
public DcLot checkQr(String qr) {
|
return displayname;
|
||||||
return new DcLot(checkQrCPtr(qr));
|
}
|
||||||
}
|
|
||||||
|
public boolean isChatmail() {
|
||||||
public native String getSecurejoinQr(int chat_id);
|
return getConfigInt("is_chatmail") == 1;
|
||||||
|
}
|
||||||
public native String getSecurejoinQrSvg(int chat_id);
|
|
||||||
|
public boolean isMuted() {
|
||||||
public native String createQrSvg(String payload);
|
return getConfigInt("is_muted") == 1;
|
||||||
|
}
|
||||||
public native int joinSecurejoin(String qr);
|
|
||||||
|
public void setMuted(boolean muted) {
|
||||||
public native void sendLocationsToChat(int chat_id, int seconds);
|
setConfigInt("is_muted", muted? 1 : 0);
|
||||||
|
}
|
||||||
public native boolean isSendingLocationsToChat(int chat_id);
|
|
||||||
|
public void restartIo() {
|
||||||
public DcProvider getProviderFromEmailWithDns(String email) {
|
if (!isEnabled()) return;
|
||||||
long cptr = getProviderFromEmailWithDnsCPtr(email);
|
|
||||||
return cptr != 0 ? new DcProvider(cptr) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return !"0".equals(getConfig(CONFIG_ACCOUNT_ENABLED));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEnabled(boolean enabled) {
|
|
||||||
setConfigInt(CONFIG_ACCOUNT_ENABLED, enabled ? 1 : 0);
|
|
||||||
if (enabled) {
|
|
||||||
startIo();
|
|
||||||
} else {
|
|
||||||
stopIo();
|
stopIo();
|
||||||
|
startIo();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMentionsEnabled() {
|
/**
|
||||||
return getConfigInt(CONFIG_MUTE_MENTIONS_IF_MUTED) != 1;
|
* @return true if at least one chat has location streaming enabled
|
||||||
}
|
*/
|
||||||
|
public native boolean setLocation (float latitude, float longitude, float accuracy);
|
||||||
|
|
||||||
public void setMentionsEnabled(boolean enabled) {
|
// working with raw c-data
|
||||||
setConfigInt(CONFIG_MUTE_MENTIONS_IF_MUTED, enabled ? 0 : 1);
|
private long contextCPtr; // CAVE: the name is referenced in the JNI
|
||||||
}
|
private native long createContextCPtr(String osName, String dbfile);
|
||||||
|
private native void unrefContextCPtr ();
|
||||||
public String getName() {
|
private native long getEventEmitterCPtr();
|
||||||
String displayname = getConfig("displayname");
|
public native long createMsgCPtr (int viewtype);
|
||||||
if (displayname.isEmpty()) {
|
private native long getChatlistCPtr (int listflags, String query, int queryId);
|
||||||
displayname = getConfig("addr");
|
private native long getChatCPtr (int chat_id);
|
||||||
}
|
private native long getMsgCPtr (int id);
|
||||||
return displayname;
|
private native long getDraftCPtr (int id);
|
||||||
}
|
private native long getContactCPtr (int id);
|
||||||
|
private native long checkQrCPtr (String qr);
|
||||||
public boolean isMuted() {
|
private native long getProviderFromEmailWithDnsCPtr (String addr);
|
||||||
return getConfigInt("is_muted") == 1;
|
private native long newBackupProviderCPtr();
|
||||||
}
|
|
||||||
|
|
||||||
public void setMuted(boolean muted) {
|
|
||||||
setConfigInt("is_muted", muted ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void restartIo() {
|
|
||||||
if (!isEnabled()) return;
|
|
||||||
stopIo();
|
|
||||||
startIo();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if at least one chat has location streaming enabled
|
|
||||||
*/
|
|
||||||
public native boolean setLocation(float latitude, float longitude, float accuracy);
|
|
||||||
|
|
||||||
// working with raw c-data
|
|
||||||
private long contextCPtr; // CAVE: the name is referenced in the JNI
|
|
||||||
|
|
||||||
private native long createContextCPtr(String osName, String dbfile);
|
|
||||||
|
|
||||||
private native void unrefContextCPtr();
|
|
||||||
|
|
||||||
private native long getEventEmitterCPtr();
|
|
||||||
|
|
||||||
public native long createMsgCPtr(int viewtype);
|
|
||||||
|
|
||||||
private native long getChatlistCPtr(int listflags, String query, int queryId);
|
|
||||||
|
|
||||||
private native long getChatCPtr(int chat_id);
|
|
||||||
|
|
||||||
private native long getMsgCPtr(int id);
|
|
||||||
|
|
||||||
private native long getDraftCPtr(int id);
|
|
||||||
|
|
||||||
private native long getContactCPtr(int id);
|
|
||||||
|
|
||||||
private native long checkQrCPtr(String qr);
|
|
||||||
|
|
||||||
private native long getProviderFromEmailWithDnsCPtr(String addr);
|
|
||||||
|
|
||||||
private native long newBackupProviderCPtr();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,31 +2,24 @@ package com.b44t.messenger;
|
|||||||
|
|
||||||
public class DcEvent {
|
public class DcEvent {
|
||||||
|
|
||||||
public DcEvent(long eventCPtr) {
|
public DcEvent(long eventCPtr) {
|
||||||
this.eventCPtr = eventCPtr;
|
this.eventCPtr = eventCPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override protected void finalize() throws Throwable {
|
||||||
protected void finalize() throws Throwable {
|
super.finalize();
|
||||||
super.finalize();
|
unrefEventCPtr();
|
||||||
unrefEventCPtr();
|
eventCPtr = 0;
|
||||||
eventCPtr = 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public native int getId();
|
public native int getId ();
|
||||||
|
public native int getData1Int ();
|
||||||
|
public native int getData2Int ();
|
||||||
|
public native String getData2Str ();
|
||||||
|
public native byte[] getData2Blob();
|
||||||
|
public native int getAccountId();
|
||||||
|
|
||||||
public native int getData1Int();
|
// working with raw c-data
|
||||||
|
private long eventCPtr; // CAVE: the name is referenced in the JNI
|
||||||
public native int getData2Int();
|
private native void unrefEventCPtr();
|
||||||
|
|
||||||
public native String getData2Str();
|
|
||||||
|
|
||||||
public native byte[] getData2Blob();
|
|
||||||
|
|
||||||
public native int getAccountId();
|
|
||||||
|
|
||||||
// working with raw c-data
|
|
||||||
private long eventCPtr; // CAVE: the name is referenced in the JNI
|
|
||||||
|
|
||||||
private native void unrefEventCPtr();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
package com.b44t.messenger;
|
|
||||||
|
|
||||||
public class DcEventChannel {
|
|
||||||
|
|
||||||
public DcEventChannel() {
|
|
||||||
eventChannelCPtr = createEventChannelCPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
if (eventChannelCPtr != 0) {
|
|
||||||
unrefEventChannelCPtr();
|
|
||||||
eventChannelCPtr = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DcEventEmitter getEventEmitter() {
|
|
||||||
return new DcEventEmitter(getEventEmitterCPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
// working with raw c-data
|
|
||||||
private long eventChannelCPtr; // CAVE: the name is referenced in the JNI
|
|
||||||
|
|
||||||
private native long createEventChannelCPtr();
|
|
||||||
|
|
||||||
private native void unrefEventChannelCPtr();
|
|
||||||
|
|
||||||
private native long getEventEmitterCPtr();
|
|
||||||
}
|
|
||||||
@@ -2,26 +2,23 @@ package com.b44t.messenger;
|
|||||||
|
|
||||||
public class DcEventEmitter {
|
public class DcEventEmitter {
|
||||||
|
|
||||||
public DcEventEmitter(long eventEmitterCPtr) {
|
public DcEventEmitter(long eventEmitterCPtr) {
|
||||||
this.eventEmitterCPtr = eventEmitterCPtr;
|
this.eventEmitterCPtr = eventEmitterCPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override protected void finalize() throws Throwable {
|
||||||
protected void finalize() throws Throwable {
|
super.finalize();
|
||||||
super.finalize();
|
unrefEventEmitterCPtr();
|
||||||
unrefEventEmitterCPtr();
|
eventEmitterCPtr = 0;
|
||||||
eventEmitterCPtr = 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public DcEvent getNextEvent() {
|
public DcEvent getNextEvent () {
|
||||||
long eventCPtr = getNextEventCPtr();
|
long eventCPtr = getNextEventCPtr();
|
||||||
return eventCPtr == 0 ? null : new DcEvent(eventCPtr);
|
return eventCPtr == 0 ? null : new DcEvent(eventCPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// working with raw c-data
|
// working with raw c-data
|
||||||
private long eventEmitterCPtr; // CAVE: the name is referenced in the JNI
|
private long eventEmitterCPtr; // CAVE: the name is referenced in the JNI
|
||||||
|
private native long getNextEventCPtr ();
|
||||||
private native long getNextEventCPtr();
|
private native void unrefEventEmitterCPtr();
|
||||||
|
|
||||||
private native void unrefEventEmitterCPtr();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,23 +2,20 @@ package com.b44t.messenger;
|
|||||||
|
|
||||||
public class DcJsonrpcInstance {
|
public class DcJsonrpcInstance {
|
||||||
|
|
||||||
public DcJsonrpcInstance(long jsonrpcInstanceCPtr) {
|
public DcJsonrpcInstance(long jsonrpcInstanceCPtr) {
|
||||||
this.jsonrpcInstanceCPtr = jsonrpcInstanceCPtr;
|
this.jsonrpcInstanceCPtr = jsonrpcInstanceCPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override protected void finalize() throws Throwable {
|
||||||
protected void finalize() throws Throwable {
|
super.finalize();
|
||||||
super.finalize();
|
unrefJsonrpcInstanceCPtr();
|
||||||
unrefJsonrpcInstanceCPtr();
|
jsonrpcInstanceCPtr = 0;
|
||||||
jsonrpcInstanceCPtr = 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public native void request(String request);
|
public native void request(String request);
|
||||||
|
public native String getNextResponse();
|
||||||
|
|
||||||
public native String getNextResponse();
|
// working with raw c-data
|
||||||
|
private long jsonrpcInstanceCPtr; // CAVE: the name is referenced in the JNI
|
||||||
// working with raw c-data
|
private native void unrefJsonrpcInstanceCPtr();
|
||||||
private long jsonrpcInstanceCPtr; // CAVE: the name is referenced in the JNI
|
|
||||||
|
|
||||||
private native void unrefJsonrpcInstanceCPtr();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,35 +2,28 @@ package com.b44t.messenger;
|
|||||||
|
|
||||||
public class DcLot {
|
public class DcLot {
|
||||||
|
|
||||||
public static final int DC_TEXT1_DRAFT = 1;
|
public final static int DC_TEXT1_DRAFT = 1;
|
||||||
public static final int DC_TEXT1_USERNAME = 2;
|
public final static int DC_TEXT1_USERNAME = 2;
|
||||||
public static final int DC_TEXT1_SELF = 3;
|
public final static int DC_TEXT1_SELF = 3;
|
||||||
|
|
||||||
public DcLot(long lotCPtr) {
|
public DcLot(long lotCPtr) {
|
||||||
this.lotCPtr = lotCPtr;
|
this.lotCPtr = lotCPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override protected void finalize() throws Throwable {
|
||||||
protected void finalize() throws Throwable {
|
super.finalize();
|
||||||
super.finalize();
|
unrefLotCPtr();
|
||||||
unrefLotCPtr();
|
lotCPtr = 0;
|
||||||
lotCPtr = 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public native String getText1();
|
public native String getText1 ();
|
||||||
|
public native int getText1Meaning();
|
||||||
|
public native String getText2 ();
|
||||||
|
public native long getTimestamp ();
|
||||||
|
public native int getState ();
|
||||||
|
public native int getId ();
|
||||||
|
|
||||||
public native int getText1Meaning();
|
// working with raw c-data
|
||||||
|
private long lotCPtr; // CAVE: the name is referenced in the JNI
|
||||||
public native String getText2();
|
private native void unrefLotCPtr();
|
||||||
|
|
||||||
public native long getTimestamp();
|
|
||||||
|
|
||||||
public native int getState();
|
|
||||||
|
|
||||||
public native int getId();
|
|
||||||
|
|
||||||
// working with raw c-data
|
|
||||||
private long lotCPtr; // CAVE: the name is referenced in the JNI
|
|
||||||
|
|
||||||
private native void unrefLotCPtr();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package com.b44t.messenger;
|
package com.b44t.messenger;
|
||||||
|
|
||||||
/** Contains a list of media entries, their respective positions and ability to move through it. */
|
/**
|
||||||
|
* Contains a list of media entries, their respective positions and ability to move through it.
|
||||||
|
*/
|
||||||
public class DcMediaGalleryElement {
|
public class DcMediaGalleryElement {
|
||||||
|
|
||||||
final int[] mediaMsgs;
|
final int[] mediaMsgs;
|
||||||
int position;
|
int position;
|
||||||
final DcContext context;
|
final DcContext context;
|
||||||
|
public DcMediaGalleryElement(int[] mediaMsgs, int position, DcContext context, boolean leftIsRecent) {
|
||||||
public DcMediaGalleryElement(
|
|
||||||
int[] mediaMsgs, int position, DcContext context, boolean leftIsRecent) {
|
|
||||||
this.mediaMsgs = mediaMsgs;
|
this.mediaMsgs = mediaMsgs;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@@ -33,7 +33,7 @@ public class DcMediaGalleryElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void moveToPosition(int newPosition) {
|
public void moveToPosition(int newPosition) {
|
||||||
if (newPosition < 0 || newPosition >= mediaMsgs.length)
|
if(newPosition < 0 || newPosition >= mediaMsgs.length)
|
||||||
throw new IllegalArgumentException("can't move outside of known area.");
|
throw new IllegalArgumentException("can't move outside of known area.");
|
||||||
position = newPosition;
|
position = newPosition;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,325 +1,266 @@
|
|||||||
package com.b44t.messenger;
|
package com.b44t.messenger;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
public class DcMsg {
|
public class DcMsg {
|
||||||
|
|
||||||
public static final int DC_MSG_UNDEFINED = 0;
|
public final static int DC_MSG_UNDEFINED = 0;
|
||||||
public static final int DC_MSG_TEXT = 10;
|
public final static int DC_MSG_TEXT = 10;
|
||||||
public static final int DC_MSG_IMAGE = 20;
|
public final static int DC_MSG_IMAGE = 20;
|
||||||
public static final int DC_MSG_GIF = 21;
|
public final static int DC_MSG_GIF = 21;
|
||||||
public static final int DC_MSG_STICKER = 23;
|
public final static int DC_MSG_STICKER = 23;
|
||||||
public static final int DC_MSG_AUDIO = 40;
|
public final static int DC_MSG_AUDIO = 40;
|
||||||
public static final int DC_MSG_VOICE = 41;
|
public final static int DC_MSG_VOICE = 41;
|
||||||
public static final int DC_MSG_VIDEO = 50;
|
public final static int DC_MSG_VIDEO = 50;
|
||||||
public static final int DC_MSG_FILE = 60;
|
public final static int DC_MSG_FILE = 60;
|
||||||
public static final int DC_MSG_CALL = 71;
|
public final static int DC_MSG_CALL = 71;
|
||||||
public static final int DC_MSG_WEBXDC = 80;
|
public final static int DC_MSG_WEBXDC = 80;
|
||||||
public static final int DC_MSG_VCARD = 90;
|
public final static int DC_MSG_VCARD = 90;
|
||||||
|
|
||||||
public static final int DC_INFO_UNKNOWN = 0;
|
public final static int DC_INFO_UNKNOWN = 0;
|
||||||
public static final int DC_INFO_GROUP_NAME_CHANGED = 2;
|
public final static int DC_INFO_GROUP_NAME_CHANGED = 2;
|
||||||
public static final int DC_INFO_GROUP_IMAGE_CHANGED = 3;
|
public final static int DC_INFO_GROUP_IMAGE_CHANGED = 3;
|
||||||
public static final int DC_INFO_MEMBER_ADDED_TO_GROUP = 4;
|
public final static int DC_INFO_MEMBER_ADDED_TO_GROUP = 4;
|
||||||
public static final int DC_INFO_MEMBER_REMOVED_FROM_GROUP = 5;
|
public final static int DC_INFO_MEMBER_REMOVED_FROM_GROUP = 5;
|
||||||
public static final int DC_INFO_SECURE_JOIN_MESSAGE = 7;
|
public final static int DC_INFO_AUTOCRYPT_SETUP_MESSAGE = 6;
|
||||||
public static final int DC_INFO_LOCATIONSTREAMING_ENABLED = 8;
|
public final static int DC_INFO_SECURE_JOIN_MESSAGE = 7;
|
||||||
public static final int DC_INFO_LOCATION_ONLY = 9;
|
public final static int DC_INFO_LOCATIONSTREAMING_ENABLED = 8;
|
||||||
public static final int DC_INFO_EPHEMERAL_TIMER_CHANGED = 10;
|
public final static int DC_INFO_LOCATION_ONLY = 9;
|
||||||
public static final int DC_INFO_PROTECTION_ENABLED = 11;
|
public final static int DC_INFO_EPHEMERAL_TIMER_CHANGED = 10;
|
||||||
public static final int DC_INFO_INVALID_UNENCRYPTED_MAIL = 13;
|
public final static int DC_INFO_PROTECTION_ENABLED = 11;
|
||||||
public static final int DC_INFO_WEBXDC_INFO_MESSAGE = 32;
|
public final static int DC_INFO_INVALID_UNENCRYPTED_MAIL = 13;
|
||||||
public static final int DC_INFO_CHAT_E2EE = 50;
|
public final static int DC_INFO_WEBXDC_INFO_MESSAGE = 32;
|
||||||
public static final int DC_INFO_CHAT_DESCRIPTION_CHANGED = 70;
|
public final static int DC_INFO_CHAT_E2EE = 50;
|
||||||
|
|
||||||
public static final int DC_STATE_UNDEFINED = 0;
|
public final static int DC_STATE_UNDEFINED = 0;
|
||||||
public static final int DC_STATE_IN_FRESH = 10;
|
public final static int DC_STATE_IN_FRESH = 10;
|
||||||
public static final int DC_STATE_IN_NOTICED = 13;
|
public final static int DC_STATE_IN_NOTICED = 13;
|
||||||
public static final int DC_STATE_IN_SEEN = 16;
|
public final static int DC_STATE_IN_SEEN = 16;
|
||||||
public static final int DC_STATE_OUT_PREPARING = 18;
|
public final static int DC_STATE_OUT_PREPARING = 18;
|
||||||
public static final int DC_STATE_OUT_DRAFT = 19;
|
public final static int DC_STATE_OUT_DRAFT = 19;
|
||||||
public static final int DC_STATE_OUT_PENDING = 20;
|
public final static int DC_STATE_OUT_PENDING = 20;
|
||||||
public static final int DC_STATE_OUT_FAILED = 24;
|
public final static int DC_STATE_OUT_FAILED = 24;
|
||||||
public static final int DC_STATE_OUT_DELIVERED = 26;
|
public final static int DC_STATE_OUT_DELIVERED = 26;
|
||||||
public static final int DC_STATE_OUT_MDN_RCVD = 28;
|
public final static int DC_STATE_OUT_MDN_RCVD = 28;
|
||||||
|
|
||||||
public static final int DC_DOWNLOAD_DONE = 0;
|
public final static int DC_DOWNLOAD_DONE = 0;
|
||||||
public static final int DC_DOWNLOAD_AVAILABLE = 10;
|
public final static int DC_DOWNLOAD_AVAILABLE = 10;
|
||||||
public static final int DC_DOWNLOAD_FAILURE = 20;
|
public final static int DC_DOWNLOAD_FAILURE = 20;
|
||||||
public static final int DC_DOWNLOAD_UNDECIPHERABLE = 30;
|
public final static int DC_DOWNLOAD_UNDECIPHERABLE = 30;
|
||||||
public static final int DC_DOWNLOAD_IN_PROGRESS = 1000;
|
public final static int DC_DOWNLOAD_IN_PROGRESS = 1000;
|
||||||
|
|
||||||
public static final int DC_MSG_NO_ID = 0;
|
public static final int DC_MSG_NO_ID = 0;
|
||||||
public static final int DC_MSG_ID_MARKER1 = 1;
|
public final static int DC_MSG_ID_MARKER1 = 1;
|
||||||
public static final int DC_MSG_ID_DAYMARKER = 9;
|
public final static int DC_MSG_ID_DAYMARKER = 9;
|
||||||
|
|
||||||
public static final int DC_VIDEOCHATTYPE_UNKNOWN = 0;
|
public final static int DC_VIDEOCHATTYPE_UNKNOWN = 0;
|
||||||
public static final int DC_VIDEOCHATTYPE_BASICWEBRTC = 1;
|
public final static int DC_VIDEOCHATTYPE_BASICWEBRTC = 1;
|
||||||
|
|
||||||
public DcMsg(DcContext context, int viewtype) {
|
private static final String TAG = DcMsg.class.getSimpleName();
|
||||||
msgCPtr = context.createMsgCPtr(viewtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DcMsg(long msgCPtr) {
|
public DcMsg(DcContext context, int viewtype) {
|
||||||
this.msgCPtr = msgCPtr;
|
msgCPtr = context.createMsgCPtr(viewtype);
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOk() {
|
|
||||||
return msgCPtr != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
unrefMsgCPtr();
|
|
||||||
msgCPtr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return this.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (other == null || !(other instanceof DcMsg)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DcMsg that = (DcMsg) other;
|
public DcMsg(long msgCPtr) {
|
||||||
return this.getId() == that.getId() && this.getId() != 0;
|
this.msgCPtr = msgCPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** If given a message, calculates the position of the message in the chat */
|
public boolean isOk() {
|
||||||
public static int getMessagePosition(DcMsg msg, DcContext dcContext) {
|
return msgCPtr != 0;
|
||||||
int msgs[] = dcContext.getChatMsgs(msg.getChatId(), 0, 0);
|
}
|
||||||
int startingPosition = -1;
|
|
||||||
int msgId = msg.getId();
|
@Override
|
||||||
for (int i = 0; i < msgs.length; i++) {
|
protected void finalize() throws Throwable {
|
||||||
if (msgs[i] == msgId) {
|
super.finalize();
|
||||||
startingPosition = msgs.length - 1 - i;
|
unrefMsgCPtr();
|
||||||
break;
|
msgCPtr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (other == null || !(other instanceof DcMsg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DcMsg that = (DcMsg) other;
|
||||||
|
return this.getId()==that.getId() && this.getId()!=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If given a message, calculates the position of the message in the chat
|
||||||
|
*/
|
||||||
|
public static int getMessagePosition(DcMsg msg, DcContext dcContext) {
|
||||||
|
int msgs[] = dcContext.getChatMsgs(msg.getChatId(), 0, 0);
|
||||||
|
int startingPosition = -1;
|
||||||
|
int msgId = msg.getId();
|
||||||
|
for (int i = 0; i < msgs.length; i++) {
|
||||||
|
if (msgs[i] == msgId) {
|
||||||
|
startingPosition = msgs.length - 1 - i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return startingPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public native int getId ();
|
||||||
|
public native String getText ();
|
||||||
|
public native String getSubject ();
|
||||||
|
public native long getTimestamp ();
|
||||||
|
public native long getSortTimestamp ();
|
||||||
|
public native boolean hasDeviatingTimestamp();
|
||||||
|
public native boolean hasLocation ();
|
||||||
|
private native int getViewType ();
|
||||||
|
public int getType () { return getDownloadState()==DC_DOWNLOAD_DONE? getViewType() : DC_MSG_TEXT; }
|
||||||
|
public native int getInfoType ();
|
||||||
|
public native int getInfoContactId ();
|
||||||
|
public native int getState ();
|
||||||
|
public native int getDownloadState ();
|
||||||
|
public native int getChatId ();
|
||||||
|
public native int getFromId ();
|
||||||
|
public native int getWidth (int def);
|
||||||
|
public native int getHeight (int def);
|
||||||
|
public native int getDuration ();
|
||||||
|
public native void lateFilingMediaSize(int width, int height, int duration);
|
||||||
|
public DcLot getSummary (DcChat chat) { return new DcLot(getSummaryCPtr(chat.getChatCPtr())); }
|
||||||
|
public native String getSummarytext (int approx_characters);
|
||||||
|
public native int showPadlock ();
|
||||||
|
public boolean hasFile () { String file = getFile(); return file!=null && !file.isEmpty(); }
|
||||||
|
public native String getFile ();
|
||||||
|
public native String getFilemime ();
|
||||||
|
public native String getFilename ();
|
||||||
|
public native long getFilebytes ();
|
||||||
|
public native byte[] getWebxdcBlob (String filename);
|
||||||
|
public JSONObject getWebxdcInfo () {
|
||||||
|
try {
|
||||||
|
String json = getWebxdcInfoJson();
|
||||||
|
if (json != null && !json.isEmpty()) return new JSONObject(json);
|
||||||
|
} catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
return new JSONObject();
|
||||||
}
|
}
|
||||||
return startingPosition;
|
public native String getWebxdcHref ();
|
||||||
}
|
public native boolean isForwarded ();
|
||||||
|
public native boolean isInfo ();
|
||||||
|
public native boolean hasHtml ();
|
||||||
|
public native String getSetupCodeBegin ();
|
||||||
|
public native void setText (String text);
|
||||||
|
public native void setSubject (String text);
|
||||||
|
public native void setHtml (String text);
|
||||||
|
public native void forceSticker ();
|
||||||
|
public native void setFileAndDeduplicate(String file, String name, String filemime);
|
||||||
|
public native void setDimension (int width, int height);
|
||||||
|
public native void setDuration (int duration);
|
||||||
|
public native void setLocation (float latitude, float longitude);
|
||||||
|
public native String getPOILocation ();
|
||||||
|
public void setQuote (DcMsg quote) { setQuoteCPtr(quote.msgCPtr); }
|
||||||
|
public native String getQuotedText ();
|
||||||
|
public native String getError ();
|
||||||
|
public native String getOverrideSenderName();
|
||||||
|
public native boolean isEdited ();
|
||||||
|
|
||||||
public native int getId();
|
public String getSenderName(DcContact dcContact) {
|
||||||
|
String overrideName = getOverrideSenderName();
|
||||||
public native String getText();
|
if (overrideName != null) {
|
||||||
|
return "~" + overrideName;
|
||||||
public native String getSubject();
|
} else {
|
||||||
|
return dcContact.getDisplayName();
|
||||||
public native long getTimestamp();
|
}
|
||||||
|
|
||||||
public native long getSortTimestamp();
|
|
||||||
|
|
||||||
public native boolean hasDeviatingTimestamp();
|
|
||||||
|
|
||||||
public native boolean hasLocation();
|
|
||||||
|
|
||||||
private native int getViewType();
|
|
||||||
|
|
||||||
public int getType() {
|
|
||||||
return getDownloadState() == DC_DOWNLOAD_DONE ? getViewType() : DC_MSG_TEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
public native int getInfoType();
|
|
||||||
|
|
||||||
public native int getInfoContactId();
|
|
||||||
|
|
||||||
public native int getState();
|
|
||||||
|
|
||||||
public native int getDownloadState();
|
|
||||||
|
|
||||||
public native int getChatId();
|
|
||||||
|
|
||||||
public native int getFromId();
|
|
||||||
|
|
||||||
public native int getWidth(int def);
|
|
||||||
|
|
||||||
public native int getHeight(int def);
|
|
||||||
|
|
||||||
public native int getDuration();
|
|
||||||
|
|
||||||
public native void lateFilingMediaSize(int width, int height, int duration);
|
|
||||||
|
|
||||||
public DcLot getSummary(DcChat chat) {
|
|
||||||
return new DcLot(getSummaryCPtr(chat.getChatCPtr()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public native String getSummarytext(int approx_characters);
|
|
||||||
|
|
||||||
public native int showPadlock();
|
|
||||||
|
|
||||||
public boolean hasFile() {
|
|
||||||
String file = getFile();
|
|
||||||
return file != null && !file.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public native String getFile();
|
|
||||||
|
|
||||||
public native String getFilemime();
|
|
||||||
|
|
||||||
public native String getFilename();
|
|
||||||
|
|
||||||
public native long getFilebytes();
|
|
||||||
|
|
||||||
public native byte[] getWebxdcBlob(String filename);
|
|
||||||
|
|
||||||
public JSONObject getWebxdcInfo() {
|
|
||||||
try {
|
|
||||||
String json = getWebxdcInfoJson();
|
|
||||||
if (json != null && !json.isEmpty()) return new JSONObject(json);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
return new JSONObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
public native String getWebxdcHref();
|
public DcMsg getQuotedMsg () {
|
||||||
|
long cPtr = getQuotedMsgCPtr();
|
||||||
public native boolean isForwarded();
|
return cPtr != 0 ? new DcMsg(cPtr) : null;
|
||||||
|
|
||||||
public native boolean isInfo();
|
|
||||||
|
|
||||||
public native boolean hasHtml();
|
|
||||||
|
|
||||||
public native void setText(String text);
|
|
||||||
|
|
||||||
public native void setSubject(String text);
|
|
||||||
|
|
||||||
public native void setHtml(String text);
|
|
||||||
|
|
||||||
public native void setFileAndDeduplicate(String file, String name, String filemime);
|
|
||||||
|
|
||||||
public native void setDimension(int width, int height);
|
|
||||||
|
|
||||||
public native void setDuration(int duration);
|
|
||||||
|
|
||||||
public native void setLocation(float latitude, float longitude);
|
|
||||||
|
|
||||||
public native String getPOILocation();
|
|
||||||
|
|
||||||
public void setQuote(DcMsg quote) {
|
|
||||||
setQuoteCPtr(quote.msgCPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public native String getQuotedText();
|
|
||||||
|
|
||||||
public native String getError();
|
|
||||||
|
|
||||||
public native String getOverrideSenderName();
|
|
||||||
|
|
||||||
public native boolean isEdited();
|
|
||||||
|
|
||||||
public String getSenderName(DcContact dcContact) {
|
|
||||||
String overrideName = getOverrideSenderName();
|
|
||||||
if (overrideName != null) {
|
|
||||||
return "~" + overrideName;
|
|
||||||
} else {
|
|
||||||
return dcContact.getDisplayName();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public DcMsg getQuotedMsg() {
|
public DcMsg getParent() {
|
||||||
long cPtr = getQuotedMsgCPtr();
|
long cPtr = getParentCPtr();
|
||||||
return cPtr != 0 ? new DcMsg(cPtr) : null;
|
return cPtr != 0 ? new DcMsg(cPtr) : null;
|
||||||
}
|
|
||||||
|
|
||||||
public DcMsg getParent() {
|
|
||||||
long cPtr = getParentCPtr();
|
|
||||||
return cPtr != 0 ? new DcMsg(cPtr) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public native int getOriginalMsgId();
|
|
||||||
|
|
||||||
public native int getSavedMsgId();
|
|
||||||
|
|
||||||
public boolean canSave() {
|
|
||||||
// saving info-messages out of context results in confusion, see
|
|
||||||
// https://github.com/deltachat/deltachat-ios/issues/2567
|
|
||||||
return !isInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getFileAsFile() {
|
|
||||||
if (getFile() == null) throw new AssertionError("expected a file to be present.");
|
|
||||||
return new File(getFile());
|
|
||||||
}
|
|
||||||
|
|
||||||
// aliases and higher-level tools
|
|
||||||
public static int[] msgSetToIds(final Set<DcMsg> dcMsgs) {
|
|
||||||
if (dcMsgs == null) {
|
|
||||||
return new int[0];
|
|
||||||
}
|
}
|
||||||
int[] ids = new int[dcMsgs.size()];
|
|
||||||
int i = 0;
|
public native int getOriginalMsgId ();
|
||||||
for (DcMsg dcMsg : dcMsgs) {
|
public native int getSavedMsgId ();
|
||||||
ids[i++] = dcMsg.getId();
|
|
||||||
|
public boolean canSave() {
|
||||||
|
// saving info-messages out of context results in confusion, see https://github.com/deltachat/deltachat-ios/issues/2567
|
||||||
|
return !isInfo();
|
||||||
}
|
}
|
||||||
return ids;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOutgoing() {
|
public File getFileAsFile() {
|
||||||
return getFromId() == DcContact.DC_CONTACT_ID_SELF;
|
if(getFile()==null)
|
||||||
}
|
throw new AssertionError("expected a file to be present.");
|
||||||
|
return new File(getFile());
|
||||||
|
}
|
||||||
|
|
||||||
public String getDisplayBody() {
|
// aliases and higher-level tools
|
||||||
return getText();
|
public static int[] msgSetToIds(final Set<DcMsg> dcMsgs) {
|
||||||
}
|
if (dcMsgs == null) {
|
||||||
|
return new int[0];
|
||||||
|
}
|
||||||
|
int[] ids = new int[dcMsgs.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (DcMsg dcMsg : dcMsgs) {
|
||||||
|
ids[i++] = dcMsg.getId();
|
||||||
|
}
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
public String getBody() {
|
public boolean isOutgoing() {
|
||||||
return getText();
|
return getFromId() == DcContact.DC_CONTACT_ID_SELF;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getDateReceived() {
|
public String getDisplayBody() {
|
||||||
return getTimestamp();
|
return getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFailed() {
|
public String getBody() {
|
||||||
return (getState() == DC_STATE_OUT_FAILED) || (!TextUtils.isEmpty(getError()));
|
return getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPreparing() {
|
public long getDateReceived() {
|
||||||
return getState() == DC_STATE_OUT_PREPARING;
|
return getTimestamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSecure() {
|
public boolean isFailed() {
|
||||||
return showPadlock() != 0;
|
return (getState() == DC_STATE_OUT_FAILED) || (!TextUtils.isEmpty(getError()));
|
||||||
}
|
}
|
||||||
|
public boolean isPreparing() {
|
||||||
|
return getState() == DC_STATE_OUT_PREPARING;
|
||||||
|
}
|
||||||
|
public boolean isSecure() {
|
||||||
|
return showPadlock()!=0;
|
||||||
|
}
|
||||||
|
public boolean isPending() {
|
||||||
|
return getState() == DC_STATE_OUT_PENDING;
|
||||||
|
}
|
||||||
|
public boolean isDelivered() {
|
||||||
|
return getState() == DC_STATE_OUT_DELIVERED;
|
||||||
|
}
|
||||||
|
public boolean isRemoteRead() {
|
||||||
|
return getState() == DC_STATE_OUT_MDN_RCVD;
|
||||||
|
}
|
||||||
|
public boolean isSeen() {
|
||||||
|
return getState() == DC_STATE_IN_SEEN;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPending() {
|
|
||||||
return getState() == DC_STATE_OUT_PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDelivered() {
|
// working with raw c-data
|
||||||
return getState() == DC_STATE_OUT_DELIVERED;
|
private long msgCPtr; // CAVE: the name is referenced in the JNI
|
||||||
}
|
private native void unrefMsgCPtr ();
|
||||||
|
private native long getSummaryCPtr (long chatCPtr);
|
||||||
public boolean isRemoteRead() {
|
private native void setQuoteCPtr (long quoteCPtr);
|
||||||
return getState() == DC_STATE_OUT_MDN_RCVD;
|
private native long getQuotedMsgCPtr ();
|
||||||
}
|
private native long getParentCPtr ();
|
||||||
|
private native String getWebxdcInfoJson ();
|
||||||
public boolean isSeen() {
|
};
|
||||||
return getState() == DC_STATE_IN_SEEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
// working with raw c-data
|
|
||||||
private long msgCPtr; // CAVE: the name is referenced in the JNI
|
|
||||||
|
|
||||||
private native void unrefMsgCPtr();
|
|
||||||
|
|
||||||
private native long getSummaryCPtr(long chatCPtr);
|
|
||||||
|
|
||||||
private native void setQuoteCPtr(long quoteCPtr);
|
|
||||||
|
|
||||||
private native long getQuotedMsgCPtr();
|
|
||||||
|
|
||||||
private native long getParentCPtr();
|
|
||||||
|
|
||||||
private native String getWebxdcInfoJson();
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|||||||
@@ -2,29 +2,25 @@ package com.b44t.messenger;
|
|||||||
|
|
||||||
public class DcProvider {
|
public class DcProvider {
|
||||||
|
|
||||||
public static final int DC_PROVIDER_STATUS_OK = 1;
|
public final static int DC_PROVIDER_STATUS_OK = 1;
|
||||||
public static final int DC_PROVIDER_STATUS_PREPARATION = 2;
|
public final static int DC_PROVIDER_STATUS_PREPARATION = 2;
|
||||||
public static final int DC_PROVIDER_STATUS_BROKEN = 3;
|
public final static int DC_PROVIDER_STATUS_BROKEN = 3;
|
||||||
|
|
||||||
public DcProvider(long providerCPtr) {
|
public DcProvider(long providerCPtr) {
|
||||||
this.providerCPtr = providerCPtr;
|
this.providerCPtr = providerCPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override protected void finalize() throws Throwable {
|
||||||
protected void finalize() throws Throwable {
|
super.finalize();
|
||||||
super.finalize();
|
unrefProviderCPtr();
|
||||||
unrefProviderCPtr();
|
providerCPtr = 0;
|
||||||
providerCPtr = 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public native int getStatus();
|
public native int getStatus ();
|
||||||
|
public native String getBeforeLoginHint ();
|
||||||
|
public native String getOverviewPage ();
|
||||||
|
|
||||||
public native String getBeforeLoginHint();
|
// working with raw c-data
|
||||||
|
private long providerCPtr; // CAVE: the name is referenced in the JNI
|
||||||
public native String getOverviewPage();
|
private native void unrefProviderCPtr();
|
||||||
|
|
||||||
// working with raw c-data
|
|
||||||
private long providerCPtr; // CAVE: the name is referenced in the JNI
|
|
||||||
|
|
||||||
private native void unrefProviderCPtr();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.b44t.messenger;
|
package com.b44t.messenger;
|
||||||
|
|
||||||
import chat.delta.rpc.BaseRpcTransport;
|
import chat.delta.rpc.BaseTransport;
|
||||||
|
|
||||||
/* RPC transport over C FFI */
|
/* RPC transport over C FFI */
|
||||||
public class FFITransport extends BaseRpcTransport {
|
public class FFITransport extends BaseTransport {
|
||||||
private final DcJsonrpcInstance dcJsonrpcInstance;
|
private final DcJsonrpcInstance dcJsonrpcInstance;
|
||||||
|
|
||||||
public FFITransport(DcJsonrpcInstance dcJsonrpcInstance) {
|
public FFITransport(DcJsonrpcInstance dcJsonrpcInstance) {
|
||||||
@@ -19,4 +19,4 @@ public class FFITransport extends BaseRpcTransport {
|
|||||||
protected String getResponse() {
|
protected String getResponse() {
|
||||||
return dcJsonrpcInstance.getNextResponse();
|
return dcJsonrpcInstance.getNextResponse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
+1208
-1216
File diff suppressed because it is too large
Load Diff
@@ -1,73 +1,61 @@
|
|||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.view.ActionMode;
|
import androidx.appcompat.view.ActionMode;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||||
import androidx.media3.session.MediaController;
|
import androidx.viewpager.widget.ViewPager;
|
||||||
import androidx.media3.session.SessionCommand;
|
|
||||||
import androidx.media3.session.SessionToken;
|
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
|
||||||
import androidx.viewpager2.widget.ViewPager2;
|
|
||||||
import com.b44t.messenger.DcChat;
|
import com.b44t.messenger.DcChat;
|
||||||
import com.b44t.messenger.DcContext;
|
import com.b44t.messenger.DcContext;
|
||||||
import com.b44t.messenger.DcEvent;
|
import com.b44t.messenger.DcEvent;
|
||||||
import com.b44t.messenger.DcMsg;
|
import com.b44t.messenger.DcMsg;
|
||||||
import com.google.android.material.tabs.TabLayout;
|
import com.google.android.material.tabs.TabLayout;
|
||||||
import com.google.android.material.tabs.TabLayoutMediator;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import org.thoughtcrime.securesms.components.audioplay.AudioPlaybackViewModel;
|
|
||||||
import org.thoughtcrime.securesms.components.audioplay.ChatAudioQueueProvider;
|
|
||||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
import org.thoughtcrime.securesms.service.AudioPlaybackService;
|
|
||||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||||
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
|
|
||||||
public class AllMediaActivity extends PassphraseRequiredActionBarActivity
|
import java.util.ArrayList;
|
||||||
implements DcEventCenter.DcEventDelegate {
|
|
||||||
private static final String TAG = "AllMediaActivity";
|
|
||||||
|
|
||||||
public static final String CHAT_ID_EXTRA = "chat_id";
|
public class AllMediaActivity extends PassphraseRequiredActionBarActivity
|
||||||
|
implements DcEventCenter.DcEventDelegate
|
||||||
|
{
|
||||||
|
|
||||||
|
public static final String CHAT_ID_EXTRA = "chat_id";
|
||||||
public static final String CONTACT_ID_EXTRA = "contact_id";
|
public static final String CONTACT_ID_EXTRA = "contact_id";
|
||||||
public static final String FORCE_GALLERY = "force_gallery";
|
public static final String FORCE_GALLERY = "force_gallery";
|
||||||
|
|
||||||
static class TabData {
|
static class TabData {
|
||||||
final int title;
|
final int title;
|
||||||
final int type1;
|
final int type1;
|
||||||
final int type2;
|
final int type2;
|
||||||
final int type3;
|
final int type3;
|
||||||
|
|
||||||
TabData(int title, int type1, int type2, int type3) {
|
TabData(int title, int type1, int type2, int type3) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.type1 = type1;
|
this.type1 = type1;
|
||||||
this.type2 = type2;
|
this.type2 = type2;
|
||||||
this.type3 = type3;
|
this.type3 = type3;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
private DcContext dcContext;
|
private DcContext dcContext;
|
||||||
private int chatId;
|
private int chatId;
|
||||||
private int contactId;
|
private int contactId;
|
||||||
|
|
||||||
private final ArrayList<TabData> tabs = new ArrayList<>();
|
private final ArrayList<TabData> tabs = new ArrayList<>();
|
||||||
private Toolbar toolbar;
|
private Toolbar toolbar;
|
||||||
private TabLayout tabLayout;
|
private TabLayout tabLayout;
|
||||||
private ViewPager2 viewPager;
|
private ViewPager viewPager;
|
||||||
|
|
||||||
private @Nullable MediaController mediaController;
|
|
||||||
private ListenableFuture<MediaController> mediaControllerFuture;
|
|
||||||
private AudioPlaybackViewModel playbackViewModel;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPreCreate() {
|
protected void onPreCreate() {
|
||||||
@@ -79,9 +67,7 @@ public class AllMediaActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle bundle, boolean ready) {
|
protected void onCreate(Bundle bundle, boolean ready) {
|
||||||
tabs.add(new TabData(R.string.webxdc_apps, DcMsg.DC_MSG_WEBXDC, 0, 0));
|
tabs.add(new TabData(R.string.webxdc_apps, DcMsg.DC_MSG_WEBXDC, 0, 0));
|
||||||
tabs.add(
|
tabs.add(new TabData(R.string.tab_gallery, DcMsg.DC_MSG_IMAGE, DcMsg.DC_MSG_GIF, DcMsg.DC_MSG_VIDEO));
|
||||||
new TabData(
|
|
||||||
R.string.tab_gallery, DcMsg.DC_MSG_IMAGE, DcMsg.DC_MSG_GIF, DcMsg.DC_MSG_VIDEO));
|
|
||||||
tabs.add(new TabData(R.string.audio, DcMsg.DC_MSG_AUDIO, DcMsg.DC_MSG_VOICE, 0));
|
tabs.add(new TabData(R.string.audio, DcMsg.DC_MSG_AUDIO, DcMsg.DC_MSG_VOICE, 0));
|
||||||
tabs.add(new TabData(R.string.files, DcMsg.DC_MSG_FILE, 0, 0));
|
tabs.add(new TabData(R.string.files, DcMsg.DC_MSG_FILE, 0, 0));
|
||||||
|
|
||||||
@@ -93,24 +79,11 @@ public class AllMediaActivity extends PassphraseRequiredActionBarActivity
|
|||||||
ActionBar supportActionBar = getSupportActionBar();
|
ActionBar supportActionBar = getSupportActionBar();
|
||||||
if (supportActionBar != null) {
|
if (supportActionBar != null) {
|
||||||
supportActionBar.setDisplayHomeAsUpEnabled(true);
|
supportActionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
supportActionBar.setTitle(
|
supportActionBar.setTitle(isGlobalGallery() ? R.string.menu_all_media : R.string.apps_and_media);
|
||||||
isGlobalGallery() ? R.string.menu_all_media : R.string.apps_and_media);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AllMediaPagerAdapter adapter = new AllMediaPagerAdapter(this);
|
this.tabLayout.setupWithViewPager(viewPager);
|
||||||
this.viewPager.setAdapter(adapter);
|
this.viewPager.setAdapter(new AllMediaPagerAdapter(getSupportFragmentManager()));
|
||||||
this.viewPager.registerOnPageChangeCallback(
|
|
||||||
new ViewPager2.OnPageChangeCallback() {
|
|
||||||
@Override
|
|
||||||
public void onPageSelected(int position) {
|
|
||||||
adapter.onPageChanged(position);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
new TabLayoutMediator(
|
|
||||||
this.tabLayout,
|
|
||||||
this.viewPager,
|
|
||||||
(tab, position) -> tab.setText(getString(tabs.get(position).title)))
|
|
||||||
.attach();
|
|
||||||
if (getIntent().getBooleanExtra(FORCE_GALLERY, false)) {
|
if (getIntent().getBooleanExtra(FORCE_GALLERY, false)) {
|
||||||
this.viewPager.setCurrentItem(1, false);
|
this.viewPager.setCurrentItem(1, false);
|
||||||
}
|
}
|
||||||
@@ -118,109 +91,78 @@ public class AllMediaActivity extends PassphraseRequiredActionBarActivity
|
|||||||
DcEventCenter eventCenter = DcHelper.getEventCenter(this);
|
DcEventCenter eventCenter = DcHelper.getEventCenter(this);
|
||||||
eventCenter.addObserver(DcContext.DC_EVENT_CHAT_MODIFIED, this);
|
eventCenter.addObserver(DcContext.DC_EVENT_CHAT_MODIFIED, this);
|
||||||
eventCenter.addObserver(DcContext.DC_EVENT_CONTACTS_CHANGED, this);
|
eventCenter.addObserver(DcContext.DC_EVENT_CONTACTS_CHANGED, this);
|
||||||
|
|
||||||
int accountId = DcHelper.getAccounts(this).getSelectedAccount().getAccountId();
|
|
||||||
playbackViewModel = new ViewModelProvider(this).get(AudioPlaybackViewModel.class);
|
|
||||||
playbackViewModel.setQueueProvider(new ChatAudioQueueProvider(this, chatId, accountId));
|
|
||||||
initializeMediaController();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
DcHelper.getEventCenter(this).removeObservers(this);
|
DcHelper.getEventCenter(this).removeObservers(this);
|
||||||
if (mediaController != null) {
|
|
||||||
MediaController.releaseFuture(mediaControllerFuture);
|
|
||||||
mediaController = null;
|
|
||||||
playbackViewModel.setMediaController(null);
|
|
||||||
}
|
|
||||||
playbackViewModel.setQueueProvider(null);
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleEvent(@NonNull DcEvent event) {}
|
public void handleEvent(@NonNull DcEvent event) {
|
||||||
|
}
|
||||||
|
|
||||||
private void initializeResources() {
|
private void initializeResources() {
|
||||||
chatId = getIntent().getIntExtra(CHAT_ID_EXTRA, 0);
|
chatId = getIntent().getIntExtra(CHAT_ID_EXTRA, 0);
|
||||||
contactId = getIntent().getIntExtra(CONTACT_ID_EXTRA, 0);
|
contactId = getIntent().getIntExtra(CONTACT_ID_EXTRA, 0);
|
||||||
|
|
||||||
if (contactId != 0) {
|
if (contactId!=0) {
|
||||||
chatId = dcContext.getChatIdByContactId(contactId);
|
chatId = dcContext.getChatIdByContactId(contactId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chatId != 0) {
|
if(chatId!=0) {
|
||||||
DcChat dcChat = dcContext.getChat(chatId);
|
DcChat dcChat = dcContext.getChat(chatId);
|
||||||
if (!dcChat.isMultiUser()) {
|
if(!dcChat.isMultiUser()) {
|
||||||
final int[] members = dcContext.getChatContacts(chatId);
|
final int[] members = dcContext.getChatContacts(chatId);
|
||||||
contactId = members.length >= 1 ? members[0] : 0;
|
contactId = members.length>=1? members[0] : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.viewPager = ViewUtil.findById(this, R.id.pager);
|
this.viewPager = ViewUtil.findById(this, R.id.pager);
|
||||||
this.toolbar = ViewUtil.findById(this, R.id.toolbar);
|
this.toolbar = ViewUtil.findById(this, R.id.toolbar);
|
||||||
this.tabLayout = ViewUtil.findById(this, R.id.tab_layout);
|
this.tabLayout = ViewUtil.findById(this, R.id.tab_layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeMediaController() {
|
private boolean isGlobalGallery() {
|
||||||
SessionToken sessionToken =
|
return contactId==0 && chatId==0;
|
||||||
new SessionToken(this, new ComponentName(this, AudioPlaybackService.class));
|
|
||||||
mediaControllerFuture = new MediaController.Builder(this, sessionToken).buildAsync();
|
|
||||||
mediaControllerFuture.addListener(
|
|
||||||
() -> {
|
|
||||||
try {
|
|
||||||
mediaController = mediaControllerFuture.get();
|
|
||||||
addActivityContext(this.getIntent().getExtras(), this.getClass().getName());
|
|
||||||
playbackViewModel.setMediaController(mediaController);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Error connecting to audio playback service", e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ContextCompat.getMainExecutor(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addActivityContext(Bundle extras, String activityClassName) {
|
private class AllMediaPagerAdapter extends FragmentStatePagerAdapter {
|
||||||
if (mediaController == null) return;
|
private Object currentFragment = null;
|
||||||
|
|
||||||
Bundle commandArgs = new Bundle();
|
AllMediaPagerAdapter(FragmentManager fragmentManager) {
|
||||||
commandArgs.putString("activity_class", activityClassName);
|
super(fragmentManager);
|
||||||
if (extras != null) {
|
|
||||||
commandArgs.putAll(extras);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionCommand updateContextCommand =
|
@Override
|
||||||
new SessionCommand("UPDATE_ACTIVITY_CONTEXT", Bundle.EMPTY);
|
public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
|
||||||
|
super.setPrimaryItem(container, position, object);
|
||||||
mediaController.sendCustomCommand(updateContextCommand, commandArgs);
|
if (currentFragment != null && currentFragment != object) {
|
||||||
}
|
ActionMode action = null;
|
||||||
|
if (currentFragment instanceof MessageSelectorFragment) {
|
||||||
private boolean isGlobalGallery() {
|
action = ((MessageSelectorFragment) currentFragment).getActionMode();
|
||||||
return contactId == 0 && chatId == 0;
|
}
|
||||||
}
|
if (action != null) {
|
||||||
|
action.finish();
|
||||||
private class AllMediaPagerAdapter extends FragmentStateAdapter {
|
}
|
||||||
private int currentPosition = -1;
|
}
|
||||||
|
currentFragment = object;
|
||||||
AllMediaPagerAdapter(FragmentActivity activity) {
|
|
||||||
super(activity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Fragment createFragment(int position) {
|
public Fragment getItem(int position) {
|
||||||
TabData data = tabs.get(position);
|
TabData data = tabs.get(position);
|
||||||
Fragment fragment;
|
Fragment fragment;
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
|
|
||||||
if (data.type1 == DcMsg.DC_MSG_IMAGE) {
|
if (data.type1 == DcMsg.DC_MSG_IMAGE) {
|
||||||
fragment = new AllMediaGalleryFragment();
|
fragment = new AllMediaGalleryFragment();
|
||||||
args.putInt(
|
args.putInt(AllMediaGalleryFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalGallery())? -1 : chatId);
|
||||||
AllMediaGalleryFragment.CHAT_ID_EXTRA,
|
|
||||||
(chatId == 0 && !isGlobalGallery()) ? -1 : chatId);
|
|
||||||
} else {
|
} else {
|
||||||
fragment = new AllMediaDocumentsFragment();
|
fragment = new AllMediaDocumentsFragment();
|
||||||
args.putInt(
|
args.putInt(AllMediaDocumentsFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalGallery())? -1 : chatId);
|
||||||
AllMediaDocumentsFragment.CHAT_ID_EXTRA,
|
|
||||||
(chatId == 0 && !isGlobalGallery()) ? -1 : chatId);
|
|
||||||
args.putInt(AllMediaDocumentsFragment.VIEWTYPE1, data.type1);
|
args.putInt(AllMediaDocumentsFragment.VIEWTYPE1, data.type1);
|
||||||
args.putInt(AllMediaDocumentsFragment.VIEWTYPE2, data.type2);
|
args.putInt(AllMediaDocumentsFragment.VIEWTYPE2, data.type2);
|
||||||
}
|
}
|
||||||
@@ -229,24 +171,13 @@ public class AllMediaActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getCount() {
|
||||||
return tabs.size();
|
return tabs.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPageChanged(int newPosition) {
|
@Override
|
||||||
if (currentPosition != -1 && currentPosition != newPosition) {
|
public CharSequence getPageTitle(int position) {
|
||||||
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
|
return getString(tabs.get(position).title);
|
||||||
if (!(fragment instanceof MessageSelectorFragment)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ActionMode action = ((MessageSelectorFragment) fragment).getActionMode();
|
|
||||||
if (action != null) {
|
|
||||||
action.finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currentPosition = newPosition;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,16 +5,15 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.b44t.messenger.DcMsg;
|
import com.b44t.messenger.DcMsg;
|
||||||
import com.codewaves.stickyheadergrid.StickyHeaderGridAdapter;
|
import com.codewaves.stickyheadergrid.StickyHeaderGridAdapter;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
import org.thoughtcrime.securesms.components.AudioView;
|
||||||
import java.util.Set;
|
|
||||||
import org.thoughtcrime.securesms.components.DocumentView;
|
import org.thoughtcrime.securesms.components.DocumentView;
|
||||||
import org.thoughtcrime.securesms.components.WebxdcView;
|
import org.thoughtcrime.securesms.components.WebxdcView;
|
||||||
import org.thoughtcrime.securesms.components.audioplay.AudioPlaybackViewModel;
|
|
||||||
import org.thoughtcrime.securesms.components.audioplay.AudioView;
|
|
||||||
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader.BucketedThreadMedia;
|
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader.BucketedThreadMedia;
|
||||||
import org.thoughtcrime.securesms.mms.AudioSlide;
|
import org.thoughtcrime.securesms.mms.AudioSlide;
|
||||||
import org.thoughtcrime.securesms.mms.DocumentSlide;
|
import org.thoughtcrime.securesms.mms.DocumentSlide;
|
||||||
@@ -22,27 +21,30 @@ import org.thoughtcrime.securesms.mms.Slide;
|
|||||||
import org.thoughtcrime.securesms.util.DateUtils;
|
import org.thoughtcrime.securesms.util.DateUtils;
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
class AllMediaDocumentsAdapter extends StickyHeaderGridAdapter {
|
class AllMediaDocumentsAdapter extends StickyHeaderGridAdapter {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final ItemClickListener itemClickListener;
|
private final ItemClickListener itemClickListener;
|
||||||
private final Set<DcMsg> selected;
|
private final Set<DcMsg> selected;
|
||||||
|
|
||||||
private BucketedThreadMedia media;
|
private BucketedThreadMedia media;
|
||||||
private AudioPlaybackViewModel playbackViewModel;
|
|
||||||
|
|
||||||
private static class ViewHolder extends StickyHeaderGridAdapter.ItemViewHolder {
|
private static class ViewHolder extends StickyHeaderGridAdapter.ItemViewHolder {
|
||||||
private final DocumentView documentView;
|
private final DocumentView documentView;
|
||||||
private final AudioView audioView;
|
private final AudioView audioView;
|
||||||
private final WebxdcView webxdcView;
|
private final WebxdcView webxdcView;
|
||||||
private final TextView date;
|
private final TextView date;
|
||||||
|
|
||||||
public ViewHolder(View v) {
|
public ViewHolder(View v) {
|
||||||
super(v);
|
super(v);
|
||||||
documentView = v.findViewById(R.id.document_view);
|
documentView = v.findViewById(R.id.document_view);
|
||||||
audioView = v.findViewById(R.id.audio_view);
|
audioView = v.findViewById(R.id.audio_view);
|
||||||
webxdcView = v.findViewById(R.id.webxdc_view);
|
webxdcView = v.findViewById(R.id.webxdc_view);
|
||||||
date = v.findViewById(R.id.date);
|
date = v.findViewById(R.id.date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,108 +57,86 @@ class AllMediaDocumentsAdapter extends StickyHeaderGridAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AllMediaDocumentsAdapter(
|
AllMediaDocumentsAdapter(@NonNull Context context,
|
||||||
@NonNull Context context, BucketedThreadMedia media, ItemClickListener clickListener) {
|
BucketedThreadMedia media,
|
||||||
this.context = context;
|
ItemClickListener clickListener)
|
||||||
this.media = media;
|
{
|
||||||
|
this.context = context;
|
||||||
|
this.media = media;
|
||||||
this.itemClickListener = clickListener;
|
this.itemClickListener = clickListener;
|
||||||
this.selected = new HashSet<>();
|
this.selected = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMedia(BucketedThreadMedia media) {
|
public void setMedia(BucketedThreadMedia media) {
|
||||||
this.media = media;
|
this.media = media;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPlaybackViewModel(AudioPlaybackViewModel playbackViewModel) {
|
|
||||||
this.playbackViewModel = playbackViewModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StickyHeaderGridAdapter.HeaderViewHolder onCreateHeaderViewHolder(
|
public StickyHeaderGridAdapter.HeaderViewHolder onCreateHeaderViewHolder(ViewGroup parent, int headerType) {
|
||||||
ViewGroup parent, int headerType) {
|
return new HeaderHolder(LayoutInflater.from(context).inflate(R.layout.contact_selection_list_divider, parent, false));
|
||||||
return new HeaderHolder(
|
|
||||||
LayoutInflater.from(context)
|
|
||||||
.inflate(R.layout.contact_selection_list_divider, parent, false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemViewHolder onCreateItemViewHolder(ViewGroup parent, int itemType) {
|
public ItemViewHolder onCreateItemViewHolder(ViewGroup parent, int itemType) {
|
||||||
return new ViewHolder(
|
return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.profile_document_item, parent, false));
|
||||||
LayoutInflater.from(context).inflate(R.layout.profile_document_item, parent, false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindHeaderViewHolder(
|
public void onBindHeaderViewHolder(StickyHeaderGridAdapter.HeaderViewHolder viewHolder, int section) {
|
||||||
StickyHeaderGridAdapter.HeaderViewHolder viewHolder, int section) {
|
((HeaderHolder)viewHolder).textView.setText(media.getName(section));
|
||||||
((HeaderHolder) viewHolder).textView.setText(media.getName(section));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindItemViewHolder(ItemViewHolder itemViewHolder, int section, int offset) {
|
public void onBindItemViewHolder(ItemViewHolder itemViewHolder, int section, int offset) {
|
||||||
ViewHolder viewHolder = ((ViewHolder) itemViewHolder);
|
ViewHolder viewHolder = ((ViewHolder)itemViewHolder);
|
||||||
DcMsg dcMsg = media.get(section, offset);
|
DcMsg dcMsg = media.get(section, offset);
|
||||||
Slide slide = MediaUtil.getSlideForMsg(context, dcMsg);
|
Slide slide = MediaUtil.getSlideForMsg(context, dcMsg);
|
||||||
|
|
||||||
if (slide != null && slide.hasAudio()) {
|
if (slide != null && slide.hasAudio()) {
|
||||||
viewHolder.documentView.setVisibility(View.GONE);
|
viewHolder.documentView.setVisibility(View.GONE);
|
||||||
viewHolder.webxdcView.setVisibility(View.GONE);
|
viewHolder.webxdcView.setVisibility(View.GONE);
|
||||||
|
|
||||||
viewHolder.audioView.setVisibility(View.VISIBLE);
|
viewHolder.audioView.setVisibility(View.VISIBLE);
|
||||||
viewHolder.audioView.setPlaybackViewModel(playbackViewModel);
|
viewHolder.audioView.setAudio((AudioSlide)slide, dcMsg.getDuration());
|
||||||
viewHolder.audioView.setAudio((AudioSlide) slide);
|
|
||||||
viewHolder.audioView.setOnClickListener(view -> itemClickListener.onMediaClicked(dcMsg));
|
viewHolder.audioView.setOnClickListener(view -> itemClickListener.onMediaClicked(dcMsg));
|
||||||
viewHolder.audioView.setOnLongClickListener(
|
viewHolder.audioView.setOnLongClickListener(view -> { itemClickListener.onMediaLongClicked(dcMsg); return true; });
|
||||||
view -> {
|
|
||||||
itemClickListener.onMediaLongClicked(dcMsg);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
viewHolder.audioView.disablePlayer(!selected.isEmpty());
|
viewHolder.audioView.disablePlayer(!selected.isEmpty());
|
||||||
viewHolder.itemView.setOnClickListener(view -> itemClickListener.onMediaClicked(dcMsg));
|
viewHolder.itemView.setOnClickListener(view -> itemClickListener.onMediaClicked(dcMsg));
|
||||||
viewHolder.date.setVisibility(View.VISIBLE);
|
viewHolder.date.setVisibility(View.VISIBLE);
|
||||||
} else if (slide != null && slide.isWebxdcDocument()) {
|
}
|
||||||
|
else if (slide != null && slide.isWebxdcDocument()) {
|
||||||
viewHolder.audioView.setVisibility(View.GONE);
|
viewHolder.audioView.setVisibility(View.GONE);
|
||||||
viewHolder.documentView.setVisibility(View.GONE);
|
viewHolder.documentView.setVisibility(View.GONE);
|
||||||
|
|
||||||
viewHolder.webxdcView.setVisibility(View.VISIBLE);
|
viewHolder.webxdcView.setVisibility(View.VISIBLE);
|
||||||
viewHolder.webxdcView.setWebxdc(dcMsg, "");
|
viewHolder.webxdcView.setWebxdc(dcMsg, "");
|
||||||
viewHolder.webxdcView.setOnClickListener(view -> itemClickListener.onMediaClicked(dcMsg));
|
viewHolder.webxdcView.setOnClickListener(view -> itemClickListener.onMediaClicked(dcMsg));
|
||||||
viewHolder.webxdcView.setOnLongClickListener(
|
viewHolder.webxdcView.setOnLongClickListener(view -> { itemClickListener.onMediaLongClicked(dcMsg); return true; });
|
||||||
view -> {
|
|
||||||
itemClickListener.onMediaLongClicked(dcMsg);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
viewHolder.itemView.setOnClickListener(view -> itemClickListener.onMediaClicked(dcMsg));
|
viewHolder.itemView.setOnClickListener(view -> itemClickListener.onMediaClicked(dcMsg));
|
||||||
viewHolder.date.setVisibility(View.GONE);
|
viewHolder.date.setVisibility(View.GONE);
|
||||||
} else if (slide != null && slide.hasDocument()) {
|
}
|
||||||
|
else if (slide != null && slide.hasDocument()) {
|
||||||
viewHolder.audioView.setVisibility(View.GONE);
|
viewHolder.audioView.setVisibility(View.GONE);
|
||||||
viewHolder.webxdcView.setVisibility(View.GONE);
|
viewHolder.webxdcView.setVisibility(View.GONE);
|
||||||
|
|
||||||
viewHolder.documentView.setVisibility(View.VISIBLE);
|
viewHolder.documentView.setVisibility(View.VISIBLE);
|
||||||
viewHolder.documentView.setDocument((DocumentSlide) slide);
|
viewHolder.documentView.setDocument((DocumentSlide)slide);
|
||||||
viewHolder.documentView.setOnClickListener(view -> itemClickListener.onMediaClicked(dcMsg));
|
viewHolder.documentView.setOnClickListener(view -> itemClickListener.onMediaClicked(dcMsg));
|
||||||
viewHolder.documentView.setOnLongClickListener(
|
viewHolder.documentView.setOnLongClickListener(view -> { itemClickListener.onMediaLongClicked(dcMsg); return true; });
|
||||||
view -> {
|
|
||||||
itemClickListener.onMediaLongClicked(dcMsg);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
viewHolder.itemView.setOnClickListener(view -> itemClickListener.onMediaClicked(dcMsg));
|
viewHolder.itemView.setOnClickListener(view -> itemClickListener.onMediaClicked(dcMsg));
|
||||||
viewHolder.date.setVisibility(View.VISIBLE);
|
viewHolder.date.setVisibility(View.VISIBLE);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
viewHolder.documentView.setVisibility(View.GONE);
|
viewHolder.documentView.setVisibility(View.GONE);
|
||||||
viewHolder.audioView.setVisibility(View.GONE);
|
viewHolder.audioView.setVisibility(View.GONE);
|
||||||
viewHolder.webxdcView.setVisibility(View.GONE);
|
viewHolder.webxdcView.setVisibility(View.GONE);
|
||||||
viewHolder.date.setVisibility(View.GONE);
|
viewHolder.date.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
viewHolder.itemView.setOnLongClickListener(
|
viewHolder.itemView.setOnLongClickListener(view -> { itemClickListener.onMediaLongClicked(dcMsg); return true; });
|
||||||
view -> {
|
|
||||||
itemClickListener.onMediaLongClicked(dcMsg);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
viewHolder.itemView.setSelected(selected.contains(dcMsg));
|
viewHolder.itemView.setSelected(selected.contains(dcMsg));
|
||||||
|
|
||||||
viewHolder.date.setText(
|
viewHolder.date.setText(DateUtils.getBriefRelativeTimeSpanString(context, dcMsg.getTimestamp()));
|
||||||
DateUtils.getBriefRelativeTimeSpanString(context, dcMsg.getTimestamp()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -197,7 +177,6 @@ class AllMediaDocumentsAdapter extends StickyHeaderGridAdapter {
|
|||||||
|
|
||||||
interface ItemClickListener {
|
interface ItemClickListener {
|
||||||
void onMediaClicked(@NonNull DcMsg mediaRecord);
|
void onMediaClicked(@NonNull DcMsg mediaRecord);
|
||||||
|
|
||||||
void onMediaLongClicked(DcMsg mediaRecord);
|
void onMediaLongClicked(DcMsg mediaRecord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,27 +12,31 @@ import android.view.MenuItem;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.view.ActionMode;
|
import androidx.appcompat.view.ActionMode;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
import androidx.loader.app.LoaderManager;
|
import androidx.loader.app.LoaderManager;
|
||||||
import androidx.loader.content.Loader;
|
import androidx.loader.content.Loader;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.b44t.messenger.DcContext;
|
import com.b44t.messenger.DcContext;
|
||||||
import com.b44t.messenger.DcEvent;
|
import com.b44t.messenger.DcEvent;
|
||||||
import com.b44t.messenger.DcMsg;
|
import com.b44t.messenger.DcMsg;
|
||||||
import com.codewaves.stickyheadergrid.StickyHeaderGridLayoutManager;
|
import com.codewaves.stickyheadergrid.StickyHeaderGridLayoutManager;
|
||||||
import java.util.Set;
|
|
||||||
import org.thoughtcrime.securesms.components.audioplay.AudioPlaybackViewModel;
|
|
||||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader;
|
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader;
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
|
|
||||||
public class AllMediaDocumentsFragment extends MessageSelectorFragment
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class AllMediaDocumentsFragment
|
||||||
|
extends MessageSelectorFragment
|
||||||
implements LoaderManager.LoaderCallbacks<BucketedThreadMediaLoader.BucketedThreadMedia>,
|
implements LoaderManager.LoaderCallbacks<BucketedThreadMediaLoader.BucketedThreadMedia>,
|
||||||
AllMediaDocumentsAdapter.ItemClickListener {
|
AllMediaDocumentsAdapter.ItemClickListener
|
||||||
|
{
|
||||||
public static final String CHAT_ID_EXTRA = "chat_id";
|
public static final String CHAT_ID_EXTRA = "chat_id";
|
||||||
public static final String VIEWTYPE1 = "viewtype1";
|
public static final String VIEWTYPE1 = "viewtype1";
|
||||||
public static final String VIEWTYPE2 = "viewtype2";
|
public static final String VIEWTYPE2 = "viewtype2";
|
||||||
@@ -44,7 +48,7 @@ public class AllMediaDocumentsFragment extends MessageSelectorFragment
|
|||||||
private int viewtype1;
|
private int viewtype1;
|
||||||
private int viewtype2;
|
private int viewtype2;
|
||||||
|
|
||||||
protected int chatId;
|
protected int chatId;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle bundle) {
|
public void onCreate(Bundle bundle) {
|
||||||
@@ -58,23 +62,19 @@ public class AllMediaDocumentsFragment extends MessageSelectorFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
|
||||||
View view = inflater.inflate(R.layout.profile_documents_fragment, container, false);
|
View view = inflater.inflate(R.layout.profile_documents_fragment, container, false);
|
||||||
|
|
||||||
this.recyclerView = ViewUtil.findById(view, R.id.recycler_view);
|
this.recyclerView = ViewUtil.findById(view, R.id.recycler_view);
|
||||||
this.noMedia = ViewUtil.findById(view, R.id.no_documents);
|
this.noMedia = ViewUtil.findById(view, R.id.no_documents);
|
||||||
this.gridManager = new StickyHeaderGridLayoutManager(1);
|
this.gridManager = new StickyHeaderGridLayoutManager(1);
|
||||||
|
|
||||||
// add padding to avoid content hidden behind system bars
|
// add padding to avoid content hidden behind system bars
|
||||||
ViewUtil.applyWindowInsets(recyclerView, true, false, true, true);
|
ViewUtil.applyWindowInsets(recyclerView, true, false, true, true);
|
||||||
|
|
||||||
AllMediaDocumentsAdapter adapter =
|
this.recyclerView.setAdapter(new AllMediaDocumentsAdapter(getContext(),
|
||||||
new AllMediaDocumentsAdapter(
|
new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()),
|
||||||
getContext(), new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()), this);
|
this));
|
||||||
this.recyclerView.setAdapter(adapter);
|
|
||||||
adapter.setPlaybackViewModel(
|
|
||||||
new ViewModelProvider(requireActivity()).get(AudioPlaybackViewModel.class));
|
|
||||||
this.recyclerView.setLayoutManager(gridManager);
|
this.recyclerView.setLayoutManager(gridManager);
|
||||||
this.recyclerView.setHasFixedSize(true);
|
this.recyclerView.setHasFixedSize(true);
|
||||||
|
|
||||||
@@ -105,15 +105,12 @@ public class AllMediaDocumentsFragment extends MessageSelectorFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Loader<BucketedThreadMediaLoader.BucketedThreadMedia> onCreateLoader(
|
public Loader<BucketedThreadMediaLoader.BucketedThreadMedia> onCreateLoader(int i, Bundle bundle) {
|
||||||
int i, Bundle bundle) {
|
|
||||||
return new BucketedThreadMediaLoader(getContext(), chatId, viewtype1, viewtype2, 0);
|
return new BucketedThreadMediaLoader(getContext(), chatId, viewtype1, viewtype2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadFinished(
|
public void onLoadFinished(Loader<BucketedThreadMediaLoader.BucketedThreadMedia> loader, BucketedThreadMediaLoader.BucketedThreadMedia bucketedThreadMedia) {
|
||||||
Loader<BucketedThreadMediaLoader.BucketedThreadMedia> loader,
|
|
||||||
BucketedThreadMediaLoader.BucketedThreadMedia bucketedThreadMedia) {
|
|
||||||
((AllMediaDocumentsAdapter) recyclerView.getAdapter()).setMedia(bucketedThreadMedia);
|
((AllMediaDocumentsAdapter) recyclerView.getAdapter()).setMedia(bucketedThreadMedia);
|
||||||
((AllMediaDocumentsAdapter) recyclerView.getAdapter()).notifyAllSectionsDataSetChanged();
|
((AllMediaDocumentsAdapter) recyclerView.getAdapter()).notifyAllSectionsDataSetChanged();
|
||||||
|
|
||||||
@@ -121,7 +118,7 @@ public class AllMediaDocumentsFragment extends MessageSelectorFragment
|
|||||||
if (chatId == DC_CHAT_NO_CHAT) {
|
if (chatId == DC_CHAT_NO_CHAT) {
|
||||||
if (viewtype1 == DcMsg.DC_MSG_WEBXDC) {
|
if (viewtype1 == DcMsg.DC_MSG_WEBXDC) {
|
||||||
noMedia.setText(R.string.all_apps_empty_hint);
|
noMedia.setText(R.string.all_apps_empty_hint);
|
||||||
} else if (viewtype1 == DcMsg.DC_MSG_FILE) {
|
} else if (viewtype1 == DcMsg.DC_MSG_FILE){
|
||||||
noMedia.setText(R.string.all_files_empty_hint);
|
noMedia.setText(R.string.all_files_empty_hint);
|
||||||
} else {
|
} else {
|
||||||
noMedia.setText(R.string.tab_all_media_empty_hint);
|
noMedia.setText(R.string.tab_all_media_empty_hint);
|
||||||
@@ -136,8 +133,7 @@ public class AllMediaDocumentsFragment extends MessageSelectorFragment
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoaderReset(Loader<BucketedThreadMediaLoader.BucketedThreadMedia> cursorLoader) {
|
public void onLoaderReset(Loader<BucketedThreadMediaLoader.BucketedThreadMedia> cursorLoader) {
|
||||||
((AllMediaDocumentsAdapter) recyclerView.getAdapter())
|
((AllMediaDocumentsAdapter) recyclerView.getAdapter()).setMedia(new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()));
|
||||||
.setMedia(new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -168,7 +164,7 @@ public class AllMediaDocumentsFragment extends MessageSelectorFragment
|
|||||||
|
|
||||||
private void handleMediaPreviewClick(@NonNull DcMsg dcMsg) {
|
private void handleMediaPreviewClick(@NonNull DcMsg dcMsg) {
|
||||||
// audio is started by the play-button
|
// audio is started by the play-button
|
||||||
if (dcMsg.getType() == DcMsg.DC_MSG_AUDIO || dcMsg.getType() == DcMsg.DC_MSG_VOICE) {
|
if (dcMsg.getType()==DcMsg.DC_MSG_AUDIO || dcMsg.getType()==DcMsg.DC_MSG_VOICE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,8 +212,7 @@ public class AllMediaDocumentsFragment extends MessageSelectorFragment
|
|||||||
}
|
}
|
||||||
menu.findItem(R.id.menu_resend).setVisible(canResend);
|
menu.findItem(R.id.menu_resend).setVisible(canResend);
|
||||||
|
|
||||||
boolean webxdcApp =
|
boolean webxdcApp = singleSelection && messageRecords.iterator().next().getType() == DcMsg.DC_MSG_WEBXDC;
|
||||||
singleSelection && messageRecords.iterator().next().getType() == DcMsg.DC_MSG_WEBXDC;
|
|
||||||
menu.findItem(R.id.menu_add_to_home_screen).setVisible(webxdcApp);
|
menu.findItem(R.id.menu_add_to_home_screen).setVisible(webxdcApp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,26 +239,19 @@ public class AllMediaDocumentsFragment extends MessageSelectorFragment
|
|||||||
@Override
|
@Override
|
||||||
public boolean onActionItemClicked(ActionMode mode, MenuItem menuItem) {
|
public boolean onActionItemClicked(ActionMode mode, MenuItem menuItem) {
|
||||||
int itemId = menuItem.getItemId();
|
int itemId = menuItem.getItemId();
|
||||||
AudioPlaybackViewModel playbackViewModel =
|
|
||||||
new ViewModelProvider(requireActivity()).get(AudioPlaybackViewModel.class);
|
|
||||||
if (itemId == R.id.details) {
|
if (itemId == R.id.details) {
|
||||||
handleDisplayDetails(getSelectedMessageRecord(getListAdapter().getSelectedMedia()));
|
handleDisplayDetails(getSelectedMessageRecord(getListAdapter().getSelectedMedia()));
|
||||||
mode.finish();
|
mode.finish();
|
||||||
return true;
|
return true;
|
||||||
} else if (itemId == R.id.delete) {
|
} else if (itemId == R.id.delete) {
|
||||||
handleDeleteMessages(
|
handleDeleteMessages(chatId, getListAdapter().getSelectedMedia());
|
||||||
chatId,
|
|
||||||
getListAdapter().getSelectedMedia(),
|
|
||||||
playbackViewModel::stopByIds,
|
|
||||||
playbackViewModel::stopByIds);
|
|
||||||
mode.finish();
|
mode.finish();
|
||||||
return true;
|
return true;
|
||||||
} else if (itemId == R.id.share) {
|
} else if (itemId == R.id.share) {
|
||||||
handleShare(getSelectedMessageRecord(getListAdapter().getSelectedMedia()));
|
handleShare(getSelectedMessageRecord(getListAdapter().getSelectedMedia()));
|
||||||
return true;
|
return true;
|
||||||
} else if (itemId == R.id.menu_add_to_home_screen) {
|
} else if (itemId == R.id.menu_add_to_home_screen) {
|
||||||
WebxdcActivity.addToHomeScreen(
|
WebxdcActivity.addToHomeScreen(getActivity(), getSelectedMessageRecord(getListAdapter().getSelectedMedia()).getId());
|
||||||
getActivity(), getSelectedMessageRecord(getListAdapter().getSelectedMedia()).getId());
|
|
||||||
mode.finish();
|
mode.finish();
|
||||||
return true;
|
return true;
|
||||||
} else if (itemId == R.id.show_in_chat) {
|
} else if (itemId == R.id.show_in_chat) {
|
||||||
|
|||||||
@@ -5,34 +5,38 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.b44t.messenger.DcMsg;
|
import com.b44t.messenger.DcMsg;
|
||||||
import com.codewaves.stickyheadergrid.StickyHeaderGridAdapter;
|
import com.codewaves.stickyheadergrid.StickyHeaderGridAdapter;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import org.thoughtcrime.securesms.components.ThumbnailView;
|
import org.thoughtcrime.securesms.components.ThumbnailView;
|
||||||
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader.BucketedThreadMedia;
|
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader.BucketedThreadMedia;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
import org.thoughtcrime.securesms.mms.Slide;
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
class AllMediaGalleryAdapter extends StickyHeaderGridAdapter {
|
class AllMediaGalleryAdapter extends StickyHeaderGridAdapter {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final GlideRequests glideRequests;
|
private final GlideRequests glideRequests;
|
||||||
private final ItemClickListener itemClickListener;
|
private final ItemClickListener itemClickListener;
|
||||||
private final Set<DcMsg> selected;
|
private final Set<DcMsg> selected;
|
||||||
|
|
||||||
private BucketedThreadMedia media;
|
private BucketedThreadMedia media;
|
||||||
|
|
||||||
private static class ViewHolder extends StickyHeaderGridAdapter.ItemViewHolder {
|
private static class ViewHolder extends StickyHeaderGridAdapter.ItemViewHolder {
|
||||||
final ThumbnailView imageView;
|
final ThumbnailView imageView;
|
||||||
final View selectedIndicator;
|
final View selectedIndicator;
|
||||||
|
|
||||||
ViewHolder(View v) {
|
ViewHolder(View v) {
|
||||||
super(v);
|
super(v);
|
||||||
imageView = v.findViewById(R.id.image);
|
imageView = v.findViewById(R.id.image);
|
||||||
selectedIndicator = v.findViewById(R.id.selected_indicator);
|
selectedIndicator = v.findViewById(R.id.selected_indicator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,16 +50,16 @@ class AllMediaGalleryAdapter extends StickyHeaderGridAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AllMediaGalleryAdapter(
|
AllMediaGalleryAdapter(@NonNull Context context,
|
||||||
@NonNull Context context,
|
@NonNull GlideRequests glideRequests,
|
||||||
@NonNull GlideRequests glideRequests,
|
BucketedThreadMedia media,
|
||||||
BucketedThreadMedia media,
|
ItemClickListener clickListener)
|
||||||
ItemClickListener clickListener) {
|
{
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.glideRequests = glideRequests;
|
this.glideRequests = glideRequests;
|
||||||
this.media = media;
|
this.media = media;
|
||||||
this.itemClickListener = clickListener;
|
this.itemClickListener = clickListener;
|
||||||
this.selected = new HashSet<>();
|
this.selected = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMedia(BucketedThreadMedia media) {
|
public void setMedia(BucketedThreadMedia media) {
|
||||||
@@ -63,42 +67,36 @@ class AllMediaGalleryAdapter extends StickyHeaderGridAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StickyHeaderGridAdapter.HeaderViewHolder onCreateHeaderViewHolder(
|
public StickyHeaderGridAdapter.HeaderViewHolder onCreateHeaderViewHolder(ViewGroup parent, int headerType) {
|
||||||
ViewGroup parent, int headerType) {
|
return new HeaderHolder(LayoutInflater.from(context).inflate(R.layout.contact_selection_list_divider, parent, false));
|
||||||
return new HeaderHolder(
|
|
||||||
LayoutInflater.from(context)
|
|
||||||
.inflate(R.layout.contact_selection_list_divider, parent, false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemViewHolder onCreateItemViewHolder(ViewGroup parent, int itemType) {
|
public ItemViewHolder onCreateItemViewHolder(ViewGroup parent, int itemType) {
|
||||||
return new ViewHolder(
|
return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.profile_gallery_item, parent, false));
|
||||||
LayoutInflater.from(context).inflate(R.layout.profile_gallery_item, parent, false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindHeaderViewHolder(
|
public void onBindHeaderViewHolder(StickyHeaderGridAdapter.HeaderViewHolder viewHolder, int section) {
|
||||||
StickyHeaderGridAdapter.HeaderViewHolder viewHolder, int section) {
|
((HeaderHolder)viewHolder).textView.setText(media.getName(section));
|
||||||
((HeaderHolder) viewHolder).textView.setText(media.getName(section));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindItemViewHolder(ItemViewHolder viewHolder, int section, int offset) {
|
public void onBindItemViewHolder(ItemViewHolder viewHolder, int section, int offset) {
|
||||||
DcMsg mediaRecord = media.get(section, offset);
|
DcMsg mediaRecord = media.get(section, offset);
|
||||||
ThumbnailView thumbnailView = ((ViewHolder) viewHolder).imageView;
|
ThumbnailView thumbnailView = ((ViewHolder)viewHolder).imageView;
|
||||||
View selectedIndicator = ((ViewHolder) viewHolder).selectedIndicator;
|
View selectedIndicator = ((ViewHolder)viewHolder).selectedIndicator;
|
||||||
Slide slide = MediaUtil.getSlideForMsg(context, mediaRecord);
|
Slide slide = MediaUtil.getSlideForMsg(context, mediaRecord);
|
||||||
|
|
||||||
if (slide != null) {
|
if (slide != null) {
|
||||||
thumbnailView.setImageResource(glideRequests, slide);
|
thumbnailView.setImageResource(glideRequests, slide);
|
||||||
}
|
}
|
||||||
|
|
||||||
thumbnailView.setOnClickListener(view -> itemClickListener.onMediaClicked(mediaRecord));
|
thumbnailView.setOnClickListener(view -> itemClickListener.onMediaClicked(mediaRecord));
|
||||||
thumbnailView.setOnLongClickListener(
|
thumbnailView.setOnLongClickListener(view -> {
|
||||||
view -> {
|
itemClickListener.onMediaLongClicked(mediaRecord);
|
||||||
itemClickListener.onMediaLongClicked(mediaRecord);
|
return true;
|
||||||
return true;
|
});
|
||||||
});
|
|
||||||
|
|
||||||
selectedIndicator.setVisibility(selected.contains(mediaRecord) ? View.VISIBLE : View.GONE);
|
selectedIndicator.setVisibility(selected.contains(mediaRecord) ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
@@ -141,7 +139,6 @@ class AllMediaGalleryAdapter extends StickyHeaderGridAdapter {
|
|||||||
|
|
||||||
interface ItemClickListener {
|
interface ItemClickListener {
|
||||||
void onMediaClicked(@NonNull DcMsg mediaRecord);
|
void onMediaClicked(@NonNull DcMsg mediaRecord);
|
||||||
|
|
||||||
void onMediaLongClicked(DcMsg mediaRecord);
|
void onMediaLongClicked(DcMsg mediaRecord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,17 +12,19 @@ import android.view.MenuItem;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.view.ActionMode;
|
import androidx.appcompat.view.ActionMode;
|
||||||
import androidx.loader.app.LoaderManager;
|
import androidx.loader.app.LoaderManager;
|
||||||
import androidx.loader.content.Loader;
|
import androidx.loader.content.Loader;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.b44t.messenger.DcContext;
|
import com.b44t.messenger.DcContext;
|
||||||
import com.b44t.messenger.DcEvent;
|
import com.b44t.messenger.DcEvent;
|
||||||
import com.b44t.messenger.DcMsg;
|
import com.b44t.messenger.DcMsg;
|
||||||
import com.codewaves.stickyheadergrid.StickyHeaderGridLayoutManager;
|
import com.codewaves.stickyheadergrid.StickyHeaderGridLayoutManager;
|
||||||
import java.util.Set;
|
|
||||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
@@ -30,9 +32,13 @@ import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader;
|
|||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
|
|
||||||
public class AllMediaGalleryFragment extends MessageSelectorFragment
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class AllMediaGalleryFragment
|
||||||
|
extends MessageSelectorFragment
|
||||||
implements LoaderManager.LoaderCallbacks<BucketedThreadMediaLoader.BucketedThreadMedia>,
|
implements LoaderManager.LoaderCallbacks<BucketedThreadMediaLoader.BucketedThreadMedia>,
|
||||||
AllMediaGalleryAdapter.ItemClickListener {
|
AllMediaGalleryAdapter.ItemClickListener
|
||||||
|
{
|
||||||
public static final String CHAT_ID_EXTRA = "chat_id";
|
public static final String CHAT_ID_EXTRA = "chat_id";
|
||||||
|
|
||||||
protected TextView noMedia;
|
protected TextView noMedia;
|
||||||
@@ -40,7 +46,7 @@ public class AllMediaGalleryFragment extends MessageSelectorFragment
|
|||||||
private StickyHeaderGridLayoutManager gridManager;
|
private StickyHeaderGridLayoutManager gridManager;
|
||||||
private final ActionModeCallback actionModeCallback = new ActionModeCallback();
|
private final ActionModeCallback actionModeCallback = new ActionModeCallback();
|
||||||
|
|
||||||
private int chatId;
|
private int chatId;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle bundle) {
|
public void onCreate(Bundle bundle) {
|
||||||
@@ -52,23 +58,20 @@ public class AllMediaGalleryFragment extends MessageSelectorFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
|
||||||
View view = inflater.inflate(R.layout.profile_gallery_fragment, container, false);
|
View view = inflater.inflate(R.layout.profile_gallery_fragment, container, false);
|
||||||
|
|
||||||
this.recyclerView = ViewUtil.findById(view, R.id.media_grid);
|
this.recyclerView = ViewUtil.findById(view, R.id.media_grid);
|
||||||
this.noMedia = ViewUtil.findById(view, R.id.no_images);
|
this.noMedia = ViewUtil.findById(view, R.id.no_images);
|
||||||
this.gridManager = new StickyHeaderGridLayoutManager(getCols());
|
this.gridManager = new StickyHeaderGridLayoutManager(getCols());
|
||||||
|
|
||||||
// add padding to avoid content hidden behind system bars
|
// add padding to avoid content hidden behind system bars
|
||||||
ViewUtil.applyWindowInsets(recyclerView, true, false, true, true);
|
ViewUtil.applyWindowInsets(recyclerView, true, false, true, true);
|
||||||
|
|
||||||
this.recyclerView.setAdapter(
|
this.recyclerView.setAdapter(new AllMediaGalleryAdapter(getContext(),
|
||||||
new AllMediaGalleryAdapter(
|
GlideApp.with(this),
|
||||||
getContext(),
|
new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()),
|
||||||
GlideApp.with(this),
|
this));
|
||||||
new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()),
|
|
||||||
this));
|
|
||||||
this.recyclerView.setLayoutManager(gridManager);
|
this.recyclerView.setLayoutManager(gridManager);
|
||||||
this.recyclerView.setHasFixedSize(true);
|
this.recyclerView.setHasFixedSize(true);
|
||||||
|
|
||||||
@@ -91,9 +94,7 @@ public class AllMediaGalleryFragment extends MessageSelectorFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int getCols() {
|
private int getCols() {
|
||||||
return getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE
|
return getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE? 5 : 3;
|
||||||
? 5
|
|
||||||
: 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -106,16 +107,12 @@ public class AllMediaGalleryFragment extends MessageSelectorFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Loader<BucketedThreadMediaLoader.BucketedThreadMedia> onCreateLoader(
|
public Loader<BucketedThreadMediaLoader.BucketedThreadMedia> onCreateLoader(int i, Bundle bundle) {
|
||||||
int i, Bundle bundle) {
|
return new BucketedThreadMediaLoader(getContext(), chatId, DcMsg.DC_MSG_IMAGE, DcMsg.DC_MSG_GIF, DcMsg.DC_MSG_VIDEO);
|
||||||
return new BucketedThreadMediaLoader(
|
|
||||||
getContext(), chatId, DcMsg.DC_MSG_IMAGE, DcMsg.DC_MSG_GIF, DcMsg.DC_MSG_VIDEO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadFinished(
|
public void onLoadFinished(Loader<BucketedThreadMediaLoader.BucketedThreadMedia> loader, BucketedThreadMediaLoader.BucketedThreadMedia bucketedThreadMedia) {
|
||||||
Loader<BucketedThreadMediaLoader.BucketedThreadMedia> loader,
|
|
||||||
BucketedThreadMediaLoader.BucketedThreadMedia bucketedThreadMedia) {
|
|
||||||
((AllMediaGalleryAdapter) recyclerView.getAdapter()).setMedia(bucketedThreadMedia);
|
((AllMediaGalleryAdapter) recyclerView.getAdapter()).setMedia(bucketedThreadMedia);
|
||||||
((AllMediaGalleryAdapter) recyclerView.getAdapter()).notifyAllSectionsDataSetChanged();
|
((AllMediaGalleryAdapter) recyclerView.getAdapter()).notifyAllSectionsDataSetChanged();
|
||||||
|
|
||||||
@@ -128,8 +125,7 @@ public class AllMediaGalleryFragment extends MessageSelectorFragment
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoaderReset(Loader<BucketedThreadMediaLoader.BucketedThreadMedia> cursorLoader) {
|
public void onLoaderReset(Loader<BucketedThreadMediaLoader.BucketedThreadMedia> cursorLoader) {
|
||||||
((AllMediaGalleryAdapter) recyclerView.getAdapter())
|
((AllMediaGalleryAdapter) recyclerView.getAdapter()).setMedia(new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()));
|
||||||
.setMedia(new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import android.net.LinkProperties;
|
|||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AppCompatDelegate;
|
import androidx.appcompat.app.AppCompatDelegate;
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
@@ -18,19 +19,13 @@ import androidx.work.ExistingPeriodicWorkPolicy;
|
|||||||
import androidx.work.NetworkType;
|
import androidx.work.NetworkType;
|
||||||
import androidx.work.PeriodicWorkRequest;
|
import androidx.work.PeriodicWorkRequest;
|
||||||
import androidx.work.WorkManager;
|
import androidx.work.WorkManager;
|
||||||
import chat.delta.rpc.Rpc;
|
|
||||||
import chat.delta.rpc.RpcException;
|
|
||||||
import com.b44t.messenger.DcAccounts;
|
import com.b44t.messenger.DcAccounts;
|
||||||
import com.b44t.messenger.DcContext;
|
import com.b44t.messenger.DcContext;
|
||||||
import com.b44t.messenger.DcEvent;
|
import com.b44t.messenger.DcEvent;
|
||||||
import com.b44t.messenger.DcEventChannel;
|
|
||||||
import com.b44t.messenger.DcEventEmitter;
|
import com.b44t.messenger.DcEventEmitter;
|
||||||
import com.b44t.messenger.FFITransport;
|
import com.b44t.messenger.FFITransport;
|
||||||
import java.io.File;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import org.thoughtcrime.securesms.calls.CallCoordinator;
|
|
||||||
import org.thoughtcrime.securesms.connect.AccountManager;
|
import org.thoughtcrime.securesms.connect.AccountManager;
|
||||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
@@ -40,6 +35,7 @@ import org.thoughtcrime.securesms.connect.KeepAliveService;
|
|||||||
import org.thoughtcrime.securesms.connect.NetworkStateReceiver;
|
import org.thoughtcrime.securesms.connect.NetworkStateReceiver;
|
||||||
import org.thoughtcrime.securesms.crypto.DatabaseSecret;
|
import org.thoughtcrime.securesms.crypto.DatabaseSecret;
|
||||||
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider;
|
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider;
|
||||||
|
import org.thoughtcrime.securesms.geolocation.DcLocationManager;
|
||||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||||
import org.thoughtcrime.securesms.notifications.FcmReceiveService;
|
import org.thoughtcrime.securesms.notifications.FcmReceiveService;
|
||||||
import org.thoughtcrime.securesms.notifications.InChatSounds;
|
import org.thoughtcrime.securesms.notifications.InChatSounds;
|
||||||
@@ -51,26 +47,35 @@ import org.thoughtcrime.securesms.util.SignalProtocolLoggerProvider;
|
|||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.thoughtcrime.securesms.webxdc.WebxdcGarbageCollectionWorker;
|
import org.thoughtcrime.securesms.webxdc.WebxdcGarbageCollectionWorker;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
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 {
|
public class ApplicationContext extends MultiDexApplication {
|
||||||
private static final String TAG = "ApplicationContext";
|
private static final String TAG = ApplicationContext.class.getSimpleName();
|
||||||
private static final Object initLock = new Object();
|
private static final Object initLock = new Object();
|
||||||
private static volatile boolean isInitialized = false;
|
private static volatile boolean isInitialized = false;
|
||||||
|
|
||||||
private static DcAccounts dcAccounts;
|
private static DcAccounts dcAccounts;
|
||||||
private Rpc rpc;
|
private Rpc rpc;
|
||||||
private DcContext dcContext;
|
private DcContext dcContext;
|
||||||
|
|
||||||
private DcEventCenter eventCenter;
|
private DcLocationManager dcLocationManager;
|
||||||
private NotificationCenter notificationCenter;
|
private DcEventCenter eventCenter;
|
||||||
private JobManager jobManager;
|
private NotificationCenter notificationCenter;
|
||||||
|
private JobManager jobManager;
|
||||||
|
|
||||||
private int debugOnAvailableCount;
|
private int debugOnAvailableCount;
|
||||||
private int debugOnBlockedStatusChangedCount;
|
private int debugOnBlockedStatusChangedCount;
|
||||||
private int debugOnCapabilitiesChangedCount;
|
private int debugOnCapabilitiesChangedCount;
|
||||||
private int debugOnLinkPropertiesChangedCount;
|
private int debugOnLinkPropertiesChangedCount;
|
||||||
|
|
||||||
public static ApplicationContext getInstance(@NonNull Context context) {
|
public static ApplicationContext getInstance(@NonNull Context context) {
|
||||||
return (ApplicationContext) context.getApplicationContext();
|
return (ApplicationContext)context.getApplicationContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ensureInitialized() {
|
private static void ensureInitialized() {
|
||||||
@@ -87,8 +92,8 @@ public class ApplicationContext extends MultiDexApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get DcAccounts instance, waiting for initialization if necessary. This method is thread-safe
|
* Get DcAccounts instance, waiting for initialization if necessary.
|
||||||
* and will block until initialization is complete.
|
* This method is thread-safe and will block until initialization is complete.
|
||||||
*/
|
*/
|
||||||
public static DcAccounts getDcAccounts() {
|
public static DcAccounts getDcAccounts() {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
@@ -96,8 +101,8 @@ public class ApplicationContext extends MultiDexApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Rpc instance, waiting for initialization if necessary. This method is thread-safe and will
|
* Get Rpc instance, waiting for initialization if necessary.
|
||||||
* block until initialization is complete.
|
* This method is thread-safe and will block until initialization is complete.
|
||||||
*/
|
*/
|
||||||
public Rpc getRpc() {
|
public Rpc getRpc() {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
@@ -105,8 +110,8 @@ public class ApplicationContext extends MultiDexApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get DcContext instance, waiting for initialization if necessary. This method is thread-safe and
|
* Get DcContext instance, waiting for initialization if necessary.
|
||||||
* will block until initialization is complete.
|
* This method is thread-safe and will block until initialization is complete.
|
||||||
*/
|
*/
|
||||||
public DcContext getDcContext() {
|
public DcContext getDcContext() {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
@@ -115,8 +120,8 @@ public class ApplicationContext extends MultiDexApplication {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set DcContext instance. This should only be called by AccountManager when switching accounts,
|
* Set DcContext instance. This should only be called by AccountManager when switching accounts,
|
||||||
* which only happens after initial initialization is complete. This method is thread-safe but
|
* which only happens after initial initialization is complete.
|
||||||
* does NOT trigger initialization or notify waiting threads.
|
* This method is thread-safe but does NOT trigger initialization or notify waiting threads.
|
||||||
*/
|
*/
|
||||||
public void setDcContext(DcContext dcContext) {
|
public void setDcContext(DcContext dcContext) {
|
||||||
synchronized (initLock) {
|
synchronized (initLock) {
|
||||||
@@ -125,8 +130,17 @@ public class ApplicationContext extends MultiDexApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get DcEventCenter instance, waiting for initialization if necessary. This method is thread-safe
|
* Get DcLocationManager instance, waiting for initialization if necessary.
|
||||||
* and will block until initialization is complete.
|
* This method is thread-safe and will block until initialization is complete.
|
||||||
|
*/
|
||||||
|
public DcLocationManager getLocationManager() {
|
||||||
|
ensureInitialized();
|
||||||
|
return dcLocationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get DcEventCenter instance, waiting for initialization if necessary.
|
||||||
|
* This method is thread-safe and will block until initialization is complete.
|
||||||
*/
|
*/
|
||||||
public DcEventCenter getEventCenter() {
|
public DcEventCenter getEventCenter() {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
@@ -134,8 +148,8 @@ public class ApplicationContext extends MultiDexApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get NotificationCenter instance, waiting for initialization if necessary. This method is
|
* Get NotificationCenter instance, waiting for initialization if necessary.
|
||||||
* thread-safe and will block until initialization is complete.
|
* This method is thread-safe and will block until initialization is complete.
|
||||||
*/
|
*/
|
||||||
public NotificationCenter getNotificationCenter() {
|
public NotificationCenter getNotificationCenter() {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
@@ -146,30 +160,25 @@ public class ApplicationContext extends MultiDexApplication {
|
|||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
Thread.setDefaultUncaughtExceptionHandler(
|
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
|
||||||
(thread, throwable) -> {
|
StringWriter stringWriter = new StringWriter();
|
||||||
StringWriter stringWriter = new StringWriter();
|
throwable.printStackTrace(new PrintWriter(stringWriter, true));
|
||||||
throwable.printStackTrace(new PrintWriter(stringWriter, true));
|
String errorMsg = "Android " + Build.VERSION.RELEASE +":\n" + stringWriter.getBuffer().toString();
|
||||||
String errorMsg =
|
String subject = "ArcaneChat " + BuildConfig.VERSION_NAME + " Crash Report";
|
||||||
"Android " + Build.VERSION.RELEASE + ":\n" + stringWriter.getBuffer().toString();
|
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
|
||||||
errorMsg += "\n" + LogViewFragment.grabLogcat();
|
intent.setType("text/plain");
|
||||||
String subject =
|
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
|
||||||
"ArcaneChat " + BuildConfig.VERSION_NAME + "-" + BuildConfig.FLAVOR + " Crash Report";
|
intent.putExtra(android.content.Intent.EXTRA_TEXT, subject + "\n\n" + errorMsg);
|
||||||
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
|
intent.putExtra(Intent.EXTRA_EMAIL, "adb@merlinux.eu");
|
||||||
intent.setType("text/plain");
|
Intent chooser = Intent.createChooser(intent, subject);
|
||||||
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
|
chooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
intent.putExtra(android.content.Intent.EXTRA_TEXT, subject + "\n\n" + errorMsg);
|
chooser.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
||||||
intent.putExtra(Intent.EXTRA_EMAIL, "adb@merlinux.eu");
|
startActivity(chooser);
|
||||||
Intent chooser = Intent.createChooser(intent, subject);
|
|
||||||
chooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
chooser.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
|
||||||
startActivity(chooser);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ApplicationContext.this.finalize();
|
ApplicationContext.this.finalize();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// if (LeakCanary.isInAnalyzerProcess(this)) {
|
// if (LeakCanary.isInAnalyzerProcess(this)) {
|
||||||
// // This process is dedicated to LeakCanary for heap analysis.
|
// // This process is dedicated to LeakCanary for heap analysis.
|
||||||
@@ -183,107 +192,84 @@ public class ApplicationContext extends MultiDexApplication {
|
|||||||
System.loadLibrary("native-utils");
|
System.loadLibrary("native-utils");
|
||||||
|
|
||||||
// Initialize DcAccounts in background to avoid ANR during SQL migrations
|
// Initialize DcAccounts in background to avoid ANR during SQL migrations
|
||||||
Util.runOnBackground(
|
Util.runOnBackground(() -> {
|
||||||
() -> {
|
synchronized (initLock) {
|
||||||
synchronized (initLock) {
|
try {
|
||||||
try {
|
dcAccounts = new DcAccounts(new File(getFilesDir(), "accounts").getAbsolutePath());
|
||||||
DcEventChannel eventChannel = new DcEventChannel();
|
Log.i(TAG, "DcAccounts created");
|
||||||
DcEventEmitter emitter = eventChannel.getEventEmitter();
|
rpc = new Rpc(new FFITransport(dcAccounts.getJsonrpcInstance()));
|
||||||
eventCenter = new DcEventCenter(this);
|
Log.i(TAG, "Rpc created");
|
||||||
|
AccountManager.getInstance().migrateToDcAccounts(this);
|
||||||
|
|
||||||
new Thread(
|
int[] allAccounts = dcAccounts.getAll();
|
||||||
() -> {
|
Log.i(TAG, "Number of profiles: " + allAccounts.length);
|
||||||
Log.i(TAG, "Starting event loop");
|
for (int accountId : allAccounts) {
|
||||||
while (true) {
|
DcContext ac = dcAccounts.getAccount(accountId);
|
||||||
DcEvent event = emitter.getNextEvent();
|
if (!ac.isOpen()) {
|
||||||
if (event == null) {
|
try {
|
||||||
break;
|
DatabaseSecret secret = DatabaseSecretProvider.getOrCreateDatabaseSecret(this, accountId);
|
||||||
}
|
boolean res = ac.open(secret.asString());
|
||||||
if (isInitialized) {
|
if (res) Log.i(TAG, "Successfully opened account " + accountId + ", path: " + ac.getBlobdir());
|
||||||
eventCenter.handleEvent(event);
|
else Log.e(TAG, "Error opening account " + accountId + ", path: " + ac.getBlobdir());
|
||||||
} else {
|
} catch (Exception e) {
|
||||||
// not fully initialized, only handle logging events,
|
Log.e(TAG, "Failed to open account " + accountId + ", path: " + ac.getBlobdir() + ": " + e);
|
||||||
// ex. account migrations during DcAccounts initialization
|
e.printStackTrace();
|
||||||
eventCenter.handleLogging(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log.i("DeltaChat", "shutting down event handler");
|
|
||||||
},
|
|
||||||
"eventThread")
|
|
||||||
.start();
|
|
||||||
|
|
||||||
dcAccounts =
|
|
||||||
new DcAccounts(
|
|
||||||
new File(getFilesDir(), "accounts").getAbsolutePath(), eventChannel);
|
|
||||||
Log.i(TAG, "DcAccounts created");
|
|
||||||
rpc = new Rpc(new FFITransport(dcAccounts.getJsonrpcInstance()));
|
|
||||||
Log.i(TAG, "Rpc created");
|
|
||||||
AccountManager.getInstance().migrateToDcAccounts(this, dcAccounts);
|
|
||||||
|
|
||||||
int[] allAccounts = dcAccounts.getAll();
|
|
||||||
Log.i(TAG, "Number of profiles: " + allAccounts.length);
|
|
||||||
for (int accountId : allAccounts) {
|
|
||||||
DcContext ac = dcAccounts.getAccount(accountId);
|
|
||||||
if (!ac.isOpen()) {
|
|
||||||
try {
|
|
||||||
DatabaseSecret secret =
|
|
||||||
DatabaseSecretProvider.getOrCreateDatabaseSecret(this, accountId);
|
|
||||||
boolean res = ac.open(secret.asString());
|
|
||||||
if (res)
|
|
||||||
Log.i(
|
|
||||||
TAG,
|
|
||||||
"Successfully opened account "
|
|
||||||
+ accountId
|
|
||||||
+ ", path: "
|
|
||||||
+ ac.getBlobdir());
|
|
||||||
else
|
|
||||||
Log.e(
|
|
||||||
TAG, "Error opening account " + accountId + ", path: " + ac.getBlobdir());
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(
|
|
||||||
TAG,
|
|
||||||
"Failed to open account "
|
|
||||||
+ accountId
|
|
||||||
+ ", path: "
|
|
||||||
+ ac.getBlobdir()
|
|
||||||
+ ": "
|
|
||||||
+ e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2025-12-16: The setting was removed.
|
|
||||||
// Revert it to the default if it was changed in the past.
|
|
||||||
ac.setConfigInt("webxdc_realtime_enabled", 1);
|
|
||||||
}
|
}
|
||||||
if (allAccounts.length == 0) {
|
}
|
||||||
try {
|
|
||||||
rpc.addAccount();
|
|
||||||
} catch (RpcException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dcContext = dcAccounts.getSelectedAccount();
|
|
||||||
notificationCenter = new NotificationCenter(this);
|
|
||||||
|
|
||||||
isInitialized = true;
|
// 2025-12-16: The setting was removed.
|
||||||
initLock.notifyAll();
|
// Revert it to the default if it was changed in the past.
|
||||||
Log.i(TAG, "DcAccounts initialization complete");
|
ac.setConfigInt("webxdc_realtime_enabled", 1);
|
||||||
|
|
||||||
// set translations before starting I/O to avoid sending untranslated MDNs (issue
|
// 2025-11-12: this is needed until core starts ignoring "delete_server_after" for chatmail
|
||||||
// #2288)
|
if (ac.isChatmail()) {
|
||||||
DcHelper.setStockTranslations(this);
|
ac.setConfig("delete_server_after", null); // reset
|
||||||
|
|
||||||
dcAccounts.startIo();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Fatal error during DcAccounts initialization", e);
|
|
||||||
// Mark as initialized even on error to avoid deadlock
|
|
||||||
isInitialized = true;
|
|
||||||
initLock.notifyAll();
|
|
||||||
throw new RuntimeException("Failed to initialize DcAccounts", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
if (allAccounts.length == 0) {
|
||||||
|
try {
|
||||||
|
rpc.addAccount();
|
||||||
|
} catch (RpcException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dcContext = dcAccounts.getSelectedAccount();
|
||||||
|
notificationCenter = new NotificationCenter(this);
|
||||||
|
eventCenter = new DcEventCenter(this);
|
||||||
|
dcLocationManager = new DcLocationManager(this, dcContext);
|
||||||
|
|
||||||
|
// Mark as initialized before starting threads that depend on it
|
||||||
|
isInitialized = true;
|
||||||
|
initLock.notifyAll();
|
||||||
|
Log.i(TAG, "DcAccounts initialization complete");
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
Log.i(TAG, "Starting event loop");
|
||||||
|
DcEventEmitter emitter = dcAccounts.getEventEmitter();
|
||||||
|
Log.i(TAG, "DcEventEmitter obtained");
|
||||||
|
while (true) {
|
||||||
|
DcEvent event = emitter.getNextEvent();
|
||||||
|
if (event==null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
eventCenter.handleEvent(event);
|
||||||
|
}
|
||||||
|
Log.i("DeltaChat", "shutting down event handler");
|
||||||
|
}, "eventThread").start();
|
||||||
|
|
||||||
|
// set translations before starting I/O to avoid sending untranslated MDNs (issue #2288)
|
||||||
|
DcHelper.setStockTranslations(this);
|
||||||
|
|
||||||
|
dcAccounts.startIo();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Fatal error during DcAccounts initialization", e);
|
||||||
|
// Mark as initialized even on error to avoid deadlock
|
||||||
|
isInitialized = true;
|
||||||
|
initLock.notifyAll();
|
||||||
|
throw new RuntimeException("Failed to initialize DcAccounts", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// October-2025 migration: delete deprecated "permanent channel" id
|
// October-2025 migration: delete deprecated "permanent channel" id
|
||||||
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
|
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
|
||||||
@@ -294,58 +280,33 @@ public class ApplicationContext extends MultiDexApplication {
|
|||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
ConnectivityManager connectivityManager =
|
ConnectivityManager connectivityManager =
|
||||||
(ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
|
(ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
connectivityManager.registerDefaultNetworkCallback(
|
connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() {
|
||||||
new ConnectivityManager.NetworkCallback() {
|
@Override
|
||||||
@Override
|
public void onAvailable(@NonNull android.net.Network network) {
|
||||||
public void onAvailable(@NonNull android.net.Network network) {
|
Log.i("DeltaChat", "++++++++++++++++++ NetworkCallback.onAvailable() #" + debugOnAvailableCount++);
|
||||||
Log.i(
|
getDcAccounts().maybeNetwork();
|
||||||
"DeltaChat",
|
}
|
||||||
"++++++++++++++++++ NetworkCallback.onAvailable() #" + debugOnAvailableCount++);
|
|
||||||
// onBlockedStatusChanged is only available on API 29+
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
|
||||||
getDcAccounts().maybeNetwork();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockedStatusChanged(
|
public void onBlockedStatusChanged(@NonNull android.net.Network network, boolean blocked) {
|
||||||
@NonNull android.net.Network network, boolean blocked) {
|
Log.i("DeltaChat", "++++++++++++++++++ NetworkCallback.onBlockedStatusChanged() #" + debugOnBlockedStatusChangedCount++);
|
||||||
Log.i(
|
}
|
||||||
"DeltaChat",
|
|
||||||
"++++++++++++++++++ NetworkCallback.onBlockedStatusChanged("
|
|
||||||
+ blocked
|
|
||||||
+ ") #"
|
|
||||||
+ debugOnBlockedStatusChangedCount++);
|
|
||||||
if (!blocked) {
|
|
||||||
getDcAccounts().maybeNetwork();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCapabilitiesChanged(
|
public void onCapabilitiesChanged(@NonNull android.net.Network network, NetworkCapabilities networkCapabilities) {
|
||||||
@NonNull android.net.Network network, NetworkCapabilities networkCapabilities) {
|
// usually called after onAvailable(), so a maybeNetwork seems contraproductive
|
||||||
// usually called after onAvailable(), so a maybeNetwork seems contraproductive
|
Log.i("DeltaChat", "++++++++++++++++++ NetworkCallback.onCapabilitiesChanged() #" + debugOnCapabilitiesChangedCount++);
|
||||||
Log.i(
|
}
|
||||||
"DeltaChat",
|
|
||||||
"++++++++++++++++++ NetworkCallback.onCapabilitiesChanged() #"
|
|
||||||
+ debugOnCapabilitiesChangedCount++);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLinkPropertiesChanged(
|
public void onLinkPropertiesChanged(@NonNull android.net.Network network, LinkProperties linkProperties) {
|
||||||
@NonNull android.net.Network network, LinkProperties linkProperties) {
|
Log.i("DeltaChat", "++++++++++++++++++ NetworkCallback.onLinkPropertiesChanged() #" + debugOnLinkPropertiesChangedCount++);
|
||||||
Log.i(
|
}
|
||||||
"DeltaChat",
|
});
|
||||||
"++++++++++++++++++ NetworkCallback.onLinkPropertiesChanged() #"
|
|
||||||
+ debugOnLinkPropertiesChangedCount++);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} // no else: use old method for debugging
|
} // no else: use old method for debugging
|
||||||
BroadcastReceiver networkStateReceiver = new NetworkStateReceiver();
|
BroadcastReceiver networkStateReceiver = new NetworkStateReceiver();
|
||||||
registerReceiver(
|
registerReceiver(networkStateReceiver, new IntentFilter(android.net.ConnectivityManager.CONNECTIVITY_ACTION));
|
||||||
networkStateReceiver,
|
|
||||||
new IntentFilter(android.net.ConnectivityManager.CONNECTIVITY_ACTION));
|
|
||||||
|
|
||||||
KeepAliveService.maybeStartSelf(this);
|
KeepAliveService.maybeStartSelf(this);
|
||||||
|
|
||||||
@@ -353,23 +314,16 @@ public class ApplicationContext extends MultiDexApplication {
|
|||||||
initializeJobManager();
|
initializeJobManager();
|
||||||
InChatSounds.getInstance(this);
|
InChatSounds.getInstance(this);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
EglUtils.getEglBase();
|
|
||||||
CallCoordinator.getInstance(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicTheme.setDefaultDayNightMode(this);
|
DynamicTheme.setDefaultDayNightMode(this);
|
||||||
|
|
||||||
IntentFilter filter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
|
IntentFilter filter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
|
||||||
registerReceiver(
|
registerReceiver(new BroadcastReceiver() {
|
||||||
new BroadcastReceiver() {
|
@Override
|
||||||
@Override
|
public void onReceive(Context context, Intent intent) {
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
Util.localeChanged();
|
Util.localeChanged();
|
||||||
DcHelper.setStockTranslations(context);
|
DcHelper.setStockTranslations(context);
|
||||||
}
|
}
|
||||||
},
|
}, filter);
|
||||||
filter);
|
|
||||||
|
|
||||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
|
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
|
||||||
|
|
||||||
@@ -380,34 +334,31 @@ public class ApplicationContext extends MultiDexApplication {
|
|||||||
// MAYBE TODO: i think the ApplicationContext is also created
|
// MAYBE TODO: i think the ApplicationContext is also created
|
||||||
// when the app is stated by FetchWorker timeouts.
|
// when the app is stated by FetchWorker timeouts.
|
||||||
// in this case, the normal threads shall not be started.
|
// in this case, the normal threads shall not be started.
|
||||||
Constraints constraints =
|
Constraints constraints = new Constraints.Builder()
|
||||||
new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();
|
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||||
PeriodicWorkRequest fetchWorkRequest =
|
.build();
|
||||||
new PeriodicWorkRequest.Builder(
|
PeriodicWorkRequest fetchWorkRequest = new PeriodicWorkRequest.Builder(
|
||||||
FetchWorker.class,
|
FetchWorker.class,
|
||||||
PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS, // usually 15 minutes
|
PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS, // usually 15 minutes
|
||||||
TimeUnit.MILLISECONDS,
|
TimeUnit.MILLISECONDS,
|
||||||
PeriodicWorkRequest
|
PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS, // the start may be preferred by up to 5 minutes, so we run every 10-15 minutes
|
||||||
.MIN_PERIODIC_FLEX_MILLIS, // the start may be preferred by up to 5 minutes,
|
TimeUnit.MILLISECONDS)
|
||||||
// so we run every 10-15 minutes
|
|
||||||
TimeUnit.MILLISECONDS)
|
|
||||||
.setConstraints(constraints)
|
.setConstraints(constraints)
|
||||||
.build();
|
.build();
|
||||||
WorkManager.getInstance(this)
|
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
|
||||||
.enqueueUniquePeriodicWork(
|
"FetchWorker",
|
||||||
"FetchWorker", ExistingPeriodicWorkPolicy.KEEP, fetchWorkRequest);
|
ExistingPeriodicWorkPolicy.KEEP,
|
||||||
|
fetchWorkRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
PeriodicWorkRequest webxdcGarbageCollectionRequest =
|
PeriodicWorkRequest webxdcGarbageCollectionRequest = new PeriodicWorkRequest.Builder(
|
||||||
new PeriodicWorkRequest.Builder(
|
WebxdcGarbageCollectionWorker.class,
|
||||||
WebxdcGarbageCollectionWorker.class,
|
PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,
|
||||||
PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,
|
TimeUnit.MILLISECONDS,
|
||||||
TimeUnit.MILLISECONDS,
|
PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS,
|
||||||
PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS,
|
TimeUnit.MILLISECONDS)
|
||||||
TimeUnit.MILLISECONDS)
|
|
||||||
.build();
|
.build();
|
||||||
WorkManager.getInstance(this)
|
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
|
||||||
.enqueueUniquePeriodicWork(
|
|
||||||
"WebxdcGarbageCollectionWorker",
|
"WebxdcGarbageCollectionWorker",
|
||||||
ExistingPeriodicWorkPolicy.KEEP,
|
ExistingPeriodicWorkPolicy.KEEP,
|
||||||
webxdcGarbageCollectionRequest);
|
webxdcGarbageCollectionRequest);
|
||||||
@@ -415,14 +366,6 @@ public class ApplicationContext extends MultiDexApplication {
|
|||||||
Log.i("DeltaChat", "+++++++++++ ApplicationContext.onCreate() finished ++++++++++");
|
Log.i("DeltaChat", "+++++++++++ ApplicationContext.onCreate() finished ++++++++++");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTerminate() {
|
|
||||||
super.onTerminate();
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
EglUtils.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public JobManager getJobManager() {
|
public JobManager getJobManager() {
|
||||||
return jobManager;
|
return jobManager;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ import android.content.Intent;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts;
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
@@ -31,17 +30,19 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.fragment.app.FragmentTransaction;
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
import com.b44t.messenger.DcContext;
|
import com.b44t.messenger.DcContext;
|
||||||
import com.b44t.messenger.DcEvent;
|
import com.b44t.messenger.DcEvent;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
import org.thoughtcrime.securesms.preferences.AdvancedPreferenceFragment;
|
import org.thoughtcrime.securesms.preferences.AdvancedPreferenceFragment;
|
||||||
import org.thoughtcrime.securesms.preferences.AppearancePreferenceFragment;
|
import org.thoughtcrime.securesms.preferences.AppearancePreferenceFragment;
|
||||||
import org.thoughtcrime.securesms.preferences.ChatsPreferenceFragment;
|
import org.thoughtcrime.securesms.preferences.ChatsPreferenceFragment;
|
||||||
|
import org.thoughtcrime.securesms.preferences.PrivacyPreferenceFragment;
|
||||||
import org.thoughtcrime.securesms.preferences.CorrectedPreferenceFragment;
|
import org.thoughtcrime.securesms.preferences.CorrectedPreferenceFragment;
|
||||||
import org.thoughtcrime.securesms.preferences.NotificationsPreferenceFragment;
|
import org.thoughtcrime.securesms.preferences.NotificationsPreferenceFragment;
|
||||||
import org.thoughtcrime.securesms.preferences.PrivacyPreferenceFragment;
|
|
||||||
import org.thoughtcrime.securesms.preferences.widgets.ProfilePreference;
|
import org.thoughtcrime.securesms.preferences.widgets.ProfilePreference;
|
||||||
import org.thoughtcrime.securesms.qr.BackupTransferActivity;
|
import org.thoughtcrime.securesms.qr.BackupTransferActivity;
|
||||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||||
@@ -54,22 +55,24 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
|||||||
* The Activity for application preference display and management.
|
* The Activity for application preference display and management.
|
||||||
*
|
*
|
||||||
* @author Moxie Marlinspike
|
* @author Moxie Marlinspike
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarActivity
|
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
|
||||||
private static final String PREFERENCE_CATEGORY_PROFILE = "preference_category_profile";
|
|
||||||
private static final String PREFERENCE_CATEGORY_NOTIFICATIONS =
|
|
||||||
"preference_category_notifications";
|
|
||||||
private static final String PREFERENCE_CATEGORY_APPEARANCE = "preference_category_appearance";
|
|
||||||
private static final String PREFERENCE_CATEGORY_CHATS = "preference_category_chats";
|
|
||||||
private static final String PREFERENCE_CATEGORY_PRIVACY = "preference_category_privacy";
|
|
||||||
private static final String PREFERENCE_CATEGORY_MULTIDEVICE = "preference_category_multidevice";
|
|
||||||
private static final String PREFERENCE_CATEGORY_ADVANCED = "preference_category_advanced";
|
|
||||||
private static final String PREFERENCE_CATEGORY_CONNECTIVITY = "preference_category_connectivity";
|
|
||||||
private static final String PREFERENCE_CATEGORY_DONATE = "preference_category_donate";
|
|
||||||
private static final String PREFERENCE_CATEGORY_HELP = "preference_category_help";
|
|
||||||
|
|
||||||
public static final int REQUEST_CODE_SET_BACKGROUND = 11;
|
public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarActivity
|
||||||
|
implements SharedPreferences.OnSharedPreferenceChangeListener
|
||||||
|
{
|
||||||
|
private static final String PREFERENCE_CATEGORY_PROFILE = "preference_category_profile";
|
||||||
|
private static final String PREFERENCE_CATEGORY_NOTIFICATIONS = "preference_category_notifications";
|
||||||
|
private static final String PREFERENCE_CATEGORY_APPEARANCE = "preference_category_appearance";
|
||||||
|
private static final String PREFERENCE_CATEGORY_CHATS = "preference_category_chats";
|
||||||
|
private static final String PREFERENCE_CATEGORY_PRIVACY = "preference_category_privacy";
|
||||||
|
private static final String PREFERENCE_CATEGORY_MULTIDEVICE = "preference_category_multidevice";
|
||||||
|
private static final String PREFERENCE_CATEGORY_ADVANCED = "preference_category_advanced";
|
||||||
|
private static final String PREFERENCE_CATEGORY_CONNECTIVITY = "preference_category_connectivity";
|
||||||
|
private static final String PREFERENCE_CATEGORY_DONATE = "preference_category_donate";
|
||||||
|
private static final String PREFERENCE_CATEGORY_HELP = "preference_category_help";
|
||||||
|
|
||||||
|
public static final int REQUEST_CODE_SET_BACKGROUND = 11;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle icicle, boolean ready) {
|
protected void onCreate(Bundle icicle, boolean ready) {
|
||||||
@@ -86,6 +89,18 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||||
|
{
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if (resultCode == RESULT_OK && requestCode == ScreenLockUtil.REQUEST_CODE_CONFIRM_CREDENTIALS) {
|
||||||
|
showBackupProvider();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment);
|
||||||
|
fragment.onActivityResult(requestCode, resultCode, data);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onSupportNavigateUp() {
|
public boolean onSupportNavigateUp() {
|
||||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||||
@@ -110,51 +125,34 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
|||||||
|
|
||||||
public void showBackupProvider() {
|
public void showBackupProvider() {
|
||||||
Intent intent = new Intent(this, BackupTransferActivity.class);
|
Intent intent = new Intent(this, BackupTransferActivity.class);
|
||||||
intent.putExtra(
|
intent.putExtra(BackupTransferActivity.TRANSFER_MODE, BackupTransferActivity.TransferMode.SENDER_SHOW_QR.getInt());
|
||||||
BackupTransferActivity.TRANSFER_MODE,
|
|
||||||
BackupTransferActivity.TransferMode.SENDER_SHOW_QR.getInt());
|
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
overridePendingTransition(
|
overridePendingTransition(0, 0); // let the activity appear in the same way as the other pages (which are mostly fragments)
|
||||||
0, 0); // let the activity appear in the same way as the other pages (which are mostly
|
|
||||||
// fragments)
|
|
||||||
finishAffinity(); // see comment (**2) in BackupTransferActivity.doFinish()
|
finishAffinity(); // see comment (**2) in BackupTransferActivity.doFinish()
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ApplicationPreferenceFragment extends CorrectedPreferenceFragment
|
public static class ApplicationPreferenceFragment extends CorrectedPreferenceFragment implements DcEventCenter.DcEventDelegate {
|
||||||
implements DcEventCenter.DcEventDelegate {
|
|
||||||
private ActivityResultLauncher<Intent> screenLockLauncher;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle icicle) {
|
public void onCreate(Bundle icicle) {
|
||||||
super.onCreate(icicle);
|
super.onCreate(icicle);
|
||||||
|
|
||||||
screenLockLauncher =
|
|
||||||
registerForActivityResult(
|
|
||||||
new ActivityResultContracts.StartActivityForResult(),
|
|
||||||
result -> {
|
|
||||||
if (result.getResultCode() == RESULT_OK) {
|
|
||||||
((ApplicationPreferencesActivity) getActivity()).showBackupProvider();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.findPreference(PREFERENCE_CATEGORY_PROFILE)
|
this.findPreference(PREFERENCE_CATEGORY_PROFILE)
|
||||||
.setOnPreferenceClickListener(new ProfileClickListener());
|
.setOnPreferenceClickListener(new ProfileClickListener());
|
||||||
this.findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS)
|
this.findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS)
|
||||||
.setOnPreferenceClickListener(
|
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_NOTIFICATIONS));
|
||||||
new CategoryClickListener(PREFERENCE_CATEGORY_NOTIFICATIONS));
|
|
||||||
this.findPreference(PREFERENCE_CATEGORY_CONNECTIVITY)
|
this.findPreference(PREFERENCE_CATEGORY_CONNECTIVITY)
|
||||||
.setOnPreferenceClickListener(
|
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_CONNECTIVITY));
|
||||||
new CategoryClickListener(PREFERENCE_CATEGORY_CONNECTIVITY));
|
|
||||||
this.findPreference(PREFERENCE_CATEGORY_APPEARANCE)
|
this.findPreference(PREFERENCE_CATEGORY_APPEARANCE)
|
||||||
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_APPEARANCE));
|
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_APPEARANCE));
|
||||||
this.findPreference(PREFERENCE_CATEGORY_CHATS)
|
this.findPreference(PREFERENCE_CATEGORY_CHATS)
|
||||||
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_CHATS));
|
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_CHATS));
|
||||||
this.findPreference(PREFERENCE_CATEGORY_PRIVACY)
|
this.findPreference(PREFERENCE_CATEGORY_PRIVACY)
|
||||||
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_PRIVACY));
|
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_PRIVACY));
|
||||||
this.findPreference(PREFERENCE_CATEGORY_MULTIDEVICE)
|
this.findPreference(PREFERENCE_CATEGORY_MULTIDEVICE)
|
||||||
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_MULTIDEVICE));
|
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_MULTIDEVICE));
|
||||||
this.findPreference(PREFERENCE_CATEGORY_ADVANCED)
|
this.findPreference(PREFERENCE_CATEGORY_ADVANCED)
|
||||||
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_ADVANCED));
|
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_ADVANCED));
|
||||||
|
|
||||||
this.findPreference(PREFERENCE_CATEGORY_DONATE)
|
this.findPreference(PREFERENCE_CATEGORY_DONATE)
|
||||||
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_DONATE));
|
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_DONATE));
|
||||||
@@ -162,8 +160,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
|||||||
this.findPreference(PREFERENCE_CATEGORY_HELP)
|
this.findPreference(PREFERENCE_CATEGORY_HELP)
|
||||||
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_HELP));
|
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_HELP));
|
||||||
|
|
||||||
DcHelper.getEventCenter(getActivity())
|
DcHelper.getEventCenter(getActivity()).addObserver(DcContext.DC_EVENT_CONNECTIVITY_CHANGED, this);
|
||||||
.addObserver(DcContext.DC_EVENT_CONNECTIVITY_CHANGED, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -175,9 +172,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
((ApplicationPreferencesActivity) getActivity())
|
((ApplicationPreferencesActivity) getActivity()).getSupportActionBar().setTitle(R.string.menu_settings);
|
||||||
.getSupportActionBar()
|
|
||||||
.setTitle(R.string.menu_settings);
|
|
||||||
setCategorySummaries();
|
setCategorySummaries();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,14 +186,12 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
|||||||
public void handleEvent(@NonNull DcEvent event) {
|
public void handleEvent(@NonNull DcEvent event) {
|
||||||
if (event.getId() == DcContext.DC_EVENT_CONNECTIVITY_CHANGED) {
|
if (event.getId() == DcContext.DC_EVENT_CONNECTIVITY_CHANGED) {
|
||||||
this.findPreference(PREFERENCE_CATEGORY_CONNECTIVITY)
|
this.findPreference(PREFERENCE_CATEGORY_CONNECTIVITY)
|
||||||
.setSummary(
|
.setSummary(DcHelper.getConnectivitySummary(getActivity(), getString(R.string.connectivity_connected)));
|
||||||
DcHelper.getConnectivitySummary(
|
|
||||||
getActivity(), getString(R.string.connectivity_connected)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCategorySummaries() {
|
private void setCategorySummaries() {
|
||||||
((ProfilePreference) this.findPreference(PREFERENCE_CATEGORY_PROFILE)).refresh();
|
((ProfilePreference)this.findPreference(PREFERENCE_CATEGORY_PROFILE)).refresh();
|
||||||
|
|
||||||
this.findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS)
|
this.findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS)
|
||||||
.setSummary(NotificationsPreferenceFragment.getSummary(getActivity()));
|
.setSummary(NotificationsPreferenceFragment.getSummary(getActivity()));
|
||||||
@@ -209,9 +202,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
|||||||
this.findPreference(PREFERENCE_CATEGORY_PRIVACY)
|
this.findPreference(PREFERENCE_CATEGORY_PRIVACY)
|
||||||
.setSummary(PrivacyPreferenceFragment.getSummary(getActivity()));
|
.setSummary(PrivacyPreferenceFragment.getSummary(getActivity()));
|
||||||
this.findPreference(PREFERENCE_CATEGORY_CONNECTIVITY)
|
this.findPreference(PREFERENCE_CATEGORY_CONNECTIVITY)
|
||||||
.setSummary(
|
.setSummary(DcHelper.getConnectivitySummary(getActivity(), getString(R.string.connectivity_connected)));
|
||||||
DcHelper.getConnectivitySummary(
|
|
||||||
getActivity(), getString(R.string.connectivity_connected)));
|
|
||||||
this.findPreference(PREFERENCE_CATEGORY_HELP)
|
this.findPreference(PREFERENCE_CATEGORY_HELP)
|
||||||
.setSummary(AdvancedPreferenceFragment.getVersion(getActivity()));
|
.setSummary(AdvancedPreferenceFragment.getVersion(getActivity()));
|
||||||
}
|
}
|
||||||
@@ -228,76 +219,63 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
|||||||
Fragment fragment = null;
|
Fragment fragment = null;
|
||||||
|
|
||||||
switch (category) {
|
switch (category) {
|
||||||
case PREFERENCE_CATEGORY_NOTIFICATIONS:
|
case PREFERENCE_CATEGORY_NOTIFICATIONS:
|
||||||
NotificationManagerCompat notificationManager =
|
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getActivity());
|
||||||
NotificationManagerCompat.from(getActivity());
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU || notificationManager.areNotificationsEnabled()) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU
|
fragment = new NotificationsPreferenceFragment();
|
||||||
|| notificationManager.areNotificationsEnabled()) {
|
} else {
|
||||||
fragment = new NotificationsPreferenceFragment();
|
new AlertDialog.Builder(getActivity())
|
||||||
} else {
|
.setTitle(R.string.notifications_disabled)
|
||||||
new AlertDialog.Builder(getActivity())
|
.setMessage(R.string.perm_explain_access_to_notifications_denied)
|
||||||
.setTitle(R.string.notifications_disabled)
|
.setPositiveButton(R.string.perm_continue, (dialog, which) -> getActivity().startActivity(Permissions.getApplicationSettingsIntent(getActivity())))
|
||||||
.setMessage(R.string.perm_explain_access_to_notifications_denied)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton(
|
.show();
|
||||||
R.string.perm_continue,
|
}
|
||||||
(dialog, which) ->
|
break;
|
||||||
getActivity()
|
case PREFERENCE_CATEGORY_CONNECTIVITY:
|
||||||
.startActivity(
|
startActivity(new Intent(getActivity(), ConnectivityActivity.class));
|
||||||
Permissions.getApplicationSettingsIntent(getActivity())))
|
break;
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
case PREFERENCE_CATEGORY_APPEARANCE:
|
||||||
.show();
|
fragment = new AppearancePreferenceFragment();
|
||||||
}
|
break;
|
||||||
break;
|
case PREFERENCE_CATEGORY_CHATS:
|
||||||
case PREFERENCE_CATEGORY_CONNECTIVITY:
|
fragment = new ChatsPreferenceFragment();
|
||||||
startActivity(new Intent(getActivity(), ConnectivityActivity.class));
|
break;
|
||||||
break;
|
case PREFERENCE_CATEGORY_PRIVACY:
|
||||||
case PREFERENCE_CATEGORY_APPEARANCE:
|
fragment = new PrivacyPreferenceFragment();
|
||||||
fragment = new AppearancePreferenceFragment();
|
break;
|
||||||
break;
|
case PREFERENCE_CATEGORY_MULTIDEVICE:
|
||||||
case PREFERENCE_CATEGORY_CHATS:
|
if (!ScreenLockUtil.applyScreenLock(getActivity(), getString(R.string.multidevice_title),
|
||||||
fragment = new ChatsPreferenceFragment();
|
getString(R.string.multidevice_this_creates_a_qr_code) + "\n\n" + getString(R.string.enter_system_secret_to_continue),
|
||||||
break;
|
ScreenLockUtil.REQUEST_CODE_CONFIRM_CREDENTIALS)) {
|
||||||
case PREFERENCE_CATEGORY_PRIVACY:
|
new AlertDialog.Builder(getActivity())
|
||||||
fragment = new PrivacyPreferenceFragment();
|
.setTitle(R.string.multidevice_title)
|
||||||
break;
|
.setMessage(R.string.multidevice_this_creates_a_qr_code)
|
||||||
case PREFERENCE_CATEGORY_MULTIDEVICE:
|
.setPositiveButton(R.string.perm_continue,
|
||||||
if (!ScreenLockUtil.applyScreenLock(
|
(dialog, which) -> ((ApplicationPreferencesActivity)getActivity()).showBackupProvider())
|
||||||
getActivity(),
|
.setNegativeButton(R.string.cancel, null)
|
||||||
getString(R.string.multidevice_title),
|
.show();
|
||||||
getString(R.string.multidevice_this_creates_a_qr_code)
|
;
|
||||||
+ "\n\n"
|
}
|
||||||
+ getString(R.string.enter_system_secret_to_continue),
|
break;
|
||||||
screenLockLauncher)) {
|
case PREFERENCE_CATEGORY_ADVANCED:
|
||||||
new AlertDialog.Builder(getActivity())
|
fragment = new AdvancedPreferenceFragment();
|
||||||
.setTitle(R.string.multidevice_title)
|
break;
|
||||||
.setMessage(R.string.multidevice_this_creates_a_qr_code)
|
case PREFERENCE_CATEGORY_DONATE:
|
||||||
.setPositiveButton(
|
IntentUtils.showInBrowser(requireActivity(), "https://arcanechat.me/#contribute");
|
||||||
R.string.perm_continue,
|
break;
|
||||||
(dialog, which) ->
|
case PREFERENCE_CATEGORY_HELP:
|
||||||
((ApplicationPreferencesActivity) getActivity()).showBackupProvider())
|
startActivity(new Intent(getActivity(), LocalHelpActivity.class));
|
||||||
.setNegativeButton(R.string.cancel, null)
|
break;
|
||||||
.show();
|
default:
|
||||||
;
|
throw new AssertionError();
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PREFERENCE_CATEGORY_ADVANCED:
|
|
||||||
fragment = new AdvancedPreferenceFragment();
|
|
||||||
break;
|
|
||||||
case PREFERENCE_CATEGORY_DONATE:
|
|
||||||
IntentUtils.showInBrowser(requireActivity(), "https://arcanechat.me/#contribute");
|
|
||||||
break;
|
|
||||||
case PREFERENCE_CATEGORY_HELP:
|
|
||||||
startActivity(new Intent(getActivity(), LocalHelpActivity.class));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fragment != null) {
|
if (fragment != null) {
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
|
|
||||||
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
|
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
|
||||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||||
fragmentTransaction.replace(R.id.fragment, fragment);
|
fragmentTransaction.replace(R.id.fragment, fragment);
|
||||||
fragmentTransaction.addToBackStack(null);
|
fragmentTransaction.addToBackStack(null);
|
||||||
@@ -319,8 +297,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
|
||||||
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package org.thoughtcrime.securesms;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
|
|
||||||
public class AttachContactActivity extends ContactSelectionActivity {
|
public class AttachContactActivity extends ContactSelectionActivity {
|
||||||
|
|
||||||
public static final String CONTACT_ID_EXTRA = "contact_id_extra";
|
public static final String CONTACT_ID_EXTRA = "contact_id_extra";
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
import androidx.activity.EdgeToEdge;
|
||||||
import androidx.annotation.IdRes;
|
import androidx.annotation.IdRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -13,14 +15,17 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.core.view.WindowCompat;
|
import androidx.core.view.WindowCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||||
import org.thoughtcrime.securesms.util.Prefs;
|
import org.thoughtcrime.securesms.util.Prefs;
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
|
||||||
public abstract class BaseActionBarActivity extends AppCompatActivity {
|
public abstract class BaseActionBarActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private static final String TAG = "BaseActionBarActivity";
|
private static final String TAG = BaseActionBarActivity.class.getSimpleName();
|
||||||
protected DynamicTheme dynamicTheme = new DynamicTheme();
|
protected DynamicTheme dynamicTheme = new DynamicTheme();
|
||||||
|
|
||||||
protected void onPreCreate() {
|
protected void onPreCreate() {
|
||||||
@@ -35,13 +40,11 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
|
|||||||
// Only enable Edge-to-Edge if it is well supported
|
// Only enable Edge-to-Edge if it is well supported
|
||||||
if (ViewUtil.isEdgeToEdgeSupported()) {
|
if (ViewUtil.isEdgeToEdgeSupported()) {
|
||||||
// docs says to use: WindowCompat.enableEdgeToEdge(getWindow());
|
// docs says to use: WindowCompat.enableEdgeToEdge(getWindow());
|
||||||
// but it actually makes things worse, the next takes care of setting the 3-buttons navigation
|
// but it actually makes things worse, the next takes care of setting the 3-buttons navigation bar background
|
||||||
// bar background
|
|
||||||
EdgeToEdge.enable(this);
|
EdgeToEdge.enable(this);
|
||||||
|
|
||||||
// force white text in status bar so it visible over background color
|
// force white text in status bar so it visible over background color
|
||||||
WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView())
|
WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView()).setAppearanceLightStatusBars(false);
|
||||||
.setAppearanceLightStatusBars(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,12 +68,14 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Modified from: http://stackoverflow.com/a/13098824 */
|
/**
|
||||||
|
* Modified from: http://stackoverflow.com/a/13098824
|
||||||
|
*/
|
||||||
private void forceOverflowMenu() {
|
private void forceOverflowMenu() {
|
||||||
try {
|
try {
|
||||||
ViewConfiguration config = ViewConfiguration.get(this);
|
ViewConfiguration config = ViewConfiguration.get(this);
|
||||||
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
|
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
|
||||||
if (menuKeyField != null) {
|
if(menuKeyField != null) {
|
||||||
menuKeyField.setAccessible(true);
|
menuKeyField.setAccessible(true);
|
||||||
menuKeyField.setBoolean(config, false);
|
menuKeyField.setBoolean(config, false);
|
||||||
}
|
}
|
||||||
@@ -81,24 +86,32 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void makeSearchMenuVisible(final Menu menu, final MenuItem searchItem) {
|
public void makeSearchMenuVisible(final Menu menu, final MenuItem searchItem, boolean visible) {
|
||||||
for (int i = 0; i < menu.size(); ++i) {
|
for (int i = 0; i < menu.size(); ++i) {
|
||||||
MenuItem item = menu.getItem(i);
|
MenuItem item = menu.getItem(i);
|
||||||
int id = item.getItemId();
|
int id = item.getItemId();
|
||||||
if (id == R.id.menu_search_up || id == R.id.menu_search_down) {
|
if (id == R.id.menu_search_up || id == R.id.menu_search_down) {
|
||||||
item.setVisible(true);
|
item.setVisible(visible);
|
||||||
} else if (item != searchItem) {
|
} else if (id == R.id.menu_search_counter) {
|
||||||
item.setVisible(false); // hide all other items
|
item.setVisible(false); // always hide menu_search_counter initially
|
||||||
|
} else if (item == searchItem) {
|
||||||
|
; // searchItem is just always visible
|
||||||
|
} else {
|
||||||
|
item.setVisible(!visible); // if search is shown, other items are hidden - and the other way round
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T extends Fragment> T initFragment(@IdRes int target, @NonNull T fragment) {
|
protected <T extends Fragment> T initFragment(@IdRes int target,
|
||||||
|
@NonNull T fragment)
|
||||||
|
{
|
||||||
return initFragment(target, fragment, null);
|
return initFragment(target, fragment, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T extends Fragment> T initFragment(
|
protected <T extends Fragment> T initFragment(@IdRes int target,
|
||||||
@IdRes int target, @NonNull T fragment, @Nullable Bundle extras) {
|
@NonNull T fragment,
|
||||||
|
@Nullable Bundle extras)
|
||||||
|
{
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
|
|
||||||
if (extras != null) {
|
if (extras != null) {
|
||||||
@@ -106,10 +119,9 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
getSupportFragmentManager()
|
getSupportFragmentManager().beginTransaction()
|
||||||
.beginTransaction()
|
.replace(target, fragment)
|
||||||
.replace(target, fragment)
|
.commitAllowingStateLoss();
|
||||||
.commitAllowingStateLoss();
|
|
||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,37 +6,42 @@ import android.util.AttributeSet;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import chat.delta.rpc.Rpc;
|
|
||||||
import com.b44t.messenger.DcChat;
|
import com.b44t.messenger.DcChat;
|
||||||
import com.b44t.messenger.DcContext;
|
import com.b44t.messenger.DcContext;
|
||||||
import com.b44t.messenger.DcMsg;
|
import com.b44t.messenger.DcMsg;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
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
|
public abstract class BaseConversationItem extends LinearLayout
|
||||||
implements BindableConversationItem {
|
implements BindableConversationItem
|
||||||
|
{
|
||||||
static final long PULSE_HIGHLIGHT_MILLIS = 500;
|
static final long PULSE_HIGHLIGHT_MILLIS = 500;
|
||||||
|
|
||||||
protected DcMsg messageRecord;
|
protected DcMsg messageRecord;
|
||||||
protected DcChat dcChat;
|
protected DcChat dcChat;
|
||||||
protected TextView bodyText;
|
protected TextView bodyText;
|
||||||
|
|
||||||
protected final Context context;
|
protected final Context context;
|
||||||
protected final DcContext dcContext;
|
protected final DcContext dcContext;
|
||||||
protected final Rpc rpc;
|
protected final Rpc rpc;
|
||||||
protected Recipient conversationRecipient;
|
protected Recipient conversationRecipient;
|
||||||
|
|
||||||
protected @NonNull Set<DcMsg> batchSelected = new HashSet<>();
|
protected @NonNull Set<DcMsg> batchSelected = new HashSet<>();
|
||||||
|
|
||||||
protected final PassthroughClickListener passthroughClickListener =
|
protected final PassthroughClickListener passthroughClickListener = new PassthroughClickListener();
|
||||||
new PassthroughClickListener();
|
|
||||||
|
|
||||||
public BaseConversationItem(Context context, AttributeSet attrs) {
|
public BaseConversationItem(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
@@ -45,32 +50,32 @@ public abstract class BaseConversationItem extends LinearLayout
|
|||||||
this.rpc = DcHelper.getRpc(context);
|
this.rpc = DcHelper.getRpc(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void bindPartial(
|
protected void bind(@NonNull DcMsg messageRecord,
|
||||||
@NonNull DcMsg messageRecord,
|
@NonNull DcChat dcChat,
|
||||||
@NonNull DcChat dcChat,
|
@NonNull Set<DcMsg> batchSelected,
|
||||||
@NonNull Set<DcMsg> batchSelected,
|
boolean pulseHighlight,
|
||||||
boolean pulseHighlight,
|
@NonNull Recipient conversationRecipient)
|
||||||
@NonNull Recipient conversationRecipient) {
|
{
|
||||||
this.messageRecord = messageRecord;
|
this.messageRecord = messageRecord;
|
||||||
this.dcChat = dcChat;
|
this.dcChat = dcChat;
|
||||||
this.batchSelected = batchSelected;
|
this.batchSelected = batchSelected;
|
||||||
this.conversationRecipient = conversationRecipient;
|
this.conversationRecipient = conversationRecipient;
|
||||||
setInteractionState(messageRecord, pulseHighlight);
|
setInteractionState(messageRecord, pulseHighlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setInteractionState(DcMsg messageRecord, boolean pulseHighlight) {
|
protected void setInteractionState(DcMsg messageRecord, boolean pulseHighlight) {
|
||||||
final int[] attributes =
|
final int[] attributes = new int[] {
|
||||||
new int[] {
|
R.attr.conversation_item_background,
|
||||||
R.attr.conversation_item_background, R.attr.conversation_item_background_animated,
|
R.attr.conversation_item_background_animated,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (batchSelected.contains(messageRecord)) {
|
if (batchSelected.contains(messageRecord)) {
|
||||||
final TypedArray attrs = context.obtainStyledAttributes(attributes);
|
final TypedArray attrs = context.obtainStyledAttributes(attributes);
|
||||||
ViewUtil.setBackground(this, attrs.getDrawable(0));
|
ViewUtil.setBackground(this, attrs.getDrawable(0));
|
||||||
attrs.recycle();
|
attrs.recycle();
|
||||||
setSelected(true);
|
setSelected(true);
|
||||||
} else if (pulseHighlight) {
|
} else if (pulseHighlight) {
|
||||||
final TypedArray attrs = context.obtainStyledAttributes(attributes);
|
final TypedArray attrs = context.obtainStyledAttributes(attributes);
|
||||||
ViewUtil.setBackground(this, attrs.getDrawable(1));
|
ViewUtil.setBackground(this, attrs.getDrawable(1));
|
||||||
attrs.recycle();
|
attrs.recycle();
|
||||||
setSelected(true);
|
setSelected(true);
|
||||||
@@ -87,16 +92,15 @@ public abstract class BaseConversationItem extends LinearLayout
|
|||||||
|
|
||||||
protected boolean shouldInterceptClicks(DcMsg messageRecord) {
|
protected boolean shouldInterceptClicks(DcMsg messageRecord) {
|
||||||
return batchSelected.isEmpty()
|
return batchSelected.isEmpty()
|
||||||
&& (messageRecord.isFailed()
|
&& (messageRecord.isFailed()
|
||||||
|| messageRecord.getInfoType() == DcMsg.DC_INFO_CHAT_E2EE
|
|| messageRecord.getInfoType() == DcMsg.DC_INFO_CHAT_E2EE
|
||||||
|| messageRecord.getInfoType() == DcMsg.DC_INFO_PROTECTION_ENABLED
|
|| messageRecord.getInfoType() == DcMsg.DC_INFO_PROTECTION_ENABLED
|
||||||
|| messageRecord.getInfoType() == DcMsg.DC_INFO_INVALID_UNENCRYPTED_MAIL);
|
|| messageRecord.getInfoType() == DcMsg.DC_INFO_INVALID_UNENCRYPTED_MAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onAccessibilityClick() {}
|
protected void onAccessibilityClick() {}
|
||||||
|
|
||||||
protected class PassthroughClickListener
|
protected class PassthroughClickListener implements View.OnLongClickListener, View.OnClickListener {
|
||||||
implements View.OnLongClickListener, View.OnClickListener {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onLongClick(View v) {
|
public boolean onLongClick(View v) {
|
||||||
@@ -122,8 +126,6 @@ public abstract class BaseConversationItem extends LinearLayout
|
|||||||
|
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (!shouldInterceptClicks(messageRecord) && parent != null) {
|
if (!shouldInterceptClicks(messageRecord) && parent != null) {
|
||||||
// The click workaround on ConversationItem shall be revised.
|
|
||||||
// In fact, it is probably better rethinking accessibility approach for the items.
|
|
||||||
if (batchSelected.isEmpty() && Util.isTouchExplorationEnabled(context)) {
|
if (batchSelected.isEmpty() && Util.isTouchExplorationEnabled(context)) {
|
||||||
BaseConversationItem.this.onAccessibilityClick();
|
BaseConversationItem.this.onAccessibilityClick();
|
||||||
}
|
}
|
||||||
@@ -133,15 +135,13 @@ public abstract class BaseConversationItem extends LinearLayout
|
|||||||
TextView detailsText = view.findViewById(R.id.details_text);
|
TextView detailsText = view.findViewById(R.id.details_text);
|
||||||
detailsText.setText(messageRecord.getError());
|
detailsText.setText(messageRecord.getError());
|
||||||
|
|
||||||
AlertDialog d =
|
AlertDialog d = new AlertDialog.Builder(context)
|
||||||
new AlertDialog.Builder(context)
|
|
||||||
.setView(view)
|
.setView(view)
|
||||||
.setTitle(R.string.error)
|
.setTitle(R.string.error)
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.create();
|
.create();
|
||||||
d.show();
|
d.show();
|
||||||
} else if (messageRecord.getInfoType() == DcMsg.DC_INFO_CHAT_E2EE
|
} else if (messageRecord.getInfoType() == DcMsg.DC_INFO_CHAT_E2EE || messageRecord.getInfoType() == DcMsg.DC_INFO_PROTECTION_ENABLED) {
|
||||||
|| messageRecord.getInfoType() == DcMsg.DC_INFO_PROTECTION_ENABLED) {
|
|
||||||
DcHelper.showProtectionEnabledDialog(context);
|
DcHelper.showProtectionEnabledDialog(context);
|
||||||
} else if (messageRecord.getInfoType() == DcMsg.DC_INFO_INVALID_UNENCRYPTED_MAIL) {
|
} else if (messageRecord.getInfoType() == DcMsg.DC_INFO_INVALID_UNENCRYPTED_MAIL) {
|
||||||
DcHelper.showInvalidUnencryptedDialog(context);
|
DcHelper.showInvalidUnencryptedDialog(context);
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public abstract class BaseConversationListAdapter<T extends RecyclerView.ViewHolder>
|
public abstract class BaseConversationListAdapter<T extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<T> {
|
||||||
extends RecyclerView.Adapter<T> {
|
protected final Set<Long> batchSet = Collections.synchronizedSet(new HashSet<Long>());
|
||||||
protected final Set<Long> batchSet = Collections.synchronizedSet(new HashSet<Long>());
|
protected boolean batchMode = false;
|
||||||
protected boolean batchMode = false;
|
|
||||||
|
|
||||||
public abstract void selectAllThreads();
|
public abstract void selectAllThreads();
|
||||||
|
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ import android.content.Intent;
|
|||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
@@ -27,38 +27,36 @@ import androidx.core.content.pm.ShortcutInfoCompat;
|
|||||||
import androidx.core.content.pm.ShortcutManagerCompat;
|
import androidx.core.content.pm.ShortcutManagerCompat;
|
||||||
import androidx.core.graphics.drawable.IconCompat;
|
import androidx.core.graphics.drawable.IconCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import chat.delta.rpc.Rpc;
|
|
||||||
import chat.delta.rpc.RpcException;
|
|
||||||
import com.b44t.messenger.DcChat;
|
import com.b44t.messenger.DcChat;
|
||||||
import com.b44t.messenger.DcContact;
|
|
||||||
import com.b44t.messenger.DcContext;
|
import com.b44t.messenger.DcContext;
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton;
|
import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton;
|
||||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
import org.thoughtcrime.securesms.connect.DirectShareUtil;
|
import org.thoughtcrime.securesms.connect.DirectShareUtil;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
import org.thoughtcrime.securesms.util.ShareUtil;
|
||||||
import org.thoughtcrime.securesms.util.SendRelayedMessageUtil;
|
import org.thoughtcrime.securesms.util.SendRelayedMessageUtil;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.thoughtcrime.securesms.util.task.SnackbarAsyncTask;
|
import org.thoughtcrime.securesms.util.task.SnackbarAsyncTask;
|
||||||
import org.thoughtcrime.securesms.util.views.ProgressDialog;
|
import org.thoughtcrime.securesms.util.views.ProgressDialog;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public abstract class BaseConversationListFragment extends Fragment implements ActionMode.Callback {
|
public abstract class BaseConversationListFragment extends Fragment implements ActionMode.Callback {
|
||||||
private static final String TAG = "BaseConversationListFragment";
|
|
||||||
protected ActionMode actionMode;
|
protected ActionMode actionMode;
|
||||||
protected PulsingFloatingActionButton fab;
|
protected PulsingFloatingActionButton fab;
|
||||||
|
|
||||||
protected abstract boolean offerToArchive();
|
protected abstract boolean offerToArchive();
|
||||||
|
|
||||||
protected abstract void setFabVisibility(boolean isActionMode);
|
protected abstract void setFabVisibility(boolean isActionMode);
|
||||||
|
|
||||||
protected abstract BaseConversationListAdapter getListAdapter();
|
protected abstract BaseConversationListAdapter getListAdapter();
|
||||||
|
|
||||||
protected void onItemClick(long chatId) {
|
protected void onItemClick(long chatId) {
|
||||||
if (actionMode == null) {
|
if (actionMode == null) {
|
||||||
((ConversationSelectedListener) requireActivity()).onCreateConversation((int) chatId);
|
((ConversationSelectedListener) requireActivity()).onCreateConversation((int)chatId);
|
||||||
} else {
|
} else {
|
||||||
BaseConversationListAdapter adapter = getListAdapter();
|
BaseConversationListAdapter adapter = getListAdapter();
|
||||||
adapter.toggleThreadInBatchSet(chatId);
|
adapter.toggleThreadInBatchSet(chatId);
|
||||||
@@ -73,9 +71,8 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onItemLongClick(long chatId) {
|
public void onItemLongClick(long chatId) {
|
||||||
actionMode = ((AppCompatActivity) requireActivity()).startSupportActionMode(this);
|
actionMode = ((AppCompatActivity)requireActivity()).startSupportActionMode(this);
|
||||||
|
|
||||||
if (actionMode != null) {
|
if (actionMode != null) {
|
||||||
getListAdapter().initializeBatchMode(true);
|
getListAdapter().initializeBatchMode(true);
|
||||||
@@ -92,54 +89,36 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
Intent intent = new Intent(getActivity(), NewConversationActivity.class);
|
Intent intent = new Intent(getActivity(), NewConversationActivity.class);
|
||||||
if (isRelayingMessageContent(getActivity())) {
|
if (isRelayingMessageContent(getActivity())) {
|
||||||
if (isActionMode) {
|
if (isActionMode) {
|
||||||
fab.setOnClickListener(
|
fab.setOnClickListener(v -> {
|
||||||
v -> {
|
final Set<Long> selectedChats = getListAdapter().getBatchSelections();
|
||||||
final Set<Long> selectedChats = getListAdapter().getBatchSelections();
|
ArrayList<Uri> uris = getSharedUris(getActivity());
|
||||||
ArrayList<Uri> uris = getSharedUris(getActivity());
|
String message;
|
||||||
String message;
|
if (isForwarding(getActivity())) {
|
||||||
if (isForwarding(getActivity())) {
|
message = String.format(Util.getLocale(), getString(R.string.ask_forward_multiple), selectedChats.size());
|
||||||
message =
|
} else if (!uris.isEmpty()) {
|
||||||
String.format(
|
message = String.format(Util.getLocale(), getString(R.string.ask_send_files_to_selected_chats), uris.size(), selectedChats.size());
|
||||||
Util.getLocale(),
|
} else {
|
||||||
getString(R.string.ask_forward_multiple),
|
message = String.format(Util.getLocale(), getString(R.string.share_text_multiple_chats), selectedChats.size(), getSharedText(getActivity()));
|
||||||
selectedChats.size());
|
}
|
||||||
} else if (!uris.isEmpty()) {
|
|
||||||
message =
|
|
||||||
String.format(
|
|
||||||
Util.getLocale(),
|
|
||||||
getString(R.string.ask_send_files_to_selected_chats),
|
|
||||||
uris.size(),
|
|
||||||
selectedChats.size());
|
|
||||||
} else {
|
|
||||||
message =
|
|
||||||
String.format(
|
|
||||||
Util.getLocale(),
|
|
||||||
getString(R.string.share_text_multiple_chats),
|
|
||||||
selectedChats.size(),
|
|
||||||
getSharedText(getActivity()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Context context = getContext();
|
Context context = getContext();
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
if (SendRelayedMessageUtil.containsVideoType(context, uris)) {
|
if (SendRelayedMessageUtil.containsVideoType(context, uris)) {
|
||||||
message += "\n\n" + getString(R.string.videos_sent_without_recoding);
|
message += "\n\n" + getString(R.string.videos_sent_without_recoding);
|
||||||
}
|
}
|
||||||
new AlertDialog.Builder(context)
|
new AlertDialog.Builder(context)
|
||||||
.setMessage(message)
|
.setMessage(message)
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setNegativeButton(android.R.string.cancel, ((dialog, which) -> {}))
|
.setNegativeButton(android.R.string.cancel, ((dialog, which) -> {}))
|
||||||
.setPositiveButton(
|
.setPositiveButton(R.string.menu_send, (dialog, which) -> {
|
||||||
R.string.menu_send,
|
SendRelayedMessageUtil.immediatelyRelay(getActivity(), selectedChats.toArray(new Long[selectedChats.size()]));
|
||||||
(dialog, which) -> {
|
actionMode.finish();
|
||||||
SendRelayedMessageUtil.immediatelyRelay(
|
actionMode = null;
|
||||||
getActivity(), selectedChats.toArray(new Long[selectedChats.size()]));
|
getActivity().finish();
|
||||||
actionMode.finish();
|
})
|
||||||
actionMode = null;
|
|
||||||
getActivity().finish();
|
|
||||||
})
|
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
acquireRelayMessageContent(getActivity(), intent);
|
acquireRelayMessageContent(getActivity(), intent);
|
||||||
fab.setOnClickListener(v -> requireActivity().startActivity(intent));
|
fab.setOnClickListener(v -> requireActivity().startActivity(intent));
|
||||||
@@ -153,8 +132,8 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
DcContext dcContext = DcHelper.getContext(requireActivity());
|
DcContext dcContext = DcHelper.getContext(requireActivity());
|
||||||
final Set<Long> selectedChats = getListAdapter().getBatchSelections();
|
final Set<Long> selectedChats = getListAdapter().getBatchSelections();
|
||||||
for (long chatId : selectedChats) {
|
for (long chatId : selectedChats) {
|
||||||
DcChat dcChat = dcContext.getChat((int) chatId);
|
DcChat dcChat = dcContext.getChat((int)chatId);
|
||||||
if (dcChat.getVisibility() != DcChat.DC_CHAT_VISIBILITY_PINNED) {
|
if (dcChat.getVisibility()!=DcChat.DC_CHAT_VISIBILITY_PINNED) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,7 +144,7 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
DcContext dcContext = DcHelper.getContext(requireActivity());
|
DcContext dcContext = DcHelper.getContext(requireActivity());
|
||||||
final Set<Long> selectedChats = getListAdapter().getBatchSelections();
|
final Set<Long> selectedChats = getListAdapter().getBatchSelections();
|
||||||
for (long chatId : selectedChats) {
|
for (long chatId : selectedChats) {
|
||||||
DcChat dcChat = dcContext.getChat((int) chatId);
|
DcChat dcChat = dcContext.getChat((int)chatId);
|
||||||
if (!dcChat.isMuted()) {
|
if (!dcChat.isMuted()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -173,26 +152,13 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean areSomeSelectedChatsFresh() {
|
|
||||||
DcContext dcContext = DcHelper.getContext(requireActivity());
|
|
||||||
final Set<Long> selectedChats = getListAdapter().getBatchSelections();
|
|
||||||
for (long chatId : selectedChats) {
|
|
||||||
if (dcContext.getFreshMsgCount((int) chatId) > 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handlePinAllSelected() {
|
private void handlePinAllSelected() {
|
||||||
final DcContext dcContext = DcHelper.getContext(requireActivity());
|
final DcContext dcContext = DcHelper.getContext(requireActivity());
|
||||||
final Set<Long> selectedConversations =
|
final Set<Long> selectedConversations = new HashSet<Long>(getListAdapter().getBatchSelections());
|
||||||
new HashSet<Long>(getListAdapter().getBatchSelections());
|
|
||||||
boolean doPin = areSomeSelectedChatsUnpinned();
|
boolean doPin = areSomeSelectedChatsUnpinned();
|
||||||
for (long chatId : selectedConversations) {
|
for (long chatId : selectedConversations) {
|
||||||
dcContext.setChatVisibility(
|
dcContext.setChatVisibility((int)chatId,
|
||||||
(int) chatId,
|
doPin? DcChat.DC_CHAT_VISIBILITY_PINNED : DcChat.DC_CHAT_VISIBILITY_NORMAL);
|
||||||
doPin ? DcChat.DC_CHAT_VISIBILITY_PINNED : DcChat.DC_CHAT_VISIBILITY_NORMAL);
|
|
||||||
}
|
}
|
||||||
if (actionMode != null) {
|
if (actionMode != null) {
|
||||||
actionMode.finish();
|
actionMode.finish();
|
||||||
@@ -201,26 +167,23 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleMuteAllSelected() {
|
private void handleMuteAllSelected() {
|
||||||
final DcContext dcContext = DcHelper.getContext(requireActivity());
|
final DcContext dcContext = DcHelper.getContext(requireActivity());
|
||||||
final Set<Long> selectedConversations =
|
final Set<Long> selectedConversations = new HashSet<Long>(getListAdapter().getBatchSelections());
|
||||||
new HashSet<Long>(getListAdapter().getBatchSelections());
|
|
||||||
if (areSomeSelectedChatsUnmuted()) {
|
if (areSomeSelectedChatsUnmuted()) {
|
||||||
MuteDialog.show(
|
MuteDialog.show(getActivity(), duration -> {
|
||||||
getActivity(),
|
for (long chatId : selectedConversations) {
|
||||||
duration -> {
|
dcContext.setChatMuteDuration((int)chatId, duration);
|
||||||
for (long chatId : selectedConversations) {
|
}
|
||||||
dcContext.setChatMuteDuration((int) chatId, duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actionMode != null) {
|
if (actionMode != null) {
|
||||||
actionMode.finish();
|
actionMode.finish();
|
||||||
actionMode = null;
|
actionMode = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// unmute
|
// unmute
|
||||||
for (long chatId : selectedConversations) {
|
for (long chatId : selectedConversations) {
|
||||||
dcContext.setChatMuteDuration((int) chatId, 0);
|
dcContext.setChatMuteDuration((int)chatId, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionMode != null) {
|
if (actionMode != null) {
|
||||||
@@ -231,11 +194,10 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleMarknoticedSelected() {
|
private void handleMarknoticedSelected() {
|
||||||
final DcContext dcContext = DcHelper.getContext(requireActivity());
|
final DcContext dcContext = DcHelper.getContext(requireActivity());
|
||||||
final Set<Long> selectedConversations =
|
final Set<Long> selectedConversations = new HashSet<Long>(getListAdapter().getBatchSelections());
|
||||||
new HashSet<Long>(getListAdapter().getBatchSelections());
|
|
||||||
for (long chatId : selectedConversations) {
|
for (long chatId : selectedConversations) {
|
||||||
dcContext.marknoticedChat((int) chatId);
|
dcContext.marknoticedChat((int)chatId);
|
||||||
}
|
}
|
||||||
if (actionMode != null) {
|
if (actionMode != null) {
|
||||||
actionMode.finish();
|
actionMode.finish();
|
||||||
@@ -243,43 +205,24 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleMarkfreshSelected() {
|
|
||||||
final Set<Long> selectedConversations =
|
|
||||||
new HashSet<Long>(getListAdapter().getBatchSelections());
|
|
||||||
|
|
||||||
final Rpc rpc = DcHelper.getRpc(requireActivity());
|
|
||||||
try {
|
|
||||||
int accId = rpc.getSelectedAccountId();
|
|
||||||
for (long chatId : selectedConversations) {
|
|
||||||
rpc.markfreshChat(accId, (int) chatId);
|
|
||||||
}
|
|
||||||
} catch (RpcException e) {
|
|
||||||
Log.e(TAG, "RPC error", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actionMode != null) {
|
|
||||||
actionMode.finish();
|
|
||||||
actionMode = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("StaticFieldLeak")
|
@SuppressLint("StaticFieldLeak")
|
||||||
private void handleArchiveAllSelected() {
|
private void handleArchiveAllSelected() {
|
||||||
final DcContext dcContext = DcHelper.getContext(requireActivity());
|
final DcContext dcContext = DcHelper.getContext(requireActivity());
|
||||||
final Set<Long> selectedConversations =
|
final Set<Long> selectedConversations = new HashSet<Long>(getListAdapter().getBatchSelections());
|
||||||
new HashSet<Long>(getListAdapter().getBatchSelections());
|
final boolean archive = offerToArchive();
|
||||||
final boolean archive = offerToArchive();
|
|
||||||
|
|
||||||
int snackBarTitleId;
|
int snackBarTitleId;
|
||||||
|
|
||||||
if (archive) snackBarTitleId = R.plurals.chat_archived;
|
if (archive) snackBarTitleId = R.plurals.chat_archived;
|
||||||
else snackBarTitleId = R.plurals.chat_unarchived;
|
else snackBarTitleId = R.plurals.chat_unarchived;
|
||||||
|
|
||||||
int count = selectedConversations.size();
|
int count = selectedConversations.size();
|
||||||
String snackBarTitle = getResources().getQuantityString(snackBarTitleId, count, count);
|
String snackBarTitle = getResources().getQuantityString(snackBarTitleId, count, count);
|
||||||
|
|
||||||
new SnackbarAsyncTask<Void>(
|
new SnackbarAsyncTask<Void>(getView(), snackBarTitle,
|
||||||
getView(), snackBarTitle, getString(R.string.undo), Snackbar.LENGTH_LONG, true) {
|
getString(R.string.undo),
|
||||||
|
Snackbar.LENGTH_LONG, true)
|
||||||
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Void result) {
|
protected void onPostExecute(Void result) {
|
||||||
@@ -294,18 +237,16 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
@Override
|
@Override
|
||||||
protected void executeAction(@Nullable Void parameter) {
|
protected void executeAction(@Nullable Void parameter) {
|
||||||
for (long chatId : selectedConversations) {
|
for (long chatId : selectedConversations) {
|
||||||
dcContext.setChatVisibility(
|
dcContext.setChatVisibility((int)chatId,
|
||||||
(int) chatId,
|
archive? DcChat.DC_CHAT_VISIBILITY_ARCHIVED : DcChat.DC_CHAT_VISIBILITY_NORMAL);
|
||||||
archive ? DcChat.DC_CHAT_VISIBILITY_ARCHIVED : DcChat.DC_CHAT_VISIBILITY_NORMAL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void reverseAction(@Nullable Void parameter) {
|
protected void reverseAction(@Nullable Void parameter) {
|
||||||
for (long threadId : selectedConversations) {
|
for (long threadId : selectedConversations) {
|
||||||
dcContext.setChatVisibility(
|
dcContext.setChatVisibility((int)threadId,
|
||||||
(int) threadId,
|
archive? DcChat.DC_CHAT_VISIBILITY_NORMAL : DcChat.DC_CHAT_VISIBILITY_ARCHIVED);
|
||||||
archive ? DcChat.DC_CHAT_VISIBILITY_NORMAL : DcChat.DC_CHAT_VISIBILITY_ARCHIVED);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
@@ -321,73 +262,51 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
final String alertText;
|
final String alertText;
|
||||||
if (chatsCount == 1) {
|
if (chatsCount == 1) {
|
||||||
long chatId = selectedChats.iterator().next();
|
long chatId = selectedChats.iterator().next();
|
||||||
alertText =
|
alertText = activity.getResources().getString(R.string.ask_delete_named_chat, dcContext.getChat((int)chatId).getName());
|
||||||
activity
|
|
||||||
.getResources()
|
|
||||||
.getString(R.string.ask_delete_named_chat, dcContext.getChat((int) chatId).getName());
|
|
||||||
} else {
|
} else {
|
||||||
alertText =
|
alertText = activity.getResources().getQuantityString(R.plurals.ask_delete_chat, chatsCount, chatsCount);
|
||||||
activity
|
|
||||||
.getResources()
|
|
||||||
.getQuantityString(R.plurals.ask_delete_chat, chatsCount, chatsCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
String alertButton = getString(R.string.delete_for_me);
|
|
||||||
for (long chatId : selectedChats) {
|
|
||||||
if (dcContext.getChat((int) chatId).shallLeaveBeforeDelete(dcContext)) {
|
|
||||||
alertButton = getString(R.string.menu_leave_and_delete);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
|
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
|
||||||
alert.setMessage(alertText);
|
alert.setMessage(alertText);
|
||||||
alert.setCancelable(true);
|
alert.setCancelable(true);
|
||||||
|
|
||||||
alert.setPositiveButton(
|
alert.setPositiveButton(R.string.delete, (dialog, which) -> {
|
||||||
alertButton,
|
|
||||||
(dialog, which) -> {
|
|
||||||
if (!selectedChats.isEmpty()) {
|
|
||||||
new AsyncTask<Void, Void, Void>() {
|
|
||||||
private ProgressDialog dialog;
|
|
||||||
|
|
||||||
@Override
|
if (!selectedChats.isEmpty()) {
|
||||||
protected void onPreExecute() {
|
new AsyncTask<Void, Void, Void>() {
|
||||||
dialog =
|
private ProgressDialog dialog;
|
||||||
ProgressDialog.show(
|
|
||||||
getActivity(),
|
|
||||||
"",
|
|
||||||
requireActivity().getString(R.string.one_moment),
|
|
||||||
true,
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected void onPreExecute() {
|
||||||
int accountId = dcContext.getAccountId();
|
dialog = ProgressDialog.show(getActivity(),
|
||||||
for (long chatId : selectedChats) {
|
"",
|
||||||
DcHelper.getNotificationCenter(requireContext())
|
requireActivity().getString(R.string.one_moment),
|
||||||
.removeNotifications(accountId, (int) chatId);
|
true, false);
|
||||||
if (dcContext.getChat((int) chatId).shallLeaveBeforeDelete(dcContext)) {
|
|
||||||
dcContext.removeContactFromChat((int) chatId, DcContact.DC_CONTACT_ID_SELF);
|
|
||||||
}
|
|
||||||
dcContext.deleteChat((int) chatId);
|
|
||||||
DirectShareUtil.clearShortcut(requireContext(), (int) chatId);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Void result) {
|
|
||||||
dialog.dismiss();
|
|
||||||
if (actionMode != null) {
|
|
||||||
actionMode.finish();
|
|
||||||
actionMode = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
int accountId = dcContext.getAccountId();
|
||||||
|
for (long chatId : selectedChats) {
|
||||||
|
DcHelper.getNotificationCenter(requireContext()).removeNotifications(accountId, (int) chatId);
|
||||||
|
dcContext.deleteChat((int) chatId);
|
||||||
|
DirectShareUtil.clearShortcut(requireContext(), (int) chatId);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
dialog.dismiss();
|
||||||
|
if (actionMode != null) {
|
||||||
|
actionMode.finish();
|
||||||
|
actionMode = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
alert.setNegativeButton(android.R.string.cancel, null);
|
alert.setNegativeButton(android.R.string.cancel, null);
|
||||||
AlertDialog dialog = alert.show();
|
AlertDialog dialog = alert.show();
|
||||||
@@ -412,39 +331,22 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
intent.putExtra(ShareActivity.EXTRA_CHAT_ID, chat.getId());
|
intent.putExtra(ShareActivity.EXTRA_CHAT_ID, chat.getId());
|
||||||
|
|
||||||
Recipient recipient = new Recipient(activity, chat);
|
Recipient recipient = new Recipient(activity, chat);
|
||||||
Util.runOnAnyBackgroundThread(
|
Util.runOnAnyBackgroundThread(() -> {
|
||||||
() -> {
|
Bitmap avatar = DirectShareUtil.getIconForShortcut(activity, recipient);
|
||||||
Bitmap avatar = DirectShareUtil.getIconForShortcut(activity, recipient);
|
ShortcutInfoCompat shortcutInfoCompat = new ShortcutInfoCompat.Builder(activity, "chat-" + dcContext.getAccountId() + "-" + chat.getId())
|
||||||
ShortcutInfoCompat shortcutInfoCompat =
|
.setShortLabel(chat.getName())
|
||||||
new ShortcutInfoCompat.Builder(
|
.setIcon(IconCompat.createWithAdaptiveBitmap(avatar))
|
||||||
activity, "chat-" + dcContext.getAccountId() + "-" + chat.getId())
|
.setIntent(intent)
|
||||||
.setShortLabel(chat.getName())
|
.build();
|
||||||
.setIcon(IconCompat.createWithAdaptiveBitmap(avatar))
|
Util.runOnMain(() -> {
|
||||||
.setIntent(intent)
|
if (!ShortcutManagerCompat.requestPinShortcut(activity, shortcutInfoCompat, null)) {
|
||||||
.build();
|
Toast.makeText(activity, "ErrAddToHomescreen: requestPinShortcut() failed", Toast.LENGTH_LONG).show();
|
||||||
|
} else if (actionMode != null) {
|
||||||
boolean success;
|
actionMode.finish();
|
||||||
try {
|
actionMode = null;
|
||||||
success = ShortcutManagerCompat.requestPinShortcut(activity, shortcutInfoCompat, null);
|
}
|
||||||
} catch (Exception e) {
|
});
|
||||||
Log.e(TAG, "ErrAddToHomescreen: requestPinShortcut() failed", e);
|
});
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
boolean finalSuccess = success;
|
|
||||||
Util.runOnMain(
|
|
||||||
() -> {
|
|
||||||
if (!finalSuccess) {
|
|
||||||
Toast.makeText(
|
|
||||||
activity,
|
|
||||||
"ErrAddToHomescreen: requestPinShortcut() failed",
|
|
||||||
Toast.LENGTH_LONG)
|
|
||||||
.show();
|
|
||||||
} else if (actionMode != null) {
|
|
||||||
actionMode.finish();
|
|
||||||
actionMode = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateActionModeItems(Menu menu) {
|
private void updateActionModeItems(Menu menu) {
|
||||||
@@ -452,16 +354,14 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
if (!isRelayingMessageContent(requireActivity())) {
|
if (!isRelayingMessageContent(requireActivity())) {
|
||||||
final int selectedCount = getListAdapter().getBatchSelections().size();
|
final int selectedCount = getListAdapter().getBatchSelections().size();
|
||||||
menu.findItem(R.id.menu_add_to_home_screen).setVisible(selectedCount == 1);
|
menu.findItem(R.id.menu_add_to_home_screen).setVisible(selectedCount == 1);
|
||||||
|
|
||||||
MenuItem archiveItem = menu.findItem(R.id.menu_archive_selected);
|
MenuItem archiveItem = menu.findItem(R.id.menu_archive_selected);
|
||||||
if (offerToArchive()) {
|
if (offerToArchive()) {
|
||||||
archiveItem.setIcon(R.drawable.ic_archive_white_24dp);
|
archiveItem.setIcon(R.drawable.ic_archive_white_24dp);
|
||||||
archiveItem.setTitle(R.string.menu_archive_chat);
|
archiveItem.setTitle(R.string.menu_archive_chat);
|
||||||
} else {
|
} else {
|
||||||
archiveItem.setIcon(R.drawable.ic_unarchive_white_24dp);
|
archiveItem.setIcon(R.drawable.ic_unarchive_white_24dp);
|
||||||
archiveItem.setTitle(R.string.menu_unarchive_chat);
|
archiveItem.setTitle(R.string.menu_unarchive_chat);
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuItem pinItem = menu.findItem(R.id.menu_pin_selected);
|
MenuItem pinItem = menu.findItem(R.id.menu_pin_selected);
|
||||||
if (areSomeSelectedChatsUnpinned()) {
|
if (areSomeSelectedChatsUnpinned()) {
|
||||||
pinItem.setIcon(R.drawable.ic_pin_white);
|
pinItem.setIcon(R.drawable.ic_pin_white);
|
||||||
@@ -470,23 +370,21 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
pinItem.setIcon(R.drawable.ic_unpin_white);
|
pinItem.setIcon(R.drawable.ic_unpin_white);
|
||||||
pinItem.setTitle(R.string.unpin_chat);
|
pinItem.setTitle(R.string.unpin_chat);
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuItem muteItem = menu.findItem(R.id.menu_mute_selected);
|
MenuItem muteItem = menu.findItem(R.id.menu_mute_selected);
|
||||||
if (areSomeSelectedChatsUnmuted()) {
|
if (areSomeSelectedChatsUnmuted()) {
|
||||||
muteItem.setTitle(R.string.menu_mute);
|
muteItem.setTitle(R.string.menu_mute);
|
||||||
} else {
|
} else {
|
||||||
muteItem.setTitle(R.string.menu_unmute);
|
muteItem.setTitle(R.string.menu_unmute);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean someAreFresh = areSomeSelectedChatsFresh();
|
|
||||||
menu.findItem(R.id.menu_marknoticed_selected).setVisible(someAreFresh);
|
|
||||||
menu.findItem(R.id.menu_markfresh_selected).setVisible(!someAreFresh);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||||
if (isRelayingMessageContent(getActivity())) {
|
if (isRelayingMessageContent(getActivity())) {
|
||||||
|
if (ShareUtil.getSharedContactId(getActivity()) != 0) {
|
||||||
|
return false; // no sharing of a contact to multiple recipients at the same time, we can reconsider when that becomes a real-world need
|
||||||
|
}
|
||||||
Context context = getContext();
|
Context context = getContext();
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
fab.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_send_sms_white_24dp));
|
fab.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_send_sms_white_24dp));
|
||||||
@@ -530,9 +428,6 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
} else if (itemId == R.id.menu_marknoticed_selected) {
|
} else if (itemId == R.id.menu_marknoticed_selected) {
|
||||||
handleMarknoticedSelected();
|
handleMarknoticedSelected();
|
||||||
return true;
|
return true;
|
||||||
} else if (itemId == R.id.menu_markfresh_selected) {
|
|
||||||
handleMarkfreshSelected();
|
|
||||||
return true;
|
|
||||||
} else if (itemId == R.id.menu_add_to_home_screen) {
|
} else if (itemId == R.id.menu_add_to_home_screen) {
|
||||||
handleAddToHomeScreen();
|
handleAddToHomeScreen();
|
||||||
return true;
|
return true;
|
||||||
@@ -556,7 +451,6 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
|||||||
|
|
||||||
public interface ConversationSelectedListener {
|
public interface ConversationSelectedListener {
|
||||||
void onCreateConversation(int chatId);
|
void onCreateConversation(int chatId);
|
||||||
|
|
||||||
void onSwitchToArchive();
|
void onSwitchToArchive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,24 +2,22 @@ package org.thoughtcrime.securesms;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.b44t.messenger.DcChat;
|
import com.b44t.messenger.DcChat;
|
||||||
import com.b44t.messenger.DcMsg;
|
import com.b44t.messenger.DcMsg;
|
||||||
import java.util.Set;
|
|
||||||
import org.thoughtcrime.securesms.components.audioplay.AudioPlaybackViewModel;
|
|
||||||
import org.thoughtcrime.securesms.components.audioplay.AudioView;
|
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public interface BindableConversationItem extends Unbindable {
|
public interface BindableConversationItem extends Unbindable {
|
||||||
void bind(
|
void bind(@NonNull DcMsg messageRecord,
|
||||||
@NonNull DcMsg messageRecord,
|
@NonNull DcChat dcChat,
|
||||||
@NonNull DcChat dcChat,
|
@NonNull GlideRequests glideRequests,
|
||||||
@NonNull GlideRequests glideRequests,
|
@NonNull Set<DcMsg> batchSelected,
|
||||||
@NonNull Set<DcMsg> batchSelected,
|
@NonNull Recipient recipients,
|
||||||
@NonNull Recipient recipients,
|
boolean pulseHighlight);
|
||||||
boolean pulseHighlight,
|
|
||||||
@Nullable AudioPlaybackViewModel playbackViewModel,
|
|
||||||
AudioView.OnActionListener audioPlayPauseListener);
|
|
||||||
|
|
||||||
DcMsg getMessageRecord();
|
DcMsg getMessageRecord();
|
||||||
|
|
||||||
@@ -27,15 +25,9 @@ public interface BindableConversationItem extends Unbindable {
|
|||||||
|
|
||||||
interface EventListener {
|
interface EventListener {
|
||||||
void onQuoteClicked(DcMsg messageRecord);
|
void onQuoteClicked(DcMsg messageRecord);
|
||||||
|
|
||||||
void onJumpToOriginalClicked(DcMsg messageRecord);
|
void onJumpToOriginalClicked(DcMsg messageRecord);
|
||||||
|
|
||||||
void onShowFullClicked(DcMsg messageRecord);
|
void onShowFullClicked(DcMsg messageRecord);
|
||||||
|
|
||||||
void onDownloadClicked(DcMsg messageRecord);
|
void onDownloadClicked(DcMsg messageRecord);
|
||||||
|
|
||||||
void onReactionClicked(DcMsg messageRecord);
|
void onReactionClicked(DcMsg messageRecord);
|
||||||
|
|
||||||
void onStickerClicked(DcMsg messageRecord);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.b44t.messenger.DcLot;
|
import com.b44t.messenger.DcLot;
|
||||||
import java.util.Set;
|
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public interface BindableConversationListItem extends Unbindable {
|
public interface BindableConversationListItem extends Unbindable {
|
||||||
|
|
||||||
public void bind(
|
public void bind(@NonNull ThreadRecord thread,
|
||||||
@NonNull ThreadRecord thread,
|
int msgId,
|
||||||
int msgId,
|
@NonNull DcLot dcSummary,
|
||||||
@NonNull DcLot dcSummary,
|
@NonNull GlideRequests glideRequests,
|
||||||
@NonNull GlideRequests glideRequests,
|
@NonNull Set<Long> selectedThreads, boolean batchMode);
|
||||||
@NonNull Set<Long> selectedThreads,
|
|
||||||
boolean batchMode);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.view.MenuItem;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
@@ -13,8 +14,10 @@ import androidx.loader.app.LoaderManager;
|
|||||||
import androidx.loader.content.Loader;
|
import androidx.loader.content.Loader;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.b44t.messenger.DcContext;
|
import com.b44t.messenger.DcContext;
|
||||||
import com.b44t.messenger.DcEvent;
|
import com.b44t.messenger.DcEvent;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.connect.DcContactsLoader;
|
import org.thoughtcrime.securesms.connect.DcContactsLoader;
|
||||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
@@ -36,18 +39,17 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case android.R.id.home:
|
case android.R.id.home: finish(); return true;
|
||||||
finish();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BlockedAndShareContactsFragment extends Fragment
|
public static class BlockedAndShareContactsFragment
|
||||||
implements LoaderManager.LoaderCallbacks<DcContactsLoader.Ret>,
|
extends Fragment
|
||||||
DcEventCenter.DcEventDelegate,
|
implements LoaderManager.LoaderCallbacks<DcContactsLoader.Ret>,
|
||||||
ContactSelectionListAdapter.ItemClickListener {
|
DcEventCenter.DcEventDelegate, ContactSelectionListAdapter.ItemClickListener {
|
||||||
|
|
||||||
|
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private TextView emptyStateView;
|
private TextView emptyStateView;
|
||||||
@@ -55,7 +57,7 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
||||||
View view = inflater.inflate(R.layout.contact_selection_list_fragment, container, false);
|
View view = inflater.inflate(R.layout.contact_selection_list_fragment, container, false);
|
||||||
recyclerView = ViewUtil.findById(view, R.id.recycler_view);
|
recyclerView = ViewUtil.findById(view, R.id.recycler_view);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
|
|
||||||
// add padding to avoid content hidden behind system bars
|
// add padding to avoid content hidden behind system bars
|
||||||
@@ -79,8 +81,11 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initializeAdapter() {
|
private void initializeAdapter() {
|
||||||
ContactSelectionListAdapter adapter =
|
ContactSelectionListAdapter adapter = new ContactSelectionListAdapter(getActivity(),
|
||||||
new ContactSelectionListAdapter(getActivity(), GlideApp.with(this), this, false, false);
|
GlideApp.with(this),
|
||||||
|
this,
|
||||||
|
false,
|
||||||
|
false);
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +112,7 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleEvent(@NonNull DcEvent event) {
|
public void handleEvent(@NonNull DcEvent event) {
|
||||||
if (event.getId() == DcContext.DC_EVENT_CONTACTS_CHANGED) {
|
if (event.getId()==DcContext.DC_EVENT_CONTACTS_CHANGED) {
|
||||||
restartLoader();
|
restartLoader();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,12 +128,10 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
public void onItemClick(ContactSelectionListItem item, boolean handleActionMode) {
|
public void onItemClick(ContactSelectionListItem item, boolean handleActionMode) {
|
||||||
new AlertDialog.Builder(getActivity())
|
new AlertDialog.Builder(getActivity())
|
||||||
.setMessage(R.string.ask_unblock_contact)
|
.setMessage(R.string.ask_unblock_contact)
|
||||||
.setCancelable(true)
|
.setCancelable(true)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton(
|
.setPositiveButton(R.string.menu_unblock_contact, (dialog, which) -> unblockContact(item.getContactId())).show();
|
||||||
R.string.menu_unblock_contact, (dialog, which) -> unblockContact(item.getContactId()))
|
|
||||||
.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unblockContact(int contactId) {
|
private void unblockContact(int contactId) {
|
||||||
@@ -140,4 +143,5 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
public void onItemLongClick(ContactSelectionListItem view) {}
|
public void onItemLongClick(ContactSelectionListItem view) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user