mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-07 04:49:41 +01:00
Compare commits
185 Commits
alpha-2200
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
5606254a4a | ||
|
9cc950e30a | ||
|
4f5e2ce273 | ||
|
6b63a4f793 | ||
|
3af5981841 | ||
|
d9be063891 | ||
|
b5ec3cd2af | ||
|
fc65a7a8d0 | ||
|
6a026c1fc7 | ||
|
c9f699d0d3 | ||
|
913907a7e2 | ||
|
7f6f077680 | ||
|
632e8f85a9 | ||
|
42bd8d2235 | ||
|
33ad578ef5 | ||
|
b7ae981c3d | ||
|
81cf077f6f | ||
|
1b7b11ff76 | ||
|
c8e4de6665 | ||
|
78cb62a3bd | ||
|
59fd9f2319 | ||
|
74a1c5aeb0 | ||
|
a3a5272dbb | ||
|
dd77ce7c4c | ||
|
94db4e6892 | ||
|
99d5fc7d19 | ||
|
ba0d37020b | ||
|
c19cba3c0d | ||
|
2d0f0d9f73 | ||
|
cdb1c4b0f8 | ||
|
ea0588cb99 | ||
|
ea19f60ef3 | ||
|
3096a73585 | ||
|
dbf5c84050 | ||
|
4c7d6f90ec | ||
|
3930d4b740 | ||
|
9b3f508652 | ||
|
28556e12cd | ||
|
bd8ad9e672 | ||
|
0a44067a58 | ||
|
4d24716a4d | ||
|
1648c61b06 | ||
|
bd050f0bc0 | ||
|
f7997d339b | ||
|
28cacf2a90 | ||
|
890a7febc2 | ||
|
48e8caac0a | ||
|
a6fbac92c2 | ||
|
439912754b | ||
|
8792ac1dbd | ||
|
adc0be1d1d | ||
|
5fccf47353 | ||
|
324e02a807 | ||
|
94894b17a6 | ||
|
f1a0d8c70a | ||
|
0edc4ea337 | ||
|
2fe295ef63 | ||
|
9723d298ed | ||
|
44f201800f | ||
|
375d7316d8 | ||
|
d89c243904 | ||
|
22a780d7c8 | ||
|
0b95237991 | ||
|
351173bb6b | ||
|
1aa2d2aaaa | ||
|
06df0084cf | ||
|
ca73e93aeb | ||
|
c305816f6d | ||
|
8bc31cdbd4 | ||
|
0d9402f496 | ||
|
9867ed08ac | ||
|
ef5f6b67f6 | ||
|
5cd84f633c | ||
|
d7d139c861 | ||
|
5612cfa19d | ||
|
b4d5af8a4c | ||
|
5ac7e8357b | ||
|
156d142ba0 | ||
|
207408a606 | ||
|
5a7f4924ab | ||
|
f53b90cdf6 | ||
|
8980bd0f64 | ||
|
6b0142c6c3 | ||
|
011ea9dc82 | ||
|
c95bed4be5 | ||
|
1a6e18b003 | ||
|
87d75102d4 | ||
|
c110ecdc2b | ||
|
fa8a72bc74 | ||
|
a8dd25a285 | ||
|
486d8d1035 | ||
|
84d09d0e58 | ||
|
cc270848b5 | ||
|
8ac9427ba6 | ||
|
6905c78796 | ||
|
4a4f4fc8e1 | ||
|
02eab6766a | ||
|
6effeef2ee | ||
|
d3d3776a8f | ||
|
d97de1bdd2 | ||
|
e94e2b63ae | ||
|
5c3cc89084 | ||
|
c2d3340ddb | ||
|
cc9ca58a69 | ||
|
21932df918 | ||
|
f29d174a61 | ||
|
8e3909efbc | ||
|
9d3ad47e20 | ||
|
f7fcc74c68 | ||
|
0eebf8b2d0 | ||
|
95f8b08a19 | ||
|
2a7359c1e9 | ||
|
86bfaa8657 | ||
|
8c066eb521 | ||
|
9e08af3306 | ||
|
95f7a1e312 | ||
|
73271018f5 | ||
|
7111109ac0 | ||
|
e3c83823e6 | ||
|
3b11a90aac | ||
|
bc29c67269 | ||
|
4a93551ef9 | ||
|
d0ff4320a8 | ||
|
20b70c2728 | ||
|
6aab2e27cd | ||
|
a34ad80a90 | ||
|
5a22f27b64 | ||
|
776ba77c3a | ||
|
3cf01d9123 | ||
|
2ab9f168d2 | ||
|
038a30dcca | ||
|
ddc40537d5 | ||
|
bd23a05a88 | ||
|
76f1e1c005 | ||
|
40c9816827 | ||
|
a7f742931e | ||
|
a361240692 | ||
|
fe6897baf4 | ||
|
18578521cf | ||
|
4b71c50fb2 | ||
|
7ec7904691 | ||
|
34992438ed | ||
|
af721510e1 | ||
|
393c70f6e6 | ||
|
d28bcbd5e9 | ||
|
03e3737e69 | ||
|
a5fe9ec133 | ||
|
6633ae223c | ||
|
1dd9d6ba7b | ||
|
1a00678e46 | ||
|
77944b4367 | ||
|
9b889ef751 | ||
|
ccecb9005c | ||
|
ccb700376a | ||
|
f574359432 | ||
|
ba690c0615 | ||
|
ccf955f43e | ||
|
856b1ebf8c | ||
|
b1448e13b5 | ||
|
224eb3d0e8 | ||
|
4158628475 | ||
|
e88bd1caf7 | ||
|
27ba2acf86 | ||
|
4efba2b953 | ||
|
f64e9e7c66 | ||
|
6cd8718ac8 | ||
|
eb72c70520 | ||
|
ca06333c48 | ||
|
325ffc4443 | ||
|
89bddbd8fd | ||
|
de62d2776c | ||
|
9aa1622929 | ||
|
9dbb7ab703 | ||
|
8307a9a0df | ||
|
a354ca197e | ||
|
12cb0825ca | ||
|
cc8e241213 | ||
|
14fd9b4af8 | ||
|
9fe39603c3 | ||
|
707371603d | ||
|
632a26d3cb | ||
|
262205b615 | ||
|
131723317b | ||
|
71c8719f88 | ||
|
2afa9ca80a |
.devcontainer
.drone.yml.github/workflows
analysis.ymlassembleFlavors.ymlcodeql.ymlpr-feedback.ymlrenovate-approve-merge.ymlreuse.ymlscorecard.ymlunit-tests.yml
CHANGELOG.mdapp
build.gradle
schemas/com.nextcloud.talk.data.source.local.TalkDatabase
src/main
java/com/nextcloud/talk
account
AccountVerificationActivity.ktServerSelectionActivity.ktSwitchAccountActivity.ktWebViewLoginActivity.kt
activities
adapters
items
messages
bottomsheet/items
call/components
chat
components
contacts
conversationcreation
conversationinfo
conversationinfoedit
conversationlist
data
database
source/local
diagnose
fullscreenfile
invitation
location
messagesearch
models/json/chat
openconversations
profile
receivers
settings
shareditems/activities
translate/ui
ui/dialog
utils
res
drawable-night
drawable
baseline_error_24.xmlbaseline_image_24.xmlbaseline_info_24.xmlbaseline_insert_drive_file_24.xmlbaseline_location_pin_24.xmlbaseline_lock_open_24.xmlbaseline_mic_24.xmlbaseline_notifications_24.xmlbaseline_photo_library_24.xmlbaseline_report_problem_24.xmlic_account_plus.xmlic_avatar_group.xmlic_avatar_mail.xmlic_baseline_do_not_touch_24.xmlic_baseline_flash_off_24.xmlic_baseline_flash_on_24.xmlic_baseline_headset_mic_24.xmlic_baseline_keyboard_24.xmlic_baseline_location_on_24.xmlic_baseline_mic_24.xmlic_baseline_mic_red_24.xmlic_baseline_notifications_off_24.xmlic_baseline_person_24.xml
@ -1,4 +1,4 @@
|
|||||||
FROM ubuntu:noble@sha256:6015f66923d7afbc53558d7ccffd325d43b4e249f41a6e93eef074c9505d2233
|
FROM ubuntu:noble@sha256:440dcf6a5640b2ae5c77724e68787a906afb8ddee98bf86db94eea8528c2c076
|
||||||
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
ENV ANDROID_HOME=/usr/lib/android-sdk
|
ENV ANDROID_HOME=/usr/lib/android-sdk
|
||||||
|
10
.drone.yml
10
.drone.yml
@ -8,7 +8,7 @@ name: generic
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: generic
|
- name: generic
|
||||||
image: ghcr.io/nextcloud/continuous-integration-android8:3
|
image: ghcr.io/nextcloud/continuous-integration-android8:4
|
||||||
commands:
|
commands:
|
||||||
- ./gradlew --console=plain assembleGeneric
|
- ./gradlew --console=plain assembleGeneric
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ name: gplay
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: gplay
|
- name: gplay
|
||||||
image: ghcr.io/nextcloud/continuous-integration-android8:3
|
image: ghcr.io/nextcloud/continuous-integration-android8:4
|
||||||
commands:
|
commands:
|
||||||
- ./gradlew --console=plain assembleGplay
|
- ./gradlew --console=plain assembleGplay
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ name: tests
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: all
|
- name: all
|
||||||
image: ghcr.io/nextcloud/continuous-integration-android8:3
|
image: ghcr.io/nextcloud/continuous-integration-android8:4
|
||||||
privileged: true
|
privileged: true
|
||||||
commands:
|
commands:
|
||||||
- emulator -avd android -no-snapshot -gpu swiftshader_indirect -no-window -no-audio -skin 500x833 &
|
- emulator -avd android -no-snapshot -gpu swiftshader_indirect -no-window -no-audio -skin 500x833 &
|
||||||
@ -81,4 +81,6 @@ trigger:
|
|||||||
- pull_request
|
- pull_request
|
||||||
---
|
---
|
||||||
kind: signature
|
kind: signature
|
||||||
hmac: cdce3f7eea46ef85c0223f62f66d1fe53d7dad007ef095c9f70fa063450d8c75
|
hmac: cf0c19e54fa45d1ee226f5f05202a32329b90aaf46711ea073c566a4c4a8a6c5
|
||||||
|
|
||||||
|
...
|
||||||
|
2
.github/workflows/analysis.yml
vendored
2
.github/workflows/analysis.yml
vendored
@ -29,7 +29,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Disabled on forks
|
- name: Disabled on forks
|
||||||
if: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
|
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }}
|
||||||
run: |
|
run: |
|
||||||
echo 'Can not analyze PRs from forks'
|
echo 'Can not analyze PRs from forks'
|
||||||
exit 1
|
exit 1
|
||||||
|
2
.github/workflows/assembleFlavors.yml
vendored
2
.github/workflows/assembleFlavors.yml
vendored
@ -34,7 +34,7 @@ jobs:
|
|||||||
java-version: 17
|
java-version: 17
|
||||||
|
|
||||||
- name: Gradle validate
|
- name: Gradle validate
|
||||||
uses: gradle/actions/wrapper-validation@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0
|
uses: gradle/actions/wrapper-validation@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||||
|
|
||||||
- name: Build ${{ matrix.flavor }}
|
- name: Build ${{ matrix.flavor }}
|
||||||
run: |
|
run: |
|
||||||
|
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
@ -43,7 +43,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
swap-size-gb: 10
|
swap-size-gb: 10
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 17
|
||||||
@ -57,4 +57,4 @@ jobs:
|
|||||||
echo "org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > "$HOME/.gradle/gradle.properties"
|
echo "org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > "$HOME/.gradle/gradle.properties"
|
||||||
./gradlew assembleDebug
|
./gradlew assembleDebug
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
|
||||||
|
2
.github/workflows/pr-feedback.yml
vendored
2
.github/workflows/pr-feedback.yml
vendored
@ -36,7 +36,7 @@ jobs:
|
|||||||
blocklist=$(curl https://raw.githubusercontent.com/nextcloud/.github/master/non-community-usernames.txt | paste -s -d, -)
|
blocklist=$(curl https://raw.githubusercontent.com/nextcloud/.github/master/non-community-usernames.txt | paste -s -d, -)
|
||||||
echo "blocklist=$blocklist" >> "$GITHUB_OUTPUT"
|
echo "blocklist=$blocklist" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- uses: nextcloud/pr-feedback-action@1883b38a033fb16f576875e0cf45f98b857655c4 # main
|
- uses: nextcloud/pr-feedback-action@e397f3c7e655092b746e3610d121545530c6a90e # main
|
||||||
with:
|
with:
|
||||||
feedback-message: |
|
feedback-message: |
|
||||||
Hello there,
|
Hello there,
|
||||||
|
19
.github/workflows/renovate-approve-merge.yml
vendored
19
.github/workflows/renovate-approve-merge.yml
vendored
@ -29,8 +29,6 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
# for hmarr/auto-approve-action to approve PRs
|
# for hmarr/auto-approve-action to approve PRs
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
# for alexwilson/enable-github-automerge-action to approve PRs
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Disabled on forks
|
- name: Disabled on forks
|
||||||
@ -46,13 +44,18 @@ jobs:
|
|||||||
|
|
||||||
# GitHub actions bot approve
|
# GitHub actions bot approve
|
||||||
- uses: hmarr/auto-approve-action@f0939ea97e9205ef24d872e76833fa908a770363 # v4.0.0
|
- uses: hmarr/auto-approve-action@f0939ea97e9205ef24d872e76833fa908a770363 # v4.0.0
|
||||||
if: startsWith(steps.branchname.outputs.branch, 'renovate/')
|
if: github.actor == 'renovate[bot]'
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
# Enable GitHub auto merge
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- name: Auto merge
|
|
||||||
uses: alexwilson/enable-github-automerge-action@56e3117d1ae1540309dc8f7a9f2825bc3c5f06ff # v2.0.0
|
|
||||||
if: startsWith(steps.branchname.outputs.branch, 'renovate/')
|
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
ref: ${{ github.head_ref }}
|
||||||
|
|
||||||
|
# Enable GitHub auto merge
|
||||||
|
- name: Enable Pull Request Automerge
|
||||||
|
if: github.actor == 'renovate[bot]'
|
||||||
|
run: gh pr merge --merge --auto
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.AUTOMERGE }}
|
||||||
|
|
||||||
|
2
.github/workflows/reuse.yml
vendored
2
.github/workflows/reuse.yml
vendored
@ -16,7 +16,7 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
reuse-compliance-check:
|
reuse-compliance-check:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest-low
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
2
.github/workflows/scorecard.yml
vendored
2
.github/workflows/scorecard.yml
vendored
@ -42,6 +42,6 @@ jobs:
|
|||||||
|
|
||||||
# Upload the results to GitHub's code scanning dashboard.
|
# Upload the results to GitHub's code scanning dashboard.
|
||||||
- name: "Upload to code-scanning"
|
- name: "Upload to code-scanning"
|
||||||
uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
|
2
.github/workflows/unit-tests.yml
vendored
2
.github/workflows/unit-tests.yml
vendored
@ -33,7 +33,7 @@ jobs:
|
|||||||
java-version: 17
|
java-version: 17
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0
|
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||||
|
|
||||||
- name: Run unit tests with coverage
|
- name: Run unit tests with coverage
|
||||||
run: ./gradlew testGplayDebugUnit
|
run: ./gradlew testGplayDebugUnit
|
||||||
|
30
CHANGELOG.md
30
CHANGELOG.md
@ -9,6 +9,36 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
Types of changes can be: Added/Changed/Deprecated/Removed/Fixed/Security
|
Types of changes can be: Added/Changed/Deprecated/Removed/Fixed/Security
|
||||||
|
|
||||||
|
## [21.1.0] - 2025-06-05
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Allow adding participants to one-to-one chats creating a new conversation
|
||||||
|
- Handling of event conversations
|
||||||
|
- Show info about participant (organization, role, timezone, ...) in 1:1 conversation info screen
|
||||||
|
- Added gallery option in chat attachment menu (access photos and videos with one click without giving permissions)
|
||||||
|
- Add self-test button for push notifications in diagnosis screen
|
||||||
|
- Edit checkbox in chat messages
|
||||||
|
- Team mentions in chat
|
||||||
|
- Add option to mark a conversation as sensitive
|
||||||
|
- Allow bluetooth headset to be discovered and used during a call (@gavine99)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Design of participants grid in call
|
||||||
|
- Improve subline in conversations screen when last message is attachment
|
||||||
|
- Improve message search
|
||||||
|
- In search window, show messages at last
|
||||||
|
- Switch video capture for calls between 4:3 and 16:9 ratio depending on portrait/ landscape mode
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Crashes
|
||||||
|
- Videos in videocall lost after app comes back to foreground
|
||||||
|
- Open conversations not being shown in search
|
||||||
|
- Minor bugs (@MmAaXx500)
|
||||||
|
|
||||||
|
Minimum: NC 17 Server, Android 8.0 Oreo
|
||||||
|
|
||||||
|
For a full list, please see https://github.com/nextcloud/talk-android/milestone/94?closed=1
|
||||||
|
|
||||||
## [21.0.1] - 2025-04-15
|
## [21.0.1] - 2025-04-15
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -13,9 +13,9 @@ import com.github.spotbugs.snom.Effort
|
|||||||
import com.github.spotbugs.snom.SpotBugsTask
|
import com.github.spotbugs.snom.SpotBugsTask
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "org.jetbrains.kotlin.plugin.compose" version "2.1.21"
|
id "org.jetbrains.kotlin.plugin.compose" version "2.2.0"
|
||||||
id "org.jetbrains.kotlin.kapt"
|
id "org.jetbrains.kotlin.kapt"
|
||||||
id 'com.google.devtools.ksp' version '2.1.21-2.0.1'
|
id 'com.google.devtools.ksp' version '2.2.0-2.0.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
@ -28,19 +28,19 @@ apply plugin: "org.jlleitschuh.gradle.ktlint"
|
|||||||
apply plugin: 'kotlinx-serialization'
|
apply plugin: 'kotlinx-serialization'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 34
|
compileSdk 35
|
||||||
|
|
||||||
namespace 'com.nextcloud.talk'
|
namespace 'com.nextcloud.talk'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 26
|
minSdkVersion 26
|
||||||
targetSdkVersion 34
|
targetSdkVersion 35
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
// mayor.minor.hotfix.increment (for increment: 01-50=Alpha / 51-89=RC / 90-99=stable)
|
// mayor.minor.hotfix.increment (for increment: 01-50=Alpha / 51-89=RC / 90-99=stable)
|
||||||
// xx .xxx .xx .xx
|
// xx .xxx .xx .xx
|
||||||
versionCode 220000004
|
versionCode 220000009
|
||||||
versionName "22.0.0 Alpha 04"
|
versionName "22.0.0 Alpha 09"
|
||||||
|
|
||||||
flavorDimensions "default"
|
flavorDimensions "default"
|
||||||
renderscriptTargetApi 19
|
renderscriptTargetApi 19
|
||||||
@ -155,18 +155,18 @@ ext {
|
|||||||
daggerVersion = "2.56.2"
|
daggerVersion = "2.56.2"
|
||||||
emojiVersion = "1.5.0"
|
emojiVersion = "1.5.0"
|
||||||
fidoVersion = "4.1.0-patch2"
|
fidoVersion = "4.1.0-patch2"
|
||||||
lifecycleVersion = '2.8.7'
|
lifecycleVersion = '2.9.1'
|
||||||
okhttpVersion = "4.12.0"
|
okhttpVersion = "4.12.0"
|
||||||
markwonVersion = "4.6.2"
|
markwonVersion = "4.6.2"
|
||||||
materialDialogsVersion = "3.3.0"
|
materialDialogsVersion = "3.3.0"
|
||||||
parcelerVersion = "1.1.13"
|
parcelerVersion = "1.1.13"
|
||||||
prismVersion = "2.0.0"
|
prismVersion = "2.0.0"
|
||||||
retrofit2Version = "2.11.0"
|
retrofit2Version = "3.0.0"
|
||||||
roomVersion = "2.7.1"
|
roomVersion = "2.7.2"
|
||||||
workVersion = "2.9.1"
|
workVersion = "2.10.2"
|
||||||
espressoVersion = "3.6.1"
|
espressoVersion = "3.6.1"
|
||||||
androidxTestVersion = "1.5.0"
|
androidxTestVersion = "1.5.0"
|
||||||
media3_version = "1.4.1"
|
media3_version = "1.7.1"
|
||||||
coroutines_version = "1.10.2"
|
coroutines_version = "1.10.2"
|
||||||
mockitoKotlinVersion = "5.4.0"
|
mockitoKotlinVersion = "5.4.0"
|
||||||
}
|
}
|
||||||
@ -180,10 +180,10 @@ configurations.configureEach {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.14.0'
|
spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.14.0'
|
||||||
spotbugsPlugins 'com.mebigfatguy.fb-contrib:fb-contrib:7.6.9'
|
spotbugsPlugins 'com.mebigfatguy.fb-contrib:fb-contrib:7.6.11'
|
||||||
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.8")
|
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.8")
|
||||||
|
|
||||||
implementation("androidx.compose.runtime:runtime:1.7.8")
|
implementation("androidx.compose.runtime:runtime:1.8.3")
|
||||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||||
implementation 'androidx.datastore:datastore-core:1.1.7'
|
implementation 'androidx.datastore:datastore-core:1.1.7'
|
||||||
implementation 'androidx.datastore:datastore-preferences:1.1.7'
|
implementation 'androidx.datastore:datastore-preferences:1.1.7'
|
||||||
@ -191,9 +191,9 @@ dependencies {
|
|||||||
|
|
||||||
implementation fileTree(include: ['*'], dir: 'libs')
|
implementation fileTree(include: ['*'], dir: 'libs')
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1"
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0"
|
||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
implementation 'androidx.appcompat:appcompat:1.7.1'
|
||||||
implementation 'com.google.android.material:material:1.12.0'
|
implementation 'com.google.android.material:material:1.12.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.2.1'
|
implementation 'androidx.constraintlayout:constraintlayout:2.2.1'
|
||||||
implementation "com.vanniktech:emoji-google:0.21.0"
|
implementation "com.vanniktech:emoji-google:0.21.0"
|
||||||
@ -236,7 +236,7 @@ dependencies {
|
|||||||
implementation "com.squareup.okhttp3:logging-interceptor:${okhttpVersion}"
|
implementation "com.squareup.okhttp3:logging-interceptor:${okhttpVersion}"
|
||||||
|
|
||||||
implementation 'com.bluelinelabs:logansquare:1.3.7'
|
implementation 'com.bluelinelabs:logansquare:1.3.7'
|
||||||
implementation 'com.fasterxml.jackson.core:jackson-core:2.14.3'
|
implementation 'com.fasterxml.jackson.core:jackson-core:2.19.1'
|
||||||
kapt 'com.bluelinelabs:logansquare-compiler:1.3.7'
|
kapt 'com.bluelinelabs:logansquare-compiler:1.3.7'
|
||||||
|
|
||||||
implementation "com.squareup.retrofit2:retrofit:${retrofit2Version}"
|
implementation "com.squareup.retrofit2:retrofit:${retrofit2Version}"
|
||||||
@ -301,24 +301,24 @@ dependencies {
|
|||||||
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
|
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
|
||||||
})
|
})
|
||||||
|
|
||||||
implementation 'androidx.core:core-ktx:1.13.1'
|
implementation 'androidx.core:core-ktx:1.16.0'
|
||||||
implementation 'androidx.activity:activity-ktx:1.9.3'
|
implementation 'androidx.activity:activity-ktx:1.10.1'
|
||||||
implementation 'com.github.nextcloud.android-common:ui:0.23.2'
|
implementation 'com.github.nextcloud.android-common:ui:0.26.0'
|
||||||
implementation 'com.github.nextcloud-deps:android-talk-webrtc:132.6834.0'
|
implementation 'com.github.nextcloud-deps:android-talk-webrtc:132.6834.0'
|
||||||
|
|
||||||
gplayImplementation 'com.google.android.gms:play-services-base:18.6.0'
|
gplayImplementation 'com.google.android.gms:play-services-base:18.6.0'
|
||||||
gplayImplementation "com.google.firebase:firebase-messaging:24.1.1"
|
gplayImplementation "com.google.firebase:firebase-messaging:24.1.2"
|
||||||
|
|
||||||
//compose
|
//compose
|
||||||
implementation(platform("androidx.compose:compose-bom:2025.04.00"))
|
implementation(platform("androidx.compose:compose-bom:2025.06.01"))
|
||||||
implementation("androidx.compose.ui:ui")
|
implementation("androidx.compose.ui:ui")
|
||||||
implementation 'androidx.compose.material3:material3:1.3.2'
|
implementation 'androidx.compose.material3:material3:1.3.2'
|
||||||
implementation("androidx.compose.ui:ui-tooling-preview")
|
implementation("androidx.compose.ui:ui-tooling-preview")
|
||||||
implementation 'androidx.activity:activity-compose:1.9.3'
|
implementation 'androidx.activity:activity-compose:1.10.1'
|
||||||
debugImplementation("androidx.compose.ui:ui-tooling")
|
debugImplementation("androidx.compose.ui:ui-tooling")
|
||||||
|
|
||||||
//tests
|
//tests
|
||||||
androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.7.8")
|
androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.8.3")
|
||||||
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
@ -343,11 +343,11 @@ dependencies {
|
|||||||
|
|
||||||
androidTestImplementation('com.android.support.test.espresso:espresso-intents:3.0.2')
|
androidTestImplementation('com.android.support.test.espresso:espresso-intents:3.0.2')
|
||||||
|
|
||||||
androidTestImplementation(platform("androidx.compose:compose-bom:2025.04.00"))
|
androidTestImplementation(platform("androidx.compose:compose-bom:2025.06.01"))
|
||||||
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
|
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
|
||||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
|
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
|
||||||
|
|
||||||
testImplementation 'org.junit.vintage:junit-vintage-engine:5.13.0'
|
testImplementation 'org.junit.vintage:junit-vintage-engine:5.13.3'
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('installGitHooks', Copy) {
|
tasks.register('installGitHooks', Copy) {
|
||||||
|
@ -0,0 +1,730 @@
|
|||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 17,
|
||||||
|
"identityHash": "5bc4247e179307faa995552da5d34324",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "User",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `userId` TEXT, `username` TEXT, `baseUrl` TEXT, `token` TEXT, `displayName` TEXT, `pushConfigurationState` TEXT, `capabilities` TEXT, `serverVersion` TEXT DEFAULT '', `clientCertificate` TEXT, `externalSignalingServer` TEXT, `current` INTEGER NOT NULL, `scheduledForDeletion` INTEGER NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "userId",
|
||||||
|
"columnName": "userId",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "username",
|
||||||
|
"columnName": "username",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "baseUrl",
|
||||||
|
"columnName": "baseUrl",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "token",
|
||||||
|
"columnName": "token",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "displayName",
|
||||||
|
"columnName": "displayName",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "pushConfigurationState",
|
||||||
|
"columnName": "pushConfigurationState",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "capabilities",
|
||||||
|
"columnName": "capabilities",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serverVersion",
|
||||||
|
"columnName": "serverVersion",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"defaultValue": "''"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "clientCertificate",
|
||||||
|
"columnName": "clientCertificate",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "externalSignalingServer",
|
||||||
|
"columnName": "externalSignalingServer",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "current",
|
||||||
|
"columnName": "current",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "scheduledForDeletion",
|
||||||
|
"columnName": "scheduledForDeletion",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "ArbitraryStorage",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountIdentifier` INTEGER NOT NULL, `key` TEXT NOT NULL, `object` TEXT, `value` TEXT, PRIMARY KEY(`accountIdentifier`, `key`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "accountIdentifier",
|
||||||
|
"columnName": "accountIdentifier",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "key",
|
||||||
|
"columnName": "key",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "storageObject",
|
||||||
|
"columnName": "object",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "value",
|
||||||
|
"columnName": "value",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"accountIdentifier",
|
||||||
|
"key"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Conversations",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`internalId` TEXT NOT NULL, `accountId` INTEGER NOT NULL, `token` TEXT NOT NULL, `displayName` TEXT NOT NULL, `actorId` TEXT NOT NULL, `actorType` TEXT NOT NULL, `avatarVersion` TEXT NOT NULL, `callFlag` INTEGER NOT NULL, `callRecording` INTEGER NOT NULL, `callStartTime` INTEGER NOT NULL, `canDeleteConversation` INTEGER NOT NULL, `canLeaveConversation` INTEGER NOT NULL, `canStartCall` INTEGER NOT NULL, `description` TEXT NOT NULL, `hasCall` INTEGER NOT NULL, `hasPassword` INTEGER NOT NULL, `isCustomAvatar` INTEGER NOT NULL, `isFavorite` INTEGER NOT NULL, `lastActivity` INTEGER NOT NULL, `lastCommonReadMessage` INTEGER NOT NULL, `lastMessage` TEXT, `lastPing` INTEGER NOT NULL, `lastReadMessage` INTEGER NOT NULL, `lobbyState` TEXT NOT NULL, `lobbyTimer` INTEGER NOT NULL, `messageExpiration` INTEGER NOT NULL, `name` TEXT NOT NULL, `notificationCalls` INTEGER NOT NULL, `notificationLevel` TEXT NOT NULL, `objectType` TEXT NOT NULL, `objectId` TEXT NOT NULL, `participantType` TEXT NOT NULL, `permissions` INTEGER NOT NULL, `readOnly` TEXT NOT NULL, `recordingConsent` INTEGER NOT NULL, `remoteServer` TEXT, `remoteToken` TEXT, `sessionId` TEXT NOT NULL, `status` TEXT, `statusClearAt` INTEGER, `statusIcon` TEXT, `statusMessage` TEXT, `type` TEXT NOT NULL, `unreadMention` INTEGER NOT NULL, `unreadMentionDirect` INTEGER NOT NULL, `unreadMessages` INTEGER NOT NULL, `hasArchived` INTEGER NOT NULL, `hasSensitive` INTEGER NOT NULL, `hasImportant` INTEGER NOT NULL, PRIMARY KEY(`internalId`), FOREIGN KEY(`accountId`) REFERENCES `User`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "internalId",
|
||||||
|
"columnName": "internalId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "accountId",
|
||||||
|
"columnName": "accountId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "token",
|
||||||
|
"columnName": "token",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "displayName",
|
||||||
|
"columnName": "displayName",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "actorId",
|
||||||
|
"columnName": "actorId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "actorType",
|
||||||
|
"columnName": "actorType",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "avatarVersion",
|
||||||
|
"columnName": "avatarVersion",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "callFlag",
|
||||||
|
"columnName": "callFlag",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "callRecording",
|
||||||
|
"columnName": "callRecording",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "callStartTime",
|
||||||
|
"columnName": "callStartTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "canDeleteConversation",
|
||||||
|
"columnName": "canDeleteConversation",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "canLeaveConversation",
|
||||||
|
"columnName": "canLeaveConversation",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "canStartCall",
|
||||||
|
"columnName": "canStartCall",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "description",
|
||||||
|
"columnName": "description",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasCall",
|
||||||
|
"columnName": "hasCall",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasPassword",
|
||||||
|
"columnName": "hasPassword",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasCustomAvatar",
|
||||||
|
"columnName": "isCustomAvatar",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "favorite",
|
||||||
|
"columnName": "isFavorite",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastActivity",
|
||||||
|
"columnName": "lastActivity",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastCommonReadMessage",
|
||||||
|
"columnName": "lastCommonReadMessage",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastMessage",
|
||||||
|
"columnName": "lastMessage",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastPing",
|
||||||
|
"columnName": "lastPing",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastReadMessage",
|
||||||
|
"columnName": "lastReadMessage",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lobbyState",
|
||||||
|
"columnName": "lobbyState",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lobbyTimer",
|
||||||
|
"columnName": "lobbyTimer",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "messageExpiration",
|
||||||
|
"columnName": "messageExpiration",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "notificationCalls",
|
||||||
|
"columnName": "notificationCalls",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "notificationLevel",
|
||||||
|
"columnName": "notificationLevel",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "objectType",
|
||||||
|
"columnName": "objectType",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "objectId",
|
||||||
|
"columnName": "objectId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "participantType",
|
||||||
|
"columnName": "participantType",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "permissions",
|
||||||
|
"columnName": "permissions",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "conversationReadOnlyState",
|
||||||
|
"columnName": "readOnly",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "recordingConsentRequired",
|
||||||
|
"columnName": "recordingConsent",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "remoteServer",
|
||||||
|
"columnName": "remoteServer",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "remoteToken",
|
||||||
|
"columnName": "remoteToken",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "sessionId",
|
||||||
|
"columnName": "sessionId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "status",
|
||||||
|
"columnName": "status",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "statusClearAt",
|
||||||
|
"columnName": "statusClearAt",
|
||||||
|
"affinity": "INTEGER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "statusIcon",
|
||||||
|
"columnName": "statusIcon",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "statusMessage",
|
||||||
|
"columnName": "statusMessage",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "unreadMention",
|
||||||
|
"columnName": "unreadMention",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "unreadMentionDirect",
|
||||||
|
"columnName": "unreadMentionDirect",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "unreadMessages",
|
||||||
|
"columnName": "unreadMessages",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasArchived",
|
||||||
|
"columnName": "hasArchived",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasSensitive",
|
||||||
|
"columnName": "hasSensitive",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasImportant",
|
||||||
|
"columnName": "hasImportant",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"internalId"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_Conversations_accountId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"accountId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Conversations_accountId` ON `${TABLE_NAME}` (`accountId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "User",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"accountId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "ChatMessages",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`internalId` TEXT NOT NULL, `accountId` INTEGER NOT NULL, `token` TEXT NOT NULL, `id` INTEGER NOT NULL, `internalConversationId` TEXT NOT NULL, `actorDisplayName` TEXT NOT NULL, `message` TEXT NOT NULL, `actorId` TEXT NOT NULL, `actorType` TEXT NOT NULL, `deleted` INTEGER NOT NULL, `expirationTimestamp` INTEGER NOT NULL, `isReplyable` INTEGER NOT NULL, `isTemporary` INTEGER NOT NULL, `lastEditActorDisplayName` TEXT, `lastEditActorId` TEXT, `lastEditActorType` TEXT, `lastEditTimestamp` INTEGER, `markdown` INTEGER, `messageParameters` TEXT, `messageType` TEXT NOT NULL, `parent` INTEGER, `reactions` TEXT, `reactionsSelf` TEXT, `referenceId` TEXT, `sendStatus` TEXT, `silent` INTEGER NOT NULL, `systemMessage` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, PRIMARY KEY(`internalId`), FOREIGN KEY(`internalConversationId`) REFERENCES `Conversations`(`internalId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "internalId",
|
||||||
|
"columnName": "internalId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "accountId",
|
||||||
|
"columnName": "accountId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "token",
|
||||||
|
"columnName": "token",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "internalConversationId",
|
||||||
|
"columnName": "internalConversationId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "actorDisplayName",
|
||||||
|
"columnName": "actorDisplayName",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "message",
|
||||||
|
"columnName": "message",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "actorId",
|
||||||
|
"columnName": "actorId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "actorType",
|
||||||
|
"columnName": "actorType",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "deleted",
|
||||||
|
"columnName": "deleted",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "expirationTimestamp",
|
||||||
|
"columnName": "expirationTimestamp",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "replyable",
|
||||||
|
"columnName": "isReplyable",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "isTemporary",
|
||||||
|
"columnName": "isTemporary",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastEditActorDisplayName",
|
||||||
|
"columnName": "lastEditActorDisplayName",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastEditActorId",
|
||||||
|
"columnName": "lastEditActorId",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastEditActorType",
|
||||||
|
"columnName": "lastEditActorType",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastEditTimestamp",
|
||||||
|
"columnName": "lastEditTimestamp",
|
||||||
|
"affinity": "INTEGER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "renderMarkdown",
|
||||||
|
"columnName": "markdown",
|
||||||
|
"affinity": "INTEGER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "messageParameters",
|
||||||
|
"columnName": "messageParameters",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "messageType",
|
||||||
|
"columnName": "messageType",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "parentMessageId",
|
||||||
|
"columnName": "parent",
|
||||||
|
"affinity": "INTEGER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "reactions",
|
||||||
|
"columnName": "reactions",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "reactionsSelf",
|
||||||
|
"columnName": "reactionsSelf",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "referenceId",
|
||||||
|
"columnName": "referenceId",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "sendStatus",
|
||||||
|
"columnName": "sendStatus",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "silent",
|
||||||
|
"columnName": "silent",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "systemMessageType",
|
||||||
|
"columnName": "systemMessage",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "timestamp",
|
||||||
|
"columnName": "timestamp",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"internalId"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_ChatMessages_internalId",
|
||||||
|
"unique": true,
|
||||||
|
"columnNames": [
|
||||||
|
"internalId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_ChatMessages_internalId` ON `${TABLE_NAME}` (`internalId`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_ChatMessages_internalConversationId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"internalConversationId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_ChatMessages_internalConversationId` ON `${TABLE_NAME}` (`internalConversationId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "Conversations",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"internalConversationId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"internalId"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "ChatBlocks",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `internalConversationId` TEXT NOT NULL, `accountId` INTEGER, `token` TEXT, `oldestMessageId` INTEGER NOT NULL, `newestMessageId` INTEGER NOT NULL, `hasHistory` INTEGER NOT NULL, FOREIGN KEY(`internalConversationId`) REFERENCES `Conversations`(`internalId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "internalConversationId",
|
||||||
|
"columnName": "internalConversationId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "accountId",
|
||||||
|
"columnName": "accountId",
|
||||||
|
"affinity": "INTEGER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "token",
|
||||||
|
"columnName": "token",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "oldestMessageId",
|
||||||
|
"columnName": "oldestMessageId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "newestMessageId",
|
||||||
|
"columnName": "newestMessageId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasHistory",
|
||||||
|
"columnName": "hasHistory",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_ChatBlocks_internalConversationId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"internalConversationId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_ChatBlocks_internalConversationId` ON `${TABLE_NAME}` (`internalConversationId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "Conversations",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"internalConversationId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"internalId"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5bc4247e179307faa995552da5d34324')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -91,7 +91,7 @@ class AccountVerificationActivity : BaseActivity() {
|
|||||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
actionBar?.hide()
|
actionBar?.hide()
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
|
|
||||||
handleIntent()
|
handleIntent()
|
||||||
}
|
}
|
||||||
@ -490,9 +490,9 @@ class AccountVerificationActivity : BaseActivity() {
|
|||||||
WorkManager.getInstance(applicationContext).enqueue(accountRemovalWork)
|
WorkManager.getInstance(applicationContext).enqueue(accountRemovalWork)
|
||||||
|
|
||||||
WorkManager.getInstance(context).getWorkInfoByIdLiveData(accountRemovalWork.id)
|
WorkManager.getInstance(context).getWorkInfoByIdLiveData(accountRemovalWork.id)
|
||||||
.observeForever { workInfo: WorkInfo ->
|
.observeForever { workInfo: WorkInfo? ->
|
||||||
|
|
||||||
when (workInfo.state) {
|
when (workInfo?.state) {
|
||||||
WorkInfo.State.SUCCEEDED -> {
|
WorkInfo.State.SUCCEEDED -> {
|
||||||
val intent = Intent(this, ServerSelectionActivity::class.java)
|
val intent = Intent(this, ServerSelectionActivity::class.java)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
|
@ -78,7 +78,7 @@ class ServerSelectionActivity : BaseActivity() {
|
|||||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
actionBar?.hide()
|
actionBar?.hide()
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
|
|
||||||
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
|
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ class SwitchAccountActivity : BaseActivity() {
|
|||||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
|
|
||||||
Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context))
|
Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context))
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ class WebViewLoginActivity : BaseActivity() {
|
|||||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
actionBar?.hide()
|
actionBar?.hide()
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
|
|
||||||
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
|
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
|
||||||
handleIntent()
|
handleIntent()
|
||||||
@ -286,6 +286,7 @@ class WebViewLoginActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("DiscouragedPrivateApi")
|
||||||
@Suppress("Detekt.TooGenericExceptionCaught")
|
@Suppress("Detekt.TooGenericExceptionCaught")
|
||||||
override fun onReceivedSslError(view: WebView, handler: SslErrorHandler, error: SslError) {
|
override fun onReceivedSslError(view: WebView, handler: SslErrorHandler, error: SslError) {
|
||||||
try {
|
try {
|
||||||
@ -388,9 +389,9 @@ class WebViewLoginActivity : BaseActivity() {
|
|||||||
WorkManager.getInstance(applicationContext).enqueue(accountRemovalWork)
|
WorkManager.getInstance(applicationContext).enqueue(accountRemovalWork)
|
||||||
|
|
||||||
WorkManager.getInstance(context).getWorkInfoByIdLiveData(accountRemovalWork.id)
|
WorkManager.getInstance(context).getWorkInfoByIdLiveData(accountRemovalWork.id)
|
||||||
.observeForever { workInfo: WorkInfo ->
|
.observeForever { workInfo: WorkInfo? ->
|
||||||
|
|
||||||
when (workInfo.state) {
|
when (workInfo?.state) {
|
||||||
WorkInfo.State.SUCCEEDED, WorkInfo.State.FAILED, WorkInfo.State.CANCELLED -> {
|
WorkInfo.State.SUCCEEDED, WorkInfo.State.FAILED, WorkInfo.State.CANCELLED -> {
|
||||||
restartApp()
|
restartApp()
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,13 @@ package com.nextcloud.talk.activities
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.WindowInsets
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.webkit.SslErrorHandler
|
import android.webkit.SslErrorHandler
|
||||||
@ -37,6 +39,7 @@ import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
|||||||
import com.nextcloud.talk.utils.DisplayUtils
|
import com.nextcloud.talk.utils.DisplayUtils
|
||||||
import com.nextcloud.talk.utils.FileViewerUtils
|
import com.nextcloud.talk.utils.FileViewerUtils
|
||||||
import com.nextcloud.talk.utils.UriUtils
|
import com.nextcloud.talk.utils.UriUtils
|
||||||
|
import com.nextcloud.talk.utils.adjustUIForAPILevel35
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
|
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
|
||||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
@ -81,6 +84,7 @@ open class BaseActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||||
|
adjustUIForAPILevel35()
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
cleanTempCertPreference()
|
cleanTempCertPreference()
|
||||||
@ -111,10 +115,23 @@ open class BaseActivity : AppCompatActivity() {
|
|||||||
eventBus.unregister(this)
|
eventBus.unregister(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setupSystemColors() {
|
/*
|
||||||
|
* May be aligned with android-common lib in the future: .../ui/util/extensions/AppCompatActivityExtensions.kt
|
||||||
|
*/
|
||||||
|
fun initSystemBars() {
|
||||||
|
window.decorView.setOnApplyWindowInsetsListener { view, insets ->
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
||||||
|
val statusBarHeight = insets.getInsets(WindowInsets.Type.statusBars()).top
|
||||||
|
view.setPadding(0, statusBarHeight, 0, 0)
|
||||||
|
val color = ResourcesCompat.getColor(resources, R.color.bg_default, context.theme)
|
||||||
|
view.setBackgroundColor(color)
|
||||||
|
} else {
|
||||||
colorizeStatusBar()
|
colorizeStatusBar()
|
||||||
colorizeNavigationBar()
|
colorizeNavigationBar()
|
||||||
}
|
}
|
||||||
|
insets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
open fun colorizeStatusBar() {
|
open fun colorizeStatusBar() {
|
||||||
if (resources != null) {
|
if (resources != null) {
|
||||||
|
@ -431,9 +431,9 @@ class ConversationItem(
|
|||||||
)
|
)
|
||||||
return lastMessage
|
return lastMessage
|
||||||
} else if (MessageType.SINGLE_NC_ATTACHMENT_MESSAGE == chatMessage?.getCalculateMessageType()) {
|
} else if (MessageType.SINGLE_NC_ATTACHMENT_MESSAGE == chatMessage?.getCalculateMessageType()) {
|
||||||
var attachmentName = chatMessage.message
|
var attachmentName = chatMessage.text
|
||||||
if (attachmentName == "{file}") {
|
if (attachmentName == "{file}") {
|
||||||
attachmentName = chatMessage.messageParameters?.get("file")?.get("name")
|
attachmentName = chatMessage.messageParameters?.get("file")?.get("name") ?: ""
|
||||||
}
|
}
|
||||||
val author = authorName(chatMessage)
|
val author = authorName(chatMessage)
|
||||||
|
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk - Android Client
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
package com.nextcloud.talk.adapters.items
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import com.nextcloud.talk.R
|
||||||
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
|
|
||||||
|
class SpacerItem(private val height: Int) : AbstractFlexibleItem<SpacerItem.ViewHolder>() {
|
||||||
|
|
||||||
|
override fun getLayoutRes(): Int = R.layout.item_spacer
|
||||||
|
|
||||||
|
override fun createViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>?>?): ViewHolder {
|
||||||
|
return ViewHolder(view!!, adapter!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bindViewHolder(
|
||||||
|
adapter: FlexibleAdapter<IFlexible<*>?>?,
|
||||||
|
holder: ViewHolder,
|
||||||
|
position: Int,
|
||||||
|
payloads: MutableList<Any>?
|
||||||
|
) {
|
||||||
|
holder.itemView.layoutParams.height = height
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?) = other is SpacerItem
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder(view: View, adapter: FlexibleAdapter<*>) :
|
||||||
|
FlexibleViewHolder(view, adapter)
|
||||||
|
}
|
@ -20,6 +20,7 @@ import autodagger.AutoInjector
|
|||||||
import coil.load
|
import coil.load
|
||||||
import com.google.android.flexbox.FlexboxLayout
|
import com.google.android.flexbox.FlexboxLayout
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
import com.nextcloud.android.common.ui.theme.utils.ColorRole
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
@ -157,7 +158,7 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
|
|||||||
binding.messageEditIndicator.visibility = View.GONE
|
binding.messageEditIndicator.visibility = View.GONE
|
||||||
binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
|
binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
|
||||||
}
|
}
|
||||||
binding.messageTime.setTextColor(ContextCompat.getColor(context, R.color.no_emphasis_text))
|
viewThemeUtils.platform.colorTextView(binding.messageTime, ColorRole.ON_SURFACE_VARIANT)
|
||||||
// parent message handling
|
// parent message handling
|
||||||
if (!message.isDeleted && message.parentMessageId != null) {
|
if (!message.isDeleted && message.parentMessageId != null) {
|
||||||
processParentMessage(message)
|
processParentMessage(message)
|
||||||
|
@ -29,6 +29,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedA
|
|||||||
import com.nextcloud.talk.chat.ChatActivity
|
import com.nextcloud.talk.chat.ChatActivity
|
||||||
import com.nextcloud.talk.chat.data.ChatMessageRepository
|
import com.nextcloud.talk.chat.data.ChatMessageRepository
|
||||||
import com.nextcloud.talk.chat.data.model.ChatMessage
|
import com.nextcloud.talk.chat.data.model.ChatMessage
|
||||||
|
import com.nextcloud.talk.data.database.model.SendStatus
|
||||||
import com.nextcloud.talk.data.network.NetworkMonitor
|
import com.nextcloud.talk.data.network.NetworkMonitor
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.ItemCustomOutcomingTextMessageBinding
|
import com.nextcloud.talk.databinding.ItemCustomOutcomingTextMessageBinding
|
||||||
@ -105,7 +106,6 @@ class OutcomingTextMessageViewHolder(itemView: View) :
|
|||||||
if (!hasCheckboxes) {
|
if (!hasCheckboxes) {
|
||||||
realView.isSelected = false
|
realView.isSelected = false
|
||||||
layoutParams.isWrapBefore = false
|
layoutParams.isWrapBefore = false
|
||||||
viewThemeUtils.platform.colorTextView(binding.messageTime, ColorRole.ON_SURFACE_VARIANT)
|
|
||||||
|
|
||||||
binding.messageText.visibility = View.VISIBLE
|
binding.messageText.visibility = View.VISIBLE
|
||||||
binding.checkboxContainer.visibility = View.GONE
|
binding.checkboxContainer.visibility = View.GONE
|
||||||
@ -172,7 +172,7 @@ class OutcomingTextMessageViewHolder(itemView: View) :
|
|||||||
binding.messageEditIndicator.visibility = View.GONE
|
binding.messageEditIndicator.visibility = View.GONE
|
||||||
binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
|
binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
|
||||||
}
|
}
|
||||||
binding.messageTime.setTextColor(ContextCompat.getColor(context, R.color.no_emphasis_text))
|
viewThemeUtils.platform.colorTextView(binding.messageTime, ColorRole.ON_SURFACE_VARIANT)
|
||||||
setBubbleOnChatMessage(message)
|
setBubbleOnChatMessage(message)
|
||||||
// parent message handling
|
// parent message handling
|
||||||
if (!message.isDeleted && message.parentMessageId != null) {
|
if (!message.isDeleted && message.parentMessageId != null) {
|
||||||
@ -185,7 +185,7 @@ class OutcomingTextMessageViewHolder(itemView: View) :
|
|||||||
binding.checkMark.visibility = View.INVISIBLE
|
binding.checkMark.visibility = View.INVISIBLE
|
||||||
binding.sendingProgress.visibility = View.GONE
|
binding.sendingProgress.visibility = View.GONE
|
||||||
|
|
||||||
if (message.sendingFailed) {
|
if (message.sendStatus == SendStatus.FAILED) {
|
||||||
updateStatus(R.drawable.baseline_error_outline_24, context.resources?.getString(R.string.nc_message_failed))
|
updateStatus(R.drawable.baseline_error_outline_24, context.resources?.getString(R.string.nc_message_failed))
|
||||||
} else if (message.isTemporary) {
|
} else if (message.isTemporary) {
|
||||||
updateStatus(R.drawable.baseline_schedule_24, context.resources?.getString(R.string.nc_message_sending))
|
updateStatus(R.drawable.baseline_schedule_24, context.resources?.getString(R.string.nc_message_sending))
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.nextcloud.talk.bottomsheet.items
|
package com.nextcloud.talk.bottomsheet.items
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
@ -65,6 +66,7 @@ internal class ListIconDialogAdapter<IT : ListItemWithImage>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListItemViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListItemViewHolder {
|
||||||
val listItemView: View = parent.inflate(dialog.windowContext, R.layout.menu_item_sheet)
|
val listItemView: View = parent.inflate(dialog.windowContext, R.layout.menu_item_sheet)
|
||||||
val viewHolder = ListItemViewHolder(
|
val viewHolder = ListItemViewHolder(
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.call.components
|
package com.nextcloud.talk.call.components
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
@ -29,6 +30,7 @@ import com.nextcloud.talk.adapters.ParticipantUiState
|
|||||||
import org.webrtc.EglBase
|
import org.webrtc.EglBase
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
|
|
||||||
|
@SuppressLint("UnusedBoxWithConstraintsScope")
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
@Composable
|
@Composable
|
||||||
fun ParticipantGrid(
|
fun ParticipantGrid(
|
||||||
@ -78,7 +80,9 @@ fun ParticipantGrid(
|
|||||||
|
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
columns = GridCells.Fixed(columns),
|
columns = GridCells.Fixed(columns),
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(availableHeight),
|
||||||
verticalArrangement = Arrangement.spacedBy(itemSpacing),
|
verticalArrangement = Arrangement.spacedBy(itemSpacing),
|
||||||
horizontalArrangement = Arrangement.spacedBy(itemSpacing),
|
horizontalArrangement = Arrangement.spacedBy(itemSpacing),
|
||||||
contentPadding = PaddingValues(vertical = edgePadding, horizontal = edgePadding)
|
contentPadding = PaddingValues(vertical = edgePadding, horizontal = edgePadding)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.call.components
|
package com.nextcloud.talk.call.components
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.BoxWithConstraints
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
@ -40,6 +41,7 @@ const val NICK_OFFSET = 4f
|
|||||||
const val NICK_BLUR_RADIUS = 4f
|
const val NICK_BLUR_RADIUS = 4f
|
||||||
const val AVATAR_SIZE_FACTOR = 0.6f
|
const val AVATAR_SIZE_FACTOR = 0.6f
|
||||||
|
|
||||||
|
@SuppressLint("UnusedBoxWithConstraintsScope")
|
||||||
@Suppress("Detekt.LongMethod")
|
@Suppress("Detekt.LongMethod")
|
||||||
@Composable
|
@Composable
|
||||||
fun ParticipantTile(
|
fun ParticipantTile(
|
||||||
|
@ -16,7 +16,6 @@ package com.nextcloud.talk.chat
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
|
||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@ -67,6 +66,8 @@ import androidx.core.graphics.drawable.toDrawable
|
|||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.text.bold
|
import androidx.core.text.bold
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.emoji2.text.EmojiCompat
|
import androidx.emoji2.text.EmojiCompat
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.fragment.app.commit
|
import androidx.fragment.app.commit
|
||||||
@ -276,6 +277,8 @@ class ChatActivity :
|
|||||||
lateinit var conversationInfoViewModel: ConversationInfoViewModel
|
lateinit var conversationInfoViewModel: ConversationInfoViewModel
|
||||||
lateinit var messageInputViewModel: MessageInputViewModel
|
lateinit var messageInputViewModel: MessageInputViewModel
|
||||||
|
|
||||||
|
private var chatMenu: Menu? = null
|
||||||
|
|
||||||
private val startSelectContactForResult = registerForActivityResult(
|
private val startSelectContactForResult = registerForActivityResult(
|
||||||
ActivityResultContracts
|
ActivityResultContracts
|
||||||
.StartActivityForResult()
|
.StartActivityForResult()
|
||||||
@ -307,16 +310,11 @@ class ChatActivity :
|
|||||||
runBlocking {
|
runBlocking {
|
||||||
val id = intent?.getStringExtra(MessageSearchActivity.RESULT_KEY_MESSAGE_ID)
|
val id = intent?.getStringExtra(MessageSearchActivity.RESULT_KEY_MESSAGE_ID)
|
||||||
id?.let {
|
id?.let {
|
||||||
val isSaved = chatViewModel.isMessageSaved(id.toLong())
|
|
||||||
if (isSaved) {
|
|
||||||
onMessageSearchResult(intent)
|
|
||||||
} else {
|
|
||||||
startContextChatWindowForMessage(id)
|
startContextChatWindowForMessage(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun startContextChatWindowForMessage(id: String?) {
|
private fun startContextChatWindowForMessage(id: String?) {
|
||||||
binding.genericComposeView.apply {
|
binding.genericComposeView.apply {
|
||||||
@ -366,6 +364,7 @@ class ChatActivity :
|
|||||||
var startCallFromRoomSwitch: Boolean = false
|
var startCallFromRoomSwitch: Boolean = false
|
||||||
|
|
||||||
var voiceOnly: Boolean = true
|
var voiceOnly: Boolean = true
|
||||||
|
var focusInput: Boolean = false
|
||||||
private lateinit var path: String
|
private lateinit var path: String
|
||||||
|
|
||||||
var myFirstMessage: CharSequence? = null
|
var myFirstMessage: CharSequence? = null
|
||||||
@ -461,7 +460,28 @@ class ChatActivity :
|
|||||||
binding = ActivityChatBinding.inflate(layoutInflater)
|
binding = ActivityChatBinding.inflate(layoutInflater)
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupSystemColors()
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.chat_container)) { view, insets ->
|
||||||
|
val statusBarInsets = insets.getInsets(WindowInsetsCompat.Type.statusBars())
|
||||||
|
val navBarInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars())
|
||||||
|
val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime())
|
||||||
|
|
||||||
|
val isKeyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
|
||||||
|
val bottomPadding = if (isKeyboardVisible) imeInsets.bottom else navBarInsets.bottom
|
||||||
|
|
||||||
|
view.setPadding(
|
||||||
|
view.paddingLeft,
|
||||||
|
statusBarInsets.top,
|
||||||
|
view.paddingRight,
|
||||||
|
bottomPadding
|
||||||
|
)
|
||||||
|
WindowInsetsCompat.CONSUMED
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
colorizeStatusBar()
|
||||||
|
colorizeNavigationBar()
|
||||||
|
}
|
||||||
|
|
||||||
conversationUser = currentUserProvider.currentUser.blockingGet()
|
conversationUser = currentUserProvider.currentUser.blockingGet()
|
||||||
handleIntent(intent)
|
handleIntent(intent)
|
||||||
@ -489,7 +509,7 @@ class ChatActivity :
|
|||||||
initObservers()
|
initObservers()
|
||||||
|
|
||||||
pickMultipleMedia = registerForActivityResult(
|
pickMultipleMedia = registerForActivityResult(
|
||||||
ActivityResultContracts.PickMultipleVisualMedia(5)
|
ActivityResultContracts.PickMultipleVisualMedia(MAX_AMOUNT_MEDIA_FILE_PICKER)
|
||||||
) { uris ->
|
) { uris ->
|
||||||
if (uris.isNotEmpty()) {
|
if (uris.isNotEmpty()) {
|
||||||
onChooseFileResult(uris)
|
onChooseFileResult(uris)
|
||||||
@ -549,6 +569,8 @@ class ChatActivity :
|
|||||||
startCallFromRoomSwitch = extras?.getBoolean(KEY_START_CALL_AFTER_ROOM_SWITCH, false) == true
|
startCallFromRoomSwitch = extras?.getBoolean(KEY_START_CALL_AFTER_ROOM_SWITCH, false) == true
|
||||||
|
|
||||||
voiceOnly = extras?.getBoolean(KEY_CALL_VOICE_ONLY, false) == true
|
voiceOnly = extras?.getBoolean(KEY_CALL_VOICE_ONLY, false) == true
|
||||||
|
|
||||||
|
focusInput = extras?.getBoolean(BundleKeys.KEY_FOCUS_INPUT) == true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
@ -640,12 +662,17 @@ class ChatActivity :
|
|||||||
supportFragmentManager.commit {
|
supportFragmentManager.commit {
|
||||||
setReorderingAllowed(true) // optimizes out redundant replace operations
|
setReorderingAllowed(true) // optimizes out redundant replace operations
|
||||||
replace(R.id.fragment_container_activity_chat, messageInputFragment)
|
replace(R.id.fragment_container_activity_chat, messageInputFragment)
|
||||||
|
runOnCommit {
|
||||||
|
if (focusInput) {
|
||||||
|
messageInputFragment.binding.fragmentMessageInputView.requestFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
joinRoomWithPassword()
|
joinRoomWithPassword()
|
||||||
|
|
||||||
if (conversationUser?.userId != "?" &&
|
if (conversationUser?.userId != "?" &&
|
||||||
CapabilitiesUtil.hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.MENTION_FLAG)
|
hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.MENTION_FLAG)
|
||||||
) {
|
) {
|
||||||
binding.chatToolbar.setOnClickListener { _ -> showConversationInfoScreen() }
|
binding.chatToolbar.setOnClickListener { _ -> showConversationInfoScreen() }
|
||||||
}
|
}
|
||||||
@ -680,7 +707,7 @@ class ChatActivity :
|
|||||||
?.split("#")
|
?.split("#")
|
||||||
?.getOrNull(1)
|
?.getOrNull(1)
|
||||||
?.toLongOrNull()
|
?.toLongOrNull()
|
||||||
val currentTimeStamp = (System.currentTimeMillis() / 1000).toLong()
|
val currentTimeStamp = (System.currentTimeMillis() / ONE_SECOND_IN_MILLIS).toLong()
|
||||||
val retentionPeriod = retentionOfEventRooms(spreedCapabilities)
|
val retentionPeriod = retentionOfEventRooms(spreedCapabilities)
|
||||||
val isPastEvent = eventEndTimeStamp?.let { it < currentTimeStamp }
|
val isPastEvent = eventEndTimeStamp?.let { it < currentTimeStamp }
|
||||||
if (isPastEvent == true && retentionPeriod != 0) {
|
if (isPastEvent == true && retentionPeriod != 0) {
|
||||||
@ -1102,6 +1129,8 @@ class ChatActivity :
|
|||||||
context.getString(R.string.nc_room_retention),
|
context.getString(R.string.nc_room_retention),
|
||||||
Snackbar.LENGTH_LONG
|
Snackbar.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
|
|
||||||
|
chatMenu?.removeItem(R.id.conversation_event)
|
||||||
}
|
}
|
||||||
is ChatViewModel.UnbindRoomUiState.Error -> {
|
is ChatViewModel.UnbindRoomUiState.Error -> {
|
||||||
Snackbar.make(
|
Snackbar.make(
|
||||||
@ -1237,11 +1266,17 @@ class ChatActivity :
|
|||||||
bringToFront()
|
bringToFront()
|
||||||
}
|
}
|
||||||
val deleteNoticeText = binding.conversationDeleteNotice.findViewById<TextView>(R.id.deletion_message)
|
val deleteNoticeText = binding.conversationDeleteNotice.findViewById<TextView>(R.id.deletion_message)
|
||||||
|
viewThemeUtils.material.themeCardView(binding.conversationDeleteNotice)
|
||||||
|
|
||||||
deleteNoticeText.text = String.format(
|
deleteNoticeText.text = resources.getQuantityString(
|
||||||
resources.getString(R.string.nc_conversation_auto_delete_notice),
|
R.plurals.nc_conversation_auto_delete_info,
|
||||||
|
retentionPeriod,
|
||||||
retentionPeriod
|
retentionPeriod
|
||||||
)
|
)
|
||||||
|
viewThemeUtils.material.colorMaterialButtonPrimaryTonal(
|
||||||
|
binding.conversationDeleteNotice
|
||||||
|
.findViewById<MaterialButton>(R.id.keep_button)
|
||||||
|
)
|
||||||
|
|
||||||
if (ConversationUtils.isParticipantOwnerOrModerator(currentConversation!!)) {
|
if (ConversationUtils.isParticipantOwnerOrModerator(currentConversation!!)) {
|
||||||
binding.conversationDeleteNotice.findViewById<MaterialButton>(R.id.delete_now_button).visibility =
|
binding.conversationDeleteNotice.findViewById<MaterialButton>(R.id.delete_now_button).visibility =
|
||||||
@ -1958,8 +1993,8 @@ class ChatActivity :
|
|||||||
WorkManager.getInstance().enqueue(downloadWorker)
|
WorkManager.getInstance().enqueue(downloadWorker)
|
||||||
|
|
||||||
WorkManager.getInstance(context).getWorkInfoByIdLiveData(downloadWorker.id)
|
WorkManager.getInstance(context).getWorkInfoByIdLiveData(downloadWorker.id)
|
||||||
.observeForever { workInfo: WorkInfo ->
|
.observeForever { workInfo: WorkInfo? ->
|
||||||
if (workInfo.state == WorkInfo.State.SUCCEEDED) {
|
if (workInfo?.state == WorkInfo.State.SUCCEEDED) {
|
||||||
funToCallWhenDownloadSuccessful()
|
funToCallWhenDownloadSuccessful()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2042,7 +2077,7 @@ class ChatActivity :
|
|||||||
|
|
||||||
private fun shouldShowLobby(): Boolean {
|
private fun shouldShowLobby(): Boolean {
|
||||||
if (currentConversation != null) {
|
if (currentConversation != null) {
|
||||||
return CapabilitiesUtil.hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.WEBINARY_LOBBY) &&
|
return hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.WEBINARY_LOBBY) &&
|
||||||
currentConversation?.lobbyState == ConversationEnums.LobbyState.LOBBY_STATE_MODERATORS_ONLY &&
|
currentConversation?.lobbyState == ConversationEnums.LobbyState.LOBBY_STATE_MODERATORS_ONLY &&
|
||||||
!ConversationUtils.canModerate(currentConversation!!, spreedCapabilities) &&
|
!ConversationUtils.canModerate(currentConversation!!, spreedCapabilities) &&
|
||||||
!participantPermissions.canIgnoreLobby()
|
!participantPermissions.canIgnoreLobby()
|
||||||
@ -2297,15 +2332,8 @@ class ChatActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onMessageSearchResult(intent: Intent?) {
|
|
||||||
val messageId = intent?.getStringExtra(MessageSearchActivity.RESULT_KEY_MESSAGE_ID)
|
|
||||||
messageId?.let { id ->
|
|
||||||
scrollToAndCenterMessageWithId(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun executeIfResultOk(result: ActivityResult, onResult: (intent: Intent?) -> Unit) {
|
private fun executeIfResultOk(result: ActivityResult, onResult: (intent: Intent?) -> Unit) {
|
||||||
if (result.resultCode == Activity.RESULT_OK) {
|
if (result.resultCode == RESULT_OK) {
|
||||||
onResult(result.data)
|
onResult(result.data)
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "resultCode for received intent was != ok")
|
Log.e(TAG, "resultCode for received intent was != ok")
|
||||||
@ -2319,7 +2347,7 @@ class ChatActivity :
|
|||||||
if (position != null && position >= 0) {
|
if (position != null && position >= 0) {
|
||||||
binding.messagesListView.scrollToPosition(position)
|
binding.messagesListView.scrollToPosition(position)
|
||||||
} else {
|
} else {
|
||||||
startContextChatWindowForMessage(messageId)
|
Log.d(TAG, "message $messageId that should be scrolled to was not found (scrollToMessageWithId)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2332,10 +2360,12 @@ class ChatActivity :
|
|||||||
binding.messagesListView.height / 2
|
binding.messagesListView.height / 2
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
startContextChatWindowForMessage(messageId)
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"message $messageId that should be scrolled " +
|
||||||
|
"to was not found (scrollToAndCenterMessageWithId)"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} ?: run {
|
|
||||||
startContextChatWindowForMessage(messageId)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2797,7 +2827,7 @@ class ChatActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this::spreedCapabilities.isInitialized) {
|
if (this::spreedCapabilities.isInitialized) {
|
||||||
if (CapabilitiesUtil.hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.MESSAGE_EXPIRATION)) {
|
if (hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.MESSAGE_EXPIRATION)) {
|
||||||
deleteExpiredMessages()
|
deleteExpiredMessages()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -3044,6 +3074,7 @@ class ChatActivity :
|
|||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
super.onCreateOptionsMenu(menu)
|
super.onCreateOptionsMenu(menu)
|
||||||
menuInflater.inflate(R.menu.menu_conversation, menu)
|
menuInflater.inflate(R.menu.menu_conversation, menu)
|
||||||
|
chatMenu = menu
|
||||||
|
|
||||||
if (currentConversation?.objectType == ConversationEnums.ObjectType.EVENT) {
|
if (currentConversation?.objectType == ConversationEnums.ObjectType.EVENT) {
|
||||||
eventConversationMenuItem = menu.findItem(R.id.conversation_event)
|
eventConversationMenuItem = menu.findItem(R.id.conversation_event)
|
||||||
@ -3057,7 +3088,6 @@ class ChatActivity :
|
|||||||
loadAvatarForStatusBar()
|
loadAvatarForStatusBar()
|
||||||
setActionBarTitle()
|
setActionBarTitle()
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3065,7 +3095,7 @@ class ChatActivity :
|
|||||||
super.onPrepareOptionsMenu(menu)
|
super.onPrepareOptionsMenu(menu)
|
||||||
|
|
||||||
if (this::spreedCapabilities.isInitialized) {
|
if (this::spreedCapabilities.isInitialized) {
|
||||||
if (CapabilitiesUtil.hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.READ_ONLY_ROOMS)) {
|
if (hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.READ_ONLY_ROOMS)) {
|
||||||
checkShowCallButtons()
|
checkShowCallButtons()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3086,7 +3116,7 @@ class ChatActivity :
|
|||||||
}.collect()
|
}.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CapabilitiesUtil.hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.SILENT_CALL)) {
|
if (hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.SILENT_CALL)) {
|
||||||
Handler().post {
|
Handler().post {
|
||||||
findViewById<View?>(R.id.conversation_voice_call)?.setOnLongClickListener {
|
findViewById<View?>(R.id.conversation_voice_call)?.setOnLongClickListener {
|
||||||
showCallButtonMenu(true)
|
showCallButtonMenu(true)
|
||||||
@ -3145,10 +3175,10 @@ class ChatActivity :
|
|||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("InflateParams")
|
||||||
private fun showPopupWindow(anchorView: View) {
|
private fun showPopupWindow(anchorView: View) {
|
||||||
val popupView = layoutInflater.inflate(R.layout.item_event_schedule, null)
|
val popupView = layoutInflater.inflate(R.layout.item_event_schedule, null)
|
||||||
|
|
||||||
val titleTextView = popupView.findViewById<TextView>(R.id.event_scheduled)
|
|
||||||
val subtitleTextView = popupView.findViewById<TextView>(R.id.meetingTime)
|
val subtitleTextView = popupView.findViewById<TextView>(R.id.meetingTime)
|
||||||
|
|
||||||
val popupWindow = PopupWindow(
|
val popupWindow = PopupWindow(
|
||||||
@ -3597,7 +3627,7 @@ class ChatActivity :
|
|||||||
|
|
||||||
fun copyMessage(message: IMessage?) {
|
fun copyMessage(message: IMessage?) {
|
||||||
val clipboardManager =
|
val clipboardManager =
|
||||||
getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
val clipData = ClipData.newPlainText(
|
val clipData = ClipData.newPlainText(
|
||||||
resources?.getString(R.string.nc_app_product_name),
|
resources?.getString(R.string.nc_app_product_name),
|
||||||
message?.text
|
message?.text
|
||||||
@ -3911,7 +3941,7 @@ class ChatActivity :
|
|||||||
val isOlderThanSixHours = message
|
val isOlderThanSixHours = message
|
||||||
.createdAt
|
.createdAt
|
||||||
.before(Date(System.currentTimeMillis() - AGE_THRESHOLD_FOR_DELETE_MESSAGE))
|
.before(Date(System.currentTimeMillis() - AGE_THRESHOLD_FOR_DELETE_MESSAGE))
|
||||||
val hasDeleteMessagesUnlimitedCapability = CapabilitiesUtil.hasSpreedFeatureCapability(
|
val hasDeleteMessagesUnlimitedCapability = hasSpreedFeatureCapability(
|
||||||
spreedCapabilities,
|
spreedCapabilities,
|
||||||
SpreedFeatures.DELETE_MESSAGES_UNLIMITED
|
SpreedFeatures.DELETE_MESSAGES_UNLIMITED
|
||||||
)
|
)
|
||||||
@ -3921,7 +3951,7 @@ class ChatActivity :
|
|||||||
!hasDeleteMessagesUnlimitedCapability && isOlderThanSixHours -> false
|
!hasDeleteMessagesUnlimitedCapability && isOlderThanSixHours -> false
|
||||||
message.systemMessageType != ChatMessage.SystemMessageType.DUMMY -> false
|
message.systemMessageType != ChatMessage.SystemMessageType.DUMMY -> false
|
||||||
message.isDeleted -> false
|
message.isDeleted -> false
|
||||||
!CapabilitiesUtil.hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.DELETE_MESSAGES) -> false
|
!hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.DELETE_MESSAGES) -> false
|
||||||
!participantPermissions.hasChatPermission() -> false
|
!participantPermissions.hasChatPermission() -> false
|
||||||
hasDeleteMessagesUnlimitedCapability -> true
|
hasDeleteMessagesUnlimitedCapability -> true
|
||||||
else -> true
|
else -> true
|
||||||
@ -4186,5 +4216,6 @@ class ChatActivity :
|
|||||||
const val OUT_OF_OFFICE_ALPHA = 76
|
const val OUT_OF_OFFICE_ALPHA = 76
|
||||||
const val ZERO_INDEX = 0
|
const val ZERO_INDEX = 0
|
||||||
const val ONE_INDEX = 1
|
const val ONE_INDEX = 1
|
||||||
|
const val MAX_AMOUNT_MEDIA_FILE_PICKER = 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ class MessageInputFragment : Fragment() {
|
|||||||
val connectionGained = (!wasOnline && isOnline)
|
val connectionGained = (!wasOnline && isOnline)
|
||||||
Log.d(TAG, "isOnline: $isOnline\nwasOnline: $wasOnline\nconnectionGained: $connectionGained")
|
Log.d(TAG, "isOnline: $isOnline\nwasOnline: $wasOnline\nconnectionGained: $connectionGained")
|
||||||
if (connectionGained) {
|
if (connectionGained) {
|
||||||
chatActivity.messageInputViewModel.sendTempMessages(
|
chatActivity.messageInputViewModel.sendUnsentMessages(
|
||||||
chatActivity.conversationUser!!.getCredentials(),
|
chatActivity.conversationUser!!.getCredentials(),
|
||||||
ApiUtils.getUrlForChat(
|
ApiUtils.getUrlForChat(
|
||||||
chatActivity.chatApiVersion,
|
chatActivity.chatApiVersion,
|
||||||
|
@ -76,8 +76,6 @@ interface ChatMessageRepository : LifecycleAwareManager {
|
|||||||
*/
|
*/
|
||||||
suspend fun getMessage(messageId: Long, bundle: Bundle): Flow<ChatMessage>
|
suspend fun getMessage(messageId: Long, bundle: Bundle): Flow<ChatMessage>
|
||||||
|
|
||||||
suspend fun checkIfMessageIsSaved(messageId: Long): Boolean
|
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
suspend fun sendChatMessage(
|
suspend fun sendChatMessage(
|
||||||
credentials: String,
|
credentials: String,
|
||||||
@ -112,7 +110,7 @@ interface ChatMessageRepository : LifecycleAwareManager {
|
|||||||
|
|
||||||
suspend fun editTempChatMessage(message: ChatMessage, editedMessageText: String): Flow<Boolean>
|
suspend fun editTempChatMessage(message: ChatMessage, editedMessageText: String): Flow<Boolean>
|
||||||
|
|
||||||
suspend fun sendTempChatMessages(credentials: String, url: String)
|
suspend fun sendUnsentChatMessages(credentials: String, url: String)
|
||||||
|
|
||||||
suspend fun deleteTempMessage(chatMessage: ChatMessage)
|
suspend fun deleteTempMessage(chatMessage: ChatMessage)
|
||||||
}
|
}
|
||||||
|
@ -183,19 +183,26 @@ class MediaPlayerManager : LifecycleAwareManager {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mediaPlayer != null && mediaPlayer?.isPlaying == true) {
|
mediaPlayer?.let { player ->
|
||||||
val pos = mediaPlayer!!.currentPosition
|
try {
|
||||||
|
if (!player.isPlaying) return@let
|
||||||
|
} catch (e: IllegalStateException) {
|
||||||
|
Log.e(TAG, "Seekbar updated during an improper state: $e")
|
||||||
|
return@let
|
||||||
|
}
|
||||||
|
|
||||||
|
val pos = player.currentPosition
|
||||||
mediaPlayerPosition = pos
|
mediaPlayerPosition = pos
|
||||||
val progress = (pos.toFloat() / mediaPlayerDuration) * DIVIDER
|
val progress = (pos.toFloat() / mediaPlayerDuration) * DIVIDER
|
||||||
val progressI = ceil(progress).toInt()
|
val progressI = ceil(progress).toInt()
|
||||||
val seconds = (pos / ONE_SEC)
|
val seconds = (pos / ONE_SEC)
|
||||||
_mediaPlayerSeekBarPosition.emit(progressI)
|
_mediaPlayerSeekBarPosition.emit(progressI)
|
||||||
currentCycledMessage?.let {
|
currentCycledMessage?.let { msg ->
|
||||||
it.isPlayingVoiceMessage = true
|
msg.isPlayingVoiceMessage = true
|
||||||
it.voiceMessageSeekbarProgress = progressI
|
msg.voiceMessageSeekbarProgress = progressI
|
||||||
it.voiceMessagePlayedSeconds = seconds
|
msg.voiceMessagePlayedSeconds = seconds
|
||||||
if (progressI >= IS_PLAYED_CUTOFF) it.wasPlayedVoiceMessage = true
|
if (progressI >= IS_PLAYED_CUTOFF) msg.wasPlayedVoiceMessage = true
|
||||||
_mediaPlayerSeekBarPositionMsg.emit(it)
|
_mediaPlayerSeekBarPositionMsg.emit(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import android.util.Log
|
|||||||
import com.bluelinelabs.logansquare.annotation.JsonIgnore
|
import com.bluelinelabs.logansquare.annotation.JsonIgnore
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
|
import com.nextcloud.talk.data.database.model.SendStatus
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.models.json.chat.ChatUtils.Companion.getParsedMessage
|
import com.nextcloud.talk.models.json.chat.ChatUtils.Companion.getParsedMessage
|
||||||
import com.nextcloud.talk.models.json.chat.ReadStatus
|
import com.nextcloud.talk.models.json.chat.ReadStatus
|
||||||
@ -119,7 +120,7 @@ data class ChatMessage(
|
|||||||
|
|
||||||
var referenceId: String? = null,
|
var referenceId: String? = null,
|
||||||
|
|
||||||
var sendingFailed: Boolean = true,
|
var sendStatus: SendStatus? = null,
|
||||||
|
|
||||||
var silent: Boolean = false
|
var silent: Boolean = false
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import com.nextcloud.talk.data.database.mappers.asEntity
|
|||||||
import com.nextcloud.talk.data.database.mappers.asModel
|
import com.nextcloud.talk.data.database.mappers.asModel
|
||||||
import com.nextcloud.talk.data.database.model.ChatBlockEntity
|
import com.nextcloud.talk.data.database.model.ChatBlockEntity
|
||||||
import com.nextcloud.talk.data.database.model.ChatMessageEntity
|
import com.nextcloud.talk.data.database.model.ChatMessageEntity
|
||||||
|
import com.nextcloud.talk.data.database.model.SendStatus
|
||||||
import com.nextcloud.talk.data.network.NetworkMonitor
|
import com.nextcloud.talk.data.network.NetworkMonitor
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.extensions.toIntOrZero
|
import com.nextcloud.talk.extensions.toIntOrZero
|
||||||
@ -214,7 +215,8 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
sendTempChatMessages(credentials, urlForChatting)
|
// this call could be deleted when we have a worker to send messages..
|
||||||
|
sendUnsentChatMessages(credentials, urlForChatting)
|
||||||
|
|
||||||
// delay is a dirty workaround to make sure messages are added to adapter on initial load before dealing
|
// delay is a dirty workaround to make sure messages are added to adapter on initial load before dealing
|
||||||
// with them (otherwise there is a race condition).
|
// with them (otherwise there is a race condition).
|
||||||
@ -365,11 +367,18 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
lookIntoFuture: Boolean,
|
lookIntoFuture: Boolean,
|
||||||
showUnreadMessagesMarker: Boolean
|
showUnreadMessagesMarker: Boolean
|
||||||
) {
|
) {
|
||||||
|
receivedChatMessages.forEach {
|
||||||
|
Log.d(TAG, "receivedChatMessage: " + it.message)
|
||||||
|
}
|
||||||
|
|
||||||
// remove all temp messages from UI
|
// remove all temp messages from UI
|
||||||
val oldTempMessages = chatDao.getTempMessagesForConversation(internalConversationId)
|
val oldTempMessages = chatDao.getTempMessagesForConversation(internalConversationId)
|
||||||
.first()
|
.first()
|
||||||
.map(ChatMessageEntity::asModel)
|
.map(ChatMessageEntity::asModel)
|
||||||
oldTempMessages.forEach { _removeMessageFlow.emit(it) }
|
oldTempMessages.forEach {
|
||||||
|
Log.d(TAG, "oldTempMessage to be removed from UI: " + it.message)
|
||||||
|
_removeMessageFlow.emit(it)
|
||||||
|
}
|
||||||
|
|
||||||
// add new messages to UI
|
// add new messages to UI
|
||||||
val tripleChatMessages = Triple(lookIntoFuture, showUnreadMessagesMarker, receivedChatMessages)
|
val tripleChatMessages = Triple(lookIntoFuture, showUnreadMessagesMarker, receivedChatMessages)
|
||||||
@ -378,6 +387,9 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
// remove temp messages from DB that are now found in the new messages
|
// remove temp messages from DB that are now found in the new messages
|
||||||
val chatMessagesReferenceIds = receivedChatMessages.mapTo(HashSet(receivedChatMessages.size)) { it.referenceId }
|
val chatMessagesReferenceIds = receivedChatMessages.mapTo(HashSet(receivedChatMessages.size)) { it.referenceId }
|
||||||
val tempChatMessagesThatCanBeReplaced = oldTempMessages.filter { it.referenceId in chatMessagesReferenceIds }
|
val tempChatMessagesThatCanBeReplaced = oldTempMessages.filter { it.referenceId in chatMessagesReferenceIds }
|
||||||
|
tempChatMessagesThatCanBeReplaced.forEach {
|
||||||
|
Log.d(TAG, "oldTempMessage that was identified in newMessages: " + it.message)
|
||||||
|
}
|
||||||
chatDao.deleteTempChatMessages(
|
chatDao.deleteTempChatMessages(
|
||||||
internalConversationId,
|
internalConversationId,
|
||||||
tempChatMessagesThatCanBeReplaced.map { it.referenceId!! }
|
tempChatMessagesThatCanBeReplaced.map { it.referenceId!! }
|
||||||
@ -389,6 +401,10 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
.sortedBy { it.internalId }
|
.sortedBy { it.internalId }
|
||||||
.map(ChatMessageEntity::asModel)
|
.map(ChatMessageEntity::asModel)
|
||||||
|
|
||||||
|
remainingTempMessages.forEach {
|
||||||
|
Log.d(TAG, "remainingTempMessage: " + it.message)
|
||||||
|
}
|
||||||
|
|
||||||
val triple = Triple(true, false, remainingTempMessages)
|
val triple = Triple(true, false, remainingTempMessages)
|
||||||
_messageFlow.emit(triple)
|
_messageFlow.emit(triple)
|
||||||
}
|
}
|
||||||
@ -475,15 +491,6 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
.map(ChatMessageEntity::asModel)
|
.map(ChatMessageEntity::asModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun checkIfMessageIsSaved(messageId: Long): Boolean {
|
|
||||||
try {
|
|
||||||
chatDao.getChatMessageForConversation(internalConversationId, messageId)
|
|
||||||
return true
|
|
||||||
} catch (_: Exception) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST", "MagicNumber", "Detekt.TooGenericExceptionCaught")
|
@Suppress("UNCHECKED_CAST", "MagicNumber", "Detekt.TooGenericExceptionCaught")
|
||||||
private fun getMessagesFromServer(bundle: Bundle): Pair<Int, List<ChatMessageJson>>? {
|
private fun getMessagesFromServer(bundle: Bundle): Pair<Int, List<ChatMessageJson>>? {
|
||||||
val fieldMap = bundle.getSerializable(BundleKeys.KEY_FIELD_MAP) as HashMap<String, Int>
|
val fieldMap = bundle.getSerializable(BundleKeys.KEY_FIELD_MAP) as HashMap<String, Int>
|
||||||
@ -852,6 +859,17 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
|
|
||||||
val chatMessageModel = response.ocs?.data?.asModel()
|
val chatMessageModel = response.ocs?.data?.asModel()
|
||||||
|
|
||||||
|
val sentMessage = chatDao.getTempMessageForConversation(
|
||||||
|
internalConversationId,
|
||||||
|
referenceId
|
||||||
|
).firstOrNull()
|
||||||
|
|
||||||
|
sentMessage?.let {
|
||||||
|
it.sendStatus = SendStatus.SENT_PENDING_ACK
|
||||||
|
chatDao.updateChatMessage(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "sending chat message succeeded: " + message)
|
||||||
emit(Result.success(chatMessageModel))
|
emit(Result.success(chatMessageModel))
|
||||||
}
|
}
|
||||||
.catch { e ->
|
.catch { e ->
|
||||||
@ -862,7 +880,7 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
referenceId
|
referenceId
|
||||||
).firstOrNull()
|
).firstOrNull()
|
||||||
failedMessage?.let {
|
failedMessage?.let {
|
||||||
it.sendingFailed = true
|
it.sendStatus = SendStatus.FAILED
|
||||||
chatDao.updateChatMessage(it)
|
chatDao.updateChatMessage(it)
|
||||||
|
|
||||||
val failedMessageModel = it.asModel()
|
val failedMessageModel = it.asModel()
|
||||||
@ -882,14 +900,15 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
sendWithoutNotification: Boolean,
|
sendWithoutNotification: Boolean,
|
||||||
referenceId: String
|
referenceId: String
|
||||||
): Flow<Result<ChatMessage?>> {
|
): Flow<Result<ChatMessage?>> {
|
||||||
val messageToResend = chatDao.getTempMessageForConversation(internalConversationId, referenceId).first()
|
val messageToResend = chatDao.getTempMessageForConversation(internalConversationId, referenceId).firstOrNull()
|
||||||
messageToResend.sendingFailed = false
|
return if (messageToResend != null) {
|
||||||
|
messageToResend.sendStatus = SendStatus.PENDING
|
||||||
chatDao.updateChatMessage(messageToResend)
|
chatDao.updateChatMessage(messageToResend)
|
||||||
|
|
||||||
val messageToResendModel = messageToResend.asModel()
|
val messageToResendModel = messageToResend.asModel()
|
||||||
_updateMessageFlow.emit(messageToResendModel)
|
_updateMessageFlow.emit(messageToResendModel)
|
||||||
|
|
||||||
return sendChatMessage(
|
sendChatMessage(
|
||||||
credentials,
|
credentials,
|
||||||
url,
|
url,
|
||||||
message,
|
message,
|
||||||
@ -898,6 +917,11 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
sendWithoutNotification,
|
sendWithoutNotification,
|
||||||
referenceId
|
referenceId
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
flow {
|
||||||
|
emit(Result.failure(IllegalStateException("No temporary message found to resend")))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("Detekt.TooGenericExceptionCaught")
|
@Suppress("Detekt.TooGenericExceptionCaught")
|
||||||
@ -939,8 +963,8 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun sendTempChatMessages(credentials: String, url: String) {
|
override suspend fun sendUnsentChatMessages(credentials: String, url: String) {
|
||||||
val tempMessages = chatDao.getTempMessagesForConversation(internalConversationId).first()
|
val tempMessages = chatDao.getTempUnsentMessagesForConversation(internalConversationId).first()
|
||||||
tempMessages.sortedBy { it.internalId }.onEach {
|
tempMessages.sortedBy { it.internalId }.onEach {
|
||||||
sendChatMessage(
|
sendChatMessage(
|
||||||
credentials,
|
credentials,
|
||||||
@ -1034,7 +1058,7 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
actorDisplayName = currentUser.displayName!!,
|
actorDisplayName = currentUser.displayName!!,
|
||||||
referenceId = referenceId,
|
referenceId = referenceId,
|
||||||
isTemporary = true,
|
isTemporary = true,
|
||||||
sendingFailed = false,
|
sendStatus = SendStatus.PENDING,
|
||||||
silent = sendWithoutNotification
|
silent = sendWithoutNotification
|
||||||
)
|
)
|
||||||
return entity
|
return entity
|
||||||
|
@ -285,10 +285,6 @@ class ChatViewModel @Inject constructor(
|
|||||||
conversationRepository.getRoom(token)
|
conversationRepository.getRoom(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun isMessageSaved(messageId: Long): Boolean {
|
|
||||||
return chatRepository.checkIfMessageIsSaved(messageId)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getCapabilities(user: User, token: String, conversationModel: ConversationModel) {
|
fun getCapabilities(user: User, token: String, conversationModel: ConversationModel) {
|
||||||
Log.d(TAG, "Remote server ${conversationModel.remoteServer}")
|
Log.d(TAG, "Remote server ${conversationModel.remoteServer}")
|
||||||
if (conversationModel.remoteServer.isNullOrEmpty()) {
|
if (conversationModel.remoteServer.isNullOrEmpty()) {
|
||||||
|
@ -169,9 +169,9 @@ class MessageInputViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendTempMessages(credentials: String, url: String) {
|
fun sendUnsentMessages(credentials: String, url: String) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
chatRepository.sendTempChatMessages(
|
chatRepository.sendUnsentChatMessages(
|
||||||
credentials,
|
credentials,
|
||||||
url
|
url
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Nextcloud Talk - Android Client
|
* Nextcloud Talk - Android Client
|
||||||
*
|
*
|
||||||
* SPDX-FileCopyrightText: 2024 Sowjanya Kota <sowjanya.kch@gmail.com>
|
|
||||||
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
|
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
@ -9,16 +8,41 @@
|
|||||||
package com.nextcloud.talk.components
|
package com.nextcloud.talk.components
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.statusBars
|
||||||
|
import androidx.compose.foundation.layout.windowInsetsTopHeight
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SetupSystemBars() {
|
fun ColoredStatusBar() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
||||||
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.windowInsetsTopHeight(WindowInsets.statusBars)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(MaterialTheme.colorScheme.surface)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ColorLegacyStatusBar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ColorLegacyStatusBar() {
|
||||||
val view = LocalView.current
|
val view = LocalView.current
|
||||||
val isDarkMode = isSystemInDarkTheme()
|
val isDarkMode = isSystemInDarkTheme()
|
||||||
val statusBarColor = MaterialTheme.colorScheme.surface.toArgb()
|
val statusBarColor = MaterialTheme.colorScheme.surface.toArgb()
|
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk - Android Client
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.talk.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.RowScope
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun VerticallyCenteredRow(content: @Composable RowScope.() -> Unit) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxHeight(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
content = content
|
||||||
|
)
|
||||||
|
}
|
@ -18,9 +18,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.nextcloud.talk.activities.BaseActivity
|
import com.nextcloud.talk.activities.BaseActivity
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
|
import com.nextcloud.talk.components.ColoredStatusBar
|
||||||
import com.nextcloud.talk.contacts.CompanionClass.Companion.KEY_HIDE_ALREADY_EXISTING_PARTICIPANTS
|
import com.nextcloud.talk.contacts.CompanionClass.Companion.KEY_HIDE_ALREADY_EXISTING_PARTICIPANTS
|
||||||
import com.nextcloud.talk.extensions.getParcelableArrayListExtraProvider
|
import com.nextcloud.talk.extensions.getParcelableArrayListExtraProvider
|
||||||
import com.nextcloud.talk.components.SetupSystemBars
|
|
||||||
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
|
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -64,11 +64,11 @@ class ContactsActivity : BaseActivity() {
|
|||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colorScheme = colorScheme
|
colorScheme = colorScheme
|
||||||
) {
|
) {
|
||||||
|
ColoredStatusBar()
|
||||||
ContactsScreen(
|
ContactsScreen(
|
||||||
contactsViewModel = contactsViewModel,
|
contactsViewModel = contactsViewModel,
|
||||||
uiState = uiState.value
|
uiState = uiState.value
|
||||||
)
|
)
|
||||||
SetupSystemBars()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,16 +11,18 @@ package com.nextcloud.talk.contacts
|
|||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.statusBarsPadding
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.colorResource
|
import androidx.compose.ui.res.colorResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.contacts.components.AppBar
|
import com.nextcloud.talk.contacts.components.ContactsAppBar
|
||||||
import com.nextcloud.talk.contacts.components.ContactsList
|
import com.nextcloud.talk.contacts.components.ContactsList
|
||||||
|
import com.nextcloud.talk.contacts.components.ContactsSearchAppBar
|
||||||
import com.nextcloud.talk.contacts.components.ConversationCreationOptions
|
import com.nextcloud.talk.contacts.components.ConversationCreationOptions
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -32,35 +34,37 @@ fun ContactsScreen(contactsViewModel: ContactsViewModel, uiState: ContactsUiStat
|
|||||||
val enableAddButton by contactsViewModel.enableAddButton.collectAsStateWithLifecycle()
|
val enableAddButton by contactsViewModel.enableAddButton.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
modifier = Modifier
|
||||||
|
.statusBarsPadding(),
|
||||||
topBar = {
|
topBar = {
|
||||||
AppBar(
|
if (isSearchActive) {
|
||||||
title = stringResource(R.string.nc_app_product_name),
|
ContactsSearchAppBar(
|
||||||
searchQuery = searchQuery,
|
searchQuery = searchQuery,
|
||||||
isSearchActive = isSearchActive,
|
onTextChange = {
|
||||||
isAddParticipants = isAddParticipants,
|
contactsViewModel.updateSearchQuery(it)
|
||||||
autocompleteUsers = autocompleteUsers,
|
contactsViewModel.getContactsFromSearchParams()
|
||||||
onEnableSearch = {
|
|
||||||
contactsViewModel.setSearchActive(true)
|
|
||||||
},
|
},
|
||||||
onDisableSearch = {
|
onCloseSearch = {
|
||||||
|
contactsViewModel.updateSearchQuery("")
|
||||||
contactsViewModel.setSearchActive(false)
|
contactsViewModel.setSearchActive(false)
|
||||||
},
|
|
||||||
onUpdateSearchQuery = {
|
|
||||||
contactsViewModel.updateSearchQuery(query = it)
|
|
||||||
},
|
|
||||||
onUpdateAutocompleteUsers = {
|
|
||||||
contactsViewModel.getContactsFromSearchParams()
|
contactsViewModel.getContactsFromSearchParams()
|
||||||
},
|
},
|
||||||
enableAddButton = enableAddButton,
|
enableAddButton = enableAddButton,
|
||||||
clickAddButton = {
|
isAddParticipants = isAddParticipants,
|
||||||
contactsViewModel.modifyClickAddButton(it)
|
clickAddButton = { contactsViewModel.modifyClickAddButton(true) }
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
ContactsAppBar(
|
||||||
|
isAddParticipants = isAddParticipants,
|
||||||
|
autocompleteUsers = autocompleteUsers,
|
||||||
|
onStartSearch = { contactsViewModel.setSearchActive(true) }
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
content = {
|
content = { paddingValues ->
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
.padding(it)
|
.padding(0.dp, paddingValues.calculateTopPadding(), 0.dp, 0.dp)
|
||||||
.background(colorResource(id = R.color.bg_default))
|
.background(colorResource(id = R.color.bg_default))
|
||||||
) {
|
) {
|
||||||
if (!isAddParticipants) {
|
if (!isAddParticipants) {
|
||||||
|
@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Talk - Android Client
|
|
||||||
*
|
|
||||||
* SPDX-FileCopyrightText: 2024 Sowjanya Kota <sowjanya.kch@gmail.com>
|
|
||||||
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.nextcloud.talk.contacts.components
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.wrapContentWidth
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.Search
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import com.nextcloud.talk.R
|
|
||||||
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
|
|
||||||
|
|
||||||
@SuppressLint("UnrememberedMutableState")
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Suppress("LongParameterList", "LongMethod")
|
|
||||||
@Composable
|
|
||||||
fun AppBar(
|
|
||||||
title: String,
|
|
||||||
searchQuery: String,
|
|
||||||
isSearchActive: Boolean,
|
|
||||||
isAddParticipants: Boolean,
|
|
||||||
autocompleteUsers: List<AutocompleteUser>,
|
|
||||||
onEnableSearch: () -> Unit,
|
|
||||||
onDisableSearch: () -> Unit,
|
|
||||||
onUpdateSearchQuery: (String) -> Unit,
|
|
||||||
onUpdateAutocompleteUsers: () -> Unit,
|
|
||||||
enableAddButton: Boolean,
|
|
||||||
clickAddButton: (Boolean) -> Unit
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
|
||||||
val appTitle = if (!isSearchActive) {
|
|
||||||
title
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
}
|
|
||||||
TopAppBar(
|
|
||||||
title = { Text(text = appTitle) },
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = {
|
|
||||||
(context as? Activity)?.finish()
|
|
||||||
}) {
|
|
||||||
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(R.string.back_button))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions = {
|
|
||||||
if (!isSearchActive) {
|
|
||||||
IconButton(onClick = onEnableSearch) {
|
|
||||||
Icon(Icons.Filled.Search, contentDescription = stringResource(R.string.search_icon))
|
|
||||||
}
|
|
||||||
if (isAddParticipants) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(id = R.string.nc_contacts_done),
|
|
||||||
modifier = Modifier.clickable {
|
|
||||||
val resultIntent = Intent().apply {
|
|
||||||
putParcelableArrayListExtra(
|
|
||||||
"selectedParticipants",
|
|
||||||
ArrayList(autocompleteUsers)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
(context as? Activity)?.setResult(Activity.RESULT_OK, resultIntent)
|
|
||||||
(context as? Activity)?.finish()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
if (isSearchActive) {
|
|
||||||
Row(modifier = Modifier.fillMaxWidth()) {
|
|
||||||
SearchComponent(
|
|
||||||
text = searchQuery,
|
|
||||||
onTextChange = { searchQuery ->
|
|
||||||
onUpdateSearchQuery(searchQuery)
|
|
||||||
onUpdateAutocompleteUsers()
|
|
||||||
},
|
|
||||||
onDisableSearch = onDisableSearch,
|
|
||||||
modifier = Modifier.weight(1f)
|
|
||||||
)
|
|
||||||
if (isAddParticipants) {
|
|
||||||
TextButton(
|
|
||||||
modifier = Modifier.align(Alignment.CenterVertically).wrapContentWidth(),
|
|
||||||
onClick = {
|
|
||||||
onDisableSearch()
|
|
||||||
onUpdateSearchQuery("")
|
|
||||||
clickAddButton(true)
|
|
||||||
onUpdateAutocompleteUsers()
|
|
||||||
},
|
|
||||||
enabled = enableAddButton
|
|
||||||
) {
|
|
||||||
Text(text = context.getString(R.string.add_participants))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk - Android Client
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Sowjanya Kota <sowjanya.kch@gmail.com>
|
||||||
|
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.talk.contacts.components
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.filled.Search
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.components.VerticallyCenteredRow
|
||||||
|
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun ContactsAppBar(isAddParticipants: Boolean, autocompleteUsers: List<AutocompleteUser>, onStartSearch: () -> Unit) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
TopAppBar(
|
||||||
|
modifier = Modifier
|
||||||
|
.height(60.dp),
|
||||||
|
title = {
|
||||||
|
VerticallyCenteredRow {
|
||||||
|
Text(
|
||||||
|
text = if (isAddParticipants) {
|
||||||
|
stringResource(R.string.nc_participants_add)
|
||||||
|
} else {
|
||||||
|
stringResource(R.string.nc_new_conversation)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
navigationIcon = {
|
||||||
|
VerticallyCenteredRow {
|
||||||
|
IconButton(onClick = { (context as? Activity)?.finish() }) {
|
||||||
|
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(R.string.back_button))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
VerticallyCenteredRow {
|
||||||
|
IconButton(onClick = onStartSearch) {
|
||||||
|
Icon(Icons.Filled.Search, contentDescription = stringResource(R.string.search_icon))
|
||||||
|
}
|
||||||
|
if (isAddParticipants) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.nc_contacts_done),
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
val resultIntent = Intent().apply {
|
||||||
|
putParcelableArrayListExtra("selectedParticipants", ArrayList(autocompleteUsers))
|
||||||
|
}
|
||||||
|
(context as? Activity)?.setResult(Activity.RESULT_OK, resultIntent)
|
||||||
|
(context as? Activity)?.finish()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
@ -15,7 +15,6 @@ import androidx.compose.foundation.layout.Arrangement
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
@ -44,9 +43,13 @@ fun ContactsItem(contacts: List<AutocompleteUser>, contactsViewModel: ContactsVi
|
|||||||
}
|
}
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(8.dp)
|
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
contentPadding = PaddingValues(all = 10.dp),
|
contentPadding = PaddingValues(
|
||||||
|
top = 10.dp,
|
||||||
|
bottom = 40.dp,
|
||||||
|
start = 10.dp,
|
||||||
|
end = 10.dp
|
||||||
|
),
|
||||||
verticalArrangement = Arrangement.spacedBy(10.dp)
|
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||||
) {
|
) {
|
||||||
groupedContacts.forEach { (initial, contactsForInitial) ->
|
groupedContacts.forEach { (initial, contactsForInitial) ->
|
||||||
|
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk - Android Client
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Sowjanya Kota <sowjanya.kch@gmail.com>
|
||||||
|
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.talk.contacts.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.filled.Close
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
|
import androidx.compose.ui.platform.SoftwareKeyboardController
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.components.VerticallyCenteredRow
|
||||||
|
|
||||||
|
@Suppress("LongParameterList")
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun ContactsSearchAppBar(
|
||||||
|
searchQuery: String,
|
||||||
|
onTextChange: (String) -> Unit,
|
||||||
|
onCloseSearch: () -> Unit,
|
||||||
|
enableAddButton: Boolean,
|
||||||
|
isAddParticipants: Boolean,
|
||||||
|
clickAddButton: (Boolean) -> Unit
|
||||||
|
) {
|
||||||
|
val keyboardController = LocalSoftwareKeyboardController.current
|
||||||
|
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier.height(60.dp)
|
||||||
|
) {
|
||||||
|
VerticallyCenteredRow {
|
||||||
|
IconButton(
|
||||||
|
modifier = Modifier.padding(start = 4.dp),
|
||||||
|
onClick = onCloseSearch
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
|
contentDescription = stringResource(R.string.back_button)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField(
|
||||||
|
value = searchQuery,
|
||||||
|
onValueChange = onTextChange,
|
||||||
|
placeholder = { Text(text = stringResource(R.string.nc_search)) },
|
||||||
|
singleLine = true,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(horizontal = 8.dp),
|
||||||
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
|
||||||
|
keyboardActions = searchKeyboardActions(searchQuery, keyboardController),
|
||||||
|
colors = searchTextFieldColors(),
|
||||||
|
trailingIcon = {
|
||||||
|
if (searchQuery.isNotEmpty()) {
|
||||||
|
IconButton(onClick = { onTextChange("") }) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Close,
|
||||||
|
contentDescription = stringResource(R.string.nc_search_clear)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isAddParticipants) {
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
onCloseSearch()
|
||||||
|
clickAddButton(true)
|
||||||
|
},
|
||||||
|
enabled = enableAddButton
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.add_participants))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun searchTextFieldColors() =
|
||||||
|
TextFieldDefaults.colors(
|
||||||
|
focusedIndicatorColor = Color.Transparent,
|
||||||
|
unfocusedIndicatorColor = Color.Transparent,
|
||||||
|
disabledIndicatorColor = Color.Transparent
|
||||||
|
)
|
||||||
|
|
||||||
|
fun searchKeyboardActions(text: String, keyboardController: SoftwareKeyboardController?) =
|
||||||
|
KeyboardActions(
|
||||||
|
onSearch = {
|
||||||
|
if (text.trim().isNotEmpty()) {
|
||||||
|
keyboardController?.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
@ -1,105 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Talk - Android Client
|
|
||||||
*
|
|
||||||
* SPDX-FileCopyrightText: 2025 Julius Linus <juliuslinus1@gmail.com>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.nextcloud.talk.contacts.components
|
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.Close
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextField
|
|
||||||
import androidx.compose.material3.TextFieldDefaults
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
|
||||||
import androidx.compose.ui.platform.SoftwareKeyboardController
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.text.TextStyle
|
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import com.nextcloud.talk.R
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SearchComponent(
|
|
||||||
text: String,
|
|
||||||
onTextChange: (String) -> Unit,
|
|
||||||
onDisableSearch: () -> Unit,
|
|
||||||
modifier: Modifier = Modifier
|
|
||||||
) {
|
|
||||||
val keyboardController = LocalSoftwareKeyboardController.current
|
|
||||||
TextField(
|
|
||||||
value = text,
|
|
||||||
onValueChange = { onTextChange(it) },
|
|
||||||
modifier = modifier
|
|
||||||
.background(MaterialTheme.colorScheme.background)
|
|
||||||
.height(60.dp),
|
|
||||||
placeholder = { Text(text = stringResource(R.string.nc_search)) },
|
|
||||||
textStyle = TextStyle(fontSize = 16.sp),
|
|
||||||
singleLine = true,
|
|
||||||
leadingIcon = { LeadingIcon(onTextChange, onDisableSearch) },
|
|
||||||
trailingIcon = { TrailingIcon(text, onTextChange) },
|
|
||||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
|
|
||||||
keyboardActions = searchKeyboardActions(text, keyboardController),
|
|
||||||
colors = searchTextFieldColors(),
|
|
||||||
maxLines = 1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun searchTextFieldColors() =
|
|
||||||
TextFieldDefaults.colors(
|
|
||||||
focusedIndicatorColor = Color.Transparent,
|
|
||||||
unfocusedIndicatorColor = Color.Transparent,
|
|
||||||
disabledIndicatorColor = Color.Transparent
|
|
||||||
)
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun LeadingIcon(onTextChange: (String) -> Unit, onDisableSearch: () -> Unit) {
|
|
||||||
IconButton(
|
|
||||||
onClick = {
|
|
||||||
onTextChange("")
|
|
||||||
onDisableSearch()
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.AutoMirrored.Default.ArrowBack,
|
|
||||||
contentDescription = stringResource(R.string.back_button)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun TrailingIcon(text: String, onTextChange: (String) -> Unit) {
|
|
||||||
if (text.isNotEmpty()) {
|
|
||||||
IconButton(
|
|
||||||
onClick = { onTextChange("") }
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Default.Close,
|
|
||||||
contentDescription = stringResource(R.string.close_icon)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchKeyboardActions(text: String, keyboardController: SoftwareKeyboardController?) =
|
|
||||||
KeyboardActions(
|
|
||||||
onSearch = {
|
|
||||||
if (text.trim().isNotEmpty()) {
|
|
||||||
keyboardController?.hide()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
@ -84,8 +84,8 @@ import com.nextcloud.talk.R
|
|||||||
import com.nextcloud.talk.activities.BaseActivity
|
import com.nextcloud.talk.activities.BaseActivity
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.chat.ChatActivity
|
import com.nextcloud.talk.chat.ChatActivity
|
||||||
|
import com.nextcloud.talk.components.ColoredStatusBar
|
||||||
import com.nextcloud.talk.contacts.ContactsActivity
|
import com.nextcloud.talk.contacts.ContactsActivity
|
||||||
import com.nextcloud.talk.components.SetupSystemBars
|
|
||||||
import com.nextcloud.talk.contacts.loadImage
|
import com.nextcloud.talk.contacts.loadImage
|
||||||
import com.nextcloud.talk.extensions.getParcelableArrayListExtraProvider
|
import com.nextcloud.talk.extensions.getParcelableArrayListExtraProvider
|
||||||
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
|
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
|
||||||
@ -117,7 +117,6 @@ class ConversationCreationActivity : BaseActivity() {
|
|||||||
colorScheme = colorScheme
|
colorScheme = colorScheme
|
||||||
) {
|
) {
|
||||||
ConversationCreationScreen(conversationCreationViewModel, context, pickImage)
|
ConversationCreationScreen(conversationCreationViewModel, context, pickImage)
|
||||||
SetupSystemBars()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,6 +171,7 @@ fun ConversationCreationScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ColoredStatusBar()
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
@ -191,7 +191,7 @@ fun ConversationCreationScreen(
|
|||||||
content = { paddingValues ->
|
content = { paddingValues ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(paddingValues)
|
.padding(0.dp, paddingValues.calculateTopPadding(), 0.dp, 0.dp)
|
||||||
.background(colorResource(id = R.color.bg_default))
|
.background(colorResource(id = R.color.bg_default))
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
@ -289,7 +289,7 @@ fun UploadAvatar(
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.ic_mimetype_folder),
|
painter = painterResource(id = R.drawable.ic_folder),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(24.dp)
|
modifier = Modifier.size(24.dp)
|
||||||
)
|
)
|
||||||
|
@ -190,7 +190,7 @@ class ConversationInfoActivity :
|
|||||||
binding = ActivityConversationInfoBinding.inflate(layoutInflater)
|
binding = ActivityConversationInfoBinding.inflate(layoutInflater)
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
|
|
||||||
viewModel =
|
viewModel =
|
||||||
ViewModelProvider(this, viewModelFactory)[ConversationInfoViewModel::class.java]
|
ViewModelProvider(this, viewModelFactory)[ConversationInfoViewModel::class.java]
|
||||||
@ -1065,21 +1065,13 @@ class ConversationInfoActivity :
|
|||||||
) {
|
) {
|
||||||
binding.addParticipantsAction.visibility = GONE
|
binding.addParticipantsAction.visibility = GONE
|
||||||
binding.startGroupChat.visibility = VISIBLE
|
binding.startGroupChat.visibility = VISIBLE
|
||||||
|
showDeleteAllMessagesOption(conversationCopy)
|
||||||
} else if (ConversationUtils.canModerate(conversationCopy, spreedCapabilities)) {
|
} else if (ConversationUtils.canModerate(conversationCopy, spreedCapabilities)) {
|
||||||
binding.addParticipantsAction.visibility = VISIBLE
|
binding.addParticipantsAction.visibility = VISIBLE
|
||||||
if (hasSpreedFeatureCapability(
|
showDeleteAllMessagesOption(conversationCopy)
|
||||||
spreedCapabilities,
|
|
||||||
SpreedFeatures.CLEAR_HISTORY
|
|
||||||
) && conversationCopy.canDeleteConversation
|
|
||||||
) {
|
|
||||||
binding.clearConversationHistory.visibility = VISIBLE
|
|
||||||
} else {
|
|
||||||
binding.clearConversationHistory.visibility = GONE
|
|
||||||
}
|
|
||||||
showOptionsMenu()
|
showOptionsMenu()
|
||||||
} else {
|
} else {
|
||||||
binding.addParticipantsAction.visibility = GONE
|
binding.addParticipantsAction.visibility = GONE
|
||||||
|
|
||||||
if (ConversationUtils.isNoteToSelfConversation(conversation)) {
|
if (ConversationUtils.isNoteToSelfConversation(conversation)) {
|
||||||
binding.notificationSettingsView.notificationSettings.visibility = VISIBLE
|
binding.notificationSettingsView.notificationSettings.visibility = VISIBLE
|
||||||
} else {
|
} else {
|
||||||
@ -1311,6 +1303,18 @@ class ConversationInfoActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showDeleteAllMessagesOption(conversationCopy: ConversationModel) {
|
||||||
|
if (hasSpreedFeatureCapability(
|
||||||
|
spreedCapabilities,
|
||||||
|
SpreedFeatures.CLEAR_HISTORY
|
||||||
|
) && conversationCopy.canDeleteConversation
|
||||||
|
) {
|
||||||
|
binding.clearConversationHistory.visibility = VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.clearConversationHistory.visibility = GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun submitRecordingConsentChanges() {
|
private fun submitRecordingConsentChanges() {
|
||||||
val state = if (binding.recordingConsentView.recordingConsentForConversationSwitch.isChecked) {
|
val state = if (binding.recordingConsentView.recordingConsentForConversationSwitch.isChecked) {
|
||||||
RECORDING_CONSENT_REQUIRED_FOR_CONVERSATION
|
RECORDING_CONSENT_REQUIRED_FOR_CONVERSATION
|
||||||
|
@ -319,15 +319,20 @@ class ConversationInfoViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("Detekt.TooGenericExceptionCaught")
|
||||||
fun getProfileData(user: User, userId: String) {
|
fun getProfileData(user: User, userId: String) {
|
||||||
val url = ApiUtils.getUrlForProfile(user.baseUrl!!, userId)
|
val url = ApiUtils.getUrlForProfile(user.baseUrl!!, userId)
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
val profile = conversationsRepository.getProfile(user.getCredentials(), url)
|
val profile = conversationsRepository.getProfile(user.getCredentials(), url)
|
||||||
if (profile != null) {
|
if (profile != null) {
|
||||||
_getProfileViewState.value = GetProfileSuccessState(profile)
|
_getProfileViewState.value = GetProfileSuccessState(profile)
|
||||||
} else {
|
} else {
|
||||||
_getProfileViewState.value = GetProfileErrorState
|
_getProfileViewState.value = GetProfileErrorState
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.w(TAG, "Failed to get profile data (if not supported there wil be http405)", e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ class ConversationInfoEditActivity : BaseActivity() {
|
|||||||
binding = ActivityConversationInfoEditBinding.inflate(layoutInflater)
|
binding = ActivityConversationInfoEditBinding.inflate(layoutInflater)
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
|
|
||||||
val extras: Bundle? = intent.extras
|
val extras: Bundle? = intent.extras
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ import android.animation.AnimatorInflater
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.SearchManager
|
import android.app.SearchManager
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
@ -41,6 +40,9 @@ import androidx.appcompat.app.AlertDialog
|
|||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||||
|
import androidx.core.content.pm.ShortcutInfoCompat
|
||||||
|
import androidx.core.content.pm.ShortcutManagerCompat
|
||||||
|
import androidx.core.graphics.drawable.IconCompat
|
||||||
import androidx.core.graphics.drawable.toDrawable
|
import androidx.core.graphics.drawable.toDrawable
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
@ -79,6 +81,7 @@ import com.nextcloud.talk.adapters.items.GenericTextHeaderItem
|
|||||||
import com.nextcloud.talk.adapters.items.LoadMoreResultsItem
|
import com.nextcloud.talk.adapters.items.LoadMoreResultsItem
|
||||||
import com.nextcloud.talk.adapters.items.MessageResultItem
|
import com.nextcloud.talk.adapters.items.MessageResultItem
|
||||||
import com.nextcloud.talk.adapters.items.MessagesTextHeaderItem
|
import com.nextcloud.talk.adapters.items.MessagesTextHeaderItem
|
||||||
|
import com.nextcloud.talk.adapters.items.SpacerItem
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager
|
import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager
|
||||||
@ -264,7 +267,7 @@ class ConversationsListActivity :
|
|||||||
binding = ActivityConversationsBinding.inflate(layoutInflater)
|
binding = ActivityConversationsBinding.inflate(layoutInflater)
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
viewThemeUtils.material.themeCardView(binding.searchToolbar)
|
viewThemeUtils.material.themeCardView(binding.searchToolbar)
|
||||||
viewThemeUtils.material.themeSearchBarText(binding.searchText)
|
viewThemeUtils.material.themeSearchBarText(binding.searchText)
|
||||||
|
|
||||||
@ -291,10 +294,9 @@ class ConversationsListActivity :
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
// actionBar?.show()
|
|
||||||
if (adapter == null) {
|
if (adapter == null) {
|
||||||
adapter = FlexibleAdapter(conversationItems, this, true)
|
adapter = FlexibleAdapter(conversationItems, this, true)
|
||||||
|
addEmptyItemForEdgeToEdgeIfNecessary()
|
||||||
} else {
|
} else {
|
||||||
binding.loadingContent.visibility = View.GONE
|
binding.loadingContent.visibility = View.GONE
|
||||||
}
|
}
|
||||||
@ -340,6 +342,14 @@ class ConversationsListActivity :
|
|||||||
showSearchOrToolbar()
|
showSearchOrToolbar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if edge to edge is used, add an empty item at the bottom of the list
|
||||||
|
@Suppress("MagicNumber")
|
||||||
|
private fun addEmptyItemForEdgeToEdgeIfNecessary() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
||||||
|
adapter?.addScrollableFooter(SpacerItem(200))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("LongMethod")
|
@Suppress("LongMethod")
|
||||||
private fun initObservers() {
|
private fun initObservers() {
|
||||||
this.lifecycleScope.launch {
|
this.lifecycleScope.launch {
|
||||||
@ -409,6 +419,10 @@ class ConversationsListActivity :
|
|||||||
conversationsListViewModel.getRoomsFlow
|
conversationsListViewModel.getRoomsFlow
|
||||||
.onEach { list ->
|
.onEach { list ->
|
||||||
setConversationList(list)
|
setConversationList(list)
|
||||||
|
val noteToSelf = list
|
||||||
|
.firstOrNull { ConversationUtils.isNoteToSelfConversation(it) }
|
||||||
|
val isNoteToSelfAvailable = noteToSelf != null
|
||||||
|
handleNoteToSelfShortcut(isNoteToSelfAvailable, noteToSelf?.token ?: "")
|
||||||
}.collect()
|
}.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,6 +539,29 @@ class ConversationsListActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleNoteToSelfShortcut(noteToSelfAvailable: Boolean, noteToSelfToken: String) {
|
||||||
|
if (noteToSelfAvailable) {
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putString(KEY_ROOM_TOKEN, noteToSelfToken)
|
||||||
|
bundle.putBoolean(BundleKeys.KEY_FOCUS_INPUT, true)
|
||||||
|
val intent = Intent(context, ChatActivity::class.java)
|
||||||
|
intent.putExtras(bundle)
|
||||||
|
intent.action = Intent.ACTION_VIEW
|
||||||
|
val openNotesString = resources.getString(R.string.open_notes)
|
||||||
|
|
||||||
|
val shortcut = ShortcutInfoCompat.Builder(context, NOTE_TO_SELF_SHORTCUT_ID)
|
||||||
|
.setShortLabel(openNotesString)
|
||||||
|
.setLongLabel(openNotesString)
|
||||||
|
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_pencil_grey600_24dp))
|
||||||
|
.setIntent(intent)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
ShortcutManagerCompat.pushDynamicShortcut(context, shortcut)
|
||||||
|
} else {
|
||||||
|
ShortcutManagerCompat.removeDynamicShortcuts(context, listOf(NOTE_TO_SELF_SHORTCUT_ID))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setConversationList(list: List<ConversationModel>) {
|
private fun setConversationList(list: List<ConversationModel>) {
|
||||||
// Update Conversations
|
// Update Conversations
|
||||||
conversationItems.clear()
|
conversationItems.clear()
|
||||||
@ -640,7 +677,7 @@ class ConversationsListActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val archiveFilterOn = filterState[ARCHIVE] ?: false
|
val archiveFilterOn = filterState[ARCHIVE] == true
|
||||||
if (archiveFilterOn && newItems.isEmpty()) {
|
if (archiveFilterOn && newItems.isEmpty()) {
|
||||||
binding.noArchivedConversationLayout.visibility = View.VISIBLE
|
binding.noArchivedConversationLayout.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
@ -755,7 +792,7 @@ class ConversationsListActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initSearchView() {
|
private fun initSearchView() {
|
||||||
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager?
|
val searchManager = getSystemService(SEARCH_SERVICE) as SearchManager?
|
||||||
if (searchItem != null) {
|
if (searchItem != null) {
|
||||||
searchView = MenuItemCompat.getActionView(searchItem) as SearchView
|
searchView = MenuItemCompat.getActionView(searchItem) as SearchView
|
||||||
viewThemeUtils.talk.themeSearchView(searchView!!)
|
viewThemeUtils.talk.themeSearchView(searchView!!)
|
||||||
@ -934,8 +971,7 @@ class ConversationsListActivity :
|
|||||||
} else {
|
} else {
|
||||||
showToolbar()
|
showToolbar()
|
||||||
}
|
}
|
||||||
colorizeStatusBar()
|
initSystemBars()
|
||||||
colorizeNavigationBar()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1217,7 +1253,7 @@ class ConversationsListActivity :
|
|||||||
})
|
})
|
||||||
binding.recyclerView.setOnTouchListener { v: View, _: MotionEvent? ->
|
binding.recyclerView.setOnTouchListener { v: View, _: MotionEvent? ->
|
||||||
if (!isDestroyed) {
|
if (!isDestroyed) {
|
||||||
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
imm.hideSoftInputFromWindow(v.windowToken, 0)
|
imm.hideSoftInputFromWindow(v.windowToken, 0)
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
@ -1398,7 +1434,7 @@ class ConversationsListActivity :
|
|||||||
adapter?.updateDataSet(conversationItems)
|
adapter?.updateDataSet(conversationItems)
|
||||||
adapter?.setFilter("")
|
adapter?.setFilter("")
|
||||||
adapter?.filterItems()
|
adapter?.filterItems()
|
||||||
val archiveFilterOn = filterState[ARCHIVE] ?: false
|
val archiveFilterOn = filterState[ARCHIVE] == true
|
||||||
if (archiveFilterOn && adapter!!.isEmpty) {
|
if (archiveFilterOn && adapter!!.isEmpty) {
|
||||||
binding.noArchivedConversationLayout.visibility = View.VISIBLE
|
binding.noArchivedConversationLayout.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
@ -1809,7 +1845,7 @@ class ConversationsListActivity :
|
|||||||
val callsChannelNotEnabled = !NotificationUtils.isCallsNotificationChannelEnabled(this)
|
val callsChannelNotEnabled = !NotificationUtils.isCallsNotificationChannelEnabled(this)
|
||||||
|
|
||||||
val serverNotificationAppInstalled =
|
val serverNotificationAppInstalled =
|
||||||
currentUser?.capabilities?.notificationsCapability?.features?.isNotEmpty() ?: false
|
currentUser?.capabilities?.notificationsCapability?.features?.isNotEmpty() == true
|
||||||
|
|
||||||
val settingsOfUserAreWrong = notificationPermissionNotGranted ||
|
val settingsOfUserAreWrong = notificationPermissionNotGranted ||
|
||||||
batteryOptimizationNotIgnored ||
|
batteryOptimizationNotIgnored ||
|
||||||
@ -1938,9 +1974,9 @@ class ConversationsListActivity :
|
|||||||
WorkManager.getInstance(applicationContext).enqueue(accountRemovalWork)
|
WorkManager.getInstance(applicationContext).enqueue(accountRemovalWork)
|
||||||
|
|
||||||
WorkManager.getInstance(context).getWorkInfoByIdLiveData(accountRemovalWork.id)
|
WorkManager.getInstance(context).getWorkInfoByIdLiveData(accountRemovalWork.id)
|
||||||
.observeForever { workInfo: WorkInfo ->
|
.observeForever { workInfo: WorkInfo? ->
|
||||||
|
|
||||||
when (workInfo.state) {
|
when (workInfo?.state) {
|
||||||
WorkInfo.State.SUCCEEDED -> {
|
WorkInfo.State.SUCCEEDED -> {
|
||||||
val text = String.format(
|
val text = String.format(
|
||||||
context.resources.getString(R.string.nc_deleted_user),
|
context.resources.getString(R.string.nc_deleted_user),
|
||||||
@ -2183,5 +2219,6 @@ class ConversationsListActivity :
|
|||||||
const val ROOM_TYPE_ONE_ONE = "1"
|
const val ROOM_TYPE_ONE_ONE = "1"
|
||||||
private const val SIXTEEN_HOURS_IN_SECONDS: Long = 57600
|
private const val SIXTEEN_HOURS_IN_SECONDS: Long = 57600
|
||||||
const val LONG_1000: Long = 1000
|
const val LONG_1000: Long = 1000
|
||||||
|
private const val NOTE_TO_SELF_SHORTCUT_ID = "NOTE_TO_SELF_SHORTCUT_ID"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,18 @@ interface ChatMessagesDao {
|
|||||||
)
|
)
|
||||||
fun getTempMessagesForConversation(internalConversationId: String): Flow<List<ChatMessageEntity>>
|
fun getTempMessagesForConversation(internalConversationId: String): Flow<List<ChatMessageEntity>>
|
||||||
|
|
||||||
|
@Query(
|
||||||
|
"""
|
||||||
|
SELECT *
|
||||||
|
FROM ChatMessages
|
||||||
|
WHERE internalConversationId = :internalConversationId
|
||||||
|
AND isTemporary = 1
|
||||||
|
AND sendStatus != 'SENT_PENDING_ACK'
|
||||||
|
ORDER BY timestamp DESC, id DESC
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun getTempUnsentMessagesForConversation(internalConversationId: String): Flow<List<ChatMessageEntity>>
|
||||||
|
|
||||||
@Query(
|
@Query(
|
||||||
"""
|
"""
|
||||||
SELECT *
|
SELECT *
|
||||||
@ -60,7 +72,7 @@ interface ChatMessagesDao {
|
|||||||
ORDER BY timestamp DESC, id DESC
|
ORDER BY timestamp DESC, id DESC
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
fun getTempMessageForConversation(internalConversationId: String, referenceId: String): Flow<ChatMessageEntity>
|
fun getTempMessageForConversation(internalConversationId: String, referenceId: String): Flow<ChatMessageEntity?>
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
suspend fun upsertChatMessages(chatMessages: List<ChatMessageEntity>)
|
suspend fun upsertChatMessages(chatMessages: List<ChatMessageEntity>)
|
||||||
|
@ -68,7 +68,7 @@ fun ChatMessageEntity.asModel() =
|
|||||||
isDeleted = deleted,
|
isDeleted = deleted,
|
||||||
referenceId = referenceId,
|
referenceId = referenceId,
|
||||||
isTemporary = isTemporary,
|
isTemporary = isTemporary,
|
||||||
sendingFailed = sendingFailed,
|
sendStatus = sendStatus,
|
||||||
readStatus = ReadStatus.NONE,
|
readStatus = ReadStatus.NONE,
|
||||||
silent = silent
|
silent = silent
|
||||||
)
|
)
|
||||||
|
@ -64,7 +64,7 @@ data class ChatMessageEntity(
|
|||||||
@ColumnInfo(name = "reactions") var reactions: LinkedHashMap<String, Int>? = null,
|
@ColumnInfo(name = "reactions") var reactions: LinkedHashMap<String, Int>? = null,
|
||||||
@ColumnInfo(name = "reactionsSelf") var reactionsSelf: ArrayList<String>? = null,
|
@ColumnInfo(name = "reactionsSelf") var reactionsSelf: ArrayList<String>? = null,
|
||||||
@ColumnInfo(name = "referenceId") var referenceId: String? = null,
|
@ColumnInfo(name = "referenceId") var referenceId: String? = null,
|
||||||
@ColumnInfo(name = "sendingFailed") var sendingFailed: Boolean = false,
|
@ColumnInfo(name = "sendStatus") var sendStatus: SendStatus? = null,
|
||||||
@ColumnInfo(name = "silent") var silent: Boolean = false,
|
@ColumnInfo(name = "silent") var silent: Boolean = false,
|
||||||
@ColumnInfo(name = "systemMessage") var systemMessageType: ChatMessage.SystemMessageType,
|
@ColumnInfo(name = "systemMessage") var systemMessageType: ChatMessage.SystemMessageType,
|
||||||
@ColumnInfo(name = "timestamp") var timestamp: Long = 0
|
@ColumnInfo(name = "timestamp") var timestamp: Long = 0
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk - Android Client
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.talk.data.database.model
|
||||||
|
|
||||||
|
enum class SendStatus {
|
||||||
|
PENDING,
|
||||||
|
SENT_PENDING_ACK,
|
||||||
|
FAILED
|
||||||
|
}
|
@ -1,18 +1,31 @@
|
|||||||
/*
|
/*
|
||||||
* Nextcloud Talk - Android Client
|
* Nextcloud Talk - Android Client
|
||||||
*
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2024-2025 Marcel Hibbe <dev@mhibbe.de>
|
||||||
* SPDX-FileCopyrightText: 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
* SPDX-FileCopyrightText: 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
package com.nextcloud.talk.data.source.local
|
package com.nextcloud.talk.data.source.local
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.room.DeleteColumn
|
||||||
|
import androidx.room.migration.AutoMigrationSpec
|
||||||
import androidx.room.migration.Migration
|
import androidx.room.migration.Migration
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
import java.sql.SQLException
|
import java.sql.SQLException
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
object Migrations {
|
object Migrations {
|
||||||
|
|
||||||
|
//region Auto migrations
|
||||||
|
|
||||||
|
@DeleteColumn(tableName = "ChatMessages", columnName = "sendingFailed")
|
||||||
|
class AutoMigration16To17 : AutoMigrationSpec
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Manual migrations
|
||||||
|
|
||||||
val MIGRATION_6_8 = object : Migration(6, 8) {
|
val MIGRATION_6_8 = object : Migration(6, 8) {
|
||||||
override fun migrate(db: SupportSQLiteDatabase) {
|
override fun migrate(db: SupportSQLiteDatabase) {
|
||||||
Log.i("Migrations", "Migrating 6 to 8")
|
Log.i("Migrations", "Migrating 6 to 8")
|
||||||
@ -76,6 +89,8 @@ object Migrations {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
fun migrateToRoom(db: SupportSQLiteDatabase) {
|
fun migrateToRoom(db: SupportSQLiteDatabase) {
|
||||||
db.execSQL(
|
db.execSQL(
|
||||||
"CREATE TABLE User_new (" +
|
"CREATE TABLE User_new (" +
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Nextcloud Talk - Android Client
|
* Nextcloud Talk - Android Client
|
||||||
*
|
*
|
||||||
* SPDX-FileCopyrightText: 2023-2024 Marcel Hibbe <dev@mhibbe.de>
|
* SPDX-FileCopyrightText: 2023-2025 Marcel Hibbe <dev@mhibbe.de>
|
||||||
* SPDX-FileCopyrightText: 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
* SPDX-FileCopyrightText: 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
* SPDX-FileCopyrightText: 2017-2020 Mario Danic <mario@lovelyhq.com>
|
* SPDX-FileCopyrightText: 2017-2020 Mario Danic <mario@lovelyhq.com>
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
@ -23,12 +23,14 @@ import com.nextcloud.talk.data.database.dao.ConversationsDao
|
|||||||
import com.nextcloud.talk.data.database.model.ChatBlockEntity
|
import com.nextcloud.talk.data.database.model.ChatBlockEntity
|
||||||
import com.nextcloud.talk.data.database.model.ChatMessageEntity
|
import com.nextcloud.talk.data.database.model.ChatMessageEntity
|
||||||
import com.nextcloud.talk.data.database.model.ConversationEntity
|
import com.nextcloud.talk.data.database.model.ConversationEntity
|
||||||
|
import com.nextcloud.talk.data.source.local.Migrations.AutoMigration16To17
|
||||||
import com.nextcloud.talk.data.source.local.converters.ArrayListConverter
|
import com.nextcloud.talk.data.source.local.converters.ArrayListConverter
|
||||||
import com.nextcloud.talk.data.source.local.converters.CapabilitiesConverter
|
import com.nextcloud.talk.data.source.local.converters.CapabilitiesConverter
|
||||||
import com.nextcloud.talk.data.source.local.converters.ExternalSignalingServerConverter
|
import com.nextcloud.talk.data.source.local.converters.ExternalSignalingServerConverter
|
||||||
import com.nextcloud.talk.data.source.local.converters.HashMapHashMapConverter
|
import com.nextcloud.talk.data.source.local.converters.HashMapHashMapConverter
|
||||||
import com.nextcloud.talk.data.source.local.converters.LinkedHashMapConverter
|
import com.nextcloud.talk.data.source.local.converters.LinkedHashMapConverter
|
||||||
import com.nextcloud.talk.data.source.local.converters.PushConfigurationConverter
|
import com.nextcloud.talk.data.source.local.converters.PushConfigurationConverter
|
||||||
|
import com.nextcloud.talk.data.source.local.converters.SendStatusConverter
|
||||||
import com.nextcloud.talk.data.source.local.converters.ServerVersionConverter
|
import com.nextcloud.talk.data.source.local.converters.ServerVersionConverter
|
||||||
import com.nextcloud.talk.data.source.local.converters.SignalingSettingsConverter
|
import com.nextcloud.talk.data.source.local.converters.SignalingSettingsConverter
|
||||||
import com.nextcloud.talk.data.storage.ArbitraryStoragesDao
|
import com.nextcloud.talk.data.storage.ArbitraryStoragesDao
|
||||||
@ -49,9 +51,10 @@ import java.util.Locale
|
|||||||
ChatMessageEntity::class,
|
ChatMessageEntity::class,
|
||||||
ChatBlockEntity::class
|
ChatBlockEntity::class
|
||||||
],
|
],
|
||||||
version = 16,
|
version = 17,
|
||||||
autoMigrations = [
|
autoMigrations = [
|
||||||
AutoMigration(from = 9, to = 10)
|
AutoMigration(from = 9, to = 10),
|
||||||
|
AutoMigration(from = 16, to = 17, spec = AutoMigration16To17::class)
|
||||||
],
|
],
|
||||||
exportSchema = true
|
exportSchema = true
|
||||||
)
|
)
|
||||||
@ -63,7 +66,8 @@ import java.util.Locale
|
|||||||
SignalingSettingsConverter::class,
|
SignalingSettingsConverter::class,
|
||||||
HashMapHashMapConverter::class,
|
HashMapHashMapConverter::class,
|
||||||
LinkedHashMapConverter::class,
|
LinkedHashMapConverter::class,
|
||||||
ArrayListConverter::class
|
ArrayListConverter::class,
|
||||||
|
SendStatusConverter::class
|
||||||
)
|
)
|
||||||
abstract class TalkDatabase : RoomDatabase() {
|
abstract class TalkDatabase : RoomDatabase() {
|
||||||
|
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk - Android Client
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.talk.data.source.local.converters
|
||||||
|
|
||||||
|
import androidx.room.TypeConverter
|
||||||
|
import com.nextcloud.talk.data.database.model.SendStatus
|
||||||
|
|
||||||
|
class SendStatusConverter {
|
||||||
|
@TypeConverter
|
||||||
|
fun fromStatus(value: SendStatus): String {
|
||||||
|
return value.name
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun toStatus(value: String): SendStatus {
|
||||||
|
return SendStatus.valueOf(value)
|
||||||
|
}
|
||||||
|
}
|
@ -21,6 +21,7 @@ import androidx.compose.foundation.background
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.statusBarsPadding
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
@ -28,8 +29,9 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.colorResource
|
import androidx.compose.ui.res.colorResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.nextcloud.talk.BuildConfig
|
import com.nextcloud.talk.BuildConfig
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
@ -37,8 +39,8 @@ import com.nextcloud.talk.activities.BaseActivity
|
|||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager
|
import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager
|
||||||
|
import com.nextcloud.talk.components.ColoredStatusBar
|
||||||
import com.nextcloud.talk.components.StandardAppBar
|
import com.nextcloud.talk.components.StandardAppBar
|
||||||
import com.nextcloud.talk.components.SetupSystemBars
|
|
||||||
import com.nextcloud.talk.users.UserManager
|
import com.nextcloud.talk.users.UserManager
|
||||||
import com.nextcloud.talk.utils.BrandingUtils
|
import com.nextcloud.talk.utils.BrandingUtils
|
||||||
import com.nextcloud.talk.utils.ClosedInterfaceImpl
|
import com.nextcloud.talk.utils.ClosedInterfaceImpl
|
||||||
@ -109,18 +111,22 @@ class DiagnoseActivity : BaseActivity() {
|
|||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colorScheme = colorScheme
|
colorScheme = colorScheme
|
||||||
) {
|
) {
|
||||||
|
ColoredStatusBar()
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
modifier = Modifier
|
||||||
|
.statusBarsPadding(),
|
||||||
topBar = {
|
topBar = {
|
||||||
StandardAppBar(
|
StandardAppBar(
|
||||||
title = stringResource(R.string.nc_settings_diagnose_title),
|
title = stringResource(R.string.nc_settings_diagnose_title),
|
||||||
menuItems
|
menuItems
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
content = {
|
content = { paddingValues ->
|
||||||
val viewState = diagnoseViewModel.notificationViewState.collectAsState().value
|
val viewState = diagnoseViewModel.notificationViewState.collectAsState().value
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
.padding(it)
|
.padding(0.dp, paddingValues.calculateTopPadding(), 0.dp, 0.dp)
|
||||||
.background(backgroundColor)
|
.background(backgroundColor)
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
@ -136,7 +142,6 @@ class DiagnoseActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
SetupSystemBars()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,12 @@ fun DiagnoseContentComposable(
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(16.dp)
|
.padding(
|
||||||
|
start = 16.dp,
|
||||||
|
top = 0.dp,
|
||||||
|
end = 16.dp,
|
||||||
|
bottom = 0.dp
|
||||||
|
)
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
data.value.forEach { element ->
|
data.value.forEach { element ->
|
||||||
@ -100,6 +105,7 @@ fun DiagnoseContentComposable(
|
|||||||
ShowTestPushButton(onTestPushClick)
|
ShowTestPushButton(onTestPushClick)
|
||||||
}
|
}
|
||||||
ShowNotificationData(isLoading, showDialog, context, viewState, onDismissDialog)
|
ShowNotificationData(isLoading, showDialog, context, viewState, onDismissDialog)
|
||||||
|
Spacer(modifier = Modifier.height(40.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,6 +190,7 @@ class FullScreenMediaActivity : AppCompatActivity() {
|
|||||||
supportActionBar?.show()
|
supportActionBar?.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(UnstableApi::class)
|
||||||
private fun applyWindowInsets() {
|
private fun applyWindowInsets() {
|
||||||
val playerView = binding.playerView
|
val playerView = binding.playerView
|
||||||
val exoControls = playerView.findViewById<FrameLayout>(R.id.exo_bottom_bar)
|
val exoControls = playerView.findViewById<FrameLayout>(R.id.exo_bottom_bar)
|
||||||
|
@ -65,7 +65,7 @@ class InvitationsActivity : BaseActivity() {
|
|||||||
binding = ActivityInvitationsBinding.inflate(layoutInflater)
|
binding = ActivityInvitationsBinding.inflate(layoutInflater)
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
|
|
||||||
adapter = InvitationsAdapter(currentUser) { invitation, action ->
|
adapter = InvitationsAdapter(currentUser) { invitation, action ->
|
||||||
handleInvitation(invitation, action)
|
handleInvitation(invitation, action)
|
||||||
|
@ -67,7 +67,7 @@ class GeocodingActivity :
|
|||||||
binding = ActivityGeocodingBinding.inflate(layoutInflater)
|
binding = ActivityGeocodingBinding.inflate(layoutInflater)
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
|
|
||||||
Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context))
|
Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context))
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ class LocationPickerActivity :
|
|||||||
binding = ActivityLocationBinding.inflate(layoutInflater)
|
binding = ActivityLocationBinding.inflate(layoutInflater)
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
|
|
||||||
getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context))
|
getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context))
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ class MessageSearchActivity : BaseActivity() {
|
|||||||
binding = ActivityMessageSearchBinding.inflate(layoutInflater)
|
binding = ActivityMessageSearchBinding.inflate(layoutInflater)
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
|
|
||||||
viewModel = ViewModelProvider(this, viewModelFactory)[MessageSearchViewModel::class.java]
|
viewModel = ViewModelProvider(this, viewModelFactory)[MessageSearchViewModel::class.java]
|
||||||
user = currentUserProvider.currentUser.blockingGet()
|
user = currentUserProvider.currentUser.blockingGet()
|
||||||
|
@ -21,7 +21,7 @@ class ChatUtils {
|
|||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("Detekt.ComplexMethod")
|
@Suppress("Detekt.ComplexMethod", "Detekt.ComplexCondition")
|
||||||
private fun parse(messageParameters: HashMap<String?, HashMap<String?, String?>>, message: String?): String? {
|
private fun parse(messageParameters: HashMap<String?, HashMap<String?, String?>>, message: String?): String? {
|
||||||
var resultMessage = message
|
var resultMessage = message
|
||||||
for (key in messageParameters.keys) {
|
for (key in messageParameters.keys) {
|
||||||
@ -29,7 +29,9 @@ class ChatUtils {
|
|||||||
|
|
||||||
if (individualHashMap != null) {
|
if (individualHashMap != null) {
|
||||||
val type = individualHashMap["type"]
|
val type = individualHashMap["type"]
|
||||||
resultMessage = if (type == "user" || type == "guest" || type == "call" || type == "email") {
|
resultMessage = if (type == "user" || type == "guest" || type == "call" || type == "email" ||
|
||||||
|
type == "user-group" || type == "circle"
|
||||||
|
) {
|
||||||
resultMessage?.replace("{$key}", "@" + individualHashMap["name"])
|
resultMessage?.replace("{$key}", "@" + individualHashMap["name"])
|
||||||
} else if (type == "geo-location") {
|
} else if (type == "geo-location") {
|
||||||
individualHashMap["name"]
|
individualHashMap["name"]
|
||||||
|
@ -57,7 +57,7 @@ class ListOpenConversationsActivity : BaseActivity() {
|
|||||||
binding = ActivityOpenConversationsBinding.inflate(layoutInflater)
|
binding = ActivityOpenConversationsBinding.inflate(layoutInflater)
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
viewThemeUtils.platform.colorImageView(binding.searchOpenConversations, ColorRole.ON_SURFACE)
|
viewThemeUtils.platform.colorImageView(binding.searchOpenConversations, ColorRole.ON_SURFACE)
|
||||||
viewThemeUtils.material.colorTextInputLayout(binding.textInputLayout)
|
viewThemeUtils.material.colorTextInputLayout(binding.textInputLayout)
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ class ProfileActivity : BaseActivity() {
|
|||||||
binding = ActivityProfileBinding.inflate(layoutInflater)
|
binding = ActivityProfileBinding.inflate(layoutInflater)
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
@ -6,14 +6,17 @@
|
|||||||
*/
|
*/
|
||||||
package com.nextcloud.talk.receivers
|
package com.nextcloud.talk.receivers
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
import android.text.style.ForegroundColorSpan
|
import android.text.style.ForegroundColorSpan
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.app.Person
|
import androidx.core.app.Person
|
||||||
@ -162,11 +165,17 @@ class DirectReplyReceiver : BroadcastReceiver() {
|
|||||||
// Set the updated style
|
// Set the updated style
|
||||||
previousBuilder.setStyle(previousStyle)
|
previousBuilder.setStyle(previousStyle)
|
||||||
|
|
||||||
|
if (ActivityCompat.checkSelfPermission(
|
||||||
|
context,
|
||||||
|
Manifest.permission.POST_NOTIFICATIONS
|
||||||
|
) == PackageManager.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
// Check if notification still exists
|
// Check if notification still exists
|
||||||
if (findActiveNotification(systemNotificationId!!) != null) {
|
if (findActiveNotification(systemNotificationId!!) != null) {
|
||||||
NotificationManagerCompat.from(context).notify(systemNotificationId!!, previousBuilder.build())
|
NotificationManagerCompat.from(context).notify(systemNotificationId!!, previousBuilder.build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe()
|
.subscribe()
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ class SettingsActivity :
|
|||||||
binding = ActivitySettingsBinding.inflate(layoutInflater)
|
binding = ActivitySettingsBinding.inflate(layoutInflater)
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
|
|
||||||
binding.avatarImage.let { ViewCompat.setTransitionName(it, "userAvatar.transitionTag") }
|
binding.avatarImage.let { ViewCompat.setTransitionName(it, "userAvatar.transitionTag") }
|
||||||
|
|
||||||
@ -681,9 +681,9 @@ class SettingsActivity :
|
|||||||
WorkManager.getInstance(applicationContext).enqueue(accountRemovalWork)
|
WorkManager.getInstance(applicationContext).enqueue(accountRemovalWork)
|
||||||
|
|
||||||
WorkManager.getInstance(context).getWorkInfoByIdLiveData(accountRemovalWork.id)
|
WorkManager.getInstance(context).getWorkInfoByIdLiveData(accountRemovalWork.id)
|
||||||
.observeForever { workInfo: WorkInfo ->
|
.observeForever { workInfo: WorkInfo? ->
|
||||||
|
|
||||||
when (workInfo.state) {
|
when (workInfo?.state) {
|
||||||
WorkInfo.State.SUCCEEDED -> {
|
WorkInfo.State.SUCCEEDED -> {
|
||||||
val text = String.format(
|
val text = String.format(
|
||||||
context.resources.getString(R.string.nc_deleted_user),
|
context.resources.getString(R.string.nc_deleted_user),
|
||||||
|
@ -13,7 +13,6 @@ import android.os.Bundle
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.content.res.ResourcesCompat
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
@ -28,7 +27,6 @@ import com.nextcloud.talk.databinding.ActivitySharedItemsBinding
|
|||||||
import com.nextcloud.talk.shareditems.adapters.SharedItemsAdapter
|
import com.nextcloud.talk.shareditems.adapters.SharedItemsAdapter
|
||||||
import com.nextcloud.talk.shareditems.model.SharedItemType
|
import com.nextcloud.talk.shareditems.model.SharedItemType
|
||||||
import com.nextcloud.talk.shareditems.viewmodels.SharedItemsViewModel
|
import com.nextcloud.talk.shareditems.viewmodels.SharedItemsViewModel
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CONVERSATION_NAME
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CONVERSATION_NAME
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -57,15 +55,11 @@ class SharedItemsActivity : BaseActivity() {
|
|||||||
setSupportActionBar(binding.sharedItemsToolbar)
|
setSupportActionBar(binding.sharedItemsToolbar)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
viewThemeUtils.platform.themeStatusBar(this)
|
initSystemBars()
|
||||||
|
|
||||||
viewThemeUtils.material.themeToolbar(binding.sharedItemsToolbar)
|
viewThemeUtils.material.themeToolbar(binding.sharedItemsToolbar)
|
||||||
viewThemeUtils.material.themeTabLayoutOnSurface(binding.sharedItemsTabs)
|
viewThemeUtils.material.themeTabLayoutOnSurface(binding.sharedItemsTabs)
|
||||||
|
|
||||||
DisplayUtils.applyColorToNavigationBar(
|
|
||||||
this.window,
|
|
||||||
ResourcesCompat.getColor(resources, R.color.bg_default, null)
|
|
||||||
)
|
|
||||||
|
|
||||||
supportActionBar?.title = conversationName
|
supportActionBar?.title = conversationName
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ class TranslateActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupSystemColors()
|
initSystemBars()
|
||||||
setupTextViews()
|
setupTextViews()
|
||||||
viewModel.getLanguages()
|
viewModel.getLanguages()
|
||||||
setupCopyButton()
|
setupCopyButton()
|
||||||
|
@ -118,7 +118,6 @@ class ConversationsListBottomDialog(
|
|||||||
currentUser.capabilities?.spreedCapability!!,
|
currentUser.capabilities?.spreedCapability!!,
|
||||||
SpreedFeatures.FAVORITES
|
SpreedFeatures.FAVORITES
|
||||||
)
|
)
|
||||||
val canModerate = ConversationUtils.canModerate(conversation, currentUser.capabilities?.spreedCapability!!)
|
|
||||||
|
|
||||||
binding.conversationRemoveFromFavorites.visibility = setVisibleIf(
|
binding.conversationRemoveFromFavorites.visibility = setVisibleIf(
|
||||||
hasFavoritesCapability && conversation.favorite
|
hasFavoritesCapability && conversation.favorite
|
||||||
@ -149,14 +148,11 @@ class ConversationsListBottomDialog(
|
|||||||
)
|
)
|
||||||
|
|
||||||
binding.conversationOperationDelete.visibility = setVisibleIf(
|
binding.conversationOperationDelete.visibility = setVisibleIf(
|
||||||
canModerate
|
conversation.canDeleteConversation
|
||||||
)
|
)
|
||||||
|
|
||||||
binding.conversationOperationLeave.visibility = setVisibleIf(
|
binding.conversationOperationLeave.visibility = setVisibleIf(
|
||||||
conversation.canLeaveConversation &&
|
conversation.canLeaveConversation
|
||||||
// leaving is by api not possible for the last user with moderator permissions.
|
|
||||||
// for now, hide this option for all moderators.
|
|
||||||
!ConversationUtils.canModerate(conversation, currentUser.capabilities!!.spreedCapability!!)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ import com.nextcloud.talk.R
|
|||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.chat.ChatActivity
|
import com.nextcloud.talk.chat.ChatActivity
|
||||||
import com.nextcloud.talk.chat.data.model.ChatMessage
|
import com.nextcloud.talk.chat.data.model.ChatMessage
|
||||||
|
import com.nextcloud.talk.data.database.model.SendStatus
|
||||||
import com.nextcloud.talk.data.network.NetworkMonitor
|
import com.nextcloud.talk.data.network.NetworkMonitor
|
||||||
import com.nextcloud.talk.databinding.DialogTempMessageActionsBinding
|
import com.nextcloud.talk.databinding.DialogTempMessageActionsBinding
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
@ -58,9 +59,10 @@ class TempMessageActionsDialog(
|
|||||||
|
|
||||||
private fun initMenuItems() {
|
private fun initMenuItems() {
|
||||||
this.lifecycleScope.launch {
|
this.lifecycleScope.launch {
|
||||||
initResendMessage(message.sendingFailed && networkMonitor.isOnline.value)
|
val sendingFailed = message.sendStatus == SendStatus.FAILED
|
||||||
initMenuEditMessage(message.sendingFailed || !networkMonitor.isOnline.value)
|
initResendMessage(sendingFailed && networkMonitor.isOnline.value)
|
||||||
initMenuDeleteMessage(message.sendingFailed || !networkMonitor.isOnline.value)
|
initMenuEditMessage(sendingFailed || !networkMonitor.isOnline.value)
|
||||||
|
initMenuDeleteMessage(sendingFailed || !networkMonitor.isOnline.value)
|
||||||
initMenuItemCopy()
|
initMenuItemCopy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk - Android Client
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.talk.utils
|
||||||
|
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.activity.SystemBarStyle
|
||||||
|
import androidx.activity.enableEdgeToEdge
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is similar to "adjustUIForAPILevel35" in
|
||||||
|
* AppCompatActivityExtensions.kt in https://github.com/nextcloud/android-common/
|
||||||
|
* Only window.addSystemBarPaddings() had to be removed. This could be unified again at some point.
|
||||||
|
*/
|
||||||
|
@JvmOverloads
|
||||||
|
fun AppCompatActivity.adjustUIForAPILevel35(
|
||||||
|
statusBarStyle: SystemBarStyle = SystemBarStyle.auto(Color.TRANSPARENT, Color.TRANSPARENT),
|
||||||
|
// It may make sense to change navigationBarStyle to "SystemBarStyle.auto(Color.TRANSPARENT, Color.TRANSPARENT)"
|
||||||
|
// For now, it is set to "light" to have a fully transparent navigation bar to align with the XML screens.
|
||||||
|
// It may be wanted to have a semi transparent navigation bar in the future. Then set it to "auto" and try to
|
||||||
|
// migrate the XML screens to Compose (having semi transparent navigation bar for XML did not work out. In
|
||||||
|
// general, supporting both XML and Compose system bar handling is a pain and we will have it easier without XML)
|
||||||
|
// So in short: migrate all screens to Compose. Then it's easier to decide if navigation bar should be semi
|
||||||
|
// transparent or not for all screens.
|
||||||
|
navigationBarStyle: SystemBarStyle = SystemBarStyle.light(Color.TRANSPARENT, Color.TRANSPARENT)
|
||||||
|
) {
|
||||||
|
val isApiLevel35OrHigher = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
||||||
|
if (!isApiLevel35OrHigher) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
enableEdgeToEdge(statusBarStyle, navigationBarStyle)
|
||||||
|
}
|
@ -81,4 +81,5 @@ object BundleKeys {
|
|||||||
const val KEY_FIELD_MAP: String = "KEY_FIELD_MAP"
|
const val KEY_FIELD_MAP: String = "KEY_FIELD_MAP"
|
||||||
const val KEY_CHAT_URL: String = "KEY_CHAT_URL"
|
const val KEY_CHAT_URL: String = "KEY_CHAT_URL"
|
||||||
const val KEY_SCROLL_TO_NOTIFICATION_CATEGORY: String = "KEY_SCROLL_TO_NOTIFICATION_CATEGORY"
|
const val KEY_SCROLL_TO_NOTIFICATION_CATEGORY: String = "KEY_SCROLL_TO_NOTIFICATION_CATEGORY"
|
||||||
|
const val KEY_FOCUS_INPUT: String = "KEY_FOCUS_INPUT"
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,11 @@ class DummyChatMessagesDaoImpl : ChatMessagesDao {
|
|||||||
override fun getTempMessagesForConversation(internalConversationId: String): Flow<List<ChatMessageEntity>> =
|
override fun getTempMessagesForConversation(internalConversationId: String): Flow<List<ChatMessageEntity>> =
|
||||||
flowOf()
|
flowOf()
|
||||||
|
|
||||||
|
override fun getTempUnsentMessagesForConversation(internalConversationId: String): Flow<List<ChatMessageEntity>> {
|
||||||
|
// nothing to return here as long this class is only used for the Search window
|
||||||
|
return flowOf()
|
||||||
|
}
|
||||||
|
|
||||||
override fun getTempMessageForConversation(
|
override fun getTempMessageForConversation(
|
||||||
internalConversationId: String,
|
internalConversationId: String,
|
||||||
referenceId: String
|
referenceId: String
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2018-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2018-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
@ -11,5 +11,6 @@
|
|||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FFFFFFFF"
|
android:fillColor="#FFFFFFFF"
|
||||||
android:pathData="M280,920Q247,920 223.5,896.5Q200,873 200,840L200,120Q200,87 223.5,63.5Q247,40 280,40L680,40Q713,40 736.5,63.5Q760,87 760,120L760,840Q760,873 736.5,896.5Q713,920 680,920L280,920ZM280,720L680,720L680,240L280,240L280,720Z" />
|
android:pathData="M280,920Q247,920 223.5,896.5Q200,873 200,840L200,120Q200,87 223.5,63.5Q247,40 280,40L680,40Q713,40 736.5,63.5Q760,87 760,120L760,244Q778,251 789,266Q800,281 800,300L800,380Q800,399 789,414Q778,429 760,436L760,840Q760,873 736.5,896.5Q713,920 680,920L280,920ZM280,840L680,840Q680,840 680,840Q680,840 680,840L680,120Q680,120 680,120Q680,120 680,120L280,120Q280,120 280,120Q280,120 280,120L280,840Q280,840 280,840Q280,840 280,840ZM280,840Q280,840 280,840Q280,840 280,840L280,120Q280,120 280,120Q280,120 280,120L280,120Q280,120 280,120Q280,120 280,120L280,840Q280,840 280,840Q280,840 280,840ZM480,240Q497,240 508.5,228.5Q520,217 520,200Q520,183 508.5,171.5Q497,160 480,160Q463,160 451.5,171.5Q440,183 440,200Q440,217 451.5,228.5Q463,240 480,240Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2018-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2018-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
@ -12,5 +12,5 @@
|
|||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M-19,861L-19,718Q-19,677 0.69,644.15Q20.38,611.29 53,594Q119,560 189.27,543Q259.54,526 332,526Q404.12,526 474.06,543Q544,560 610,594Q642.63,611.29 662.31,644.15Q682,677 682,718L682,861L-19,861ZM767,861L767,706Q767,664 744,614Q721,564 672,529Q735,535 790.5,551.5Q846,568 893,594Q934.84,617.77 956.92,646.88Q979,676 979,706L979,861L767,861ZM331,473Q253.45,473 198.23,417.78Q143,362.55 143,285Q143,207.45 198.23,152.22Q253.45,97 331,97Q408.55,97 463.77,152.22Q519,207.45 519,285Q519,362.55 463.77,417.78Q408.55,473 331,473ZM816,285Q816,362.55 760.78,417.78Q705.55,473 628,473Q613,473 587,469.5Q561,466 546,461Q575,423 589.5,378.15Q604,333.3 604,285Q604,236.7 589.5,191.85Q575,147 546,109Q566,102 587,99.5Q608,97 628,97Q705.55,97 760.78,152.22Q816,207.45 816,285Z" />
|
android:pathData="M40,800L40,688Q40,654 57.5,625.5Q75,597 104,582Q166,551 230,535.5Q294,520 360,520Q426,520 490,535.5Q554,551 616,582Q645,597 662.5,625.5Q680,654 680,688L680,800L40,800ZM760,800L760,680Q760,636 735.5,595.5Q711,555 666,526Q717,532 762,546.5Q807,561 846,582Q882,602 901,626.5Q920,651 920,680L920,800L760,800ZM360,480Q294,480 247,433Q200,386 200,320Q200,254 247,207Q294,160 360,160Q426,160 473,207Q520,254 520,320Q520,386 473,433Q426,480 360,480ZM760,320Q760,386 713,433Q666,480 600,480Q589,480 572,477.5Q555,475 544,472Q571,440 585.5,401Q600,362 600,320Q600,278 585.5,239Q571,200 544,168Q558,163 572,161.5Q586,160 600,160Q666,160 713,207Q760,254 760,320ZM120,720L600,720L600,688Q600,677 594.5,668Q589,659 580,654Q526,627 471,613.5Q416,600 360,600Q304,600 249,613.5Q194,627 140,654Q131,659 125.5,668Q120,677 120,688L120,720ZM360,400Q393,400 416.5,376.5Q440,353 440,320Q440,287 416.5,263.5Q393,240 360,240Q327,240 303.5,263.5Q280,287 280,320Q280,353 303.5,376.5Q327,400 360,400ZM360,720L360,720L360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720ZM360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
|
~ SPDX-FileCopyrightText: 2018-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: GPL-3.0-or-later
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="16dp"
|
android:width="24dp"
|
||||||
android:height="16dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="16"
|
android:tint="#FFFFFFFF"
|
||||||
android:viewportHeight="16">
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FFFFFFFF"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="m7.95,0.65c-4.1,0 -7.4,3.3 -7.4,7.4s3.3,7.4 7.4,7.4 7.4,-3.3 7.4,-7.4 -3.3,-7.4 -7.4,-7.4zM8.75,1.55c1.3,0 2.4,0.8 3.5,1.3l1.8,2.5 -0.3,1.1 0.6,0.3v2.4c-0.2,0.7 -0.6,1.3 -0.9,2 -0.2,0.1 0,-0.8 -0.1,-1 0,-0.6 -0.5,-0.6 -0.9,-0.2 -0.4,0.3 -1.4,0.3 -1.5,-0.4 -0.3,-0.8 0,-1.7 0.3,-2.5l-0.6,-0.7 0.2,-1.8 -0.8,-0.9 0.2,-1 -1,-0.6c-0.2,-0.2 -0.6,-0.2 -0.7,-0.4 0.1,0 0.2,-0.1 0.2,-0.1zM6.15,1.65s0.1,0 0.1,0.1c0.4,0.2 -0.1,0.4 -0.2,0.6 -0.5,0.3 0.3,0.7 0.5,1 0.4,-0.1 0.8,-0.7 1.4,-0.5 0.7,-0.2 0.6,0.6 1.1,1 0.1,0.2 0.9,0.8 0.4,0.6 -0.5,-0.4 -1,-0.4 -1.3,0.1 -0.8,0.5 -0.3,-0.9 -0.7,-1.2 -0.6,-0.7 -0.4,0.5 -0.4,0.9 -0.4,0 -1.1,-0.3 -1.5,0.2l0.4,0.6 0.5,-0.7c0,-0.3 0.1,0.2 0.3,0.3 0.1,0.2 0.8,0.7 0.3,0.9 -0.8,0.4 -1.4,1.1 -2.1,1.7 -0.2,0.5 -0.7,0.4 -1,0 -0.7,-0.4 -0.7,0.7 -0.6,1.1l0.6,-0.4v1.1c-0.4,0.4 -0.9,-0.7 -1.3,-0.9v-1.6c0,-0.4 -0.1,-0.9 0,-1.3 0.8,-0.9 1.7,-1.9 2.2,-3h0.8c0.6,0.2 0.3,-0.7 0.5,-0.6zM4.95,9.85c0.1,0 0.2,0 0.3,0.1 0.8,0.1 1.4,0.7 2,1.1 0.5,0.5 1.6,0.3 1.7,1.2 -0.2,0.9 -1.1,1.4 -1.8,1.7 -0.2,0.1 -0.4,0.2 -0.6,0.2 -0.7,0.2 -1,-0.6 -1.2,-1.1 -0.3,-0.7 -1.1,-1.2 -1,-2.1 0,-0.4 0.2,-1 0.6,-1.1z" />
|
android:pathData="M480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q614,800 707,707Q800,614 800,480Q800,473 799.5,465.5Q799,458 799,453Q794,482 772,501Q750,520 720,520L640,520Q607,520 583.5,496.5Q560,473 560,440L560,400L400,400L400,320Q400,287 423.5,263.5Q447,240 480,240L520,240L520,240Q520,217 532.5,199.5Q545,182 563,171Q543,166 522.5,163Q502,160 480,160Q346,160 253,253Q160,346 160,480Q160,480 160,480Q160,480 160,480L360,480Q426,480 473,527Q520,574 520,640L520,680L400,680L400,790Q420,795 439.5,797.5Q459,800 480,800Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2018-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2018-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="16dp"
|
android:width="24dp"
|
||||||
android:height="16dp"
|
android:height="24dp"
|
||||||
|
android:tint="#FFFFFFFF"
|
||||||
android:viewportWidth="960"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FFFFFFFF"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M240,880Q207,880 183.5,856.5Q160,833 160,800L160,400Q160,367 183.5,343.5Q207,320 240,320L280,320L280,240Q280,157 338.5,98.5Q397,40 480,40Q563,40 621.5,98.5Q680,157 680,240L680,320L720,320Q753,320 776.5,343.5Q800,367 800,400L800,800Q800,833 776.5,856.5Q753,880 720,880L240,880ZM480,680Q513,680 536.5,656.5Q560,633 560,600Q560,567 536.5,543.5Q513,520 480,520Q447,520 423.5,543.5Q400,567 400,600Q400,633 423.5,656.5Q447,680 480,680ZM360,320L600,320L600,240Q600,190 565,155Q530,120 480,120Q430,120 395,155Q360,190 360,240L360,320Z" />
|
android:pathData="M240,880Q207,880 183.5,856.5Q160,833 160,800L160,400Q160,367 183.5,343.5Q207,320 240,320L280,320L280,240Q280,157 338.5,98.5Q397,40 480,40Q563,40 621.5,98.5Q680,157 680,240L680,320L720,320Q753,320 776.5,343.5Q800,367 800,400L800,800Q800,833 776.5,856.5Q753,880 720,880L240,880ZM240,800L720,800Q720,800 720,800Q720,800 720,800L720,400Q720,400 720,400Q720,400 720,400L240,400Q240,400 240,400Q240,400 240,400L240,800Q240,800 240,800Q240,800 240,800ZM480,680Q513,680 536.5,656.5Q560,633 560,600Q560,567 536.5,543.5Q513,520 480,520Q447,520 423.5,543.5Q400,567 400,600Q400,633 423.5,656.5Q447,680 480,680ZM360,320L600,320L600,240Q600,190 565,155Q530,120 480,120Q430,120 395,155Q360,190 360,240L360,320ZM240,800Q240,800 240,800Q240,800 240,800L240,400Q240,400 240,400Q240,400 240,400L240,400Q240,400 240,400Q240,400 240,400L240,800Q240,800 240,800Q240,800 240,800Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2018-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2018-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:fillColor="#ffffff"
|
android:tint="#ffffff"
|
||||||
android:viewportWidth="960"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M480,680Q497,680 508.5,668.5Q520,657 520,640Q520,623 508.5,611.5Q497,600 480,600Q463,600 451.5,611.5Q440,623 440,640Q440,657 451.5,668.5Q463,680 480,680ZM440,520L520,520L520,280L440,280L440,520ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880Z" />
|
android:pathData="M480,680Q497,680 508.5,668.5Q520,657 520,640Q520,623 508.5,611.5Q497,600 480,600Q463,600 451.5,611.5Q440,623 440,640Q440,657 451.5,668.5Q463,680 480,680ZM440,520L520,520L520,280L440,280L440,520ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q614,800 707,707Q800,614 800,480Q800,346 707,253Q614,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -4,15 +4,13 @@
|
|||||||
~ SPDX-FileCopyrightText: 2018-2025 Google LLC
|
~ SPDX-FileCopyrightText: 2018-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="#969696"
|
android:tint="#969696"
|
||||||
android:viewportHeight="24"
|
android:viewportWidth="960"
|
||||||
android:viewportWidth="24"
|
android:viewportHeight="960">
|
||||||
android:width="24dp">
|
<path
|
||||||
|
android:fillColor="#969696"
|
||||||
<path android:fillColor="#969696"
|
android:pathData="M200,840Q167,840 143.5,816.5Q120,793 120,760L120,200Q120,167 143.5,143.5Q167,120 200,120L760,120Q793,120 816.5,143.5Q840,167 840,200L840,760Q840,793 816.5,816.5Q793,840 760,840L200,840ZM240,680L720,680L570,480L450,640L360,520L240,680ZM340,400Q365,400 382.5,382.5Q400,365 400,340Q400,315 382.5,297.5Q365,280 340,280Q315,280 297.5,297.5Q280,315 280,340Q280,365 297.5,382.5Q315,400 340,400Z" />
|
||||||
android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/>
|
|
||||||
|
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2023-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2023-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
@ -12,5 +12,5 @@
|
|||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M480,680Q497,680 508.5,668.5Q520,657 520,640Q520,623 508.5,611.5Q497,600 480,600Q463,600 451.5,611.5Q440,623 440,640Q440,657 451.5,668.5Q463,680 480,680ZM440,520L520,520L520,280L440,280L440,520ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880Z" />
|
android:pathData="M480,680Q497,680 508.5,668.5Q520,657 520,640Q520,623 508.5,611.5Q497,600 480,600Q463,600 451.5,611.5Q440,623 440,640Q440,657 451.5,668.5Q463,680 480,680ZM440,520L520,520L520,280L440,280L440,520ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q614,800 707,707Q800,614 800,480Q800,346 707,253Q614,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -5,14 +5,13 @@
|
|||||||
~ SPDX-License-Identifier: GPL-3.0-or-later
|
~ SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:autoMirrored="true"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
|
android:autoMirrored="true"
|
||||||
android:tint="#969696"
|
android:tint="#969696"
|
||||||
android:viewportHeight="24"
|
android:viewportWidth="960"
|
||||||
android:viewportWidth="24"
|
android:viewportHeight="960">
|
||||||
android:width="24dp">
|
<path
|
||||||
|
android:fillColor="#969696"
|
||||||
<path android:fillColor="#969696"
|
android:pathData="M240,880Q207,880 183.5,856.5Q160,833 160,800L160,160Q160,127 183.5,103.5Q207,80 240,80L560,80L800,320L800,800Q800,833 776.5,856.5Q753,880 720,880L240,880ZM520,360L720,360L520,160L520,360Z"/>
|
||||||
android:pathData="M6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6L6,2zM13,9L13,3.5L18.5,9L13,9z"/>
|
|
||||||
|
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -4,15 +4,13 @@
|
|||||||
~ SPDX-FileCopyrightText: 2025 Google LLC
|
~ SPDX-FileCopyrightText: 2025 Google LLC
|
||||||
~ SPDX-License-Identifier: GPL-3.0-or-later
|
~ SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="#969696"
|
android:tint="#969696"
|
||||||
android:viewportHeight="24"
|
android:viewportWidth="960"
|
||||||
android:viewportWidth="24"
|
android:viewportHeight="960">
|
||||||
android:width="24dp">
|
<path
|
||||||
|
android:fillColor="#969696"
|
||||||
<path android:fillColor="#969696"
|
android:pathData="M480,480Q513,480 536.5,456.5Q560,433 560,400Q560,367 536.5,343.5Q513,320 480,320Q447,320 423.5,343.5Q400,367 400,400Q400,433 423.5,456.5Q447,480 480,480ZM480,880Q319,743 239.5,625.5Q160,508 160,408Q160,258 256.5,169Q353,80 480,80Q607,80 703.5,169Q800,258 800,408Q800,508 720.5,625.5Q641,743 480,880Z" />
|
||||||
android:pathData="M12,2L12,2C8.13,2 5,5.13 5,9c0,1.74 0.5,3.37 1.41,4.84c0.95,1.54 2.2,2.86 3.16,4.4c0.47,0.75 0.81,1.45 1.17,2.26C11,21.05 11.21,22 12,22h0c0.79,0 1,-0.95 1.25,-1.5c0.37,-0.81 0.7,-1.51 1.17,-2.26c0.96,-1.53 2.21,-2.85 3.16,-4.4C18.5,12.37 19,10.74 19,9C19,5.13 15.87,2 12,2zM12,11.75c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5S13.38,11.75 12,11.75z"/>
|
|
||||||
|
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2024 Google LLC
|
~ SPDX-FileCopyrightText: 2025 Google LLC
|
||||||
~ SPDX-License-Identifier: GPL-3.0-or-later
|
~ SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
@ -5,13 +5,12 @@
|
|||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="#969696"
|
android:tint="#969696"
|
||||||
android:viewportHeight="24"
|
android:viewportWidth="960"
|
||||||
android:viewportWidth="24"
|
android:viewportHeight="960">
|
||||||
android:width="24dp">
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
<path android:fillColor="#969696"
|
android:pathData="M480,560Q430,560 395,525Q360,490 360,440L360,200Q360,150 395,115Q430,80 480,80Q530,80 565,115Q600,150 600,200L600,440Q600,490 565,525Q530,560 480,560ZM480,320Q480,320 480,320Q480,320 480,320L480,320Q480,320 480,320Q480,320 480,320Q480,320 480,320Q480,320 480,320L480,320Q480,320 480,320Q480,320 480,320ZM440,840L440,717Q336,703 268,624Q200,545 200,440L280,440Q280,523 338.5,581.5Q397,640 480,640Q563,640 621.5,581.5Q680,523 680,440L760,440Q760,545 692,624Q624,703 520,717L520,840L440,840ZM480,480Q497,480 508.5,468.5Q520,457 520,440L520,200Q520,183 508.5,171.5Q497,160 480,160Q463,160 451.5,171.5Q440,183 440,200L440,440Q440,457 451.5,468.5Q463,480 480,480Z" />
|
||||||
android:pathData="M12,14c1.66,0 2.99,-1.34 2.99,-3L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6c0,1.66 1.34,3 3,3zM17.3,11c0,3 -2.54,5.1 -5.3,5.1S6.7,14 6.7,11L5,11c0,3.41 2.72,6.23 6,6.72L11,21h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z"/>
|
|
||||||
|
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2021-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2021-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
@ -12,5 +12,5 @@
|
|||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FF000000"
|
android:fillColor="#FF000000"
|
||||||
android:pathData="M160,760L160,680L240,680L240,400Q240,317 290,252.5Q340,188 420,168L420,140Q420,115 437.5,97.5Q455,80 480,80Q505,80 522.5,97.5Q540,115 540,140L540,168Q620,188 670,252.5Q720,317 720,400L720,680L800,680L800,760L160,760ZM480,880Q447,880 423.5,856.5Q400,833 400,800L560,800Q560,833 536.5,856.5Q513,880 480,880Z" />
|
android:pathData="M160,760L160,680L240,680L240,400Q240,317 290,252.5Q340,188 420,168L420,140Q420,115 437.5,97.5Q455,80 480,80Q505,80 522.5,97.5Q540,115 540,140L540,168Q620,188 670,252.5Q720,317 720,400L720,680L800,680L800,760L160,760ZM480,460L480,460L480,460L480,460Q480,460 480,460Q480,460 480,460Q480,460 480,460Q480,460 480,460ZM480,880Q447,880 423.5,856.5Q400,833 400,800L560,800Q560,833 536.5,856.5Q513,880 480,880ZM320,680L640,680L640,400Q640,334 593,287Q546,240 480,240Q414,240 367,287Q320,334 320,400L320,680Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -8,8 +8,9 @@
|
|||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="#000000"
|
android:tint="#000000"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="960">
|
||||||
<path android:fillColor="@android:color/white"
|
<path
|
||||||
android:pathData="M22,16L22,4c0,-1.1 -0.9,-2 -2,-2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zM11,12l2.03,2.71L16,11l4,5L8,16l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6L2,6z"/>
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M360,560L760,560L622,380L530,500L468,420L360,560ZM320,720Q287,720 263.5,696.5Q240,673 240,640L240,160Q240,127 263.5,103.5Q287,80 320,80L800,80Q833,80 856.5,103.5Q880,127 880,160L880,640Q880,673 856.5,696.5Q833,720 800,720L320,720ZM320,640L800,640Q800,640 800,640Q800,640 800,640L800,160Q800,160 800,160Q800,160 800,160L320,160Q320,160 320,160Q320,160 320,160L320,640Q320,640 320,640Q320,640 320,640ZM160,880Q127,880 103.5,856.5Q80,833 80,800L80,240L160,240L160,800Q160,800 160,800Q160,800 160,800L720,800L720,880L160,880ZM320,160L320,160Q320,160 320,160Q320,160 320,160L320,640Q320,640 320,640Q320,640 320,640L320,640Q320,640 320,640Q320,640 320,640L320,160Q320,160 320,160Q320,160 320,160Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2021-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2021-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
@ -12,5 +12,5 @@
|
|||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M40,840L480,80L920,840L40,840ZM480,720Q497,720 508.5,708.5Q520,697 520,680Q520,663 508.5,651.5Q497,640 480,640Q463,640 451.5,651.5Q440,663 440,680Q440,697 451.5,708.5Q463,720 480,720ZM440,600L520,600L520,400L440,400L440,600Z" />
|
android:pathData="M40,840L480,80L920,840L40,840ZM178,760L782,760L480,240L178,760ZM480,720Q497,720 508.5,708.5Q520,697 520,680Q520,663 508.5,651.5Q497,640 480,640Q463,640 451.5,651.5Q440,663 440,680Q440,697 451.5,708.5Q463,720 480,720ZM440,600L520,600L520,400L440,400L440,600ZM480,500L480,500L480,500Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2023-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2023-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
@ -11,6 +11,6 @@
|
|||||||
android:viewportWidth="960"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FF000000"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M720,560L720,440L600,440L600,360L720,360L720,240L800,240L800,360L920,360L920,440L800,440L800,560L720,560ZM360,480Q294,480 247,433Q200,386 200,320Q200,254 247,207Q294,160 360,160Q426,160 473,207Q520,254 520,320Q520,386 473,433Q426,480 360,480ZM40,800L40,688Q40,654 57.5,625.5Q75,597 104,582Q166,551 230,535.5Q294,520 360,520Q426,520 490,535.5Q554,551 616,582Q645,597 662.5,625.5Q680,654 680,688L680,800L40,800Z" />
|
android:pathData="M720,560L720,440L600,440L600,360L720,360L720,240L800,240L800,360L920,360L920,440L800,440L800,560L720,560ZM360,480Q294,480 247,433Q200,386 200,320Q200,254 247,207Q294,160 360,160Q426,160 473,207Q520,254 520,320Q520,386 473,433Q426,480 360,480ZM40,800L40,688Q40,654 57.5,625.5Q75,597 104,582Q166,551 230,535.5Q294,520 360,520Q426,520 490,535.5Q554,551 616,582Q645,597 662.5,625.5Q680,654 680,688L680,800L40,800ZM120,720L600,720L600,688Q600,677 594.5,668Q589,659 580,654Q526,627 471,613.5Q416,600 360,600Q304,600 249,613.5Q194,627 140,654Q131,659 125.5,668Q120,677 120,688L120,720ZM360,400Q393,400 416.5,376.5Q440,353 440,320Q440,287 416.5,263.5Q393,240 360,240Q327,240 303.5,263.5Q280,287 280,320Q280,353 303.5,376.5Q327,400 360,400ZM360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320ZM360,720L360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720L360,720Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
|
~ SPDX-FileCopyrightText: 2018-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: GPL-3.0-or-later
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
@ -12,5 +12,5 @@
|
|||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M40,800L40,688Q40,654 57.5,625.5Q75,597 104,582Q166,551 230,535.5Q294,520 360,520Q426,520 490,535.5Q554,551 616,582Q645,597 662.5,625.5Q680,654 680,688L680,800L40,800ZM760,800L760,680Q760,636 735.5,595.5Q711,555 666,526Q717,532 762,546.5Q807,561 846,582Q882,602 901,626.5Q920,651 920,680L920,800L760,800ZM360,480Q294,480 247,433Q200,386 200,320Q200,254 247,207Q294,160 360,160Q426,160 473,207Q520,254 520,320Q520,386 473,433Q426,480 360,480ZM760,320Q760,386 713,433Q666,480 600,480Q589,480 572,477.5Q555,475 544,472Q571,440 585.5,401Q600,362 600,320Q600,278 585.5,239Q571,200 544,168Q558,163 572,161.5Q586,160 600,160Q666,160 713,207Q760,254 760,320Z" />
|
android:pathData="M40,800L40,688Q40,654 57.5,625.5Q75,597 104,582Q166,551 230,535.5Q294,520 360,520Q426,520 490,535.5Q554,551 616,582Q645,597 662.5,625.5Q680,654 680,688L680,800L40,800ZM760,800L760,680Q760,636 735.5,595.5Q711,555 666,526Q717,532 762,546.5Q807,561 846,582Q882,602 901,626.5Q920,651 920,680L920,800L760,800ZM360,480Q294,480 247,433Q200,386 200,320Q200,254 247,207Q294,160 360,160Q426,160 473,207Q520,254 520,320Q520,386 473,433Q426,480 360,480ZM760,320Q760,386 713,433Q666,480 600,480Q589,480 572,477.5Q555,475 544,472Q571,440 585.5,401Q600,362 600,320Q600,278 585.5,239Q571,200 544,168Q558,163 572,161.5Q586,160 600,160Q666,160 713,207Q760,254 760,320ZM120,720L600,720L600,688Q600,677 594.5,668Q589,659 580,654Q526,627 471,613.5Q416,600 360,600Q304,600 249,613.5Q194,627 140,654Q131,659 125.5,668Q120,677 120,688L120,720ZM360,400Q393,400 416.5,376.5Q440,353 440,320Q440,287 416.5,263.5Q393,240 360,240Q327,240 303.5,263.5Q280,287 280,320Q280,353 303.5,376.5Q327,400 360,400ZM360,720L360,720L360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720Q360,720 360,720ZM360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Q360,320 360,320Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2018-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2018-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#ffffff"
|
android:fillColor="@android:color/white"
|
||||||
android:fillType="nonZero"
|
android:pathData="M160,800Q127,800 103.5,776.5Q80,753 80,720L80,240Q80,207 103.5,183.5Q127,160 160,160L800,160Q833,160 856.5,183.5Q880,207 880,240L880,720Q880,753 856.5,776.5Q833,800 800,800L160,800ZM480,520L160,320L160,720Q160,720 160,720Q160,720 160,720L800,720Q800,720 800,720Q800,720 800,720L800,320L480,520ZM480,440L800,240L160,240L480,440ZM160,320L160,240L160,240L160,320L160,720Q160,720 160,720Q160,720 160,720L160,720Q160,720 160,720Q160,720 160,720L160,320Z" />
|
||||||
android:pathData="M7.2,15.8C6.87,15.8 6.587,15.682 6.353,15.448C6.118,15.213 6,14.93 6,14.6L6,7.4C6,7.07 6.118,6.787 6.353,6.552C6.587,6.318 6.87,6.2 7.2,6.2L16.8,6.2C17.13,6.2 17.413,6.318 17.648,6.552C17.882,6.787 18,7.07 18,7.4L18,14.6C18,14.93 17.882,15.213 17.648,15.448C17.413,15.682 17.13,15.8 16.8,15.8L7.2,15.8ZM12,11.6L16.8,8.6L16.8,7.4L12,10.4L7.2,7.4L7.2,8.6L12,11.6Z" />
|
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2023-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2023-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
@ -11,5 +11,5 @@
|
|||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M84,83L876,875L819,932L775,888Q755,903 731,911.5Q707,920 680,920L402,920Q372,920 346,906.5Q320,893 303,868L48,495L72,472Q91,453 117,450Q143,447 164,462L280,543L280,393L27,140L84,83ZM840,726L600,487L600,487L600,120Q600,103 611.5,91.5Q623,80 640,80Q657,80 668.5,91.5Q680,103 680,120L680,487L760,487L760,200Q760,183 771.5,171.5Q783,160 800,160Q817,160 828.5,171.5Q840,183 840,200L840,726ZM520,406L440,326L440,80Q440,63 451.5,51.5Q463,40 480,40Q497,40 508.5,51.5Q520,63 520,80L520,406ZM360,246L280,166L280,160Q280,143 291.5,131.5Q303,120 320,120Q337,120 348.5,131.5Q360,143 360,160L360,246Z" />
|
android:pathData="M840,726L760,646L760,200Q760,183 771.5,171.5Q783,160 800,160Q817,160 828.5,171.5Q840,183 840,200L840,726ZM360,246L280,166L280,160Q280,143 291.5,131.5Q303,120 320,120Q337,120 348.5,131.5Q360,143 360,160L360,246ZM520,406L440,326L440,80Q440,63 451.5,51.5Q463,40 480,40Q497,40 508.5,51.5Q520,63 520,80L520,406ZM680,487L600,487L600,487L600,120Q600,103 611.5,91.5Q623,80 640,80Q657,80 668.5,91.5Q680,103 680,120L680,487ZM717,830L360,473L360,697L212,593L369,822Q374,830 383,835Q392,840 402,840L680,840Q690,840 699.5,837.5Q709,835 717,830ZM402,920Q372,920 346,906.5Q320,893 303,868L48,495L72,472Q91,453 117,450Q143,447 164,462L280,543L280,393L27,140L84,83L876,875L819,932L775,888Q755,903 731,911.5Q707,920 680,920L402,920ZM539,652Q539,652 539,652Q539,652 539,652L539,652Q539,652 539,652Q539,652 539,652L539,652L539,652L539,652ZM600,487L600,487L600,487Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2021-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2021-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="#757575"
|
android:tint="#757575"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M3.27,3L2,4.27l5,5V13h3v9l3.58,-6.14L17.73,20 19,18.73 3.27,3zM17,10h-4l4,-8H7v2.18l8.46,8.46L17,10z" />
|
android:pathData="M280,80L680,80L600,360L760,360L643,529L586,472L608,440L554,440L507,393L574,160L360,160L360,246L280,166L280,80ZM400,880L400,560L280,560L280,394L55,169L112,112L848,848L791,905L550,664L400,880ZM473,359L473,359L473,359L473,359L473,359L473,359L473,359Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2021-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2021-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="#757575"
|
android:tint="#757575"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M7,2v11h3v9l7,-12h-4l4,-8z" />
|
android:pathData="M480,624L608,440L494,440L574,160L360,160L360,480L480,480L480,624ZM400,880L400,560L280,560L280,80L680,80L600,360L760,360L400,880ZM480,480L480,480L360,480L360,480L480,480L480,480L480,480Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2018-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2018-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
@ -12,5 +12,5 @@
|
|||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M480,920L480,840L760,840Q760,840 760,840Q760,840 760,840L760,800L600,800L600,480L760,480L760,440Q760,324 678,242Q596,160 480,160Q364,160 282,242Q200,324 200,440L200,480L360,480L360,800L200,800Q167,800 143.5,776.5Q120,753 120,720L120,440Q120,366 148.5,300.5Q177,235 226,186Q275,137 340.5,108.5Q406,80 480,80Q554,80 619.5,108.5Q685,137 734,186Q783,235 811.5,300.5Q840,366 840,440L840,840Q840,873 816.5,896.5Q793,920 760,920L480,920Z" />
|
android:pathData="M480,920L480,840L760,840Q760,840 760,840Q760,840 760,840L760,800L600,800L600,480L760,480L760,440Q760,324 678,242Q596,160 480,160Q364,160 282,242Q200,324 200,440L200,480L360,480L360,800L200,800Q167,800 143.5,776.5Q120,753 120,720L120,440Q120,366 148.5,300.5Q177,235 226,186Q275,137 340.5,108.5Q406,80 480,80Q554,80 619.5,108.5Q685,137 734,186Q783,235 811.5,300.5Q840,366 840,440L840,840Q840,873 816.5,896.5Q793,920 760,920L480,920ZM200,720L280,720L280,560L200,560L200,720Q200,720 200,720Q200,720 200,720ZM680,720L760,720L760,560L680,560L680,720ZM200,560Q200,560 200,560Q200,560 200,560L200,560L280,560L280,560L200,560ZM680,560L680,560L760,560L760,560L680,560Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2021-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2021-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
@ -12,5 +12,5 @@
|
|||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M160,760Q127,760 103.5,736.5Q80,713 80,680L80,280Q80,247 103.5,223.5Q127,200 160,200L800,200Q833,200 856.5,223.5Q880,247 880,280L880,680Q880,713 856.5,736.5Q833,760 800,760L160,760ZM320,640L640,640L640,560L320,560L320,640ZM200,520L280,520L280,440L200,440L200,520ZM320,520L400,520L400,440L320,440L320,520ZM440,520L520,520L520,440L440,440L440,520ZM560,520L640,520L640,440L560,440L560,520ZM680,520L760,520L760,440L680,440L680,520ZM200,400L280,400L280,320L200,320L200,400ZM320,400L400,400L400,320L320,320L320,400ZM440,400L520,400L520,320L440,320L440,400ZM560,400L640,400L640,320L560,320L560,400ZM680,400L760,400L760,320L680,320L680,400Z" />
|
android:pathData="M160,760Q127,760 103.5,736.5Q80,713 80,680L80,280Q80,247 103.5,223.5Q127,200 160,200L800,200Q833,200 856.5,223.5Q880,247 880,280L880,680Q880,713 856.5,736.5Q833,760 800,760L160,760ZM160,680L800,680Q800,680 800,680Q800,680 800,680L800,280Q800,280 800,280Q800,280 800,280L160,280Q160,280 160,280Q160,280 160,280L160,680Q160,680 160,680Q160,680 160,680ZM320,640L640,640L640,560L320,560L320,640ZM200,520L280,520L280,440L200,440L200,520ZM320,520L400,520L400,440L320,440L320,520ZM440,520L520,520L520,440L440,440L440,520ZM560,520L640,520L640,440L560,440L560,520ZM680,520L760,520L760,440L680,440L680,520ZM200,400L280,400L280,320L200,320L200,400ZM320,400L400,400L400,320L320,320L320,400ZM440,400L520,400L520,320L440,320L440,400ZM560,400L640,400L640,320L560,320L560,400ZM680,400L760,400L760,320L680,320L680,400ZM160,680Q160,680 160,680Q160,680 160,680L160,280Q160,280 160,280Q160,280 160,280L160,280Q160,280 160,280Q160,280 160,280L160,680Q160,680 160,680Q160,680 160,680Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2021-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2021-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
@ -11,6 +11,6 @@
|
|||||||
android:viewportWidth="960"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#757575"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M480,480Q513,480 536.5,456.5Q560,433 560,400Q560,367 536.5,343.5Q513,320 480,320Q447,320 423.5,343.5Q400,367 400,400Q400,433 423.5,456.5Q447,480 480,480ZM480,880Q319,743 239.5,625.5Q160,508 160,408Q160,258 256.5,169Q353,80 480,80Q607,80 703.5,169Q800,258 800,408Q800,508 720.5,625.5Q641,743 480,880Z" />
|
android:pathData="M480,480Q513,480 536.5,456.5Q560,433 560,400Q560,367 536.5,343.5Q513,320 480,320Q447,320 423.5,343.5Q400,367 400,400Q400,433 423.5,456.5Q447,480 480,480ZM480,774Q602,662 661,570.5Q720,479 720,408Q720,299 650.5,229.5Q581,160 480,160Q379,160 309.5,229.5Q240,299 240,408Q240,479 299,570.5Q358,662 480,774ZM480,880Q319,743 239.5,625.5Q160,508 160,408Q160,258 256.5,169Q353,80 480,80Q607,80 703.5,169Q800,258 800,408Q800,508 720.5,625.5Q641,743 480,880ZM480,400Q480,400 480,400Q480,400 480,400Q480,400 480,400Q480,400 480,400Q480,400 480,400Q480,400 480,400Q480,400 480,400Q480,400 480,400Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2021-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2021-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="?attr/colorControlNormal"
|
android:tint="?attr/colorControlNormal"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/fontAppbar"
|
android:fillColor="@color/fontAppbar"
|
||||||
android:pathData="M12,14c1.66,0 2.99,-1.34 2.99,-3L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6c0,1.66 1.34,3 3,3zM17.3,11c0,3 -2.54,5.1 -5.3,5.1S6.7,14 6.7,11L5,11c0,3.41 2.72,6.23 6,6.72L11,21h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z" />
|
android:pathData="M480,560Q430,560 395,525Q360,490 360,440L360,200Q360,150 395,115Q430,80 480,80Q530,80 565,115Q600,150 600,200L600,440Q600,490 565,525Q530,560 480,560ZM480,320Q480,320 480,320Q480,320 480,320L480,320Q480,320 480,320Q480,320 480,320Q480,320 480,320Q480,320 480,320L480,320Q480,320 480,320Q480,320 480,320ZM440,840L440,717Q336,703 268,624Q200,545 200,440L280,440Q280,523 338.5,581.5Q397,640 480,640Q563,640 621.5,581.5Q680,523 680,440L760,440Q760,545 692,624Q624,703 520,717L520,840L440,840ZM480,480Q497,480 508.5,468.5Q520,457 520,440L520,200Q520,183 508.5,171.5Q497,160 480,160Q463,160 451.5,171.5Q440,183 440,200L440,440Q440,457 451.5,468.5Q463,480 480,480Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2021-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2021-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="@color/nc_darkRed"
|
android:tint="@color/nc_darkRed"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/fontAppbar"
|
android:fillColor="@color/fontAppbar"
|
||||||
android:pathData="M12,14c1.66,0 2.99,-1.34 2.99,-3L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6c0,1.66 1.34,3 3,3zM17.3,11c0,3 -2.54,5.1 -5.3,5.1S6.7,14 6.7,11L5,11c0,3.41 2.72,6.23 6,6.72L11,21h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z" />
|
android:pathData="M480,560Q430,560 395,525Q360,490 360,440L360,200Q360,150 395,115Q430,80 480,80Q530,80 565,115Q600,150 600,200L600,440Q600,490 565,525Q530,560 480,560ZM480,320Q480,320 480,320Q480,320 480,320L480,320Q480,320 480,320Q480,320 480,320Q480,320 480,320Q480,320 480,320L480,320Q480,320 480,320Q480,320 480,320ZM440,840L440,717Q336,703 268,624Q200,545 200,440L280,440Q280,523 338.5,581.5Q397,640 480,640Q563,640 621.5,581.5Q680,523 680,440L760,440Q760,545 692,624Q624,703 520,717L520,840L440,840ZM480,480Q497,480 508.5,468.5Q520,457 520,440L520,200Q520,183 508.5,171.5Q497,160 480,160Q463,160 451.5,171.5Q440,183 440,200L440,440Q440,457 451.5,468.5Q463,480 480,480Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2021-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2021-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
@ -12,5 +12,5 @@
|
|||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M160,760L160,680L240,680L240,400Q240,367 248.5,335Q257,303 274,274L400,400L288,400L56,168L112,112L848,848L792,904L646,760L160,760ZM720,606L328,214Q348,198 371,186Q394,174 420,168L420,140Q420,115 437.5,97.5Q455,80 480,80Q505,80 522.5,97.5Q540,115 540,140L540,168Q620,188 670,252.5Q720,317 720,400L720,606ZM480,880Q447,880 423.5,856.5Q400,833 400,800L560,800Q560,833 536.5,856.5Q513,880 480,880Z" />
|
android:pathData="M160,760L160,680L240,680L240,400Q240,367 248.5,335Q257,303 274,274L334,334Q327,350 323.5,366.5Q320,383 320,400L320,680L568,680L56,168L112,112L848,848L792,904L646,760L160,760ZM720,606L640,526L640,400Q640,334 593,287Q546,240 480,240Q454,240 430,248Q406,256 386,272L328,214Q348,198 371,186Q394,174 420,168L420,140Q420,115 437.5,97.5Q455,80 480,80Q505,80 522.5,97.5Q540,115 540,140L540,168Q620,188 670,252.5Q720,317 720,400L720,606ZM444,556L444,556L444,556L444,556ZM480,880Q447,880 423.5,856.5Q400,833 400,800L560,800Q560,833 536.5,856.5Q513,880 480,880ZM513,399Q513,399 513,399Q513,399 513,399L513,399L513,399Q513,399 513,399Q513,399 513,399Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Nextcloud Talk - Android Client
|
~ Nextcloud Talk - Android Client
|
||||||
~
|
~
|
||||||
~ SPDX-FileCopyrightText: 2021-2024 Google LLC
|
~ SPDX-FileCopyrightText: 2021-2025 Google LLC
|
||||||
~ SPDX-License-Identifier: Apache-2.0
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="?attr/colorControlNormal"
|
android:tint="?attr/colorControlNormal"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z" />
|
android:pathData="M480,480Q414,480 367,433Q320,386 320,320Q320,254 367,207Q414,160 480,160Q546,160 593,207Q640,254 640,320Q640,386 593,433Q546,480 480,480ZM160,800L160,688Q160,654 177.5,625.5Q195,597 224,582Q286,551 350,535.5Q414,520 480,520Q546,520 610,535.5Q674,551 736,582Q765,597 782.5,625.5Q800,654 800,688L800,800L160,800ZM240,720L720,720L720,688Q720,677 714.5,668Q709,659 700,654Q646,627 591,613.5Q536,600 480,600Q424,600 369,613.5Q314,627 260,654Q251,659 245.5,668Q240,677 240,688L240,720ZM480,400Q513,400 536.5,376.5Q560,353 560,320Q560,287 536.5,263.5Q513,240 480,240Q447,240 423.5,263.5Q400,287 400,320Q400,353 423.5,376.5Q447,400 480,400ZM480,320Q480,320 480,320Q480,320 480,320Q480,320 480,320Q480,320 480,320Q480,320 480,320Q480,320 480,320Q480,320 480,320Q480,320 480,320ZM480,720L480,720Q480,720 480,720Q480,720 480,720Q480,720 480,720Q480,720 480,720Q480,720 480,720Q480,720 480,720Q480,720 480,720Q480,720 480,720L480,720Z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user