From a8bbf29b426b66b4c5f9c21fbc192310f799f207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Fri, 15 Apr 2022 22:50:54 +0200 Subject: [PATCH 001/244] Remove unused dependencies --- build.gradle | 17 +++++++++++++++++ dependencies.gradle | 2 +- library/attachment-viewer/build.gradle | 6 ++++-- library/core-utils/build.gradle | 3 +-- library/multipicker/build.gradle | 2 +- library/ui-styles/build.gradle | 6 +----- matrix-sdk-android-flow/build.gradle | 5 ----- matrix-sdk-android/build.gradle | 10 +--------- vector/build.gradle | 3 --- 9 files changed, 26 insertions(+), 28 deletions(-) diff --git a/build.gradle b/build.gradle index 1ff1da7427..6cbc11351e 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,7 @@ buildscript { // ktlint Plugin plugins { id "org.jlleitschuh.gradle.ktlint" version "10.2.1" + id 'com.autonomousapps.dependency-analysis' version "1.0.0" } // https://github.com/jeremylong/DependencyCheck @@ -193,3 +194,19 @@ project(":library:diff-match-patch") { // } // } //} + +dependencyAnalysis { + dependencies { + bundle("kotlin-stdlib") { + includeGroup("org.jetbrains.kotlin") + } + bundle("react") { + includeGroup("com.facebook.react") + } + } + issues { + all { + ignoreKtx(true) // default is false + } + } +} diff --git a/dependencies.gradle b/dependencies.gradle index 7666a3bf9f..be1b888502 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -81,7 +81,7 @@ ext.libs = [ 'hiltCompiler' : "com.google.dagger:hilt-compiler:$dagger" ], squareup : [ - 'moshi' : "com.squareup.moshi:moshi-adapters:$moshi", + 'moshi' : "com.squareup.moshi:moshi:$moshi", 'moshiKotlin' : "com.squareup.moshi:moshi-kotlin-codegen:$moshi", 'retrofit' : "com.squareup.retrofit2:retrofit:$retrofit", 'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit" diff --git a/library/attachment-viewer/build.gradle b/library/attachment-viewer/build.gradle index 048710f62c..b51136a993 100644 --- a/library/attachment-viewer/build.gradle +++ b/library/attachment-viewer/build.gradle @@ -55,5 +55,7 @@ dependencies { implementation libs.androidx.appCompat implementation libs.androidx.recyclerview - implementation libs.google.material -} \ No newline at end of file + api("androidx.viewpager2:viewpager2:1.0.0") + implementation("androidx.core:core:1.7.0") + implementation("androidx.transition:transition:1.2.0") +} diff --git a/library/core-utils/build.gradle b/library/core-utils/build.gradle index ad3a948808..1cc518c432 100644 --- a/library/core-utils/build.gradle +++ b/library/core-utils/build.gradle @@ -50,6 +50,5 @@ android { } dependencies { - implementation libs.androidx.appCompat implementation libs.jetbrains.coroutinesAndroid -} \ No newline at end of file +} diff --git a/library/multipicker/build.gradle b/library/multipicker/build.gradle index bb98a2f852..861238c02b 100644 --- a/library/multipicker/build.gradle +++ b/library/multipicker/build.gradle @@ -39,8 +39,8 @@ android { dependencies { implementation libs.androidx.appCompat - implementation libs.androidx.fragmentKtx implementation libs.androidx.exifinterface + implementation libs.androidx.core // Log implementation libs.jakewharton.timber diff --git a/library/ui-styles/build.gradle b/library/ui-styles/build.gradle index 0ac513b252..debfdf8649 100644 --- a/library/ui-styles/build.gradle +++ b/library/ui-styles/build.gradle @@ -54,10 +54,6 @@ android { dependencies { implementation libs.androidx.appCompat implementation libs.google.material - // Pref theme - implementation libs.androidx.preferenceKtx - // PFLockScreen attrs - implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta12' // dialpad dimen implementation 'im.dlg:android-dialer:1.2.5' -} \ No newline at end of file +} diff --git a/matrix-sdk-android-flow/build.gradle b/matrix-sdk-android-flow/build.gradle index ea43ce20c8..fb69af2d82 100644 --- a/matrix-sdk-android-flow/build.gradle +++ b/matrix-sdk-android-flow/build.gradle @@ -31,9 +31,7 @@ android { } dependencies { - implementation project(":matrix-sdk-android") - implementation libs.androidx.appCompat implementation libs.jetbrains.coroutinesCore implementation libs.jetbrains.coroutinesAndroid @@ -41,7 +39,4 @@ dependencies { // Paging implementation libs.androidx.pagingRuntimeKtx - - // Logging - implementation libs.jakewharton.timber } diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 0cffa4148e..e9c8804bac 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -109,7 +109,6 @@ dependencies { implementation libs.jetbrains.coroutinesCore implementation libs.jetbrains.coroutinesAndroid - implementation libs.androidx.appCompat implementation libs.androidx.core // Lifecycle @@ -128,12 +127,11 @@ dependencies { implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.3")) implementation 'com.squareup.okhttp3:okhttp' implementation 'com.squareup.okhttp3:logging-interceptor' - implementation 'com.squareup.okhttp3:okhttp-urlconnection' implementation libs.squareup.moshi kapt libs.squareup.moshiKotlin - implementation libs.markwon.core + api "com.atlassian.commonmark:commonmark:0.13.0" // Image implementation libs.androidx.exifinterface @@ -149,10 +147,6 @@ dependencies { // Work implementation libs.androidx.work - // FP - implementation libs.arrow.core - implementation libs.arrow.instances - // olm lib is now hosted in MavenCentral implementation 'org.matrix.android:olm-sdk:3.2.10' @@ -174,8 +168,6 @@ dependencies { implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.46' testImplementation libs.tests.junit - testImplementation 'org.robolectric:robolectric:4.7.3' - //testImplementation 'org.robolectric:shadows-support-v4:3.0' // Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281 testImplementation libs.mockk.mockk testImplementation libs.tests.kluent diff --git a/vector/build.gradle b/vector/build.gradle index c7950da28e..237754d2d1 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -6,7 +6,6 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-parcelize' apply plugin: 'kotlin-kapt' apply plugin: 'com.likethesalad.stem' -apply plugin: 'dagger.hilt.android.plugin' kapt { correctErrorTypes = true @@ -373,7 +372,6 @@ dependencies { // FlowBinding implementation libs.github.flowBinding implementation libs.github.flowBindingAppcompat - implementation libs.github.flowBindingMaterial implementation libs.airbnb.epoxy implementation libs.airbnb.epoxyGlide @@ -448,7 +446,6 @@ dependencies { implementation 'com.github.jetradarmobile:android-snowfall:1.2.1' // DI implementation libs.dagger.hilt - kapt libs.dagger.hiltCompiler // Analytics implementation 'com.posthog.android:posthog:1.1.2' From b3cfc88773075b3ef64ca89ed3fa18708eff10b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Fri, 15 Apr 2022 23:36:42 +0200 Subject: [PATCH 002/244] Fix androidTest --- library/attachment-viewer/build.gradle | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/library/attachment-viewer/build.gradle b/library/attachment-viewer/build.gradle index b51136a993..b89d9c6cca 100644 --- a/library/attachment-viewer/build.gradle +++ b/library/attachment-viewer/build.gradle @@ -55,7 +55,5 @@ dependencies { implementation libs.androidx.appCompat implementation libs.androidx.recyclerview - api("androidx.viewpager2:viewpager2:1.0.0") - implementation("androidx.core:core:1.7.0") - implementation("androidx.transition:transition:1.2.0") + implementation libs.google.material } From cdd7db417409bac50ff24db741dcdc80c963219e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Sat, 16 Apr 2022 09:40:15 +0200 Subject: [PATCH 003/244] Fix unused resource references properly --- library/attachment-viewer/build.gradle | 3 ++- .../src/main/res/values/styles_pin_code.xml | 14 +------------- .../ui-styles/src/main/res/values/theme_dark.xml | 11 ----------- .../ui-styles/src/main/res/values/theme_light.xml | 11 ----------- 4 files changed, 3 insertions(+), 36 deletions(-) diff --git a/library/attachment-viewer/build.gradle b/library/attachment-viewer/build.gradle index b89d9c6cca..57e5f30887 100644 --- a/library/attachment-viewer/build.gradle +++ b/library/attachment-viewer/build.gradle @@ -55,5 +55,6 @@ dependencies { implementation libs.androidx.appCompat implementation libs.androidx.recyclerview - implementation libs.google.material + api "androidx.viewpager2:viewpager2:1.0.0" + implementation "androidx.transition:transition:1.2.0" } diff --git a/library/ui-styles/src/main/res/values/styles_pin_code.xml b/library/ui-styles/src/main/res/values/styles_pin_code.xml index 2b6c113359..edec029faf 100644 --- a/library/ui-styles/src/main/res/values/styles_pin_code.xml +++ b/library/ui-styles/src/main/res/values/styles_pin_code.xml @@ -21,18 +21,6 @@ 24dp - - - - @@ -41,4 +29,4 @@ ?vctr_content_primary - \ No newline at end of file + diff --git a/library/ui-styles/src/main/res/values/theme_dark.xml b/library/ui-styles/src/main/res/values/theme_dark.xml index 7177687fdd..185e5b919c 100644 --- a/library/ui-styles/src/main/res/values/theme_dark.xml +++ b/library/ui-styles/src/main/res/values/theme_dark.xml @@ -106,17 +106,6 @@ never - @style/PreferenceThemeOverlay.v14.Material - - @style/PinCodeScreenStyle - @style/PinCodeKeyButtonStyle - @style/PinCodeTitleStyle - @style/PinCodeHintStyle - @style/PinCodeDotsViewStyle - @style/PinCodeDeleteButtonStyle - @style/PinCodeFingerprintButtonStyle - @style/PinCodeNextButtonStyle - @color/android_status_bar_background_dark @color/android_navigation_bar_background_dark diff --git a/library/ui-styles/src/main/res/values/theme_light.xml b/library/ui-styles/src/main/res/values/theme_light.xml index c90c021591..0eb11a139c 100644 --- a/library/ui-styles/src/main/res/values/theme_light.xml +++ b/library/ui-styles/src/main/res/values/theme_light.xml @@ -106,17 +106,6 @@ never - @style/PreferenceThemeOverlay.v14.Material - - @style/PinCodeScreenStyle - @style/PinCodeKeyButtonStyle - @style/PinCodeTitleStyle - @style/PinCodeHintStyle - @style/PinCodeDotsViewStyle - @style/PinCodeDeleteButtonStyle - @style/PinCodeFingerprintButtonStyle - @style/PinCodeNextButtonStyle - @color/android_status_bar_background_dark From 2138ec07992af8f153367daaaf937d8d7847fdf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Sat, 16 Apr 2022 11:14:04 +0200 Subject: [PATCH 004/244] Remove unused resource to make lint happy --- .../ui-styles/src/main/res/drawable/bg_pin_key.xml | 13 ------------- .../src/main/res/values/styles_pin_code.xml | 6 ------ 2 files changed, 19 deletions(-) delete mode 100644 library/ui-styles/src/main/res/drawable/bg_pin_key.xml diff --git a/library/ui-styles/src/main/res/drawable/bg_pin_key.xml b/library/ui-styles/src/main/res/drawable/bg_pin_key.xml deleted file mode 100644 index d4a54577be..0000000000 --- a/library/ui-styles/src/main/res/drawable/bg_pin_key.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/library/ui-styles/src/main/res/values/styles_pin_code.xml b/library/ui-styles/src/main/res/values/styles_pin_code.xml index edec029faf..c69819f7ba 100644 --- a/library/ui-styles/src/main/res/values/styles_pin_code.xml +++ b/library/ui-styles/src/main/res/values/styles_pin_code.xml @@ -5,12 +5,6 @@ ?android:colorBackground - - From 4305b21ba85a785c2947784a1ea46f88a69facf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Sat, 16 Apr 2022 20:36:43 +0200 Subject: [PATCH 005/244] Remove unused resource to make lint happy --- .../main/res/drawable/pin_code_dot_empty.xml | 13 ---------- .../main/res/drawable/pin_code_dot_fill.xml | 12 --------- .../src/main/res/drawable/pin_code_dots.xml | 9 ------- .../src/main/res/values/styles_pin_code.xml | 26 ------------------- 4 files changed, 60 deletions(-) delete mode 100644 library/ui-styles/src/main/res/drawable/pin_code_dot_empty.xml delete mode 100644 library/ui-styles/src/main/res/drawable/pin_code_dot_fill.xml delete mode 100644 library/ui-styles/src/main/res/drawable/pin_code_dots.xml delete mode 100644 library/ui-styles/src/main/res/values/styles_pin_code.xml diff --git a/library/ui-styles/src/main/res/drawable/pin_code_dot_empty.xml b/library/ui-styles/src/main/res/drawable/pin_code_dot_empty.xml deleted file mode 100644 index 1827a7682b..0000000000 --- a/library/ui-styles/src/main/res/drawable/pin_code_dot_empty.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/library/ui-styles/src/main/res/drawable/pin_code_dot_fill.xml b/library/ui-styles/src/main/res/drawable/pin_code_dot_fill.xml deleted file mode 100644 index 799ea30174..0000000000 --- a/library/ui-styles/src/main/res/drawable/pin_code_dot_fill.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/library/ui-styles/src/main/res/drawable/pin_code_dots.xml b/library/ui-styles/src/main/res/drawable/pin_code_dots.xml deleted file mode 100644 index 29e445e511..0000000000 --- a/library/ui-styles/src/main/res/drawable/pin_code_dots.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/library/ui-styles/src/main/res/values/styles_pin_code.xml b/library/ui-styles/src/main/res/values/styles_pin_code.xml deleted file mode 100644 index c69819f7ba..0000000000 --- a/library/ui-styles/src/main/res/values/styles_pin_code.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - From 2c84f234a600eedca62b37e9dd63f994da758401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Sun, 17 Apr 2022 11:09:10 +0200 Subject: [PATCH 006/244] Cleanup --- dependencies.gradle | 5 ++++- library/attachment-viewer/build.gradle | 4 ++-- library/multipicker/build.gradle | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index be1b888502..ec27184d5c 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -45,6 +45,7 @@ ext.libs = [ 'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines" ], androidx : [ + 'activity' : "androidx.activity:activity:1.2.4", 'appCompat' : "androidx.appcompat:appcompat:1.4.0", 'core' : "androidx.core:core-ktx:1.7.0", 'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1", @@ -69,7 +70,9 @@ ext.libs = [ 'testRules' : "androidx.test:rules:$androidxTest", 'espressoCore' : "androidx.test.espresso:espresso-core:$espresso", 'espressoContrib' : "androidx.test.espresso:espresso-contrib:$espresso", - 'espressoIntents' : "androidx.test.espresso:espresso-intents:$espresso" + 'espressoIntents' : "androidx.test.espresso:espresso-intents:$espresso", + 'viewpager2' : "androidx.viewpager2:viewpager2:1.0.0", + 'transition' : "androidx.transition:transition:1.2.0", ], google : [ 'material' : "com.google.android.material:material:1.5.0" diff --git a/library/attachment-viewer/build.gradle b/library/attachment-viewer/build.gradle index 57e5f30887..8bbafd3387 100644 --- a/library/attachment-viewer/build.gradle +++ b/library/attachment-viewer/build.gradle @@ -55,6 +55,6 @@ dependencies { implementation libs.androidx.appCompat implementation libs.androidx.recyclerview - api "androidx.viewpager2:viewpager2:1.0.0" - implementation "androidx.transition:transition:1.2.0" + api libs.androidx.viewpager2 + implementation libs.androidx.transition } diff --git a/library/multipicker/build.gradle b/library/multipicker/build.gradle index 861238c02b..2de99d5c20 100644 --- a/library/multipicker/build.gradle +++ b/library/multipicker/build.gradle @@ -38,7 +38,7 @@ android { } dependencies { - implementation libs.androidx.appCompat + api libs.androidx.activity implementation libs.androidx.exifinterface implementation libs.androidx.core From 2bbecd4cc5d3bf245575ce0816a4f4829ac4f9d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Sun, 17 Apr 2022 11:35:30 +0200 Subject: [PATCH 007/244] Fix regressions --- library/ui-styles/build.gradle | 4 ++ .../src/main/res/drawable/bg_pin_key.xml | 13 ++++++ .../main/res/drawable/pin_code_dot_empty.xml | 13 ++++++ .../main/res/drawable/pin_code_dot_fill.xml | 12 +++++ .../src/main/res/drawable/pin_code_dots.xml | 9 ++++ .../src/main/res/values/styles_pin_code.xml | 44 +++++++++++++++++++ .../src/main/res/values/theme_dark.xml | 11 +++++ .../src/main/res/values/theme_light.xml | 11 +++++ vector/build.gradle | 2 + 9 files changed, 119 insertions(+) create mode 100644 library/ui-styles/src/main/res/drawable/bg_pin_key.xml create mode 100644 library/ui-styles/src/main/res/drawable/pin_code_dot_empty.xml create mode 100644 library/ui-styles/src/main/res/drawable/pin_code_dot_fill.xml create mode 100644 library/ui-styles/src/main/res/drawable/pin_code_dots.xml create mode 100644 library/ui-styles/src/main/res/values/styles_pin_code.xml diff --git a/library/ui-styles/build.gradle b/library/ui-styles/build.gradle index debfdf8649..31cfdd24c7 100644 --- a/library/ui-styles/build.gradle +++ b/library/ui-styles/build.gradle @@ -54,6 +54,10 @@ android { dependencies { implementation libs.androidx.appCompat implementation libs.google.material + // Pref theme + implementation libs.androidx.preferenceKtx + // PFLockScreen attrs + implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta12' // dialpad dimen implementation 'im.dlg:android-dialer:1.2.5' } diff --git a/library/ui-styles/src/main/res/drawable/bg_pin_key.xml b/library/ui-styles/src/main/res/drawable/bg_pin_key.xml new file mode 100644 index 0000000000..5bf293aab0 --- /dev/null +++ b/library/ui-styles/src/main/res/drawable/bg_pin_key.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/library/ui-styles/src/main/res/drawable/pin_code_dot_empty.xml b/library/ui-styles/src/main/res/drawable/pin_code_dot_empty.xml new file mode 100644 index 0000000000..879cac15ca --- /dev/null +++ b/library/ui-styles/src/main/res/drawable/pin_code_dot_empty.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/library/ui-styles/src/main/res/drawable/pin_code_dot_fill.xml b/library/ui-styles/src/main/res/drawable/pin_code_dot_fill.xml new file mode 100644 index 0000000000..83bdac5126 --- /dev/null +++ b/library/ui-styles/src/main/res/drawable/pin_code_dot_fill.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/library/ui-styles/src/main/res/drawable/pin_code_dots.xml b/library/ui-styles/src/main/res/drawable/pin_code_dots.xml new file mode 100644 index 0000000000..c4b1073f85 --- /dev/null +++ b/library/ui-styles/src/main/res/drawable/pin_code_dots.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/library/ui-styles/src/main/res/values/styles_pin_code.xml b/library/ui-styles/src/main/res/values/styles_pin_code.xml new file mode 100644 index 0000000000..cb22863694 --- /dev/null +++ b/library/ui-styles/src/main/res/values/styles_pin_code.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/library/ui-styles/src/main/res/values/theme_dark.xml b/library/ui-styles/src/main/res/values/theme_dark.xml index 185e5b919c..7177687fdd 100644 --- a/library/ui-styles/src/main/res/values/theme_dark.xml +++ b/library/ui-styles/src/main/res/values/theme_dark.xml @@ -106,6 +106,17 @@ never + @style/PreferenceThemeOverlay.v14.Material + + @style/PinCodeScreenStyle + @style/PinCodeKeyButtonStyle + @style/PinCodeTitleStyle + @style/PinCodeHintStyle + @style/PinCodeDotsViewStyle + @style/PinCodeDeleteButtonStyle + @style/PinCodeFingerprintButtonStyle + @style/PinCodeNextButtonStyle + @color/android_status_bar_background_dark @color/android_navigation_bar_background_dark diff --git a/library/ui-styles/src/main/res/values/theme_light.xml b/library/ui-styles/src/main/res/values/theme_light.xml index 0eb11a139c..c90c021591 100644 --- a/library/ui-styles/src/main/res/values/theme_light.xml +++ b/library/ui-styles/src/main/res/values/theme_light.xml @@ -106,6 +106,17 @@ never + @style/PreferenceThemeOverlay.v14.Material + + @style/PinCodeScreenStyle + @style/PinCodeKeyButtonStyle + @style/PinCodeTitleStyle + @style/PinCodeHintStyle + @style/PinCodeDotsViewStyle + @style/PinCodeDeleteButtonStyle + @style/PinCodeFingerprintButtonStyle + @style/PinCodeNextButtonStyle + @color/android_status_bar_background_dark diff --git a/vector/build.gradle b/vector/build.gradle index 237754d2d1..6d318f82b9 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -6,6 +6,7 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-parcelize' apply plugin: 'kotlin-kapt' apply plugin: 'com.likethesalad.stem' +apply plugin: 'dagger.hilt.android.plugin' kapt { correctErrorTypes = true @@ -446,6 +447,7 @@ dependencies { implementation 'com.github.jetradarmobile:android-snowfall:1.2.1' // DI implementation libs.dagger.hilt + kapt libs.dagger.hiltCompiler // Analytics implementation 'com.posthog.android:posthog:1.1.2' From 0250f61d10d4a0cb0963d35556d9ae322788d29c Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Tue, 26 Apr 2022 15:48:34 +0200 Subject: [PATCH 008/244] Replaces izPublic with isPublic --- .../home/room/list/RoomSummaryItem.kt | 68 ++++++++++++++----- .../home/room/list/RoomSummaryItemFactory.kt | 2 +- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt index 70c5846646..e5a4e374c9 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt @@ -45,24 +45,56 @@ import org.matrix.android.sdk.api.util.MatrixItem @EpoxyModelClass(layout = R.layout.item_room) abstract class RoomSummaryItem : VectorEpoxyModel() { - @EpoxyAttribute lateinit var typingMessage: String - @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer - @EpoxyAttribute lateinit var matrixItem: MatrixItem + @EpoxyAttribute + lateinit var typingMessage: String - @EpoxyAttribute lateinit var lastFormattedEvent: EpoxyCharSequence - @EpoxyAttribute lateinit var lastEventTime: String - @EpoxyAttribute var encryptionTrustLevel: RoomEncryptionTrustLevel? = null - @EpoxyAttribute var userPresence: UserPresence? = null - @EpoxyAttribute var showPresence: Boolean = false - @EpoxyAttribute var izPublic: Boolean = false - @EpoxyAttribute var unreadNotificationCount: Int = 0 - @EpoxyAttribute var hasUnreadMessage: Boolean = false - @EpoxyAttribute var hasDraft: Boolean = false - @EpoxyAttribute var showHighlighted: Boolean = false - @EpoxyAttribute var hasFailedSending: Boolean = false - @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var itemLongClickListener: View.OnLongClickListener? = null - @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var itemClickListener: ClickListener? = null - @EpoxyAttribute var showSelected: Boolean = false + @EpoxyAttribute + lateinit var avatarRenderer: AvatarRenderer + + @EpoxyAttribute + lateinit var matrixItem: MatrixItem + + @EpoxyAttribute + lateinit var lastFormattedEvent: EpoxyCharSequence + + @EpoxyAttribute + lateinit var lastEventTime: String + + @EpoxyAttribute + var encryptionTrustLevel: RoomEncryptionTrustLevel? = null + + @EpoxyAttribute + var userPresence: UserPresence? = null + + @EpoxyAttribute + var showPresence: Boolean = false + + @EpoxyAttribute @JvmField + var isPublic: Boolean = false + + @EpoxyAttribute + var unreadNotificationCount: Int = 0 + + @EpoxyAttribute + var hasUnreadMessage: Boolean = false + + @EpoxyAttribute + var hasDraft: Boolean = false + + @EpoxyAttribute + var showHighlighted: Boolean = false + + @EpoxyAttribute + var hasFailedSending: Boolean = false + + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) + var itemLongClickListener: View.OnLongClickListener? = null + + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) + var itemClickListener: ClickListener? = null + + @EpoxyAttribute + var showSelected: Boolean = false override fun bind(holder: Holder) { super.bind(holder) @@ -79,7 +111,7 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { holder.draftView.isVisible = hasDraft avatarRenderer.render(matrixItem, holder.avatarImageView) holder.roomAvatarDecorationImageView.render(encryptionTrustLevel) - holder.roomAvatarPublicDecorationImageView.isVisible = izPublic + holder.roomAvatarPublicDecorationImageView.isVisible = isPublic holder.roomAvatarFailSendingImageView.isVisible = hasFailedSending renderSelection(holder, showSelected) holder.typingView.setTextOrHide(typingMessage) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt index 6326d9c97a..cd3a8b0890 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt @@ -124,7 +124,7 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor .avatarRenderer(avatarRenderer) // We do not display shield in the room list anymore // .encryptionTrustLevel(roomSummary.roomEncryptionTrustLevel) - .izPublic(roomSummary.isPublic) + .isPublic(roomSummary.isPublic) .showPresence(roomSummary.isDirect) .userPresence(roomSummary.directUserPresence) .matrixItem(roomSummary.toMatrixItem()) From a3367d4075f54a06f0d7601d3432ad1fef081aea Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Tue, 26 Apr 2022 15:48:49 +0200 Subject: [PATCH 009/244] Replaces else cases in when branches to RoomListDisplayMode.FILTERED --- .../features/home/room/list/RoomListFragment.kt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt index aaa469f68d..ef7a1012df 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt @@ -204,7 +204,7 @@ class RoomListFragment @Inject constructor( RoomListDisplayMode.NOTIFICATIONS -> views.createChatFabMenu.isVisible = true RoomListDisplayMode.PEOPLE -> views.createChatRoomButton.isVisible = true RoomListDisplayMode.ROOMS -> views.createGroupRoomButton.isVisible = true - else -> Unit // No button in this mode + RoomListDisplayMode.FILTERED -> Unit // No button in this mode } views.createChatRoomButton.debouncedClicks { @@ -230,7 +230,7 @@ class RoomListFragment @Inject constructor( RoomListDisplayMode.NOTIFICATIONS -> views.createChatFabMenu.hide() RoomListDisplayMode.PEOPLE -> views.createChatRoomButton.hide() RoomListDisplayMode.ROOMS -> views.createGroupRoomButton.hide() - else -> Unit + RoomListDisplayMode.FILTERED -> Unit } } } @@ -309,7 +309,7 @@ class RoomListFragment @Inject constructor( ) } } - section.isExpanded.observe(viewLifecycleOwner) { _ -> + section.isExpanded.observe(viewLifecycleOwner) { refreshCollapseStates() } controller.listener = this @@ -330,7 +330,7 @@ class RoomListFragment @Inject constructor( checkEmptyState() } observeItemCount(section, sectionAdapter) - section.isExpanded.observe(viewLifecycleOwner) { _ -> + section.isExpanded.observe(viewLifecycleOwner) { refreshCollapseStates() } controller.listener = this @@ -359,7 +359,7 @@ class RoomListFragment @Inject constructor( ) } } - section.isExpanded.observe(viewLifecycleOwner) { _ -> + section.isExpanded.observe(viewLifecycleOwner) { refreshCollapseStates() } controller.listener = this @@ -395,7 +395,7 @@ class RoomListFragment @Inject constructor( RoomListDisplayMode.NOTIFICATIONS -> views.createChatFabMenu.show() RoomListDisplayMode.PEOPLE -> views.createChatRoomButton.show() RoomListDisplayMode.ROOMS -> views.createGroupRoomButton.show() - else -> Unit + RoomListDisplayMode.FILTERED -> Unit } } } @@ -474,7 +474,8 @@ class RoomListFragment @Inject constructor( StateView.State.Empty( title = getString(R.string.room_list_catchup_empty_title), image = ContextCompat.getDrawable(requireContext(), R.drawable.ic_noun_party_popper), - message = getString(R.string.room_list_catchup_empty_body)) + message = getString(R.string.room_list_catchup_empty_body) + ) } RoomListDisplayMode.PEOPLE -> StateView.State.Empty( @@ -490,7 +491,7 @@ class RoomListFragment @Inject constructor( isBigImage = true, message = getString(R.string.room_list_rooms_empty_body) ) - else -> + RoomListDisplayMode.FILTERED -> // Always display the content in this mode, because if the footer StateView.State.Content } From 9e53e6cc8f1ef6f0507d93c5961c342185d1a07e Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 28 Apr 2022 10:41:40 +0200 Subject: [PATCH 010/244] Adds space name to rooms in filtered search --- .../relationship/RoomChildRelationInfo.kt | 16 ++-------- .../room/summary/RoomSummaryUpdater.kt | 29 ++++++++----------- .../list/CollapsableTypedEpoxyController.kt | 2 +- .../home/room/list/RoomListFragment.kt | 2 +- .../home/room/list/RoomSummaryItem.kt | 17 ++++++++++- .../home/room/list/RoomSummaryItemFactory.kt | 7 ++++- .../room/list/RoomSummaryListController.kt | 3 +- .../room/list/RoomSummaryPagedController.kt | 6 ++-- .../list/RoomSummaryPagedControllerFactory.kt | 5 ++-- .../features/share/IncomingShareController.kt | 3 +- vector/src/main/res/layout/item_room.xml | 3 +- 11 files changed, 52 insertions(+), 41 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relationship/RoomChildRelationInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relationship/RoomChildRelationInfo.kt index 5bad334afc..fffca96acf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relationship/RoomChildRelationInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relationship/RoomChildRelationInfo.kt @@ -43,7 +43,6 @@ internal class RoomChildRelationInfo( data class SpaceChildInfo( val roomId: String, val order: String?, -// val autoJoin: Boolean, val viaServers: List ) @@ -60,18 +59,13 @@ internal class RoomChildRelationInfo( fun getDirectChildrenDescriptions(): List { return CurrentStateEventEntity.whereType(realm, roomId, EventType.STATE_SPACE_CHILD) .findAll() -// .also { -// Timber.v("## Space: Found ${it.count()} m.space.child state events for $roomId") -// } .mapNotNull { ContentMapper.map(it.root?.content).toModel()?.let { scc -> -// Timber.v("## Space child desc state event $scc") // Children where via is not present are ignored. scc.via?.let { via -> SpaceChildInfo( roomId = it.stateKey, order = scc.validOrder(), -// autoJoin = scc.autoJoin ?: false, viaServers = via ) } @@ -83,17 +77,13 @@ internal class RoomChildRelationInfo( fun getParentDescriptions(): List { return CurrentStateEventEntity.whereType(realm, roomId, EventType.STATE_SPACE_PARENT) .findAll() -// .also { -// Timber.v("## Space: Found ${it.count()} m.space.parent state events for $roomId") -// } .mapNotNull { - ContentMapper.map(it.root?.content).toModel()?.let { scc -> -// Timber.v("## Space parent desc state event $scc") + ContentMapper.map(it.root?.content).toModel()?.let { spaceParentContent -> // Parent where via is not present are ignored. - scc.via?.let { via -> + spaceParentContent.via?.let { via -> SpaceParentInfo( roomId = it.stateKey, - canonical = scc.canonical ?: false, + canonical = spaceParentContent.canonical ?: false, viaServers = via, stateEventSender = it.root?.sender ?: "" ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt index 3af579d050..70c1453865 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.session.room.summary import io.realm.Realm +import io.realm.RealmList import io.realm.kotlin.createObject import kotlinx.coroutines.runBlocking import org.matrix.android.sdk.api.extensions.orFalse @@ -349,39 +350,34 @@ internal class RoomSummaryUpdater @Inject constructor( } val acyclicGraph = graph.withoutEdges(backEdges) -// Timber.v("## SPACES: acyclicGraph $acyclicGraph") val flattenSpaceParents = acyclicGraph.flattenDestination().map { it.key.name to it.value.map { it.name } }.toMap() -// Timber.v("## SPACES: flattenSpaceParents ${flattenSpaceParents.map { it.key.name to it.value.map { it.name } }.joinToString("\n") { -// it.first + ": [" + it.second.joinToString(",") + "]" -// }}") - -// Timber.v("## SPACES: lookup map ${lookupMap.map { it.key.name to it.value.map { it.name } }.toMap()}") lookupMap.entries .filter { it.key.roomType == RoomType.SPACE && it.key.membership == Membership.JOIN } .forEach { entry -> val parent = RoomSummaryEntity.where(realm, entry.key.roomId).findFirst() if (parent != null) { -// Timber.v("## SPACES: check hierarchy of ${parent.name} id ${parent.roomId}") -// Timber.v("## SPACES: flat known parents of ${parent.name} are ${flattenSpaceParents[parent.roomId]}") val flattenParentsIds = (flattenSpaceParents[parent.roomId] ?: emptyList()) + listOf(parent.roomId) -// Timber.v("## SPACES: flatten known parents of children of ${parent.name} are ${flattenParentsIds}") entry.value.forEach { child -> RoomSummaryEntity.where(realm, child.roomId).findFirst()?.let { childSum -> - -// Timber.w("## SPACES: ${childSum.name} is ${childSum.roomId} fc: ${childSum.flattenParentIds}") -// var allParents = childSum.flattenParentIds ?: "" + // TODO: Revisit + childSum.parents.add(SpaceParentSummaryEntity( + true, + parent.roomId, + parent, + RealmList() + )) if (childSum.flattenParentIds == null) childSum.flattenParentIds = "" flattenParentsIds.forEach { if (childSum.flattenParentIds?.contains(it) != true) { - childSum.flattenParentIds += "|$it" + if (childSum.flattenParentIds?.isEmpty() == false) { + childSum.flattenParentIds += "|" + } + childSum.flattenParentIds += it } } -// childSum.flattenParentIds = "$allParents|" - -// Timber.v("## SPACES: flatten of ${childSum.name} is ${childSum.flattenParentIds}") } } } @@ -411,7 +407,6 @@ internal class RoomSummaryUpdater @Inject constructor( // we keep real m.child/m.parent relations and add the one for common memberships dmRoom.flattenParentIds += "|${flattenRelated.joinToString("|")}|" } -// Timber.v("## SPACES: flatten of ${dmRoom.otherMemberIds.joinToString(",")} is ${dmRoom.flattenParentIds}") } // Maybe a good place to count the number of notifications for spaces? diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/CollapsableTypedEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/CollapsableTypedEpoxyController.kt index 8cf7e6bcab..35396d52d5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/CollapsableTypedEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/CollapsableTypedEpoxyController.kt @@ -68,7 +68,7 @@ abstract class CollapsableTypedEpoxyController : } override fun buildModels() { - check(isBuildingModels()) { + check(isBuildingModels) { ("You cannot call `buildModels` directly. Call `setData` instead to trigger a model " + "refresh with new data.") } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt index ef7a1012df..cabaf11b75 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt @@ -287,7 +287,7 @@ class RoomListFragment @Inject constructor( val contentAdapter = when { section.livePages != null -> { - pagedControllerFactory.createRoomSummaryPagedController() + pagedControllerFactory.createRoomSummaryPagedController(roomListParams.displayMode) .also { controller -> section.livePages.observe(viewLifecycleOwner) { pl -> controller.submitList(pl) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt index e5a4e374c9..a869041aa8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt @@ -36,6 +36,7 @@ import im.vector.app.core.ui.views.PresenceStateImageView import im.vector.app.core.ui.views.ShieldImageView import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer +import im.vector.app.features.home.RoomListDisplayMode import im.vector.app.features.themes.ThemeUtils import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel @@ -54,6 +55,12 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { @EpoxyAttribute lateinit var matrixItem: MatrixItem + @EpoxyAttribute + var displayMode: RoomListDisplayMode = RoomListDisplayMode.PEOPLE + + @EpoxyAttribute + var spaceName: String? = null + @EpoxyAttribute lateinit var lastFormattedEvent: EpoxyCharSequence @@ -105,7 +112,7 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { } holder.titleView.text = matrixItem.getBestName() holder.lastEventTimeView.text = lastEventTime - holder.lastEventView.text = lastFormattedEvent.charSequence + holder.lastEventView.text = getTextForLastEventView() holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State(unreadNotificationCount, showHighlighted)) holder.unreadIndentIndicator.isVisible = hasUnreadMessage holder.draftView.isVisible = hasDraft @@ -119,6 +126,14 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { holder.roomAvatarPresenceImageView.render(showPresence, userPresence) } + private fun getTextForLastEventView(): CharSequence { + return if (displayMode == RoomListDisplayMode.FILTERED) { + spaceName.orEmpty() // TODO: handle other cases + } else { + lastFormattedEvent.charSequence + } + } + override fun unbind(holder: Holder) { holder.rootView.setOnClickListener(null) holder.rootView.setOnLongClickListener(null) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt index cd3a8b0890..f11f39e402 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt @@ -26,6 +26,7 @@ import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.AvatarRenderer +import im.vector.app.features.home.RoomListDisplayMode import im.vector.app.features.home.room.detail.timeline.format.DisplayableEventFormatter import im.vector.app.features.home.room.typing.TypingHelper import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence @@ -46,13 +47,14 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor fun create(roomSummary: RoomSummary, roomChangeMembershipStates: Map, selectedRoomIds: Set, + displayMode: RoomListDisplayMode, listener: RoomListListener?): VectorEpoxyModel<*> { return when (roomSummary.membership) { Membership.INVITE -> { val changeMembershipState = roomChangeMembershipStates[roomSummary.roomId] ?: ChangeMembershipState.Unknown createInvitationItem(roomSummary, changeMembershipState, listener) } - else -> createRoomItem(roomSummary, selectedRoomIds, listener?.let { it::onRoomClicked }, listener?.let { it::onRoomLongClicked }) + else -> createRoomItem(roomSummary, selectedRoomIds, displayMode, listener?.let { it::onRoomClicked }, listener?.let { it::onRoomLongClicked }) } } @@ -105,6 +107,7 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor fun createRoomItem( roomSummary: RoomSummary, selectedRoomIds: Set, + displayMode: RoomListDisplayMode, onClick: ((RoomSummary) -> Unit)?, onLongClick: ((RoomSummary) -> Boolean)? ): VectorEpoxyModel<*> { @@ -124,6 +127,8 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor .avatarRenderer(avatarRenderer) // We do not display shield in the room list anymore // .encryptionTrustLevel(roomSummary.roomEncryptionTrustLevel) + .displayMode(displayMode) + .spaceName(roomSummary.spaceParents?.firstOrNull()?.roomSummary?.name.orEmpty()) .isPublic(roomSummary.isPublic) .showPresence(roomSummary.isDirect) .userPresence(roomSummary.directUserPresence) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryListController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryListController.kt index 75aaee45cb..683263dbbc 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryListController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryListController.kt @@ -16,6 +16,7 @@ package im.vector.app.features.home.room.list +import im.vector.app.features.home.RoomListDisplayMode import org.matrix.android.sdk.api.session.room.model.RoomSummary class RoomSummaryListController( @@ -26,7 +27,7 @@ class RoomSummaryListController( override fun buildModels(data: List?) { data?.forEach { - add(roomSummaryItemFactory.create(it, emptyMap(), emptySet(), listener)) + add(roomSummaryItemFactory.create(it, emptyMap(), emptySet(), RoomListDisplayMode.ROOMS /* TODO: change */, listener)) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedController.kt index e9cbc69215..445438eec9 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedController.kt @@ -19,11 +19,13 @@ package im.vector.app.features.home.room.list import com.airbnb.epoxy.EpoxyModel import com.airbnb.epoxy.paging.PagedListEpoxyController import im.vector.app.core.utils.createUIHandler +import im.vector.app.features.home.RoomListDisplayMode import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.model.RoomSummary class RoomSummaryPagedController( - private val roomSummaryItemFactory: RoomSummaryItemFactory + private val roomSummaryItemFactory: RoomSummaryItemFactory, + private val displayMode: RoomListDisplayMode ) : PagedListEpoxyController( // Important it must match the PageList builder notify Looper modelBuildingHandler = createUIHandler() @@ -57,6 +59,6 @@ class RoomSummaryPagedController( override fun buildItemModel(currentPosition: Int, item: RoomSummary?): EpoxyModel<*> { // for place holder if enabled item ?: return RoomSummaryItemPlaceHolder_().apply { id(currentPosition) } - return roomSummaryItemFactory.create(item, roomChangeMembershipStates.orEmpty(), emptySet(), listener) + return roomSummaryItemFactory.create(item, roomChangeMembershipStates.orEmpty(), emptySet(), displayMode, listener) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedControllerFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedControllerFactory.kt index c86d8ab243..36f1b5ac90 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedControllerFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedControllerFactory.kt @@ -16,14 +16,15 @@ package im.vector.app.features.home.room.list +import im.vector.app.features.home.RoomListDisplayMode import javax.inject.Inject class RoomSummaryPagedControllerFactory @Inject constructor( private val roomSummaryItemFactory: RoomSummaryItemFactory ) { - fun createRoomSummaryPagedController(): RoomSummaryPagedController { - return RoomSummaryPagedController(roomSummaryItemFactory) + fun createRoomSummaryPagedController(displayMode: RoomListDisplayMode): RoomSummaryPagedController { + return RoomSummaryPagedController(roomSummaryItemFactory, displayMode) } fun createRoomSummaryListController(): RoomSummaryListController { diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt index fd35bf11a4..7c82b7aea0 100644 --- a/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt +++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt @@ -22,6 +22,7 @@ import im.vector.app.R import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.resources.StringProvider +import im.vector.app.features.home.RoomListDisplayMode import im.vector.app.features.home.room.list.RoomSummaryItemFactory import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject @@ -53,7 +54,7 @@ class IncomingShareController @Inject constructor(private val roomSummaryItemFac } else { roomSummaries.forEach { roomSummary -> roomSummaryItemFactory - .createRoomItem(roomSummary, data.selectedRoomIds, callback?.let { it::onRoomClicked }, callback?.let { it::onRoomLongClicked }) + .createRoomItem(roomSummary, data.selectedRoomIds, RoomListDisplayMode.ROOMS /* TODO: Change */, callback?.let { it::onRoomClicked }, callback?.let { it::onRoomLongClicked }) .addTo(this) } } diff --git a/vector/src/main/res/layout/item_room.xml b/vector/src/main/res/layout/item_room.xml index 2b27cb8efe..3911e8df34 100644 --- a/vector/src/main/res/layout/item_room.xml +++ b/vector/src/main/res/layout/item_room.xml @@ -213,7 +213,8 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@id/roomNameView" app:layout_constraintTop_toBottomOf="@id/roomNameView" - tools:text="Alice is typing…" /> + tools:text="Alice is typing…" + tools:visibility="gone" /> Date: Thu, 28 Apr 2022 11:12:47 +0200 Subject: [PATCH 011/244] Adds user id and canonical alias to search result subtitles --- .../app/features/home/room/list/RoomSummaryItem.kt | 10 +++++----- .../home/room/list/RoomSummaryItemFactory.kt | 12 +++++++++++- vector/src/main/res/layout/item_room.xml | 4 ++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt index a869041aa8..3c091d0e05 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt @@ -59,7 +59,7 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { var displayMode: RoomListDisplayMode = RoomListDisplayMode.PEOPLE @EpoxyAttribute - var spaceName: String? = null + lateinit var subtitle: String @EpoxyAttribute lateinit var lastFormattedEvent: EpoxyCharSequence @@ -112,7 +112,7 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { } holder.titleView.text = matrixItem.getBestName() holder.lastEventTimeView.text = lastEventTime - holder.lastEventView.text = getTextForLastEventView() + holder.subtitleView.text = getTextForLastEventView() holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State(unreadNotificationCount, showHighlighted)) holder.unreadIndentIndicator.isVisible = hasUnreadMessage holder.draftView.isVisible = hasDraft @@ -122,13 +122,13 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { holder.roomAvatarFailSendingImageView.isVisible = hasFailedSending renderSelection(holder, showSelected) holder.typingView.setTextOrHide(typingMessage) - holder.lastEventView.isInvisible = holder.typingView.isVisible + holder.subtitleView.isInvisible = holder.typingView.isVisible holder.roomAvatarPresenceImageView.render(showPresence, userPresence) } private fun getTextForLastEventView(): CharSequence { return if (displayMode == RoomListDisplayMode.FILTERED) { - spaceName.orEmpty() // TODO: handle other cases + subtitle } else { lastFormattedEvent.charSequence } @@ -157,7 +157,7 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { val titleView by bind(R.id.roomNameView) val unreadCounterBadgeView by bind(R.id.roomUnreadCounterBadgeView) val unreadIndentIndicator by bind(R.id.roomUnreadIndicator) - val lastEventView by bind(R.id.roomLastEventView) + val subtitleView by bind(R.id.subtitleView) val typingView by bind(R.id.roomTypingView) val draftView by bind(R.id.roomDraftBadge) val lastEventTimeView by bind(R.id.roomLastEventTimeView) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt index f11f39e402..cc99c0eb6e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt @@ -111,6 +111,7 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor onClick: ((RoomSummary) -> Unit)?, onLongClick: ((RoomSummary) -> Boolean)? ): VectorEpoxyModel<*> { + val subtitle = getSearchResultSubtitle(roomSummary) val unreadCount = roomSummary.notificationCount val showHighlighted = roomSummary.highlightCount > 0 val showSelected = selectedRoomIds.contains(roomSummary.roomId) @@ -121,6 +122,7 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor latestFormattedEvent = displayableEventFormatter.format(latestEvent, roomSummary.isDirect, roomSummary.isDirect.not()) latestEventTime = dateFormatter.format(latestEvent.root.originServerTs, DateFormatKind.ROOM_LIST) } + val typingMessage = typingHelper.getTypingMessage(roomSummary.typingUsers) return RoomSummaryItem_() .id(roomSummary.roomId) @@ -128,7 +130,7 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor // We do not display shield in the room list anymore // .encryptionTrustLevel(roomSummary.roomEncryptionTrustLevel) .displayMode(displayMode) - .spaceName(roomSummary.spaceParents?.firstOrNull()?.roomSummary?.name.orEmpty()) + .subtitle(subtitle) .isPublic(roomSummary.isPublic) .showPresence(roomSummary.isDirect) .userPresence(roomSummary.directUserPresence) @@ -147,4 +149,12 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor } .itemClickListener { onClick?.invoke(roomSummary) } } + + private fun getSearchResultSubtitle(roomSummary: RoomSummary): String { + val spaceName = roomSummary.spaceParents?.firstOrNull()?.roomSummary?.name + val userId = roomSummary.directUserId + val canonicalAlias = roomSummary.canonicalAlias + + return (spaceName ?: userId ?: canonicalAlias).orEmpty() + } } diff --git a/vector/src/main/res/layout/item_room.xml b/vector/src/main/res/layout/item_room.xml index 3911e8df34..ab0af18acb 100644 --- a/vector/src/main/res/layout/item_room.xml +++ b/vector/src/main/res/layout/item_room.xml @@ -183,7 +183,7 @@ tools:text="@tools:sample/date/hhmm" /> Date: Thu, 28 Apr 2022 11:46:02 +0200 Subject: [PATCH 012/244] Disables typing indicator in filtered search --- .../app/features/home/room/list/RoomSummaryItem.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt index 3c091d0e05..e0547b87b1 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt @@ -121,9 +121,16 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { holder.roomAvatarPublicDecorationImageView.isVisible = isPublic holder.roomAvatarFailSendingImageView.isVisible = hasFailedSending renderSelection(holder, showSelected) - holder.typingView.setTextOrHide(typingMessage) - holder.subtitleView.isInvisible = holder.typingView.isVisible holder.roomAvatarPresenceImageView.render(showPresence, userPresence) + showTypingViewIfNecessary(holder) + + } + + private fun showTypingViewIfNecessary(holder: Holder) { + if (displayMode != RoomListDisplayMode.FILTERED) { + holder.typingView.setTextOrHide(typingMessage) + holder.subtitleView.isInvisible = holder.typingView.isVisible + } } private fun getTextForLastEventView(): CharSequence { From 33475602f865d339c3119cb7e137c5c02aa4e9c5 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 28 Apr 2022 11:54:51 +0200 Subject: [PATCH 013/244] Adds canonical named argument to RoomSummaryUpdater --- .../sdk/internal/session/room/summary/RoomSummaryUpdater.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt index 70c1453865..1c1963bfd4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt @@ -364,7 +364,7 @@ internal class RoomSummaryUpdater @Inject constructor( RoomSummaryEntity.where(realm, child.roomId).findFirst()?.let { childSum -> // TODO: Revisit childSum.parents.add(SpaceParentSummaryEntity( - true, + canonical = true, parent.roomId, parent, RealmList() From b28035807788e1ac40a1586a24b2a9b79046c4c7 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 28 Apr 2022 11:55:44 +0200 Subject: [PATCH 014/244] Adds more named arguments to RoomSummaryUpdater --- .../sdk/internal/session/room/summary/RoomSummaryUpdater.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt index 1c1963bfd4..81979c6926 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt @@ -365,9 +365,9 @@ internal class RoomSummaryUpdater @Inject constructor( // TODO: Revisit childSum.parents.add(SpaceParentSummaryEntity( canonical = true, - parent.roomId, - parent, - RealmList() + parentRoomId = parent.roomId, + parentSummaryEntity = parent, + viaServers = RealmList() )) if (childSum.flattenParentIds == null) childSum.flattenParentIds = "" flattenParentsIds.forEach { From 4784717b0cecab67d03731daaa4dc32f58ef8e1d Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 28 Apr 2022 12:02:04 +0200 Subject: [PATCH 015/244] Fixes lint error --- .../im/vector/app/features/home/room/list/RoomSummaryItem.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt index e0547b87b1..aa459afd3b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt @@ -123,7 +123,6 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { renderSelection(holder, showSelected) holder.roomAvatarPresenceImageView.render(showPresence, userPresence) showTypingViewIfNecessary(holder) - } private fun showTypingViewIfNecessary(holder: Holder) { From 962e9abc6bea1bfd0efa9105fd0db072b6f48a67 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 28 Apr 2022 12:04:54 +0200 Subject: [PATCH 016/244] Fixes lint error --- .../app/features/home/room/list/RoomSummaryItemFactory.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt index cc99c0eb6e..f9f61f730b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt @@ -54,7 +54,9 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor val changeMembershipState = roomChangeMembershipStates[roomSummary.roomId] ?: ChangeMembershipState.Unknown createInvitationItem(roomSummary, changeMembershipState, listener) } - else -> createRoomItem(roomSummary, selectedRoomIds, displayMode, listener?.let { it::onRoomClicked }, listener?.let { it::onRoomLongClicked }) + else -> createRoomItem( + roomSummary, selectedRoomIds, displayMode, listener?.let { it::onRoomClicked }, listener?.let { it::onRoomLongClicked } + ) } } From 7e415e82b099dcb5111caffb05d1577f843fc3f8 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 28 Apr 2022 12:37:54 +0200 Subject: [PATCH 017/244] Fixes lint error --- .../vector/app/features/share/IncomingShareController.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt index 7c82b7aea0..6926a54cc4 100644 --- a/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt +++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt @@ -54,7 +54,13 @@ class IncomingShareController @Inject constructor(private val roomSummaryItemFac } else { roomSummaries.forEach { roomSummary -> roomSummaryItemFactory - .createRoomItem(roomSummary, data.selectedRoomIds, RoomListDisplayMode.ROOMS /* TODO: Change */, callback?.let { it::onRoomClicked }, callback?.let { it::onRoomLongClicked }) + .createRoomItem( + roomSummary, + data.selectedRoomIds, + RoomListDisplayMode.ROOMS /* TODO: Change */, + callback?.let { it::onRoomClicked }, + callback?.let { it::onRoomLongClicked } + ) .addTo(this) } } From 7cc79fef0faa72b764efdfedc97957e312f2a522 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 29 Apr 2022 12:37:19 +0200 Subject: [PATCH 018/244] Refactors RoomSummaryItem --- .../home/room/list/RoomSummaryItem.kt | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt index aa459afd3b..4cea812775 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt @@ -105,14 +105,14 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { override fun bind(holder: Holder) { super.bind(holder) + + renderDisplayMode(holder) holder.rootView.onClick(itemClickListener) holder.rootView.setOnLongClickListener { it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) itemLongClickListener?.onLongClick(it) ?: false } holder.titleView.text = matrixItem.getBestName() - holder.lastEventTimeView.text = lastEventTime - holder.subtitleView.text = getTextForLastEventView() holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State(unreadNotificationCount, showHighlighted)) holder.unreadIndentIndicator.isVisible = hasUnreadMessage holder.draftView.isVisible = hasDraft @@ -122,22 +122,24 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { holder.roomAvatarFailSendingImageView.isVisible = hasFailedSending renderSelection(holder, showSelected) holder.roomAvatarPresenceImageView.render(showPresence, userPresence) - showTypingViewIfNecessary(holder) } - private fun showTypingViewIfNecessary(holder: Holder) { - if (displayMode != RoomListDisplayMode.FILTERED) { - holder.typingView.setTextOrHide(typingMessage) - holder.subtitleView.isInvisible = holder.typingView.isVisible - } + private fun renderDisplayMode(holder: Holder) = when (displayMode) { + RoomListDisplayMode.ROOMS, + RoomListDisplayMode.PEOPLE, + RoomListDisplayMode.NOTIFICATIONS -> renderForDefaultDisplayMode(holder) + RoomListDisplayMode.FILTERED -> renderForFilteredDisplayMode(holder) } - private fun getTextForLastEventView(): CharSequence { - return if (displayMode == RoomListDisplayMode.FILTERED) { - subtitle - } else { - lastFormattedEvent.charSequence - } + private fun renderForDefaultDisplayMode(holder: Holder) { + holder.subtitleView.text = lastFormattedEvent.charSequence + holder.lastEventTimeView.text = lastEventTime + } + + private fun renderForFilteredDisplayMode(holder: Holder) { + holder.subtitleView.text = subtitle + holder.typingView.setTextOrHide(typingMessage) + holder.subtitleView.isInvisible = holder.typingView.isVisible } override fun unbind(holder: Holder) { From a355b625e9dd671af000970963eb4406f270faa0 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 29 Apr 2022 13:05:08 +0200 Subject: [PATCH 019/244] Adds displayMode to RoomSummaryListController --- .../vector/app/features/home/room/list/RoomListFragment.kt | 2 +- .../app/features/home/room/list/RoomSummaryListController.kt | 5 +++-- .../home/room/list/RoomSummaryPagedControllerFactory.kt | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt index cabaf11b75..65055346e6 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt @@ -337,7 +337,7 @@ class RoomListFragment @Inject constructor( } } else -> { - pagedControllerFactory.createRoomSummaryListController() + pagedControllerFactory.createRoomSummaryListController(roomListParams.displayMode) .also { controller -> section.liveList?.observe(viewLifecycleOwner) { list -> controller.setData(list) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryListController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryListController.kt index 683263dbbc..2eb8921fd5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryListController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryListController.kt @@ -20,14 +20,15 @@ import im.vector.app.features.home.RoomListDisplayMode import org.matrix.android.sdk.api.session.room.model.RoomSummary class RoomSummaryListController( - private val roomSummaryItemFactory: RoomSummaryItemFactory + private val roomSummaryItemFactory: RoomSummaryItemFactory, + private val displayMode: RoomListDisplayMode ) : CollapsableTypedEpoxyController>() { var listener: RoomListListener? = null override fun buildModels(data: List?) { data?.forEach { - add(roomSummaryItemFactory.create(it, emptyMap(), emptySet(), RoomListDisplayMode.ROOMS /* TODO: change */, listener)) + add(roomSummaryItemFactory.create(it, emptyMap(), emptySet(), displayMode, listener)) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedControllerFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedControllerFactory.kt index 36f1b5ac90..f72698048d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedControllerFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedControllerFactory.kt @@ -27,8 +27,8 @@ class RoomSummaryPagedControllerFactory @Inject constructor( return RoomSummaryPagedController(roomSummaryItemFactory, displayMode) } - fun createRoomSummaryListController(): RoomSummaryListController { - return RoomSummaryListController(roomSummaryItemFactory) + fun createRoomSummaryListController(displayMode: RoomListDisplayMode): RoomSummaryListController { + return RoomSummaryListController(roomSummaryItemFactory, displayMode) } fun createSuggestedRoomListController(): SuggestedRoomListController { From f70a24d257f6e28c9c6c3cd5216b52293d1af410 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 29 Apr 2022 13:18:46 +0200 Subject: [PATCH 020/244] Changes IncomingShareController display mode to FILTERED --- .../im/vector/app/features/share/IncomingShareController.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt index 6926a54cc4..bf5cedd5da 100644 --- a/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt +++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt @@ -57,7 +57,7 @@ class IncomingShareController @Inject constructor(private val roomSummaryItemFac .createRoomItem( roomSummary, data.selectedRoomIds, - RoomListDisplayMode.ROOMS /* TODO: Change */, + RoomListDisplayMode.FILTERED, callback?.let { it::onRoomClicked }, callback?.let { it::onRoomLongClicked } ) From 47493fcfa135ab6464fda974a45d9bd164ee5222 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Mon, 2 May 2022 14:11:17 +0200 Subject: [PATCH 021/244] Replaces method for getting the space parents of rooms --- .../session/room/summary/RoomSummaryDataSource.kt | 13 +++++++++++++ .../session/room/summary/RoomSummaryUpdater.kt | 8 -------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt index 18a4f80547..a84f9aa7d6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt @@ -37,6 +37,7 @@ import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomType +import org.matrix.android.sdk.api.session.room.model.SpaceParentInfo import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams import org.matrix.android.sdk.api.session.room.spaceSummaryQueryParams import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount @@ -197,6 +198,18 @@ internal class RoomSummaryDataSource @Inject constructor( } val dataSourceFactory = realmDataSourceFactory.map { roomSummaryMapper.map(it) + }.map { roomSummary -> + val parents = roomSummary.flattenParentIds.mapNotNull { parentId -> + getRoomSummary(parentId)?.let { parentSummary -> + SpaceParentInfo( + parentId = parentSummary.flattenParentIds.firstOrNull(), + roomSummary = parentSummary, + canonical = true, + viaServers = emptyList() + ) + } + } + roomSummary.copy(spaceParents = parents) } val boundaries = MutableLiveData(ResultBoundaries()) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt index 81979c6926..4a9f6c44c9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt @@ -17,7 +17,6 @@ package org.matrix.android.sdk.internal.session.room.summary import io.realm.Realm -import io.realm.RealmList import io.realm.kotlin.createObject import kotlinx.coroutines.runBlocking import org.matrix.android.sdk.api.extensions.orFalse @@ -362,13 +361,6 @@ internal class RoomSummaryUpdater @Inject constructor( val flattenParentsIds = (flattenSpaceParents[parent.roomId] ?: emptyList()) + listOf(parent.roomId) entry.value.forEach { child -> RoomSummaryEntity.where(realm, child.roomId).findFirst()?.let { childSum -> - // TODO: Revisit - childSum.parents.add(SpaceParentSummaryEntity( - canonical = true, - parentRoomId = parent.roomId, - parentSummaryEntity = parent, - viaServers = RealmList() - )) if (childSum.flattenParentIds == null) childSum.flattenParentIds = "" flattenParentsIds.forEach { if (childSum.flattenParentIds?.contains(it) != true) { From c9b32fec44515b26f4815f41a10dafc738e3c7d6 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Mon, 2 May 2022 14:42:56 +0200 Subject: [PATCH 022/244] Changes ordering of room subtitles used --- .../room/summary/RoomSummaryUpdater.kt | 21 +++++++++++++++---- .../home/room/list/RoomSummaryItemFactory.kt | 4 ++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt index 4a9f6c44c9..3af579d050 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt @@ -349,27 +349,39 @@ internal class RoomSummaryUpdater @Inject constructor( } val acyclicGraph = graph.withoutEdges(backEdges) +// Timber.v("## SPACES: acyclicGraph $acyclicGraph") val flattenSpaceParents = acyclicGraph.flattenDestination().map { it.key.name to it.value.map { it.name } }.toMap() +// Timber.v("## SPACES: flattenSpaceParents ${flattenSpaceParents.map { it.key.name to it.value.map { it.name } }.joinToString("\n") { +// it.first + ": [" + it.second.joinToString(",") + "]" +// }}") + +// Timber.v("## SPACES: lookup map ${lookupMap.map { it.key.name to it.value.map { it.name } }.toMap()}") lookupMap.entries .filter { it.key.roomType == RoomType.SPACE && it.key.membership == Membership.JOIN } .forEach { entry -> val parent = RoomSummaryEntity.where(realm, entry.key.roomId).findFirst() if (parent != null) { +// Timber.v("## SPACES: check hierarchy of ${parent.name} id ${parent.roomId}") +// Timber.v("## SPACES: flat known parents of ${parent.name} are ${flattenSpaceParents[parent.roomId]}") val flattenParentsIds = (flattenSpaceParents[parent.roomId] ?: emptyList()) + listOf(parent.roomId) +// Timber.v("## SPACES: flatten known parents of children of ${parent.name} are ${flattenParentsIds}") entry.value.forEach { child -> RoomSummaryEntity.where(realm, child.roomId).findFirst()?.let { childSum -> + +// Timber.w("## SPACES: ${childSum.name} is ${childSum.roomId} fc: ${childSum.flattenParentIds}") +// var allParents = childSum.flattenParentIds ?: "" if (childSum.flattenParentIds == null) childSum.flattenParentIds = "" flattenParentsIds.forEach { if (childSum.flattenParentIds?.contains(it) != true) { - if (childSum.flattenParentIds?.isEmpty() == false) { - childSum.flattenParentIds += "|" - } - childSum.flattenParentIds += it + childSum.flattenParentIds += "|$it" } } +// childSum.flattenParentIds = "$allParents|" + +// Timber.v("## SPACES: flatten of ${childSum.name} is ${childSum.flattenParentIds}") } } } @@ -399,6 +411,7 @@ internal class RoomSummaryUpdater @Inject constructor( // we keep real m.child/m.parent relations and add the one for common memberships dmRoom.flattenParentIds += "|${flattenRelated.joinToString("|")}|" } +// Timber.v("## SPACES: flatten of ${dmRoom.otherMemberIds.joinToString(",")} is ${dmRoom.flattenParentIds}") } // Maybe a good place to count the number of notifications for spaces? diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt index f9f61f730b..05701b908f 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt @@ -153,10 +153,10 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor } private fun getSearchResultSubtitle(roomSummary: RoomSummary): String { - val spaceName = roomSummary.spaceParents?.firstOrNull()?.roomSummary?.name val userId = roomSummary.directUserId + val spaceName = roomSummary.spaceParents?.firstOrNull()?.roomSummary?.name val canonicalAlias = roomSummary.canonicalAlias - return (spaceName ?: userId ?: canonicalAlias).orEmpty() + return (userId ?: spaceName ?: canonicalAlias).orEmpty() } } From b46794d4df2e863ef1799da1c1ae3e154ce49751 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Mon, 2 May 2022 14:44:23 +0200 Subject: [PATCH 023/244] Adds changelog file --- changelog.d/5860.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5860.feature diff --git a/changelog.d/5860.feature b/changelog.d/5860.feature new file mode 100644 index 0000000000..6c34fa0905 --- /dev/null +++ b/changelog.d/5860.feature @@ -0,0 +1 @@ +Adds space or user id as a subtitle under rooms in search From 21fe5a23fb5a32ec5204a7be502ffce1c57d822a Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 13 May 2022 13:07:20 +0200 Subject: [PATCH 024/244] Adds vertical centering of title when no subtitle is present --- .../home/room/list/RoomSummaryItem.kt | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt index 4cea812775..0a97518cf1 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt @@ -18,9 +18,10 @@ package im.vector.app.features.home.room.list import android.view.HapticFeedbackConstants import android.view.View -import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.constraintlayout.widget.ConstraintSet import androidx.core.view.isInvisible import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute @@ -134,12 +135,33 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { private fun renderForDefaultDisplayMode(holder: Holder) { holder.subtitleView.text = lastFormattedEvent.charSequence holder.lastEventTimeView.text = lastEventTime + holder.typingView.setTextOrHide(typingMessage) + holder.subtitleView.isInvisible = holder.typingView.isVisible } private fun renderForFilteredDisplayMode(holder: Holder) { holder.subtitleView.text = subtitle - holder.typingView.setTextOrHide(typingMessage) - holder.subtitleView.isInvisible = holder.typingView.isVisible + if (subtitle.isEmpty()) { + holder.centerTitleVertically() + } + } + + private fun Holder.centerTitleVertically() { + removeTitleTopMargin() + constrainTitleToParentBottom() + } + + private fun Holder.removeTitleTopMargin() { + val layoutParams = titleView.layoutParams as ConstraintLayout.LayoutParams + layoutParams.topMargin = 0 + titleView.layoutParams = layoutParams + } + + private fun Holder.constrainTitleToParentBottom() { + val constraintSet = ConstraintSet() + constraintSet.clone(rootView) + constraintSet.connect(titleView.id, ConstraintSet.BOTTOM, rootView.id, ConstraintSet.BOTTOM) + constraintSet.applyTo(rootView) } override fun unbind(holder: Holder) { @@ -175,6 +197,6 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { val roomAvatarPublicDecorationImageView by bind(R.id.roomAvatarPublicDecorationImageView) val roomAvatarFailSendingImageView by bind(R.id.roomAvatarFailSendingImageView) val roomAvatarPresenceImageView by bind(R.id.roomAvatarPresenceImageView) - val rootView by bind(R.id.itemRoomLayout) + val rootView by bind(R.id.itemRoomLayout) } } From 50839c206bf14e2783c8953275580f547a990ba2 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 13 May 2022 20:43:03 +0200 Subject: [PATCH 025/244] Adds flattenParents field to RoomSummary and corresponding mapping --- .../sdk/api/session/room/model/RoomSummary.kt | 1 + .../room/summary/RoomSummaryDataSource.kt | 28 ++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomSummary.kt index 71c1d8303e..5a265c2b26 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomSummary.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomSummary.kt @@ -62,6 +62,7 @@ data class RoomSummary( val roomType: String? = null, val spaceParents: List? = null, val spaceChildren: List? = null, + val flattenParents: List = emptyList(), val flattenParentIds: List = emptyList(), val roomEncryptionAlgorithm: RoomEncryptionAlgorithm? = null ) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt index b165fb3001..752c828710 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt @@ -194,19 +194,7 @@ internal class RoomSummaryDataSource @Inject constructor( } val dataSourceFactory = realmDataSourceFactory.map { roomSummaryMapper.map(it) - }.map { roomSummary -> - val parents = roomSummary.flattenParentIds.mapNotNull { parentId -> - getRoomSummary(parentId)?.let { parentSummary -> - SpaceParentInfo( - parentId = parentSummary.flattenParentIds.firstOrNull(), - roomSummary = parentSummary, - canonical = true, - viaServers = emptyList() - ) - } - } - roomSummary.copy(spaceParents = parents) - } + }.map { it.getWithParents()} val boundaries = MutableLiveData(ResultBoundaries()) @@ -245,6 +233,20 @@ internal class RoomSummaryDataSource @Inject constructor( } } + private fun RoomSummary.getWithParents(): RoomSummary { + val parents = flattenParentIds.mapNotNull { parentId -> + getRoomSummary(parentId)?.let { parentSummary -> + SpaceParentInfo( + parentId = parentSummary.flattenParentIds.firstOrNull(), + roomSummary = parentSummary, + canonical = true, + viaServers = emptyList() + ) + } + } + return copy(flattenParents = parents) + } + fun getCountLive(queryParams: RoomSummaryQueryParams): LiveData { val liveRooms = monarchy.findAllManagedWithChanges { roomSummariesQuery(it, queryParams) From 7c1d1c34647e6a860b68adc7913a63a8574159a4 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Mon, 16 May 2022 10:26:28 +0200 Subject: [PATCH 026/244] Adds centering of items with no subtitles --- .../home/room/list/RoomSummaryItem.kt | 25 ++++--------------- vector/src/main/res/layout/item_room.xml | 18 +++++++++++-- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt index 0a97518cf1..abcfe0d5d8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt @@ -19,9 +19,9 @@ package im.vector.app.features.home.room.list import android.view.HapticFeedbackConstants import android.view.View import android.widget.ImageView +import android.widget.Space import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout -import androidx.constraintlayout.widget.ConstraintSet import androidx.core.view.isInvisible import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute @@ -141,27 +141,11 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { private fun renderForFilteredDisplayMode(holder: Holder) { holder.subtitleView.text = subtitle - if (subtitle.isEmpty()) { - holder.centerTitleVertically() - } + holder.centerTitle(shouldCenter = subtitle.isEmpty()) } - private fun Holder.centerTitleVertically() { - removeTitleTopMargin() - constrainTitleToParentBottom() - } - - private fun Holder.removeTitleTopMargin() { - val layoutParams = titleView.layoutParams as ConstraintLayout.LayoutParams - layoutParams.topMargin = 0 - titleView.layoutParams = layoutParams - } - - private fun Holder.constrainTitleToParentBottom() { - val constraintSet = ConstraintSet() - constraintSet.clone(rootView) - constraintSet.connect(titleView.id, ConstraintSet.BOTTOM, rootView.id, ConstraintSet.BOTTOM) - constraintSet.applyTo(rootView) + private fun Holder.centerTitle(shouldCenter: Boolean) { + centerTitleSpace.isVisible = shouldCenter } override fun unbind(holder: Holder) { @@ -198,5 +182,6 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { val roomAvatarFailSendingImageView by bind(R.id.roomAvatarFailSendingImageView) val roomAvatarPresenceImageView by bind(R.id.roomAvatarPresenceImageView) val rootView by bind(R.id.itemRoomLayout) + val centerTitleSpace by bind(R.id.centerTitleSpace) } } diff --git a/vector/src/main/res/layout/item_room.xml b/vector/src/main/res/layout/item_room.xml index ab0af18acb..ac028ccb08 100644 --- a/vector/src/main/res/layout/item_room.xml +++ b/vector/src/main/res/layout/item_room.xml @@ -112,13 +112,27 @@ app:layout_constraintTop_toBottomOf="@id/roomAvatarContainer" tools:layout_marginStart="20dp" /> + + + + Date: Mon, 16 May 2022 10:31:16 +0200 Subject: [PATCH 027/244] Fixes lint error --- .../sdk/internal/session/room/summary/RoomSummaryDataSource.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt index 752c828710..f3ad4cbdd3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt @@ -194,7 +194,7 @@ internal class RoomSummaryDataSource @Inject constructor( } val dataSourceFactory = realmDataSourceFactory.map { roomSummaryMapper.map(it) - }.map { it.getWithParents()} + }.map { it.getWithParents() } val boundaries = MutableLiveData(ResultBoundaries()) From e706c5a3c8c264feb3d0b19e5efe3dbd56d9dd35 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Tue, 17 May 2022 11:09:14 +0200 Subject: [PATCH 028/244] Adds up navigation from spaces --- .../vector/app/features/home/HomeActivity.kt | 75 ++++++++++--------- .../features/home/HomeActivitySharedAction.kt | 3 +- .../app/features/home/HomeDetailFragment.kt | 70 ++++++++--------- .../src/main/res/drawable/ic_arrow_back.xml | 5 ++ .../main/res/layout/fragment_home_detail.xml | 17 ++++- vector/src/main/res/values/strings.xml | 1 + 6 files changed, 98 insertions(+), 73 deletions(-) create mode 100644 vector/src/main/res/drawable/ic_arrow_back.xml diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index cc202868cc..b4943ce1b4 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -199,43 +199,13 @@ class HomeActivity : when (sharedAction) { is HomeActivitySharedAction.OpenDrawer -> views.drawerLayout.openDrawer(GravityCompat.START) is HomeActivitySharedAction.CloseDrawer -> views.drawerLayout.closeDrawer(GravityCompat.START) - is HomeActivitySharedAction.OpenGroup -> { - views.drawerLayout.closeDrawer(GravityCompat.START) - - // Temporary - // When switching from space to group or group to space, we need to reload the fragment - // To be removed when dropping legacy groups - if (sharedAction.clearFragment) { - replaceFragment(views.homeDetailFragmentContainer, HomeDetailFragment::class.java, allowStateLoss = true) - } else { - // nop - } - // we might want to delay that to avoid having the drawer animation lagging - // would be probably better to let the drawer do that? in the on closed callback? - } - is HomeActivitySharedAction.OpenSpacePreview -> { - startActivity(SpacePreviewActivity.newIntent(this, sharedAction.spaceId)) - } - is HomeActivitySharedAction.AddSpace -> { - createSpaceResultLauncher.launch(SpaceCreationActivity.newIntent(this)) - } - is HomeActivitySharedAction.ShowSpaceSettings -> { - // open bottom sheet - SpaceSettingsMenuBottomSheet - .newInstance(sharedAction.spaceId, object : SpaceSettingsMenuBottomSheet.InteractionListener { - override fun onShareSpaceSelected(spaceId: String) { - ShareSpaceBottomSheet.show(supportFragmentManager, spaceId) - } - }) - .show(supportFragmentManager, "SPACE_SETTINGS") - } - is HomeActivitySharedAction.OpenSpaceInvite -> { - SpaceInviteBottomSheet.newInstance(sharedAction.spaceId) - .show(supportFragmentManager, "SPACE_INVITE") - } - HomeActivitySharedAction.SendSpaceFeedBack -> { - bugReporter.openBugReportScreen(this, ReportType.SPACE_BETA_FEEDBACK) - } + is HomeActivitySharedAction.OpenGroup -> openGroup(sharedAction.shouldClearFragment) + is HomeActivitySharedAction.OpenSpacePreview -> startActivity(SpacePreviewActivity.newIntent(this, sharedAction.spaceId)) + is HomeActivitySharedAction.AddSpace -> createSpaceResultLauncher.launch(SpaceCreationActivity.newIntent(this)) + is HomeActivitySharedAction.ShowSpaceSettings -> showSpaceSettings(sharedAction.spaceId) + is HomeActivitySharedAction.OpenSpaceInvite -> openSpaceInvite(sharedAction.spaceId) + HomeActivitySharedAction.SendSpaceFeedBack -> bugReporter.openBugReportScreen(this, ReportType.SPACE_BETA_FEEDBACK) + HomeActivitySharedAction.CloseGroup -> closeGroup() } } .launchIn(lifecycleScope) @@ -272,6 +242,37 @@ class HomeActivity : homeActivityViewModel.handle(HomeActivityViewActions.ViewStarted) } + private fun openGroup(shouldClearFragment: Boolean) { + views.drawerLayout.closeDrawer(GravityCompat.START) + + // When switching from space to group or group to space, we need to reload the fragment + if (shouldClearFragment) { + replaceFragment(views.homeDetailFragmentContainer, HomeDetailFragment::class.java, allowStateLoss = true) + } else { + // do nothing + } + } + + private fun showSpaceSettings(spaceId: String) { + // open bottom sheet + SpaceSettingsMenuBottomSheet + .newInstance(spaceId, object : SpaceSettingsMenuBottomSheet.InteractionListener { + override fun onShareSpaceSelected(spaceId: String) { + ShareSpaceBottomSheet.show(supportFragmentManager, spaceId) + } + }) + .show(supportFragmentManager, "SPACE_SETTINGS") + } + + private fun openSpaceInvite(spaceId: String) { + SpaceInviteBottomSheet.newInstance(spaceId) + .show(supportFragmentManager, "SPACE_INVITE") + } + + private fun closeGroup() { + views.drawerLayout.openDrawer(GravityCompat.START) + } + private fun handleShowAnalyticsOptIn() { navigator.openAnalyticsOptIn(this) } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt index 6047a1e55e..cebde7fe0a 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt @@ -24,7 +24,8 @@ import im.vector.app.core.platform.VectorSharedAction sealed class HomeActivitySharedAction : VectorSharedAction { object OpenDrawer : HomeActivitySharedAction() object CloseDrawer : HomeActivitySharedAction() - data class OpenGroup(val clearFragment: Boolean) : HomeActivitySharedAction() + data class OpenGroup(val shouldClearFragment: Boolean) : HomeActivitySharedAction() + object CloseGroup : HomeActivitySharedAction() object AddSpace : HomeActivitySharedAction() data class OpenSpacePreview(val spaceId: String) : HomeActivitySharedAction() data class OpenSpaceInvite(val spaceId: String) : HomeActivitySharedAction() diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt index 2753ba817d..9ab1ad60e7 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt @@ -60,6 +60,11 @@ import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject +/* + * TODO: + * 1) Change the hamburger menu to a back button when in a space + * 2) Make the back navigation button follow the same behaviour + */ class HomeDetailFragment @Inject constructor( private val avatarRenderer: AvatarRenderer, private val colorProvider: ColorProvider, @@ -130,12 +135,8 @@ class HomeDetailFragment @Inject constructor( viewModel.onEach(HomeDetailViewState::roomGroupingMethod) { roomGroupingMethod -> when (roomGroupingMethod) { - is RoomGroupingMethod.ByLegacyGroup -> { - onGroupChange(roomGroupingMethod.groupSummary) - } - is RoomGroupingMethod.BySpace -> { - onSpaceChange(roomGroupingMethod.spaceSummary) - } + is RoomGroupingMethod.ByLegacyGroup -> onGroupChange(roomGroupingMethod.groupSummary) + is RoomGroupingMethod.BySpace -> onSpaceChange(roomGroupingMethod.spaceSummary) } } @@ -147,6 +148,10 @@ class HomeDetailFragment @Inject constructor( updateTabVisibilitySafely(R.id.bottom_action_dial_pad, showDialPadTab) } + views.groupToolbarNavigateUp.setOnClickListener { + navigateUpOneParentSpace() + } + viewModel.observeViewEvents { viewEvent -> when (viewEvent) { HomeDetailViewEvents.CallStarted -> handleCallStarted() @@ -157,7 +162,6 @@ class HomeDetailFragment @Inject constructor( unknownDeviceDetectorSharedViewModel.onEach { state -> state.unknownSessions.invoke()?.let { unknownDevices -> -// Timber.v("## Detector Triggerred in fragment - ${unknownDevices.firstOrNull()}") if (unknownDevices.firstOrNull()?.currentSessionTrust == true) { val uid = "review_login" alertManager.cancelAlert(uid) @@ -190,6 +194,15 @@ class HomeDetailFragment @Inject constructor( } } + private fun navigateUpOneParentSpace() = with(appStateHandler) { + val parentId = when (val roomGroupingMethod = getCurrentRoomGroupingMethod()) { + is RoomGroupingMethod.BySpace -> roomGroupingMethod.spaceSummary?.flattenParentIds?.firstOrNull { it.isNotBlank() } + else -> null + } + setCurrentSpace(parentId) + sharedActionViewModel.post(HomeActivitySharedAction.CloseGroup) + } + private fun handleCallStarted() { dismissLoadingDialog() val fragmentTag = HomeTab.DialPad.toFragmentTag() @@ -203,20 +216,16 @@ class HomeDetailFragment @Inject constructor( override fun onResume() { super.onResume() - // update notification tab if needed updateTabVisibilitySafely(R.id.bottom_action_notification, vectorPreferences.labAddNotificationTab()) callManager.checkForProtocolsSupportIfNeeded() + refreshSpaceState() + } - // Current space/group is not live so at least refresh toolbar on resume - appStateHandler.getCurrentRoomGroupingMethod()?.let { roomGroupingMethod -> - when (roomGroupingMethod) { - is RoomGroupingMethod.ByLegacyGroup -> { - onGroupChange(roomGroupingMethod.groupSummary) - } - is RoomGroupingMethod.BySpace -> { - onSpaceChange(roomGroupingMethod.spaceSummary) - } - } + private fun refreshSpaceState() { + when (val roomGroupingMethod = appStateHandler.getCurrentRoomGroupingMethod()) { + is RoomGroupingMethod.ByLegacyGroup -> onGroupChange(roomGroupingMethod.groupSummary) + is RoomGroupingMethod.BySpace -> onSpaceChange(roomGroupingMethod.spaceSummary) + else -> Unit } } @@ -260,12 +269,12 @@ class HomeDetailFragment @Inject constructor( viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer) colorInt = colorProvider.getColorFromAttribute(R.attr.colorPrimary) contentAction = Runnable { - (weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let { + (weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let { activity -> // mark as ignored to avoid showing it again unknownDeviceDetectorSharedViewModel.handle( UnknownDeviceDetectorSharedViewModel.Action.IgnoreDevice(oldUnverified.mapNotNull { it.deviceId }) ) - it.navigator.openSettings(it, EXTRA_DIRECT_ACCESS_SECURITY_PRIVACY_MANAGE_SESSIONS) + activity.navigator.openSettings(activity, EXTRA_DIRECT_ACCESS_SECURITY_PRIVACY_MANAGE_SESSIONS) } } dismissedAction = Runnable { @@ -289,9 +298,13 @@ class HomeDetailFragment @Inject constructor( private fun onSpaceChange(spaceSummary: RoomSummary?) { if (spaceSummary == null) { views.groupToolbarSpaceTitleView.isVisible = false + views.groupToolbarAvatarImageView.isVisible = true + views.groupToolbarNavigateUp.isVisible = false } else { views.groupToolbarSpaceTitleView.isVisible = true views.groupToolbarSpaceTitleView.text = spaceSummary.displayName + views.groupToolbarAvatarImageView.isVisible = false + views.groupToolbarNavigateUp.isVisible = true } } @@ -324,11 +337,11 @@ class HomeDetailFragment @Inject constructor( withState(viewModel) { when (it.roomGroupingMethod) { is RoomGroupingMethod.ByLegacyGroup -> { - // nothing do far + // do nothing } is RoomGroupingMethod.BySpace -> { - it.roomGroupingMethod.spaceSummary?.let { - sharedActionViewModel.post(HomeActivitySharedAction.ShowSpaceSettings(it.roomId)) + it.roomGroupingMethod.spaceSummary?.let { spaceSummary -> + sharedActionViewModel.post(HomeActivitySharedAction.ShowSpaceSettings(spaceSummary.roomId)) } } } @@ -348,17 +361,6 @@ class HomeDetailFragment @Inject constructor( viewModel.handle(HomeDetailAction.SwitchTab(tab)) true } - -// val menuView = bottomNavigationView.getChildAt(0) as BottomNavigationMenuView - -// bottomNavigationView.getOrCreateBadge() -// menuView.forEachIndexed { index, view -> -// val itemView = view as BottomNavigationItemView -// val badgeLayout = LayoutInflater.from(requireContext()).inflate(R.layout.vector_home_badge_unread_layout, menuView, false) -// val unreadCounterBadgeView: UnreadCounterBadgeView = badgeLayout.findViewById(R.id.actionUnreadCounterBadgeView) -// itemView.addView(badgeLayout) -// unreadCounterBadgeViews.add(index, unreadCounterBadgeView) -// } } private fun updateUIForTab(tab: HomeTab) { diff --git a/vector/src/main/res/drawable/ic_arrow_back.xml b/vector/src/main/res/drawable/ic_arrow_back.xml new file mode 100644 index 0000000000..8452791cfd --- /dev/null +++ b/vector/src/main/res/drawable/ic_arrow_back.xml @@ -0,0 +1,5 @@ + + + diff --git a/vector/src/main/res/layout/fragment_home_detail.xml b/vector/src/main/res/layout/fragment_home_detail.xml index a53f001125..c734f55a4e 100644 --- a/vector/src/main/res/layout/fragment_home_detail.xml +++ b/vector/src/main/res/layout/fragment_home_detail.xml @@ -38,6 +38,7 @@ android:layout_height="40dp" android:layout_marginTop="8dp" android:layout_marginBottom="8dp" + android:visibility="gone" android:contentDescription="@string/a11y_open_drawer" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -74,6 +75,20 @@ + + - \ No newline at end of file + diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 3e6bdad70b..c0421c7d6c 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1777,6 +1777,7 @@ Send attachment Open the navigation drawer + Navigate up one space Open the create room menu Close the create room menu… Create a new direct conversation From bc500a567a96a1fe6611b18c29c344ec52f03a03 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Tue, 17 May 2022 11:28:37 +0200 Subject: [PATCH 029/244] Adds back button implementation of navigating up spaces --- .../app/features/home/HomeDetailFragment.kt | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt index 9ab1ad60e7..f7266db214 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt @@ -33,6 +33,7 @@ import im.vector.app.R import im.vector.app.RoomGroupingMethod import im.vector.app.core.extensions.commitTransaction import im.vector.app.core.extensions.toMvRxBundle +import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.resources.ColorProvider @@ -60,11 +61,6 @@ import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject -/* - * TODO: - * 1) Change the hamburger menu to a back button when in a space - * 2) Make the back navigation button follow the same behaviour - */ class HomeDetailFragment @Inject constructor( private val avatarRenderer: AvatarRenderer, private val colorProvider: ColorProvider, @@ -74,7 +70,8 @@ class HomeDetailFragment @Inject constructor( private val appStateHandler: AppStateHandler ) : VectorBaseFragment(), KeysBackupBanner.Delegate, - CurrentCallsView.Callback { + CurrentCallsView.Callback, + OnBackPressed { private val viewModel: HomeDetailViewModel by fragmentViewModel() private val unknownDeviceDetectorSharedViewModel: UnknownDeviceDetectorSharedViewModel by activityViewModel() @@ -149,7 +146,7 @@ class HomeDetailFragment @Inject constructor( } views.groupToolbarNavigateUp.setOnClickListener { - navigateUpOneParentSpace() + navigateUpOneSpace() } viewModel.observeViewEvents { viewEvent -> @@ -194,15 +191,14 @@ class HomeDetailFragment @Inject constructor( } } - private fun navigateUpOneParentSpace() = with(appStateHandler) { - val parentId = when (val roomGroupingMethod = getCurrentRoomGroupingMethod()) { - is RoomGroupingMethod.BySpace -> roomGroupingMethod.spaceSummary?.flattenParentIds?.firstOrNull { it.isNotBlank() } - else -> null - } - setCurrentSpace(parentId) + private fun navigateUpOneSpace() { + val parentId = getCurrentSpace()?.flattenParentIds?.lastOrNull() + appStateHandler.setCurrentSpace(parentId) sharedActionViewModel.post(HomeActivitySharedAction.CloseGroup) } + private fun getCurrentSpace() = (appStateHandler.getCurrentRoomGroupingMethod() as? RoomGroupingMethod.BySpace)?.spaceSummary + private fun handleCallStarted() { dismissLoadingDialog() val fragmentTag = HomeTab.DialPad.toFragmentTag() @@ -438,7 +434,6 @@ class HomeDetailFragment @Inject constructor( } override fun invalidate() = withState(viewModel) { -// Timber.v(it.toString()) views.bottomNavigationView.getOrCreateBadge(R.id.bottom_action_people).render(it.notificationCountPeople, it.notificationHighlightPeople) views.bottomNavigationView.getOrCreateBadge(R.id.bottom_action_rooms).render(it.notificationCountRooms, it.notificationHighlightRooms) views.bottomNavigationView.getOrCreateBadge(R.id.bottom_action_notification).render(it.notificationCountCatchup, it.notificationHighlightCatchup) @@ -498,4 +493,11 @@ class HomeDetailFragment @Inject constructor( } return this } + + override fun onBackPressed(toolbarButton: Boolean) = if (getCurrentSpace() != null) { + navigateUpOneSpace() + true + } else { + false + } } From 520c3e474cf1a39dfb4cad36edfd87620bae6f47 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Tue, 17 May 2022 12:02:29 +0200 Subject: [PATCH 030/244] Adds changelog file --- changelog.d/6073.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6073.feature diff --git a/changelog.d/6073.feature b/changelog.d/6073.feature new file mode 100644 index 0000000000..295f45f3ce --- /dev/null +++ b/changelog.d/6073.feature @@ -0,0 +1 @@ +Adds up navigation in spaces From 4adaa20f728d72bb0847c9107d44c7f09458060d Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Tue, 17 May 2022 12:16:45 +0200 Subject: [PATCH 031/244] Fixes default visibilities in fragment_home_detail --- vector/src/main/res/layout/fragment_home_detail.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vector/src/main/res/layout/fragment_home_detail.xml b/vector/src/main/res/layout/fragment_home_detail.xml index c734f55a4e..301abef4b8 100644 --- a/vector/src/main/res/layout/fragment_home_detail.xml +++ b/vector/src/main/res/layout/fragment_home_detail.xml @@ -38,7 +38,6 @@ android:layout_height="40dp" android:layout_marginTop="8dp" android:layout_marginBottom="8dp" - android:visibility="gone" android:contentDescription="@string/a11y_open_drawer" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -82,7 +81,7 @@ android:src="@drawable/ic_arrow_back" android:layout_marginEnd="8dp" android:contentDescription="@string/a11y_navigate_up_space" - android:visibility="visible" + android:visibility="gone" app:tint="?vctr_content_secondary" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" From 03acf4505acba15f48ae9e8783829aa4087e0c61 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Tue, 17 May 2022 18:03:34 +0200 Subject: [PATCH 032/244] Uses second layout to center room summary item title --- .../home/room/list/RoomSummaryItem.kt | 7 - .../home/room/list/RoomSummaryItemCentered.kt | 134 +++++++++++++++ .../home/room/list/RoomSummaryItemFactory.kt | 91 ++++++++--- vector/src/main/res/layout/item_room.xml | 18 +-- .../main/res/layout/item_room_centered.xml | 152 ++++++++++++++++++ 5 files changed, 355 insertions(+), 47 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemCentered.kt create mode 100644 vector/src/main/res/layout/item_room_centered.xml diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt index abcfe0d5d8..5452b03992 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt @@ -19,7 +19,6 @@ package im.vector.app.features.home.room.list import android.view.HapticFeedbackConstants import android.view.View import android.widget.ImageView -import android.widget.Space import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isInvisible @@ -141,11 +140,6 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { private fun renderForFilteredDisplayMode(holder: Holder) { holder.subtitleView.text = subtitle - holder.centerTitle(shouldCenter = subtitle.isEmpty()) - } - - private fun Holder.centerTitle(shouldCenter: Boolean) { - centerTitleSpace.isVisible = shouldCenter } override fun unbind(holder: Holder) { @@ -182,6 +176,5 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { val roomAvatarFailSendingImageView by bind(R.id.roomAvatarFailSendingImageView) val roomAvatarPresenceImageView by bind(R.id.roomAvatarPresenceImageView) val rootView by bind(R.id.itemRoomLayout) - val centerTitleSpace by bind(R.id.centerTitleSpace) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemCentered.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemCentered.kt new file mode 100644 index 0000000000..8f2d949178 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemCentered.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.home.room.list + +import android.view.HapticFeedbackConstants +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.isVisible +import com.airbnb.epoxy.EpoxyAttribute +import com.airbnb.epoxy.EpoxyModelClass +import com.amulyakhare.textdrawable.TextDrawable +import im.vector.app.R +import im.vector.app.core.epoxy.ClickListener +import im.vector.app.core.epoxy.VectorEpoxyHolder +import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.core.epoxy.onClick +import im.vector.app.core.ui.views.PresenceStateImageView +import im.vector.app.core.ui.views.ShieldImageView +import im.vector.app.features.displayname.getBestName +import im.vector.app.features.home.AvatarRenderer +import im.vector.app.features.home.RoomListDisplayMode +import im.vector.app.features.themes.ThemeUtils +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel +import org.matrix.android.sdk.api.session.presence.model.UserPresence +import org.matrix.android.sdk.api.util.MatrixItem + +@EpoxyModelClass(layout = R.layout.item_room_centered) +abstract class RoomSummaryItemCentered : VectorEpoxyModel() { + + @EpoxyAttribute + lateinit var avatarRenderer: AvatarRenderer + + @EpoxyAttribute + lateinit var matrixItem: MatrixItem + + @EpoxyAttribute + var displayMode: RoomListDisplayMode = RoomListDisplayMode.PEOPLE + + @EpoxyAttribute + var encryptionTrustLevel: RoomEncryptionTrustLevel? = null + + @EpoxyAttribute + var userPresence: UserPresence? = null + + @EpoxyAttribute + var showPresence: Boolean = false + + @EpoxyAttribute @JvmField + var isPublic: Boolean = false + + @EpoxyAttribute + var unreadNotificationCount: Int = 0 + + @EpoxyAttribute + var hasUnreadMessage: Boolean = false + + @EpoxyAttribute + var hasDraft: Boolean = false + + @EpoxyAttribute + var hasFailedSending: Boolean = false + + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) + var itemLongClickListener: View.OnLongClickListener? = null + + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) + var itemClickListener: ClickListener? = null + + @EpoxyAttribute + var showSelected: Boolean = false + + override fun bind(holder: Holder) { + super.bind(holder) + + holder.rootView.onClick(itemClickListener) + holder.rootView.setOnLongClickListener { + it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) + itemLongClickListener?.onLongClick(it) ?: false + } + holder.titleView.text = matrixItem.getBestName() + avatarRenderer.render(matrixItem, holder.avatarImageView) + holder.roomAvatarDecorationImageView.render(encryptionTrustLevel) + holder.roomAvatarPublicDecorationImageView.isVisible = isPublic + holder.roomAvatarFailSendingImageView.isVisible = hasFailedSending + renderSelection(holder, showSelected) + holder.roomAvatarPresenceImageView.render(showPresence, userPresence) + } + + override fun unbind(holder: Holder) { + holder.rootView.setOnClickListener(null) + holder.rootView.setOnLongClickListener(null) + avatarRenderer.clear(holder.avatarImageView) + super.unbind(holder) + } + + private fun renderSelection(holder: Holder, isSelected: Boolean) { + if (isSelected) { + holder.avatarCheckedImageView.visibility = View.VISIBLE + val backgroundColor = ThemeUtils.getColor(holder.view.context, R.attr.colorPrimary) + val backgroundDrawable = TextDrawable.builder().buildRound("", backgroundColor) + holder.avatarImageView.setImageDrawable(backgroundDrawable) + } else { + holder.avatarCheckedImageView.visibility = View.GONE + avatarRenderer.render(matrixItem, holder.avatarImageView) + } + } + + class Holder : VectorEpoxyHolder() { + val titleView by bind(R.id.roomNameView) + val avatarCheckedImageView by bind(R.id.roomAvatarCheckedImageView) + val avatarImageView by bind(R.id.roomAvatarImageView) + val roomAvatarDecorationImageView by bind(R.id.roomAvatarDecorationImageView) + val roomAvatarPublicDecorationImageView by bind(R.id.roomAvatarPublicDecorationImageView) + val roomAvatarFailSendingImageView by bind(R.id.roomAvatarFailSendingImageView) + val roomAvatarPresenceImageView by bind(R.id.roomAvatarPresenceImageView) + val rootView by bind(R.id.itemRoomLayout) + } +} diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt index 05701b908f..792303eaf6 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt @@ -126,31 +126,74 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor } val typingMessage = typingHelper.getTypingMessage(roomSummary.typingUsers) - return RoomSummaryItem_() - .id(roomSummary.roomId) - .avatarRenderer(avatarRenderer) - // We do not display shield in the room list anymore - // .encryptionTrustLevel(roomSummary.roomEncryptionTrustLevel) - .displayMode(displayMode) - .subtitle(subtitle) - .isPublic(roomSummary.isPublic) - .showPresence(roomSummary.isDirect) - .userPresence(roomSummary.directUserPresence) - .matrixItem(roomSummary.toMatrixItem()) - .lastEventTime(latestEventTime) - .typingMessage(typingMessage) - .lastFormattedEvent(latestFormattedEvent.toEpoxyCharSequence()) - .showHighlighted(showHighlighted) - .showSelected(showSelected) - .hasFailedSending(roomSummary.hasFailedSending) - .unreadNotificationCount(unreadCount) - .hasUnreadMessage(roomSummary.hasUnreadMessages) - .hasDraft(roomSummary.userDrafts.isNotEmpty()) - .itemLongClickListener { _ -> - onLongClick?.invoke(roomSummary) ?: false - } - .itemClickListener { onClick?.invoke(roomSummary) } + + return if (subtitle.isBlank() && displayMode == RoomListDisplayMode.FILTERED) { + createCenteredRoomSummaryItem(roomSummary, displayMode, showSelected, unreadCount, onClick, onLongClick) + } else { + createRoomSummaryItem(roomSummary, displayMode, subtitle, latestEventTime, typingMessage, + latestFormattedEvent, showHighlighted, showSelected, unreadCount, onClick, onLongClick) + } } + + private fun createRoomSummaryItem( + roomSummary: RoomSummary, + displayMode: RoomListDisplayMode, + subtitle: String, + latestEventTime: String, + typingMessage: String, + latestFormattedEvent: CharSequence, + showHighlighted: Boolean, + showSelected: Boolean, + unreadCount: Int, + onClick: ((RoomSummary) -> Unit)?, + onLongClick: ((RoomSummary) -> Boolean)? + ) = RoomSummaryItem_() + .id(roomSummary.roomId) + .avatarRenderer(avatarRenderer) + // We do not display shield in the room list anymore + // .encryptionTrustLevel(roomSummary.roomEncryptionTrustLevel) + .displayMode(displayMode) + .subtitle(subtitle) + .isPublic(roomSummary.isPublic) + .showPresence(roomSummary.isDirect) + .userPresence(roomSummary.directUserPresence) + .matrixItem(roomSummary.toMatrixItem()) + .lastEventTime(latestEventTime) + .typingMessage(typingMessage) + .lastFormattedEvent(latestFormattedEvent.toEpoxyCharSequence()) + .showHighlighted(showHighlighted) + .showSelected(showSelected) + .hasFailedSending(roomSummary.hasFailedSending) + .unreadNotificationCount(unreadCount) + .hasUnreadMessage(roomSummary.hasUnreadMessages) + .hasDraft(roomSummary.userDrafts.isNotEmpty()) + .itemLongClickListener { _ -> onLongClick?.invoke(roomSummary) ?: false } + .itemClickListener { onClick?.invoke(roomSummary) } + + private fun createCenteredRoomSummaryItem( + roomSummary: RoomSummary, + displayMode: RoomListDisplayMode, + showSelected: Boolean, + unreadCount: Int, + onClick: ((RoomSummary) -> Unit)?, + onLongClick: ((RoomSummary) -> Boolean)? + ) = RoomSummaryItemCentered_() + .id(roomSummary.roomId) + .avatarRenderer(avatarRenderer) + // We do not display shield in the room list anymore + // .encryptionTrustLevel(roomSummary.roomEncryptionTrustLevel) + .displayMode(displayMode) + .isPublic(roomSummary.isPublic) + .showPresence(roomSummary.isDirect) + .userPresence(roomSummary.directUserPresence) + .matrixItem(roomSummary.toMatrixItem()) + .showSelected(showSelected) + .hasFailedSending(roomSummary.hasFailedSending) + .unreadNotificationCount(unreadCount) + .hasUnreadMessage(roomSummary.hasUnreadMessages) + .hasDraft(roomSummary.userDrafts.isNotEmpty()) + .itemLongClickListener { _ -> onLongClick?.invoke(roomSummary) ?: false } + .itemClickListener { onClick?.invoke(roomSummary) } private fun getSearchResultSubtitle(roomSummary: RoomSummary): String { val userId = roomSummary.directUserId diff --git a/vector/src/main/res/layout/item_room.xml b/vector/src/main/res/layout/item_room.xml index ac028ccb08..ab0af18acb 100644 --- a/vector/src/main/res/layout/item_room.xml +++ b/vector/src/main/res/layout/item_room.xml @@ -112,27 +112,13 @@ app:layout_constraintTop_toBottomOf="@id/roomAvatarContainer" tools:layout_marginStart="20dp" /> - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From d12ab175163fe4f8e58a0c25cc941c042aaf0848 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Wed, 18 May 2022 11:29:23 +0200 Subject: [PATCH 033/244] Fixes lint errors --- .../app/features/home/room/list/RoomSummaryItemFactory.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt index 792303eaf6..3f29c1d14c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt @@ -130,11 +130,13 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor return if (subtitle.isBlank() && displayMode == RoomListDisplayMode.FILTERED) { createCenteredRoomSummaryItem(roomSummary, displayMode, showSelected, unreadCount, onClick, onLongClick) } else { - createRoomSummaryItem(roomSummary, displayMode, subtitle, latestEventTime, typingMessage, - latestFormattedEvent, showHighlighted, showSelected, unreadCount, onClick, onLongClick) + createRoomSummaryItem( + roomSummary, displayMode, subtitle, latestEventTime, typingMessage, + latestFormattedEvent, showHighlighted, showSelected, unreadCount, onClick, onLongClick + ) } } - + private fun createRoomSummaryItem( roomSummary: RoomSummary, displayMode: RoomListDisplayMode, From 388e35e828afcea811156f1959763107fd1b04e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Wed, 18 May 2022 14:19:11 +0200 Subject: [PATCH 034/244] Remove even more deps --- build.gradle | 4 +++- library/jsonviewer/build.gradle | 2 +- matrix-sdk-android-flow/build.gradle | 3 --- vector-config/build.gradle | 4 ---- vector/build.gradle | 1 - 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index cf49f37809..79637f9756 100644 --- a/build.gradle +++ b/build.gradle @@ -41,7 +41,9 @@ plugins { id "org.jlleitschuh.gradle.ktlint" version "10.3.0" // Detekt id "io.gitlab.arturbosch.detekt" version "1.20.0" - id 'com.autonomousapps.dependency-analysis' version "1.0.0" + + // Dependency Analysis + id 'com.autonomousapps.dependency-analysis' version "1.2.1" } // https://github.com/jeremylong/DependencyCheck diff --git a/library/jsonviewer/build.gradle b/library/jsonviewer/build.gradle index 2110747feb..e1a3b0c9ee 100644 --- a/library/jsonviewer/build.gradle +++ b/library/jsonviewer/build.gradle @@ -52,6 +52,7 @@ dependencies { implementation libs.androidx.appCompat implementation libs.androidx.core + implementation libs.androidx.recyclerview implementation libs.airbnb.epoxy kapt libs.airbnb.epoxyProcessor @@ -60,7 +61,6 @@ dependencies { // Span utils implementation 'me.gujun.android:span:1.7' - implementation libs.google.material implementation libs.jetbrains.coroutinesCore implementation libs.jetbrains.coroutinesAndroid diff --git a/matrix-sdk-android-flow/build.gradle b/matrix-sdk-android-flow/build.gradle index fb69af2d82..6385e66abb 100644 --- a/matrix-sdk-android-flow/build.gradle +++ b/matrix-sdk-android-flow/build.gradle @@ -36,7 +36,4 @@ dependencies { implementation libs.jetbrains.coroutinesCore implementation libs.jetbrains.coroutinesAndroid implementation libs.androidx.lifecycleLivedata - - // Paging - implementation libs.androidx.pagingRuntimeKtx } diff --git a/vector-config/build.gradle b/vector-config/build.gradle index 4156e74274..95b6a6215d 100644 --- a/vector-config/build.gradle +++ b/vector-config/build.gradle @@ -1,6 +1,5 @@ plugins { id 'com.android.library' - id 'org.jetbrains.kotlin.android' } android { @@ -14,7 +13,4 @@ android { sourceCompatibility versions.sourceCompat targetCompatibility versions.targetCompat } - kotlinOptions { - jvmTarget = "11" - } } diff --git a/vector/build.gradle b/vector/build.gradle index c91b7b50b7..1c0a4718c4 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -370,7 +370,6 @@ dependencies { implementation libs.androidx.lifecycleProcess implementation libs.androidx.lifecycleRuntimeKtx - implementation libs.androidx.datastore implementation libs.androidx.datastorepreferences From 6c569e6f9d1739dee15ceb9ff2859b8cdab18ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Wed, 18 May 2022 18:22:36 +0200 Subject: [PATCH 035/244] Bring back a false positive --- matrix-sdk-android-flow/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/matrix-sdk-android-flow/build.gradle b/matrix-sdk-android-flow/build.gradle index 6385e66abb..fb69af2d82 100644 --- a/matrix-sdk-android-flow/build.gradle +++ b/matrix-sdk-android-flow/build.gradle @@ -36,4 +36,7 @@ dependencies { implementation libs.jetbrains.coroutinesCore implementation libs.jetbrains.coroutinesAndroid implementation libs.androidx.lifecycleLivedata + + // Paging + implementation libs.androidx.pagingRuntimeKtx } From 86663ec073870a2125e3f266761c5a9ed3ffc132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Wed, 18 May 2022 18:47:52 +0200 Subject: [PATCH 036/244] Fine tune dependency analysis, add CI workflow --- .github/workflows/quality.yml | 8 ++++++++ build.gradle | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index a97d532644..d7d3ceffcc 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -117,6 +117,8 @@ jobs: ${{ runner.os }}-gradle- - name: Lint analysis run: ./gradlew clean :vector:lint --stacktrace + - name: Dependency analysis + run: ./gradlew buildHealth - name: Upload reports if: always() uses: actions/upload-artifact@v3 @@ -124,6 +126,12 @@ jobs: name: lint-report path: | vector/build/reports/*.* + - name: Upload dependency analysis + if: always() + uses: actions/upload-artifact@v3 + with: + name: dependency-analysis + path: build/reports/dependency-analysis/build-health-report.txt # Lint for Gplay and Fdroid release APK apk-lint: diff --git a/build.gradle b/build.gradle index 79637f9756..fe71865ef1 100644 --- a/build.gradle +++ b/build.gradle @@ -234,7 +234,38 @@ dependencyAnalysis { } issues { all { - ignoreKtx(true) // default is false + ignoreKtx(true) + onUsedTransitiveDependencies { + // Transitively used dependencies that should be declared directly + severity("ignore") + } + onUnusedDependencies { + severity("fail") + } + onUnusedAnnotationProcessors { + severity("fail") + exclude("com.airbnb.android:epoxy-processor", "com.google.dagger:hilt-compiler") // False positives + } + } + project(":library:jsonviewer") { + onUnusedDependencies { + exclude("org.json:json") // Used in unit tests, overwrites the one bundled into Android + } + } + project(":library:ui-styles") { + onUnusedDependencies { + exclude("com.github.vector-im:PFLockScreen-Android") // False positive + } + } + project(":matrix-sdk-android") { + onUnusedDependencies { + exclude("io.reactivex.rxjava2:rxkotlin") // Transitively required for mocking realm as monarchy doesn't expose Rx + } + } + project(":matrix-sdk-android-flow") { + onUnusedDependencies { + exclude("androidx.paging:paging-runtime-ktx") // False positive + } } } } From 93264812c0cd07d93d26e1149adde918cba3a2a6 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 19 May 2022 10:20:46 +0200 Subject: [PATCH 037/244] Adds back navigation to spaces --- .../java/im/vector/app/AppStateHandler.kt | 14 ++++++++++--- .../app/features/home/HomeDetailFragment.kt | 21 +++++++++++++++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/vector/src/main/java/im/vector/app/AppStateHandler.kt b/vector/src/main/java/im/vector/app/AppStateHandler.kt index 1608d561bc..d44af53a55 100644 --- a/vector/src/main/java/im/vector/app/AppStateHandler.kt +++ b/vector/src/main/java/im/vector/app/AppStateHandler.kt @@ -72,6 +72,8 @@ class AppStateHandler @Inject constructor( val selectedRoomGroupingFlow = selectedSpaceDataSource.stream() + private val spaceBackstack = ArrayDeque() + fun getCurrentRoomGroupingMethod(): RoomGroupingMethod? { // XXX we should somehow make it live :/ just a work around // For example just after creating a space and switching to it the @@ -87,12 +89,16 @@ class AppStateHandler @Inject constructor( } } - fun setCurrentSpace(spaceId: String?, session: Session? = null, persistNow: Boolean = false) { + fun setCurrentSpace(spaceId: String?, session: Session? = null, persistNow: Boolean = false, isForwardNavigation: Boolean = true) { + val currentSpace = (selectedSpaceDataSource.currentValue?.orNull() as? RoomGroupingMethod.BySpace)?.space() val uSession = session ?: activeSessionHolder.getSafeActiveSession() ?: return - if (selectedSpaceDataSource.currentValue?.orNull() is RoomGroupingMethod.BySpace && - spaceId == selectedSpaceDataSource.currentValue?.orNull()?.space()?.roomId) return + if (currentSpace != null && spaceId == currentSpace.roomId) return val spaceSum = spaceId?.let { uSession.getRoomSummary(spaceId) } + if (isForwardNavigation) { + spaceBackstack.addLast(currentSpace?.roomId) + } + if (persistNow) { uiStateRepository.storeGroupingMethod(true, uSession.sessionId) uiStateRepository.storeSelectedSpace(spaceSum?.roomId, uSession.sessionId) @@ -151,6 +157,8 @@ class AppStateHandler @Inject constructor( }.launchIn(session.coroutineScope) } + fun getSpaceBackstack() = spaceBackstack + fun safeActiveSpaceId(): String? { return (selectedSpaceDataSource.currentValue?.orNull() as? RoomGroupingMethod.BySpace)?.spaceSummary?.roomId } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt index f7266db214..213c9fe193 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt @@ -146,7 +146,7 @@ class HomeDetailFragment @Inject constructor( } views.groupToolbarNavigateUp.setOnClickListener { - navigateUpOneSpace() + navigateBack() } viewModel.observeViewEvents { viewEvent -> @@ -191,10 +191,23 @@ class HomeDetailFragment @Inject constructor( } } + private fun navigateBack() { + try { + val lastSpace = appStateHandler.getSpaceBackstack().removeLast() + setCurrentSpace(lastSpace) + } catch (e: NoSuchElementException) { + navigateUpOneSpace() + } + } + + private fun setCurrentSpace(spaceId: String?) { + appStateHandler.setCurrentSpace(spaceId, isForwardNavigation = false) + sharedActionViewModel.post(HomeActivitySharedAction.CloseGroup) + } + private fun navigateUpOneSpace() { val parentId = getCurrentSpace()?.flattenParentIds?.lastOrNull() - appStateHandler.setCurrentSpace(parentId) - sharedActionViewModel.post(HomeActivitySharedAction.CloseGroup) + setCurrentSpace(parentId) } private fun getCurrentSpace() = (appStateHandler.getCurrentRoomGroupingMethod() as? RoomGroupingMethod.BySpace)?.spaceSummary @@ -495,7 +508,7 @@ class HomeDetailFragment @Inject constructor( } override fun onBackPressed(toolbarButton: Boolean) = if (getCurrentSpace() != null) { - navigateUpOneSpace() + navigateBack() true } else { false From c093b3476fc2a790fbefb4aaeef68f943f450d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Thu, 19 May 2022 10:57:06 +0200 Subject: [PATCH 038/244] Limit parallel Gradle tasks --- .github/workflows/quality.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index d7d3ceffcc..8b3d966e9b 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -118,7 +118,7 @@ jobs: - name: Lint analysis run: ./gradlew clean :vector:lint --stacktrace - name: Dependency analysis - run: ./gradlew buildHealth + run: ./gradlew buildHealth --max-workers=1 - name: Upload reports if: always() uses: actions/upload-artifact@v3 From 464735f82995fce3657bb9a5c741591da4158e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Thu, 19 May 2022 11:31:32 +0200 Subject: [PATCH 039/244] Move dependency analysis to its own job --- .github/workflows/quality.yml | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 8b3d966e9b..d51d732a3b 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -97,6 +97,25 @@ jobs: comment_id: ${{ steps.fc.outputs.comment-id }} }) +# Gradle dependency analysis using https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin + dependency-analysis: + name: Dependency analysis + runs-on: ubuntu-latest + # Allow all jobs on main and develop. Just one per PR. + concurrency: + group: ${{ github.ref == 'refs/heads/main' && format('ktlint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('ktlint-develop-{0}', github.sha) || format('ktlint-{0}', github.ref) }} + cancel-in-progress: true + steps: + - uses: actions/checkout@v3 + - name: Dependency analysis + run: ./gradlew buildHealth --max-workers=1 + - name: Upload dependency analysis + if: always() + uses: actions/upload-artifact@v3 + with: + name: dependency-analysis + path: build/reports/dependency-analysis/build-health-report.txt + # Lint for main module android-lint: name: Android Linter @@ -117,8 +136,6 @@ jobs: ${{ runner.os }}-gradle- - name: Lint analysis run: ./gradlew clean :vector:lint --stacktrace - - name: Dependency analysis - run: ./gradlew buildHealth --max-workers=1 - name: Upload reports if: always() uses: actions/upload-artifact@v3 @@ -126,12 +143,6 @@ jobs: name: lint-report path: | vector/build/reports/*.* - - name: Upload dependency analysis - if: always() - uses: actions/upload-artifact@v3 - with: - name: dependency-analysis - path: build/reports/dependency-analysis/build-health-report.txt # Lint for Gplay and Fdroid release APK apk-lint: From bc050d303044af1b42c5f5aada9a7ce0bb97fec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Thu, 19 May 2022 12:08:17 +0200 Subject: [PATCH 040/244] Tweak JVM memory settings --- .github/workflows/quality.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index d51d732a3b..84823906c7 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -5,6 +5,12 @@ on: push: branches: [ main, develop ] +# Enrich gradle.properties for CI/CD +env: + CI_GRADLE_ARG_PROPERTIES: > + -Porg.gradle.jvmargs=-Xmx4g + -Porg.gradle.parallel=false + jobs: check: name: Project Check Suite @@ -108,7 +114,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Dependency analysis - run: ./gradlew buildHealth --max-workers=1 + run: ./gradlew buildHealth $CI_GRADLE_ARG_PROPERTIES - name: Upload dependency analysis if: always() uses: actions/upload-artifact@v3 From 429094511897178045023f443a2eb541714f6b51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Thu, 19 May 2022 12:09:45 +0200 Subject: [PATCH 041/244] Enable parallelism --- .github/workflows/quality.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 84823906c7..ae6af06d86 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -9,7 +9,6 @@ on: env: CI_GRADLE_ARG_PROPERTIES: > -Porg.gradle.jvmargs=-Xmx4g - -Porg.gradle.parallel=false jobs: check: From bad62be49752c1352d0d27a7fc89614cbaecfc03 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 17:00:07 +0200 Subject: [PATCH 042/244] Use Kdoc format, else it's not extracted to the documentation by dokka --- .../crypto/keysbackup/KeysBackupState.kt | 42 +++++++++++++------ .../crypto/model/RoomEncryptionTrustLevel.kt | 16 +++++-- .../crypto/verification/VerificationMethod.kt | 12 ++++-- .../sdk/api/session/room/send/SendState.kt | 31 ++++++++++---- .../threads/ThreadNotificationState.kt | 15 ++++--- 5 files changed, 85 insertions(+), 31 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupState.kt index a4cc133398..c4392ef9f1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupState.kt @@ -51,33 +51,51 @@ package org.matrix.android.sdk.api.session.crypto.keysbackup * */ enum class KeysBackupState { - // Need to check the current backup version on the homeserver + /** + * Need to check the current backup version on the homeserver + */ Unknown, - // Checking if backup is enabled on homeserver + /** + * Checking if backup is enabled on homeserver + */ CheckingBackUpOnHomeserver, - // Backup has been stopped because a new backup version has been detected on the homeserver + /** + * Backup has been stopped because a new backup version has been detected on the homeserver + */ WrongBackUpVersion, - // Backup from this device is not enabled + /** + * Backup from this device is not enabled + */ Disabled, - // There is a backup available on the homeserver but it is not trusted. - // It is not trusted because the signature is invalid or the device that created it is not verified - // Use [KeysBackup.getKeysBackupTrust()] to get trust details. - // Consequently, the backup from this device is not enabled. + /** + * There is a backup available on the homeserver but it is not trusted. + * It is not trusted because the signature is invalid or the device that created it is not verified + * Use [KeysBackup.getKeysBackupTrust()] to get trust details. + * Consequently, the backup from this device is not enabled. + */ NotTrusted, - // Backup is being enabled: the backup version is being created on the homeserver + /** + * Backup is being enabled: the backup version is being created on the homeserver + */ Enabling, - // Backup is enabled and ready to send backup to the homeserver + /** + * Backup is enabled and ready to send backup to the homeserver + */ ReadyToBackUp, - // e2e keys are going to be sent to the homeserver + /** + * e2e keys are going to be sent to the homeserver + */ WillBackUp, - // e2e keys are being sent to the homeserver + /** + * e2e keys are being sent to the homeserver + */ BackingUp } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt index 68c7496d58..d030988303 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt @@ -20,15 +20,23 @@ package org.matrix.android.sdk.api.session.crypto.model * RoomEncryptionTrustLevel represents the trust level in an encrypted room. */ enum class RoomEncryptionTrustLevel { - // No one in the room has been verified -> Black shield + /** + * No one in the room has been verified -> Black shield + */ Default, - // There are one or more device un-verified -> the app should display a red shield + /** + * There are one or more device un-verified -> the app should display a red shield + */ Warning, - // All devices in the room are verified -> the app should display a green shield + /** + * All devices in the room are verified -> the app should display a green shield + */ Trusted, - // e2e is active but with an unsupported algorithm + /** + * e2e is active but with an unsupported algorithm + */ E2EWithUnsupportedAlgorithm } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt index f2de2c4b47..b3758c364b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt @@ -20,12 +20,18 @@ package org.matrix.android.sdk.api.session.crypto.verification * Verification methods. */ enum class VerificationMethod { - // Use it when your application supports the SAS verification method + /** + * Use it when your application supports the SAS verification method + */ SAS, - // Use it if your application is able to display QR codes + /** + * Use it if your application is able to display QR codes + */ QR_CODE_SHOW, - // Use it if your application is able to scan QR codes + /** + * Use it if your application is able to scan QR codes + */ QR_CODE_SCAN } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt index 7c806bf35b..bb4a649a95 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt @@ -17,27 +17,44 @@ package org.matrix.android.sdk.api.session.room.send enum class SendState { + /** + * The state is unknown + */ UNKNOWN, - // the event has not been sent + /** + * The event has not been sent + */ UNSENT, - // the event is encrypting + /** + * The event is encrypting + */ ENCRYPTING, - // the event is currently sending + /** + * The event is currently sending + */ SENDING, - // the event has been sent + /** + * The event has been sent + */ SENT, - // the event has been received from server + /** + * The event has been received from server + */ SYNCED, - // The event failed to be sent + /** + * The event failed to be sent + */ UNDELIVERED, - // the event failed to be sent because some unknown devices have been found while encrypting it + /** + * The event failed to be sent because some unknown devices have been found while encrypting it + */ FAILED_UNKNOWN_DEVICES; internal companion object { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt index c110802d23..226e7cc12e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt @@ -20,14 +20,19 @@ package org.matrix.android.sdk.api.session.threads * This class defines the state of a thread notification. */ enum class ThreadNotificationState { - - // There are no new message + /** + * There are no new message + */ NO_NEW_MESSAGE, - // There is at least one new message + /** + * There is at least one new message + */ NEW_MESSAGE, - // The is at least one new message that should be highlighted - // ex. "Hello @aris.kotsomitopoulos" + /** + * The is at least one new message that should be highlighted + * ex. "Hello @aris.kotsomitopoulos" + */ NEW_HIGHLIGHTED_MESSAGE; } From 96c825e265fd2f183f954760a6ed8d00fca47bca Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 17:25:58 +0200 Subject: [PATCH 043/244] Create _userstories package and add the 2 first user stories --- matrix-sdk-android/docs/packages.md | 4 +++ .../sdk/_userstories/Us000InitMatrix.kt | 28 +++++++++++++++++ .../android/sdk/_userstories/Us100SignIn.kt | 31 +++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us000InitMatrix.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us100SignIn.kt diff --git a/matrix-sdk-android/docs/packages.md b/matrix-sdk-android/docs/packages.md index ae7bee1b4e..98b0e0c034 100644 --- a/matrix-sdk-android/docs/packages.md +++ b/matrix-sdk-android/docs/packages.md @@ -1,3 +1,7 @@ +# Package org.matrix.android.sdk._userstories + +This package contains some user stories (**Us** prefix) of the SDK usage. You will find example of what it is possible to do with the SDK and the API which can be used to do it. + # Package org.matrix.android.sdk.api This is the root package of the API exposed by this SDK. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us000InitMatrix.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us000InitMatrix.kt new file mode 100644 index 0000000000..823a9522cf --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us000InitMatrix.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("unused") + +package org.matrix.android.sdk._userstories + +/** + * ### Title + * Init a Matrix object + * + * ### Required APIs: + * - [org.matrix.android.sdk.api.Matrix] constructor + */ +object Us000InitMatrix diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us100SignIn.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us100SignIn.kt new file mode 100644 index 0000000000..5344e19ae4 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us100SignIn.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("unused") + +package org.matrix.android.sdk._userstories + +/** + * ### Title + * Sign in to an existing account + * + * #### Required APIs: + * - [org.matrix.android.sdk.api.Matrix.authenticationService] + * - [org.matrix.android.sdk.api.auth.AuthenticationService.getLoginFlow] + * - [org.matrix.android.sdk.api.auth.AuthenticationService.getLoginWizard] + * - [org.matrix.android.sdk.api.auth.login.LoginWizard.login] + */ +object Us100SignIn From cfd645661435619ad1dc542e32eb3ce9e6de55ef Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 17:51:08 +0200 Subject: [PATCH 044/244] Add other user stories (with TODO) --- .../sdk/_userstories/Us150VerifySession.kt | 28 +++++++++++++++++++ .../android/sdk/_userstories/Us190SignOut.kt | 28 +++++++++++++++++++ .../android/sdk/_userstories/Us200RoomList.kt | 28 +++++++++++++++++++ .../sdk/_userstories/Us300RoomTimeline.kt | 28 +++++++++++++++++++ .../Us350RoomTimelineFromPermalink.kt | 28 +++++++++++++++++++ .../sdk/_userstories/Us400RoomSendContent.kt | 28 +++++++++++++++++++ .../sdk/_userstories/Us500Notification.kt | 28 +++++++++++++++++++ .../_userstories/Us600SyncWithTheServer.kt | 28 +++++++++++++++++++ 8 files changed, 224 insertions(+) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us150VerifySession.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us190SignOut.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us200RoomList.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us300RoomTimeline.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us350RoomTimelineFromPermalink.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us400RoomSendContent.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us500Notification.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us600SyncWithTheServer.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us150VerifySession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us150VerifySession.kt new file mode 100644 index 0000000000..59eb056cb0 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us150VerifySession.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("unused") + +package org.matrix.android.sdk._userstories + +/** + * ### Title + * Verify a Session after a Sign in + * + * #### Required APIs: + * - TODO + */ +object Us150VerifySession diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us190SignOut.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us190SignOut.kt new file mode 100644 index 0000000000..c9504e4a5e --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us190SignOut.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("unused") + +package org.matrix.android.sdk._userstories + +/** + * ### Title + * Sign out + * + * #### Required APIs: + * - TODO + */ +object Us190SignOut diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us200RoomList.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us200RoomList.kt new file mode 100644 index 0000000000..fa71b8cedf --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us200RoomList.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("unused") + +package org.matrix.android.sdk._userstories + +/** + * ### Title + * Get the Room list + * + * #### Required APIs: + * - TODO + */ +object Us200RoomList diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us300RoomTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us300RoomTimeline.kt new file mode 100644 index 0000000000..ce899f53f8 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us300RoomTimeline.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("unused") + +package org.matrix.android.sdk._userstories + +/** + * ### Title + * Display a Room timeline, and navigate backward and forward + * + * #### Required APIs: + * - TODO + */ +object Us300RoomTimeline diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us350RoomTimelineFromPermalink.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us350RoomTimelineFromPermalink.kt new file mode 100644 index 0000000000..6684d2b8f3 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us350RoomTimelineFromPermalink.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("unused") + +package org.matrix.android.sdk._userstories + +/** + * ### Title + * Display a Room timeline at a specific point + * + * #### Required APIs: + * - TODO + */ +object Us350RoomTimelineFromPermalink diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us400RoomSendContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us400RoomSendContent.kt new file mode 100644 index 0000000000..fcff950228 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us400RoomSendContent.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("unused") + +package org.matrix.android.sdk._userstories + +/** + * ### Title + * Send content to a room, including monitoring the sending state + * + * #### Required APIs: + * - TODO + */ +object Us400RoomSendContent diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us500Notification.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us500Notification.kt new file mode 100644 index 0000000000..a58f09a62c --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us500Notification.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("unused") + +package org.matrix.android.sdk._userstories + +/** + * ### Title + * Get notified when new Events are received + * + * #### Required APIs: + * - TODO + */ +object Us500Notification diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us600SyncWithTheServer.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us600SyncWithTheServer.kt new file mode 100644 index 0000000000..52973259fd --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us600SyncWithTheServer.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("unused") + +package org.matrix.android.sdk._userstories + +/** + * ### Title + * Manage the sync with the server + * + * #### Required APIs: + * - TODO + */ +object Us600SyncWithTheServer From e6c8ffd1b8330827a97b0c5214b9aa1a40ac804e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 18:07:31 +0200 Subject: [PATCH 045/244] Change `val` to `fun` on the SDK interfaces. Dokka will generate a better documentation (`Functions` and `Properties` are 2 distinct tab), and for Service it's better to have only `fun` --- .../sdk/api/auth/AuthenticationService.kt | 2 +- .../auth/registration/RegistrationWizard.kt | 8 ++++---- .../auth/DefaultAuthenticationService.kt | 3 +-- .../registration/DefaultRegistrationWizard.kt | 20 +++++++++---------- .../app/features/login/LoginViewModel.kt | 6 +++--- .../app/features/login2/LoginViewModel2.kt | 6 +++--- .../onboarding/OnboardingViewModel.kt | 6 +++--- 7 files changed, 24 insertions(+), 27 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt index 5a19df90c4..629d947bb3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt @@ -66,7 +66,7 @@ interface AuthenticationService { /** * True when login and password has been sent with success to the homeserver. */ - val isRegistrationStarted: Boolean + fun isRegistrationStarted(): Boolean /** * Cancel pending login or pending registration. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt index 0cda64499f..6100ae2a80 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt @@ -109,14 +109,14 @@ interface RegistrationWizard { suspend fun checkIfEmailHasBeenValidated(delayMillis: Long): RegistrationResult /** - * This is the current ThreePid, waiting for validation. The SDK will store it in database, so it can be + * Returns the current ThreePid, waiting for validation. The SDK will store it in database, so it can be * restored even if the app has been killed during the registration */ - val currentThreePid: String? + fun currentThreePid(): String? /** - * True when login and password have been sent with success to the homeserver, i.e. [createAccount] has been + * Return true when login and password have been sent with success to the homeserver, i.e. [createAccount] has been * called successfully. */ - val isRegistrationStarted: Boolean + fun isRegistrationStarted(): Boolean } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt index 02dfce04b5..fe78ccc75a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt @@ -323,8 +323,7 @@ internal class DefaultAuthenticationService @Inject constructor( } } - override val isRegistrationStarted: Boolean - get() = currentRegistrationWizard?.isRegistrationStarted == true + override fun isRegistrationStarted() = currentRegistrationWizard?.isRegistrationStarted() == true override fun getLoginWizard(): LoginWizard { return currentLoginWizard diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt index 8f00f3440c..03f54705fc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt @@ -49,20 +49,18 @@ internal class DefaultRegistrationWizard( private val validateCodeTask: ValidateCodeTask = DefaultValidateCodeTask(authAPI) private val registerCustomTask: RegisterCustomTask = DefaultRegisterCustomTask(authAPI) - override val currentThreePid: String? - get() { - return when (val threePid = pendingSessionData.currentThreePidData?.threePid) { - is RegisterThreePid.Email -> threePid.email - is RegisterThreePid.Msisdn -> { - // Take formatted msisdn if provided by the server - pendingSessionData.currentThreePidData?.addThreePidRegistrationResponse?.formattedMsisdn?.takeIf { it.isNotBlank() } ?: threePid.msisdn - } - null -> null + override fun currentThreePid(): String? { + return when (val threePid = pendingSessionData.currentThreePidData?.threePid) { + is RegisterThreePid.Email -> threePid.email + is RegisterThreePid.Msisdn -> { + // Take formatted msisdn if provided by the server + pendingSessionData.currentThreePidData?.addThreePidRegistrationResponse?.formattedMsisdn?.takeIf { it.isNotBlank() } ?: threePid.msisdn } + null -> null } + } - override val isRegistrationStarted: Boolean - get() = pendingSessionData.isRegistrationStarted + override fun isRegistrationStarted() = pendingSessionData.isRegistrationStarted override suspend fun getRegistrationFlow(): RegistrationResult { val params = RegistrationParams() diff --git a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt index 1b08d2a86f..ed9ec7b3b9 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt @@ -91,11 +91,11 @@ class LoginViewModel @AssistedInject constructor( private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() val currentThreePid: String? - get() = registrationWizard?.currentThreePid + get() = registrationWizard?.currentThreePid() // True when login and password has been sent with success to the homeserver val isRegistrationStarted: Boolean - get() = authenticationService.isRegistrationStarted + get() = authenticationService.isRegistrationStarted() private val registrationWizard: RegistrationWizard? get() = authenticationService.getRegistrationWizard() @@ -455,7 +455,7 @@ class LoginViewModel @AssistedInject constructor( // If there is a pending email validation continue on this step try { - if (registrationWizard?.isRegistrationStarted == true) { + if (registrationWizard?.isRegistrationStarted() == true) { currentThreePid?.let { handle(LoginAction.PostViewEvent(LoginViewEvents.OnSendEmailSuccess(it))) } diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt index 6b9d255937..1117c32d39 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt @@ -92,11 +92,11 @@ class LoginViewModel2 @AssistedInject constructor( private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() val currentThreePid: String? - get() = registrationWizard?.currentThreePid + get() = registrationWizard?.currentThreePid() // True when login and password has been sent with success to the homeserver val isRegistrationStarted: Boolean - get() = authenticationService.isRegistrationStarted + get() = authenticationService.isRegistrationStarted() private val registrationWizard: RegistrationWizard? get() = authenticationService.getRegistrationWizard() @@ -420,7 +420,7 @@ class LoginViewModel2 @AssistedInject constructor( // If there is a pending email validation continue on this step try { - if (registrationWizard?.isRegistrationStarted == true) { + if (registrationWizard?.isRegistrationStarted() == true) { currentThreePid?.let { handle(LoginAction2.PostViewEvent(LoginViewEvents2.OnSendEmailSuccess(it))) } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 03526b47a5..b247086dbf 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -114,11 +114,11 @@ class OnboardingViewModel @AssistedInject constructor( get() = authenticationService.getRegistrationWizard() val currentThreePid: String? - get() = registrationWizard.currentThreePid + get() = registrationWizard.currentThreePid() // True when login and password has been sent with success to the homeserver val isRegistrationStarted: Boolean - get() = authenticationService.isRegistrationStarted + get() = authenticationService.isRegistrationStarted() private val loginWizard: LoginWizard? get() = authenticationService.getLoginWizard() @@ -396,7 +396,7 @@ class OnboardingViewModel @AssistedInject constructor( // If there is a pending email validation continue on this step try { - if (registrationWizard.isRegistrationStarted) { + if (registrationWizard.isRegistrationStarted()) { currentThreePid?.let { handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnSendEmailSuccess(it))) } From 768df330b522d1d7bb2abbb0b27e9636031b526c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 18:08:28 +0200 Subject: [PATCH 046/244] Rename `currentThreePid` to `getCurrentThreePid` --- .../android/sdk/api/auth/registration/RegistrationWizard.kt | 2 +- .../sdk/internal/auth/registration/DefaultRegistrationWizard.kt | 2 +- .../main/java/im/vector/app/features/login/LoginViewModel.kt | 2 +- .../main/java/im/vector/app/features/login2/LoginViewModel2.kt | 2 +- .../im/vector/app/features/onboarding/OnboardingViewModel.kt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt index 6100ae2a80..14d26bf2b3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt @@ -112,7 +112,7 @@ interface RegistrationWizard { * Returns the current ThreePid, waiting for validation. The SDK will store it in database, so it can be * restored even if the app has been killed during the registration */ - fun currentThreePid(): String? + fun getCurrentThreePid(): String? /** * Return true when login and password have been sent with success to the homeserver, i.e. [createAccount] has been diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt index 03f54705fc..345f4097db 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt @@ -49,7 +49,7 @@ internal class DefaultRegistrationWizard( private val validateCodeTask: ValidateCodeTask = DefaultValidateCodeTask(authAPI) private val registerCustomTask: RegisterCustomTask = DefaultRegisterCustomTask(authAPI) - override fun currentThreePid(): String? { + override fun getCurrentThreePid(): String? { return when (val threePid = pendingSessionData.currentThreePidData?.threePid) { is RegisterThreePid.Email -> threePid.email is RegisterThreePid.Msisdn -> { diff --git a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt index ed9ec7b3b9..cacbd0e282 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt @@ -91,7 +91,7 @@ class LoginViewModel @AssistedInject constructor( private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() val currentThreePid: String? - get() = registrationWizard?.currentThreePid() + get() = registrationWizard?.getCurrentThreePid() // True when login and password has been sent with success to the homeserver val isRegistrationStarted: Boolean diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt index 1117c32d39..06388a04a0 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt @@ -92,7 +92,7 @@ class LoginViewModel2 @AssistedInject constructor( private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() val currentThreePid: String? - get() = registrationWizard?.currentThreePid() + get() = registrationWizard?.getCurrentThreePid() // True when login and password has been sent with success to the homeserver val isRegistrationStarted: Boolean diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index b247086dbf..f795b39c51 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -114,7 +114,7 @@ class OnboardingViewModel @AssistedInject constructor( get() = authenticationService.getRegistrationWizard() val currentThreePid: String? - get() = registrationWizard.currentThreePid() + get() = registrationWizard.getCurrentThreePid() // True when login and password has been sent with success to the homeserver val isRegistrationStarted: Boolean From d3d17ebbcb51ff170125b5cca1f82b0b206c2806 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 18:17:23 +0200 Subject: [PATCH 047/244] Extract HttpPusher to its own file --- .../sdk/api/session/pushers/HttpPusher.kt | 73 +++++++++++++++++++ .../sdk/api/session/pushers/PushersService.kt | 57 --------------- .../session/pushers/DefaultPushersService.kt | 7 +- .../vector/app/core/pushers/PushersManager.kt | 4 +- 4 files changed, 79 insertions(+), 62 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/HttpPusher.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/HttpPusher.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/HttpPusher.kt new file mode 100644 index 0000000000..1ae23e2b70 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/HttpPusher.kt @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.api.session.pushers + +data class HttpPusher( + /** + * This is a unique identifier for this pusher. The value you should use for + * this is the routing or destination address information for the notification, + * for example, the APNS token for APNS or the Registration ID for GCM. If your + * notification client has no such concept, use any unique identifier. Max length, 512 chars. + */ + val pushkey: String, + + /** + * The application id + * This is a reverse-DNS style identifier for the application. It is recommended + * that this end with the platform, such that different platform versions get + * different app identifiers. Max length, 64 chars. + */ + val appId: String, + + /** + * This string determines which set of device specific rules this pusher executes. + */ + val profileTag: String, + + /** + * The preferred language for receiving notifications (e.g. "en" or "en-US"). + */ + val lang: String, + + /** + * A human readable string that will allow the user to identify what application owns this pusher. + */ + val appDisplayName: String, + + /** + * A human readable string that will allow the user to identify what device owns this pusher. + */ + val deviceDisplayName: String, + + /** + * The URL to use to send notifications to. MUST be an HTTPS URL with a path of /_matrix/push/v1/notify. + */ + val url: String, + + /** + * If true, the homeserver should add another pusher with the given pushkey and App ID in addition + * to any others with different user IDs. Otherwise, the homeserver must remove any other pushers + * with the same App ID and pushkey for different users. + */ + val append: Boolean, + + /** + * true to limit the push content to only id and not message content + * Ref: https://matrix.org/docs/spec/push_gateway/r0.1.1#homeserver-behaviour + */ + val withEventIdOnly: Boolean +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt index 5cb7857021..396f13ce46 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt @@ -107,61 +107,4 @@ interface PushersService { * Get the current pushers. */ fun getPushers(): List - - data class HttpPusher( - - /** - * This is a unique identifier for this pusher. The value you should use for - * this is the routing or destination address information for the notification, - * for example, the APNS token for APNS or the Registration ID for GCM. If your - * notification client has no such concept, use any unique identifier. Max length, 512 chars. - */ - val pushkey: String, - - /** - * The application id - * This is a reverse-DNS style identifier for the application. It is recommended - * that this end with the platform, such that different platform versions get - * different app identifiers. Max length, 64 chars. - */ - val appId: String, - - /** - * This string determines which set of device specific rules this pusher executes. - */ - val profileTag: String, - - /** - * The preferred language for receiving notifications (e.g. "en" or "en-US"). - */ - val lang: String, - - /** - * A human readable string that will allow the user to identify what application owns this pusher. - */ - val appDisplayName: String, - - /** - * A human readable string that will allow the user to identify what device owns this pusher. - */ - val deviceDisplayName: String, - - /** - * The URL to use to send notifications to. MUST be an HTTPS URL with a path of /_matrix/push/v1/notify. - */ - val url: String, - - /** - * If true, the homeserver should add another pusher with the given pushkey and App ID in addition - * to any others with different user IDs. Otherwise, the homeserver must remove any other pushers - * with the same App ID and pushkey for different users. - */ - val append: Boolean, - - /** - * true to limit the push content to only id and not message content - * Ref: https://matrix.org/docs/spec/push_gateway/r0.1.1#homeserver-behaviour - */ - val withEventIdOnly: Boolean - ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt index 13b990a9ff..9437550d7a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.pushers import androidx.lifecycle.LiveData import androidx.work.BackoffPolicy import com.zhuinden.monarchy.Monarchy +import org.matrix.android.sdk.api.session.pushers.HttpPusher import org.matrix.android.sdk.api.session.pushers.Pusher import org.matrix.android.sdk.api.session.pushers.PushersService import org.matrix.android.sdk.internal.database.mapper.asDomain @@ -58,15 +59,15 @@ internal class DefaultPushersService @Inject constructor( .executeBy(taskExecutor) } - override fun enqueueAddHttpPusher(httpPusher: PushersService.HttpPusher): UUID { + override fun enqueueAddHttpPusher(httpPusher: HttpPusher): UUID { return enqueueAddPusher(httpPusher.toJsonPusher()) } - override suspend fun addHttpPusher(httpPusher: PushersService.HttpPusher) { + override suspend fun addHttpPusher(httpPusher: HttpPusher) { addPusherTask.execute(AddPusherTask.Params(httpPusher.toJsonPusher())) } - private fun PushersService.HttpPusher.toJsonPusher() = JsonPusher( + private fun HttpPusher.toJsonPusher() = JsonPusher( pushKey = pushkey, kind = "http", appId = appId, diff --git a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt index b1bb4c7d88..c89dc7a73c 100644 --- a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt @@ -21,7 +21,7 @@ import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.resources.AppNameProvider import im.vector.app.core.resources.LocaleProvider import im.vector.app.core.resources.StringProvider -import org.matrix.android.sdk.api.session.pushers.PushersService +import org.matrix.android.sdk.api.session.pushers.HttpPusher import java.util.UUID import javax.inject.Inject import kotlin.math.abs @@ -55,7 +55,7 @@ class PushersManager @Inject constructor( currentSession.pushersService().addHttpPusher(createHttpPusher(pushKey)) } - private fun createHttpPusher(pushKey: String) = PushersService.HttpPusher( + private fun createHttpPusher(pushKey: String) = HttpPusher( pushKey, stringProvider.getString(R.string.pusher_app_id), profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + abs(activeSessionHolder.getActiveSession().myUserId.hashCode()), From 1ab4ae9eac2b91e654b24370ad4cae95ca758bac Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 18:19:27 +0200 Subject: [PATCH 048/244] Extract KeyRef to its own file --- .../sdk/internal/crypto/ssss/QuadSTests.kt | 10 ++++----- .../sdk/api/session/securestorage/KeyRef.kt | 22 +++++++++++++++++++ .../SharedSecretStorageService.kt | 5 ----- .../DefaultSharedSecretStorageService.kt | 3 ++- .../recover/BackupToQuadSMigrationTask.kt | 4 ++-- .../recover/BootstrapCrossSigningTask.kt | 12 +++++----- .../fakes/FakeSharedSecretStorageService.kt | 3 ++- 7 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/KeyRef.kt diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt index c758050fc9..dbe6f076d6 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt @@ -31,11 +31,11 @@ import org.matrix.android.sdk.api.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2 import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent +import org.matrix.android.sdk.api.session.securestorage.KeyRef import org.matrix.android.sdk.api.session.securestorage.KeySigner import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec import org.matrix.android.sdk.api.session.securestorage.SecretStorageKeyContent import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageError -import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.toBase64NoPadding @@ -123,7 +123,7 @@ class QuadSTests : InstrumentedTest { aliceSession.sharedSecretStorageService().storeSecret( "secret.of.life", clearSecret, - listOf(SharedSecretStorageService.KeyRef(null, keySpec)) // default key + listOf(KeyRef(null, keySpec)) // default key ) } @@ -191,8 +191,8 @@ class QuadSTests : InstrumentedTest { "my.secret", mySecretText.toByteArray().toBase64NoPadding(), listOf( - SharedSecretStorageService.KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)), - SharedSecretStorageService.KeyRef(keyId2, RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey)) + KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)), + KeyRef(keyId2, RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey)) ) ) } @@ -241,7 +241,7 @@ class QuadSTests : InstrumentedTest { aliceSession.sharedSecretStorageService().storeSecret( "my.secret", mySecretText.toByteArray().toBase64NoPadding(), - listOf(SharedSecretStorageService.KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey))) + listOf(KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey))) ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/KeyRef.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/KeyRef.kt new file mode 100644 index 0000000000..5a1bf67fdd --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/KeyRef.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.api.session.securestorage + +data class KeyRef( + val keyId: String?, + val keySpec: SsssKeySpec? +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt index e3a9860523..929463563f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt @@ -132,9 +132,4 @@ interface SharedSecretStorageService { fun checkShouldBeAbleToAccessSecrets(secretNames: List, keyId: String?): IntegrityResult suspend fun requestSecret(name: String, myOtherDeviceId: String) - - data class KeyRef( - val keyId: String?, - val keySpec: SsssKeySpec? - ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt index 1ded9c6c7e..0daaec11a1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt @@ -30,6 +30,7 @@ import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent import org.matrix.android.sdk.api.session.securestorage.IntegrityResult import org.matrix.android.sdk.api.session.securestorage.KeyInfo import org.matrix.android.sdk.api.session.securestorage.KeyInfoResult +import org.matrix.android.sdk.api.session.securestorage.KeyRef import org.matrix.android.sdk.api.session.securestorage.KeySigner import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec import org.matrix.android.sdk.api.session.securestorage.SecretStorageKeyContent @@ -157,7 +158,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor( return getKey(keyId) } - override suspend fun storeSecret(name: String, secretBase64: String, keys: List) { + override suspend fun storeSecret(name: String, secretBase64: String, keys: List) { withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.computation) { val encryptedContents = HashMap() keys.forEach { diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BackupToQuadSMigrationTask.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BackupToQuadSMigrationTask.kt index e620500d70..5d866c7220 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BackupToQuadSMigrationTask.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BackupToQuadSMigrationTask.kt @@ -26,8 +26,8 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_S import org.matrix.android.sdk.api.session.crypto.keysbackup.computeRecoveryKey import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey import org.matrix.android.sdk.api.session.securestorage.EmptyKeySigner +import org.matrix.android.sdk.api.session.securestorage.KeyRef import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec -import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo import org.matrix.android.sdk.api.util.awaitCallback import org.matrix.android.sdk.api.util.toBase64NoPadding @@ -142,7 +142,7 @@ class BackupToQuadSMigrationTask @Inject constructor( quadS.storeSecret( KEYBACKUP_SECRET_SSSS_NAME, curveKey.toBase64NoPadding(), - listOf(SharedSecretStorageService.KeyRef(info.keyId, info.keySpec)) + listOf(KeyRef(info.keyId, info.keySpec)) ) // save for gossiping diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapCrossSigningTask.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapCrossSigningTask.kt index c26aec45dd..6926c0b30b 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapCrossSigningTask.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapCrossSigningTask.kt @@ -34,7 +34,7 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreation import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult import org.matrix.android.sdk.api.session.securestorage.EmptyKeySigner -import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService +import org.matrix.android.sdk.api.session.securestorage.KeyRef import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo import org.matrix.android.sdk.api.session.securestorage.SsssKeySpec import org.matrix.android.sdk.api.util.awaitCallback @@ -183,7 +183,7 @@ class BootstrapCrossSigningTask @Inject constructor( ssssService.storeSecret( MASTER_KEY_SSSS_NAME, mskPrivateKey, - listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec)) + listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec)) ) params.progressListener?.onProgress( WaitingViewData( @@ -195,7 +195,7 @@ class BootstrapCrossSigningTask @Inject constructor( ssssService.storeSecret( USER_SIGNING_KEY_SSSS_NAME, uskPrivateKey, - listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec)) + listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec)) ) params.progressListener?.onProgress( WaitingViewData( @@ -206,7 +206,7 @@ class BootstrapCrossSigningTask @Inject constructor( ssssService.storeSecret( SELF_SIGNING_KEY_SSSS_NAME, sskPrivateKey, - listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec)) + listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec)) ) } catch (failure: Failure) { Timber.e("## BootstrapCrossSigningTask: Creating 4S - Failed to store keys <${failure.localizedMessage}>") @@ -258,7 +258,7 @@ class BootstrapCrossSigningTask @Inject constructor( ssssService.storeSecret( KEYBACKUP_SECRET_SSSS_NAME, secret, - listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec)) + listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec)) ) } } else { @@ -275,7 +275,7 @@ class BootstrapCrossSigningTask @Inject constructor( ssssService.storeSecret( KEYBACKUP_SECRET_SSSS_NAME, secret, - listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec)) + listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec)) ) } } else { diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSharedSecretStorageService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSharedSecretStorageService.kt index c79a0be542..e81bd8f90e 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeSharedSecretStorageService.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSharedSecretStorageService.kt @@ -19,6 +19,7 @@ package im.vector.app.test.fakes import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.session.securestorage.IntegrityResult import org.matrix.android.sdk.api.session.securestorage.KeyInfoResult +import org.matrix.android.sdk.api.session.securestorage.KeyRef import org.matrix.android.sdk.api.session.securestorage.KeySigner import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageError import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService @@ -56,7 +57,7 @@ class FakeSharedSecretStorageService : SharedSecretStorageService { TODO("Not yet implemented") } - override suspend fun storeSecret(name: String, secretBase64: String, keys: List) { + override suspend fun storeSecret(name: String, secretBase64: String, keys: List) { TODO("Not yet implemented") } From ede784684f6be4ee8b2327c7b64667375b8e0046 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 18:58:41 +0200 Subject: [PATCH 049/244] Change in KeysBackupService: `isEnabled` and `isStucked` are now fun, and `state` has been renamed to `getState` and is now a fun. --- .../crypto/keysbackup/KeysBackupTest.kt | 66 +++++++++---------- .../crypto/keysbackup/KeysBackupTestHelper.kt | 6 +- .../crypto/keysbackup/KeysBackupService.kt | 9 ++- .../keysbackup/DefaultKeysBackupService.kt | 34 ++++------ .../im/vector/app/SecurityBootstrapTest.kt | 2 +- .../im/vector/app/core/extensions/Session.kt | 2 +- .../settings/KeysBackupSettingsViewModel.kt | 4 +- .../action/MessageActionsViewModel.kt | 4 +- .../signout/ServerBackupStatusViewModel.kt | 6 +- .../workers/signout/SignoutCheckViewModel.kt | 2 +- 10 files changed, 66 insertions(+), 69 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt index 9136272b1e..5c324852ee 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt @@ -113,7 +113,7 @@ class KeysBackupTest : InstrumentedTest { val stateObserver = StateObserver(keysBackup) - assertFalse(keysBackup.isEnabled) + assertFalse(keysBackup.isEnabled()) val megolmBackupCreationInfo = testHelper.doSync { keysBackup.prepareKeysBackupVersion(null, null, it) @@ -143,13 +143,13 @@ class KeysBackupTest : InstrumentedTest { val stateObserver = StateObserver(keysBackup) - assertFalse(keysBackup.isEnabled) + assertFalse(keysBackup.isEnabled()) val megolmBackupCreationInfo = testHelper.doSync { keysBackup.prepareKeysBackupVersion(null, null, it) } - assertFalse(keysBackup.isEnabled) + assertFalse(keysBackup.isEnabled()) // Create the version val version = testHelper.doSync { @@ -157,7 +157,7 @@ class KeysBackupTest : InstrumentedTest { } // Backup must be enable now - assertTrue(keysBackup.isEnabled) + assertTrue(keysBackup.isEnabled()) // Check that it's signed with MSK val versionResult = testHelper.doSync { @@ -441,8 +441,8 @@ class KeysBackupTest : InstrumentedTest { // - The new device must see the previous backup as not trusted assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion) - assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled) - assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state) + assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled()) + assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState()) // - Trust the backup from the new device testHelper.doSync { @@ -458,7 +458,7 @@ class KeysBackupTest : InstrumentedTest { // - Backup must be enabled on the new device, on the same version assertEquals(testData.prepareKeysBackupDataResult.version, testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion?.version) - assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled) + assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled()) // - Retrieve the last version from the server val keysVersionResult = testHelper.doSync { @@ -504,8 +504,8 @@ class KeysBackupTest : InstrumentedTest { // - The new device must see the previous backup as not trusted assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion) - assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled) - assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state) + assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled()) + assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState()) // - Trust the backup from the new device with the recovery key testHelper.doSync { @@ -521,7 +521,7 @@ class KeysBackupTest : InstrumentedTest { // - Backup must be enabled on the new device, on the same version assertEquals(testData.prepareKeysBackupDataResult.version, testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion?.version) - assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled) + assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled()) // - Retrieve the last version from the server val keysVersionResult = testHelper.doSync { @@ -565,8 +565,8 @@ class KeysBackupTest : InstrumentedTest { // - The new device must see the previous backup as not trusted assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion) - assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled) - assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state) + assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled()) + assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState()) // - Try to trust the backup from the new device with a wrong recovery key val latch = CountDownLatch(1) @@ -579,8 +579,8 @@ class KeysBackupTest : InstrumentedTest { // - The new device must still see the previous backup as not trusted assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion) - assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled) - assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state) + assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled()) + assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState()) stateObserver.stopAndCheckStates(null) testData.cleanUp(testHelper) @@ -612,8 +612,8 @@ class KeysBackupTest : InstrumentedTest { // - The new device must see the previous backup as not trusted assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion) - assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled) - assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state) + assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled()) + assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState()) // - Trust the backup from the new device with the password testHelper.doSync { @@ -629,7 +629,7 @@ class KeysBackupTest : InstrumentedTest { // - Backup must be enabled on the new device, on the same version assertEquals(testData.prepareKeysBackupDataResult.version, testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion?.version) - assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled) + assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled()) // - Retrieve the last version from the server val keysVersionResult = testHelper.doSync { @@ -676,8 +676,8 @@ class KeysBackupTest : InstrumentedTest { // - The new device must see the previous backup as not trusted assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion) - assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled) - assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state) + assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled()) + assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState()) // - Try to trust the backup from the new device with a wrong password val latch = CountDownLatch(1) @@ -690,8 +690,8 @@ class KeysBackupTest : InstrumentedTest { // - The new device must still see the previous backup as not trusted assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion) - assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled) - assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state) + assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled()) + assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState()) stateObserver.stopAndCheckStates(null) testData.cleanUp(testHelper) @@ -969,7 +969,7 @@ class KeysBackupTest : InstrumentedTest { val stateObserver = StateObserver(keysBackup) - assertFalse(keysBackup.isEnabled) + assertFalse(keysBackup.isEnabled()) // Wait for keys backup to be finished val latch0 = CountDownLatch(1) @@ -993,7 +993,7 @@ class KeysBackupTest : InstrumentedTest { // - Make alice back up her keys to her homeserver keysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup) - assertTrue(keysBackup.isEnabled) + assertTrue(keysBackup.isEnabled()) testHelper.await(latch0) @@ -1012,8 +1012,8 @@ class KeysBackupTest : InstrumentedTest { testHelper.await(latch2) // -> That must fail and her backup state must be WrongBackUpVersion - assertEquals(KeysBackupState.WrongBackUpVersion, keysBackup.state) - assertFalse(keysBackup.isEnabled) + assertEquals(KeysBackupState.WrongBackUpVersion, keysBackup.getState()) + assertFalse(keysBackup.isEnabled()) stateObserver.stopAndCheckStates(null) cryptoTestData.cleanUp(testHelper) @@ -1069,7 +1069,7 @@ class KeysBackupTest : InstrumentedTest { // - Try to backup all in aliceSession2, it must fail val keysBackup2 = aliceSession2.cryptoService().keysBackupService() - assertFalse("Backup should not be enabled", keysBackup2.isEnabled) + assertFalse("Backup should not be enabled", keysBackup2.isEnabled()) val stateObserver2 = StateObserver(keysBackup2) @@ -1088,8 +1088,8 @@ class KeysBackupTest : InstrumentedTest { assertFalse(isSuccessful) // Backup state must be NotTrusted - assertEquals("Backup state must be NotTrusted", KeysBackupState.NotTrusted, keysBackup2.state) - assertFalse("Backup should not be enabled", keysBackup2.isEnabled) + assertEquals("Backup state must be NotTrusted", KeysBackupState.NotTrusted, keysBackup2.getState()) + assertFalse("Backup should not be enabled", keysBackup2.isEnabled()) // - Validate the old device from the new one aliceSession2.cryptoService().setDeviceVerification( @@ -1103,7 +1103,7 @@ class KeysBackupTest : InstrumentedTest { keysBackup2.addListener(object : KeysBackupStateListener { override fun onStateChange(newState: KeysBackupState) { // Check the backup completes - if (keysBackup2.state == KeysBackupState.ReadyToBackUp) { + if (keysBackup2.getState() == KeysBackupState.ReadyToBackUp) { // Remove itself from the list of listeners keysBackup2.removeListener(this) @@ -1121,7 +1121,7 @@ class KeysBackupTest : InstrumentedTest { } // -> It must success - assertTrue(aliceSession2.cryptoService().keysBackupService().isEnabled) + assertTrue(aliceSession2.cryptoService().keysBackupService().isEnabled()) stateObserver.stopAndCheckStates(null) stateObserver2.stopAndCheckStates(null) @@ -1146,17 +1146,17 @@ class KeysBackupTest : InstrumentedTest { val stateObserver = StateObserver(keysBackup) - assertFalse(keysBackup.isEnabled) + assertFalse(keysBackup.isEnabled()) val keyBackupCreationInfo = keysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup) - assertTrue(keysBackup.isEnabled) + assertTrue(keysBackup.isEnabled()) // Delete the backup testHelper.doSync { keysBackup.deleteBackup(keyBackupCreationInfo.version, it) } // Backup is now disabled - assertFalse(keysBackup.isEnabled) + assertFalse(keysBackup.isEnabled()) stateObserver.stopAndCheckStates(null) cryptoTestData.cleanUp(testHelper) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt index 2220536e28..4eccdfad1f 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt @@ -106,7 +106,7 @@ internal class KeysBackupTestHelper( Assert.assertNotNull(megolmBackupCreationInfo) - Assert.assertFalse("Key backup should not be enabled before creation", keysBackup.isEnabled) + Assert.assertFalse("Key backup should not be enabled before creation", keysBackup.isEnabled()) // Create the version val keysVersion = testHelper.doSync { @@ -116,7 +116,7 @@ internal class KeysBackupTestHelper( Assert.assertNotNull("Key backup version should not be null", keysVersion.version) // Backup must be enable now - Assert.assertTrue(keysBackup.isEnabled) + Assert.assertTrue(keysBackup.isEnabled()) stateObserver.stopAndCheckStates(null) return PrepareKeysBackupDataResult(megolmBackupCreationInfo, keysVersion.version) @@ -128,7 +128,7 @@ internal class KeysBackupTestHelper( */ fun waitForKeysBackupToBeInState(session: Session, state: KeysBackupState) { // If already in the wanted state, return - if (session.cryptoService().keysBackupService().state == state) { + if (session.cryptoService().keysBackupService().getState() == state) { return } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt index 9029c7f8a3..b36797acf6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt @@ -204,10 +204,13 @@ interface KeysBackupService { callback: MatrixCallback) val keysBackupVersion: KeysVersionResult? + val currentBackupVersion: String? - val isEnabled: Boolean - val isStucked: Boolean - val state: KeysBackupState + get() = keysBackupVersion?.version + + fun isEnabled(): Boolean + fun isStucked(): Boolean + fun getState(): KeysBackupState // For gossiping fun saveBackupRecoveryKey(recoveryKey: String?, version: String?) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt index 813adf7459..520f2be4d0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt @@ -137,17 +137,11 @@ internal class DefaultKeysBackupService @Inject constructor( private var keysBackupStateListener: KeysBackupStateListener? = null - override val isEnabled: Boolean - get() = keysBackupStateManager.isEnabled + override fun isEnabled(): Boolean = keysBackupStateManager.isEnabled - override val isStucked: Boolean - get() = keysBackupStateManager.isStucked + override fun isStucked(): Boolean = keysBackupStateManager.isStucked - override val state: KeysBackupState - get() = keysBackupStateManager.state - - override val currentBackupVersion: String? - get() = keysBackupVersion?.version + override fun getState(): KeysBackupState = keysBackupStateManager.state override fun addListener(listener: KeysBackupStateListener) { keysBackupStateManager.addListener(listener) @@ -291,7 +285,7 @@ internal class DefaultKeysBackupService @Inject constructor( this.callback = object : MatrixCallback { private fun eventuallyRestartBackup() { // Do not stay in KeysBackupState.Unknown but check what is available on the homeserver - if (state == KeysBackupState.Unknown) { + if (getState() == KeysBackupState.Unknown) { checkAndStartKeysBackup() } } @@ -383,7 +377,7 @@ internal class DefaultKeysBackupService @Inject constructor( } // If backup is finished, notify the main listener - if (state === KeysBackupState.ReadyToBackUp) { + if (getState() === KeysBackupState.ReadyToBackUp) { backupAllGroupSessionsCallback?.onSuccess(Unit) resetBackupAllGroupSessionsListeners() } @@ -915,12 +909,12 @@ internal class DefaultKeysBackupService @Inject constructor( */ fun maybeBackupKeys() { when { - isStucked -> { + isStucked() -> { // If not already done, or in error case, check for a valid backup version on the homeserver. // If there is one, maybeBackupKeys will be called again. checkAndStartKeysBackup() } - state == KeysBackupState.ReadyToBackUp -> { + getState() == KeysBackupState.ReadyToBackUp -> { keysBackupStateManager.state = KeysBackupState.WillBackUp // Wait between 0 and 10 seconds, to avoid backup requests from @@ -933,8 +927,8 @@ internal class DefaultKeysBackupService @Inject constructor( uiHandler.post { backupKeys() } } } - else -> { - Timber.v("maybeBackupKeys: Skip it because state: $state") + else -> { + Timber.v("maybeBackupKeys: Skip it because state: ${getState()}") } } } @@ -1018,9 +1012,9 @@ internal class DefaultKeysBackupService @Inject constructor( } override fun checkAndStartKeysBackup() { - if (!isStucked) { + if (!isStucked()) { // Try to start or restart the backup only if it is in unknown or bad state - Timber.w("checkAndStartKeysBackup: invalid state: $state") + Timber.w("checkAndStartKeysBackup: invalid state: ${getState()}") return } @@ -1259,16 +1253,16 @@ internal class DefaultKeysBackupService @Inject constructor( Timber.v("backupKeys") // Sanity check, as this method can be called after a delay, the state may have change during the delay - if (!isEnabled || backupOlmPkEncryption == null || keysBackupVersion == null) { + if (!isEnabled() || backupOlmPkEncryption == null || keysBackupVersion == null) { Timber.v("backupKeys: Invalid configuration") backupAllGroupSessionsCallback?.onFailure(IllegalStateException("Invalid configuration")) resetBackupAllGroupSessionsListeners() return } - if (state === KeysBackupState.BackingUp) { + if (getState() === KeysBackupState.BackingUp) { // Do nothing if we are already backing up - Timber.v("backupKeys: Invalid state: $state") + Timber.v("backupKeys: Invalid state: ${getState()}") return } diff --git a/vector/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt b/vector/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt index 21fd226317..eaf39310a8 100644 --- a/vector/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt +++ b/vector/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt @@ -165,7 +165,7 @@ class SecurityBootstrapTest : VerificationTestBase() { assert(uiSession.cryptoService().crossSigningService().isCrossSigningInitialized()) assert(uiSession.cryptoService().crossSigningService().canCrossSign()) assert(uiSession.cryptoService().crossSigningService().allPrivateKeysKnown()) - assert(uiSession.cryptoService().keysBackupService().isEnabled) + assert(uiSession.cryptoService().keysBackupService().isEnabled()) assert(uiSession.cryptoService().keysBackupService().currentBackupVersion != null) assert(uiSession.sharedSecretStorageService().isRecoverySetup()) assert(uiSession.sharedSecretStorageService().isMegolmKeyInBackup()) diff --git a/vector/src/main/java/im/vector/app/core/extensions/Session.kt b/vector/src/main/java/im/vector/app/core/extensions/Session.kt index 1884909906..2a2198d96b 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Session.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Session.kt @@ -66,7 +66,7 @@ fun Session.startSyncing(context: Context) { */ fun Session.hasUnsavedKeys(): Boolean { return cryptoService().inboundGroupSessionsCount(false) > 0 && - cryptoService().keysBackupService().state != KeysBackupState.ReadyToBackUp + cryptoService().keysBackupService().getState() != KeysBackupState.ReadyToBackUp } fun Session.cannotLogoutSafely(): Boolean { diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt index b47b84af71..dea481dbad 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt @@ -60,7 +60,7 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS init { setState { this.copy( - keysBackupState = keysBackupService.state, + keysBackupState = keysBackupService.getState(), keysBackupVersion = keysBackupService.keysBackupVersion ) } @@ -206,7 +206,7 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS } fun canExit(): Boolean { - val currentBackupState = keysBackupService.state + val currentBackupState = keysBackupService.getState() return currentBackupState == KeysBackupState.Unknown || currentBackupState == KeysBackupState.CheckingBackUpOnHomeserver diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt index 4bc513284b..79a6dd27ff 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt @@ -401,8 +401,8 @@ class MessageActionsViewModel @AssistedInject constructor( if (vectorPreferences.developerMode()) { if (timelineEvent.isEncrypted() && timelineEvent.root.mCryptoError != null) { val keysBackupService = session.cryptoService().keysBackupService() - if (keysBackupService.state == KeysBackupState.NotTrusted || - (keysBackupService.state == KeysBackupState.ReadyToBackUp && + if (keysBackupService.getState() == KeysBackupState.NotTrusted || + (keysBackupService.getState() == KeysBackupState.ReadyToBackUp && keysBackupService.canRestoreKeys()) ) { add(EventSharedAction.UseKeyBackup) diff --git a/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt b/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt index 8c24b2893a..6a38de44c6 100644 --- a/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt @@ -81,7 +81,7 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS init { session.cryptoService().keysBackupService().addListener(this) - keysBackupState.value = session.cryptoService().keysBackupService().state + keysBackupState.value = session.cryptoService().keysBackupService().getState() val liveUserAccountData = session.flow().liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME)) val liveCrossSigningInfo = session.flow().liveCrossSigningInfo(session.myUserId) val liveCrossSigningPrivateKeys = session.flow().liveCrossSigningPrivateKeys() @@ -116,7 +116,7 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS } viewModelScope.launch { - keyBackupFlow.tryEmit(session.cryptoService().keysBackupService().state) + keyBackupFlow.tryEmit(session.cryptoService().keysBackupService().getState()) } } @@ -148,7 +148,7 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS override fun onStateChange(newState: KeysBackupState) { viewModelScope.launch { - keyBackupFlow.tryEmit(session.cryptoService().keysBackupService().state) + keyBackupFlow.tryEmit(session.cryptoService().keysBackupService().getState()) } keysBackupState.value = newState } diff --git a/vector/src/main/java/im/vector/app/features/workers/signout/SignoutCheckViewModel.kt b/vector/src/main/java/im/vector/app/features/workers/signout/SignoutCheckViewModel.kt index 79df62d7fb..49d1192b2b 100644 --- a/vector/src/main/java/im/vector/app/features/workers/signout/SignoutCheckViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/workers/signout/SignoutCheckViewModel.kt @@ -76,7 +76,7 @@ class SignoutCheckViewModel @AssistedInject constructor( val quad4SIsSetup = session.sharedSecretStorageService().isRecoverySetup() val allKeysKnown = session.cryptoService().crossSigningService().allPrivateKeysKnown() - val backupState = session.cryptoService().keysBackupService().state + val backupState = session.cryptoService().keysBackupService().getState() setState { copy( userId = session.myUserId, From 853c0a25bfafb99553eef232e3ce39035e8c5cdf Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 19:00:03 +0200 Subject: [PATCH 050/244] Method `onSecretKeyGossip` doe snot have to be in the public interface --- .../sdk/api/session/crypto/keysbackup/KeysBackupService.kt | 2 -- .../sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt index b36797acf6..824ed1b992 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt @@ -168,8 +168,6 @@ interface KeysBackupService { password: String, callback: MatrixCallback) - fun onSecretKeyGossip(secret: String) - /** * Restore a backup with a recovery key from a given backup version stored on the homeserver. * diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt index 520f2be4d0..fe63529547 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt @@ -622,7 +622,7 @@ internal class DefaultKeysBackupService @Inject constructor( } } - override fun onSecretKeyGossip(secret: String) { + fun onSecretKeyGossip(secret: String) { Timber.i("## CrossSigning - onSecretKeyGossip") cryptoCoroutineScope.launch(coroutineDispatchers.io) { From 740acda60bc4ac58be4b1f85c08e6c294f458366 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 20:53:02 +0200 Subject: [PATCH 051/244] Please ktlint. Ok, the user story will appear at the end of the doc. --- .../sdk/{_userstories => userstories}/Us000InitMatrix.kt | 2 +- .../android/sdk/{_userstories => userstories}/Us100SignIn.kt | 2 +- .../sdk/{_userstories => userstories}/Us150VerifySession.kt | 2 +- .../android/sdk/{_userstories => userstories}/Us190SignOut.kt | 2 +- .../android/sdk/{_userstories => userstories}/Us200RoomList.kt | 2 +- .../sdk/{_userstories => userstories}/Us300RoomTimeline.kt | 2 +- .../Us350RoomTimelineFromPermalink.kt | 2 +- .../sdk/{_userstories => userstories}/Us400RoomSendContent.kt | 2 +- .../sdk/{_userstories => userstories}/Us500Notification.kt | 2 +- .../sdk/{_userstories => userstories}/Us600SyncWithTheServer.kt | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/{_userstories => userstories}/Us000InitMatrix.kt (94%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/{_userstories => userstories}/Us100SignIn.kt (95%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/{_userstories => userstories}/Us150VerifySession.kt (94%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/{_userstories => userstories}/Us190SignOut.kt (94%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/{_userstories => userstories}/Us200RoomList.kt (94%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/{_userstories => userstories}/Us300RoomTimeline.kt (94%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/{_userstories => userstories}/Us350RoomTimelineFromPermalink.kt (94%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/{_userstories => userstories}/Us400RoomSendContent.kt (94%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/{_userstories => userstories}/Us500Notification.kt (94%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/{_userstories => userstories}/Us600SyncWithTheServer.kt (94%) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us000InitMatrix.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us000InitMatrix.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us000InitMatrix.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us000InitMatrix.kt index 823a9522cf..1eb926c54a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us000InitMatrix.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us000InitMatrix.kt @@ -16,7 +16,7 @@ @file:Suppress("unused") -package org.matrix.android.sdk._userstories +package org.matrix.android.sdk.userstories /** * ### Title diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us100SignIn.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us100SignIn.kt similarity index 95% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us100SignIn.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us100SignIn.kt index 5344e19ae4..fdd78737f8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us100SignIn.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us100SignIn.kt @@ -16,7 +16,7 @@ @file:Suppress("unused") -package org.matrix.android.sdk._userstories +package org.matrix.android.sdk.userstories /** * ### Title diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us150VerifySession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us150VerifySession.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us150VerifySession.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us150VerifySession.kt index 59eb056cb0..6ccee2e783 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us150VerifySession.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us150VerifySession.kt @@ -16,7 +16,7 @@ @file:Suppress("unused") -package org.matrix.android.sdk._userstories +package org.matrix.android.sdk.userstories /** * ### Title diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us190SignOut.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us190SignOut.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us190SignOut.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us190SignOut.kt index c9504e4a5e..fb50449148 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us190SignOut.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us190SignOut.kt @@ -16,7 +16,7 @@ @file:Suppress("unused") -package org.matrix.android.sdk._userstories +package org.matrix.android.sdk.userstories /** * ### Title diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us200RoomList.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us200RoomList.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us200RoomList.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us200RoomList.kt index fa71b8cedf..acc73aa340 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us200RoomList.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us200RoomList.kt @@ -16,7 +16,7 @@ @file:Suppress("unused") -package org.matrix.android.sdk._userstories +package org.matrix.android.sdk.userstories /** * ### Title diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us300RoomTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us300RoomTimeline.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us300RoomTimeline.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us300RoomTimeline.kt index ce899f53f8..23a06ba27a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us300RoomTimeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us300RoomTimeline.kt @@ -16,7 +16,7 @@ @file:Suppress("unused") -package org.matrix.android.sdk._userstories +package org.matrix.android.sdk.userstories /** * ### Title diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us350RoomTimelineFromPermalink.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us350RoomTimelineFromPermalink.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us350RoomTimelineFromPermalink.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us350RoomTimelineFromPermalink.kt index 6684d2b8f3..6d0ae32cca 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us350RoomTimelineFromPermalink.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us350RoomTimelineFromPermalink.kt @@ -16,7 +16,7 @@ @file:Suppress("unused") -package org.matrix.android.sdk._userstories +package org.matrix.android.sdk.userstories /** * ### Title diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us400RoomSendContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us400RoomSendContent.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us400RoomSendContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us400RoomSendContent.kt index fcff950228..8938f0703d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us400RoomSendContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us400RoomSendContent.kt @@ -16,7 +16,7 @@ @file:Suppress("unused") -package org.matrix.android.sdk._userstories +package org.matrix.android.sdk.userstories /** * ### Title diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us500Notification.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us500Notification.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us500Notification.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us500Notification.kt index a58f09a62c..5d08ac2366 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us500Notification.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us500Notification.kt @@ -16,7 +16,7 @@ @file:Suppress("unused") -package org.matrix.android.sdk._userstories +package org.matrix.android.sdk.userstories /** * ### Title diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us600SyncWithTheServer.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us600SyncWithTheServer.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us600SyncWithTheServer.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us600SyncWithTheServer.kt index 52973259fd..f6532ae9d1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/_userstories/Us600SyncWithTheServer.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us600SyncWithTheServer.kt @@ -16,7 +16,7 @@ @file:Suppress("unused") -package org.matrix.android.sdk._userstories +package org.matrix.android.sdk.userstories /** * ### Title From 6e3979a32d9c9a6d713ef47602355233eaf8da32 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 23:52:53 +0200 Subject: [PATCH 052/244] Fix test compilation --- .../java/im/vector/app/test/fakes/FakeAuthenticationService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeAuthenticationService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeAuthenticationService.kt index fedda18aeb..0456bbd474 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeAuthenticationService.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeAuthenticationService.kt @@ -33,7 +33,7 @@ class FakeAuthenticationService : AuthenticationService by mockk() { } fun givenRegistrationStarted(started: Boolean) { - every { isRegistrationStarted } returns started + every { isRegistrationStarted() } returns started } fun givenLoginFlow(config: HomeServerConnectionConfig, result: LoginFlowResult) { From d92875e3c2211eee2992f5468e42fe4f2b34ff98 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 23:54:00 +0200 Subject: [PATCH 053/244] Improve documentation --- .../auth/registration/RegistrationResult.kt | 20 ++++++++++++- .../sdk/api/auth/registration/Stage.kt | 29 ++++++++++++++----- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationResult.kt index 439b4beb41..f1639d2a09 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationResult.kt @@ -18,13 +18,31 @@ package org.matrix.android.sdk.api.auth.registration import org.matrix.android.sdk.api.session.Session -// Either a session or an object containing data about registration stages +/** + * Either a session or an object containing data about registration stages + */ sealed class RegistrationResult { + /** + * The registration is successful, the [Session] is provided + */ data class Success(val session: Session) : RegistrationResult() + + /** + * The registration still miss some steps. See [FlowResult] to know the details + */ data class FlowResponse(val flowResult: FlowResult) : RegistrationResult() } +/** + * Information about the missing and completed [Stage] + */ data class FlowResult( + /** + * List of missing stages + */ val missingStages: List, + /** + * List of completed stages + */ val completedStages: List ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/Stage.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/Stage.kt index c21b667cf7..ce834b976d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/Stage.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/Stage.kt @@ -16,25 +16,40 @@ package org.matrix.android.sdk.api.auth.registration +/** + * Registration stages + */ sealed class Stage(open val mandatory: Boolean) { - // m.login.recaptcha + /** + * m.login.recaptcha stage + */ data class ReCaptcha(override val mandatory: Boolean, val publicKey: String) : Stage(mandatory) - // m.login.email.identity + /** + * m.login.email.identity stage + */ data class Email(override val mandatory: Boolean) : Stage(mandatory) - // m.login.msisdn + /** + * m.login.msisdn stage + */ data class Msisdn(override val mandatory: Boolean) : Stage(mandatory) - // m.login.dummy, can be mandatory if there is no other stages. In this case the account cannot be created by just sending a username - // and a password, the dummy stage has to be done + /** + * m.login.dummy, can be mandatory if there is no other stages. In this case the account cannot be created by just sending a username + * and a password, the dummy stage has to be done + */ data class Dummy(override val mandatory: Boolean) : Stage(mandatory) - // Undocumented yet: m.login.terms + /** + * Undocumented yet: m.login.terms stage + */ data class Terms(override val mandatory: Boolean, val policies: TermPolicies) : Stage(mandatory) - // For unknown stages + /** + * For unknown stages + */ data class Other(override val mandatory: Boolean, val type: String, val params: Map<*, *>?) : Stage(mandatory) } From dc1eba28475df0945e2afcc486627b5405bf2d91 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 6 May 2022 00:04:44 +0200 Subject: [PATCH 054/244] Improve documentation --- .../android/sdk/api/cache/CacheStrategy.kt | 14 +++++++---- .../matrix/android/sdk/api/failure/Failure.kt | 4 +++- .../verification/VerificationTxState.kt | 24 ++++++++++++++----- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/cache/CacheStrategy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/cache/CacheStrategy.kt index 2880d851d6..5e2b1b0aff 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/cache/CacheStrategy.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/cache/CacheStrategy.kt @@ -17,13 +17,19 @@ package org.matrix.android.sdk.api.cache sealed class CacheStrategy { - // Data is always fetched from the server + /** + * Data is always fetched from the server + */ object NoCache : CacheStrategy() - // Once data is retrieved, it is stored for the provided amount of time. - // In case of error, and if strict is set to false, the cache can be returned if available + /** + * Once data is retrieved, it is stored for the provided amount of time. + * In case of error, and if strict is set to false, the cache can be returned if available + */ data class TtlCache(val validityDurationInMillis: Long, val strict: Boolean) : CacheStrategy() - // Once retrieved, the data is stored in cache and will be always get from the cache + /** + * Once retrieved, the data is stored in cache and will be always get from the cache + */ object InfiniteCache : CacheStrategy() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt index be139fd82b..4ded8bc47e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt @@ -37,7 +37,9 @@ sealed class Failure(cause: Throwable? = null) : Throwable(cause = cause) { data class ServerError(val error: MatrixError, val httpCode: Int) : Failure(RuntimeException(error.toString())) object SuccessError : Failure(RuntimeException(RuntimeException("SuccessResult is false"))) - // When server send an error, but it cannot be interpreted as a MatrixError + /** + * When server send an error, but it cannot be interpreted as a MatrixError + */ data class OtherServerError(val errorBody: String, val httpCode: Int) : Failure(RuntimeException("HTTP $httpCode: $errorBody")) data class RegistrationFlowError(val registrationFlowResponse: RegistrationFlowResponse) : Failure(RuntimeException(registrationFlowResponse.toString())) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt index 39de2cc712..0f8f4cd987 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt @@ -17,10 +17,14 @@ package org.matrix.android.sdk.api.session.crypto.verification sealed class VerificationTxState { - // Uninitialized state + /** + * Uninitialized state + */ object None : VerificationTxState() - // Specific for SAS + /** + * Specific for SAS + */ abstract class VerificationSasTxState : VerificationTxState() object SendingStart : VerificationSasTxState() @@ -38,18 +42,26 @@ sealed class VerificationTxState { object MacSent : VerificationSasTxState() object Verifying : VerificationSasTxState() - // Specific for QR code + /** + * Specific for QR code + */ abstract class VerificationQrTxState : VerificationTxState() - // Will be used to ask the user if the other user has correctly scanned + /** + * Will be used to ask the user if the other user has correctly scanned + */ object QrScannedByOther : VerificationQrTxState() object WaitingOtherReciprocateConfirm : VerificationQrTxState() - // Terminal states + /** + * Terminal states + */ abstract class TerminalTxState : VerificationTxState() object Verified : TerminalTxState() - // Cancelled by me or by other + /** + * Cancelled by me or by other + */ data class Cancelled(val cancelCode: CancelCode, val byMe: Boolean) : TerminalTxState() } From 268c41a0ee0b9aea4baef0ac02c415ec3bb640a6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 11 May 2022 15:16:35 +0200 Subject: [PATCH 055/244] Changelog --- changelog.d/5952.sdk | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelog.d/5952.sdk diff --git a/changelog.d/5952.sdk b/changelog.d/5952.sdk new file mode 100644 index 0000000000..4973ec9c7c --- /dev/null +++ b/changelog.d/5952.sdk @@ -0,0 +1,3 @@ +- Some `val` have been changed to `fun` to increase their visibility in the generated documentation. Just add `()` if you were using them. +- `KeysBackupService.state` has been replaced by `KeysBackupService.getState()` +- SDK documentation improved From 8d74acf060d148fb799e66783046e816ea66795c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 11 May 2022 16:23:02 +0200 Subject: [PATCH 056/244] Fix post rebase issue --- .../org/matrix/android/sdk/common/CryptoTestHelper.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt index 348841313b..ac3da80fc5 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt @@ -58,7 +58,7 @@ import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams import org.matrix.android.sdk.api.session.securestorage.EmptyKeySigner -import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService +import org.matrix.android.sdk.api.session.securestorage.KeyRef import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.awaitCallback import org.matrix.android.sdk.api.util.toBase64NoPadding @@ -361,19 +361,19 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { ssssService.storeSecret( MASTER_KEY_SSSS_NAME, session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.master!!, - listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec)) + listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec)) ) ssssService.storeSecret( SELF_SIGNING_KEY_SSSS_NAME, session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.selfSigned!!, - listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec)) + listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec)) ) ssssService.storeSecret( USER_SIGNING_KEY_SSSS_NAME, session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.user!!, - listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec)) + listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec)) ) // set up megolm backup @@ -390,7 +390,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { ssssService.storeSecret( KEYBACKUP_SECRET_SSSS_NAME, secret, - listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec)) + listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec)) ) } } From 8218d8f26797b00c4fb4975ed98a39565ed4a44d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 May 2022 14:44:10 +0200 Subject: [PATCH 057/244] Typo: isStucked -> isStuck --- .../sdk/api/session/crypto/keysbackup/KeysBackupService.kt | 2 +- .../internal/crypto/keysbackup/DefaultKeysBackupService.kt | 6 +++--- .../internal/crypto/keysbackup/KeysBackupStateManager.kt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt index 824ed1b992..dc8b03eaae 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt @@ -207,7 +207,7 @@ interface KeysBackupService { get() = keysBackupVersion?.version fun isEnabled(): Boolean - fun isStucked(): Boolean + fun isStuck(): Boolean fun getState(): KeysBackupState // For gossiping diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt index fe63529547..1319e54e32 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt @@ -139,7 +139,7 @@ internal class DefaultKeysBackupService @Inject constructor( override fun isEnabled(): Boolean = keysBackupStateManager.isEnabled - override fun isStucked(): Boolean = keysBackupStateManager.isStucked + override fun isStuck(): Boolean = keysBackupStateManager.isStuck override fun getState(): KeysBackupState = keysBackupStateManager.state @@ -909,7 +909,7 @@ internal class DefaultKeysBackupService @Inject constructor( */ fun maybeBackupKeys() { when { - isStucked() -> { + isStuck() -> { // If not already done, or in error case, check for a valid backup version on the homeserver. // If there is one, maybeBackupKeys will be called again. checkAndStartKeysBackup() @@ -1012,7 +1012,7 @@ internal class DefaultKeysBackupService @Inject constructor( } override fun checkAndStartKeysBackup() { - if (!isStucked()) { + if (!isStuck()) { // Try to start or restart the backup only if it is in unknown or bad state Timber.w("checkAndStartKeysBackup: invalid state: ${getState()}") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupStateManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupStateManager.kt index 78ef958bbf..0614eceb16 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupStateManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupStateManager.kt @@ -49,7 +49,7 @@ internal class KeysBackupStateManager(private val uiHandler: Handler) { state == KeysBackupState.BackingUp // True if unknown or bad state - val isStucked: Boolean + val isStuck: Boolean get() = state == KeysBackupState.Unknown || state == KeysBackupState.Disabled || state == KeysBackupState.WrongBackUpVersion || From 827c7e58f6e6b4ba9a21840b3c3d1acffcb4351c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 May 2022 14:45:15 +0200 Subject: [PATCH 058/244] Package have been renamed, so also rename it here. Dokka does not complain about unknown package in this file :/ --- matrix-sdk-android/docs/packages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/docs/packages.md b/matrix-sdk-android/docs/packages.md index 98b0e0c034..19f7c15a7a 100644 --- a/matrix-sdk-android/docs/packages.md +++ b/matrix-sdk-android/docs/packages.md @@ -1,4 +1,4 @@ -# Package org.matrix.android.sdk._userstories +# Package org.matrix.android.sdk.userstories This package contains some user stories (**Us** prefix) of the SDK usage. You will find example of what it is possible to do with the SDK and the API which can be used to do it. From b86693580ed2944b76a91517115d20f080fab21b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 May 2022 14:57:39 +0200 Subject: [PATCH 059/244] `class` with `private constructor` instead of `object` --- .../java/org/matrix/android/sdk/userstories/Us000InitMatrix.kt | 2 +- .../main/java/org/matrix/android/sdk/userstories/Us100SignIn.kt | 2 +- .../org/matrix/android/sdk/userstories/Us150VerifySession.kt | 2 +- .../java/org/matrix/android/sdk/userstories/Us190SignOut.kt | 2 +- .../java/org/matrix/android/sdk/userstories/Us200RoomList.kt | 2 +- .../org/matrix/android/sdk/userstories/Us300RoomTimeline.kt | 2 +- .../android/sdk/userstories/Us350RoomTimelineFromPermalink.kt | 2 +- .../org/matrix/android/sdk/userstories/Us400RoomSendContent.kt | 2 +- .../org/matrix/android/sdk/userstories/Us500Notification.kt | 2 +- .../matrix/android/sdk/userstories/Us600SyncWithTheServer.kt | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us000InitMatrix.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us000InitMatrix.kt index 1eb926c54a..f0c2e42edb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us000InitMatrix.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us000InitMatrix.kt @@ -25,4 +25,4 @@ package org.matrix.android.sdk.userstories * ### Required APIs: * - [org.matrix.android.sdk.api.Matrix] constructor */ -object Us000InitMatrix +class Us000InitMatrix private constructor() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us100SignIn.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us100SignIn.kt index fdd78737f8..91d82a78b7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us100SignIn.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us100SignIn.kt @@ -28,4 +28,4 @@ package org.matrix.android.sdk.userstories * - [org.matrix.android.sdk.api.auth.AuthenticationService.getLoginWizard] * - [org.matrix.android.sdk.api.auth.login.LoginWizard.login] */ -object Us100SignIn +class Us100SignIn private constructor() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us150VerifySession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us150VerifySession.kt index 6ccee2e783..c26f2d45af 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us150VerifySession.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us150VerifySession.kt @@ -25,4 +25,4 @@ package org.matrix.android.sdk.userstories * #### Required APIs: * - TODO */ -object Us150VerifySession +class Us150VerifySession private constructor() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us190SignOut.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us190SignOut.kt index fb50449148..de895ad710 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us190SignOut.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us190SignOut.kt @@ -25,4 +25,4 @@ package org.matrix.android.sdk.userstories * #### Required APIs: * - TODO */ -object Us190SignOut +class Us190SignOut private constructor() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us200RoomList.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us200RoomList.kt index acc73aa340..61b5e3384b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us200RoomList.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us200RoomList.kt @@ -25,4 +25,4 @@ package org.matrix.android.sdk.userstories * #### Required APIs: * - TODO */ -object Us200RoomList +class Us200RoomList private constructor() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us300RoomTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us300RoomTimeline.kt index 23a06ba27a..4c0db3fbcf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us300RoomTimeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us300RoomTimeline.kt @@ -25,4 +25,4 @@ package org.matrix.android.sdk.userstories * #### Required APIs: * - TODO */ -object Us300RoomTimeline +class Us300RoomTimeline private constructor() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us350RoomTimelineFromPermalink.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us350RoomTimelineFromPermalink.kt index 6d0ae32cca..2ca4f1ec2b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us350RoomTimelineFromPermalink.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us350RoomTimelineFromPermalink.kt @@ -25,4 +25,4 @@ package org.matrix.android.sdk.userstories * #### Required APIs: * - TODO */ -object Us350RoomTimelineFromPermalink +class Us350RoomTimelineFromPermalink private constructor() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us400RoomSendContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us400RoomSendContent.kt index 8938f0703d..854fcd2f87 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us400RoomSendContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us400RoomSendContent.kt @@ -25,4 +25,4 @@ package org.matrix.android.sdk.userstories * #### Required APIs: * - TODO */ -object Us400RoomSendContent +class Us400RoomSendContent private constructor() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us500Notification.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us500Notification.kt index 5d08ac2366..157b3112f8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us500Notification.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us500Notification.kt @@ -25,4 +25,4 @@ package org.matrix.android.sdk.userstories * #### Required APIs: * - TODO */ -object Us500Notification +class Us500Notification private constructor() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us600SyncWithTheServer.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us600SyncWithTheServer.kt index f6532ae9d1..5202b75369 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us600SyncWithTheServer.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us600SyncWithTheServer.kt @@ -25,4 +25,4 @@ package org.matrix.android.sdk.userstories * #### Required APIs: * - TODO */ -object Us600SyncWithTheServer +class Us600SyncWithTheServer private constructor() From 0307e572c0803c2c9b5a675f9f608b179a3a123e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 May 2022 16:25:29 +0200 Subject: [PATCH 060/244] Add note about API renaming --- changelog.d/5952.sdk | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.d/5952.sdk b/changelog.d/5952.sdk index 4973ec9c7c..4226aba136 100644 --- a/changelog.d/5952.sdk +++ b/changelog.d/5952.sdk @@ -1,3 +1,4 @@ - Some `val` have been changed to `fun` to increase their visibility in the generated documentation. Just add `()` if you were using them. - `KeysBackupService.state` has been replaced by `KeysBackupService.getState()` +- `KeysBackupService.isStucked` has been replaced by `KeysBackupService.isStuck()` - SDK documentation improved From 92d54dc73322fbce0c6dbaad34488348d81c7f0f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 20 May 2022 21:13:30 +0200 Subject: [PATCH 061/244] Fix compilation issue --- .../sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt index 1319e54e32..efd3bca824 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt @@ -341,7 +341,7 @@ internal class DefaultKeysBackupService @Inject constructor( override fun backupAllGroupSessions(progressListener: ProgressListener?, callback: MatrixCallback?) { - if (!isEnabled || backupOlmPkEncryption == null || keysBackupVersion == null) { + if (!isEnabled() || backupOlmPkEncryption == null || keysBackupVersion == null) { callback?.onFailure(Throwable("Backup not enabled")) return } From 53c83ab8d839e46a9dea33512da99b4bee58b484 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 20 May 2022 21:22:47 +0200 Subject: [PATCH 062/244] Add missing punctuation --- .../auth/registration/RegistrationResult.kt | 12 ++++++------ .../android/sdk/api/auth/registration/Stage.kt | 14 +++++++------- .../android/sdk/api/cache/CacheStrategy.kt | 4 ++-- .../matrix/android/sdk/api/failure/Failure.kt | 2 +- .../crypto/keysbackup/KeysBackupState.kt | 18 +++++++++--------- .../crypto/model/RoomEncryptionTrustLevel.kt | 8 ++++---- .../crypto/verification/VerificationMethod.kt | 6 +++--- .../crypto/verification/VerificationTxState.kt | 12 ++++++------ .../sdk/api/session/room/send/SendState.kt | 16 ++++++++-------- .../session/threads/ThreadNotificationState.kt | 6 +++--- .../android/sdk/userstories/Us000InitMatrix.kt | 2 +- .../android/sdk/userstories/Us100SignIn.kt | 2 +- .../sdk/userstories/Us150VerifySession.kt | 2 +- .../android/sdk/userstories/Us190SignOut.kt | 2 +- .../android/sdk/userstories/Us200RoomList.kt | 2 +- .../sdk/userstories/Us300RoomTimeline.kt | 2 +- .../Us350RoomTimelineFromPermalink.kt | 2 +- .../sdk/userstories/Us400RoomSendContent.kt | 2 +- .../sdk/userstories/Us500Notification.kt | 2 +- .../sdk/userstories/Us600SyncWithTheServer.kt | 2 +- 20 files changed, 59 insertions(+), 59 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationResult.kt index f1639d2a09..9e6b2b3ad9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationResult.kt @@ -19,30 +19,30 @@ package org.matrix.android.sdk.api.auth.registration import org.matrix.android.sdk.api.session.Session /** - * Either a session or an object containing data about registration stages + * Either a session or an object containing data about registration stages. */ sealed class RegistrationResult { /** - * The registration is successful, the [Session] is provided + * The registration is successful, the [Session] is provided. */ data class Success(val session: Session) : RegistrationResult() /** - * The registration still miss some steps. See [FlowResult] to know the details + * The registration still miss some steps. See [FlowResult] to know the details. */ data class FlowResponse(val flowResult: FlowResult) : RegistrationResult() } /** - * Information about the missing and completed [Stage] + * Information about the missing and completed [Stage]. */ data class FlowResult( /** - * List of missing stages + * List of missing stages. */ val missingStages: List, /** - * List of completed stages + * List of completed stages. */ val completedStages: List ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/Stage.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/Stage.kt index ce834b976d..281b0c2808 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/Stage.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/Stage.kt @@ -17,38 +17,38 @@ package org.matrix.android.sdk.api.auth.registration /** - * Registration stages + * Registration stages. */ sealed class Stage(open val mandatory: Boolean) { /** - * m.login.recaptcha stage + * m.login.recaptcha stage. */ data class ReCaptcha(override val mandatory: Boolean, val publicKey: String) : Stage(mandatory) /** - * m.login.email.identity stage + * m.login.email.identity stage. */ data class Email(override val mandatory: Boolean) : Stage(mandatory) /** - * m.login.msisdn stage + * m.login.msisdn stage. */ data class Msisdn(override val mandatory: Boolean) : Stage(mandatory) /** * m.login.dummy, can be mandatory if there is no other stages. In this case the account cannot be created by just sending a username - * and a password, the dummy stage has to be done + * and a password, the dummy stage has to be done. */ data class Dummy(override val mandatory: Boolean) : Stage(mandatory) /** - * Undocumented yet: m.login.terms stage + * Undocumented yet: m.login.terms stage. */ data class Terms(override val mandatory: Boolean, val policies: TermPolicies) : Stage(mandatory) /** - * For unknown stages + * For unknown stages. */ data class Other(override val mandatory: Boolean, val type: String, val params: Map<*, *>?) : Stage(mandatory) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/cache/CacheStrategy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/cache/CacheStrategy.kt index 5e2b1b0aff..ddf76d6e42 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/cache/CacheStrategy.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/cache/CacheStrategy.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.api.cache sealed class CacheStrategy { /** - * Data is always fetched from the server + * Data is always fetched from the server. */ object NoCache : CacheStrategy() @@ -29,7 +29,7 @@ sealed class CacheStrategy { data class TtlCache(val validityDurationInMillis: Long, val strict: Boolean) : CacheStrategy() /** - * Once retrieved, the data is stored in cache and will be always get from the cache + * Once retrieved, the data is stored in cache and will be always get from the cache. */ object InfiniteCache : CacheStrategy() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt index 4ded8bc47e..7d4f553bed 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt @@ -38,7 +38,7 @@ sealed class Failure(cause: Throwable? = null) : Throwable(cause = cause) { object SuccessError : Failure(RuntimeException(RuntimeException("SuccessResult is false"))) /** - * When server send an error, but it cannot be interpreted as a MatrixError + * When server send an error, but it cannot be interpreted as a MatrixError. */ data class OtherServerError(val errorBody: String, val httpCode: Int) : Failure(RuntimeException("HTTP $httpCode: $errorBody")) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupState.kt index c4392ef9f1..a867d573de 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupState.kt @@ -52,50 +52,50 @@ package org.matrix.android.sdk.api.session.crypto.keysbackup */ enum class KeysBackupState { /** - * Need to check the current backup version on the homeserver + * Need to check the current backup version on the homeserver. */ Unknown, /** - * Checking if backup is enabled on homeserver + * Checking if backup is enabled on homeserver. */ CheckingBackUpOnHomeserver, /** - * Backup has been stopped because a new backup version has been detected on the homeserver + * Backup has been stopped because a new backup version has been detected on the homeserver. */ WrongBackUpVersion, /** - * Backup from this device is not enabled + * Backup from this device is not enabled. */ Disabled, /** * There is a backup available on the homeserver but it is not trusted. - * It is not trusted because the signature is invalid or the device that created it is not verified + * It is not trusted because the signature is invalid or the device that created it is not verified. * Use [KeysBackup.getKeysBackupTrust()] to get trust details. * Consequently, the backup from this device is not enabled. */ NotTrusted, /** - * Backup is being enabled: the backup version is being created on the homeserver + * Backup is being enabled: the backup version is being created on the homeserver. */ Enabling, /** - * Backup is enabled and ready to send backup to the homeserver + * Backup is enabled and ready to send backup to the homeserver. */ ReadyToBackUp, /** - * e2e keys are going to be sent to the homeserver + * e2e keys are going to be sent to the homeserver. */ WillBackUp, /** - * e2e keys are being sent to the homeserver + * e2e keys are being sent to the homeserver. */ BackingUp } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt index d030988303..78724819a3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt @@ -21,22 +21,22 @@ package org.matrix.android.sdk.api.session.crypto.model */ enum class RoomEncryptionTrustLevel { /** - * No one in the room has been verified -> Black shield + * No one in the room has been verified -> Black shield. */ Default, /** - * There are one or more device un-verified -> the app should display a red shield + * There are one or more device un-verified -> the app should display a red shield. */ Warning, /** - * All devices in the room are verified -> the app should display a green shield + * All devices in the room are verified -> the app should display a green shield. */ Trusted, /** - * e2e is active but with an unsupported algorithm + * e2e is active but with an unsupported algorithm. */ E2EWithUnsupportedAlgorithm } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt index b3758c364b..0ab47a2ecd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt @@ -21,17 +21,17 @@ package org.matrix.android.sdk.api.session.crypto.verification */ enum class VerificationMethod { /** - * Use it when your application supports the SAS verification method + * Use it when your application supports the SAS verification method. */ SAS, /** - * Use it if your application is able to display QR codes + * Use it if your application is able to display QR codes. */ QR_CODE_SHOW, /** - * Use it if your application is able to scan QR codes + * Use it if your application is able to scan QR codes. */ QR_CODE_SCAN } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt index 0f8f4cd987..30e4c66937 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt @@ -18,12 +18,12 @@ package org.matrix.android.sdk.api.session.crypto.verification sealed class VerificationTxState { /** - * Uninitialized state + * Uninitialized state. */ object None : VerificationTxState() /** - * Specific for SAS + * Specific for SAS. */ abstract class VerificationSasTxState : VerificationTxState() @@ -43,25 +43,25 @@ sealed class VerificationTxState { object Verifying : VerificationSasTxState() /** - * Specific for QR code + * Specific for QR code. */ abstract class VerificationQrTxState : VerificationTxState() /** - * Will be used to ask the user if the other user has correctly scanned + * Will be used to ask the user if the other user has correctly scanned. */ object QrScannedByOther : VerificationQrTxState() object WaitingOtherReciprocateConfirm : VerificationQrTxState() /** - * Terminal states + * Terminal states. */ abstract class TerminalTxState : VerificationTxState() object Verified : TerminalTxState() /** - * Cancelled by me or by other + * Cancelled by me or by other. */ data class Cancelled(val cancelCode: CancelCode, val byMe: Boolean) : TerminalTxState() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt index bb4a649a95..d058ff2840 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt @@ -18,42 +18,42 @@ package org.matrix.android.sdk.api.session.room.send enum class SendState { /** - * The state is unknown + * The state is unknown. */ UNKNOWN, /** - * The event has not been sent + * The event has not been sent. */ UNSENT, /** - * The event is encrypting + * The event is encrypting. */ ENCRYPTING, /** - * The event is currently sending + * The event is currently sending. */ SENDING, /** - * The event has been sent + * The event has been sent. */ SENT, /** - * The event has been received from server + * The event has been received from server. */ SYNCED, /** - * The event failed to be sent + * The event failed to be sent. */ UNDELIVERED, /** - * The event failed to be sent because some unknown devices have been found while encrypting it + * The event failed to be sent because some unknown devices have been found while encrypting it. */ FAILED_UNKNOWN_DEVICES; diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt index 226e7cc12e..6825f8c279 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt @@ -21,17 +21,17 @@ package org.matrix.android.sdk.api.session.threads */ enum class ThreadNotificationState { /** - * There are no new message + * There are no new message. */ NO_NEW_MESSAGE, /** - * There is at least one new message + * There is at least one new message. */ NEW_MESSAGE, /** - * The is at least one new message that should be highlighted + * The is at least one new message that should be highlighted. * ex. "Hello @aris.kotsomitopoulos" */ NEW_HIGHLIGHTED_MESSAGE; diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us000InitMatrix.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us000InitMatrix.kt index f0c2e42edb..06c6cc9ef9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us000InitMatrix.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us000InitMatrix.kt @@ -20,7 +20,7 @@ package org.matrix.android.sdk.userstories /** * ### Title - * Init a Matrix object + * Init a Matrix object. * * ### Required APIs: * - [org.matrix.android.sdk.api.Matrix] constructor diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us100SignIn.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us100SignIn.kt index 91d82a78b7..f508a75db7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us100SignIn.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us100SignIn.kt @@ -20,7 +20,7 @@ package org.matrix.android.sdk.userstories /** * ### Title - * Sign in to an existing account + * Sign in to an existing account. * * #### Required APIs: * - [org.matrix.android.sdk.api.Matrix.authenticationService] diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us150VerifySession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us150VerifySession.kt index c26f2d45af..ac56cc35dd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us150VerifySession.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us150VerifySession.kt @@ -20,7 +20,7 @@ package org.matrix.android.sdk.userstories /** * ### Title - * Verify a Session after a Sign in + * Verify a Session after a Sign in. * * #### Required APIs: * - TODO diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us190SignOut.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us190SignOut.kt index de895ad710..0c74c0dfef 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us190SignOut.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us190SignOut.kt @@ -20,7 +20,7 @@ package org.matrix.android.sdk.userstories /** * ### Title - * Sign out + * Sign out. * * #### Required APIs: * - TODO diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us200RoomList.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us200RoomList.kt index 61b5e3384b..1f0b2e4103 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us200RoomList.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us200RoomList.kt @@ -20,7 +20,7 @@ package org.matrix.android.sdk.userstories /** * ### Title - * Get the Room list + * Get the Room list. * * #### Required APIs: * - TODO diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us300RoomTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us300RoomTimeline.kt index 4c0db3fbcf..5db06f95f6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us300RoomTimeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us300RoomTimeline.kt @@ -20,7 +20,7 @@ package org.matrix.android.sdk.userstories /** * ### Title - * Display a Room timeline, and navigate backward and forward + * Display a Room timeline, and navigate backward and forward. * * #### Required APIs: * - TODO diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us350RoomTimelineFromPermalink.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us350RoomTimelineFromPermalink.kt index 2ca4f1ec2b..5e0f6d3b3d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us350RoomTimelineFromPermalink.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us350RoomTimelineFromPermalink.kt @@ -20,7 +20,7 @@ package org.matrix.android.sdk.userstories /** * ### Title - * Display a Room timeline at a specific point + * Display a Room timeline at a specific point. * * #### Required APIs: * - TODO diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us400RoomSendContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us400RoomSendContent.kt index 854fcd2f87..3f72cd0b9e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us400RoomSendContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us400RoomSendContent.kt @@ -20,7 +20,7 @@ package org.matrix.android.sdk.userstories /** * ### Title - * Send content to a room, including monitoring the sending state + * Send content to a room, including monitoring the sending state. * * #### Required APIs: * - TODO diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us500Notification.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us500Notification.kt index 157b3112f8..c5c2107fa6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us500Notification.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us500Notification.kt @@ -20,7 +20,7 @@ package org.matrix.android.sdk.userstories /** * ### Title - * Get notified when new Events are received + * Get notified when new Events are received. * * #### Required APIs: * - TODO diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us600SyncWithTheServer.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us600SyncWithTheServer.kt index 5202b75369..6b8fb87df7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us600SyncWithTheServer.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/userstories/Us600SyncWithTheServer.kt @@ -20,7 +20,7 @@ package org.matrix.android.sdk.userstories /** * ### Title - * Manage the sync with the server + * Manage the sync with the server. * * #### Required APIs: * - TODO From 97b2dd3d14ad46872c8b36a42aa5d7c878616cf1 Mon Sep 17 00:00:00 2001 From: "Auri B. P" Date: Thu, 19 May 2022 19:11:54 +0000 Subject: [PATCH 063/244] Translated using Weblate (Catalan) Currently translated at 83.3% (1854 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ca/ --- vector/src/main/res/values-ca/strings.xml | 48 +++++++++++++++++++---- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/vector/src/main/res/values-ca/strings.xml b/vector/src/main/res/values-ca/strings.xml index 157396781a..167b41d1dc 100644 --- a/vector/src/main/res/values-ca/strings.xml +++ b/vector/src/main/res/values-ca/strings.xml @@ -846,7 +846,7 @@ Ja existeix una còpia de seguretat al teu servidor Sembla que ja has configurat una còpia de seguretat de claus des d\'una altra sessió. Vols reemplaçar-la amb la que estàs creant\? Reemplaçar - Aturar + Atura Comprovant l\'estat de la còpia de seguretat Verificat! Entesos @@ -1633,9 +1633,9 @@ Comparteix aquest codi amb la gent perquè puguin escanejar-lo, afegir-te i començar a xatejar amb tu. L\'usuari no s\'ha acceptat el consentiment. Envia el missatge proporcionat amb confetis - Envia el missatge proporcionat nevant - envia confetis 🎉 - envia una nevada❄️ + Envia el missatge proporcionat amb una nevada + ha enviat confetis 🎉 + ha enviat una nevada ❄️ El meu codi Comparteix el meu codi Escaneja un codi QR @@ -1651,8 +1651,8 @@ No tens permís per activar el xifrat en aquesta sala. Activa el xifrat d\'extrem a extrem… Editor de missatges - Envia l\'emoticona proporcionat pintat amb un arc de Sant Martí - Envia el missatge proporcionat pintat amb un arc de Sant Martí + Envia l\'emoticona proporcionat pintat en arc de Sant Martí + Envia el missatge proporcionat pintat en arc de Sant Martí Pot ser causat per diferents motius: \n \n• Has canviat la teva contrasenya des d\'una altra sessió. @@ -2051,4 +2051,38 @@ %d canvi a l\'ACL del servidor %d canvis a l\'ACL del servidor - + Privat + Públic + Espai privat per organitzar les teves sales + Espai públic (teu) + Espai privat (teu) + Afegeix espai + Espai privat + Espai públic + Actualitza una sala a una nova versió + A fora + Ocupat + Fora de línia + Pausa %1$s + Pausa missatge de veu + Deixa d\'ignorar un usuari, es mostraran els nous missatges + Reprodueix %1$s + %1$d minuts %2$d segons + %1$s, %2$s, %3$s + Missatge de veu (%1$s) + No pots respondre o editar mentre el missatge de veu està actiu + No es pot enregistrar missatge de veu + Aquest missatge de veu no es pot reproduir + Clica l\'enregistrament per aturar-lo o escoltar-lo + %1$ds restants + Manté per enregistrar, deixa anar per enviar + Elimina enregistrament + Enregistrant missatge de veu + Atura l\'enregistrament + Reprodueix missatge de veu + Llisca per cancel·lar + Enregistra missatge de veu + S\'ha produït un error en provar d\'entrar a: %s + Actualitza a la versió de sala recomanada + Aquesta sala té la versió %s, la qual està marcada com a no estable pel servidor. + \ No newline at end of file From 422487ea9fe61d3afd17a49a2401e00f9d428aa5 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Wed, 18 May 2022 06:11:11 +0000 Subject: [PATCH 064/244] Translated using Weblate (Czech) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/ --- vector/src/main/res/values-cs/strings.xml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-cs/strings.xml b/vector/src/main/res/values-cs/strings.xml index 1ecc1c26f6..a098db1689 100644 --- a/vector/src/main/res/values-cs/strings.xml +++ b/vector/src/main/res/values-cs/strings.xml @@ -2291,7 +2291,7 @@ Nastaví název místnosti Přestane ignorovat uživatele a zobrazí jeho zprávy Ignoruje uživatele a skrývá jeho zprávy - Nedostupný + Pryč Offline Online Naslouchání oznámením @@ -2378,7 +2378,7 @@ Otevřít fotoaparát Váš systém bude automaticky odesílat chybové protokoly, když dojde k chybě dešifrování Automaticky nahlašovat chyby dešifrování. - Přepsat barvu přezdívky + Přepsat barvu zobrazovaného jména Již mám účet Bezpečené zasílání zpráv. Máte vše pod kontrolou. @@ -2537,4 +2537,8 @@ \n \nTato akce povede k restartování aplikace a může trvat nějakou dobu. Požadavek na počáteční synchronizaci - + Zobrazit nejnovější informace o uživateli + Zobrazit nejnovější informace o profilu (avatar a zobrazované jméno) u všech zpráv. + Zaneprázdněn + Záloha má platný podpis tohoto uživatele. + \ No newline at end of file From aac075fa89b4042fb5e3c5ea25aa200472fdbee7 Mon Sep 17 00:00:00 2001 From: John Doe Date: Fri, 20 May 2022 17:01:02 +0000 Subject: [PATCH 065/244] Translated using Weblate (Spanish) Currently translated at 99.8% (2221 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/es/ --- vector/src/main/res/values-es/strings.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-es/strings.xml b/vector/src/main/res/values-es/strings.xml index ba5a8dfc02..d609dad45b 100644 --- a/vector/src/main/res/values-es/strings.xml +++ b/vector/src/main/res/values-es/strings.xml @@ -2486,4 +2486,8 @@ \n \nTen en cuenta que esta acción reiniciará la aplicación y podría tardar algo de tiempo. Petición inicial de sincronización - + La copia de seguridad tiene una firma válida de este usuario. + Mostrar la última información del perfil (avatar y nick) para todos los mensajes. + Mostrar última información del usuario + Ocupado + \ No newline at end of file From 49acc6704f34f7e807ac918b2119114b0b33d19d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Tue, 17 May 2022 18:41:45 +0000 Subject: [PATCH 066/244] Translated using Weblate (Estonian) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/et/ --- vector/src/main/res/values-et/strings.xml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-et/strings.xml b/vector/src/main/res/values-et/strings.xml index 8aa1dfb09b..5422d18097 100644 --- a/vector/src/main/res/values-et/strings.xml +++ b/vector/src/main/res/values-et/strings.xml @@ -2251,7 +2251,7 @@ Määrab jututoa nime Lõpeta kasutaja eiramine ja näita edaspidi tema sõnumeid Eirab kasutajat peites kõik tema sõnumid sinu eest - Pole leitav + Eemal Võrgust väljas Võrgus Vali koduserver @@ -2333,7 +2333,7 @@ populaarsem valik Kui sõnumite dekrüptimisel tekib viga, siis rakendus saadab selle kohta automaatse teate arendajatele Automaatselt teata dekrüptimise vigadest. - Asenda hüüdnime värvid + Asenda kuvatava nime värvid Mul on kasutajakonto juba olemas Turvaline sõnumivahetus. Sul on kontroll oma andmete üle. @@ -2490,4 +2490,8 @@ \n \nPalun arvesta, et selle käigus rakendus käivitub uuesti ja see võib aega võtta. Alusandmete sünkroniseerimise päring - + Näita kõikide sõnumite puhul viimast profiili teavet (tunnuspilt ja kuvatav nimi). + Näita viimast kasutajateavet + Hõivatud + Varukoopial on kehtiv allkiri sellelt kasutajalt. + \ No newline at end of file From 7ff956678838afed83df22b03e3be0c103f02a59 Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Wed, 18 May 2022 09:12:55 +0000 Subject: [PATCH 067/244] Translated using Weblate (Persian) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fa/ --- vector/src/main/res/values-fa/strings.xml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-fa/strings.xml b/vector/src/main/res/values-fa/strings.xml index 171a145eb6..a35f632991 100644 --- a/vector/src/main/res/values-fa/strings.xml +++ b/vector/src/main/res/values-fa/strings.xml @@ -2251,7 +2251,7 @@ نام اتاق را تنظیم می‌کند به کاربری چشم گشوده و پیام‌های بعدیش را نشان می‌دهد از کاربری چشم‌پوشی کرده و پیام‌هایش را از شما پنهان می‌کند - ناموجود + بیرون برون‌خط برخط گزینش کارساز خانگی @@ -2359,7 +2359,7 @@ نتایج تنها هنگامی که نظرسنجی را پایان دهید آشکار می‌شوند رأی دهندگان به محض دادن رأی، نتایج را می‌بینند رمزنگاری بد پیکربندی شده - پایمالی رنگ نام مستعار + پایمالی رنگ نام نمایشی لطفاً برای بازگردانی رمزنگاری به یه وضعیتی معتبر، با مدیری تماس بگیرید. رمزنگاری بد پیکربندی شده. رمزنگاشتهٔ سرتاسری و بدون نیاز به شماره تلفن. بدون تبلیغات یا داده‌کاوی. @@ -2490,4 +2490,8 @@ هم‌رسانی صفحه - برخی کاربران ناچشم‌پوشی شده‌اند درخواست همگام سازی نخستین - + نمایش جدیدترین اطَلاعات نمایه (چهرک و نام نمایشی) برای تمامی پیام‌ها. + نمایش جدیدترین اطّلاعات کاربری + مشغول + پشتیبان امضای معتبری از این کاربر دارد. + \ No newline at end of file From d307349ae20b2924d3c458951cb7504946e497e2 Mon Sep 17 00:00:00 2001 From: Linerly Date: Wed, 18 May 2022 18:33:40 +0000 Subject: [PATCH 068/244] Translated using Weblate (Indonesian) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/id/ --- vector/src/main/res/values-in/strings.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/values-in/strings.xml b/vector/src/main/res/values-in/strings.xml index a8a457b4af..efb60739d7 100644 --- a/vector/src/main/res/values-in/strings.xml +++ b/vector/src/main/res/values-in/strings.xml @@ -2213,7 +2213,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Mengubah avatar ruangan saat ini Mengubah avatar Anda di ruangan saat ini saja Menampilkan - Tidak Tersedia + Tidak tersedia Luring Daring Pilih homeserver @@ -2445,4 +2445,8 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. \n \nDicatat bahwa tindakan ini akan memulai ulang aplikasinya dan mungkin membutuhkan beberapa waktu. Permintaan sinkronisasi awal - + Tampilkan info profil (avatar dan nama tampilan) terkini untuk semua pesan. + Tampilkan info pengguna terkini + Sibuk + Cadangan memiliki tandatangan yang valid dari pengguna ini. + \ No newline at end of file From 165b8d1b93d3c6faa9d3f1afb29cd8712bf30ec0 Mon Sep 17 00:00:00 2001 From: random Date: Wed, 18 May 2022 08:52:34 +0000 Subject: [PATCH 069/244] Translated using Weblate (Italian) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/it/ --- vector/src/main/res/values-it/strings.xml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-it/strings.xml b/vector/src/main/res/values-it/strings.xml index 3eec2c5f14..0dc9c1a240 100644 --- a/vector/src/main/res/values-it/strings.xml +++ b/vector/src/main/res/values-it/strings.xml @@ -2242,7 +2242,7 @@ Imposta il nome della stanza Smetti di ignorare un utente, mostrando i suoi messaggi successivi Ignora un utente, non mostrandoti i suoi messaggi - Non disponibile + Assente Offline Online Scegli homeserver @@ -2324,7 +2324,7 @@ Apri fotocamera Il tuo sistema invierà automaticamente i log quando si verifica un errore di decifrazione Auto-segnala errori di decifrazione. - Sovrascrivi colore nick + Sovrascrivi colore nome visualizzato Ho già un account Messaggistica sicura. Tu hai il controllo. @@ -2481,4 +2481,8 @@ \n \nNota che questa azione riavvierà l\'app e potrebbe richiedere del tempo. Richiesta di sincronizzazione iniziale - + Mostra le informazioni di profilo più recenti (avatar e nome visualizzato) per tutti i messaggi. + Mostra info utente più recenti + Occupato + Il backup ha una firma valida da questo utente. + \ No newline at end of file From 9710447ea3dafc069446aacb0cd7a86eff788bfc Mon Sep 17 00:00:00 2001 From: Piotr Strebski Date: Fri, 20 May 2022 09:16:17 +0000 Subject: [PATCH 070/244] Translated using Weblate (Polish) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pl/ --- vector/src/main/res/values-pl/strings.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-pl/strings.xml b/vector/src/main/res/values-pl/strings.xml index d6fef1c620..c9a7c9acf7 100644 --- a/vector/src/main/res/values-pl/strings.xml +++ b/vector/src/main/res/values-pl/strings.xml @@ -2258,7 +2258,7 @@ Edytuj treść Poznaj stan pokoju Narzędzia deweloperskie - Niedostępny + Nieobecny Pokój publiczny Nie powiadamiaj Powiadom bez dźwięku @@ -2321,7 +2321,7 @@ Usunąłeś(aś) %1$s jako adresy tego pokoju. Usunąłeś(aś) %1$s jako adresy tego pokoju. - Nadpisz kolor nicku + Zastąp kolor wyświetlanej nazwy Posiadam już konto Połącz się z każdym. Ty jesteś w kontroli. @@ -2583,4 +2583,5 @@ Udostępnij ekran - Niektórzy użytkownicy przestali być ignorowani Początkowe żądanie synchronizacji - + Kopia zapasowa ma poprawny podpis tego użytkownika. + \ No newline at end of file From 946353aeb9f57d008151349da2b7ae84f837a907 Mon Sep 17 00:00:00 2001 From: Didek Date: Wed, 18 May 2022 22:25:44 +0000 Subject: [PATCH 071/244] Translated using Weblate (Polish) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pl/ --- vector/src/main/res/values-pl/strings.xml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-pl/strings.xml b/vector/src/main/res/values-pl/strings.xml index c9a7c9acf7..23b1ef5d0c 100644 --- a/vector/src/main/res/values-pl/strings.xml +++ b/vector/src/main/res/values-pl/strings.xml @@ -736,8 +736,8 @@ Zaproszenia, usunięcia i bany pozostają nienaruszone. Wysyłaj wiadomości za pomocą klawisza enter Przycisk enter na klawiaturze programowej wyśle wiadomość zamiast wprowadzania łamanania linii - Znajdź - Zarządzaj ustawieniami wyszukiwania. + Ustawienia wyszukiwania + Ustal jak inni mogą odnaleść twoje konto. Media Domyślne źródło mediów Odzyskiwanie zaszyforwanych wiadomości @@ -1619,7 +1619,7 @@ Jeżeli chcesz zresetować kod PIN, naciśnij Zapomnij kod PIN aby wylogować i zresetować. Włącz kod PIN Skonfiguruj ochronę - Ochrona dostępu poprzez kod PIN oraz biometrię. + Blokada aplikacji poprzez kod PIN oraz biometrię. Ochrona dostępu Aby zresetować kod PIN musisz się ponownie zalogować i utworzyć nowy. Nowy kod PIN @@ -2584,4 +2584,7 @@ - Niektórzy użytkownicy przestali być ignorowani Początkowe żądanie synchronizacji Kopia zapasowa ma poprawny podpis tego użytkownika. + Pokazuj aktualny stan profilu (obraz i nazwa) w całej historii konwersacji. + Pokazuj najnowsze informacje o użytkowniku + Zajęty \ No newline at end of file From b12e0cd9f3462bf3b35eccef75eea56a99162d74 Mon Sep 17 00:00:00 2001 From: lvre <7uu3qrbvm@relay.firefox.com> Date: Tue, 17 May 2022 16:14:02 +0000 Subject: [PATCH 072/244] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pt_BR/ --- vector/src/main/res/values-pt-rBR/strings.xml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-pt-rBR/strings.xml b/vector/src/main/res/values-pt-rBR/strings.xml index 97896dec64..e689f4be82 100644 --- a/vector/src/main/res/values-pt-rBR/strings.xml +++ b/vector/src/main/res/values-pt-rBR/strings.xml @@ -2251,7 +2251,7 @@ Define o nome da sala Para de ignorar um/uma usuário(a), mostrando as mensagens dele/dela de agora em diante Ignora um/uma usuário(a), escondendo as mensagens dele/dela de você - Indisponível + Fora Offline Online Escolher servidorcasa @@ -2333,7 +2333,7 @@ Abrir câmera Seu sistema vai automaticamente enviar logs quando um erro incapaz de decriptar ocorre Auro Reportar Erros de Decriptação. - Sobrepor cor de nick + Sobrepor cor de nome de exibição Eu já tenho uma conta Mensageria segura. Você está em controle. @@ -2490,4 +2490,8 @@ \n \nNote que esta ação vai recomeçar o app e pode levar algum tempo. Requisição de sinc inicial - + Mostrar a info de perfil mais recente (avatar e nome de exibição) para todas as mensagens. + Mostrar info de usuária(o) mais recente + Ocupada(o) + Backup tem uma assinatura válida desta(e) usuária(o). + \ No newline at end of file From 79858a6560c1441db112d672e5e1d922e65f0be1 Mon Sep 17 00:00:00 2001 From: homocomputeris Date: Tue, 17 May 2022 22:54:32 +0000 Subject: [PATCH 073/244] Translated using Weblate (Russian) Currently translated at 97.6% (2172 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- vector/src/main/res/values-ru/strings.xml | 62 ++++++++++++++++------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml index cbc4bea123..f822cf05f3 100644 --- a/vector/src/main/res/values-ru/strings.xml +++ b/vector/src/main/res/values-ru/strings.xml @@ -46,7 +46,7 @@ Начальная синхронизация: \nИмпорт комнат Начальная синхронизация: -\nЗагрузка ваших бесед +\nВаши беседы загружаются \nЕсли вы присоединились к большому количеству комнат, это может занять некоторое время Начальная синхронизация: \nИмпорт приглашенных комнат @@ -417,9 +417,7 @@ Новый пароль Не удалось обновить пароль Пароль был обновлен - Отображать сообщения пользователя %s\? -\n -\nУчтите, что это действие перезапустит приложение и может занять некоторое время. + Показать все сообщения %s\? Выберите страну Тема Доступ к истории комнаты @@ -531,7 +529,7 @@ Вас заблокировал %2$s в %1$s Причина: %1$s Встряхните устройство, чтобы сообщить об ошибке - Список участников + Участники %d комната %d комнаты @@ -610,8 +608,8 @@ Изменить ваше отображаемое имя Вкл/выкл markdown Эта комната была заменена и больше не активна. - Этот разговор продолжается здесь - Эта комната является продолжением другого разговора + Беседа продолжается здесь + Эта комната — продолжение другой беседы Нажмите здесь для просмотра старых сообщений Присоединиться к комнате с указанным адресом Для исправления управления приложениями Matrix @@ -901,7 +899,7 @@ Вы в теме! У вас больше нет непрочитанных сообщений Беседы - Здесь будут отображаться ваши диалоги. Нажмите + внизу справа, чтобы начать что-то. + Здесь будут ваши диалоги. Нажмите кнопку «+» внизу справа, чтобы начать беседу. Комнаты Здесь будут отображаться ваши комнаты. Коснитесь + внизу справа, чтобы найти существующие или создать свои. Реакции @@ -961,7 +959,7 @@ (изменено) Изменение сообщения Изменения не найдены - Отфильтровывать разговоры… + Отфильтровать беседы… Не можете найти то, что ищете\? Создать новую комнату Отправить новое сообщение в диалог @@ -1073,7 +1071,7 @@ Введите ключевые слова, чтобы найти реакцию. Долгий клик по комнате покажет дополнительные опции Непрочитанные сообщения - Это ваш разговор. Владейте им. + Это ваша переписка. Контролируйте её. Общайтесь с людьми напрямую или в группах Начнем Выберите сервер @@ -1307,7 +1305,7 @@ \n \nВы можете отменить это действие в любое время в общих настройках. Перестать игнорировать пользователя - Если вы перестанете игнорировать этого пользователя, то все его сообщения вновь будут отображаться. + Если вы перестанете игнорировать этого пользователя, то вы увидите все его сообщения снова. Отменить приглашение Вы уверены, что хотите отменить приглашение для этого пользователя\? Выгнать пользователя @@ -1354,7 +1352,7 @@ Вы не игнорируете никаких пользователей Вы сделали комнату доступной для всех, у кого есть ссылка. Вы сделали комнату только по приглашению. - Сохраняйте конфиденциальность разговоров с помощью шифрования + Храните тайну переписки с помощью шифрования Расширьте и персонализируйте свой опыт использования Присоединяйтесь к миллионам бесплатно на крупнейшем публичном сервере Войти в %1$s @@ -1824,7 +1822,7 @@ Добавить людей "Тема: " Добавьте тему - Это начало разговора. + Это начало беседы. Это начало %s. У вас нет разрешения на включение шифрования в этой комнате. Создание комнаты… @@ -2404,11 +2402,11 @@ Создать учетную запись Обмен сообщениями для вашей команды. Сквозное шифрование не требующее номера телефона. Нет рекламы или сбора данных. - Выбор где хранятся ваши разговоры дает вам власть и независимость. Подключено с помощью Matrix. + Решайте самостоятельно и независимо, где хранить беседы. Благодаря Matrix. Безопасное и независимое общение, обеспечивающее вам такой же уровень конфиденциальности, как при личном общении в вашем собственном доме. Безопасный обмен сообщениями. Ваше управление. - Ваши собственные разговоры. + Контролируйте свою переписку. Местоположение Вы согласны отправить эту информацию\? Чтобы обнаружить существующие контакты, необходимо отправить контактную информацию (электронную почту и номера телефонов) на сервер обнаружения. Мы хешируем ваши данные перед отправкой для обеспечения конфиденциальности. @@ -2441,7 +2439,7 @@ Не могу связаться с домашним сервером на URL %s. Пожалуйста, проверьте вашу ссылку или выберите домашний сервер вручную. Не сейчас Включить - Поиск уведомлений + Ожидание уведомлений Вам не разрешено подключаться к этой комнате Организуйте обсуждение с помощью веток Показать все ветки, в которых вы участвуете @@ -2468,7 +2466,7 @@ Команда «%s» распознается, но не поддерживается в ветках. Из ветки Совет: нажмите и удерживайте сообщение и используйте «%s». - Ветки помогают хранить ваши разговоры по темам и легко отслеживать их. + Ветки помогают не терять нить беседы, и за ними легко следить. Мои ветки Показать все ветки этой комнаты Фильтр @@ -2494,4 +2492,32 @@ %d изменений ACL сервера %d изменений ACL сервера - + Поехали! + Его можно изменить позже + Добавить аватар + Его можно изменить позже + Имя для показа + Показывается, когда вы отправляете сообщения. + Выберите имя для показа + Ваш аккаунт «%s» создан. + Поздравляем! + Домой + Персонализировать + БЕТА + Отзывы на бета-версию веток + Оставить отзыв + БЕТА + Если включено, для других вы всегда будете выглядеть, как в офлайне, даже при использовании приложения. + Офлайн-режим + Бета-версия веток + Бета-версия веток + Ветки почти в бете 🎉 + Остановить демонстрацию экрана + Демонстрировать экран + Узнать больше + Попробуйте + Отключить + - Несколько пользователей больше не игнорируются + Начальный запрос на синхронизацию + Ветки помогают не терять нить беседы, и за ними легко следить.%sВключение веток обновит приложение. Может занять продолжительное время. + \ No newline at end of file From 096e51951a8d8c2728795b9023a1bd0fbf25274a Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Tue, 17 May 2022 16:20:52 +0000 Subject: [PATCH 074/244] Translated using Weblate (Slovak) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sk/ --- vector/src/main/res/values-sk/strings.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/values-sk/strings.xml b/vector/src/main/res/values-sk/strings.xml index a7a9f152fd..628d02ccd4 100644 --- a/vector/src/main/res/values-sk/strings.xml +++ b/vector/src/main/res/values-sk/strings.xml @@ -2385,7 +2385,7 @@ Hľadať názov Spätnú väzbu sa nepodarilo odoslať (%s) Zobraziť informácie o ladení chýb na obrazovke - Nahradiť farbu prezývky + Nahradiť farbu zobrazovaného mena Chcete sa pripojiť k existujúcemu serveru\? Udalosť bola upravená administrátorom miestnosti, dôvod: %1$s Táto miestnosť je momentálne neprístupná. @@ -2537,4 +2537,8 @@ \n \nUpozorňujeme, že táto akcia spôsobí reštart aplikácie a môže chvíľu trvať. Úvodná žiadosť o synchronizáciu - + Zobraziť najnovšie informácie o profile (obrázok a zobrazované meno) pre všetky správy. + Zobraziť najnovšie informácie o používateľovi + Obsadený/zaneprázdnený + Zálohovanie má platný podpis od tohto používateľa. + \ No newline at end of file From 3826b7ba2865262eae3f6ff5fee53f1e23817135 Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Fri, 20 May 2022 16:32:24 +0000 Subject: [PATCH 075/244] Translated using Weblate (Swedish) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sv/ --- vector/src/main/res/values-sv/strings.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/values-sv/strings.xml b/vector/src/main/res/values-sv/strings.xml index 5a05f73cf4..7c3eb549d8 100644 --- a/vector/src/main/res/values-sv/strings.xml +++ b/vector/src/main/res/values-sv/strings.xml @@ -2251,7 +2251,7 @@ Slutför inställning av upptäckbarhet. Du använder för närvarande ingen identitetsserver. För att bjuda in teammedlemmar och kunna upptäckas av dem, konfigurera en nedan. Bjud in med användarnamn eller e-postadress - Otillgänglig + Borta Offline Online Välj hemserver @@ -2490,4 +2490,8 @@ \n \nObservera att detta startar om appen, och kan ta ett tag. Förfrågan om inledande synk - + Visa den senaste profilinfon (avatar och visningsnamn) för alla meddelandena. + Visa senaste användarinfon + Upptagen + Säkerhetskopian har en giltig signatur från den här användaren. + \ No newline at end of file From b784c0fcc27da21a29af11c2bccf0cd2f8489b35 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Tue, 17 May 2022 17:38:47 +0000 Subject: [PATCH 076/244] Translated using Weblate (Ukrainian) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/uk/ --- vector/src/main/res/values-uk/strings.xml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-uk/strings.xml b/vector/src/main/res/values-uk/strings.xml index d9847bbb81..f3290460b4 100644 --- a/vector/src/main/res/values-uk/strings.xml +++ b/vector/src/main/res/values-uk/strings.xml @@ -2155,7 +2155,7 @@ Надіслати подію стану Надіслати власну подію Дізнатися стан кімнати - Недоступний + Відсутній Не в мережі У мережі Перегляд підтвердження прочитання @@ -2421,7 +2421,7 @@ Відкрити камеру Ваша система автоматично надсилатиме журнали, коли виникне помилка неможливості розшифрування Автозвіт про помилки шифрування. - Замінити колір псевдоніма + Замінити колір показуваного імені Я вже маю обліковий запис Захищене спілкування. Ви контролюєте все. @@ -2582,4 +2582,8 @@ \n \nЗауважте, що ця дія перезапустить застосунок, і це може тривати деякий час. Початковий запит синхронізації - + Показати найновіші відомості про профіль (аватар і показуване ім\'я) для всіх повідомлень. + Показати найновіші відомості про користувача + Зайнятий + Резервна копія має дійсний підпис від цього користувача. + \ No newline at end of file From 7d9cb1dc0cd7d656b2734797487e4e81ed55ea83 Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Wed, 18 May 2022 03:37:31 +0000 Subject: [PATCH 077/244] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hant/ --- vector/src/main/res/values-zh-rTW/strings.xml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-zh-rTW/strings.xml b/vector/src/main/res/values-zh-rTW/strings.xml index 8fd51266f5..fe77ba3f0a 100644 --- a/vector/src/main/res/values-zh-rTW/strings.xml +++ b/vector/src/main/res/values-zh-rTW/strings.xml @@ -2211,7 +2211,7 @@ 設定聊天室名稱 停止忽略使用者,繼續顯示他們的訊息 忽略使用者,為您隱藏他們的訊息 - 不可用 + 離開 離線 線上 選擇家伺服器 @@ -2288,7 +2288,7 @@ 開啟攝影機 發生無法解密錯誤時,您的系統將會自動傳送紀錄檔 自動回報解密錯誤。 - 覆寫暱稱色彩 + 覆寫顯示名稱色彩 我已有一個帳號 安全傳送訊息。 您已掌控了您的資料。 @@ -2443,4 +2443,8 @@ \n \n注意,此動作將會重新啟動應用程式,並可能需要一些時間。 初始同步請求 - + 顯示所有訊息的最新個人檔案資訊(大頭照與顯示名稱)。 + 顯示最新的使用者資訊 + 忙碌 + 備份具有來自該使用者的有效簽名。 + \ No newline at end of file From ddd6fc214fa04ec4ffc65235c64a22a0a1e6ea76 Mon Sep 17 00:00:00 2001 From: John Doe Date: Wed, 18 May 2022 13:57:48 +0000 Subject: [PATCH 078/244] Translated using Weblate (Spanish) Currently translated at 61.6% (37 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/es/ --- fastlane/metadata/android/es-ES/changelogs/40104140.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/es-ES/changelogs/40104140.txt diff --git a/fastlane/metadata/android/es-ES/changelogs/40104140.txt b/fastlane/metadata/android/es-ES/changelogs/40104140.txt new file mode 100644 index 0000000000..595cd6b3d4 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Cambios principales en esta versión: Mejoras en la administración de usuarios ignorados. Varias correciones de bugs y mejoras en la estabilidad. +Registro de cambios: https://github.com/vector-im/element-android/releases From a7a1645abe516310630648a8df38a21351414c08 Mon Sep 17 00:00:00 2001 From: lvre <7uu3qrbvm@relay.firefox.com> Date: Tue, 17 May 2022 16:11:24 +0000 Subject: [PATCH 079/244] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (60 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/pt_BR/ --- fastlane/metadata/android/pt-BR/changelogs/40104140.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/pt-BR/changelogs/40104140.txt diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104140.txt b/fastlane/metadata/android/pt-BR/changelogs/40104140.txt new file mode 100644 index 0000000000..ed1a53c910 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Melhorar gerenciamento de usuárias(os) ignoradas(os). Vários consertos de bugs e melhorias de estabilidade. +Changelog completo: https://github.com/vector-im/element-android/releases From 69aabb56a0a377063d1e8138eb32908911beba13 Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Tue, 17 May 2022 16:17:15 +0000 Subject: [PATCH 080/244] Translated using Weblate (Slovak) Currently translated at 100.0% (60 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sk/ --- fastlane/metadata/android/sk/changelogs/40104140.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/sk/changelogs/40104140.txt diff --git a/fastlane/metadata/android/sk/changelogs/40104140.txt b/fastlane/metadata/android/sk/changelogs/40104140.txt new file mode 100644 index 0000000000..e1c85961a4 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Zlepšenie správy ignorovaných používateľov. Rôzne opravy chýb a vylepšenia stability. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases From afa0090c78e48d056957fb7b3558eba138de2527 Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Fri, 20 May 2022 16:33:08 +0000 Subject: [PATCH 081/244] Translated using Weblate (Swedish) Currently translated at 100.0% (60 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sv/ --- fastlane/metadata/android/sv-SE/changelogs/40104140.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/sv-SE/changelogs/40104140.txt diff --git a/fastlane/metadata/android/sv-SE/changelogs/40104140.txt b/fastlane/metadata/android/sv-SE/changelogs/40104140.txt new file mode 100644 index 0000000000..9b58878dfb --- /dev/null +++ b/fastlane/metadata/android/sv-SE/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Huvudsakliga ändringar i den här versionen: Förbättra hantering av ignorerade användare. Diverse buggfixar och stabilitetsförbättringar. +Full ändringslogg: https://github.com/vector-im/element-android/releases From 311374d6422690925dc3003de647f900adc0d483 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Tue, 17 May 2022 17:36:45 +0000 Subject: [PATCH 082/244] Translated using Weblate (Ukrainian) Currently translated at 100.0% (60 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/uk/ --- fastlane/metadata/android/uk/changelogs/40104140.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/uk/changelogs/40104140.txt diff --git a/fastlane/metadata/android/uk/changelogs/40104140.txt b/fastlane/metadata/android/uk/changelogs/40104140.txt new file mode 100644 index 0000000000..293ad117e4 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Основні зміни у цій версії: Удосконалено керування нехтуваними користувачами. Різні виправлення помилок та поліпшення стабільності. +Вичерпний журнал змін: https://github.com/vector-im/element-android/releases From 90c78f1244e732cdc60cd924cbae1cb23a30f724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Tue, 17 May 2022 18:39:39 +0000 Subject: [PATCH 083/244] Translated using Weblate (Estonian) Currently translated at 100.0% (60 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/et/ --- fastlane/metadata/android/et/changelogs/40104140.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/et/changelogs/40104140.txt diff --git a/fastlane/metadata/android/et/changelogs/40104140.txt b/fastlane/metadata/android/et/changelogs/40104140.txt new file mode 100644 index 0000000000..9000616f38 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: eiratud kasutajate parem haldus ning erinevate vigade parandused ja stabiilsust edendavad kohendused. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases From bda822d2e5727d56a79532f670be36d6c496bb6d Mon Sep 17 00:00:00 2001 From: random Date: Wed, 18 May 2022 08:53:15 +0000 Subject: [PATCH 084/244] Translated using Weblate (Italian) Currently translated at 100.0% (60 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/it/ --- fastlane/metadata/android/it-IT/changelogs/40104140.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/it-IT/changelogs/40104140.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/40104140.txt b/fastlane/metadata/android/it-IT/changelogs/40104140.txt new file mode 100644 index 0000000000..ae367e72d0 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: migliorata la gestione degli utenti ignorati. Varie correzioni e miglioramenti della stabilità. +Cronologia completa: https://github.com/vector-im/element-android/releases From 182fae77da5a8d4e55ba73f702f26262169fb6be Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Wed, 18 May 2022 09:11:14 +0000 Subject: [PATCH 085/244] Translated using Weblate (Persian) Currently translated at 100.0% (60 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/fa/ --- fastlane/metadata/android/fa/changelogs/40104140.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/fa/changelogs/40104140.txt diff --git a/fastlane/metadata/android/fa/changelogs/40104140.txt b/fastlane/metadata/android/fa/changelogs/40104140.txt new file mode 100644 index 0000000000..cf5d7bc6ac --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40104140.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: مدیریت بهبودیافتهٔ کاربران چشم‌پوشیده. رفع اشکال‌های مختلف و بهبودهای پایداری. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases From cd27ea69bba269bfa9f662c002a61f0df2699f5d Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Wed, 18 May 2022 03:35:39 +0000 Subject: [PATCH 086/244] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (60 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/zh_Hant/ --- fastlane/metadata/android/zh-TW/changelogs/40104140.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/zh-TW/changelogs/40104140.txt diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104140.txt b/fastlane/metadata/android/zh-TW/changelogs/40104140.txt new file mode 100644 index 0000000000..ff830dab7c --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40104140.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:改善被忽略使用者的管理。多個臭蟲修復與穩定性改善。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases From 62dd47b15dc548ded098ff1d15a4ead8bf2ca5a6 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Wed, 18 May 2022 06:11:46 +0000 Subject: [PATCH 087/244] Translated using Weblate (Czech) Currently translated at 100.0% (60 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/cs/ --- fastlane/metadata/android/cs-CZ/changelogs/40104140.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/cs-CZ/changelogs/40104140.txt diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104140.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104140.txt new file mode 100644 index 0000000000..d369efa9f2 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Zlepšení správy ignorovaných uživatelů. Opravy různých chyb a vylepšení stability. +Úplný seznam změn: https://github.com/vector-im/element-android/releases From b1e045d911b6bf158c3aa12e88d83eb219d43d2c Mon Sep 17 00:00:00 2001 From: Linerly Date: Wed, 18 May 2022 18:35:39 +0000 Subject: [PATCH 088/244] Translated using Weblate (Indonesian) Currently translated at 100.0% (60 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/id/ --- fastlane/metadata/android/id/changelogs/40104140.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/id/changelogs/40104140.txt diff --git a/fastlane/metadata/android/id/changelogs/40104140.txt b/fastlane/metadata/android/id/changelogs/40104140.txt new file mode 100644 index 0000000000..174e8dcded --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Tingkatkan pengelolaan pengguna yang diabaikan. Beberapa perbaikan kutu dan stabilitas. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases From 94f2640f5c7e74234e452bd82694560fef839ee6 Mon Sep 17 00:00:00 2001 From: Piotr Strebski Date: Fri, 20 May 2022 09:45:53 +0000 Subject: [PATCH 089/244] Translated using Weblate (Polish) Currently translated at 66.6% (40 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/pl/ --- fastlane/metadata/android/pl-PL/changelogs/40101120.txt | 2 ++ fastlane/metadata/android/pl-PL/changelogs/40101130.txt | 2 ++ fastlane/metadata/android/pl-PL/changelogs/40101140.txt | 2 ++ fastlane/metadata/android/pl-PL/changelogs/40101150.txt | 2 ++ fastlane/metadata/android/pl-PL/changelogs/40101160.txt | 2 ++ fastlane/metadata/android/pl-PL/changelogs/40102000.txt | 2 ++ fastlane/metadata/android/pl-PL/changelogs/40102010.txt | 2 ++ fastlane/metadata/android/pl-PL/changelogs/40103000.txt | 2 ++ fastlane/metadata/android/pl-PL/changelogs/40103010.txt | 2 ++ fastlane/metadata/android/pl-PL/changelogs/40103020.txt | 2 ++ fastlane/metadata/android/pl-PL/changelogs/40103030.txt | 2 ++ fastlane/metadata/android/pl-PL/changelogs/40103040.txt | 2 ++ fastlane/metadata/android/pl-PL/changelogs/40104140.txt | 2 ++ 13 files changed, 26 insertions(+) create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40101120.txt create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40101130.txt create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40101140.txt create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40101150.txt create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40101160.txt create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40102000.txt create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40102010.txt create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40103000.txt create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40103010.txt create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40103020.txt create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40103030.txt create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40103040.txt create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40104140.txt diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101120.txt b/fastlane/metadata/android/pl-PL/changelogs/40101120.txt new file mode 100644 index 0000000000..6a62f1c6a9 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40101120.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: aktualizacja motywu i stylu oraz naprawa awarii po rozmowie wideo +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.12 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101130.txt b/fastlane/metadata/android/pl-PL/changelogs/40101130.txt new file mode 100644 index 0000000000..ec8d488eb8 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40101130.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: głównie aktualizacja stabilności i poprawki błędów. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.13 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101140.txt b/fastlane/metadata/android/pl-PL/changelogs/40101140.txt new file mode 100644 index 0000000000..c4c102da4a --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40101140.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: naprawienie problemu z zaszyfrowanymi wiadomościami. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.14 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101150.txt b/fastlane/metadata/android/pl-PL/changelogs/40101150.txt new file mode 100644 index 0000000000..2eb1a3f018 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40101150.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: implementacja wiadomości głosowych w ustawieniach laboratorium. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.15 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101160.txt b/fastlane/metadata/android/pl-PL/changelogs/40101160.txt new file mode 100644 index 0000000000..682da8be76 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40101160.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Naprawiono błąd podczas wysyłania zaszyfrowanej wiadomości, jeśli ktoś w pokoju się wyloguje. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.16 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40102000.txt b/fastlane/metadata/android/pl-PL/changelogs/40102000.txt new file mode 100644 index 0000000000..cdae0a4ba7 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40102000.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Wiadomość głosowa jest domyślnie włączona. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.2.0 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40102010.txt b/fastlane/metadata/android/pl-PL/changelogs/40102010.txt new file mode 100644 index 0000000000..0a825e8672 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40102010.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Wiele ulepszeń w VoIP i Przestrzeniach (nadal w wersji beta). +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.2.1 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103000.txt b/fastlane/metadata/android/pl-PL/changelogs/40103000.txt new file mode 100644 index 0000000000..8b408ced72 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103000.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Organizuj swoje pokoje za pomocą Przestrzeni! +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.0 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103010.txt b/fastlane/metadata/android/pl-PL/changelogs/40103010.txt new file mode 100644 index 0000000000..0a49e7fa68 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103010.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Organizuj swoje pokoje za pomocą Przestrzeni! Wersja 1.3.1 naprawia awarię, która może wystąpić w wersji 1.3.0. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.1 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103020.txt b/fastlane/metadata/android/pl-PL/changelogs/40103020.txt new file mode 100644 index 0000000000..3e37f64b76 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103020.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Dodano obsługę Android Auto. Wiele poprawek błędów! +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.2 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103030.txt b/fastlane/metadata/android/pl-PL/changelogs/40103030.txt new file mode 100644 index 0000000000..8f80d95b5a --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103030.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Uwidocznij politykę(-i) serwera tożsamości w ustawieniach. Tymczasowo usunięto obsługę Androida Auto. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.3 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103040.txt b/fastlane/metadata/android/pl-PL/changelogs/40103040.txt new file mode 100644 index 0000000000..13458a7b2d --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103040.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Dodanie obsługi obecności, dla pokoju wiadomości bezpośrednich (uwaga: obecność jest wyłączona na matrix.org). Dodano ponownie obsługę Androida Auto. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.4 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40104140.txt b/fastlane/metadata/android/pl-PL/changelogs/40104140.txt new file mode 100644 index 0000000000..84ab57a2ac --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Poprawa zarządzania ignorowanymi użytkownikami. Różne poprawki błędów i ulepszenia stabilności. +Pełna lista zmian: https://github.com/vector-im/element-android/releases From 9779e9b9a5df2abdc986470f7bfda6870335862f Mon Sep 17 00:00:00 2001 From: anoloth Date: Thu, 19 May 2022 09:42:57 +0000 Subject: [PATCH 090/244] Translated using Weblate (Lao) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/lo/ --- vector/src/main/res/values-lo/strings.xml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-lo/strings.xml b/vector/src/main/res/values-lo/strings.xml index 3d12927ac7..c22e5edf86 100644 --- a/vector/src/main/res/values-lo/strings.xml +++ b/vector/src/main/res/values-lo/strings.xml @@ -2018,7 +2018,7 @@ ສົ່ງເຫດການທີ່ກຳນົດເອງ ສຳຫຼວດສະຖານະຫ້ອງ ເຄື່ອງມືພັດທະນາ - ບໍ່ສາມາດໃຊ້ໄດ້ + ບໍ່ຢູ່ ອອຟລາຍ ອອນລາຍ ຫ້ອງສາທາລະນະ @@ -2243,7 +2243,7 @@ ກຳນົດເອງ ຜູ້ຄວບຄຸມ ຜູ້ເບິ່ງແຍງລະບົບ - ລົບລ້າງສີ nick + ໂຊທັບສີຂອງຊື່ນີ້ ກຳລັງອອກຈາກຫ້ອງ… ອອກໄປ ອອກຈາກຫ້ອງ @@ -2441,4 +2441,8 @@ ຢຸດການບັນທຶກ ຢຸດຂໍ້ຄວາມສຽງຊົ່ວຄາວ ຫຼິ້ນຂໍ້ຄວາມສຽງ - + ໂຊຂໍ້ມູນໂປຟາຍລ້າສຸດ (ໂຕກະຕູນ ແລະ ຊື່ສະແດງ) ສຳລັບທຸກໆຂໍ້ຄວາມ. + ໂຊຂໍ້ມູນຜູ້ໃຊ້ລ້າສຸດ + ບໍ່ວ່າງ + ແບັກອັບມີລາຍເຊັນຖືກຕ້ອງຈາກຜູ້ໃຊ້ນີ້. + \ No newline at end of file From 5e359101d243941423d3c321c66403aae80e8b87 Mon Sep 17 00:00:00 2001 From: anoloth Date: Thu, 19 May 2022 09:39:39 +0000 Subject: [PATCH 091/244] Translated using Weblate (Lao) Currently translated at 100.0% (60 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/lo/ --- fastlane/metadata/android/lo/changelogs/40104140.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/lo/changelogs/40104140.txt diff --git a/fastlane/metadata/android/lo/changelogs/40104140.txt b/fastlane/metadata/android/lo/changelogs/40104140.txt new file mode 100644 index 0000000000..e8c8d84031 --- /dev/null +++ b/fastlane/metadata/android/lo/changelogs/40104140.txt @@ -0,0 +1,2 @@ +ການປ່ຽນແປງຫຼັກໃນສະບັບນີ້: ປັບປຸງການບໍລິຫານການລະເວັ້ນຜູ້ໃຊ້. ປັບປຸງບັກ ແລະຄວາມສະຖຽນ. +ບັນທຶກການປ່ຽນແປງສະບັບເຕັມ: https://github.com/vector-im/element-android/releases From 76fc3b53361068c4e9483720c26e9bc5dfe6b019 Mon Sep 17 00:00:00 2001 From: "Auri B. P" Date: Sat, 21 May 2022 20:07:04 +0000 Subject: [PATCH 092/244] Translated using Weblate (Catalan) Currently translated at 83.3% (1855 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ca/ --- vector/src/main/res/values-ca/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/vector/src/main/res/values-ca/strings.xml b/vector/src/main/res/values-ca/strings.xml index 167b41d1dc..8b3223ed26 100644 --- a/vector/src/main/res/values-ca/strings.xml +++ b/vector/src/main/res/values-ca/strings.xml @@ -2085,4 +2085,5 @@ S\'ha produït un error en provar d\'entrar a: %s Actualitza a la versió de sala recomanada Aquesta sala té la versió %s, la qual està marcada com a no estable pel servidor. + Només amb invitació, per tu o per equips \ No newline at end of file From a07c1b8afa9f54629b7267ab7dc3f0e05256a665 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Mon, 23 May 2022 13:46:53 +0100 Subject: [PATCH 093/244] Removes top bar back arrow --- .../vector/app/features/home/HomeDetailFragment.kt | 8 -------- .../src/main/res/layout/fragment_home_detail.xml | 14 -------------- 2 files changed, 22 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt index 213c9fe193..4eedb528d1 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt @@ -145,10 +145,6 @@ class HomeDetailFragment @Inject constructor( updateTabVisibilitySafely(R.id.bottom_action_dial_pad, showDialPadTab) } - views.groupToolbarNavigateUp.setOnClickListener { - navigateBack() - } - viewModel.observeViewEvents { viewEvent -> when (viewEvent) { HomeDetailViewEvents.CallStarted -> handleCallStarted() @@ -307,13 +303,9 @@ class HomeDetailFragment @Inject constructor( private fun onSpaceChange(spaceSummary: RoomSummary?) { if (spaceSummary == null) { views.groupToolbarSpaceTitleView.isVisible = false - views.groupToolbarAvatarImageView.isVisible = true - views.groupToolbarNavigateUp.isVisible = false } else { views.groupToolbarSpaceTitleView.isVisible = true views.groupToolbarSpaceTitleView.text = spaceSummary.displayName - views.groupToolbarAvatarImageView.isVisible = false - views.groupToolbarNavigateUp.isVisible = true } } diff --git a/vector/src/main/res/layout/fragment_home_detail.xml b/vector/src/main/res/layout/fragment_home_detail.xml index 301abef4b8..e3db68434e 100644 --- a/vector/src/main/res/layout/fragment_home_detail.xml +++ b/vector/src/main/res/layout/fragment_home_detail.xml @@ -74,20 +74,6 @@ - - Date: Tue, 24 May 2022 14:12:49 +1200 Subject: [PATCH 094/244] Fix grammar in strings in strings.xml `room_list_people_empty_body` and `room_list_rooms_empty_body` --- vector/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 63d4730dc5..24e984a6bc 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1584,9 +1584,9 @@ You’re all caught up! You have no more unread messages Conversations - Your direct message conversations will be displayed here. Tap the + bottom right to start some. + Your direct message conversations will be displayed here. Tap the + at the bottom right to start some. Rooms - Your rooms will be displayed here. Tap the + bottom right to find existing ones or start some of your own. + Your rooms will be displayed here. Tap the + at the bottom right to find existing ones or start some of your own. Reactions Add Reaction From 3b1a7f93cbad810000b4a13d65dc94301989c7ae Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 24 May 2022 14:40:13 +1200 Subject: [PATCH 095/244] Create 6132.misc --- changelog.d/6132.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6132.misc diff --git a/changelog.d/6132.misc b/changelog.d/6132.misc new file mode 100644 index 0000000000..4bcfb224ef --- /dev/null +++ b/changelog.d/6132.misc @@ -0,0 +1 @@ +Fixed grammar errors in /vector/src/main/res/values/strings.xml From d0628129f5704505890495cf4c56d2b95aba8fa2 Mon Sep 17 00:00:00 2001 From: Jean-Luc KABORE-TURQUIN Date: Wed, 25 May 2022 07:14:49 +0000 Subject: [PATCH 096/244] Translated using Weblate (French) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fr/ --- vector/src/main/res/values-fr/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-fr/strings.xml b/vector/src/main/res/values-fr/strings.xml index fc41b217c1..c7b1b8c797 100644 --- a/vector/src/main/res/values-fr/strings.xml +++ b/vector/src/main/res/values-fr/strings.xml @@ -2454,4 +2454,5 @@ \nPour nous y préparer, nous avons besoin de faire certains changements : les fils créés avant maintenant seront affichés comme des réponses classiques. \n \nCette transition sera unique, maintenant que les fils de discussions ont intégré la spécification de Matrix. - + Partage d\'écran en cours + \ No newline at end of file From 71706bc6a65d54ebca42ffb935eabd739a1f0660 Mon Sep 17 00:00:00 2001 From: Glandos Date: Wed, 25 May 2022 07:14:30 +0000 Subject: [PATCH 097/244] Translated using Weblate (French) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fr/ --- vector/src/main/res/values-fr/strings.xml | 51 ++++++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/vector/src/main/res/values-fr/strings.xml b/vector/src/main/res/values-fr/strings.xml index c7b1b8c797..4cf1b89b84 100644 --- a/vector/src/main/res/values-fr/strings.xml +++ b/vector/src/main/res/values-fr/strings.xml @@ -407,9 +407,7 @@ Paramètres utilisateur %1$s @ %2$s Vérifiez votre courriel et cliquez sur le lien qu’il contient. Une fois ceci fait, cliquez sur continuer. - Afficher tous les messages de %s \? -\n -\nVeuillez noter que cette action redémarrera l’application et pourra prendre un certain temps. + Afficher tous les messages de %s \? Qui peut lire l’historique \? Uniquement les membres (à partir de l’activation de cette option) Uniquement les membres (depuis leur invitation) @@ -1683,7 +1681,7 @@ Adresses électroniques Aucun numéro de téléphone n’a été ajouté à votre compte Filtrer les utilisateurs exclus - Ne plus ignorer cet utilisateur aura pour effet de ré-afficher ses messages. + Ne plus ignorer cet utilisateur affichera à nouveau ses messages. expulser un utilisateur le supprimera de ce salon. \n \nPour l’empêcher de revenir, vous devez plutôt le bannir. @@ -2253,7 +2251,7 @@ L’expulsion des utilisateurs va les supprimer de cet espace \n \nPour les empêcher de revenir, vous devriez les exclure. - Indisponible + Absent Hors ligne En ligne Choisir un serveur d’accueil @@ -2334,7 +2332,7 @@ Activer les mathématiques LaTeX Votre système enverra automatiquement des informations dès qu’une erreur de déchiffrement de message se présente Signalement automatique des erreurs de déchiffrement. - Outrepasser la couleur du pseudo + Outrepasser la couleur du pseudonyme J’ai déjà un compte Messagerie sécurisée. Vous êtes aux commandes. @@ -2455,4 +2453,45 @@ \n \nCette transition sera unique, maintenant que les fils de discussions ont intégré la spécification de Matrix. Partage d\'écran en cours + Partage d’écran pour ${app_name} + Chargement de la position en direct… + 8 heures + 1 heure + 15 minutes + Partager votre position en direct pendant + (%1$s) + %1$s (%2$s) + Impossible de lire %1$s + Pause %1$s + Lire %1$s + %1$d minutes %2$d secondes + %1$s, %2$s, %3$s + Afficher les informations des profils les plus récentes (avatar et nom d’affichage) pour tous les messages. + Afficher les informations utilisateurs les plus récentes + Occupé + On partagé leur position en direct + ${app_name} est parfaite pour le bureau. Les sociétés aux plus gros besoins de sécurité lui font confiance. + BÊTA + Les fils de discussion sont en cours de développement avec des fonctionnalités nouvelles et excitantes à venir, telles que des notifications améliorées. Nous adorerions avoir vos remarques ! + Remarques sur les fils de discussion Bêta + Emvoyer des remarques + BÊTA + La sauvegarde a une signature valide de cet utilisateur. + Si active, vous apparaîtrez toujours hors-ligne aux autres utilisateurs, même lorsque vous utilisez l’application. + Mode hors-ligne + Présence + Votre serveur d\'accueil ne prend pas actuellement en charge les fils de discussions, cette fonctionnalité peut donc ne pas être fiable. Certains messages dans les fils de discussions peuvent ne pas être disponibles de manière fiable. %sVoulez-vous activer les fils de discussion malgré tout \? + Fils de discussion Bêta + Les fils de discussion vous permettent de recentrer vos conversations et de les rendre facile à suivre. %sActiver les fils de discussion rechargera l’application. Cela peut prendre du temps pour certains comptes. + Fils de discussion Bêta + – Certains utilisateurs ne sont plus ignorés + Arrêter le partage d’écran + Partager l’écran + En savoir plus + Essayer + ${app_name} a besoin d’effacer le cache pour la mise-à-jour, pour la raison suivante : +\n%s +\n +\nCette action va redémarrer l’application et pourra prendre du temps. + Requête de synchronisation initiale \ No newline at end of file From 59c13bf8c1b98b5ed0b9eb73743c82ebaea291ae Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Wed, 25 May 2022 12:35:43 +0200 Subject: [PATCH 098/244] Make widget web view request system permissions for camera and microphone Previously the widget web view prompted to grant the widget permissions but it didn't actually request those permissions from the system. So if the web view requested, e.g. the camera permission but the app hadn't previously been granted that permission, the web view wouldn't get camera access even when the widget permission request had been confirmed. With this commit, the app will also request camera and microphone permissions from the system when needed. Signed-off-by: Johannes Marbach --- .../webview/WebChromeEventListener.kt | 32 ++++++++++ .../app/features/widgets/WidgetFragment.kt | 20 +++++- .../widgets/webview/WebviewPermissionUtils.kt | 61 ++++++++++++++++++- .../features/widgets/webview/WidgetWebView.kt | 5 +- 4 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/webview/WebChromeEventListener.kt diff --git a/vector/src/main/java/im/vector/app/features/webview/WebChromeEventListener.kt b/vector/src/main/java/im/vector/app/features/webview/WebChromeEventListener.kt new file mode 100644 index 0000000000..8a12052def --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/webview/WebChromeEventListener.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.webview + +import android.webkit.PermissionRequest + +interface WebChromeEventListener { + + /** + * Triggered when the web view requests permissions. + * + * @param request The permission request. + */ + fun onPermissionRequest(request: PermissionRequest) { + // NO-OP + } + +} diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt index cd2a4dcdf4..c8a13d11cf 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt @@ -26,6 +26,8 @@ import android.view.Menu import android.view.MenuItem import android.view.View import android.view.ViewGroup +import android.webkit.PermissionRequest +import androidx.activity.result.contract.ActivityResultContracts import androidx.core.view.isInvisible import androidx.core.view.isVisible import com.airbnb.mvrx.Fail @@ -42,7 +44,9 @@ import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.openUrlInExternalBrowser import im.vector.app.databinding.FragmentRoomWidgetBinding +import im.vector.app.features.webview.WebChromeEventListener import im.vector.app.features.webview.WebViewEventListener +import im.vector.app.features.widgets.webview.WebviewPermissionUtils import im.vector.app.features.widgets.webview.clearAfterWidget import im.vector.app.features.widgets.webview.setupForWidget import kotlinx.parcelize.Parcelize @@ -63,6 +67,7 @@ data class WidgetArgs( class WidgetFragment @Inject constructor() : VectorBaseFragment(), WebViewEventListener, + WebChromeEventListener, OnBackPressed { private val fragmentArgs: WidgetArgs by args() @@ -75,7 +80,7 @@ class WidgetFragment @Inject constructor() : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setHasOptionsMenu(true) - views.widgetWebView.setupForWidget(this) + views.widgetWebView.setupForWidget(this, this) if (fragmentArgs.kind.isAdmin()) { viewModel.getPostAPIMediator().setWebView(views.widgetWebView) } @@ -271,6 +276,19 @@ class WidgetFragment @Inject constructor() : viewModel.handle(WidgetAction.OnWebViewLoadingError(url, true, errorCode, description)) } + private val permissionResultLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result -> + WebviewPermissionUtils.onPermissionResult(result) + } + + override fun onPermissionRequest(request: PermissionRequest) { + WebviewPermissionUtils.promptForPermissions( + title = R.string.room_widget_resource_permission_title, + request = request, + context = requireContext(), + activity = requireActivity(), + activityResultLauncher = permissionResultLauncher) + } + private fun displayTerms(displayTerms: WidgetViewEvents.DisplayTerms) { navigator.openTerms( context = requireContext(), diff --git a/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt b/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt index 12b58cc208..f1111a4650 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt @@ -15,17 +15,30 @@ */ package im.vector.app.features.widgets.webview +import android.Manifest import android.annotation.SuppressLint import android.content.Context import android.webkit.PermissionRequest +import androidx.activity.result.ActivityResultLauncher import androidx.annotation.StringRes +import androidx.fragment.app.FragmentActivity import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R +import im.vector.app.core.utils.checkPermissions object WebviewPermissionUtils { + private var permissionRequest: PermissionRequest? = null + private var selectedPermissions = listOf() + @SuppressLint("NewApi") - fun promptForPermissions(@StringRes title: Int, request: PermissionRequest, context: Context) { + fun promptForPermissions( + @StringRes title: Int, + request: PermissionRequest, + context: Context, + activity: FragmentActivity, + activityResultLauncher: ActivityResultLauncher> + ) { val allowedPermissions = request.resources.map { it to false }.toMutableList() @@ -37,9 +50,21 @@ object WebviewPermissionUtils { allowedPermissions[which] = allowedPermissions[which].first to isChecked } .setPositiveButton(R.string.room_widget_resource_grant_permission) { _, _ -> - request.grant(allowedPermissions.mapNotNull { perm -> + permissionRequest = request + selectedPermissions = allowedPermissions.mapNotNull { perm -> perm.first.takeIf { perm.second } - }.toTypedArray()) + } + + val requiredAndroidPermissions = selectedPermissions.mapNotNull { permission -> + webPermissionToAndroidPermission(permission) + } + + // When checkPermissions returns false, some of the required Android permissions will + // have to be requested and the flow completes asynchronously via onPermissionResult + if (checkPermissions(requiredAndroidPermissions, activity, activityResultLauncher)) { + request.grant(selectedPermissions.toTypedArray()) + reset() + } } .setNegativeButton(R.string.room_widget_resource_decline_permission) { _, _ -> request.deny() @@ -47,6 +72,28 @@ object WebviewPermissionUtils { .show() } + fun onPermissionResult(result: Map) { + permissionRequest?.let { request -> + val grantedPermissions = selectedPermissions.filter { webPermission -> + val androidPermission = webPermissionToAndroidPermission(webPermission) + ?: return@filter true // No corresponding Android permission exists + return@filter result[androidPermission] + ?: return@filter true // Android permission already granted before + } + if (grantedPermissions.isNotEmpty()) { + request.grant(grantedPermissions.toTypedArray()) + } else { + request.deny() + } + reset() + } + } + + private fun reset() { + permissionRequest = null + selectedPermissions = listOf() + } + private fun webPermissionToHumanReadable(permission: String, context: Context): String { return when (permission) { PermissionRequest.RESOURCE_AUDIO_CAPTURE -> context.getString(R.string.room_widget_webview_access_microphone) @@ -55,4 +102,12 @@ object WebviewPermissionUtils { else -> permission } } + + private fun webPermissionToAndroidPermission(permission: String): String? { + return when (permission) { + PermissionRequest.RESOURCE_AUDIO_CAPTURE -> Manifest.permission.RECORD_AUDIO + PermissionRequest.RESOURCE_VIDEO_CAPTURE -> Manifest.permission.CAMERA + else -> null + } + } } diff --git a/vector/src/main/java/im/vector/app/features/widgets/webview/WidgetWebView.kt b/vector/src/main/java/im/vector/app/features/widgets/webview/WidgetWebView.kt index 7147529e5f..a49eb802da 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/webview/WidgetWebView.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/webview/WidgetWebView.kt @@ -25,10 +25,11 @@ import android.webkit.WebView import im.vector.app.R import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.webview.VectorWebViewClient +import im.vector.app.features.webview.WebChromeEventListener import im.vector.app.features.webview.WebViewEventListener @SuppressLint("NewApi") -fun WebView.setupForWidget(webViewEventListener: WebViewEventListener) { +fun WebView.setupForWidget(webViewEventListener: WebViewEventListener, webChromeEventListener: WebChromeEventListener) { // xml value seems ignored setBackgroundColor(ThemeUtils.getColor(context, R.attr.colorSurface)) @@ -59,7 +60,7 @@ fun WebView.setupForWidget(webViewEventListener: WebViewEventListener) { // Permission requests webChromeClient = object : WebChromeClient() { override fun onPermissionRequest(request: PermissionRequest) { - WebviewPermissionUtils.promptForPermissions(R.string.room_widget_resource_permission_title, request, context) + webChromeEventListener.onPermissionRequest(request) } } webViewClient = VectorWebViewClient(webViewEventListener) From 946902719b3229e6b555d8843c296bd145cbf870 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Wed, 25 May 2022 12:53:47 +0200 Subject: [PATCH 099/244] Add changelog entry --- changelog.d/6149.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6149.bugfix diff --git a/changelog.d/6149.bugfix b/changelog.d/6149.bugfix new file mode 100644 index 0000000000..c255a8daee --- /dev/null +++ b/changelog.d/6149.bugfix @@ -0,0 +1 @@ +Make widget web view request system permissions for camera and microphone (PSF-1061) From 580bbd60e73837a7887a8e4fb2679b23bb99dcd0 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Wed, 25 May 2022 13:01:42 +0200 Subject: [PATCH 100/244] Appease the linter --- .../im/vector/app/features/webview/WebChromeEventListener.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/webview/WebChromeEventListener.kt b/vector/src/main/java/im/vector/app/features/webview/WebChromeEventListener.kt index 8a12052def..cc9725abc4 100644 --- a/vector/src/main/java/im/vector/app/features/webview/WebChromeEventListener.kt +++ b/vector/src/main/java/im/vector/app/features/webview/WebChromeEventListener.kt @@ -28,5 +28,4 @@ interface WebChromeEventListener { fun onPermissionRequest(request: PermissionRequest) { // NO-OP } - } From cf90ff9fd2bef649ca8dcfb2b78e23a667cf9a1d Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 11 May 2022 14:07:05 +0200 Subject: [PATCH 101/244] Adding changelog entry --- changelog.d/6012.wip | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.d/6012.wip b/changelog.d/6012.wip index 9c67d562fe..783ca6d46a 100644 --- a/changelog.d/6012.wip +++ b/changelog.d/6012.wip @@ -1 +1,2 @@ Live location sharing: navigation from timeline to map screen +Live location sharing: show user pins on map screen From 44ca82bbef801ed29d68e5c6d621258738a23f68 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 11 May 2022 15:25:58 +0200 Subject: [PATCH 102/244] Adding ViewModel to Activity --- .../app/core/di/MavericksViewModelModule.kt | 6 +++ .../live/map/LocationLiveMapAction.kt | 21 ++++++++ .../live/map/LocationLiveMapViewEvents.kt | 21 ++++++++ .../live/map/LocationLiveMapViewModel.kt | 50 +++++++++++++++++++ .../live/map/LocationLiveMapViewState.kt | 34 +++++++++++++ 5 files changed, 132 insertions(+) create mode 100644 vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapAction.kt create mode 100644 vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewEvents.kt create mode 100644 vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt create mode 100644 vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt diff --git a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt index 33afcf1dfb..313fd7b98c 100644 --- a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt @@ -54,6 +54,7 @@ import im.vector.app.features.home.room.list.RoomListViewModel import im.vector.app.features.homeserver.HomeServerCapabilitiesViewModel import im.vector.app.features.invite.InviteUsersToRoomViewModel import im.vector.app.features.location.LocationSharingViewModel +import im.vector.app.features.location.live.map.LocationLiveMapViewModel import im.vector.app.features.login.LoginViewModel import im.vector.app.features.login2.LoginViewModel2 import im.vector.app.features.login2.created.AccountCreatedViewModel @@ -600,4 +601,9 @@ interface MavericksViewModelModule { @IntoMap @MavericksViewModelKey(VectorAttachmentViewerViewModel::class) fun vectorAttachmentViewerViewModelFactory(factory: VectorAttachmentViewerViewModel.Factory): MavericksAssistedViewModelFactory<*, *> + + @Binds + @IntoMap + @MavericksViewModelKey(LocationLiveMapViewModel::class) + fun locationLiveMapViewModelFactory(factory: LocationLiveMapViewModel.Factory): MavericksAssistedViewModelFactory<*, *> } diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapAction.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapAction.kt new file mode 100644 index 0000000000..a31e02611f --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapAction.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.location.live.map + +import im.vector.app.core.platform.VectorViewModelAction + +sealed interface LocationLiveMapAction : VectorViewModelAction diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewEvents.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewEvents.kt new file mode 100644 index 0000000000..6645ff58d9 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewEvents.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.location.live.map + +import im.vector.app.core.platform.VectorViewEvents + +sealed interface LocationLiveMapViewEvents : VectorViewEvents diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt new file mode 100644 index 0000000000..e9b9cc8259 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.location.live.map + +import com.airbnb.mvrx.MavericksViewModelFactory +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import im.vector.app.core.di.MavericksAssistedViewModelFactory +import im.vector.app.core.di.hiltMavericksViewModelFactory +import im.vector.app.core.platform.VectorViewModel +import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider +import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.getRoom + +class LocationLiveMapViewModel @AssistedInject constructor( + @Assisted private val initialState: LocationLiveMapViewState, +) : VectorViewModel(initialState) { + + // TODO create useCase to get Flow of user live location in room => Mock data for now + + @AssistedFactory + interface Factory : MavericksAssistedViewModelFactory { + override fun create(initialState: LocationLiveMapViewState): LocationLiveMapViewModel + } + + companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() + + init { + // TODO call use case to collect flow of user live location + } + + override fun handle(action: LocationLiveMapAction) { + // do nothing, no action for now + } +} diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt new file mode 100644 index 0000000000..d6e58b2486 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.location.live.map + +import com.airbnb.mvrx.MavericksState +import im.vector.app.features.location.LocationData + +data class LocationLiveMapViewState( + val roomId: String, + val userLocations: List = emptyList() +) : MavericksState { + constructor(locationLiveMapViewArgs: LocationLiveMapViewArgs) : this( + roomId = locationLiveMapViewArgs.roomId + ) +} + +data class UserLiveLocationViewState( + val userId: String, + val locationData: LocationData +) From d6029210d00f65ba99a9d1670e5817632779ea92 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 11 May 2022 16:15:45 +0200 Subject: [PATCH 103/244] Adding use case to get live location of users --- .../map/GetCurrentUserLiveLocationUseCase.kt | 49 +++++++++++++++++++ .../live/map/LocationLiveMapViewModel.kt | 13 ++--- 2 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/location/live/map/GetCurrentUserLiveLocationUseCase.kt diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/GetCurrentUserLiveLocationUseCase.kt b/vector/src/main/java/im/vector/app/features/location/live/map/GetCurrentUserLiveLocationUseCase.kt new file mode 100644 index 0000000000..3f12fb9181 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/live/map/GetCurrentUserLiveLocationUseCase.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.location.live.map + +import im.vector.app.features.location.LocationData +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import javax.inject.Inject + +class GetCurrentUserLiveLocationUseCase @Inject constructor() { + + // TODO add unit tests + fun execute(): Flow> { + // TODO get room and call SDK to get the correct flow + return flow { + val user1 = UserLiveLocationViewState( + userId = "user1", + locationData = LocationData( + latitude = 48.863447, + longitude = 2.328608, + uncertainty = null + ) + ) + val user2 = UserLiveLocationViewState( + userId = "user2", + locationData = LocationData( + latitude = 48.843816, + longitude = 2.359235, + uncertainty = null + ) + ) + emit(listOf(user1, user2)) + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt index e9b9cc8259..c33e708d6b 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt @@ -23,16 +23,15 @@ import dagger.assisted.AssistedInject import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel -import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider -import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.getRoom +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +// TODO add unit tests class LocationLiveMapViewModel @AssistedInject constructor( @Assisted private val initialState: LocationLiveMapViewState, + getCurrentUserLiveLocationUseCase: GetCurrentUserLiveLocationUseCase ) : VectorViewModel(initialState) { - // TODO create useCase to get Flow of user live location in room => Mock data for now - @AssistedFactory interface Factory : MavericksAssistedViewModelFactory { override fun create(initialState: LocationLiveMapViewState): LocationLiveMapViewModel @@ -41,7 +40,9 @@ class LocationLiveMapViewModel @AssistedInject constructor( companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() init { - // TODO call use case to collect flow of user live location + getCurrentUserLiveLocationUseCase.execute() + .onEach { setState { copy(userLocations = it) } } + .launchIn(viewModelScope) } override fun handle(action: LocationLiveMapAction) { From 5410b61ae32b9d645b789ecbbd79e54a037fbbfc Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Thu, 12 May 2022 09:27:01 +0200 Subject: [PATCH 104/244] Show user pins with correct zoom when map is first opened --- .../map/GetCurrentUserLiveLocationUseCase.kt | 49 ----------- .../map/GetListOfUserLiveLocationUseCase.kt | 66 ++++++++++++++ .../live/map/LocationLiveMapViewFragment.kt | 87 ++++++++++++++++++- .../live/map/LocationLiveMapViewModel.kt | 4 +- .../live/map/LocationLiveMapViewState.kt | 2 + 5 files changed, 155 insertions(+), 53 deletions(-) delete mode 100644 vector/src/main/java/im/vector/app/features/location/live/map/GetCurrentUserLiveLocationUseCase.kt create mode 100644 vector/src/main/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCase.kt diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/GetCurrentUserLiveLocationUseCase.kt b/vector/src/main/java/im/vector/app/features/location/live/map/GetCurrentUserLiveLocationUseCase.kt deleted file mode 100644 index 3f12fb9181..0000000000 --- a/vector/src/main/java/im/vector/app/features/location/live/map/GetCurrentUserLiveLocationUseCase.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2022 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.vector.app.features.location.live.map - -import im.vector.app.features.location.LocationData -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import javax.inject.Inject - -class GetCurrentUserLiveLocationUseCase @Inject constructor() { - - // TODO add unit tests - fun execute(): Flow> { - // TODO get room and call SDK to get the correct flow - return flow { - val user1 = UserLiveLocationViewState( - userId = "user1", - locationData = LocationData( - latitude = 48.863447, - longitude = 2.328608, - uncertainty = null - ) - ) - val user2 = UserLiveLocationViewState( - userId = "user2", - locationData = LocationData( - latitude = 48.843816, - longitude = 2.359235, - uncertainty = null - ) - ) - emit(listOf(user1, user2)) - } - } -} diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCase.kt b/vector/src/main/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCase.kt new file mode 100644 index 0000000000..2505ba11a4 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCase.kt @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.location.live.map + +import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider +import im.vector.app.features.location.LocationData +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.trySendBlocking +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.callbackFlow +import org.matrix.android.sdk.api.session.Session +import javax.inject.Inject + +class GetListOfUserLiveLocationUseCase @Inject constructor( + private val session: Session, + private val locationPinProvider: LocationPinProvider +) { + + // TODO add unit tests + fun execute(): Flow> { + // TODO get room and call SDK to get the correct flow of locations + + return callbackFlow { + val myUserId = session.myUserId + + locationPinProvider.create(myUserId) { pinDrawable -> + val user1 = UserLiveLocationViewState( + userId = session.myUserId, + pinDrawable = pinDrawable, + locationData = LocationData( + latitude = 48.863447, + longitude = 2.328608, + uncertainty = null + ) + ) + val user2 = UserLiveLocationViewState( + userId = session.myUserId, + pinDrawable = pinDrawable, + locationData = LocationData( + latitude = 48.843816, + longitude = 2.359235, + uncertainty = null + ) + ) + val userLocations = listOf(user1, user2) + trySendBlocking(userLocations) + channel.close() + } + awaitClose() + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt index 32b87727d8..8ba4cdb5d2 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt @@ -16,20 +16,34 @@ package im.vector.app.features.location.live.map +import android.graphics.drawable.Drawable import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.args +import com.airbnb.mvrx.fragmentViewModel +import com.airbnb.mvrx.withState +import com.mapbox.mapboxsdk.camera.CameraPosition +import com.mapbox.mapboxsdk.constants.MapboxConstants +import com.mapbox.mapboxsdk.geometry.LatLng +import com.mapbox.mapboxsdk.geometry.LatLngBounds +import com.mapbox.mapboxsdk.maps.MapView +import com.mapbox.mapboxsdk.maps.MapboxMap import com.mapbox.mapboxsdk.maps.MapboxMapOptions +import com.mapbox.mapboxsdk.maps.Style import com.mapbox.mapboxsdk.maps.SupportMapFragment import dagger.hilt.android.AndroidEntryPoint +import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager +import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions +import com.mapbox.mapboxsdk.style.layers.Property import im.vector.app.R import im.vector.app.core.extensions.addChildFragment import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSimpleContainerBinding import im.vector.app.features.location.UrlMapProvider +import java.lang.ref.WeakReference import javax.inject.Inject /** @@ -43,6 +57,14 @@ class LocationLiveMapViewFragment : VectorBaseFragment? = null + private var symbolManager: SymbolManager? = null + private var mapStyle: Style? = null + private val pendingLiveLocations = mutableListOf() + private var isMapFirstUpdate = true + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSimpleContainerBinding { return FragmentSimpleContainerBinding.inflate(layoutInflater, container, false) } @@ -55,9 +77,70 @@ class LocationLiveMapViewFragment : VectorBaseFragment + mapFragment.getMapAsync { mapboxMap -> lifecycleScope.launchWhenCreated { - mapBoxMap.setStyle(urlMapProvider.getMapUrl()) + mapboxMap.setStyle(urlMapProvider.getMapUrl()) { style -> + mapStyle = style + this@LocationLiveMapViewFragment.mapboxMap = WeakReference(mapboxMap) + symbolManager = SymbolManager(mapFragment.view as MapView, mapboxMap, style) + pendingLiveLocations + .takeUnless { it.isEmpty() } + ?.let { updateMap(it) } + } + } + } + } + + override fun invalidate() = withState(viewModel) { viewState -> + updateMap(viewState.userLocations) + } + + private fun updateMap(userLiveLocations: List) { + symbolManager?.let { + it.deleteAll() + + val latLngBoundsBuilder = LatLngBounds.Builder() + userLiveLocations.forEach { userLocation -> + addUserPinToMapStyle(userLocation.userId, userLocation.pinDrawable) + val symbolOptions = buildSymbolOptions(userLocation) + it.create(symbolOptions) + + if (isMapFirstUpdate) { + latLngBoundsBuilder.include(LatLng(userLocation.locationData.latitude, userLocation.locationData.longitude)) + } + } + + if (isMapFirstUpdate) { + isMapFirstUpdate = false + zoomToViewAllUsers(latLngBoundsBuilder.build()) + } + } ?: run { + pendingLiveLocations.clear() + pendingLiveLocations.addAll(userLiveLocations) + } + } + + private fun addUserPinToMapStyle(userId: String, userPinDrawable: Drawable) { + mapStyle?.let { style -> + if (style.getImage(userId) == null) { + style.addImage(userId, userPinDrawable) + } + } + } + + private fun buildSymbolOptions(userLiveLocation: UserLiveLocationViewState) = + SymbolOptions() + .withLatLng(LatLng(userLiveLocation.locationData.latitude, userLiveLocation.locationData.longitude)) + .withIconImage(userLiveLocation.userId) + .withIconAnchor(Property.ICON_ANCHOR_BOTTOM) + + private fun zoomToViewAllUsers(latLngBounds: LatLngBounds) { + mapboxMap?.get()?.let { mapboxMap -> + mapboxMap.getCameraForLatLngBounds(latLngBounds)?.let { cameraPosition -> + // update the zoom a little to avoid having pins exactly at the edges of the map + mapboxMap.cameraPosition = CameraPosition.Builder(cameraPosition) + .zoom((cameraPosition.zoom - 1).coerceAtLeast(MapboxConstants.MINIMUM_ZOOM.toDouble())) + .build() } } } diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt index c33e708d6b..bd834b4672 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt @@ -29,7 +29,7 @@ import kotlinx.coroutines.flow.onEach // TODO add unit tests class LocationLiveMapViewModel @AssistedInject constructor( @Assisted private val initialState: LocationLiveMapViewState, - getCurrentUserLiveLocationUseCase: GetCurrentUserLiveLocationUseCase + getListOfUserLiveLocationUseCase: GetListOfUserLiveLocationUseCase ) : VectorViewModel(initialState) { @AssistedFactory @@ -40,7 +40,7 @@ class LocationLiveMapViewModel @AssistedInject constructor( companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() init { - getCurrentUserLiveLocationUseCase.execute() + getListOfUserLiveLocationUseCase.execute() .onEach { setState { copy(userLocations = it) } } .launchIn(viewModelScope) } diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt index d6e58b2486..ca3be8e6ca 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt @@ -16,6 +16,7 @@ package im.vector.app.features.location.live.map +import android.graphics.drawable.Drawable import com.airbnb.mvrx.MavericksState import im.vector.app.features.location.LocationData @@ -30,5 +31,6 @@ data class LocationLiveMapViewState( data class UserLiveLocationViewState( val userId: String, + val pinDrawable: Drawable, val locationData: LocationData ) From 7a7af40d6178a8791ada152433db852ea7c66aee Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 16 May 2022 17:44:54 +0200 Subject: [PATCH 105/244] Creation of LocationSharingService to get current users sharing their live locations --- .../android/sdk/api/session/room/Room.kt | 6 +++ .../location/DefaultLocationSharingService.kt | 48 +++++++++++++++++++ .../room/location/LocationSharingService.kt | 27 +++++++++++ .../LiveLocationShareAggregatedSummary.kt | 1 + .../database/RealmSessionStoreMigration.kt | 4 +- .../mapper/EventAnnotationsSummaryMapper.kt | 2 +- ...iveLocationShareAggregatedSummaryMapper.kt | 5 +- .../database/migration/MigrateSessionTo029.kt | 38 +++++++++++++++ ...iveLocationShareAggregatedSummaryEntity.kt | 2 + ...cationShareAggregatedSummaryEntityQuery.kt | 20 +++++++- .../sdk/internal/session/room/DefaultRoom.kt | 3 ++ .../sdk/internal/session/room/RoomFactory.kt | 3 ++ 12 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/DefaultLocationSharingService.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo029.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt index 3a18cf1497..85ccdeceff 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt @@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataServic import org.matrix.android.sdk.api.session.room.alias.AliasService import org.matrix.android.sdk.api.session.room.call.RoomCallService import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService +import org.matrix.android.sdk.api.session.room.location.LocationSharingService import org.matrix.android.sdk.api.session.room.members.MembershipService import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.relation.RelationService @@ -163,4 +164,9 @@ interface Room { * Get the RoomVersionService associated to this Room. */ fun roomVersionService(): RoomVersionService + + /** + * Get the LocationSharingService associated to this Room + */ + fun locationSharingService(): LocationSharingService } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/DefaultLocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/DefaultLocationSharingService.kt new file mode 100644 index 0000000000..abd6860309 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/DefaultLocationSharingService.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.api.session.room.location + +import androidx.lifecycle.LiveData +import com.zhuinden.monarchy.Monarchy +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary +import org.matrix.android.sdk.internal.database.mapper.LiveLocationShareAggregatedSummaryMapper +import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity +import org.matrix.android.sdk.internal.database.query.findRunningLiveLocationShareInRoom +import org.matrix.android.sdk.internal.di.SessionDatabase + +// TODO add unit tests +internal class DefaultLocationSharingService @AssistedInject constructor( + @Assisted private val roomId: String, + @SessionDatabase private val monarchy: Monarchy, + private val liveLocationShareAggregatedSummaryMapper: LiveLocationShareAggregatedSummaryMapper, +) : LocationSharingService { + + @AssistedFactory + interface Factory { + fun create(roomId: String): DefaultLocationSharingService + } + + override fun getRunningLiveLocationShareSummaries(): LiveData> { + return monarchy.findAllMappedWithChanges( + { LiveLocationShareAggregatedSummaryEntity.findRunningLiveLocationShareInRoom(it, roomId = roomId) }, + { liveLocationShareAggregatedSummaryMapper.map(it) } + ) + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt new file mode 100644 index 0000000000..dd48d51f45 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.api.session.room.location + +import androidx.lifecycle.LiveData +import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary + +/** + * Manage all location sharing related features. + */ +interface LocationSharingService { + fun getRunningLiveLocationShareSummaries(): LiveData> +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationShareAggregatedSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationShareAggregatedSummary.kt index 059fe21471..5ad1a48217 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationShareAggregatedSummary.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationShareAggregatedSummary.kt @@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocati * Aggregation info concerning a live location share. */ data class LiveLocationShareAggregatedSummary( + val userId: String?, /** * Indicate whether the live is currently running. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt index 55bccfd1ec..592461f927 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt @@ -46,6 +46,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo025 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo026 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo027 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo028 +import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo029 import org.matrix.android.sdk.internal.util.Normalizer import timber.log.Timber import javax.inject.Inject @@ -60,7 +61,7 @@ internal class RealmSessionStoreMigration @Inject constructor( override fun equals(other: Any?) = other is RealmSessionStoreMigration override fun hashCode() = 1000 - val schemaVersion = 28L + val schemaVersion = 29L override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) { Timber.d("Migrating Realm Session from $oldVersion to $newVersion") @@ -93,5 +94,6 @@ internal class RealmSessionStoreMigration @Inject constructor( if (oldVersion < 26) MigrateSessionTo026(realm).perform() if (oldVersion < 27) MigrateSessionTo027(realm).perform() if (oldVersion < 28) MigrateSessionTo028(realm).perform() + if (oldVersion < 29) MigrateSessionTo029(realm).perform() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventAnnotationsSummaryMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventAnnotationsSummaryMapper.kt index c747ad334f..6bbeb17fdd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventAnnotationsSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventAnnotationsSummaryMapper.kt @@ -58,7 +58,7 @@ internal object EventAnnotationsSummaryMapper { PollResponseAggregatedSummaryEntityMapper.map(it) }, liveLocationShareAggregatedSummary = annotationsSummary.liveLocationShareAggregatedSummary?.let { - LiveLocationShareAggregatedSummaryMapper.map(it) + LiveLocationShareAggregatedSummaryMapper().map(it) } ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapper.kt index 71b36f88bd..e8abcdb205 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapper.kt @@ -20,11 +20,14 @@ import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity +import javax.inject.Inject -internal object LiveLocationShareAggregatedSummaryMapper { +// TODO add unit tests +internal class LiveLocationShareAggregatedSummaryMapper @Inject constructor() { fun map(entity: LiveLocationShareAggregatedSummaryEntity): LiveLocationShareAggregatedSummary { return LiveLocationShareAggregatedSummary( + userId = entity.userId, isActive = entity.isActive, endOfLiveTimestampMillis = entity.endOfLiveTimestampMillis, lastLocationDataContent = ContentMapper.map(entity.lastLocationContent).toModel() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo029.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo029.kt new file mode 100644 index 0000000000..fda7379726 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo029.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.database.migration + +import io.realm.DynamicRealm +import io.realm.FieldAttribute +import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields +import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntityFields +import org.matrix.android.sdk.internal.util.database.RealmMigrator + +/** + * Migrating to: + * Live location sharing aggregated summary: adding new field userId + */ +internal class MigrateSessionTo029(realm: DynamicRealm) : RealmMigrator(realm, 28) { + + override fun doMigrate(realm: DynamicRealm) { + realm.schema.get("LiveLocationShareAggregatedSummaryEntity") + ?.addField(LiveLocationShareAggregatedSummaryEntityFields.USER_ID, String::class.java, FieldAttribute.REQUIRED) + ?.transform { obj -> + obj.setString(LiveLocationShareAggregatedSummaryEntityFields.USER_ID, "") + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/livelocation/LiveLocationShareAggregatedSummaryEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/livelocation/LiveLocationShareAggregatedSummaryEntity.kt index e84337693f..c5df8e9338 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/livelocation/LiveLocationShareAggregatedSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/livelocation/LiveLocationShareAggregatedSummaryEntity.kt @@ -31,6 +31,8 @@ internal open class LiveLocationShareAggregatedSummaryEntity( var roomId: String = "", + var userId: String = "", + /** * Indicate whether the live is currently running. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt index 816b5f4392..9730a0ec16 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt @@ -20,6 +20,7 @@ import io.realm.Realm import io.realm.RealmQuery import io.realm.kotlin.where import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntity +import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntityFields @@ -28,11 +29,17 @@ internal fun LiveLocationShareAggregatedSummaryEntity.Companion.where( roomId: String, eventId: String, ): RealmQuery { - return realm.where() - .equalTo(LiveLocationShareAggregatedSummaryEntityFields.ROOM_ID, roomId) + return LiveLocationShareAggregatedSummaryEntity + .whereRoomId(realm, roomId = roomId) .equalTo(LiveLocationShareAggregatedSummaryEntityFields.EVENT_ID, eventId) } +internal fun LiveLocationShareAggregatedSummaryEntity.Companion.whereRoomId(realm: Realm, + roomId: String): RealmQuery { + return realm.where() + .equalTo(TimelineEventEntityFields.ROOM_ID, roomId) +} + internal fun LiveLocationShareAggregatedSummaryEntity.Companion.create( realm: Realm, roomId: String, @@ -63,3 +70,12 @@ internal fun LiveLocationShareAggregatedSummaryEntity.Companion.get( ): LiveLocationShareAggregatedSummaryEntity? { return LiveLocationShareAggregatedSummaryEntity.where(realm, roomId, eventId).findFirst() } + +internal fun LiveLocationShareAggregatedSummaryEntity.Companion.findRunningLiveLocationShareInRoom( + realm: Realm, + roomId: String, +): RealmQuery { + return LiveLocationShareAggregatedSummaryEntity + .whereRoomId(realm, roomId = roomId) + .equalTo(LiveLocationShareAggregatedSummaryEntityFields.IS_ACTIVE, true) +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt index 7326adee4c..abea2d34cd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt @@ -23,6 +23,7 @@ import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataServic import org.matrix.android.sdk.api.session.room.alias.AliasService import org.matrix.android.sdk.api.session.room.call.RoomCallService import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService +import org.matrix.android.sdk.api.session.room.location.LocationSharingService import org.matrix.android.sdk.api.session.room.members.MembershipService import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomType @@ -69,6 +70,7 @@ internal class DefaultRoom( private val roomAccountDataService: RoomAccountDataService, private val roomVersionService: RoomVersionService, private val viaParameterFinder: ViaParameterFinder, + private val locationSharingService: LocationSharingService, override val coroutineDispatchers: MatrixCoroutineDispatchers ) : Room { @@ -104,4 +106,5 @@ internal class DefaultRoom( override fun roomPushRuleService() = roomPushRuleService override fun roomAccountDataService() = roomAccountDataService override fun roomVersionService() = roomVersionService + override fun locationSharingService() = locationSharingService } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt index 01c4fd1501..adfd55ca49 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.room import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.session.room.Room +import org.matrix.android.sdk.api.session.room.location.DefaultLocationSharingService import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder import org.matrix.android.sdk.internal.session.room.accountdata.DefaultRoomAccountDataService @@ -69,6 +70,7 @@ internal class DefaultRoomFactory @Inject constructor( private val roomVersionServiceFactory: DefaultRoomVersionService.Factory, private val roomAccountDataServiceFactory: DefaultRoomAccountDataService.Factory, private val viaParameterFinder: ViaParameterFinder, + private val locationSharingServiceFactory: DefaultLocationSharingService.Factory, private val coroutineDispatchers: MatrixCoroutineDispatchers ) : RoomFactory { @@ -96,6 +98,7 @@ internal class DefaultRoomFactory @Inject constructor( roomAccountDataService = roomAccountDataServiceFactory.create(roomId), roomVersionService = roomVersionServiceFactory.create(roomId), viaParameterFinder = viaParameterFinder, + locationSharingService = locationSharingServiceFactory.create(roomId), coroutineDispatchers = coroutineDispatchers ) } From 81b90df90983da0f8e71ed328f6b9fd5d98c64e6 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 16 May 2022 18:01:54 +0200 Subject: [PATCH 106/244] Observe the current live location shares in a room --- .../map/GetListOfUserLiveLocationUseCase.kt | 49 ++++------------ .../live/map/LocationLiveMapViewModel.kt | 2 +- .../map/UserLiveLocationViewStateMapper.kt | 56 +++++++++++++++++++ 3 files changed, 69 insertions(+), 38 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/location/live/map/UserLiveLocationViewStateMapper.kt diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCase.kt b/vector/src/main/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCase.kt index 2505ba11a4..ca4f6859ee 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCase.kt @@ -16,51 +16,26 @@ package im.vector.app.features.location.live.map -import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider -import im.vector.app.features.location.LocationData -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.channels.trySendBlocking +import androidx.lifecycle.asFlow import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.mapLatest import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.getRoom import javax.inject.Inject class GetListOfUserLiveLocationUseCase @Inject constructor( private val session: Session, - private val locationPinProvider: LocationPinProvider + private val userLiveLocationViewStateMapper: UserLiveLocationViewStateMapper, ) { // TODO add unit tests - fun execute(): Flow> { - // TODO get room and call SDK to get the correct flow of locations - - return callbackFlow { - val myUserId = session.myUserId - - locationPinProvider.create(myUserId) { pinDrawable -> - val user1 = UserLiveLocationViewState( - userId = session.myUserId, - pinDrawable = pinDrawable, - locationData = LocationData( - latitude = 48.863447, - longitude = 2.328608, - uncertainty = null - ) - ) - val user2 = UserLiveLocationViewState( - userId = session.myUserId, - pinDrawable = pinDrawable, - locationData = LocationData( - latitude = 48.843816, - longitude = 2.359235, - uncertainty = null - ) - ) - val userLocations = listOf(user1, user2) - trySendBlocking(userLocations) - channel.close() - } - awaitClose() - } + fun execute(roomId: String): Flow> { + return session.getRoom(roomId) + ?.locationSharingService() + ?.getRunningLiveLocationShareSummaries() + ?.asFlow() + ?.mapLatest { it.mapNotNull { summary -> userLiveLocationViewStateMapper.map(summary) } } + ?: emptyFlow() } } diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt index bd834b4672..73608d35bc 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt @@ -40,7 +40,7 @@ class LocationLiveMapViewModel @AssistedInject constructor( companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() init { - getListOfUserLiveLocationUseCase.execute() + getListOfUserLiveLocationUseCase.execute(initialState.roomId) .onEach { setState { copy(userLocations = it) } } .launchIn(viewModelScope) } diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/UserLiveLocationViewStateMapper.kt b/vector/src/main/java/im/vector/app/features/location/live/map/UserLiveLocationViewStateMapper.kt new file mode 100644 index 0000000000..fb5eb24769 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/live/map/UserLiveLocationViewStateMapper.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.location.live.map + +import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider +import im.vector.app.features.location.toLocationData +import kotlinx.coroutines.suspendCancellableCoroutine +import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary +import javax.inject.Inject + +// TODO add unit tests +class UserLiveLocationViewStateMapper @Inject constructor( + private val locationPinProvider: LocationPinProvider, +) { + + suspend fun map(liveLocationShareAggregatedSummary: LiveLocationShareAggregatedSummary) = + suspendCancellableCoroutine { continuation -> + val userId = liveLocationShareAggregatedSummary.userId + val locationData = liveLocationShareAggregatedSummary.lastLocationDataContent + ?.getBestLocationInfo() + ?.geoUri + .toLocationData() + + when { + userId.isNullOrEmpty() || locationData == null -> continuation.resume(null) { + // do nothing on cancellation + } + else -> { + locationPinProvider.create(userId) { pinDrawable -> + val viewState = UserLiveLocationViewState( + userId = userId, + pinDrawable = pinDrawable, + locationData = locationData + ) + continuation.resume(viewState) { + // do nothing on cancellation + } + } + } + } + } +} From 3b06f18ccb70eee30d8159d9bbddfbc15ee3fca3 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 17 May 2022 11:16:47 +0200 Subject: [PATCH 107/244] Remove unused imports --- .../sdk/internal/database/migration/MigrateSessionTo029.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo029.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo029.kt index fda7379726..44f4073144 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo029.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo029.kt @@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.database.migration import io.realm.DynamicRealm import io.realm.FieldAttribute -import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator From ca9591e4237d025fd3f5f0057f26e5f098b4d598 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 17 May 2022 14:23:49 +0200 Subject: [PATCH 108/244] Fix set of userId in aggregation process --- .../aggregation/livelocation/LiveLocationAggregationProcessor.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt index 42dfc7ba9f..cbe41bccdb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt @@ -70,6 +70,7 @@ internal class LiveLocationAggregationProcessor @Inject constructor( val endOfLiveTimestampMillis = content.getBestTimestampMillis()?.let { it + (content.timeout ?: 0) } aggregatedSummary.endOfLiveTimestampMillis = endOfLiveTimestampMillis aggregatedSummary.isActive = isLive + aggregatedSummary.userId = event.senderId if (isLive) { scheduleDeactivationAfterTimeout(targetEventId, roomId, endOfLiveTimestampMillis) From bec3f793f33cc60a598528e77946ee6b6eb05466 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 17 May 2022 14:24:31 +0200 Subject: [PATCH 109/244] Improve query of current running live location shares --- .../query/LiveLocationShareAggregatedSummaryEntityQuery.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt index 9730a0ec16..73da921d74 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt @@ -35,7 +35,7 @@ internal fun LiveLocationShareAggregatedSummaryEntity.Companion.where( } internal fun LiveLocationShareAggregatedSummaryEntity.Companion.whereRoomId(realm: Realm, - roomId: String): RealmQuery { + roomId: String): RealmQuery { return realm.where() .equalTo(TimelineEventEntityFields.ROOM_ID, roomId) } @@ -78,4 +78,6 @@ internal fun LiveLocationShareAggregatedSummaryEntity.Companion.findRunningLiveL return LiveLocationShareAggregatedSummaryEntity .whereRoomId(realm, roomId = roomId) .equalTo(LiveLocationShareAggregatedSummaryEntityFields.IS_ACTIVE, true) + .isNotEmpty(LiveLocationShareAggregatedSummaryEntityFields.USER_ID) + .isNotNull(LiveLocationShareAggregatedSummaryEntityFields.LAST_LOCATION_CONTENT) } From 40d8d5c6054b0fcc2f9522e689608ea128cd3a7f Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 17 May 2022 14:33:52 +0200 Subject: [PATCH 110/244] Updating user pins on location update --- .../location/LocationSharingFragment.kt | 2 +- .../app/features/location/MapBoxMapExt.kt | 39 ++++++ .../app/features/location/MapTilerMapView.kt | 10 +- .../live/map/LocationLiveMapViewFragment.kt | 114 ++++++++++++------ .../live/map/LocationLiveMapViewModel.kt | 5 + 5 files changed, 126 insertions(+), 44 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/location/MapBoxMapExt.kt diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt index cc5586e7f5..6de853519b 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt @@ -181,7 +181,7 @@ class LocationSharingFragment @Inject constructor( } private fun handleZoomToUserLocationEvent(event: LocationSharingViewEvents.ZoomToUserLocation) { - views.mapView.zoomToLocation(event.userLocation.latitude, event.userLocation.longitude) + views.mapView.zoomToLocation(event.userLocation) } private fun handleStartLiveLocationService(event: LocationSharingViewEvents.StartLiveLocationService) { diff --git a/vector/src/main/java/im/vector/app/features/location/MapBoxMapExt.kt b/vector/src/main/java/im/vector/app/features/location/MapBoxMapExt.kt new file mode 100644 index 0000000000..dbd2225909 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/MapBoxMapExt.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.location + +import com.mapbox.mapboxsdk.camera.CameraPosition +import com.mapbox.mapboxsdk.constants.MapboxConstants +import com.mapbox.mapboxsdk.geometry.LatLng +import com.mapbox.mapboxsdk.geometry.LatLngBounds +import com.mapbox.mapboxsdk.maps.MapboxMap + +fun MapboxMap?.zoomToLocation(locationData: LocationData) { + this?.cameraPosition = CameraPosition.Builder() + .target(LatLng(locationData.latitude, locationData.longitude)) + .zoom(INITIAL_MAP_ZOOM_IN_PREVIEW) + .build() +} + +fun MapboxMap?.zoomToBounds(latLngBounds: LatLngBounds) { + this?.getCameraForLatLngBounds(latLngBounds)?.let { camPosition -> + // unZoom a little to avoid having pins exactly at the edges of the map + cameraPosition = CameraPosition.Builder(camPosition) + .zoom((camPosition.zoom - 1).coerceAtLeast(MapboxConstants.MINIMUM_ZOOM.toDouble())) + .build() + } +} diff --git a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt index 69e4e9fc20..dd2a56fb3a 100644 --- a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt +++ b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt @@ -25,7 +25,6 @@ import androidx.core.content.ContextCompat import androidx.core.view.marginBottom import androidx.core.view.marginTop import androidx.core.view.updateLayoutParams -import com.mapbox.mapboxsdk.camera.CameraPosition import com.mapbox.mapboxsdk.geometry.LatLng import com.mapbox.mapboxsdk.maps.MapView import com.mapbox.mapboxsdk.maps.MapboxMap @@ -164,7 +163,7 @@ class MapTilerMapView @JvmOverloads constructor( state.userLocationData?.let { locationData -> if (!initZoomDone || !state.zoomOnlyOnce) { - zoomToLocation(locationData.latitude, locationData.longitude) + zoomToLocation(locationData) initZoomDone = true } @@ -180,12 +179,9 @@ class MapTilerMapView @JvmOverloads constructor( } } - fun zoomToLocation(latitude: Double, longitude: Double) { + fun zoomToLocation(locationData: LocationData) { Timber.d("## Location: zoomToLocation") - mapRefs?.map?.cameraPosition = CameraPosition.Builder() - .target(LatLng(latitude, longitude)) - .zoom(INITIAL_MAP_ZOOM_IN_PREVIEW) - .build() + mapRefs?.map?.zoomToLocation(locationData) } fun getLocationOfMapCenter(): LocationData? = diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt index 8ba4cdb5d2..5e81ae7393 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt @@ -25,8 +25,6 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState -import com.mapbox.mapboxsdk.camera.CameraPosition -import com.mapbox.mapboxsdk.constants.MapboxConstants import com.mapbox.mapboxsdk.geometry.LatLng import com.mapbox.mapboxsdk.geometry.LatLngBounds import com.mapbox.mapboxsdk.maps.MapView @@ -43,11 +41,13 @@ import im.vector.app.core.extensions.addChildFragment import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSimpleContainerBinding import im.vector.app.features.location.UrlMapProvider +import im.vector.app.features.location.zoomToBounds +import im.vector.app.features.location.zoomToLocation import java.lang.ref.WeakReference import javax.inject.Inject /** - * Screen showing a map with all the current users sharing their live location in room. + * Screen showing a map with all the current users sharing their live location in a room. */ @AndroidEntryPoint class LocationLiveMapViewFragment : VectorBaseFragment() { @@ -91,35 +91,92 @@ class LocationLiveMapViewFragment : VectorBaseFragment updateMap(viewState.userLocations) } private fun updateMap(userLiveLocations: List) { - symbolManager?.let { - it.deleteAll() - + symbolManager?.let { sManager -> val latLngBoundsBuilder = LatLngBounds.Builder() + userLiveLocations.forEach { userLocation -> - addUserPinToMapStyle(userLocation.userId, userLocation.pinDrawable) - val symbolOptions = buildSymbolOptions(userLocation) - it.create(symbolOptions) + createOrUpdateSymbol(userLocation, sManager) if (isMapFirstUpdate) { - latLngBoundsBuilder.include(LatLng(userLocation.locationData.latitude, userLocation.locationData.longitude)) + val latLng = LatLng(userLocation.locationData.latitude, userLocation.locationData.longitude) + latLngBoundsBuilder.include(latLng) } } - if (isMapFirstUpdate) { - isMapFirstUpdate = false - zoomToViewAllUsers(latLngBoundsBuilder.build()) - } - } ?: run { - pendingLiveLocations.clear() - pendingLiveLocations.addAll(userLiveLocations) + removeOutdatedSymbols(userLiveLocations, sManager) + updateMapZoomWhenNeeded(userLiveLocations, latLngBoundsBuilder) + + } ?: postponeUpdateOfMap(userLiveLocations) + } + + private fun createOrUpdateSymbol(userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) { + val symbolId = viewModel.mapSymbolIds[userLocation.userId] + + if (symbolId == null) { + createSymbol(userLocation, symbolManager) + } else { + updateSymbol(symbolId, userLocation, symbolManager) } } + private fun createSymbol(userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) { + addUserPinToMapStyle(userLocation.userId, userLocation.pinDrawable) + val symbolOptions = buildSymbolOptions(userLocation) + val symbol = symbolManager.create(symbolOptions) + viewModel.mapSymbolIds[userLocation.userId] = symbol.id + } + + private fun updateSymbol(symbolId: Long, userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) { + val newLocation = LatLng(userLocation.locationData.latitude, userLocation.locationData.longitude) + val symbol = symbolManager.annotations.get(symbolId) + symbol?.let { + it.latLng = newLocation + symbolManager.update(it) + } + } + + private fun removeOutdatedSymbols(userLiveLocations: List, symbolManager: SymbolManager) { + val userIdsToRemove = viewModel.mapSymbolIds.keys.subtract(userLiveLocations.map { it.userId }.toSet()) + userIdsToRemove + .mapNotNull { userId -> + removeUserPinFromMapStyle(userId) + viewModel.mapSymbolIds[userId] + } + .forEach { symbolId -> + val symbol = symbolManager.annotations.get(symbolId) + symbolManager.delete(symbol) + } + } + + private fun updateMapZoomWhenNeeded(userLiveLocations: List, latLngBoundsBuilder: LatLngBounds.Builder) { + if (userLiveLocations.isNotEmpty() && isMapFirstUpdate) { + isMapFirstUpdate = false + if (userLiveLocations.size > 1) { + mapboxMap?.get()?.zoomToBounds(latLngBoundsBuilder.build()) + } else { + mapboxMap?.get()?.zoomToLocation(userLiveLocations.first().locationData) + } + } + } + + private fun postponeUpdateOfMap(userLiveLocations: List) { + pendingLiveLocations.clear() + pendingLiveLocations.addAll(userLiveLocations) + } + private fun addUserPinToMapStyle(userId: String, userPinDrawable: Drawable) { mapStyle?.let { style -> if (style.getImage(userId) == null) { @@ -128,31 +185,16 @@ class LocationLiveMapViewFragment : VectorBaseFragment - mapboxMap.getCameraForLatLngBounds(latLngBounds)?.let { cameraPosition -> - // update the zoom a little to avoid having pins exactly at the edges of the map - mapboxMap.cameraPosition = CameraPosition.Builder(cameraPosition) - .zoom((cameraPosition.zoom - 1).coerceAtLeast(MapboxConstants.MINIMUM_ZOOM.toDouble())) - .build() - } - } - } - - private fun getOrCreateSupportMapFragment() = - childFragmentManager.findFragmentByTag(MAP_FRAGMENT_TAG) as? SupportMapFragment - ?: run { - val options = MapboxMapOptions.createFromAttributes(requireContext(), null) - SupportMapFragment.newInstance(options) - .also { addChildFragment(R.id.fragmentContainer, it, tag = MAP_FRAGMENT_TAG) } - } - companion object { private const val MAP_FRAGMENT_TAG = "im.vector.app.features.location.live.map" } diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt index 73608d35bc..1695055d72 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt @@ -39,6 +39,11 @@ class LocationLiveMapViewModel @AssistedInject constructor( companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() + /** + * Map to keep track of symbol ids associated to each user Id. + */ + val mapSymbolIds = mutableMapOf() + init { getListOfUserLiveLocationUseCase.execute(initialState.roomId) .onEach { setState { copy(userLocations = it) } } From 79212321a2d04141d7879188c0338c1df70fbd09 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 18 May 2022 09:22:19 +0200 Subject: [PATCH 111/244] Deactivate all previous active beacons when receiving one from user --- .../location/DefaultLocationSharingService.kt | 4 ++-- ...cationShareAggregatedSummaryEntityQuery.kt | 20 ++++++++++++++++--- .../LiveLocationAggregationProcessor.kt | 14 +++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/DefaultLocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/DefaultLocationSharingService.kt index abd6860309..196fec1100 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/DefaultLocationSharingService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/DefaultLocationSharingService.kt @@ -24,7 +24,7 @@ import dagger.assisted.AssistedInject import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary import org.matrix.android.sdk.internal.database.mapper.LiveLocationShareAggregatedSummaryMapper import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity -import org.matrix.android.sdk.internal.database.query.findRunningLiveLocationShareInRoom +import org.matrix.android.sdk.internal.database.query.findRunningLiveInRoom import org.matrix.android.sdk.internal.di.SessionDatabase // TODO add unit tests @@ -41,7 +41,7 @@ internal class DefaultLocationSharingService @AssistedInject constructor( override fun getRunningLiveLocationShareSummaries(): LiveData> { return monarchy.findAllMappedWithChanges( - { LiveLocationShareAggregatedSummaryEntity.findRunningLiveLocationShareInRoom(it, roomId = roomId) }, + { LiveLocationShareAggregatedSummaryEntity.findRunningLiveInRoom(it, roomId = roomId) }, { liveLocationShareAggregatedSummaryMapper.map(it) } ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt index 73da921d74..67d481b48a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt @@ -20,7 +20,6 @@ import io.realm.Realm import io.realm.RealmQuery import io.realm.kotlin.where import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntity -import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntityFields @@ -37,7 +36,7 @@ internal fun LiveLocationShareAggregatedSummaryEntity.Companion.where( internal fun LiveLocationShareAggregatedSummaryEntity.Companion.whereRoomId(realm: Realm, roomId: String): RealmQuery { return realm.where() - .equalTo(TimelineEventEntityFields.ROOM_ID, roomId) + .equalTo(LiveLocationShareAggregatedSummaryEntityFields.ROOM_ID, roomId) } internal fun LiveLocationShareAggregatedSummaryEntity.Companion.create( @@ -71,7 +70,22 @@ internal fun LiveLocationShareAggregatedSummaryEntity.Companion.get( return LiveLocationShareAggregatedSummaryEntity.where(realm, roomId, eventId).findFirst() } -internal fun LiveLocationShareAggregatedSummaryEntity.Companion.findRunningLiveLocationShareInRoom( +internal fun LiveLocationShareAggregatedSummaryEntity.Companion.findActiveLiveInRoomForUser( + realm: Realm, + roomId: String, + userId: String, +): List { + return LiveLocationShareAggregatedSummaryEntity + .whereRoomId(realm, roomId = roomId) + .equalTo(LiveLocationShareAggregatedSummaryEntityFields.USER_ID, userId) + .equalTo(LiveLocationShareAggregatedSummaryEntityFields.IS_ACTIVE, true) + .findAll() +} + +/** + * A live is considered as running when active and with at least a last known location. + */ +internal fun LiveLocationShareAggregatedSummaryEntity.Companion.findRunningLiveInRoom( realm: Realm, roomId: String, ): RealmQuery { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt index cbe41bccdb..487786e69f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt @@ -26,6 +26,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoCo import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent import org.matrix.android.sdk.internal.database.mapper.ContentMapper import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity +import org.matrix.android.sdk.internal.database.query.findActiveLiveInRoomForUser import org.matrix.android.sdk.internal.database.query.getOrCreate import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.di.WorkManagerProvider @@ -72,6 +73,8 @@ internal class LiveLocationAggregationProcessor @Inject constructor( aggregatedSummary.isActive = isLive aggregatedSummary.userId = event.senderId + deactivateAllPreviousBeacons(realm, roomId, event.senderId, targetEventId) + if (isLive) { scheduleDeactivationAfterTimeout(targetEventId, roomId, endOfLiveTimestampMillis) } else { @@ -138,5 +141,16 @@ internal class LiveLocationAggregationProcessor @Inject constructor( } } + private fun deactivateAllPreviousBeacons(realm: Realm, roomId: String, userId: String, currentEventId: String) { + LiveLocationShareAggregatedSummaryEntity + .findActiveLiveInRoomForUser( + realm = realm, + roomId = roomId, + userId = userId + ) + .filterNot { it.eventId == currentEventId } + .forEach { it.isActive = false } + } + private fun Long.isMoreRecentThan(timestamp: Long) = this > timestamp } From bd473375a19c8022f8075a60c33559d7d665e55d Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 18 May 2022 14:43:53 +0200 Subject: [PATCH 112/244] Fix no text visible if using direct pin drawable --- .../features/location/live/map/LocationLiveMapViewFragment.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt index 5e81ae7393..953c399c7f 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt @@ -21,6 +21,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.graphics.drawable.toBitmap import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel @@ -180,7 +181,7 @@ class LocationLiveMapViewFragment : VectorBaseFragment if (style.getImage(userId) == null) { - style.addImage(userId, userPinDrawable) + style.addImage(userId, userPinDrawable.toBitmap()) } } } From 401027e91926e2204da9a83d19f908f691c0b155 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 18 May 2022 17:25:38 +0200 Subject: [PATCH 113/244] Adding end of live timestamp into view state --- .../features/location/live/map/LocationLiveMapViewState.kt | 3 ++- .../location/live/map/UserLiveLocationViewStateMapper.kt | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt index ca3be8e6ca..9fa8635d82 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt @@ -32,5 +32,6 @@ data class LocationLiveMapViewState( data class UserLiveLocationViewState( val userId: String, val pinDrawable: Drawable, - val locationData: LocationData + val locationData: LocationData, + val endOfLiveTimestampMillis: Long? ) diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/UserLiveLocationViewStateMapper.kt b/vector/src/main/java/im/vector/app/features/location/live/map/UserLiveLocationViewStateMapper.kt index fb5eb24769..8790144040 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/UserLiveLocationViewStateMapper.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/UserLiveLocationViewStateMapper.kt @@ -22,7 +22,6 @@ import kotlinx.coroutines.suspendCancellableCoroutine import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary import javax.inject.Inject -// TODO add unit tests class UserLiveLocationViewStateMapper @Inject constructor( private val locationPinProvider: LocationPinProvider, ) { @@ -44,7 +43,8 @@ class UserLiveLocationViewStateMapper @Inject constructor( val viewState = UserLiveLocationViewState( userId = userId, pinDrawable = pinDrawable, - locationData = locationData + locationData = locationData, + endOfLiveTimestampMillis = liveLocationShareAggregatedSummary.endOfLiveTimestampMillis ) continuation.resume(viewState) { // do nothing on cancellation From 7ef91ce7175fc1b4eb763b7a455cd5bdba31ea99 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 18 May 2022 17:25:52 +0200 Subject: [PATCH 114/244] Adding unit tests for view state mapper --- .../UserLiveLocationViewStateMapperTest.kt | 106 ++++++++++++++++++ .../app/test/fakes/FakeLocationPinProvider.kt | 32 ++++++ 2 files changed, 138 insertions(+) create mode 100644 vector/src/test/java/im/vector/app/features/location/live/map/UserLiveLocationViewStateMapperTest.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeLocationPinProvider.kt diff --git a/vector/src/test/java/im/vector/app/features/location/live/map/UserLiveLocationViewStateMapperTest.kt b/vector/src/test/java/im/vector/app/features/location/live/map/UserLiveLocationViewStateMapperTest.kt new file mode 100644 index 0000000000..7f83f99b98 --- /dev/null +++ b/vector/src/test/java/im/vector/app/features/location/live/map/UserLiveLocationViewStateMapperTest.kt @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.location.live.map + +import android.graphics.drawable.Drawable +import im.vector.app.features.location.LocationData +import im.vector.app.features.location.toLocationData +import im.vector.app.test.fakes.FakeLocationPinProvider +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.unmockkStatic +import kotlinx.coroutines.test.runTest +import org.amshove.kluent.internal.assertEquals +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary +import org.matrix.android.sdk.api.session.room.model.message.LocationInfo +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent + +class UserLiveLocationViewStateMapperTest { + + private val locationPinProvider = FakeLocationPinProvider() + + private val userLiveLocationViewStateMapper = UserLiveLocationViewStateMapper(locationPinProvider.instance) + + @Before + fun setUp() { + mockkStatic("im.vector.app.features.location.LocationDataKt") + } + + @After + fun tearDown() { + unmockkStatic("im.vector.app.features.location.LocationDataKt") + } + + @Test + fun `given a summary with invalid data then result is null`() = runTest { + val summary1 = LiveLocationShareAggregatedSummary( + userId = null, + isActive = true, + endOfLiveTimestampMillis = null, + lastLocationDataContent = null, + ) + val summary2 = summary1.copy(userId = "") + val summaryWithoutLocation = summary1.copy(userId = "userId") + + val viewState1 = userLiveLocationViewStateMapper.map(summary1) + val viewState2 = userLiveLocationViewStateMapper.map(summary2) + val viewState3 = userLiveLocationViewStateMapper.map(summaryWithoutLocation) + + assertEquals(null, viewState1) + assertEquals(null, viewState2) + assertEquals(null, viewState3) + } + + @Test + fun `given a summary with valid data then result is correctly mapped`() = runTest { + val geoUri = "geoUri" + val userId = "userId" + val pinDrawable = mockk() + val endOfLiveTimestampMillis = 123L + + val locationDataContent = MessageBeaconLocationDataContent( + locationInfo = LocationInfo(geoUri = geoUri) + ) + val summary = LiveLocationShareAggregatedSummary( + userId = userId, + isActive = true, + endOfLiveTimestampMillis = endOfLiveTimestampMillis, + lastLocationDataContent = locationDataContent, + ) + val locationData = LocationData( + latitude = 1.0, + longitude = 2.0, + uncertainty = null + ) + every { geoUri.toLocationData() } returns locationData + locationPinProvider.givenCreateForUserId(userId, pinDrawable) + + val viewState = userLiveLocationViewStateMapper.map(summary) + + val expectedViewState = UserLiveLocationViewState( + userId = userId, + pinDrawable = pinDrawable, + locationData = locationData, + endOfLiveTimestampMillis = endOfLiveTimestampMillis + ) + assertEquals(expectedViewState, viewState) + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeLocationPinProvider.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeLocationPinProvider.kt new file mode 100644 index 0000000000..9688f30927 --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeLocationPinProvider.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.test.fakes + +import android.graphics.drawable.Drawable +import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider +import io.mockk.every +import io.mockk.invoke +import io.mockk.mockk + +class FakeLocationPinProvider { + + val instance = mockk(relaxed = true) + + fun givenCreateForUserId(userId: String, expectedDrawable: Drawable) { + every { instance.create(userId, captureLambda()) } answers { lambda<(Drawable) -> Unit>().invoke(expectedDrawable)} + } +} From c07bc0890f33773283b70fa3d321b2da426993e7 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 23 May 2022 10:04:41 +0200 Subject: [PATCH 115/244] WIP - unit tests --- ...iveLocationShareAggregatedSummaryMapper.kt | 1 - ...ocationShareAggregatedSummaryMapperTest.kt | 76 +++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapper.kt index e8abcdb205..9460e4c6ba 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapper.kt @@ -22,7 +22,6 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocati import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity import javax.inject.Inject -// TODO add unit tests internal class LiveLocationShareAggregatedSummaryMapper @Inject constructor() { fun map(entity: LiveLocationShareAggregatedSummaryEntity): LiveLocationShareAggregatedSummary { diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt new file mode 100644 index 0000000000..6209a9d65f --- /dev/null +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.database.mapper + +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.unmockkStatic +import org.amshove.kluent.internal.assertEquals +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.matrix.android.sdk.api.session.events.model.Content +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent +import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity + +class LiveLocationShareAggregatedSummaryMapperTest { + + private val mapper = LiveLocationShareAggregatedSummaryMapper() + + @Before + fun setUp() { + mockkStatic("org.matrix.android.sdk.internal.database.mapper.ContentMapperKt") + mockkStatic("org.matrix.android.sdk.api.session.events.model.EventKt") + } + + @After + fun tearDown() { + unmockkStatic("org.matrix.android.sdk.internal.database.mapper.ContentMapperKt") + unmockkStatic("org.matrix.android.sdk.api.session.events.model.EventKt") + } + + @Test + fun `given an entity then result should be mapped correctly`() { + val userId = "userId" + val timeout = 123L + val isActive = true + val lastKnownLocationContent = "lastKnownLocationContent" + val messageBeaconLocationDataContent = MessageBeaconLocationDataContent() + val entity = LiveLocationShareAggregatedSummaryEntity( + userId = userId, + isActive = isActive, + endOfLiveTimestampMillis = timeout, + lastLocationContent = lastKnownLocationContent + ) + val content = mockk() + every { ContentMapper.map(lastKnownLocationContent) } returns content + every { content.toModel() } returns messageBeaconLocationDataContent + + val summary = mapper.map(entity) + + val expectedSummary = LiveLocationShareAggregatedSummary( + userId = userId, + isActive = isActive, + endOfLiveTimestampMillis = timeout, + lastLocationDataContent = messageBeaconLocationDataContent + ) + assertEquals(expectedSummary, summary) + } +} From 8145049315c644d3acb041141856f19696783ad1 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 23 May 2022 17:19:29 +0200 Subject: [PATCH 116/244] Fix potential access to null value --- .../location/live/map/LocationLiveMapViewFragment.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt index 953c399c7f..ecbdf7e39c 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt @@ -33,10 +33,10 @@ import com.mapbox.mapboxsdk.maps.MapboxMap import com.mapbox.mapboxsdk.maps.MapboxMapOptions import com.mapbox.mapboxsdk.maps.Style import com.mapbox.mapboxsdk.maps.SupportMapFragment -import dagger.hilt.android.AndroidEntryPoint import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions import com.mapbox.mapboxsdk.style.layers.Property +import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.core.extensions.addChildFragment import im.vector.app.core.platform.VectorBaseFragment @@ -44,6 +44,7 @@ import im.vector.app.databinding.FragmentSimpleContainerBinding import im.vector.app.features.location.UrlMapProvider import im.vector.app.features.location.zoomToBounds import im.vector.app.features.location.zoomToLocation +import timber.log.Timber import java.lang.ref.WeakReference import javax.inject.Inject @@ -155,10 +156,13 @@ class LocationLiveMapViewFragment : VectorBaseFragment removeUserPinFromMapStyle(userId) viewModel.mapSymbolIds[userId] + viewModel.mapSymbolIds.remove(userId) } .forEach { symbolId -> - val symbol = symbolManager.annotations.get(symbolId) - symbolManager.delete(symbol) + Timber.d("trying to delete symbol with id: $symbolId") + symbolManager.annotations.get(symbolId)?.let { + symbolManager.delete(it) + } } } From 5efe26c7ddfcd2d7e9ac88466e99f89341bacd21 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 24 May 2022 09:24:10 +0200 Subject: [PATCH 117/244] Fix code quality issues --- .../mapper/LiveLocationShareAggregatedSummaryMapperTest.kt | 2 +- .../features/location/live/map/LocationLiveMapViewFragment.kt | 1 - .../java/im/vector/app/test/fakes/FakeLocationPinProvider.kt | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt index 6209a9d65f..85b80f0a6e 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt index ecbdf7e39c..46c238ad12 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt @@ -120,7 +120,6 @@ class LocationLiveMapViewFragment : VectorBaseFragment(relaxed = true) fun givenCreateForUserId(userId: String, expectedDrawable: Drawable) { - every { instance.create(userId, captureLambda()) } answers { lambda<(Drawable) -> Unit>().invoke(expectedDrawable)} + every { instance.create(userId, captureLambda()) } answers { lambda<(Drawable) -> Unit>().invoke(expectedDrawable) } } } From d9480bb1360a0bf72527a0deb3b5377143220518 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 24 May 2022 16:40:38 +0200 Subject: [PATCH 118/244] Adding todo to add unit tests on aggregation process --- .../aggregation/livelocation/LiveLocationAggregationProcessor.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt index 487786e69f..0317de682a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt @@ -36,6 +36,7 @@ import timber.log.Timber import java.util.concurrent.TimeUnit import javax.inject.Inject +// TODO add unit tests internal class LiveLocationAggregationProcessor @Inject constructor( @SessionId private val sessionId: String, private val workManagerProvider: WorkManagerProvider, From 095cc12e10e0a40d77f1276f26c288d5920a0b35 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 24 May 2022 16:40:52 +0200 Subject: [PATCH 119/244] Fixing unit tests of the mapper --- ...LiveLocationShareAggregatedSummaryMapperTest.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt index 85b80f0a6e..1d070863b8 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt @@ -18,7 +18,9 @@ package org.matrix.android.sdk.internal.database.mapper import io.mockk.every import io.mockk.mockk +import io.mockk.mockkObject import io.mockk.mockkStatic +import io.mockk.unmockkObject import io.mockk.unmockkStatic import org.amshove.kluent.internal.assertEquals import org.junit.After @@ -36,14 +38,12 @@ class LiveLocationShareAggregatedSummaryMapperTest { @Before fun setUp() { - mockkStatic("org.matrix.android.sdk.internal.database.mapper.ContentMapperKt") - mockkStatic("org.matrix.android.sdk.api.session.events.model.EventKt") + mockkObject(ContentMapper) } @After fun tearDown() { - unmockkStatic("org.matrix.android.sdk.internal.database.mapper.ContentMapperKt") - unmockkStatic("org.matrix.android.sdk.api.session.events.model.EventKt") + unmockkObject(ContentMapper) } @Test @@ -52,7 +52,6 @@ class LiveLocationShareAggregatedSummaryMapperTest { val timeout = 123L val isActive = true val lastKnownLocationContent = "lastKnownLocationContent" - val messageBeaconLocationDataContent = MessageBeaconLocationDataContent() val entity = LiveLocationShareAggregatedSummaryEntity( userId = userId, isActive = isActive, @@ -61,15 +60,16 @@ class LiveLocationShareAggregatedSummaryMapperTest { ) val content = mockk() every { ContentMapper.map(lastKnownLocationContent) } returns content - every { content.toModel() } returns messageBeaconLocationDataContent val summary = mapper.map(entity) + // note: unfortunately the implementation relies on an inline method to map the lastLocationDataContent + // since inline methods do not produce bytecode, it is not mockable and the verification on this field cannot be done val expectedSummary = LiveLocationShareAggregatedSummary( userId = userId, isActive = isActive, endOfLiveTimestampMillis = timeout, - lastLocationDataContent = messageBeaconLocationDataContent + lastLocationDataContent = null ) assertEquals(expectedSummary, summary) } From 65d7ec86964071b7027c333122dbfbbb8dd6d87d Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 24 May 2022 17:45:22 +0200 Subject: [PATCH 120/244] Adding unit tests for use case to get the list of current running lives --- .../map/GetListOfUserLiveLocationUseCase.kt | 1 - .../GetListOfUserLiveLocationUseCaseTest.kt | 110 ++++++++++++++++++ .../test/fakes/FakeLocationSharingService.kt | 34 ++++++ .../java/im/vector/app/test/fakes/FakeRoom.kt | 27 +++++ .../vector/app/test/fakes/FakeRoomService.kt | 27 +++++ .../im/vector/app/test/fakes/FakeSession.kt | 4 +- 6 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 vector/src/test/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCaseTest.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeLocationSharingService.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeRoom.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeRoomService.kt diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCase.kt b/vector/src/main/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCase.kt index ca4f6859ee..91f6999e2c 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCase.kt @@ -29,7 +29,6 @@ class GetListOfUserLiveLocationUseCase @Inject constructor( private val userLiveLocationViewStateMapper: UserLiveLocationViewStateMapper, ) { - // TODO add unit tests fun execute(roomId: String): Flow> { return session.getRoom(roomId) ?.locationSharingService() diff --git a/vector/src/test/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCaseTest.kt new file mode 100644 index 0000000000..765eee4937 --- /dev/null +++ b/vector/src/test/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCaseTest.kt @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.location.live.map + +import androidx.lifecycle.asFlow +import com.airbnb.mvrx.test.MvRxTestRule +import im.vector.app.features.location.LocationData +import im.vector.app.test.fakes.FakeSession +import io.mockk.coEvery +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.unmockkStatic +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.runTest +import org.amshove.kluent.internal.assertEquals +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent + +class GetListOfUserLiveLocationUseCaseTest { + + @get:Rule + val mvRxTestRule = MvRxTestRule() + + private val fakeSession = FakeSession() + + private val viewStateMapper = mockk() + + private val getListOfUserLiveLocationUseCase = GetListOfUserLiveLocationUseCase(fakeSession, viewStateMapper) + + @Before + fun setUp() { + mockkStatic("androidx.lifecycle.FlowLiveDataConversions") + } + + @After + fun tearDown() { + unmockkStatic("androidx.lifecycle.FlowLiveDataConversions") + } + + @Test + fun `given a room id then the correct flow of view states list is collected`() = runTest { + val roomId = "roomId" + + val summary1 = LiveLocationShareAggregatedSummary( + userId = "userId1", + isActive = true, + endOfLiveTimestampMillis = 123, + lastLocationDataContent = MessageBeaconLocationDataContent() + ) + val summary2 = LiveLocationShareAggregatedSummary( + userId = "userId2", + isActive = true, + endOfLiveTimestampMillis = 1234, + lastLocationDataContent = MessageBeaconLocationDataContent() + ) + val summary3 = LiveLocationShareAggregatedSummary( + userId = "userId3", + isActive = true, + endOfLiveTimestampMillis = 1234, + lastLocationDataContent = MessageBeaconLocationDataContent() + ) + val summaries = listOf(summary1, summary2, summary3) + val liveData = fakeSession.roomService() + .getRoom(roomId) + .locationSharingService() + .givenRunningLiveLocationShareSummaries(summaries) + + every { liveData.asFlow() } returns flowOf(summaries) + + val viewState1 = UserLiveLocationViewState( + userId = "userId1", + pinDrawable = mockk(), + locationData = LocationData(latitude = 1.0, longitude = 2.0, uncertainty = null), + endOfLiveTimestampMillis = 123 + ) + val viewState2 = UserLiveLocationViewState( + userId = "userId2", + pinDrawable = mockk(), + locationData = LocationData(latitude = 1.0, longitude = 2.0, uncertainty = null), + endOfLiveTimestampMillis = 1234 + ) + coEvery { viewStateMapper.map(summary1) } returns viewState1 + coEvery { viewStateMapper.map(summary2) } returns viewState2 + coEvery { viewStateMapper.map(summary3) } returns null + + val viewStates = getListOfUserLiveLocationUseCase.execute(roomId).first() + + assertEquals(listOf(viewState1, viewState2), viewStates) + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeLocationSharingService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeLocationSharingService.kt new file mode 100644 index 0000000000..2cd98c086c --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeLocationSharingService.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.test.fakes + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import io.mockk.every +import io.mockk.mockk +import org.matrix.android.sdk.api.session.room.location.LocationSharingService +import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary + +class FakeLocationSharingService : LocationSharingService by mockk() { + + fun givenRunningLiveLocationShareSummaries(summaries: List): + LiveData> { + return MutableLiveData(summaries).also { + every { getRunningLiveLocationShareSummaries() } returns it + } + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeRoom.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeRoom.kt new file mode 100644 index 0000000000..ff87ab0fde --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeRoom.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.test.fakes + +import io.mockk.mockk +import org.matrix.android.sdk.api.session.room.Room + +class FakeRoom( + private val fakeLocationSharingService: FakeLocationSharingService = FakeLocationSharingService(), +) : Room by mockk() { + + override fun locationSharingService() = fakeLocationSharingService +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeRoomService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeRoomService.kt new file mode 100644 index 0000000000..b09256f747 --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeRoomService.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.test.fakes + +import io.mockk.mockk +import org.matrix.android.sdk.api.session.room.RoomService + +class FakeRoomService( + private val fakeRoom: FakeRoom = FakeRoom() +) : RoomService by mockk() { + + override fun getRoom(roomId: String) = fakeRoom +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt index 5f02879e65..cf94493f61 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt @@ -33,7 +33,8 @@ class FakeSession( val fakeCryptoService: FakeCryptoService = FakeCryptoService(), val fakeProfileService: FakeProfileService = FakeProfileService(), val fakeHomeServerCapabilitiesService: FakeHomeServerCapabilitiesService = FakeHomeServerCapabilitiesService(), - val fakeSharedSecretStorageService: FakeSharedSecretStorageService = FakeSharedSecretStorageService() + val fakeSharedSecretStorageService: FakeSharedSecretStorageService = FakeSharedSecretStorageService(), + private val fakeRoomService: FakeRoomService = FakeRoomService(), ) : Session by mockk(relaxed = true) { init { @@ -48,6 +49,7 @@ class FakeSession( override fun profileService(): ProfileService = fakeProfileService override fun homeServerCapabilitiesService(): HomeServerCapabilitiesService = fakeHomeServerCapabilitiesService override fun sharedSecretStorageService() = fakeSharedSecretStorageService + override fun roomService() = fakeRoomService fun givenVectorStore(vectorSessionStore: VectorSessionStore) { coEvery { From 1b8440d7c85ff1ff96031ea726d3d138e82f96bf Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 24 May 2022 17:52:48 +0200 Subject: [PATCH 121/244] Removing unused imports --- .../mapper/LiveLocationShareAggregatedSummaryMapperTest.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt index 1d070863b8..f8b3b39350 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapperTest.kt @@ -19,17 +19,13 @@ package org.matrix.android.sdk.internal.database.mapper import io.mockk.every import io.mockk.mockk import io.mockk.mockkObject -import io.mockk.mockkStatic import io.mockk.unmockkObject -import io.mockk.unmockkStatic import org.amshove.kluent.internal.assertEquals import org.junit.After import org.junit.Before import org.junit.Test import org.matrix.android.sdk.api.session.events.model.Content -import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary -import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity class LiveLocationShareAggregatedSummaryMapperTest { From 8d2debf47ea86263643043a0bbf12efe1d50b2e3 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 25 May 2022 09:44:07 +0200 Subject: [PATCH 122/244] Adding missing ending dots in comments --- .../main/java/org/matrix/android/sdk/api/session/room/Room.kt | 2 +- .../sdk/internal/database/migration/MigrateSessionTo029.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt index 85ccdeceff..5d2769ac3c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt @@ -166,7 +166,7 @@ interface Room { fun roomVersionService(): RoomVersionService /** - * Get the LocationSharingService associated to this Room + * Get the LocationSharingService associated to this Room. */ fun locationSharingService(): LocationSharingService } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo029.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo029.kt index 44f4073144..aebca11c2b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo029.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo029.kt @@ -23,7 +23,7 @@ import org.matrix.android.sdk.internal.util.database.RealmMigrator /** * Migrating to: - * Live location sharing aggregated summary: adding new field userId + * Live location sharing aggregated summary: adding new field userId. */ internal class MigrateSessionTo029(realm: DynamicRealm) : RealmMigrator(realm, 28) { From 33151eef73a90cf43ec3dfe7f654968b1b91699b Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 25 May 2022 10:54:09 +0200 Subject: [PATCH 123/244] Move the default implementation of location sharing service into internal package --- .../matrix/android/sdk/internal/session/room/RoomFactory.kt | 2 +- .../session/room/location/DefaultLocationSharingService.kt | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/{api => internal}/session/room/location/DefaultLocationSharingService.kt (91%) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt index adfd55ca49..512b88e3e0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.session.room import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.session.room.Room -import org.matrix.android.sdk.api.session.room.location.DefaultLocationSharingService +import org.matrix.android.sdk.internal.session.room.location.DefaultLocationSharingService import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder import org.matrix.android.sdk.internal.session.room.accountdata.DefaultRoomAccountDataService diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/DefaultLocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt similarity index 91% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/DefaultLocationSharingService.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt index 196fec1100..cecad77f06 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/DefaultLocationSharingService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,14 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.session.room.location +package org.matrix.android.sdk.internal.session.room.location import androidx.lifecycle.LiveData import com.zhuinden.monarchy.Monarchy import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import org.matrix.android.sdk.api.session.room.location.LocationSharingService import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary import org.matrix.android.sdk.internal.database.mapper.LiveLocationShareAggregatedSummaryMapper import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity From aa65d8234139a16baafcb76d32d492e188a2c615 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 25 May 2022 14:01:36 +0200 Subject: [PATCH 124/244] Adding unit tests for ViewModel --- .../live/map/LocationLiveMapViewModel.kt | 1 - .../live/map/LocationLiveMapViewModelTest.kt | 70 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 vector/src/test/java/im/vector/app/features/location/live/map/LocationLiveMapViewModelTest.kt diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt index 1695055d72..8c5f292f25 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt @@ -26,7 +26,6 @@ import im.vector.app.core.platform.VectorViewModel import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -// TODO add unit tests class LocationLiveMapViewModel @AssistedInject constructor( @Assisted private val initialState: LocationLiveMapViewState, getListOfUserLiveLocationUseCase: GetListOfUserLiveLocationUseCase diff --git a/vector/src/test/java/im/vector/app/features/location/live/map/LocationLiveMapViewModelTest.kt b/vector/src/test/java/im/vector/app/features/location/live/map/LocationLiveMapViewModelTest.kt new file mode 100644 index 0000000000..330cedf986 --- /dev/null +++ b/vector/src/test/java/im/vector/app/features/location/live/map/LocationLiveMapViewModelTest.kt @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.location.live.map + +import com.airbnb.mvrx.test.MvRxTestRule +import im.vector.app.features.location.LocationData +import im.vector.app.test.test +import io.mockk.every +import io.mockk.mockk +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test + +class LocationLiveMapViewModelTest { + + @get:Rule + val mvrxTestRule = MvRxTestRule() + + private val fakeRoomId = "" + + private val args = LocationLiveMapViewArgs(roomId = fakeRoomId) + + private val getListOfUserLiveLocationUseCase = mockk() + + private fun createViewModel(): LocationLiveMapViewModel { + return LocationLiveMapViewModel( + LocationLiveMapViewState(args), + getListOfUserLiveLocationUseCase + ) + } + + @Test + fun `given the viewModel has been initialized then viewState contains user locations list`() = runTest { + val userLocations = listOf( + UserLiveLocationViewState( + userId = "", + pinDrawable = mockk(), + locationData = LocationData(latitude = 1.0, longitude = 2.0, uncertainty = null), + endOfLiveTimestampMillis = 123 + ) + ) + + every { getListOfUserLiveLocationUseCase.execute(fakeRoomId) } returns flowOf(userLocations) + + val viewModel = createViewModel() + viewModel + .test() + .assertState( + LocationLiveMapViewState(args).copy( + userLocations = userLocations + ) + ) + .finish() + } +} From eda0aa97d0a5af2b3149ba991583fe3da28f9beb Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 25 May 2022 14:11:18 +0200 Subject: [PATCH 125/244] Fixing code quality issues --- .../org/matrix/android/sdk/internal/session/room/RoomFactory.kt | 2 +- .../session/room/location/DefaultLocationSharingService.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt index 512b88e3e0..ffe7679575 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt @@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.session.room import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.session.room.Room -import org.matrix.android.sdk.internal.session.room.location.DefaultLocationSharingService import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder import org.matrix.android.sdk.internal.session.room.accountdata.DefaultRoomAccountDataService @@ -26,6 +25,7 @@ import org.matrix.android.sdk.internal.session.room.alias.DefaultAliasService import org.matrix.android.sdk.internal.session.room.call.DefaultRoomCallService import org.matrix.android.sdk.internal.session.room.crypto.DefaultRoomCryptoService import org.matrix.android.sdk.internal.session.room.draft.DefaultDraftService +import org.matrix.android.sdk.internal.session.room.location.DefaultLocationSharingService import org.matrix.android.sdk.internal.session.room.membership.DefaultMembershipService import org.matrix.android.sdk.internal.session.room.notification.DefaultRoomPushRuleService import org.matrix.android.sdk.internal.session.room.read.DefaultReadService diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt index cecad77f06..8cf6fcdfbf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 690fda180c339b4710b50d800cc74c3ae441b1a6 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 11 May 2022 18:29:44 +0100 Subject: [PATCH 126/244] providing dedicated reset action for resetting invalid deeplink homeserver - also fixes the usecase screen becoming stuck with an invalid homeserver deeplink --- .../features/onboarding/OnboardingAction.kt | 5 +- .../onboarding/OnboardingViewModel.kt | 15 ++-- .../FtueAuthSplashCarouselFragment.kt | 75 ++++++++++++++----- .../ftueauth/FtueAuthSplashFragment.kt | 7 +- .../ftueauth/FtueAuthUseCaseFragment.kt | 32 +++++++- 5 files changed, 101 insertions(+), 33 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt index bef624ddc4..97a631dd1f 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt @@ -25,8 +25,9 @@ import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.network.ssl.Fingerprint sealed interface OnboardingAction : VectorViewModelAction { - data class OnGetStarted(val resetLoginConfig: Boolean, val onboardingFlow: OnboardingFlow) : OnboardingAction - data class OnIAlreadyHaveAnAccount(val resetLoginConfig: Boolean, val onboardingFlow: OnboardingFlow) : OnboardingAction + object ResetDeeplinkConfig : OnboardingAction + data class OnGetStarted(val onboardingFlow: OnboardingFlow) : OnboardingAction + data class OnIAlreadyHaveAnAccount(val onboardingFlow: OnboardingFlow) : OnboardingAction data class UpdateServerType(val serverType: ServerType) : OnboardingAction diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 0bd61758bc..a7de3c157a 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -30,6 +30,7 @@ import im.vector.app.core.extensions.configureAndStart import im.vector.app.core.extensions.vectorStore import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider +import im.vector.app.core.utils.ensureProtocol import im.vector.app.core.utils.ensureTrailingSlash import im.vector.app.features.VectorFeatures import im.vector.app.features.VectorOverrides @@ -110,7 +111,8 @@ class OnboardingViewModel @AssistedInject constructor( private var currentHomeServerConnectionConfig: HomeServerConnectionConfig? = null private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() - private val defaultHomeserverUrl = matrixOrgUrl + private val defaultHomeserverUrl: String + get() = loginConfig?.homeServerUrl?.ensureProtocol() ?: matrixOrgUrl private val registrationWizard: RegistrationWizard get() = authenticationService.getRegistrationWizard() @@ -132,8 +134,8 @@ class OnboardingViewModel @AssistedInject constructor( override fun handle(action: OnboardingAction) { when (action) { - is OnboardingAction.OnGetStarted -> handleSplashAction(action.resetLoginConfig, action.onboardingFlow) - is OnboardingAction.OnIAlreadyHaveAnAccount -> handleSplashAction(action.resetLoginConfig, action.onboardingFlow) + is OnboardingAction.OnGetStarted -> handleSplashAction(action.onboardingFlow) + is OnboardingAction.OnIAlreadyHaveAnAccount -> handleSplashAction(action.onboardingFlow) is OnboardingAction.UpdateUseCase -> handleUpdateUseCase(action) OnboardingAction.ResetUseCase -> resetUseCase() is OnboardingAction.UpdateServerType -> handleUpdateServerType(action) @@ -157,6 +159,7 @@ class OnboardingViewModel @AssistedInject constructor( OnboardingAction.SaveSelectedProfilePicture -> updateProfilePicture() is OnboardingAction.PostViewEvent -> _viewEvents.post(action.viewEvent) OnboardingAction.StopEmailValidationCheck -> cancelWaitForEmailValidation() + OnboardingAction.ResetDeeplinkConfig -> loginConfig = null } } @@ -173,10 +176,7 @@ class OnboardingViewModel @AssistedInject constructor( } } - private fun handleSplashAction(resetConfig: Boolean, onboardingFlow: OnboardingFlow) { - if (resetConfig) { - loginConfig = null - } + private fun handleSplashAction(onboardingFlow: OnboardingFlow) { setState { copy(onboardingFlow = onboardingFlow) } return when (val config = loginConfig.toHomeserverConfig()) { @@ -422,7 +422,6 @@ class OnboardingViewModel @AssistedInject constructor( private fun handleInitWith(action: OnboardingAction.InitWith) { loginConfig = action.loginConfig - // If there is a pending email validation continue on this step try { if (registrationWizard.isRegistrationStarted) { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt index 30416bde9e..8306589e89 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt @@ -17,6 +17,9 @@ package im.vector.app.features.onboarding.ftueauth import android.annotation.SuppressLint +import android.content.Context +import android.net.ConnectivityManager +import android.net.NetworkCapabilities import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -41,8 +44,7 @@ import im.vector.app.features.settings.VectorPreferences import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import org.matrix.android.sdk.api.failure.Failure -import java.net.UnknownHostException +import org.matrix.android.sdk.api.failure.isHomeserverUnavailable import javax.inject.Inject private const val CAROUSEL_ROTATION_DELAY_MS = 5000L @@ -128,11 +130,11 @@ class FtueAuthSplashCarouselFragment @Inject constructor( private fun splashSubmit(isAlreadyHaveAccountEnabled: Boolean) { val getStartedFlow = if (isAlreadyHaveAccountEnabled) OnboardingFlow.SignUp else OnboardingFlow.SignInSignUp - viewModel.handle(OnboardingAction.OnGetStarted(resetLoginConfig = false, onboardingFlow = getStartedFlow)) + viewModel.handle(OnboardingAction.OnGetStarted(onboardingFlow = getStartedFlow)) } private fun alreadyHaveAnAccount() { - viewModel.handle(OnboardingAction.OnIAlreadyHaveAnAccount(resetLoginConfig = false, onboardingFlow = OnboardingFlow.SignIn)) + viewModel.handle(OnboardingAction.OnIAlreadyHaveAnAccount(onboardingFlow = OnboardingFlow.SignIn)) } override fun resetViewModel() { @@ -140,21 +142,56 @@ class FtueAuthSplashCarouselFragment @Inject constructor( } override fun onError(throwable: Throwable) { - if (throwable is Failure.NetworkConnection && - throwable.ioException is UnknownHostException) { - // Invalid homeserver from URL config - val url = viewModel.getInitialHomeServerUrl().orEmpty() - MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) - .setMessage(getString(R.string.login_error_homeserver_from_url_not_found, url)) - .setPositiveButton(R.string.login_error_homeserver_from_url_not_found_enter_manual) { _, _ -> - val flow = withState(viewModel) { it.onboardingFlow } ?: OnboardingFlow.SignInSignUp - viewModel.handle(OnboardingAction.OnGetStarted(resetLoginConfig = true, flow)) - } - .setNegativeButton(R.string.action_cancel, null) - .show() - } else { - super.onError(throwable) + when { + requireContext().inferNoConnectivity() -> super.onError(throwable) + throwable.isHomeserverUnavailable() -> { + val url = viewModel.getInitialHomeServerUrl().orEmpty() + homeserverUnavailableDialog(url) { onContinueFlowWithLoginConfigReset() } + } + else -> super.onError(throwable) } } + + private fun onContinueFlowWithLoginConfigReset() { + viewModel.handle(OnboardingAction.ResetDeeplinkConfig) + when (val flow = withState(viewModel) { it.onboardingFlow } ?: OnboardingFlow.SignInSignUp) { + OnboardingFlow.SignIn -> if (vectorFeatures.isOnboardingCombinedLoginEnabled()) { + viewModel.handle(OnboardingAction.OnIAlreadyHaveAnAccount(flow)) + } else { + viewModel.handle(OnboardingAction.OnGetStarted(flow)) + } + else -> viewModel.handle(OnboardingAction.OnGetStarted(flow)) + } + } + + private fun homeserverUnavailableDialog(url: String, action: () -> Unit) { + MaterialAlertDialogBuilder(requireActivity()) + .setTitle(R.string.dialog_title_error) + .setMessage(getString(R.string.login_error_homeserver_from_url_not_found, url)) + .setPositiveButton(R.string.login_error_homeserver_from_url_not_found_enter_manual) { _, _ -> action() } + .setNegativeButton(R.string.action_cancel, null) + .show() + } +} + +fun Context.inferNoConnectivity(): Boolean { + var networkAvailable = false + + val connectivityManager: ConnectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + val network = connectivityManager.activeNetwork + val networkCapabilities = connectivityManager.getNetworkCapabilities(network) + + when { + networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == true -> { + networkAvailable = true + } + networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) == true -> { + networkAvailable = true + } + networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_VPN) == true -> { + networkAvailable = true + } + } + + return !networkAvailable } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt index 2fa3b52706..c961986fd2 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt @@ -75,11 +75,11 @@ class FtueAuthSplashFragment @Inject constructor( private fun splashSubmit(isAlreadyHaveAccountEnabled: Boolean) { val getStartedFlow = if (isAlreadyHaveAccountEnabled) OnboardingFlow.SignUp else OnboardingFlow.SignInSignUp - viewModel.handle(OnboardingAction.OnGetStarted(resetLoginConfig = false, onboardingFlow = getStartedFlow)) + viewModel.handle(OnboardingAction.OnGetStarted(onboardingFlow = getStartedFlow)) } private fun alreadyHaveAnAccount() { - viewModel.handle(OnboardingAction.OnIAlreadyHaveAnAccount(resetLoginConfig = false, onboardingFlow = OnboardingFlow.SignIn)) + viewModel.handle(OnboardingAction.OnIAlreadyHaveAnAccount(onboardingFlow = OnboardingFlow.SignIn)) } override fun resetViewModel() { @@ -96,7 +96,8 @@ class FtueAuthSplashFragment @Inject constructor( .setMessage(getString(R.string.login_error_homeserver_from_url_not_found, url)) .setPositiveButton(R.string.login_error_homeserver_from_url_not_found_enter_manual) { _, _ -> val flow = withState(viewModel) { it.onboardingFlow } ?: OnboardingFlow.SignInSignUp - viewModel.handle(OnboardingAction.OnGetStarted(resetLoginConfig = true, flow)) + viewModel.handle(OnboardingAction.ResetDeeplinkConfig) + viewModel.handle(OnboardingAction.OnGetStarted(flow)) } .setNegativeButton(R.string.action_cancel, null) .show() diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthUseCaseFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthUseCaseFragment.kt index 5325b25e93..41675e20ca 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthUseCaseFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthUseCaseFragment.kt @@ -28,6 +28,8 @@ import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.core.content.ContextCompat +import com.airbnb.mvrx.withState +import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.extensions.getResTintedDrawable import im.vector.app.core.extensions.getTintedDrawable @@ -38,13 +40,14 @@ import im.vector.app.features.login.ServerType import im.vector.app.features.onboarding.FtueUseCase import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.themes.ThemeProvider +import org.matrix.android.sdk.api.failure.isHomeserverUnavailable import javax.inject.Inject private const val DARK_MODE_ICON_BACKGROUND_ALPHA = 0.30f private const val LIGHT_MODE_ICON_BACKGROUND_ALPHA = 0.15f class FtueAuthUseCaseFragment @Inject constructor( - private val themeProvider: ThemeProvider + private val themeProvider: ThemeProvider, ) : AbstractFtueAuthFragment() { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueAuthUseCaseBinding { @@ -111,4 +114,31 @@ class FtueAuthUseCaseFragment @Inject constructor( val whiteLayer = context.getTintedDrawable(R.drawable.bg_feature_icon, Color.WHITE) return LayerDrawable(arrayOf(whiteLayer, iconBackground, ContextCompat.getDrawable(context, icon))) } + + override fun onError(throwable: Throwable) { + when { + requireContext().inferNoConnectivity() -> super.onError(throwable) + throwable.isHomeserverUnavailable() -> { + val url = viewModel.getInitialHomeServerUrl().orEmpty() + homeserverUnavailableDialog(url) { onContinueFlowWithLoginConfigReset() } + } + else -> super.onError(throwable) + } + } + + private fun onContinueFlowWithLoginConfigReset() { + viewModel.handle(OnboardingAction.ResetDeeplinkConfig) + withState(viewModel) { it.useCase }?.let { + viewModel.handle(OnboardingAction.UpdateUseCase(it)) + } + } + + private fun homeserverUnavailableDialog(url: String, action: () -> Unit) { + MaterialAlertDialogBuilder(requireActivity()) + .setTitle(R.string.dialog_title_error) + .setMessage(getString(R.string.login_error_homeserver_from_url_not_found, url)) + .setPositiveButton(R.string.login_error_homeserver_from_url_not_found_enter_manual) { _, _ -> action() } + .setNegativeButton(R.string.action_cancel, null) + .show() + } } From b8418f97dc674adc68a6ef805a61b43bb38e1cac Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 12 May 2022 10:41:10 +0100 Subject: [PATCH 127/244] extracting server selection branches to their own functions --- .../onboarding/OnboardingViewModel.kt | 78 ++++++++++--------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index a7de3c157a..7970977b95 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -649,42 +649,11 @@ class OnboardingViewModel @AssistedInject constructor( } when (trigger) { - is OnboardingAction.HomeServerChange.EditHomeServer -> { - when (awaitState().onboardingFlow) { - OnboardingFlow.SignUp -> internalRegisterAction(RegisterAction.StartRegistration) { - updateServerSelection(config, serverTypeOverride, authResult) - _viewEvents.post(OnboardingViewEvents.OnHomeserverEdited) - } - OnboardingFlow.SignIn -> { - updateServerSelection(config, serverTypeOverride, authResult) - _viewEvents.post(OnboardingViewEvents.OnHomeserverEdited) - } - else -> throw IllegalArgumentException("developer error") - } - } is OnboardingAction.HomeServerChange.SelectHomeServer -> { - updateServerSelection(config, serverTypeOverride, authResult) - if (authResult.selectedHomeserver.preferredLoginMode.supportsSignModeScreen()) { - when (awaitState().onboardingFlow) { - OnboardingFlow.SignIn -> { - updateSignMode(SignMode.SignIn) - when (vectorFeatures.isOnboardingCombinedLoginEnabled()) { - true -> _viewEvents.post(OnboardingViewEvents.OpenCombinedLogin) - false -> _viewEvents.post(OnboardingViewEvents.OnSignModeSelected(SignMode.SignIn)) - } - } - OnboardingFlow.SignUp -> { - updateSignMode(SignMode.SignUp) - internalRegisterAction(RegisterAction.StartRegistration, ::emitFlowResultViewEvent) - } - OnboardingFlow.SignInSignUp, - null -> { - _viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved) - } - } - } else { - _viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved) - } + onHomeServerSelected(config, serverTypeOverride, authResult) + } + is OnboardingAction.HomeServerChange.EditHomeServer -> { + onHomeServerEdited(config, serverTypeOverride, authResult) } else -> { updateServerSelection(config, serverTypeOverride, authResult) @@ -693,6 +662,45 @@ class OnboardingViewModel @AssistedInject constructor( } } + private suspend fun onHomeServerSelected(config: HomeServerConnectionConfig, serverTypeOverride: ServerType?, authResult: StartAuthenticationResult) { + updateServerSelection(config, serverTypeOverride, authResult) + if (authResult.selectedHomeserver.preferredLoginMode.supportsSignModeScreen()) { + when (awaitState().onboardingFlow) { + OnboardingFlow.SignIn -> { + updateSignMode(SignMode.SignIn) + when (vectorFeatures.isOnboardingCombinedLoginEnabled()) { + true -> _viewEvents.post(OnboardingViewEvents.OpenCombinedLogin) + false -> _viewEvents.post(OnboardingViewEvents.OnSignModeSelected(SignMode.SignIn)) + } + } + OnboardingFlow.SignUp -> { + updateSignMode(SignMode.SignUp) + internalRegisterAction(RegisterAction.StartRegistration, ::emitFlowResultViewEvent) + } + OnboardingFlow.SignInSignUp, + null -> { + _viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved) + } + } + } else { + _viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved) + } + } + + private suspend fun onHomeServerEdited(config: HomeServerConnectionConfig, serverTypeOverride: ServerType?, authResult: StartAuthenticationResult) { + when (awaitState().onboardingFlow) { + OnboardingFlow.SignUp -> internalRegisterAction(RegisterAction.StartRegistration) { + updateServerSelection(config, serverTypeOverride, authResult) + _viewEvents.post(OnboardingViewEvents.OnHomeserverEdited) + } + OnboardingFlow.SignIn -> { + updateServerSelection(config, serverTypeOverride, authResult) + _viewEvents.post(OnboardingViewEvents.OnHomeserverEdited) + } + else -> throw IllegalArgumentException("developer error") + } + } + private fun updateServerSelection(config: HomeServerConnectionConfig, serverTypeOverride: ServerType?, authResult: StartAuthenticationResult) { setState { copy( From 59afb5cf4cfd74d2e87d1f4fd6a4ecb89f86bee4 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 12 May 2022 11:24:10 +0100 Subject: [PATCH 128/244] downscoping the possible action types when selecting homeservers --- .../features/onboarding/OnboardingAction.kt | 3 +- .../onboarding/OnboardingViewModel.kt | 60 +++++++++---------- 2 files changed, 28 insertions(+), 35 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt index 97a631dd1f..5d5dc9b6c0 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt @@ -25,7 +25,6 @@ import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.network.ssl.Fingerprint sealed interface OnboardingAction : VectorViewModelAction { - object ResetDeeplinkConfig : OnboardingAction data class OnGetStarted(val onboardingFlow: OnboardingFlow) : OnboardingAction data class OnIAlreadyHaveAnAccount(val onboardingFlow: OnboardingFlow) : OnboardingAction @@ -59,7 +58,7 @@ sealed interface OnboardingAction : VectorViewModelAction { // Reset actions sealed interface ResetAction : OnboardingAction - + object ResetDeeplinkConfig : ResetAction object ResetHomeServerType : ResetAction object ResetHomeServerUrl : ResetAction object ResetSignMode : ResetAction diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 7970977b95..f5131e1c08 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -111,8 +111,7 @@ class OnboardingViewModel @AssistedInject constructor( private var currentHomeServerConnectionConfig: HomeServerConnectionConfig? = null private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() - private val defaultHomeserverUrl: String - get() = loginConfig?.homeServerUrl?.ensureProtocol() ?: matrixOrgUrl + private val defaultHomeserverUrl = matrixOrgUrl private val registrationWizard: RegistrationWizard get() = authenticationService.getRegistrationWizard() @@ -159,7 +158,6 @@ class OnboardingViewModel @AssistedInject constructor( OnboardingAction.SaveSelectedProfilePicture -> updateProfilePicture() is OnboardingAction.PostViewEvent -> _viewEvents.post(action.viewEvent) OnboardingAction.StopEmailValidationCheck -> cancelWaitForEmailValidation() - OnboardingAction.ResetDeeplinkConfig -> loginConfig = null } } @@ -178,21 +176,7 @@ class OnboardingViewModel @AssistedInject constructor( private fun handleSplashAction(onboardingFlow: OnboardingFlow) { setState { copy(onboardingFlow = onboardingFlow) } - - return when (val config = loginConfig.toHomeserverConfig()) { - null -> continueToPageAfterSplash(onboardingFlow) - else -> startAuthenticationFlow(trigger = null, config, ServerType.Other) - } - } - - private fun LoginConfig?.toHomeserverConfig(): HomeServerConnectionConfig? { - return this?.homeServerUrl?.takeIf { it.isNotEmpty() }?.let { url -> - homeServerConnectionConfigFactory.create(url).also { - if (it == null) { - Timber.w("Url from config url was invalid: $url") - } - } - } + continueToPageAfterSplash(onboardingFlow) } private fun continueToPageAfterSplash(onboardingFlow: OnboardingFlow) { @@ -206,10 +190,21 @@ class OnboardingViewModel @AssistedInject constructor( } ) } - OnboardingFlow.SignIn -> if (vectorFeatures.isOnboardingCombinedLoginEnabled()) { - handle(OnboardingAction.HomeServerChange.SelectHomeServer(defaultHomeserverUrl)) - } else _viewEvents.post(OnboardingViewEvents.OpenServerSelection) - OnboardingFlow.SignInSignUp -> _viewEvents.post(OnboardingViewEvents.OpenServerSelection) + OnboardingFlow.SignIn -> when { + vectorFeatures.isOnboardingCombinedLoginEnabled() -> { + handle(OnboardingAction.HomeServerChange.SelectHomeServer(deeplinkOrDefaultHomeserverUrl())) + } + else -> openServerSelectionOrDeeplinkToOther() + } + + OnboardingFlow.SignInSignUp -> openServerSelectionOrDeeplinkToOther() + } + } + + private fun openServerSelectionOrDeeplinkToOther() { + when (loginConfig) { + null -> _viewEvents.post(OnboardingViewEvents.OpenServerSelection) + else -> handleHomeserverChange(OnboardingAction.HomeServerChange.SelectHomeServer(deeplinkOrDefaultHomeserverUrl()), ServerType.Other) } } @@ -220,7 +215,7 @@ class OnboardingViewModel @AssistedInject constructor( is OnboardingAction.HomeServerChange.SelectHomeServer -> { currentHomeServerConnectionConfig ?.let { it.copy(allowedFingerprints = it.allowedFingerprints + action.fingerprint) } - ?.let { startAuthenticationFlow(finalLastAction, it) } + ?.let { startAuthenticationFlow(finalLastAction, it, serverTypeOverride = null) } } is AuthenticateAction.LoginDirect -> handleDirectLogin( @@ -374,6 +369,7 @@ class OnboardingViewModel @AssistedInject constructor( ) } } + OnboardingAction.ResetDeeplinkConfig -> loginConfig = null } } @@ -394,11 +390,13 @@ class OnboardingViewModel @AssistedInject constructor( private fun handleUpdateUseCase(action: OnboardingAction.UpdateUseCase) { setState { copy(useCase = action.useCase) } when (vectorFeatures.isOnboardingCombinedRegisterEnabled()) { - true -> handle(OnboardingAction.HomeServerChange.SelectHomeServer(defaultHomeserverUrl)) + true -> handle(OnboardingAction.HomeServerChange.SelectHomeServer(deeplinkOrDefaultHomeserverUrl())) false -> _viewEvents.post(OnboardingViewEvents.OpenServerSelection) } } + private fun deeplinkOrDefaultHomeserverUrl() = loginConfig?.homeServerUrl?.ensureProtocol() ?: defaultHomeserverUrl + private fun resetUseCase() { setState { copy(useCase = null) } } @@ -610,20 +608,20 @@ class OnboardingViewModel @AssistedInject constructor( } } - private fun handleHomeserverChange(action: OnboardingAction.HomeServerChange) { + private fun handleHomeserverChange(action: OnboardingAction.HomeServerChange, serverTypeOverride: ServerType? = null) { val homeServerConnectionConfig = homeServerConnectionConfigFactory.create(action.homeServerUrl) if (homeServerConnectionConfig == null) { // This is invalid _viewEvents.post(OnboardingViewEvents.Failure(Throwable("Unable to create a HomeServerConnectionConfig"))) } else { - startAuthenticationFlow(action, homeServerConnectionConfig) + startAuthenticationFlow(action, homeServerConnectionConfig, serverTypeOverride) } } private fun startAuthenticationFlow( - trigger: OnboardingAction?, + trigger: OnboardingAction.HomeServerChange, homeServerConnectionConfig: HomeServerConnectionConfig, - serverTypeOverride: ServerType? = null + serverTypeOverride: ServerType? ) { currentHomeServerConnectionConfig = homeServerConnectionConfig @@ -638,7 +636,7 @@ class OnboardingViewModel @AssistedInject constructor( } private suspend fun onAuthenticationStartedSuccess( - trigger: OnboardingAction?, + trigger: OnboardingAction.HomeServerChange, config: HomeServerConnectionConfig, authResult: StartAuthenticationResult, serverTypeOverride: ServerType? @@ -655,10 +653,6 @@ class OnboardingViewModel @AssistedInject constructor( is OnboardingAction.HomeServerChange.EditHomeServer -> { onHomeServerEdited(config, serverTypeOverride, authResult) } - else -> { - updateServerSelection(config, serverTypeOverride, authResult) - _viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved) - } } } From 100aa2402114ea1829c8875d11d5cd792b50c1c1 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 12 May 2022 11:26:26 +0100 Subject: [PATCH 129/244] adding helper for inferring if the device has connectivity, this helps with breaking down UnknownHost exceptioncauses and shouldn't be used for checking offline status --- .../im/vector/app/core/extensions/Context.kt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/vector/src/main/java/im/vector/app/core/extensions/Context.kt b/vector/src/main/java/im/vector/app/core/extensions/Context.kt index 0f785e43a3..35bc01ef29 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Context.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Context.kt @@ -18,7 +18,10 @@ package im.vector.app.core.extensions import android.content.Context import android.graphics.drawable.Drawable +import android.net.ConnectivityManager +import android.net.NetworkCapabilities import android.net.Uri +import android.os.Build import android.text.Spannable import android.text.SpannableString import android.text.style.ImageSpan @@ -77,3 +80,30 @@ val Context.dataStoreProvider: (String) -> DataStore by dataStorePr fun Context.safeOpenOutputStream(uri: Uri): OutputStream? { return contentResolver.openOutputStream(uri, "wt") } + +/** + * Checks for an active connection to infer if the device is offline. + * This is useful for breaking down UnknownHost exceptions and should not be used to determine if a valid connection is present + * + * @return true if no active connection is found + */ +@Suppress("deprecation") +fun Context.inferNoConnectivity(): Boolean { + val connectivityManager: ConnectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + return if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { + val networkCapabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork) + when { + networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == true -> false + networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) == true -> false + networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_VPN) == true -> false + else -> true + } + } else { + when (connectivityManager.activeNetworkInfo?.type) { + ConnectivityManager.TYPE_WIFI -> false + ConnectivityManager.TYPE_MOBILE -> false + ConnectivityManager.TYPE_VPN -> false + else -> true + } + } +} From ea7df9b6735ba087f11c35133b2a59469dc8bc0e Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 12 May 2022 11:49:46 +0100 Subject: [PATCH 130/244] lifting unavailable homeserver rendering to the activity/ftuevariant - the viewmodel is now responsible for inferring connectivity errors and providing a retry action --- .../features/onboarding/OnboardingAction.kt | 8 ++- .../onboarding/OnboardingViewEvents.kt | 1 + .../onboarding/OnboardingViewModel.kt | 29 +++++++-- .../FtueAuthSplashCarouselFragment.kt | 64 +------------------ .../ftueauth/FtueAuthSplashFragment.kt | 28 +------- .../ftueauth/FtueAuthUseCaseFragment.kt | 32 +--------- .../onboarding/ftueauth/FtueAuthVariant.kt | 21 +++++- .../onboarding/ftueauth/FtueExtensions.kt | 4 ++ 8 files changed, 58 insertions(+), 129 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt index 5d5dc9b6c0..ce387d29fa 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt @@ -25,8 +25,12 @@ import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.network.ssl.Fingerprint sealed interface OnboardingAction : VectorViewModelAction { - data class OnGetStarted(val onboardingFlow: OnboardingFlow) : OnboardingAction - data class OnIAlreadyHaveAnAccount(val onboardingFlow: OnboardingFlow) : OnboardingAction + sealed interface SplashAction: OnboardingAction { + val onboardingFlow: OnboardingFlow + + data class OnGetStarted(override val onboardingFlow: OnboardingFlow) : SplashAction + data class OnIAlreadyHaveAnAccount(override val onboardingFlow: OnboardingFlow) : SplashAction + } data class UpdateServerType(val serverType: ServerType) : OnboardingAction diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewEvents.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewEvents.kt index 5dbcd162f3..5d6e7005c4 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewEvents.kt @@ -28,6 +28,7 @@ import org.matrix.android.sdk.api.auth.registration.FlowResult sealed class OnboardingViewEvents : VectorViewEvents { data class Loading(val message: CharSequence? = null) : OnboardingViewEvents() data class Failure(val throwable: Throwable) : OnboardingViewEvents() + data class DeeplinkAuthenticationFailure(val retryAction: OnboardingAction) : OnboardingViewEvents() data class RegistrationFlowResult(val flowResult: FlowResult, val isRegistrationStarted: Boolean) : OnboardingViewEvents() object OutdatedHomeserver : OnboardingViewEvents() diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index f5131e1c08..2a5f57ac70 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -27,6 +27,7 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.extensions.cancelCurrentOnSet import im.vector.app.core.extensions.configureAndStart +import im.vector.app.core.extensions.inferNoConnectivity import im.vector.app.core.extensions.vectorStore import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider @@ -56,6 +57,7 @@ import org.matrix.android.sdk.api.auth.login.LoginWizard import org.matrix.android.sdk.api.auth.registration.FlowResult import org.matrix.android.sdk.api.auth.registration.RegistrationWizard import org.matrix.android.sdk.api.auth.registration.Stage +import org.matrix.android.sdk.api.failure.isHomeserverUnavailable import org.matrix.android.sdk.api.session.Session import timber.log.Timber import java.util.UUID @@ -133,8 +135,7 @@ class OnboardingViewModel @AssistedInject constructor( override fun handle(action: OnboardingAction) { when (action) { - is OnboardingAction.OnGetStarted -> handleSplashAction(action.onboardingFlow) - is OnboardingAction.OnIAlreadyHaveAnAccount -> handleSplashAction(action.onboardingFlow) + is OnboardingAction.SplashAction -> handleSplashAction(action) is OnboardingAction.UpdateUseCase -> handleUpdateUseCase(action) OnboardingAction.ResetUseCase -> resetUseCase() is OnboardingAction.UpdateServerType -> handleUpdateServerType(action) @@ -174,9 +175,9 @@ class OnboardingViewModel @AssistedInject constructor( } } - private fun handleSplashAction(onboardingFlow: OnboardingFlow) { - setState { copy(onboardingFlow = onboardingFlow) } - continueToPageAfterSplash(onboardingFlow) + private fun handleSplashAction(action: OnboardingAction.SplashAction) { + setState { copy(onboardingFlow = action.onboardingFlow) } + continueToPageAfterSplash(action.onboardingFlow) } private fun continueToPageAfterSplash(onboardingFlow: OnboardingFlow) { @@ -629,12 +630,28 @@ class OnboardingViewModel @AssistedInject constructor( setState { copy(isLoading = true) } runCatching { startAuthenticationFlowUseCase.execute(homeServerConnectionConfig) }.fold( onSuccess = { onAuthenticationStartedSuccess(trigger, homeServerConnectionConfig, it, serverTypeOverride) }, - onFailure = { _viewEvents.post(OnboardingViewEvents.Failure(it)) } + onFailure = { onAuthenticationStartError(it, trigger) } ) setState { copy(isLoading = false) } } } + private fun onAuthenticationStartError(it: Throwable, trigger: OnboardingAction.HomeServerChange) { + when { + it.isHomeserverUnavailable() && applicationContext.inferNoConnectivity() -> _viewEvents.post( + OnboardingViewEvents.Failure(it) + ) + it.isHomeserverUnavailable() && trigger is OnboardingAction.HomeServerChange.SelectHomeServer -> _viewEvents.post( + OnboardingViewEvents.DeeplinkAuthenticationFailure(retryAction = trigger.resetToDefaultUrl()) + ) + else -> _viewEvents.post( + OnboardingViewEvents.Failure(it) + ) + } + } + + private fun OnboardingAction.HomeServerChange.SelectHomeServer.resetToDefaultUrl() = copy(homeServerUrl = defaultHomeserverUrl) + private suspend fun onAuthenticationStartedSuccess( trigger: OnboardingAction.HomeServerChange, config: HomeServerConnectionConfig, diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt index 8306589e89..0d86c4cd24 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt @@ -17,9 +17,6 @@ package im.vector.app.features.onboarding.ftueauth import android.annotation.SuppressLint -import android.content.Context -import android.net.ConnectivityManager -import android.net.NetworkCapabilities import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -29,8 +26,6 @@ import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.lifecycleScope import androidx.viewpager2.widget.ViewPager2 -import com.airbnb.mvrx.withState -import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.tabs.TabLayoutMediator import im.vector.app.BuildConfig import im.vector.app.R @@ -44,7 +39,6 @@ import im.vector.app.features.settings.VectorPreferences import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import org.matrix.android.sdk.api.failure.isHomeserverUnavailable import javax.inject.Inject private const val CAROUSEL_ROTATION_DELAY_MS = 5000L @@ -130,68 +124,14 @@ class FtueAuthSplashCarouselFragment @Inject constructor( private fun splashSubmit(isAlreadyHaveAccountEnabled: Boolean) { val getStartedFlow = if (isAlreadyHaveAccountEnabled) OnboardingFlow.SignUp else OnboardingFlow.SignInSignUp - viewModel.handle(OnboardingAction.OnGetStarted(onboardingFlow = getStartedFlow)) + viewModel.handle(OnboardingAction.SplashAction.OnGetStarted(onboardingFlow = getStartedFlow)) } private fun alreadyHaveAnAccount() { - viewModel.handle(OnboardingAction.OnIAlreadyHaveAnAccount(onboardingFlow = OnboardingFlow.SignIn)) + viewModel.handle(OnboardingAction.SplashAction.OnIAlreadyHaveAnAccount(onboardingFlow = OnboardingFlow.SignIn)) } override fun resetViewModel() { // Nothing to do } - - override fun onError(throwable: Throwable) { - when { - requireContext().inferNoConnectivity() -> super.onError(throwable) - throwable.isHomeserverUnavailable() -> { - val url = viewModel.getInitialHomeServerUrl().orEmpty() - homeserverUnavailableDialog(url) { onContinueFlowWithLoginConfigReset() } - } - else -> super.onError(throwable) - } - } - - private fun onContinueFlowWithLoginConfigReset() { - viewModel.handle(OnboardingAction.ResetDeeplinkConfig) - when (val flow = withState(viewModel) { it.onboardingFlow } ?: OnboardingFlow.SignInSignUp) { - OnboardingFlow.SignIn -> if (vectorFeatures.isOnboardingCombinedLoginEnabled()) { - viewModel.handle(OnboardingAction.OnIAlreadyHaveAnAccount(flow)) - } else { - viewModel.handle(OnboardingAction.OnGetStarted(flow)) - } - else -> viewModel.handle(OnboardingAction.OnGetStarted(flow)) - } - } - - private fun homeserverUnavailableDialog(url: String, action: () -> Unit) { - MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) - .setMessage(getString(R.string.login_error_homeserver_from_url_not_found, url)) - .setPositiveButton(R.string.login_error_homeserver_from_url_not_found_enter_manual) { _, _ -> action() } - .setNegativeButton(R.string.action_cancel, null) - .show() - } -} - -fun Context.inferNoConnectivity(): Boolean { - var networkAvailable = false - - val connectivityManager: ConnectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - val network = connectivityManager.activeNetwork - val networkCapabilities = connectivityManager.getNetworkCapabilities(network) - - when { - networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == true -> { - networkAvailable = true - } - networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) == true -> { - networkAvailable = true - } - networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_VPN) == true -> { - networkAvailable = true - } - } - - return !networkAvailable } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt index c961986fd2..cd1e4b2714 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt @@ -22,8 +22,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible -import com.airbnb.mvrx.withState -import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.BuildConfig import im.vector.app.R import im.vector.app.databinding.FragmentFtueAuthSplashBinding @@ -31,8 +29,6 @@ import im.vector.app.features.VectorFeatures import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingFlow import im.vector.app.features.settings.VectorPreferences -import org.matrix.android.sdk.api.failure.Failure -import java.net.UnknownHostException import javax.inject.Inject /** @@ -75,34 +71,14 @@ class FtueAuthSplashFragment @Inject constructor( private fun splashSubmit(isAlreadyHaveAccountEnabled: Boolean) { val getStartedFlow = if (isAlreadyHaveAccountEnabled) OnboardingFlow.SignUp else OnboardingFlow.SignInSignUp - viewModel.handle(OnboardingAction.OnGetStarted(onboardingFlow = getStartedFlow)) + viewModel.handle(OnboardingAction.SplashAction.OnGetStarted(onboardingFlow = getStartedFlow)) } private fun alreadyHaveAnAccount() { - viewModel.handle(OnboardingAction.OnIAlreadyHaveAnAccount(onboardingFlow = OnboardingFlow.SignIn)) + viewModel.handle(OnboardingAction.SplashAction.OnIAlreadyHaveAnAccount(onboardingFlow = OnboardingFlow.SignIn)) } override fun resetViewModel() { // Nothing to do } - - override fun onError(throwable: Throwable) { - if (throwable is Failure.NetworkConnection && - throwable.ioException is UnknownHostException) { - // Invalid homeserver from URL config - val url = viewModel.getInitialHomeServerUrl().orEmpty() - MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) - .setMessage(getString(R.string.login_error_homeserver_from_url_not_found, url)) - .setPositiveButton(R.string.login_error_homeserver_from_url_not_found_enter_manual) { _, _ -> - val flow = withState(viewModel) { it.onboardingFlow } ?: OnboardingFlow.SignInSignUp - viewModel.handle(OnboardingAction.ResetDeeplinkConfig) - viewModel.handle(OnboardingAction.OnGetStarted(flow)) - } - .setNegativeButton(R.string.action_cancel, null) - .show() - } else { - super.onError(throwable) - } - } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthUseCaseFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthUseCaseFragment.kt index 41675e20ca..35439a794e 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthUseCaseFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthUseCaseFragment.kt @@ -28,8 +28,6 @@ import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.core.content.ContextCompat -import com.airbnb.mvrx.withState -import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.extensions.getResTintedDrawable import im.vector.app.core.extensions.getTintedDrawable @@ -40,7 +38,6 @@ import im.vector.app.features.login.ServerType import im.vector.app.features.onboarding.FtueUseCase import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.themes.ThemeProvider -import org.matrix.android.sdk.api.failure.isHomeserverUnavailable import javax.inject.Inject private const val DARK_MODE_ICON_BACKGROUND_ALPHA = 0.30f @@ -107,38 +104,11 @@ class FtueAuthUseCaseFragment @Inject constructor( private fun createIcon(@ColorRes tint: Int, icon: Int, isLightMode: Boolean): Drawable { val context = requireContext() val alpha = when (isLightMode) { - true -> LIGHT_MODE_ICON_BACKGROUND_ALPHA + true -> LIGHT_MODE_ICON_BACKGROUND_ALPHA false -> DARK_MODE_ICON_BACKGROUND_ALPHA } val iconBackground = context.getResTintedDrawable(R.drawable.bg_feature_icon, tint, alpha = alpha) val whiteLayer = context.getTintedDrawable(R.drawable.bg_feature_icon, Color.WHITE) return LayerDrawable(arrayOf(whiteLayer, iconBackground, ContextCompat.getDrawable(context, icon))) } - - override fun onError(throwable: Throwable) { - when { - requireContext().inferNoConnectivity() -> super.onError(throwable) - throwable.isHomeserverUnavailable() -> { - val url = viewModel.getInitialHomeServerUrl().orEmpty() - homeserverUnavailableDialog(url) { onContinueFlowWithLoginConfigReset() } - } - else -> super.onError(throwable) - } - } - - private fun onContinueFlowWithLoginConfigReset() { - viewModel.handle(OnboardingAction.ResetDeeplinkConfig) - withState(viewModel) { it.useCase }?.let { - viewModel.handle(OnboardingAction.UpdateUseCase(it)) - } - } - - private fun homeserverUnavailableDialog(url: String, action: () -> Unit) { - MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) - .setMessage(getString(R.string.login_error_homeserver_from_url_not_found, url)) - .setPositiveButton(R.string.login_error_homeserver_from_url_not_found_enter_manual) { _, _ -> action() } - .setNegativeButton(R.string.action_cancel, null) - .show() - } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt index 5ad6b7e78d..7a3729ac69 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt @@ -227,11 +227,28 @@ class FtueAuthVariant( option = commonOption ) } - OnboardingViewEvents.OnHomeserverEdited -> activity.popBackstack() - OnboardingViewEvents.OpenCombinedLogin -> onStartCombinedLogin() + OnboardingViewEvents.OnHomeserverEdited -> activity.popBackstack() + OnboardingViewEvents.OpenCombinedLogin -> onStartCombinedLogin() + is OnboardingViewEvents.DeeplinkAuthenticationFailure -> onDeeplinkedHomeserverUnavailable(viewEvents) } } + private fun onDeeplinkedHomeserverUnavailable(viewEvents: OnboardingViewEvents.DeeplinkAuthenticationFailure) { + showHomeserverUnavailableDialog(onboardingViewModel.getInitialHomeServerUrl().orEmpty()) { + onboardingViewModel.handle(OnboardingAction.ResetDeeplinkConfig) + onboardingViewModel.handle(viewEvents.retryAction) + } + } + + private fun showHomeserverUnavailableDialog(url: String, action: () -> Unit) { + MaterialAlertDialogBuilder(activity) + .setTitle(R.string.dialog_title_error) + .setMessage(activity.getString(R.string.login_error_homeserver_from_url_not_found, url)) + .setPositiveButton(R.string.login_error_homeserver_from_url_not_found_enter_manual) { _, _ -> action() } + .setNegativeButton(R.string.action_cancel, null) + .show() + } + private fun onStartCombinedLogin() { addRegistrationStageFragmentToBackstack(FtueAuthCombinedLoginFragment::class.java) } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt index 8d63fbf547..5228e289bc 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt @@ -17,13 +17,17 @@ package im.vector.app.features.onboarding.ftueauth import android.widget.Button +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.textfield.TextInputLayout +import im.vector.app.R import im.vector.app.core.extensions.hasContentFlow +import im.vector.app.core.extensions.inferNoConnectivity import im.vector.app.features.login.SignMode import im.vector.app.features.onboarding.OnboardingAction import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.onEach +import org.matrix.android.sdk.api.failure.isHomeserverUnavailable fun SignMode.toAuthenticateAction(login: String, password: String, initialDeviceName: String): OnboardingAction.AuthenticateAction { return when (this) { From 797e0ee7066787dc31ec8253aed0cae4a177c8aa Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 12 May 2022 12:33:23 +0100 Subject: [PATCH 131/244] creating a build meta abstraction for allowing testing classes with build version checks --- .../im/vector/app/core/di/SingletonModule.kt | 6 +++++ .../im/vector/app/core/resources/BuildMeta.kt | 23 +++++++++++++++++++ .../app/test/fixtures/BuildMetaFixture.kt | 22 ++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 vector/src/main/java/im/vector/app/core/resources/BuildMeta.kt create mode 100644 vector/src/test/java/im/vector/app/test/fixtures/BuildMetaFixture.kt diff --git a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt index 2945ae7d87..22ce4ee0ce 100644 --- a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt @@ -33,6 +33,7 @@ import im.vector.app.config.analyticsConfig import im.vector.app.core.dispatchers.CoroutineDispatchers import im.vector.app.core.error.DefaultErrorFormatter import im.vector.app.core.error.ErrorFormatter +import im.vector.app.core.resources.BuildMeta import im.vector.app.core.time.Clock import im.vector.app.core.time.DefaultClock import im.vector.app.features.analytics.AnalyticsConfig @@ -185,4 +186,9 @@ object VectorStaticModule { fun providesAnalyticsConfig(): AnalyticsConfig { return analyticsConfig } + + + @Provides + @Singleton + fun providesBuildMeta() = BuildMeta() } diff --git a/vector/src/main/java/im/vector/app/core/resources/BuildMeta.kt b/vector/src/main/java/im/vector/app/core/resources/BuildMeta.kt new file mode 100644 index 0000000000..14d97e4c8f --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/resources/BuildMeta.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.core.resources + +import android.os.Build + +data class BuildMeta( + val sdkInt: Int = Build.VERSION.SDK_INT +) diff --git a/vector/src/test/java/im/vector/app/test/fixtures/BuildMetaFixture.kt b/vector/src/test/java/im/vector/app/test/fixtures/BuildMetaFixture.kt new file mode 100644 index 0000000000..b0e6b1dd51 --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fixtures/BuildMetaFixture.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.test.fixtures + +import android.os.Build +import im.vector.app.core.resources.BuildMeta + +fun aBuildMeta() = BuildMeta(Build.VERSION_CODES.O) From 75d038b05863422c16eee51141dfc76feadf359f Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 12 May 2022 12:35:13 +0100 Subject: [PATCH 132/244] adding test case around invalid deeplinks within the onboarding flow --- .../im/vector/app/core/di/SingletonModule.kt | 1 - .../im/vector/app/core/extensions/Context.kt | 10 +++-- .../onboarding/OnboardingViewModel.kt | 18 +++++--- .../onboarding/ftueauth/FtueExtensions.kt | 4 -- .../onboarding/OnboardingViewModelTest.kt | 29 +++++++++++- .../app/test/fakes/FakeConnectivityManager.kt | 44 +++++++++++++++++++ .../im/vector/app/test/fakes/FakeContext.kt | 18 ++++++++ .../app/test/fakes/FakeNetworkCapabilities.kt | 32 ++++++++++++++ .../FakeStartAuthenticationFlowUseCase.kt | 6 +++ .../app/test/fixtures/FailureFixture.kt | 3 ++ 10 files changed, 151 insertions(+), 14 deletions(-) create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeConnectivityManager.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeNetworkCapabilities.kt diff --git a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt index 22ce4ee0ce..44f8bb1b3e 100644 --- a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt @@ -187,7 +187,6 @@ object VectorStaticModule { return analyticsConfig } - @Provides @Singleton fun providesBuildMeta() = BuildMeta() diff --git a/vector/src/main/java/im/vector/app/core/extensions/Context.kt b/vector/src/main/java/im/vector/app/core/extensions/Context.kt index 35bc01ef29..81844a403b 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Context.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Context.kt @@ -16,6 +16,7 @@ package im.vector.app.core.extensions +import android.annotation.SuppressLint import android.content.Context import android.graphics.drawable.Drawable import android.net.ConnectivityManager @@ -30,11 +31,13 @@ import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.annotation.FloatRange import androidx.core.content.ContextCompat +import androidx.core.content.getSystemService import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import dagger.hilt.EntryPoints import im.vector.app.core.datastore.dataStoreProvider import im.vector.app.core.di.SingletonEntryPoint +import im.vector.app.core.resources.BuildMeta import java.io.OutputStream import kotlin.math.roundToInt @@ -88,9 +91,10 @@ fun Context.safeOpenOutputStream(uri: Uri): OutputStream? { * @return true if no active connection is found */ @Suppress("deprecation") -fun Context.inferNoConnectivity(): Boolean { - val connectivityManager: ConnectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - return if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { +@SuppressLint("NewApi") // false positive +fun Context.inferNoConnectivity(buildMeta: BuildMeta): Boolean { + val connectivityManager = getSystemService()!! + return if (buildMeta.sdkInt > Build.VERSION_CODES.M) { val networkCapabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork) when { networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == true -> false diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 2a5f57ac70..5af4fa138b 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -30,6 +30,7 @@ import im.vector.app.core.extensions.configureAndStart import im.vector.app.core.extensions.inferNoConnectivity import im.vector.app.core.extensions.vectorStore import im.vector.app.core.platform.VectorViewModel +import im.vector.app.core.resources.BuildMeta import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.ensureProtocol import im.vector.app.core.utils.ensureTrailingSlash @@ -81,7 +82,8 @@ class OnboardingViewModel @AssistedInject constructor( private val registrationActionHandler: RegistrationActionHandler, private val directLoginUseCase: DirectLoginUseCase, private val startAuthenticationFlowUseCase: StartAuthenticationFlowUseCase, - private val vectorOverrides: VectorOverrides + private val vectorOverrides: VectorOverrides, + private val buildMeta: BuildMeta ) : VectorViewModel(initialState) { @AssistedFactory @@ -638,18 +640,24 @@ class OnboardingViewModel @AssistedInject constructor( private fun onAuthenticationStartError(it: Throwable, trigger: OnboardingAction.HomeServerChange) { when { - it.isHomeserverUnavailable() && applicationContext.inferNoConnectivity() -> _viewEvents.post( + it.isHomeserverUnavailable() && applicationContext.inferNoConnectivity(buildMeta) -> _viewEvents.post( OnboardingViewEvents.Failure(it) ) - it.isHomeserverUnavailable() && trigger is OnboardingAction.HomeServerChange.SelectHomeServer -> _viewEvents.post( - OnboardingViewEvents.DeeplinkAuthenticationFailure(retryAction = trigger.resetToDefaultUrl()) + deeplinkUrlIsUnavailable(it, trigger) -> _viewEvents.post( + OnboardingViewEvents.DeeplinkAuthenticationFailure( + retryAction = (trigger as OnboardingAction.HomeServerChange.SelectHomeServer).resetToDefaultUrl() + ) ) - else -> _viewEvents.post( + else -> _viewEvents.post( OnboardingViewEvents.Failure(it) ) } } + private fun deeplinkUrlIsUnavailable(error: Throwable, trigger: OnboardingAction.HomeServerChange) = error.isHomeserverUnavailable() && + loginConfig != null && + trigger is OnboardingAction.HomeServerChange.SelectHomeServer + private fun OnboardingAction.HomeServerChange.SelectHomeServer.resetToDefaultUrl() = copy(homeServerUrl = defaultHomeserverUrl) private suspend fun onAuthenticationStartedSuccess( diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt index 5228e289bc..8d63fbf547 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt @@ -17,17 +17,13 @@ package im.vector.app.features.onboarding.ftueauth import android.widget.Button -import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.textfield.TextInputLayout -import im.vector.app.R import im.vector.app.core.extensions.hasContentFlow -import im.vector.app.core.extensions.inferNoConnectivity import im.vector.app.features.login.SignMode import im.vector.app.features.onboarding.OnboardingAction import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.onEach -import org.matrix.android.sdk.api.failure.isHomeserverUnavailable fun SignMode.toAuthenticateAction(login: String, password: String, initialDeviceName: String): OnboardingAction.AuthenticateAction { return when (this) { diff --git a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt index e4e687536c..3c394181d1 100644 --- a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt @@ -18,6 +18,8 @@ package im.vector.app.features.onboarding import android.net.Uri import com.airbnb.mvrx.test.MvRxTestRule +import im.vector.app.R +import im.vector.app.features.login.LoginConfig import im.vector.app.features.login.LoginMode import im.vector.app.features.login.ReAuthHelper import im.vector.app.features.login.SignMode @@ -38,6 +40,8 @@ import im.vector.app.test.fakes.FakeUri import im.vector.app.test.fakes.FakeUriFilenameResolver import im.vector.app.test.fakes.FakeVectorFeatures import im.vector.app.test.fakes.FakeVectorOverrides +import im.vector.app.test.fakes.toTestString +import im.vector.app.test.fixtures.aBuildMeta import im.vector.app.test.fixtures.aHomeServerCapabilities import im.vector.app.test.test import kotlinx.coroutines.test.runTest @@ -242,6 +246,28 @@ class OnboardingViewModelTest { .finish() } + @Test + fun `given unavailable deeplink, when selecting homeserver, then emits failure with default homeserver as retry action`() = runTest { + fakeContext.givenHasConnection() + fakeHomeServerConnectionConfigFactory.givenConfigFor(A_HOMESERVER_URL, A_HOMESERVER_CONFIG) + fakeStartAuthenticationFlowUseCase.givenHomeserverUnavailable(A_HOMESERVER_CONFIG) + val test = viewModel.test() + + viewModel.handle(OnboardingAction.InitWith(LoginConfig(A_HOMESERVER_URL, null))) + viewModel.handle(OnboardingAction.HomeServerChange.SelectHomeServer(A_HOMESERVER_URL)) + + val expectedRetryAction = OnboardingAction.HomeServerChange.SelectHomeServer("${R.string.matrix_org_server_url.toTestString()}/") + test + .assertStatesChanges( + initialState, + { copy(isLoading = true) }, + { copy(isLoading = false) } + + ) + .assertEvents(OnboardingViewEvents.DeeplinkAuthenticationFailure(expectedRetryAction)) + .finish() + } + @Test fun `given in the sign up flow, when editing homeserver, then updates selected homeserver state and emits edited event`() = runTest { viewModelWith(initialState.copy(onboardingFlow = OnboardingFlow.SignUp)) @@ -457,7 +483,8 @@ class OnboardingViewModelTest { fakeRegisterActionHandler.instance, fakeDirectLoginUseCase.instance, fakeStartAuthenticationFlowUseCase.instance, - FakeVectorOverrides() + FakeVectorOverrides(), + aBuildMeta() ).also { viewModel = it initialState = state diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeConnectivityManager.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeConnectivityManager.kt new file mode 100644 index 0000000000..d565105f81 --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeConnectivityManager.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.test.fakes + +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import io.mockk.every +import io.mockk.mockk + +class FakeConnectivityManager { + val instance = mockk() + + fun givenNoActiveConnection() { + every { instance.activeNetwork } returns null + } + + fun givenHasActiveConnection() { + val network = mockk() + every { instance.activeNetwork } returns network + + val networkCapabilities = FakeNetworkCapabilities() + networkCapabilities.givenTransports( + NetworkCapabilities.TRANSPORT_CELLULAR, + NetworkCapabilities.TRANSPORT_WIFI, + NetworkCapabilities.TRANSPORT_VPN + ) + every { instance.getNetworkCapabilities(network) } returns networkCapabilities.instance + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeContext.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeContext.kt index 2a50c34ca3..eb491c9e0c 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeContext.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeContext.kt @@ -18,6 +18,7 @@ package im.vector.app.test.fakes import android.content.ContentResolver import android.content.Context +import android.net.ConnectivityManager import android.net.Uri import android.os.ParcelFileDescriptor import io.mockk.every @@ -48,4 +49,21 @@ class FakeContext( fun givenMissingSafeOutputStreamFor(uri: Uri) { every { contentResolver.openOutputStream(uri, "wt") } returns null } + + fun givenNoConnection() { + val connectivityManager = FakeConnectivityManager() + connectivityManager.givenNoActiveConnection() + givenService(Context.CONNECTIVITY_SERVICE, ConnectivityManager::class.java, connectivityManager.instance) + } + + private fun givenService(name: String, klass: Class, service: T) { + every { instance.getSystemService(name) } returns service + every { instance.getSystemService(klass) } returns service + } + + fun givenHasConnection() { + val connectivityManager = FakeConnectivityManager() + connectivityManager.givenHasActiveConnection() + givenService(Context.CONNECTIVITY_SERVICE, ConnectivityManager::class.java, connectivityManager.instance) + } } diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeNetworkCapabilities.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeNetworkCapabilities.kt new file mode 100644 index 0000000000..36add7128c --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeNetworkCapabilities.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.test.fakes + +import android.net.NetworkCapabilities +import io.mockk.every +import io.mockk.mockk + +class FakeNetworkCapabilities { + val instance = mockk() + + fun givenTransports(vararg type: Int) { + every { instance.hasTransport(any()) } answers { + val input = it.invocation.args.first() as Int + type.contains(input) + } + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeStartAuthenticationFlowUseCase.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeStartAuthenticationFlowUseCase.kt index 697de6bf25..88ad1a7a6b 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeStartAuthenticationFlowUseCase.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeStartAuthenticationFlowUseCase.kt @@ -18,9 +18,11 @@ package im.vector.app.test.fakes import im.vector.app.features.onboarding.StartAuthenticationFlowUseCase import im.vector.app.features.onboarding.StartAuthenticationFlowUseCase.StartAuthenticationResult +import im.vector.app.test.fixtures.aHomeserverUnavailableError import io.mockk.coEvery import io.mockk.mockk import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig +import org.matrix.android.sdk.api.failure.Failure class FakeStartAuthenticationFlowUseCase { @@ -29,4 +31,8 @@ class FakeStartAuthenticationFlowUseCase { fun givenResult(config: HomeServerConnectionConfig, result: StartAuthenticationResult) { coEvery { instance.execute(config) } returns result } + + fun givenHomeserverUnavailable(config: HomeServerConnectionConfig) { + coEvery { instance.execute(config) } throws aHomeserverUnavailableError() + } } diff --git a/vector/src/test/java/im/vector/app/test/fixtures/FailureFixture.kt b/vector/src/test/java/im/vector/app/test/fixtures/FailureFixture.kt index 39c139c208..9ac851ef5e 100644 --- a/vector/src/test/java/im/vector/app/test/fixtures/FailureFixture.kt +++ b/vector/src/test/java/im/vector/app/test/fixtures/FailureFixture.kt @@ -18,8 +18,11 @@ package im.vector.app.test.fixtures import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError +import java.net.UnknownHostException import javax.net.ssl.HttpsURLConnection fun a401ServerError() = Failure.ServerError( MatrixError(MatrixError.M_UNAUTHORIZED, ""), HttpsURLConnection.HTTP_UNAUTHORIZED ) + +fun aHomeserverUnavailableError() = Failure.NetworkConnection(UnknownHostException()) From 73c93958c23fe54023e159f95d89f4c8a277633b Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 12 May 2022 15:10:53 +0100 Subject: [PATCH 133/244] adding changelog entry --- changelog.d/6023.wip | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6023.wip diff --git a/changelog.d/6023.wip b/changelog.d/6023.wip new file mode 100644 index 0000000000..aefd62bcd7 --- /dev/null +++ b/changelog.d/6023.wip @@ -0,0 +1 @@ +FTUE - Adds homeserver login/register deeplink support From f6190b125c458ec5f2542ebce332ace6ef87ac21 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 12 May 2022 15:11:12 +0100 Subject: [PATCH 134/244] removing extra line --- .../im/vector/app/features/onboarding/OnboardingViewModelTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt index 3c394181d1..1abfa7e9a8 100644 --- a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt @@ -262,7 +262,6 @@ class OnboardingViewModelTest { initialState, { copy(isLoading = true) }, { copy(isLoading = false) } - ) .assertEvents(OnboardingViewEvents.DeeplinkAuthenticationFailure(expectedRetryAction)) .finish() From 86c9e601291fe120ff8ed791efa4102dae3cd78f Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 17 May 2022 10:46:15 +0100 Subject: [PATCH 135/244] formatting --- .../java/im/vector/app/features/onboarding/OnboardingAction.kt | 2 +- .../app/test/fakes/FakeStartAuthenticationFlowUseCase.kt | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt index ce387d29fa..bd2ff1a26a 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt @@ -25,7 +25,7 @@ import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.network.ssl.Fingerprint sealed interface OnboardingAction : VectorViewModelAction { - sealed interface SplashAction: OnboardingAction { + sealed interface SplashAction : OnboardingAction { val onboardingFlow: OnboardingFlow data class OnGetStarted(override val onboardingFlow: OnboardingFlow) : SplashAction diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeStartAuthenticationFlowUseCase.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeStartAuthenticationFlowUseCase.kt index 88ad1a7a6b..bfbef9e565 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeStartAuthenticationFlowUseCase.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeStartAuthenticationFlowUseCase.kt @@ -22,7 +22,6 @@ import im.vector.app.test.fixtures.aHomeserverUnavailableError import io.mockk.coEvery import io.mockk.mockk import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig -import org.matrix.android.sdk.api.failure.Failure class FakeStartAuthenticationFlowUseCase { @@ -33,6 +32,6 @@ class FakeStartAuthenticationFlowUseCase { } fun givenHomeserverUnavailable(config: HomeServerConnectionConfig) { - coEvery { instance.execute(config) } throws aHomeserverUnavailableError() + coEvery { instance.execute(config) } throws aHomeserverUnavailableError() } } From 8f0641574473c57f63cfe73057e5270bbab0149b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 25 May 2022 15:08:13 +0200 Subject: [PATCH 136/244] Fix compilation issue after rebase --- .../app/features/crypto/quads/SharedSecureStorageViewModel.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt index e045ac020d..649890cda9 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt @@ -41,8 +41,8 @@ import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.securestorage.IntegrityResult import org.matrix.android.sdk.api.session.securestorage.KeyInfo import org.matrix.android.sdk.api.session.securestorage.KeyInfoResult +import org.matrix.android.sdk.api.session.securestorage.KeyRef import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec -import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService import org.matrix.android.sdk.api.util.toBase64NoPadding import org.matrix.android.sdk.flow.flow import timber.log.Timber @@ -283,7 +283,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor( session.sharedSecretStorageService().storeSecret( name = name, secretBase64 = value, - keys = listOf(SharedSecretStorageService.KeyRef(keyInfo.id, keySpec)) + keys = listOf(KeyRef(keyInfo.id, keySpec)) ) decryptedSecretMap[name] = value } From 6ec6d41aa992b8d58b9bde03e4d2c727e3e3d237 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Wed, 25 May 2022 15:53:58 +0200 Subject: [PATCH 137/244] Make permission utils instantiable and throw when permission request is null --- .../app/features/widgets/WidgetFragment.kt | 8 +++-- .../widgets/webview/WebviewPermissionUtils.kt | 30 ++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt index c8a13d11cf..ed2c69c908 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt @@ -72,6 +72,7 @@ class WidgetFragment @Inject constructor() : private val fragmentArgs: WidgetArgs by args() private val viewModel: WidgetViewModel by activityViewModel() + private val permissionUtils = WebviewPermissionUtils() override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentRoomWidgetBinding { return FragmentRoomWidgetBinding.inflate(inflater, container, false) @@ -277,16 +278,17 @@ class WidgetFragment @Inject constructor() : } private val permissionResultLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result -> - WebviewPermissionUtils.onPermissionResult(result) + permissionUtils.onPermissionResult(result) } override fun onPermissionRequest(request: PermissionRequest) { - WebviewPermissionUtils.promptForPermissions( + permissionUtils.promptForPermissions( title = R.string.room_widget_resource_permission_title, request = request, context = requireContext(), activity = requireActivity(), - activityResultLauncher = permissionResultLauncher) + activityResultLauncher = permissionResultLauncher + ) } private fun displayTerms(displayTerms: WidgetViewEvents.DisplayTerms) { diff --git a/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt b/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt index f1111a4650..3a39153581 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt @@ -25,8 +25,9 @@ import androidx.fragment.app.FragmentActivity import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.utils.checkPermissions +import java.lang.NullPointerException -object WebviewPermissionUtils { +class WebviewPermissionUtils { private var permissionRequest: PermissionRequest? = null private var selectedPermissions = listOf() @@ -73,20 +74,21 @@ object WebviewPermissionUtils { } fun onPermissionResult(result: Map) { - permissionRequest?.let { request -> - val grantedPermissions = selectedPermissions.filter { webPermission -> - val androidPermission = webPermissionToAndroidPermission(webPermission) - ?: return@filter true // No corresponding Android permission exists - return@filter result[androidPermission] - ?: return@filter true // Android permission already granted before - } - if (grantedPermissions.isNotEmpty()) { - request.grant(grantedPermissions.toTypedArray()) - } else { - request.deny() - } - reset() + if (permissionRequest == null) { + throw NullPointerException("permissionRequest was null! Make sure to call promptForPermissions first.") } + val grantedPermissions = selectedPermissions.filter { webPermission -> + val androidPermission = webPermissionToAndroidPermission(webPermission) + ?: return@filter true // No corresponding Android permission exists + return@filter result[androidPermission] + ?: return@filter true // Android permission already granted before + } + if (grantedPermissions.isNotEmpty()) { + permissionRequest?.grant(grantedPermissions.toTypedArray()) + } else { + permissionRequest?.deny() + } + reset() } private fun reset() { From 9e084ec372aa9de27bb431844c5b51590db16871 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Wed, 25 May 2022 16:22:16 +0200 Subject: [PATCH 138/244] Inject permission utils --- .../java/im/vector/app/features/widgets/WidgetFragment.kt | 5 +++-- .../app/features/widgets/webview/WebviewPermissionUtils.kt | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt index ed2c69c908..897f6d6279 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt @@ -64,7 +64,9 @@ data class WidgetArgs( val urlParams: Map = emptyMap() ) : Parcelable -class WidgetFragment @Inject constructor() : +class WidgetFragment @Inject constructor( + private val permissionUtils: WebviewPermissionUtils +) : VectorBaseFragment(), WebViewEventListener, WebChromeEventListener, @@ -72,7 +74,6 @@ class WidgetFragment @Inject constructor() : private val fragmentArgs: WidgetArgs by args() private val viewModel: WidgetViewModel by activityViewModel() - private val permissionUtils = WebviewPermissionUtils() override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentRoomWidgetBinding { return FragmentRoomWidgetBinding.inflate(inflater, container, false) diff --git a/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt b/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt index 3a39153581..2bf12dff43 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt @@ -26,8 +26,9 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.utils.checkPermissions import java.lang.NullPointerException +import javax.inject.Inject -class WebviewPermissionUtils { +class WebviewPermissionUtils @Inject constructor() { private var permissionRequest: PermissionRequest? = null private var selectedPermissions = listOf() From 096db6c35d78eb58727fd02b0df9c83373a97e34 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 25 May 2022 17:34:00 +0100 Subject: [PATCH 139/244] giving arugment a proper name --- .../app/features/onboarding/OnboardingViewModel.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 5af4fa138b..bf79873909 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -638,18 +638,18 @@ class OnboardingViewModel @AssistedInject constructor( } } - private fun onAuthenticationStartError(it: Throwable, trigger: OnboardingAction.HomeServerChange) { + private fun onAuthenticationStartError(error: Throwable, trigger: OnboardingAction.HomeServerChange) { when { - it.isHomeserverUnavailable() && applicationContext.inferNoConnectivity(buildMeta) -> _viewEvents.post( - OnboardingViewEvents.Failure(it) + error.isHomeserverUnavailable() && applicationContext.inferNoConnectivity(buildMeta) -> _viewEvents.post( + OnboardingViewEvents.Failure(error) ) - deeplinkUrlIsUnavailable(it, trigger) -> _viewEvents.post( + deeplinkUrlIsUnavailable(error, trigger) -> _viewEvents.post( OnboardingViewEvents.DeeplinkAuthenticationFailure( retryAction = (trigger as OnboardingAction.HomeServerChange.SelectHomeServer).resetToDefaultUrl() ) ) - else -> _viewEvents.post( - OnboardingViewEvents.Failure(it) + else -> _viewEvents.post( + OnboardingViewEvents.Failure(error) ) } } From e18402f834b25ca30a3b941d293ea4a26654929c Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 13 May 2022 16:12:06 +0200 Subject: [PATCH 140/244] Improve test stability --- .../android/sdk/common/CommonTestHelper.kt | 30 ++++++++++- .../android/sdk/common/CryptoTestHelper.kt | 2 +- .../sdk/internal/crypto/PreShareKeysTest.kt | 11 ++-- .../sdk/internal/crypto/UnwedgingTest.kt | 10 ++-- .../crypto/crosssigning/XSigningTest.kt | 21 +++----- .../crypto/encryption/EncryptionTest.kt | 50 +++++++++---------- 6 files changed, 67 insertions(+), 57 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt index 96ea99d92f..c36e72db53 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt @@ -50,6 +50,16 @@ import java.util.UUID import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit +internal fun withTestHelpers(context: Context, block: (CryptoTestHelper) -> Unit) { + val testHelper = CommonTestHelper(context) + val cryptoTestHelper = CryptoTestHelper(testHelper) + return try { + block(cryptoTestHelper) + } finally { + testHelper.cleanUpOpenedSessions() + } +} + /** * This class exposes methods to be used in common cases * Registration, login, Sync, Sending messages... @@ -60,6 +70,8 @@ class CommonTestHelper(context: Context) { private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) private var accountNumber = 0 + private val trackedSessions = mutableListOf() + fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor init { @@ -84,6 +96,15 @@ class CommonTestHelper(context: Context) { return logIntoAccount(userId, TestConstants.PASSWORD, testParams) } + fun cleanUpOpenedSessions() { + trackedSessions.forEach { + runBlockingTest { + it.signOutService().signOut(true) + } + } + trackedSessions.clear() + } + /** * Create a homeserver configuration, with Http connection allowed for test */ @@ -245,7 +266,9 @@ class CommonTestHelper(context: Context) { testParams ) assertNotNull(session) - return session + return session.also { + trackedSessions.add(session) + } } /** @@ -261,7 +284,9 @@ class CommonTestHelper(context: Context) { testParams: SessionTestParams): Session { val session = logAccountAndSync(userId, password, testParams) assertNotNull(session) - return session + return session.also { + trackedSessions.add(session) + } } /** @@ -436,6 +461,7 @@ class CommonTestHelper(context: Context) { fun Iterable.signOutAndClose() = forEach { signOutAndClose(it) } fun signOutAndClose(session: Session) { + trackedSessions.remove(session) runBlockingTest(timeout = 60_000) { session.signOutService().signOut(true) } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt index 348841313b..e9afbb984a 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt @@ -66,7 +66,7 @@ import java.util.UUID import kotlin.coroutines.Continuation import kotlin.coroutines.resume -class CryptoTestHelper(private val testHelper: CommonTestHelper) { +class CryptoTestHelper(val testHelper: CommonTestHelper) { private val messagesFromAlice: List = listOf("0 - Hello I'm Alice!", "4 - Go!") private val messagesFromBob: List = listOf("1 - Hello I'm Bob!", "2 - Isn't life grand?", "3 - Let's go to the opera.") diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt index 93aa78a305..01e865f15e 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt @@ -30,18 +30,15 @@ import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventCon import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.getTimelineEvent -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.withTestHelpers @RunWith(AndroidJUnit4::class) @FixMethodOrder(MethodSorters.JVM) class PreShareKeysTest : InstrumentedTest { - private val testHelper = CommonTestHelper(context()) - private val cryptoTestHelper = CryptoTestHelper(testHelper) - @Test - fun ensure_outbound_session_happy_path() { + fun ensure_outbound_session_happy_path() = withTestHelpers(context()) { cryptoTestHelper -> + val testHelper = cryptoTestHelper.testHelper val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val e2eRoomID = testData.roomId val aliceSession = testData.firstSession @@ -94,7 +91,5 @@ class PreShareKeysTest : InstrumentedTest { bobSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEvent.eventId)?.root?.getClearType() == EventType.MESSAGE } } - - testData.cleanUp(testHelper) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt index 0f3a4b4181..703c9d410f 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt @@ -38,9 +38,8 @@ import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.TestConstants +import org.matrix.android.sdk.common.withTestHelpers import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm import org.matrix.android.sdk.internal.crypto.store.db.serializeForRealm @@ -63,8 +62,6 @@ import kotlin.coroutines.resume class UnwedgingTest : InstrumentedTest { private lateinit var messagesReceivedByBob: List - private val testHelper = CommonTestHelper(context()) - private val cryptoTestHelper = CryptoTestHelper(testHelper) @Before fun init() { @@ -85,7 +82,8 @@ class UnwedgingTest : InstrumentedTest { * -> This is automatically fixed after SDKs restarted the olm session */ @Test - fun testUnwedging() { + fun testUnwedging() = withTestHelpers(context()) { cryptoTestHelper -> + val testHelper = cryptoTestHelper.testHelper val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession @@ -240,8 +238,6 @@ class UnwedgingTest : InstrumentedTest { } bobTimeline.dispose() - - cryptoTestData.cleanUp(testHelper) } private fun createEventListener(latch: CountDownLatch, expectedNumberOfMessages: Int): Timeline.Listener { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt index abcf1714b8..f48adb03cd 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt @@ -37,10 +37,9 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.isCrossSignedVerif import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants +import org.matrix.android.sdk.common.withTestHelpers import kotlin.coroutines.Continuation import kotlin.coroutines.resume @@ -49,11 +48,9 @@ import kotlin.coroutines.resume @LargeTest class XSigningTest : InstrumentedTest { - private val testHelper = CommonTestHelper(context()) - private val cryptoTestHelper = CryptoTestHelper(testHelper) - @Test - fun test_InitializeAndStoreKeys() { + fun test_InitializeAndStoreKeys() = withTestHelpers(context()) { cryptoTestHelper -> + val testHelper = cryptoTestHelper.testHelper val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) testHelper.doSync { @@ -87,7 +84,8 @@ class XSigningTest : InstrumentedTest { } @Test - fun test_CrossSigningCheckBobSeesTheKeys() { + fun test_CrossSigningCheckBobSeesTheKeys() = withTestHelpers(context()) { cryptoTestHelper -> + val testHelper = cryptoTestHelper.testHelper val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession @@ -137,12 +135,11 @@ class XSigningTest : InstrumentedTest { ) assertFalse("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV.isTrusted()) - - cryptoTestData.cleanUp(testHelper) } @Test - fun test_CrossSigningTestAliceTrustBobNewDevice() { + fun test_CrossSigningTestAliceTrustBobNewDevice() = withTestHelpers(context()) { cryptoTestHelper -> + val testHelper = cryptoTestHelper.testHelper val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession @@ -216,9 +213,5 @@ class XSigningTest : InstrumentedTest { val result = aliceSession.cryptoService().crossSigningService().checkDeviceTrust(bobUserId, bobSecondDeviceId, null) assertTrue("Bob second device should be trusted from alice POV", result.isCrossSignedVerified()) - - testHelper.signOutAndClose(aliceSession) - testHelper.signOutAndClose(bobSession) - testHelper.signOutAndClose(bobSession2) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt index 85b6c21df3..f65b08ec4e 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt @@ -34,43 +34,44 @@ import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings -import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.withTestHelpers import java.util.concurrent.CountDownLatch @RunWith(AndroidJUnit4::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class EncryptionTest : InstrumentedTest { - private val testHelper = CommonTestHelper(context()) - private val cryptoTestHelper = CryptoTestHelper(testHelper) - @Test fun test_EncryptionEvent() { - performTest(roomShouldBeEncrypted = false) { room -> - // Send an encryption Event as an Event (and not as a state event) - room.sendService().sendEvent( - eventType = EventType.STATE_ROOM_ENCRYPTION, - content = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent() - ) - } - } - - @Test - fun test_EncryptionStateEvent() { - performTest(roomShouldBeEncrypted = true) { room -> - runBlocking { - // Send an encryption Event as a State Event - room.stateService().sendStateEvent( + withTestHelpers(context()) { cryptoTestHelper -> + performTest(cryptoTestHelper, roomShouldBeEncrypted = false) { room -> + // Send an encryption Event as an Event (and not as a state event) + room.sendService().sendEvent( eventType = EventType.STATE_ROOM_ENCRYPTION, - stateKey = "", - body = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent() + content = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent() ) } } } - private fun performTest(roomShouldBeEncrypted: Boolean, action: (Room) -> Unit) { + @Test + fun test_EncryptionStateEvent() { + withTestHelpers(context()) { cryptoTestHelper -> + performTest(cryptoTestHelper, roomShouldBeEncrypted = true) { room -> + runBlocking { + // Send an encryption Event as a State Event + room.stateService().sendStateEvent( + eventType = EventType.STATE_ROOM_ENCRYPTION, + stateKey = "", + body = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent() + ) + } + } + } + } + + private fun performTest(cryptoTestHelper: CryptoTestHelper, roomShouldBeEncrypted: Boolean, action: (Room) -> Unit) { val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(encryptedRoom = false) val aliceSession = cryptoTestData.firstSession @@ -103,12 +104,11 @@ class EncryptionTest : InstrumentedTest { timeline.addListener(timelineListener) action.invoke(room) - testHelper.await(latch) + cryptoTestHelper.testHelper.await(latch) timeline.dispose() - testHelper.waitWithLatch { + cryptoTestHelper.testHelper.waitWithLatch { room.roomCryptoService().isEncrypted() shouldBe roomShouldBeEncrypted it.countDown() } - cryptoTestData.cleanUp(testHelper) } } From 29ff4d1e8496740b519128f7baba6412bceebdf7 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 13 May 2022 17:32:18 +0200 Subject: [PATCH 141/244] use withTestHelpers in sanity tests --- .../sdk/internal/crypto/E2eeSanityTests.kt | 44 +++++-------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt index 74c218af58..3373dab398 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt @@ -84,9 +84,8 @@ class E2eeSanityTests : InstrumentedTest { * Alice sends a new message, then check that the new one can be decrypted */ @Test - fun testSendingE2EEMessages() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun testSendingE2EEMessages() = withTestHelpers(context()) { cryptoTestHelper -> + val testHelper = cryptoTestHelper.testHelper val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = cryptoTestData.firstSession @@ -200,13 +199,6 @@ class E2eeSanityTests : InstrumentedTest { } } } - - otherAccounts.forEach { - testHelper.signOutAndClose(it) - } - newAccount.forEach { testHelper.signOutAndClose(it) } - - cryptoTestData.cleanUp(testHelper) } @Test @@ -232,9 +224,8 @@ class E2eeSanityTests : InstrumentedTest { * 9. Check that new session can decrypt */ @Test - fun testBasicBackupImport() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun testBasicBackupImport() = withTestHelpers(context()) { cryptoTestHelper -> + val testHelper = cryptoTestHelper.testHelper val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = cryptoTestData.firstSession @@ -346,8 +337,6 @@ class E2eeSanityTests : InstrumentedTest { // ensure bob can now decrypt cryptoTestHelper.ensureCanDecrypt(sentEventIds, newBobSession, e2eRoomID, messagesText) - - testHelper.signOutAndClose(newBobSession) } /** @@ -355,9 +344,8 @@ class E2eeSanityTests : InstrumentedTest { * get them from an older one. */ @Test - fun testSimpleGossip() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun testSimpleGossip() = withTestHelpers(context()) { cryptoTestHelper -> + val testHelper = cryptoTestHelper.testHelper val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = cryptoTestData.firstSession @@ -451,18 +439,14 @@ class E2eeSanityTests : InstrumentedTest { } cryptoTestHelper.ensureCanDecrypt(sentEventIds, newBobSession, e2eRoomID, messagesText) - - cryptoTestData.cleanUp(testHelper) - testHelper.signOutAndClose(newBobSession) } /** * Test that if a better key is forwarded (lower index, it is then used) */ @Test - fun testForwardBetterKey() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun testForwardBetterKey() = withTestHelpers(context()) { cryptoTestHelper -> + val testHelper = cryptoTestHelper.testHelper val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = cryptoTestData.firstSession @@ -578,10 +562,6 @@ class E2eeSanityTests : InstrumentedTest { canDecryptFirst && canDecryptSecond } } - - testHelper.signOutAndClose(aliceSession) - testHelper.signOutAndClose(bobSessionWithBetterKey) - testHelper.signOutAndClose(newBobSession) } private fun sendMessageInRoom(testHelper: CommonTestHelper, aliceRoomPOV: Room, text: String): String? { @@ -612,9 +592,8 @@ class E2eeSanityTests : InstrumentedTest { * Test that if a better key is forwared (lower index, it is then used) */ @Test - fun testSelfInteractiveVerificationAndGossip() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun testASelfInteractiveVerificationAndGossip() = withTestHelpers(context()) { cryptoTestHelper -> + val testHelper = cryptoTestHelper.testHelper val aliceSession = testHelper.createAccount("alice", SessionTestParams(true)) cryptoTestHelper.bootstrapSecurity(aliceSession) @@ -753,9 +732,6 @@ class E2eeSanityTests : InstrumentedTest { aliceSession.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()!!.version, aliceNewSession.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()!!.version ) - - testHelper.signOutAndClose(aliceSession) - testHelper.signOutAndClose(aliceNewSession) } private fun ensureMembersHaveJoined(testHelper: CommonTestHelper, aliceSession: Session, otherAccounts: List, e2eRoomID: String) { From 3332d827f0c04591a763bdfa08ee3ed774c241e8 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 20 May 2022 16:41:51 +0200 Subject: [PATCH 142/244] rename testHelpers and make constructor private --- .../sdk/account/AccountCreationTest.kt | 26 ++-- .../android/sdk/account/ChangePasswordTest.kt | 11 +- .../sdk/account/DeactivateAccountTest.kt | 6 +- .../sdk/api/network/ApiInterceptorTest.kt | 6 +- .../android/sdk/common/CommonTestHelper.kt | 33 +++-- .../sdk/internal/crypto/E2eeSanityTests.kt | 22 ++- .../sdk/internal/crypto/PreShareKeysTest.kt | 5 +- .../sdk/internal/crypto/UnwedgingTest.kt | 5 +- .../crypto/crosssigning/XSigningTest.kt | 12 +- .../crypto/encryption/EncryptionTest.kt | 17 +-- .../crypto/gossiping/KeyShareTests.kt | 26 +--- .../crypto/gossiping/WithHeldTests.kt | 24 +--- .../crypto/keysbackup/KeysBackupTest.kt | 112 ++++------------ .../sdk/internal/crypto/ssss/QuadSTests.kt | 51 +++---- .../internal/crypto/verification/SASTest.kt | 54 ++------ .../verification/qrcode/VerificationTest.kt | 13 +- .../room/threads/ThreadMessagingTest.kt | 19 +-- .../room/timeline/PollAggregationTest.kt | 8 +- .../timeline/TimelineForwardPaginationTest.kt | 9 +- .../TimelinePreviousLastForwardTest.kt | 7 +- .../TimelineSimpleBackPaginationTest.kt | 8 +- .../timeline/TimelineWithManyMembersTest.kt | 8 +- .../sdk/session/search/SearchMessagesTest.kt | 9 +- .../sdk/session/space/SpaceCreationTest.kt | 16 +-- .../sdk/session/space/SpaceHierarchyTest.kt | 126 ++++++++---------- 25 files changed, 208 insertions(+), 425 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/AccountCreationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/AccountCreationTest.kt index 486bc02769..7e4fc4768f 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/AccountCreationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/AccountCreationTest.kt @@ -24,8 +24,8 @@ import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants @@ -34,32 +34,22 @@ import org.matrix.android.sdk.common.TestConstants @LargeTest class AccountCreationTest : InstrumentedTest { - private val commonTestHelper = CommonTestHelper(context()) - private val cryptoTestHelper = CryptoTestHelper(commonTestHelper) - @Test - fun createAccountTest() { - val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true)) - - commonTestHelper.signOutAndClose(session) + fun createAccountTest() = runSessionTest(context()) { commonTestHelper -> + commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true)) } @Test @Ignore("This test will be ignored until it is fixed") - fun createAccountAndLoginAgainTest() { + fun createAccountAndLoginAgainTest() = runSessionTest(context()) { commonTestHelper -> val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true)) // Log again to the same account - val session2 = commonTestHelper.logIntoAccount(session.myUserId, SessionTestParams(withInitialSync = true)) - - commonTestHelper.signOutAndClose(session) - commonTestHelper.signOutAndClose(session2) + commonTestHelper.logIntoAccount(session.myUserId, SessionTestParams(withInitialSync = true)) } @Test - fun simpleE2eTest() { - val res = cryptoTestHelper.doE2ETestWithAliceInARoom() - - res.cleanUp(commonTestHelper) + fun simpleE2eTest() = runCryptoTest(context()) { cryptoTestHelper, _ -> + cryptoTestHelper.doE2ETestWithAliceInARoom() } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt index 6d740c5a34..260e8dbe05 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt @@ -25,7 +25,7 @@ import org.junit.runners.JUnit4 import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.failure.isInvalidPassword -import org.matrix.android.sdk.common.CommonTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants @@ -34,14 +34,12 @@ import org.matrix.android.sdk.common.TestConstants @Ignore("This test will be ignored until it is fixed") class ChangePasswordTest : InstrumentedTest { - private val commonTestHelper = CommonTestHelper(context()) - companion object { private const val NEW_PASSWORD = "this is a new password" } @Test - fun changePasswordTest() { + fun changePasswordTest() = runSessionTest(context()) { commonTestHelper -> val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false)) // Change password @@ -54,9 +52,6 @@ class ChangePasswordTest : InstrumentedTest { throwable.isInvalidPassword().shouldBeTrue() // Try to login with the new password, should work - val session2 = commonTestHelper.logIntoAccount(session.myUserId, NEW_PASSWORD, SessionTestParams(withInitialSync = false)) - - commonTestHelper.signOutAndClose(session) - commonTestHelper.signOutAndClose(session2) + commonTestHelper.logIntoAccount(session.myUserId, NEW_PASSWORD, SessionTestParams(withInitialSync = false)) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt index d2dfe4d945..3575e19c2b 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt @@ -29,7 +29,7 @@ import org.matrix.android.sdk.api.auth.UserPasswordAuth import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError -import org.matrix.android.sdk.common.CommonTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants import kotlin.coroutines.Continuation @@ -39,10 +39,8 @@ import kotlin.coroutines.resume @FixMethodOrder(MethodSorters.JVM) class DeactivateAccountTest : InstrumentedTest { - private val commonTestHelper = CommonTestHelper(context()) - @Test - fun deactivateAccountTest() { + fun deactivateAccountTest() = runSessionTest(context()) { commonTestHelper -> val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true)) // Deactivate the account diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/network/ApiInterceptorTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/network/ApiInterceptorTest.kt index 9371154aaf..8dbff82015 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/network/ApiInterceptorTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/network/ApiInterceptorTest.kt @@ -23,7 +23,7 @@ import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest -import org.matrix.android.sdk.common.CommonTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants import timber.log.Timber @@ -32,10 +32,8 @@ import timber.log.Timber @FixMethodOrder(MethodSorters.JVM) class ApiInterceptorTest : InstrumentedTest { - private val commonTestHelper = CommonTestHelper(context()) - @Test - fun apiInterceptorTest() { + fun apiInterceptorTest() = runSessionTest(context()) { commonTestHelper -> val responses = mutableListOf() val listener = object : ApiInterceptorListener { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt index c36e72db53..1c17da83b6 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt @@ -50,21 +50,32 @@ import java.util.UUID import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit -internal fun withTestHelpers(context: Context, block: (CryptoTestHelper) -> Unit) { - val testHelper = CommonTestHelper(context) - val cryptoTestHelper = CryptoTestHelper(testHelper) - return try { - block(cryptoTestHelper) - } finally { - testHelper.cleanUpOpenedSessions() - } -} - /** * This class exposes methods to be used in common cases * Registration, login, Sync, Sending messages... */ -class CommonTestHelper(context: Context) { +class CommonTestHelper private constructor(context: Context) { + + companion object { + internal fun runSessionTest(context: Context, block: (CommonTestHelper) -> Unit) { + val testHelper = CommonTestHelper(context) + return try { + block(testHelper) + } finally { + testHelper.cleanUpOpenedSessions() + } + } + + internal fun runCryptoTest(context: Context, block: (CryptoTestHelper, CommonTestHelper) -> Unit) { + val testHelper = CommonTestHelper(context) + val cryptoTestHelper = CryptoTestHelper(testHelper) + return try { + block(cryptoTestHelper, testHelper) + } finally { + testHelper.cleanUpOpenedSessions() + } + } + } internal val matrix: TestMatrix private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt index 3373dab398..010383dab8 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt @@ -58,7 +58,8 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest import org.matrix.android.sdk.common.RetryTestRule import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants @@ -84,8 +85,7 @@ class E2eeSanityTests : InstrumentedTest { * Alice sends a new message, then check that the new one can be decrypted */ @Test - fun testSendingE2EEMessages() = withTestHelpers(context()) { cryptoTestHelper -> - val testHelper = cryptoTestHelper.testHelper + fun testSendingE2EEMessages() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = cryptoTestData.firstSession @@ -202,11 +202,9 @@ class E2eeSanityTests : InstrumentedTest { } @Test - fun testKeyGossipingIsEnabledByDefault() { - val testHelper = CommonTestHelper(context()) + fun testKeyGossipingIsEnabledByDefault() = runSessionTest(context()) { testHelper -> val session = testHelper.createAccount("alice", SessionTestParams(true)) Assert.assertTrue("Key gossiping should be enabled by default", session.cryptoService().isKeyGossipingEnabled()) - testHelper.signOutAndClose(session) } /** @@ -224,8 +222,7 @@ class E2eeSanityTests : InstrumentedTest { * 9. Check that new session can decrypt */ @Test - fun testBasicBackupImport() = withTestHelpers(context()) { cryptoTestHelper -> - val testHelper = cryptoTestHelper.testHelper + fun testBasicBackupImport() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = cryptoTestData.firstSession @@ -344,8 +341,7 @@ class E2eeSanityTests : InstrumentedTest { * get them from an older one. */ @Test - fun testSimpleGossip() = withTestHelpers(context()) { cryptoTestHelper -> - val testHelper = cryptoTestHelper.testHelper + fun testSimpleGossip() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = cryptoTestData.firstSession @@ -445,8 +441,7 @@ class E2eeSanityTests : InstrumentedTest { * Test that if a better key is forwarded (lower index, it is then used) */ @Test - fun testForwardBetterKey() = withTestHelpers(context()) { cryptoTestHelper -> - val testHelper = cryptoTestHelper.testHelper + fun testForwardBetterKey() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = cryptoTestData.firstSession @@ -592,8 +587,7 @@ class E2eeSanityTests : InstrumentedTest { * Test that if a better key is forwared (lower index, it is then used) */ @Test - fun testASelfInteractiveVerificationAndGossip() = withTestHelpers(context()) { cryptoTestHelper -> - val testHelper = cryptoTestHelper.testHelper + fun testASelfInteractiveVerificationAndGossip() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val aliceSession = testHelper.createAccount("alice", SessionTestParams(true)) cryptoTestHelper.bootstrapSecurity(aliceSession) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt index 01e865f15e..e37ae5be86 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt @@ -30,15 +30,14 @@ import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventCon import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.getTimelineEvent -import org.matrix.android.sdk.common.withTestHelpers +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest @RunWith(AndroidJUnit4::class) @FixMethodOrder(MethodSorters.JVM) class PreShareKeysTest : InstrumentedTest { @Test - fun ensure_outbound_session_happy_path() = withTestHelpers(context()) { cryptoTestHelper -> - val testHelper = cryptoTestHelper.testHelper + fun ensure_outbound_session_happy_path() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val e2eRoomID = testData.roomId val aliceSession = testData.firstSession diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt index 703c9d410f..5fe7376184 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt @@ -38,8 +38,8 @@ import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest import org.matrix.android.sdk.common.TestConstants -import org.matrix.android.sdk.common.withTestHelpers import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm import org.matrix.android.sdk.internal.crypto.store.db.serializeForRealm @@ -82,8 +82,7 @@ class UnwedgingTest : InstrumentedTest { * -> This is automatically fixed after SDKs restarted the olm session */ @Test - fun testUnwedging() = withTestHelpers(context()) { cryptoTestHelper -> - val testHelper = cryptoTestHelper.testHelper + fun testUnwedging() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt index f48adb03cd..05790bfb7d 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt @@ -37,9 +37,10 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.isCrossSignedVerif import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants -import org.matrix.android.sdk.common.withTestHelpers import kotlin.coroutines.Continuation import kotlin.coroutines.resume @@ -49,8 +50,7 @@ import kotlin.coroutines.resume class XSigningTest : InstrumentedTest { @Test - fun test_InitializeAndStoreKeys() = withTestHelpers(context()) { cryptoTestHelper -> - val testHelper = cryptoTestHelper.testHelper + fun test_InitializeAndStoreKeys() = runSessionTest(context()) { testHelper -> val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) testHelper.doSync { @@ -84,8 +84,7 @@ class XSigningTest : InstrumentedTest { } @Test - fun test_CrossSigningCheckBobSeesTheKeys() = withTestHelpers(context()) { cryptoTestHelper -> - val testHelper = cryptoTestHelper.testHelper + fun test_CrossSigningCheckBobSeesTheKeys() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession @@ -138,8 +137,7 @@ class XSigningTest : InstrumentedTest { } @Test - fun test_CrossSigningTestAliceTrustBobNewDevice() = withTestHelpers(context()) { cryptoTestHelper -> - val testHelper = cryptoTestHelper.testHelper + fun test_CrossSigningTestAliceTrustBobNewDevice() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt index f65b08ec4e..5f26fda946 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt @@ -34,8 +34,9 @@ import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings +import org.matrix.android.sdk.common.CommonTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest import org.matrix.android.sdk.common.CryptoTestHelper -import org.matrix.android.sdk.common.withTestHelpers import java.util.concurrent.CountDownLatch @RunWith(AndroidJUnit4::class) @@ -44,8 +45,8 @@ class EncryptionTest : InstrumentedTest { @Test fun test_EncryptionEvent() { - withTestHelpers(context()) { cryptoTestHelper -> - performTest(cryptoTestHelper, roomShouldBeEncrypted = false) { room -> + runCryptoTest(context()) { cryptoTestHelper, testHelper -> + performTest(cryptoTestHelper, testHelper, roomShouldBeEncrypted = false) { room -> // Send an encryption Event as an Event (and not as a state event) room.sendService().sendEvent( eventType = EventType.STATE_ROOM_ENCRYPTION, @@ -57,8 +58,8 @@ class EncryptionTest : InstrumentedTest { @Test fun test_EncryptionStateEvent() { - withTestHelpers(context()) { cryptoTestHelper -> - performTest(cryptoTestHelper, roomShouldBeEncrypted = true) { room -> + runCryptoTest(context()) { cryptoTestHelper, testHelper -> + performTest(cryptoTestHelper, testHelper, roomShouldBeEncrypted = true) { room -> runBlocking { // Send an encryption Event as a State Event room.stateService().sendStateEvent( @@ -71,7 +72,7 @@ class EncryptionTest : InstrumentedTest { } } - private fun performTest(cryptoTestHelper: CryptoTestHelper, roomShouldBeEncrypted: Boolean, action: (Room) -> Unit) { + private fun performTest(cryptoTestHelper: CryptoTestHelper, testHelper: CommonTestHelper, roomShouldBeEncrypted: Boolean, action: (Room) -> Unit) { val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(encryptedRoom = false) val aliceSession = cryptoTestData.firstSession @@ -104,9 +105,9 @@ class EncryptionTest : InstrumentedTest { timeline.addListener(timelineListener) action.invoke(room) - cryptoTestHelper.testHelper.await(latch) + testHelper.await(latch) timeline.dispose() - cryptoTestHelper.testHelper.waitWithLatch { + testHelper.waitWithLatch { room.roomCryptoService().isEncrypted() shouldBe roomShouldBeEncrypted it.countDown() } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt index 895f95aeac..b16e4b82eb 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt @@ -41,8 +41,7 @@ import org.matrix.android.sdk.api.session.room.getTimelineEvent import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest import org.matrix.android.sdk.common.RetryTestRule import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants @@ -56,9 +55,7 @@ class KeyShareTests : InstrumentedTest { @get:Rule val rule = RetryTestRule(3) @Test - fun test_DoNotSelfShareIfNotTrusted() { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + fun test_DoNotSelfShareIfNotTrusted() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val aliceSession = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) Log.v("TEST", "=======> AliceSession 1 is ${aliceSession.sessionParams.deviceId}") @@ -194,9 +191,7 @@ class KeyShareTests : InstrumentedTest { * if the key was originally shared with him */ @Test - fun test_reShareIfWasIntendedToBeShared() { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + fun test_reShareIfWasIntendedToBeShared() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = testData.firstSession @@ -227,9 +222,7 @@ class KeyShareTests : InstrumentedTest { * if the key was originally shared with him */ @Test - fun test_reShareToUnverifiedIfWasIntendedToBeShared() { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + fun test_reShareToUnverifiedIfWasIntendedToBeShared() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val testData = cryptoTestHelper.doE2ETestWithAliceInARoom(true) val aliceSession = testData.firstSession @@ -266,9 +259,7 @@ class KeyShareTests : InstrumentedTest { * Tests that keys reshared with own verified session are done from the earliest known index */ @Test - fun test_reShareFromTheEarliestKnownIndexWithOwnVerifiedSession() { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + fun test_reShareFromTheEarliestKnownIndexWithOwnVerifiedSession() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = testData.firstSession @@ -388,10 +379,7 @@ class KeyShareTests : InstrumentedTest { * Tests that we don't cancel a request to early on first forward if the index is not good enough */ @Test - fun test_dontCancelToEarly() { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) - + fun test_dontCancelToEarly() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = testData.firstSession val bobSession = testData.secondSession!! @@ -442,7 +430,7 @@ class KeyShareTests : InstrumentedTest { // Should get a reply from bob and not from alice commonTestHelper.waitWithLatch { latch -> commonTestHelper.retryPeriodicallyWithLatch(latch) { - // Log.d("#TEST", "outgoing key requests :${aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().joinToString { it.sessionId ?: "?" }}") + // Log.d("#TEST", "outgoing key requests :${aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().joinToString { it.sessionId ?: "?" }}") val outgoing = aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().firstOrNull { it.sessionId == sentEventMegolmSession } val bobReply = outgoing?.results?.firstOrNull { it.userId == bobSession.myUserId } val result = bobReply?.result diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt index 13133b726c..0aac4297e4 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt @@ -36,8 +36,7 @@ import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.getTimelineEvent -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest import org.matrix.android.sdk.common.MockOkHttpInterceptor import org.matrix.android.sdk.common.RetryTestRule import org.matrix.android.sdk.common.SessionTestParams @@ -52,9 +51,7 @@ class WithHeldTests : InstrumentedTest { @get:Rule val rule = RetryTestRule(3) @Test - fun test_WithHeldUnverifiedReason() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun test_WithHeldUnverifiedReason() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> // ============================= // ARRANGE @@ -153,16 +150,10 @@ class WithHeldTests : InstrumentedTest { bobUnverifiedSession.cryptoService().decryptEvent(eventBobPOV.root, "") } } - - testHelper.signOutAndClose(aliceSession) - testHelper.signOutAndClose(bobSession) - testHelper.signOutAndClose(bobUnverifiedSession) } @Test - fun test_WithHeldNoOlm() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun test_WithHeldNoOlm() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = testData.firstSession @@ -239,14 +230,10 @@ class WithHeldTests : InstrumentedTest { Assert.assertEquals("Alice should have marked bob's device for this session", 1, chainIndex2) aliceInterceptor.clearRules() - testData.cleanUp(testHelper) - testHelper.signOutAndClose(bobSecondSession) } @Test - fun test_WithHeldKeyRequest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun test_WithHeldKeyRequest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = testData.firstSession @@ -293,8 +280,5 @@ class WithHeldTests : InstrumentedTest { wc?.code == WithHeldCode.UNAUTHORISED } } - - testHelper.signOutAndClose(aliceSession) - testHelper.signOutAndClose(bobSecondSession) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt index d5fd299f1f..6b59b976ba 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt @@ -44,8 +44,8 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreation import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult import org.matrix.android.sdk.api.session.getRoom -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest import org.matrix.android.sdk.common.RetryTestRule import org.matrix.android.sdk.common.TestConstants import org.matrix.android.sdk.common.TestMatrixCallback @@ -65,9 +65,7 @@ class KeysBackupTest : InstrumentedTest { * - Reset keys backup markers */ @Test - fun roomKeysTest_testBackupStore_ok() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun roomKeysTest_testBackupStore_ok() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages() @@ -106,8 +104,7 @@ class KeysBackupTest : InstrumentedTest { * Check that prepareKeysBackupVersionWithPassword returns valid data */ @Test - fun prepareKeysBackupVersionTest() { - val testHelper = CommonTestHelper(context()) + fun prepareKeysBackupVersionTest() = runSessionTest(context()) { testHelper -> val bobSession = testHelper.createAccount(TestConstants.USER_BOB, KeysBackupTestConstants.defaultSessionParams) @@ -129,16 +126,13 @@ class KeysBackupTest : InstrumentedTest { assertNotNull(megolmBackupCreationInfo.recoveryKey) stateObserver.stopAndCheckStates(null) - testHelper.signOutAndClose(bobSession) } /** * Test creating a keys backup version and check that createKeysBackupVersion() returns valid data */ @Test - fun createKeysBackupVersionTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun createKeysBackupVersionTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val bobSession = testHelper.createAccount(TestConstants.USER_BOB, KeysBackupTestConstants.defaultSessionParams) cryptoTestHelper.initializeCrossSigning(bobSession) @@ -197,7 +191,6 @@ class KeysBackupTest : InstrumentedTest { } stateObserver.stopAndCheckStates(null) - testHelper.signOutAndClose(bobSession) } /** @@ -205,9 +198,7 @@ class KeysBackupTest : InstrumentedTest { * - Check the backup completes */ @Test - fun backupAfterCreateKeysBackupVersionTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun backupAfterCreateKeysBackupVersionTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages() @@ -242,16 +233,13 @@ class KeysBackupTest : InstrumentedTest { KeysBackupState.ReadyToBackUp ) ) - cryptoTestData.cleanUp(testHelper) } /** * Check that backupAllGroupSessions() returns valid data */ @Test - fun backupAllGroupSessionsTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun backupAllGroupSessionsTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages() @@ -285,7 +273,6 @@ class KeysBackupTest : InstrumentedTest { assertEquals("All keys must have been marked as backed up", nbOfKeys, backedUpKeys) stateObserver.stopAndCheckStates(null) - cryptoTestData.cleanUp(testHelper) } /** @@ -297,9 +284,7 @@ class KeysBackupTest : InstrumentedTest { * - Compare the decrypted megolm key with the original one */ @Test - fun testEncryptAndDecryptKeysBackupData() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun testEncryptAndDecryptKeysBackupData() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages() @@ -334,7 +319,6 @@ class KeysBackupTest : InstrumentedTest { keysBackupTestHelper.assertKeysEquals(session.exportKeys(), sessionData) stateObserver.stopAndCheckStates(null) - cryptoTestData.cleanUp(testHelper) } /** @@ -344,9 +328,7 @@ class KeysBackupTest : InstrumentedTest { * - Restore must be successful */ @Test - fun restoreKeysBackupTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun restoreKeysBackupTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null) @@ -432,9 +414,7 @@ class KeysBackupTest : InstrumentedTest { * - It must be trusted and must have with 2 signatures now */ @Test - fun trustKeyBackupVersionTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun trustKeyBackupVersionTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) // - Do an e2e backup to the homeserver with a recovery key @@ -481,7 +461,6 @@ class KeysBackupTest : InstrumentedTest { assertEquals(2, keysBackupVersionTrust.signatures.size) stateObserver.stopAndCheckStates(null) - testData.cleanUp(testHelper) } /** @@ -495,9 +474,7 @@ class KeysBackupTest : InstrumentedTest { * - It must be trusted and must have with 2 signatures now */ @Test - fun trustKeyBackupVersionWithRecoveryKeyTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun trustKeyBackupVersionWithRecoveryKeyTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) // - Do an e2e backup to the homeserver with a recovery key @@ -544,7 +521,6 @@ class KeysBackupTest : InstrumentedTest { assertEquals(2, keysBackupVersionTrust.signatures.size) stateObserver.stopAndCheckStates(null) - testData.cleanUp(testHelper) } /** @@ -556,9 +532,7 @@ class KeysBackupTest : InstrumentedTest { * - The backup must still be untrusted and disabled */ @Test - fun trustKeyBackupVersionWithWrongRecoveryKeyTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun trustKeyBackupVersionWithWrongRecoveryKeyTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) // - Do an e2e backup to the homeserver with a recovery key @@ -587,7 +561,6 @@ class KeysBackupTest : InstrumentedTest { assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state) stateObserver.stopAndCheckStates(null) - testData.cleanUp(testHelper) } /** @@ -601,9 +574,7 @@ class KeysBackupTest : InstrumentedTest { * - It must be trusted and must have with 2 signatures now */ @Test - fun trustKeyBackupVersionWithPasswordTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun trustKeyBackupVersionWithPasswordTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) val password = "Password" @@ -652,7 +623,6 @@ class KeysBackupTest : InstrumentedTest { assertEquals(2, keysBackupVersionTrust.signatures.size) stateObserver.stopAndCheckStates(null) - testData.cleanUp(testHelper) } /** @@ -664,9 +634,7 @@ class KeysBackupTest : InstrumentedTest { * - The backup must still be untrusted and disabled */ @Test - fun trustKeyBackupVersionWithWrongPasswordTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun trustKeyBackupVersionWithWrongPasswordTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) val password = "Password" @@ -698,7 +666,6 @@ class KeysBackupTest : InstrumentedTest { assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state) stateObserver.stopAndCheckStates(null) - testData.cleanUp(testHelper) } /** @@ -708,9 +675,7 @@ class KeysBackupTest : InstrumentedTest { * - It must fail */ @Test - fun restoreKeysBackupWithAWrongRecoveryKeyTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun restoreKeysBackupWithAWrongRecoveryKeyTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null) @@ -734,8 +699,6 @@ class KeysBackupTest : InstrumentedTest { // onSuccess may not have been called assertNull(importRoomKeysResult) - - testData.cleanUp(testHelper) } /** @@ -745,9 +708,7 @@ class KeysBackupTest : InstrumentedTest { * - Restore must be successful */ @Test - fun testBackupWithPassword() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun testBackupWithPassword() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) val password = "password" @@ -794,8 +755,6 @@ class KeysBackupTest : InstrumentedTest { assertEquals(100, (steps[104] as StepProgressListener.Step.ImportingKey).progress) keysBackupTestHelper.checkRestoreSuccess(testData, importRoomKeysResult.totalNumberOfKeys, importRoomKeysResult.successfullyNumberOfImportedKeys) - - testData.cleanUp(testHelper) } /** @@ -805,9 +764,7 @@ class KeysBackupTest : InstrumentedTest { * - It must fail */ @Test - fun restoreKeysBackupWithAWrongPasswordTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun restoreKeysBackupWithAWrongPasswordTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) val password = "password" @@ -834,8 +791,6 @@ class KeysBackupTest : InstrumentedTest { // onSuccess may not have been called assertNull(importRoomKeysResult) - - testData.cleanUp(testHelper) } /** @@ -845,9 +800,7 @@ class KeysBackupTest : InstrumentedTest { * - Restore must be successful */ @Test - fun testUseRecoveryKeyToRestoreAPasswordBasedKeysBackup() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun testUseRecoveryKeyToRestoreAPasswordBasedKeysBackup() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) val password = "password" @@ -867,8 +820,6 @@ class KeysBackupTest : InstrumentedTest { } keysBackupTestHelper.checkRestoreSuccess(testData, importRoomKeysResult.totalNumberOfKeys, importRoomKeysResult.successfullyNumberOfImportedKeys) - - testData.cleanUp(testHelper) } /** @@ -878,9 +829,7 @@ class KeysBackupTest : InstrumentedTest { * - It must fail */ @Test - fun testUsePasswordToRestoreARecoveryKeyBasedKeysBackup() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun testUsePasswordToRestoreARecoveryKeyBasedKeysBackup() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null) @@ -904,8 +853,6 @@ class KeysBackupTest : InstrumentedTest { // onSuccess may not have been called assertNull(importRoomKeysResult) - - testData.cleanUp(testHelper) } /** @@ -913,9 +860,7 @@ class KeysBackupTest : InstrumentedTest { * - Check the returned KeysVersionResult is trusted */ @Test - fun testIsKeysBackupTrusted() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun testIsKeysBackupTrusted() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) // - Create a backup version @@ -949,7 +894,6 @@ class KeysBackupTest : InstrumentedTest { assertEquals(signature.device!!.deviceId, cryptoTestData.firstSession.sessionParams.deviceId) stateObserver.stopAndCheckStates(null) - cryptoTestData.cleanUp(testHelper) } /** @@ -961,9 +905,7 @@ class KeysBackupTest : InstrumentedTest { * -> That must fail and her backup state must be WrongBackUpVersion */ @Test - fun testBackupWhenAnotherBackupWasCreated() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun testBackupWhenAnotherBackupWasCreated() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) // - Create a backup version @@ -1020,7 +962,6 @@ class KeysBackupTest : InstrumentedTest { assertFalse(keysBackup.isEnabled) stateObserver.stopAndCheckStates(null) - cryptoTestData.cleanUp(testHelper) } /** @@ -1036,9 +977,7 @@ class KeysBackupTest : InstrumentedTest { * -> It must success */ @Test - fun testBackupAfterVerifyingADevice() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun testBackupAfterVerifyingADevice() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) // - Create a backup version @@ -1129,8 +1068,6 @@ class KeysBackupTest : InstrumentedTest { stateObserver.stopAndCheckStates(null) stateObserver2.stopAndCheckStates(null) - testHelper.signOutAndClose(aliceSession2) - cryptoTestData.cleanUp(testHelper) } /** @@ -1138,9 +1075,7 @@ class KeysBackupTest : InstrumentedTest { * - Delete the backup */ @Test - fun deleteKeysBackupTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun deleteKeysBackupTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) // - Create a backup version @@ -1163,6 +1098,5 @@ class KeysBackupTest : InstrumentedTest { assertFalse(keysBackup.isEnabled) stateObserver.stopAndCheckStates(null) - cryptoTestData.cleanUp(testHelper) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt index c758050fc9..2f55c3d870 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt @@ -40,6 +40,7 @@ import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.toBase64NoPadding import org.matrix.android.sdk.common.CommonTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService @@ -55,8 +56,7 @@ class QuadSTests : InstrumentedTest { } @Test - fun test_Generate4SKey() { - val testHelper = CommonTestHelper(context()) + fun test_Generate4SKey() = runSessionTest(context()) { testHelper -> val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) @@ -108,12 +108,11 @@ class QuadSTests : InstrumentedTest { } @Test - fun test_StoreSecret() { - val testHelper = CommonTestHelper(context()) + fun test_StoreSecret() = runSessionTest(context()) { testHelper -> val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) val keyId = "My.Key" - val info = generatedSecret(aliceSession, keyId, true) + val info = generatedSecret(testHelper, aliceSession, keyId, true) val keySpec = RawBytesKeySpec.fromRecoveryKey(info.recoveryKey) @@ -127,7 +126,7 @@ class QuadSTests : InstrumentedTest { ) } - val secretAccountData = assertAccountData(aliceSession, "secret.of.life") + val secretAccountData = assertAccountData(testHelper, aliceSession, "secret.of.life") val encryptedContent = secretAccountData.content["encrypted"] as? Map<*, *> assertNotNull("Element should be encrypted", encryptedContent) @@ -149,12 +148,10 @@ class QuadSTests : InstrumentedTest { } assertEquals("Secret mismatch", clearSecret, decryptedSecret) - testHelper.signOutAndClose(aliceSession) } @Test - fun test_SetDefaultLocalEcho() { - val testHelper = CommonTestHelper(context()) + fun test_SetDefaultLocalEcho() = runSessionTest(context()) { testHelper -> val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) @@ -170,19 +167,16 @@ class QuadSTests : InstrumentedTest { testHelper.runBlockingTest { quadS.setDefaultKey(TEST_KEY_ID) } - - testHelper.signOutAndClose(aliceSession) } @Test - fun test_StoreSecretWithMultipleKey() { - val testHelper = CommonTestHelper(context()) + fun test_StoreSecretWithMultipleKey() = runSessionTest(context()) { testHelper -> val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) val keyId1 = "Key.1" - val key1Info = generatedSecret(aliceSession, keyId1, true) + val key1Info = generatedSecret(testHelper, aliceSession, keyId1, true) val keyId2 = "Key2" - val key2Info = generatedSecret(aliceSession, keyId2, true) + val key2Info = generatedSecret(testHelper, aliceSession, keyId2, true) val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit" @@ -221,19 +215,16 @@ class QuadSTests : InstrumentedTest { RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey)!! ) } - - testHelper.signOutAndClose(aliceSession) } @Test @Ignore("Test is working locally, not in GitHub actions") - fun test_GetSecretWithBadPassphrase() { - val testHelper = CommonTestHelper(context()) + fun test_GetSecretWithBadPassphrase() = runSessionTest(context()) { testHelper -> val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) val keyId1 = "Key.1" val passphrase = "The good pass phrase" - val key1Info = generatedSecretFromPassphrase(aliceSession, passphrase, keyId1, true) + val key1Info = generatedSecretFromPassphrase(testHelper, aliceSession, passphrase, keyId1, true) val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit" @@ -275,13 +266,9 @@ class QuadSTests : InstrumentedTest { ) ) } - - testHelper.signOutAndClose(aliceSession) } - private fun assertAccountData(session: Session, type: String): UserAccountDataEvent { - val testHelper = CommonTestHelper(context()) - + private fun assertAccountData(testHelper: CommonTestHelper, session: Session, type: String): UserAccountDataEvent { var accountData: UserAccountDataEvent? = null testHelper.waitWithLatch { val liveAccountData = session.accountDataService().getLiveUserAccountDataEvent(type) @@ -297,29 +284,27 @@ class QuadSTests : InstrumentedTest { return accountData!! } - private fun generatedSecret(session: Session, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo { + private fun generatedSecret(testHelper: CommonTestHelper, session: Session, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo { val quadS = session.sharedSecretStorageService() - val testHelper = CommonTestHelper(context()) val creationInfo = testHelper.runBlockingTest { quadS.generateKey(keyId, null, keyId, emptyKeySigner) } - assertAccountData(session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId") + assertAccountData(testHelper, session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId") if (asDefault) { testHelper.runBlockingTest { quadS.setDefaultKey(keyId) } - assertAccountData(session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID) + assertAccountData(testHelper, session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID) } return creationInfo } - private fun generatedSecretFromPassphrase(session: Session, passphrase: String, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo { + private fun generatedSecretFromPassphrase(testHelper: CommonTestHelper, session: Session, passphrase: String, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo { val quadS = session.sharedSecretStorageService() - val testHelper = CommonTestHelper(context()) val creationInfo = testHelper.runBlockingTest { quadS.generateKeyWithPassphrase( @@ -331,12 +316,12 @@ class QuadSTests : InstrumentedTest { ) } - assertAccountData(session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId") + assertAccountData(testHelper, session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId") if (asDefault) { testHelper.runBlockingTest { quadS.setDefaultKey(keyId) } - assertAccountData(session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID) + assertAccountData(testHelper, session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID) } return creationInfo diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt index 2892cf8464..c4d9ba4ee3 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt @@ -44,8 +44,7 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransa import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.toModel -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationCancel import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationStart import org.matrix.android.sdk.internal.crypto.model.rest.toValue @@ -56,9 +55,7 @@ import java.util.concurrent.CountDownLatch class SASTest : InstrumentedTest { @Test - fun test_aliceStartThenAliceCancel() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun test_aliceStartThenAliceCancel() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession @@ -135,15 +132,11 @@ class SASTest : InstrumentedTest { assertNull(bobVerificationService.getExistingTransaction(aliceSession.myUserId, txID)) assertNull(aliceVerificationService.getExistingTransaction(bobSession.myUserId, txID)) - - cryptoTestData.cleanUp(testHelper) } @Test @Ignore("This test will be ignored until it is fixed") - fun test_key_agreement_protocols_must_include_curve25519() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun test_key_agreement_protocols_must_include_curve25519() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> fail("Not passing for the moment") val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() @@ -195,15 +188,11 @@ class SASTest : InstrumentedTest { testHelper.await(cancelLatch) assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod, cancelReason) - - cryptoTestData.cleanUp(testHelper) } @Test @Ignore("This test will be ignored until it is fixed") - fun test_key_agreement_macs_Must_include_hmac_sha256() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun test_key_agreement_macs_Must_include_hmac_sha256() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> fail("Not passing for the moment") val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() @@ -236,15 +225,11 @@ class SASTest : InstrumentedTest { val cancelReq = canceledToDeviceEvent!!.content.toModel()!! assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code) - - cryptoTestData.cleanUp(testHelper) } @Test @Ignore("This test will be ignored until it is fixed") - fun test_key_agreement_short_code_include_decimal() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun test_key_agreement_short_code_include_decimal() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> fail("Not passing for the moment") val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() @@ -277,8 +262,6 @@ class SASTest : InstrumentedTest { val cancelReq = canceledToDeviceEvent!!.content.toModel()!! assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code) - - cryptoTestData.cleanUp(testHelper) } private fun fakeBobStart(bobSession: Session, @@ -314,9 +297,7 @@ class SASTest : InstrumentedTest { // any two devices may only have at most one key verification in flight at a time. // If a device has two verifications in progress with the same device, then it should cancel both verifications. @Test - fun test_aliceStartTwoRequests() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun test_aliceStartTwoRequests() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession @@ -357,9 +338,7 @@ class SASTest : InstrumentedTest { */ @Test @Ignore("This test will be ignored until it is fixed") - fun test_aliceAndBobAgreement() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun test_aliceAndBobAgreement() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession @@ -413,14 +392,10 @@ class SASTest : InstrumentedTest { accepted!!.shortAuthenticationStrings.forEach { assertTrue("all agreed Short Code should be known by alice", startReq!!.shortAuthenticationStrings.contains(it)) } - - cryptoTestData.cleanUp(testHelper) } @Test - fun test_aliceAndBobSASCode() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun test_aliceAndBobSASCode() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession @@ -473,14 +448,10 @@ class SASTest : InstrumentedTest { "Should have same SAS", aliceTx.getShortCodeRepresentation(SasMode.DECIMAL), bobTx.getShortCodeRepresentation(SasMode.DECIMAL) ) - - cryptoTestData.cleanUp(testHelper) } @Test - fun test_happyPath() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun test_happyPath() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession @@ -553,13 +524,10 @@ class SASTest : InstrumentedTest { assertTrue("alice device should be verified from bob point of view", aliceDeviceInfoFromBobPOV!!.isVerified) assertTrue("bob device should be verified from alice point of view", bobDeviceInfoFromAlicePOV!!.isVerified) - cryptoTestData.cleanUp(testHelper) } @Test - fun test_ConcurrentStart() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun test_ConcurrentStart() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession @@ -646,7 +614,5 @@ class SASTest : InstrumentedTest { bobPovTx?.state == VerificationTxState.ShortCodeReady } } - - cryptoTestData.cleanUp(testHelper) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt index ceebc3cd01..462f47cafc 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt @@ -31,8 +31,8 @@ import org.matrix.android.sdk.api.session.crypto.verification.CancelCode import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod import org.matrix.android.sdk.api.session.crypto.verification.VerificationService -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants import java.util.concurrent.CountDownLatch @@ -154,9 +154,7 @@ class VerificationTest : InstrumentedTest { private fun doTest(aliceSupportedMethods: List, bobSupportedMethods: List, expectedResultForAlice: ExpectedResult, - expectedResultForBob: ExpectedResult) { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + expectedResultForBob: ExpectedResult) = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession @@ -251,14 +249,11 @@ class VerificationTest : InstrumentedTest { pr.otherCanShowQrCode() shouldBe expectedResultForBob.otherCanShowQrCode pr.otherCanScanQrCode() shouldBe expectedResultForBob.otherCanScanQrCode } - - cryptoTestData.cleanUp(testHelper) } @Test - fun test_selfVerificationAcceptedCancelsItForOtherSessions() { + fun test_selfVerificationAcceptedCancelsItForOtherSessions() = runSessionTest(context()) { testHelper -> val defaultSessionParams = SessionTestParams(true) - val testHelper = CommonTestHelper(context()) val aliceSessionToVerify = testHelper.createAccount(TestConstants.USER_ALICE, defaultSessionParams) val aliceSessionThatVerifies = testHelper.logIntoAccount(aliceSessionToVerify.myUserId, TestConstants.PASSWORD, defaultSessionParams) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt index a2984dd27e..1ffcc2a3e6 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt @@ -34,8 +34,7 @@ import org.matrix.android.sdk.api.session.events.model.isThread import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest import java.util.concurrent.CountDownLatch @RunWith(JUnit4::class) @@ -44,9 +43,7 @@ import java.util.concurrent.CountDownLatch class ThreadMessagingTest : InstrumentedTest { @Test - fun reply_in_thread_should_create_a_thread() { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + fun reply_in_thread_should_create_a_thread() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false) val aliceSession = cryptoTestData.firstSession @@ -104,9 +101,7 @@ class ThreadMessagingTest : InstrumentedTest { } @Test - fun reply_in_thread_should_create_a_thread_from_other_user() { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + fun reply_in_thread_should_create_a_thread_from_other_user() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false) val aliceSession = cryptoTestData.firstSession @@ -179,9 +174,7 @@ class ThreadMessagingTest : InstrumentedTest { } @Test - fun reply_in_thread_to_timeline_message_multiple_times() { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + fun reply_in_thread_to_timeline_message_multiple_times() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false) val aliceSession = cryptoTestData.firstSession @@ -244,9 +237,7 @@ class ThreadMessagingTest : InstrumentedTest { } @Test - fun thread_summary_advanced_validation_after_multiple_messages_in_multiple_threads() { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + fun thread_summary_advanced_validation_after_multiple_messages_in_multiple_threads() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false) val aliceSession = cryptoTestData.firstSession diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/PollAggregationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/PollAggregationTest.kt index 61ab6d4b40..2b72ecc52a 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/PollAggregationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/PollAggregationTest.kt @@ -38,8 +38,7 @@ import org.matrix.android.sdk.api.session.room.model.message.PollType import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest import java.util.concurrent.CountDownLatch @RunWith(JUnit4::class) @@ -47,9 +46,7 @@ import java.util.concurrent.CountDownLatch class PollAggregationTest : InstrumentedTest { @Test - fun testAllPollUseCases() { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + fun testAllPollUseCases() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false) val aliceSession = cryptoTestData.firstSession @@ -138,7 +135,6 @@ class PollAggregationTest : InstrumentedTest { aliceSession.stopSync() aliceTimeline.dispose() - cryptoTestData.cleanUp(commonTestHelper) } private fun testInitialPollConditions(pollContent: MessagePollContent, pollSummary: PollResponseAggregatedSummary?) { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt index e407c1b42d..3dd3f5fa2a 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt @@ -34,8 +34,7 @@ import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest import org.matrix.android.sdk.common.checkSendOrder import timber.log.Timber import java.util.concurrent.CountDownLatch @@ -53,9 +52,7 @@ class TimelineForwardPaginationTest : InstrumentedTest { * This test ensure that if we click to permalink, we will be able to go back to the live */ @Test - fun forwardPaginationTest() { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + fun forwardPaginationTest() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val numberOfMessagesToSend = 90 val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false) @@ -177,7 +174,5 @@ class TimelineForwardPaginationTest : InstrumentedTest { } aliceTimeline.dispose() - - cryptoTestData.cleanUp(commonTestHelper) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt index 1a36adec44..3ff4572add 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt @@ -33,7 +33,6 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.checkSendOrder import timber.log.Timber import java.util.concurrent.CountDownLatch @@ -48,9 +47,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest { */ @Test - fun previousLastForwardTest() { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + fun previousLastForwardTest() = CommonTestHelper.runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false) val aliceSession = cryptoTestData.firstSession @@ -242,7 +239,5 @@ class TimelinePreviousLastForwardTest : InstrumentedTest { } bobTimeline.dispose() - - cryptoTestData.cleanUp(commonTestHelper) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt index 42f710d7cf..7ed0be927c 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt @@ -32,8 +32,7 @@ import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest import org.matrix.android.sdk.common.TestConstants @RunWith(JUnit4::class) @@ -42,9 +41,7 @@ import org.matrix.android.sdk.common.TestConstants class TimelineSimpleBackPaginationTest : InstrumentedTest { @Test - fun timeline_backPaginate_shouldReachEndOfTimeline() { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + fun timeline_backPaginate_shouldReachEndOfTimeline() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val numberOfMessagesToSent = 200 val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false) @@ -102,6 +99,5 @@ class TimelineSimpleBackPaginationTest : InstrumentedTest { assertEquals(numberOfMessagesToSent, onlySentEvents.size) bobTimeline.dispose() - cryptoTestData.cleanUp(commonTestHelper) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt index 02430dda74..87f404b0f1 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt @@ -30,8 +30,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest import java.util.concurrent.CountDownLatch /** !! Not working with the new timeline @@ -47,15 +46,12 @@ class TimelineWithManyMembersTest : InstrumentedTest { private const val NUMBER_OF_MEMBERS = 6 } - private val commonTestHelper = CommonTestHelper(context()) - private val cryptoTestHelper = CryptoTestHelper(commonTestHelper) - /** * Ensures when someone sends a message to a crowded room, everyone can decrypt the message. */ @Test - fun everyone_should_decrypt_message_in_a_crowded_room() { + fun everyone_should_decrypt_message_in_a_crowded_room() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithManyMembers(NUMBER_OF_MEMBERS) val sessionForFirstMember = cryptoTestData.firstSession diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt index e17b7efbd6..7c97426c39 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt @@ -26,9 +26,8 @@ import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.search.SearchResult -import org.matrix.android.sdk.common.CommonTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest import org.matrix.android.sdk.common.CryptoTestData -import org.matrix.android.sdk.common.CryptoTestHelper @RunWith(JUnit4::class) @FixMethodOrder(MethodSorters.JVM) @@ -74,9 +73,7 @@ class SearchMessagesTest : InstrumentedTest { } } - private fun doTest(block: suspend (CryptoTestData) -> SearchResult) { - val commonTestHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + private fun doTest(block: suspend (CryptoTestData) -> SearchResult) = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false) val aliceSession = cryptoTestData.firstSession val aliceRoomId = cryptoTestData.roomId @@ -99,7 +96,5 @@ class SearchMessagesTest : InstrumentedTest { (it.event.content?.get("body") as? String)?.startsWith(MESSAGE).orFalse() }.orFalse() ) - - cryptoTestData.cleanUp(commonTestHelper) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt index b9760c1bfc..0d8a9058a2 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt @@ -40,7 +40,7 @@ import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent import org.matrix.android.sdk.api.session.space.JoinSpaceResult -import org.matrix.android.sdk.common.CommonTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest import org.matrix.android.sdk.common.SessionTestParams @RunWith(JUnit4::class) @@ -49,8 +49,7 @@ import org.matrix.android.sdk.common.SessionTestParams class SpaceCreationTest : InstrumentedTest { @Test - fun createSimplePublicSpace() { - val commonTestHelper = CommonTestHelper(context()) + fun createSimplePublicSpace() = runSessionTest(context()) { commonTestHelper -> val session = commonTestHelper.createAccount("Hubble", SessionTestParams(true)) val roomName = "My Space" val topic = "A public space for test" @@ -96,13 +95,10 @@ class SpaceCreationTest : InstrumentedTest { ?.toModel()?.historyVisibility assertEquals("Public space room should be world readable", RoomHistoryVisibility.WORLD_READABLE, historyVisibility) - - commonTestHelper.signOutAndClose(session) } @Test - fun testJoinSimplePublicSpace() { - val commonTestHelper = CommonTestHelper(context()) + fun testJoinSimplePublicSpace() = runSessionTest(context()) { commonTestHelper -> val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true)) val bobSession = commonTestHelper.createAccount("bob", SessionTestParams(true)) @@ -134,8 +130,7 @@ class SpaceCreationTest : InstrumentedTest { } @Test - fun testSimplePublicSpaceWithChildren() { - val commonTestHelper = CommonTestHelper(context()) + fun testSimplePublicSpaceWithChildren() = runSessionTest(context()) { commonTestHelper -> val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true)) val bobSession = commonTestHelper.createAccount("bob", SessionTestParams(true)) @@ -204,8 +199,5 @@ class SpaceCreationTest : InstrumentedTest { // ).size // // assertEquals("Unexpected number of joined children", 1, childCount) - - commonTestHelper.signOutAndClose(aliceSession) - commonTestHelper.signOutAndClose(bobSession) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt index 6a17cb74ad..4a9d7cc6ea 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt @@ -48,6 +48,7 @@ import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper import org.matrix.android.sdk.api.session.room.powerlevels.Role import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams import org.matrix.android.sdk.common.CommonTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest import org.matrix.android.sdk.common.SessionTestParams @RunWith(JUnit4::class) @@ -55,8 +56,7 @@ import org.matrix.android.sdk.common.SessionTestParams class SpaceHierarchyTest : InstrumentedTest { @Test - fun createCanonicalChildRelation() { - val commonTestHelper = CommonTestHelper(context()) + fun createCanonicalChildRelation() = runSessionTest(context()) { commonTestHelper -> val session = commonTestHelper.createAccount("John", SessionTestParams(true)) val spaceName = "My Space" @@ -173,8 +173,7 @@ class SpaceHierarchyTest : InstrumentedTest { // } @Test - fun testFilteringBySpace() { - val commonTestHelper = CommonTestHelper(context()) + fun testFilteringBySpace() = CommonTestHelper.runSessionTest(context()) { commonTestHelper -> val session = commonTestHelper.createAccount("John", SessionTestParams(true)) val spaceAInfo = createPublicSpace( @@ -185,12 +184,12 @@ class SpaceHierarchyTest : InstrumentedTest { ) /* val spaceBInfo = */ createPublicSpace( - session, "SpaceB", listOf( - Triple("B1", true /*auto-join*/, true/*canonical*/), - Triple("B2", true, true), - Triple("B3", true, true) - ) - ) + session, "SpaceB", listOf( + Triple("B1", true /*auto-join*/, true/*canonical*/), + Triple("B2", true, true), + Triple("B3", true, true) + ) + ) val spaceCInfo = createPublicSpace( session, "SpaceC", listOf( @@ -256,8 +255,7 @@ class SpaceHierarchyTest : InstrumentedTest { @Test @Ignore("This test will be ignored until it is fixed") - fun testBreakCycle() { - val commonTestHelper = CommonTestHelper(context()) + fun testBreakCycle() = CommonTestHelper.runSessionTest(context()) { commonTestHelper -> val session = commonTestHelper.createAccount("John", SessionTestParams(true)) val spaceAInfo = createPublicSpace( @@ -302,8 +300,7 @@ class SpaceHierarchyTest : InstrumentedTest { } @Test - fun testLiveFlatChildren() { - val commonTestHelper = CommonTestHelper(context()) + fun testLiveFlatChildren() = CommonTestHelper.runSessionTest(context()) { commonTestHelper -> val session = commonTestHelper.createAccount("John", SessionTestParams(true)) val spaceAInfo = createPublicSpace( @@ -395,25 +392,26 @@ class SpaceHierarchyTest : InstrumentedTest { childInfo: List> /** Name, auto-join, canonical*/ ): TestSpaceCreationResult { - val commonTestHelper = CommonTestHelper(context()) var spaceId = "" var roomIds: List = emptyList() - commonTestHelper.waitWithLatch { latch -> - spaceId = session.spaceService().createSpace(spaceName, "Test Topic", null, true) - val syncedSpace = session.spaceService().getSpace(spaceId) - val viaServers = listOf(session.sessionParams.homeServerHost ?: "") + runSessionTest(context()) { commonTestHelper -> + commonTestHelper.waitWithLatch { latch -> + spaceId = session.spaceService().createSpace(spaceName, "Test Topic", null, true) + val syncedSpace = session.spaceService().getSpace(spaceId) + val viaServers = listOf(session.sessionParams.homeServerHost ?: "") - roomIds = childInfo.map { entry -> - session.roomService().createRoom(CreateRoomParams().apply { name = entry.first }) - } - roomIds.forEachIndexed { index, roomId -> - syncedSpace!!.addChildren(roomId, viaServers, null, childInfo[index].second) - val canonical = childInfo[index].third - if (canonical != null) { - session.spaceService().setSpaceParent(roomId, spaceId, canonical, viaServers) + roomIds = childInfo.map { entry -> + session.roomService().createRoom(CreateRoomParams().apply { name = entry.first }) } + roomIds.forEachIndexed { index, roomId -> + syncedSpace!!.addChildren(roomId, viaServers, null, childInfo[index].second) + val canonical = childInfo[index].third + if (canonical != null) { + session.spaceService().setSpaceParent(roomId, spaceId, canonical, viaServers) + } + } + latch.countDown() } - latch.countDown() } return TestSpaceCreationResult(spaceId, roomIds) } @@ -423,51 +421,51 @@ class SpaceHierarchyTest : InstrumentedTest { childInfo: List> /** Name, auto-join, canonical*/ ): TestSpaceCreationResult { - val commonTestHelper = CommonTestHelper(context()) var spaceId = "" var roomIds: List = emptyList() - commonTestHelper.waitWithLatch { latch -> - spaceId = session.spaceService().createSpace(spaceName, "My Private Space", null, false) - val syncedSpace = session.spaceService().getSpace(spaceId) - val viaServers = listOf(session.sessionParams.homeServerHost ?: "") - roomIds = - childInfo.map { entry -> - val homeServerCapabilities = session - .homeServerCapabilitiesService() - .getHomeServerCapabilities() - session.roomService().createRoom(CreateRoomParams().apply { - name = entry.first - this.featurePreset = RestrictedRoomPreset( - homeServerCapabilities, - listOf( - RoomJoinRulesAllowEntry.restrictedToRoom(spaceId) - ) - ) - }) + runSessionTest(context()) { commonTestHelper -> + commonTestHelper.waitWithLatch { latch -> + spaceId = session.spaceService().createSpace(spaceName, "My Private Space", null, false) + val syncedSpace = session.spaceService().getSpace(spaceId) + val viaServers = listOf(session.sessionParams.homeServerHost ?: "") + roomIds = + childInfo.map { entry -> + val homeServerCapabilities = session + .homeServerCapabilitiesService() + .getHomeServerCapabilities() + session.roomService().createRoom(CreateRoomParams().apply { + name = entry.first + this.featurePreset = RestrictedRoomPreset( + homeServerCapabilities, + listOf( + RoomJoinRulesAllowEntry.restrictedToRoom(spaceId) + ) + ) + }) + } + roomIds.forEachIndexed { index, roomId -> + syncedSpace!!.addChildren(roomId, viaServers, null, childInfo[index].second) + val canonical = childInfo[index].third + if (canonical != null) { + session.spaceService().setSpaceParent(roomId, spaceId, canonical, viaServers) } - roomIds.forEachIndexed { index, roomId -> - syncedSpace!!.addChildren(roomId, viaServers, null, childInfo[index].second) - val canonical = childInfo[index].third - if (canonical != null) { - session.spaceService().setSpaceParent(roomId, spaceId, canonical, viaServers) } + latch.countDown() } - latch.countDown() } return TestSpaceCreationResult(spaceId, roomIds) } @Test - fun testRootSpaces() { - val commonTestHelper = CommonTestHelper(context()) + fun testRootSpaces() = runSessionTest(context()) { commonTestHelper -> val session = commonTestHelper.createAccount("John", SessionTestParams(true)) /* val spaceAInfo = */ createPublicSpace( - session, "SpaceA", listOf( - Triple("A1", true /*auto-join*/, true/*canonical*/), - Triple("A2", true, true) - ) - ) + session, "SpaceA", listOf( + Triple("A1", true /*auto-join*/, true/*canonical*/), + Triple("A2", true, true) + ) + ) val spaceBInfo = createPublicSpace( session, "SpaceB", listOf( @@ -506,13 +504,10 @@ class SpaceHierarchyTest : InstrumentedTest { } assertEquals("Unexpected number of root spaces ${rootSpaces.map { it.name }}", 2, rootSpaces.size) - - commonTestHelper.signOutAndClose(session) } @Test - fun testParentRelation() { - val commonTestHelper = CommonTestHelper(context()) + fun testParentRelation() = runSessionTest(context()) { commonTestHelper -> val aliceSession = commonTestHelper.createAccount("Alice", SessionTestParams(true)) val bobSession = commonTestHelper.createAccount("Bib", SessionTestParams(true)) @@ -604,8 +599,5 @@ class SpaceHierarchyTest : InstrumentedTest { bobSession.getRoomSummary(bobRoomId)?.flattenParentIds?.contains(spaceAInfo.spaceId) == true } } - - commonTestHelper.signOutAndClose(aliceSession) - commonTestHelper.signOutAndClose(bobSession) } } From adb5b4c1b95c2e1e5bf2bae76a2e137a7bcfdeaa Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 25 May 2022 15:33:32 +0200 Subject: [PATCH 143/244] Fix closing deactivated accounts in tests --- .../java/org/matrix/android/sdk/common/CommonTestHelper.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt index 1c17da83b6..dee54d3427 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt @@ -110,7 +110,11 @@ class CommonTestHelper private constructor(context: Context) { fun cleanUpOpenedSessions() { trackedSessions.forEach { runBlockingTest { - it.signOutService().signOut(true) + try { + it.signOutService().signOut(true) + } catch (failure: Throwable) { + // Well, as long as you tried. + } } } trackedSessions.clear() From e1292c03a1742f110f11700920ceb83573450b94 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 25 May 2022 17:47:46 +0200 Subject: [PATCH 144/244] code review --- .../sdk/account/DeactivateAccountTest.kt | 2 +- .../android/sdk/common/CommonTestHelper.kt | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt index 3575e19c2b..0b21f85742 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt @@ -40,7 +40,7 @@ import kotlin.coroutines.resume class DeactivateAccountTest : InstrumentedTest { @Test - fun deactivateAccountTest() = runSessionTest(context()) { commonTestHelper -> + fun deactivateAccountTest() = runSessionTest(context(), false /* session will be deactivated */) { commonTestHelper -> val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true)) // Deactivate the account diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt index dee54d3427..fdfaceeb4d 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt @@ -57,22 +57,26 @@ import java.util.concurrent.TimeUnit class CommonTestHelper private constructor(context: Context) { companion object { - internal fun runSessionTest(context: Context, block: (CommonTestHelper) -> Unit) { + internal fun runSessionTest(context: Context, autoSignoutOnClose: Boolean = true, block: (CommonTestHelper) -> Unit) { val testHelper = CommonTestHelper(context) return try { block(testHelper) } finally { - testHelper.cleanUpOpenedSessions() + if (autoSignoutOnClose) { + testHelper.cleanUpOpenedSessions() + } } } - internal fun runCryptoTest(context: Context, block: (CryptoTestHelper, CommonTestHelper) -> Unit) { + internal fun runCryptoTest(context: Context, autoSignoutOnClose: Boolean = true, block: (CryptoTestHelper, CommonTestHelper) -> Unit) { val testHelper = CommonTestHelper(context) val cryptoTestHelper = CryptoTestHelper(testHelper) return try { block(cryptoTestHelper, testHelper) } finally { - testHelper.cleanUpOpenedSessions() + if (autoSignoutOnClose) { + testHelper.cleanUpOpenedSessions() + } } } } @@ -110,11 +114,7 @@ class CommonTestHelper private constructor(context: Context) { fun cleanUpOpenedSessions() { trackedSessions.forEach { runBlockingTest { - try { - it.signOutService().signOut(true) - } catch (failure: Throwable) { - // Well, as long as you tried. - } + it.signOutService().signOut(true) } } trackedSessions.clear() @@ -419,8 +419,8 @@ class CommonTestHelper private constructor(context: Context) { */ fun await(latch: CountDownLatch, timeout: Long? = TestConstants.timeOutMillis) { assertTrue( - "Timed out after " + timeout + "ms waiting for something to happen. See stacktrace for cause.", - latch.await(timeout ?: TestConstants.timeOutMillis, TimeUnit.MILLISECONDS) + "Timed out after " + timeout + "ms waiting for something to happen. See stacktrace for cause.", + latch.await(timeout ?: TestConstants.timeOutMillis, TimeUnit.MILLISECONDS) ) } From 5735b094ac3d13a582b053e77bc4f0ede20acb11 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 25 May 2022 18:41:37 +0200 Subject: [PATCH 145/244] post rebase fix --- .../sdk/internal/crypto/DecryptRedactedEventTest.kt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/DecryptRedactedEventTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/DecryptRedactedEventTest.kt index de5fa41581..a48b45a1f5 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/DecryptRedactedEventTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/DecryptRedactedEventTest.kt @@ -27,18 +27,14 @@ import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.getTimelineEvent -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest @RunWith(AndroidJUnit4::class) @FixMethodOrder(MethodSorters.JVM) class DecryptRedactedEventTest : InstrumentedTest { @Test - fun doNotFailToDecryptRedactedEvent() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) - + fun doNotFailToDecryptRedactedEvent() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val e2eRoomID = testData.roomId val aliceSession = testData.firstSession From 92a140b5041f9fc4423ccc9aa9348de41ab8a1c8 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Wed, 25 May 2022 20:50:58 +0200 Subject: [PATCH 146/244] Add unit tests for filter/map logic --- .../widgets/WebviewPermissionUtilsTest.kt | 83 +++++++++++++++++++ .../widgets/webview/WebviewPermissionUtils.kt | 18 ++-- 2 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 vector/src/androidTest/java/im/vector/app/features/widgets/WebviewPermissionUtilsTest.kt diff --git a/vector/src/androidTest/java/im/vector/app/features/widgets/WebviewPermissionUtilsTest.kt b/vector/src/androidTest/java/im/vector/app/features/widgets/WebviewPermissionUtilsTest.kt new file mode 100644 index 0000000000..6ae17dbda4 --- /dev/null +++ b/vector/src/androidTest/java/im/vector/app/features/widgets/WebviewPermissionUtilsTest.kt @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.widgets + +import android.Manifest +import android.webkit.PermissionRequest +import im.vector.app.InstrumentedTest +import im.vector.app.features.widgets.webview.WebviewPermissionUtils +import org.amshove.kluent.shouldBeEqualTo +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.junit.runners.MethodSorters + +@RunWith(JUnit4::class) +@FixMethodOrder(MethodSorters.JVM) +class WebviewPermissionUtilsTest : InstrumentedTest { + + private val utils = WebviewPermissionUtils() + + @Test + fun filterPermissionsToBeGranted_selectedAndGrantedNothing() { + val permissions = utils.filterPermissionsToBeGranted( + selectedWebPermissions = listOf(), + androidPermissionResult = mapOf()) + permissions shouldBeEqualTo listOf() + } + + @Test + fun filterPermissionsToBeGranted_selectedNothingGrantedCamera() { + val permissions = utils.filterPermissionsToBeGranted( + selectedWebPermissions = listOf(), + androidPermissionResult = mapOf(Manifest.permission.CAMERA to true)) + permissions shouldBeEqualTo listOf() + } + + @Test + fun filterPermissionsToBeGranted_selectedAndPreviouslyGrantedCamera() { + val permissions = utils.filterPermissionsToBeGranted( + selectedWebPermissions = listOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE), + androidPermissionResult = mapOf()) + permissions shouldBeEqualTo listOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE) + } + + @Test + fun filterPermissionsToBeGranted_selectedAndGrantedCamera() { + val permissions = utils.filterPermissionsToBeGranted( + selectedWebPermissions = listOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE), + androidPermissionResult = mapOf(Manifest.permission.CAMERA to true)) + permissions shouldBeEqualTo listOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE) + } + + @Test + fun filterPermissionsToBeGranted_selectedAndDeniedCamera() { + val permissions = utils.filterPermissionsToBeGranted( + selectedWebPermissions = listOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE), + androidPermissionResult = mapOf(Manifest.permission.CAMERA to false)) + permissions shouldBeEqualTo listOf() + } + + @Test + fun filterPermissionsToBeGranted_selectedProtectedMediaGrantedNothing() { + val permissions = utils.filterPermissionsToBeGranted( + selectedWebPermissions = listOf(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID), + androidPermissionResult = mapOf(Manifest.permission.CAMERA to false)) + permissions shouldBeEqualTo listOf(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID) + } +} diff --git a/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt b/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt index 2bf12dff43..92b6ad213c 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt @@ -21,6 +21,7 @@ import android.content.Context import android.webkit.PermissionRequest import androidx.activity.result.ActivityResultLauncher import androidx.annotation.StringRes +import androidx.annotation.VisibleForTesting import androidx.fragment.app.FragmentActivity import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R @@ -78,12 +79,7 @@ class WebviewPermissionUtils @Inject constructor() { if (permissionRequest == null) { throw NullPointerException("permissionRequest was null! Make sure to call promptForPermissions first.") } - val grantedPermissions = selectedPermissions.filter { webPermission -> - val androidPermission = webPermissionToAndroidPermission(webPermission) - ?: return@filter true // No corresponding Android permission exists - return@filter result[androidPermission] - ?: return@filter true // Android permission already granted before - } + val grantedPermissions = filterPermissionsToBeGranted(selectedPermissions, result) if (grantedPermissions.isNotEmpty()) { permissionRequest?.grant(grantedPermissions.toTypedArray()) } else { @@ -92,6 +88,16 @@ class WebviewPermissionUtils @Inject constructor() { reset() } + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + fun filterPermissionsToBeGranted(selectedWebPermissions: List, androidPermissionResult: Map): List { + return selectedWebPermissions.filter { webPermission -> + val androidPermission = webPermissionToAndroidPermission(webPermission) + ?: return@filter true // No corresponding Android permission exists + return@filter androidPermissionResult[androidPermission] + ?: return@filter true // Android permission already granted before + } + } + private fun reset() { permissionRequest = null selectedPermissions = listOf() From 2802a714ab9e8c848ac1f009833b84dddad174f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Thu, 26 May 2022 08:36:12 +0200 Subject: [PATCH 147/244] Fix concurrency group --- .github/workflows/quality.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index ae6af06d86..014139d0ba 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -108,7 +108,7 @@ jobs: runs-on: ubuntu-latest # Allow all jobs on main and develop. Just one per PR. concurrency: - group: ${{ github.ref == 'refs/heads/main' && format('ktlint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('ktlint-develop-{0}', github.sha) || format('ktlint-{0}', github.ref) }} + group: ${{ github.ref == 'refs/heads/main' && format('dep-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('dep-develop-{0}', github.sha) || format('dep-{0}', github.ref) }} cancel-in-progress: true steps: - uses: actions/checkout@v3 From 3336249b00693227c294bf1869509a01f37949d0 Mon Sep 17 00:00:00 2001 From: "Auri B. P" Date: Wed, 25 May 2022 06:44:45 +0000 Subject: [PATCH 148/244] Translated using Weblate (Catalan) Currently translated at 84.2% (1874 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ca/ --- vector/src/main/res/values-ca/strings.xml | 29 +++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/vector/src/main/res/values-ca/strings.xml b/vector/src/main/res/values-ca/strings.xml index 8b3223ed26..1a7b828b5b 100644 --- a/vector/src/main/res/values-ca/strings.xml +++ b/vector/src/main/res/values-ca/strings.xml @@ -36,7 +36,7 @@ %1$s a canviat el seu àlies a %2$s %s ha realitzat una videotrucada. %s ha realitzat una trucada de veu. - Convida a la sala + %1$s i %2$s Sala buida %s s\'ha actualitzat aquí. @@ -505,7 +505,7 @@ Crea Inici Sales - Ha sigut convidat + Convidat %2$s t\'ha expulsat de %1$s %2$s l\'ha expulsat de la sala %1$s Raó: %1$s @@ -1185,7 +1185,7 @@ Vetar usuaris Expulsar usuaris Canviar la configuració - Convidar usuaris + Convida usuaris Enviar missatges Rol predeterminat No tens permisos per modificar els rols necessaris per canviar les diferents parts de la sala @@ -1957,7 +1957,7 @@ Públic Només els convidats poden trobar-la i unir-s\'hi Qualsevol pot demanar entrar a la sala, els participants poden acceptar-ho o rebutjar-ho - Permet als convidats unir-se + Sales suggerides Activa les notificacions per correu de %s Notificacions per correu @@ -2086,4 +2086,25 @@ Actualitza a la versió de sala recomanada Aquesta sala té la versió %s, la qual està marcada com a no estable pel servidor. Només amb invitació, per tu o per equips + ${app_name} Ubicació en directe + Atura + Carregant ubicació en directe… + Compartició d\'ubicació en directe activada + No s\'ha pogut carregar el mapa + Mostra les ubicacions dels usuaris a la cronologia + Si està activat, podràs enviar la teva ubicació a qualsevol sala + Activa la compartició d\'ubicació + Obre amb + ${app_name} no ha pogut accedir a la teva ubicació. Torna-ho a provar més tard. + ${app_name} no ha pogut accedir a la teva ubicació + Permet l\'accés + 8 hores + 1 hora + 15 minuts + Comparteix la teva ubicació en directe durant + Comparteix la ubicació + Comparteix la ubicació + Convida gent al teu espai + Convida gent + Posa-li un nom per continuar. \ No newline at end of file From e1285aa50b37e8d875ccdab00e1539d5bcc69021 Mon Sep 17 00:00:00 2001 From: Glandos Date: Wed, 25 May 2022 07:14:58 +0000 Subject: [PATCH 149/244] Translated using Weblate (French) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fr/ --- vector/src/main/res/values-fr/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/res/values-fr/strings.xml b/vector/src/main/res/values-fr/strings.xml index 4cf1b89b84..5df4fbb091 100644 --- a/vector/src/main/res/values-fr/strings.xml +++ b/vector/src/main/res/values-fr/strings.xml @@ -2452,7 +2452,7 @@ \nPour nous y préparer, nous avons besoin de faire certains changements : les fils créés avant maintenant seront affichés comme des réponses classiques. \n \nCette transition sera unique, maintenant que les fils de discussions ont intégré la spécification de Matrix. - Partage d\'écran en cours + Partage d’écran en cours Partage d’écran pour ${app_name} Chargement de la position en direct… 8 heures From 24dc5b10e8d1f8db8751e67d908346f08b84db7b Mon Sep 17 00:00:00 2001 From: Vancha Date: Wed, 25 May 2022 13:24:47 +0000 Subject: [PATCH 150/244] Translated using Weblate (Frisian) Currently translated at 40.6% (905 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fy/ --- vector/src/main/res/values-fy/strings.xml | 25 +++-------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/vector/src/main/res/values-fy/strings.xml b/vector/src/main/res/values-fy/strings.xml index bb1dce247d..d16b81d39b 100644 --- a/vector/src/main/res/values-fy/strings.xml +++ b/vector/src/main/res/values-fy/strings.xml @@ -38,7 +38,6 @@ Ynlûke Ferbining ferbrekke Ynhâld melde - of Utnûgje Akseptearje @@ -70,7 +69,6 @@ Allinnich Matrix-kontakten Gjin resultaten Petearen - Mienskippen Lochboek ferstjoere Ungeloklochboek ferstjoere @@ -365,7 +363,6 @@ Thússerver Oanmeld as Autentikaasje - Foar it letst sjoen Iepenbiere namme wizigje Iepenbiere namme @@ -382,8 +379,6 @@ Ferstjoere Jo brûke gjin identiteitsserver Unbekende flater - - Ferifikaasjeoanfraach %s wol jo sesje ferifiearje Ferifiearre! @@ -680,7 +675,6 @@ %1$s hat gasten tastien om dizze keamer binnen te gean. Systeemstandert Jo hawwe end-to-end-fersifering ynskeakele (ûnbekend algoritme %1$s). - %1$s, %2$s, %3$s en %4$d oar %1$s, %2$s, %3$s en %4$d oaren @@ -844,8 +838,6 @@ SSL-flater: de identiteit fan de oar is net befêstige. Thússerver kieze Graach it belied fan dizze thússerver lêze en oanfurdigje: - - Dit telefoannûmer is al definiearre. Dit is gjin jildich e-mailadres Ferkearde brûkersnamme en/of wachtwurd @@ -857,7 +849,6 @@ Live ferbining opsetten mislearre. \nFreegje de behearder fan jo thússerver om in TURN-server te konfigurearjen, sadat oproppen betrouber wurkje. ${app_name} Oprop mislearre - Binne jo wis dat jo in fideo-oprop begjinne wolle\? Binne jo wis dat jo in spraakoprop begjinne wolle\? Skodzje om in probleem te melden @@ -893,20 +884,15 @@ %1$s hat %2$s as alternatyf keameradres tafoege. %1$s hat %2$s as alternative keameradressen tafoege. - Gean nei net-lêzen Ledelist Ofwize Tagong jaan ta jo kontaktpersoanen. Om de QR-koade te scannen moatte jo tagong ta de kamera jaan. - ${app_name} hat tagong nedich ta jo kamera en mikrofoan om fideo-oproppen te meitsjen. \n \nJou tagong op de folgjende pop-ups om de oprop te meitsjen. - ${app_name} hat tagong nedich ta jo mikrofoan om spraakoproppen te meitsjen. - - Oprop beëinigje… De oare kant hat net opnommen. Gjin antwurd @@ -957,15 +943,10 @@ \nBinne jo wis\? Untballe Dit petear is net iepenbier. Jo kinne net opnij ta trede sûnder útnûging. - - - - %d dielnimmer %d dielnimmers - Der binne ien of mear tests mislearre, probearje de oanrekommandearre oplossing(en). Basisdiagnoaze is oké. As jo noch hieltyd gjin meldingen ûntfange, meitsje dan in bugmelding oan om ús te helpen ûndersykjen. Diagnostyske probleemoplossingsynformaasje @@ -981,10 +962,7 @@ De keamer is ferlitten! Fluchkeppeling oan startskerm tafoegje Allinnich fermeldingen en kaaiwurden - - Ferballe brûkers filterje - Underwerp wizigje De romte opwurdearje De keamer opwurdearje @@ -1011,4 +989,7 @@ %s is oan it typen… Troch dizze brûker net mear te ferballen kin dy opnij oan it petear meidwaan. Troch dizze brûker net mear te ferballen kin dy opnij yn de romte komme. + - Beskate brûkers binne net mear negearre + Inisjele syngronisaasje oanfreegje + It is jo net tastien dizze keamer binnen te gean \ No newline at end of file From bc8432418d71ca891cca529b0edb9ee04cce6c69 Mon Sep 17 00:00:00 2001 From: Szimszon Date: Tue, 24 May 2022 06:59:47 +0000 Subject: [PATCH 151/244] Translated using Weblate (Hungarian) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/hu/ --- vector/src/main/res/values-hu/strings.xml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-hu/strings.xml b/vector/src/main/res/values-hu/strings.xml index 07d97a8c86..3444d388ac 100644 --- a/vector/src/main/res/values-hu/strings.xml +++ b/vector/src/main/res/values-hu/strings.xml @@ -2251,7 +2251,7 @@ A Visszaállítási Kulcsot tartsd biztonságos helyen, mint pl. egy jelszókeze Szobanév beállítása A felhasználó újbóli figyelembe vétele, és az üzenetei megjelenítése a jövőben Figyelmen kívül hagy egy felhasználót, elrejtve előled az üzeneteit - Elérhetetlen + Távol Kapcsolat nélkül Kapcsolódva Matrix szerver kiválasztása @@ -2334,7 +2334,7 @@ A Visszaállítási Kulcsot tartsd biztonságos helyen, mint pl. egy jelszókeze Fájl feltöltése Képek és videók küldése Kamera megnyitása - Becenév színének megváltoztatása + Megjelenítendő név színének megváltoztatása Már van fiókom Biztonságos üzenetküldés. Te irányítasz. @@ -2490,4 +2490,8 @@ A Visszaállítási Kulcsot tartsd biztonságos helyen, mint pl. egy jelszókeze \n \nFigyelem, ez az alkalmazást újra is indítja, ami eltarthat egy darabig. Kezdő szinkronizálási kérés - + A legfrissebb profil információk (profilkép és megjelenítendő név) megjelenítése minden üzenetnél. + Legfrissebb felhasználói információ megjelenítése + Foglalt + A mentésnek érvényes aláírása van ettől a felhasználótól. + \ No newline at end of file From e6614fc4fcc0ceaece51e5c961a55c675033dca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sveinn=20=C3=AD=20Felli?= Date: Mon, 23 May 2022 18:44:48 +0000 Subject: [PATCH 152/244] Translated using Weblate (Icelandic) Currently translated at 84.0% (1870 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/is/ --- vector/src/main/res/values-is/strings.xml | 54 ++++++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/values-is/strings.xml b/vector/src/main/res/values-is/strings.xml index 892d56b795..9bdeb92d31 100644 --- a/vector/src/main/res/values-is/strings.xml +++ b/vector/src/main/res/values-is/strings.xml @@ -1060,7 +1060,7 @@ Tegund Senda sérsniðinn atburð Skoða stöðu spjallrásar - Ekki tiltækt + Fjarverandi Ónettengt Nettengt Ekki tilkynna @@ -1976,4 +1976,54 @@ Spjallþræðir í bráðlegri Beta-útgáfu 🎉 Ráðfæri við %1$s Ráðfæra fyrst - + Deiling á skjá er í vinnslu + ${app_name} skjádeiling + Deiling staðsetningar er í vinnslu + ${app_name} rauntímastaðsetning + Hleð inn rauntímastaðsetningu… + 8 klukkustundir + 1 klukkustund + 15 mínútur + Deildu rauntímastaðsetningu þinni í + (%1$s) + %1$s (%2$s) + Gat ekki spilað %1$s + Setja %1$s í bið + Spila %1$s + %1$d mínútur %2$d sekúndur + %1$s, %2$s, %3$s + Upptekinn + Flytja yfir í %1$s + Útbý SSSS-lykil úr endurheimtulykli + Útbý SSSS-lykil úr lykilsetningu (%s) + Útbý SSSS-lykil úr lykilsetningu + Athuga öryggisafritunarlykil (%s) + Þú ert búin/n! + Deildu raunstaðsetningu sinni + Upphafleg samstilling… + Séð af + Sleppa þessu skrefi + Vista og halda áfram + Kjörstillingarnar þínar hafa verið vistaðar. + Nú ertu tilbúin(n)! + Hefjumst handa + Þú getur breytt þessu hvenær sem er. + Bættu við auðkennismynd + Þú getur breytt þessu síðar + Birtingarnafn + Veldu birtingarnafn + Til hamingju! + Virkja ítarlega atvikaskráningu. + BETA-prófunarútgáfa + Gefðu umsögn + BETA-prófunarútgáfa + Næ í útgáfu öryggisafrits… + Ónettengdur hamur + Viðvera + Hætta skjádeilingu + Deila skjá + Kanna nánar + Prófaðu það + Gera óvirkt + Upphafleg samstillingarbeiðni + \ No newline at end of file From fef3cdaeb1d1af6146dd1573feb38785caea1d77 Mon Sep 17 00:00:00 2001 From: Johan Smits Date: Tue, 24 May 2022 18:36:12 +0000 Subject: [PATCH 153/244] Translated using Weblate (Dutch) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/nl/ --- vector/src/main/res/values-nl/strings.xml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-nl/strings.xml b/vector/src/main/res/values-nl/strings.xml index 3397415ab7..4d47149d5b 100644 --- a/vector/src/main/res/values-nl/strings.xml +++ b/vector/src/main/res/values-nl/strings.xml @@ -1691,7 +1691,7 @@ Aangepaste gebeurtenis versturen Kamer status ontdekken Ontwikkel tools - Niet beschikbaar + Afwezig Offline Online Openbare kamer @@ -2334,7 +2334,7 @@ Word lid van de Space met het opgegeven id Toevoegen aan een Space Maak een Space - Bijnaam kleur overschrijven + Kleur weergavenaam overschrijven Ik heb al een account Veilig berichtenverkeer. U heeft de controle. @@ -2490,4 +2490,8 @@ \n \nHoud er rekening mee dat deze actie de app opnieuw zal starten en dat dit enige tijd kan duren. Initieel synchronisatieverzoek - + Toon de laatste profielinformatie (avatar en weergavenaam) voor alle berichten. + Toon laatste persoonsinformatie + Bezet + Back-up heeft een geldige handtekening van deze persoon. + \ No newline at end of file From 7a9b931a3689d1faea8a80df7b8e3d378d9a7605 Mon Sep 17 00:00:00 2001 From: Didek Date: Mon, 23 May 2022 06:19:25 +0000 Subject: [PATCH 154/244] Translated using Weblate (Polish) Currently translated at 100.0% (2225 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pl/ --- vector/src/main/res/values-pl/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-pl/strings.xml b/vector/src/main/res/values-pl/strings.xml index 23b1ef5d0c..e7ec77d1f4 100644 --- a/vector/src/main/res/values-pl/strings.xml +++ b/vector/src/main/res/values-pl/strings.xml @@ -1851,7 +1851,7 @@ %d nie odebranych połączeń głosowych %d nie odebranych połączeń głosowych - Połączenie przychodzące… + Dzwoni… Błąd autoryzacji, niepoprawne dane logowania Wybierz serwer domowy Nie można było połączyć się z serwerem domowym %s. Proszę sprawdzić link lub wybrać serwer domowy manualnie. @@ -1964,7 +1964,7 @@ Szukasz kogoś , kto nie jest w %s\? %s Cię zaprasza Zostałeś zaproszony - Przestrzenie są nową metodą na zarządzanie pokojami i osobami. + Przestrzenie są nową metodą na grupowanie razem wielu pokoi i osób. Dodaj przestrzeń do jakiejkolwiek przestrzeni którą zarządzasz. Dodaj istniejące przestrzenie Dodaj istniejące pokoje @@ -2083,7 +2083,7 @@ Podziel się opinią Nie udało się przesłać opinii (%s) Dziękujemy, Twoja opinia została wysłana - Zachęcamy do kontaktu, jeśli masz dodatkowe pytania + Pozwalam na kontakt ze mną w razie dodatkowych pytań Używasz przestrzeni w wersji beta. Ta opinia pomoże nam w tworzeniu kolejnych wersji. Twoja platforma i nazwa użytkownika zostaną odnotowane, abyśmy mogli w pełni wykorzystać Twoje sugestie. Prześlij opinię o przestrzeniach Stwórz nową przestrzeń From fc3ebca27311ea8bcb545e0742e81b2076f1fdf5 Mon Sep 17 00:00:00 2001 From: homocomputeris Date: Wed, 25 May 2022 23:03:53 +0000 Subject: [PATCH 155/244] Translated using Weblate (Russian) Currently translated at 97.6% (2172 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- vector/src/main/res/values-ru/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml index f822cf05f3..5a73e8281a 100644 --- a/vector/src/main/res/values-ru/strings.xml +++ b/vector/src/main/res/values-ru/strings.xml @@ -1,6 +1,6 @@ - %s приглашение + приглашение %s %1$s пригласил(а) %2$s %1$s пригласил(а) вас %1$s вошёл(ла) в комнату From 897d28bb03fc3ec15d71fdb7431f86a99952f282 Mon Sep 17 00:00:00 2001 From: Glandos Date: Wed, 25 May 2022 06:59:39 +0000 Subject: [PATCH 156/244] Translated using Weblate (French) Currently translated at 100.0% (60 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/fr/ --- fastlane/metadata/android/fr-FR/changelogs/40104100.txt | 2 ++ fastlane/metadata/android/fr-FR/changelogs/40104110.txt | 2 ++ fastlane/metadata/android/fr-FR/changelogs/40104120.txt | 2 ++ fastlane/metadata/android/fr-FR/changelogs/40104130.txt | 2 ++ fastlane/metadata/android/fr-FR/changelogs/40104140.txt | 2 ++ 5 files changed, 10 insertions(+) create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40104100.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40104110.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40104120.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40104130.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40104140.txt diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104100.txt b/fastlane/metadata/android/fr-FR/changelogs/40104100.txt new file mode 100644 index 0000000000..f2453c5539 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104100.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Défilement dans les messages vocaux. Plusieurs corrections de bogues et d’améliorations de stabilité. +Intégralité des changements : https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104110.txt b/fastlane/metadata/android/fr-FR/changelogs/40104110.txt new file mode 100644 index 0000000000..fe61fd021c --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104110.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Plusieurs corrections de bogues et d’améliorations de stabilité. +Intégralité des changements : https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104120.txt b/fastlane/metadata/android/fr-FR/changelogs/40104120.txt new file mode 100644 index 0000000000..accd82fe72 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104120.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Les utilisateurs peuvent apparaître hors-ligne. Ajout d’un lecteur pour les pièces jointes audio +Intégralité des changements : https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104130.txt b/fastlane/metadata/android/fr-FR/changelogs/40104130.txt new file mode 100644 index 0000000000..accd82fe72 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104130.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Les utilisateurs peuvent apparaître hors-ligne. Ajout d’un lecteur pour les pièces jointes audio +Intégralité des changements : https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104140.txt b/fastlane/metadata/android/fr-FR/changelogs/40104140.txt new file mode 100644 index 0000000000..087d5bc1c8 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Amélioration de la gestion des utilisateurs ignorés. Plusieurs corrections de bogues et d’améliorations de stabilité. +Intégralité des changements : https://github.com/vector-im/element-android/releases From c6e5a7544815e0d35df56beec38c83ba5ee4c831 Mon Sep 17 00:00:00 2001 From: Anderson Ivanovich Date: Thu, 26 May 2022 07:32:08 +0000 Subject: [PATCH 157/244] Translated using Weblate (Tamil) Currently translated at 3.2% (72 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ta/ --- vector/src/main/res/values-ta/strings.xml | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/vector/src/main/res/values-ta/strings.xml b/vector/src/main/res/values-ta/strings.xml index 26f337757f..31f2e1ebe8 100644 --- a/vector/src/main/res/values-ta/strings.xml +++ b/vector/src/main/res/values-ta/strings.xml @@ -1,4 +1,62 @@ %1$s அறையில் சேர்ந்தார் + • உடன் பொருந்தக்கூடிய சேவையகங்கள் இப்போது தடைசெய்யப்பட்டுள்ளன. + • %s உடன் பொருந்தக்கூடிய சேவையகங்கள் இப்போது தடைசெய்யப்பட்டுள்ளன. + + %d சேவையக-அணுகல் கட்டுப்பாட்டுப் பட்டியல் மாற்றம் + %d சேவையக-அணுகல் கட்டுப்பாட்டுப் பட்டியல் மாற்றங்கள் + + நீங்கள் இந்த அறைக்கான சேவையக-அணுகல் கட்டுப்பாட்டுப் பட்டியல் (ACL) களை மாற்றினீர்கள். + %s இந்த அறைக்கான சேவையக-அணுகல் கட்டுப்பாட்டுப் பட்டியல் (ACL) களை மாற்றினார். + • IP எழுத்துக்கள் உடன் பொருந்தக்கூடிய சேவையகங்கள் தடைசெய்யப்பட்டுள்ளன. + • IP எழுத்துக்கள் உடன் பொருந்தக்கூடிய சேவையகங்கள் அனுமதிக்கப்பட்டுள்ளன. + • %s உடன் பொருந்தக்கூடிய சேவையகங்கள் அனுமதிக்கப்பட்டுள்ளன. + • %s உடன் பொருந்தக்கூடிய சேவையகங்கள் தடைசெய்யப்பட்டுள்ளன. + நீங்கள் இந்த அறைக்கான சேவையக-அணுகல் கட்டுப்பாட்டுப் பட்டியல் (ACL) களை அமைத்தீர்கள். + %s இந்த அறைக்கான சேவையக-அணுகல் கட்டுப்பாட்டுப் பட்டியல் (ACL) களை அமைத்தார். + %s இங்குத் திறமுயர்த்தினார். + நீங்கள் இங்குத் திறமுயர்த்தினீர்கள். + நீங்கள் இந்த அறையைத் திறமுயர்த்தினீர்கள். + %s இந்த அறையைத் திறமுயர்த்தினார். + யாரேனும் ஒருவர். + எல்லா அறை உறுப்பினர்களும். + எல்லா அறை உறுப்பினர்களும், அவர்கள் இணைந்த இடத்திலிருந்து. + எல்லா அறை உறுப்பினர்களும், அவர்கள் அழைக்கப்பட்ட இடத்திலிருந்து. + அழைப்பை அமைக்க %s தரவை அனுப்பியுள்ளார். + %1$s என்பவர் வருங்கால குறுஞ்செய்திகள் %2$s க்கு புலப்படும்படி அமைத்தார் + நீங்கள் வருங்கால குறுஞ்செய்திகள் %1$s க்கு புலப்படும்படி அமைத்தீர்கள் + நீங்கள் வருங்கால அறை வரலாறு %1$s க்கு புலப்படும்படி அமைத்தீர்கள் + %1$s என்பவர் வருங்கால அறை வரலாறு %2$s க்கு புலப்படும்படி அமைத்தார் + நீங்கள் அழைப்பை முடித்தீர்கள். + %s அழைப்பை முடித்தார். + நீங்கள் அழைப்புக்குப் பதிலளித்தீர்கள். + %s அழைப்புக்கு பதிலளித்தார். + அழைப்பை அமைக்க நீங்கள் தரவை அனுப்பியுள்ளீர்கள். + நீங்கள் குரல் அழைப்பு விடுத்துள்ளீர். + %s என்பவர் குரல் அழைப்பு விடுத்துள்ளார். + நீங்கள் காணொளி அழைப்பு விடுத்துள்ளீர். + %s என்பவர் காணொளி அழைப்பு விடுத்துள்ளார். + %1$s என்பவர் அறை பெயரை %2$s என மாற்றியுள்ளார் + நீங்கள் அறை பெயரை %1$s என மாற்றியுள்ளீர்கள் + நீங்கள் அறை படத்தை மாற்றியுள்ளீர்கள் + %1$s என்பவர் தலைப்பை %2$s க்கு மாற்றினார் + %1$s என்பவர் அறை படத்தை மாற்றியுள்ளார் + நீங்கள் தலைப்பை %1$s க்கு மாற்றியுள்ளீர்கள் + நீங்கள் உங்கள் காட்சிப் பெயரை நீக்கியுள்ளீர்கள் (முன்பு %1$s ஆக இருந்தது) + %1$s தனது காட்சிப் பெயரை நீக்கியுள்ளார் (முன்பு %2$s ஆக இருந்தது) + நீங்கள் உங்கள் காட்சிப் பெயரை %1$s இருந்து %2$s க்கு மாற்றியுள்ளீர்கள் + %1$s தனது காட்சிப் பெயரை %2$s இருந்து %3$s க்கு மாற்றினார் + %1$s தனது காட்சிப் பெயரை %2$s என அமைத்தார் + நீங்கள் உங்கள் காட்சிப் பெயரை %1$s என அமைத்துள்ளீர்கள் + நீங்கள் உங்கள் சுயவிவரப் படத்தை மாற்றினீர்கள் + %1$s தனது சுயவிவரப் படத்தை மாற்றினார் + %2$s இன் அழைப்பிதழை %1$s திரும்பப் பெற்றார் + %1$s இன் அழைப்பிதழை நீங்கள் திரும்பப் பெற்றீர்கள் + நீங்கள் %1$s ஐ தடை செய்துள்ளீர்கள் + %1$s என்பவர் %2$s ஐ தடை செய்துள்ளார் + நீங்கள் %1$s இன் தடையை நீக்கியுள்ளீர்கள் + %1$s என்பவர் %2$s இன் தடையை நீக்கியுள்ளார் + %2$s ஐ %1$s நீக்கினார் + %1$s ஐ நீங்கள் நீக்கினீர்கள் \ No newline at end of file From 6a52ff4da22381eae0a94391fa01356f55491952 Mon Sep 17 00:00:00 2001 From: kingoflove819 Date: Wed, 25 May 2022 09:08:20 +0000 Subject: [PATCH 158/244] Translated using Weblate (Tamil) Currently translated at 3.2% (72 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ta/ --- vector/src/main/res/values-ta/strings.xml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-ta/strings.xml b/vector/src/main/res/values-ta/strings.xml index 31f2e1ebe8..a044ce5ddd 100644 --- a/vector/src/main/res/values-ta/strings.xml +++ b/vector/src/main/res/values-ta/strings.xml @@ -1,6 +1,6 @@ - %1$s அறையில் சேர்ந்தார் + %1$s அறையில் சேர்ந்துள்ளார் • உடன் பொருந்தக்கூடிய சேவையகங்கள் இப்போது தடைசெய்யப்பட்டுள்ளன. • %s உடன் பொருந்தக்கூடிய சேவையகங்கள் இப்போது தடைசெய்யப்பட்டுள்ளன. @@ -59,4 +59,20 @@ %1$s என்பவர் %2$s இன் தடையை நீக்கியுள்ளார் %2$s ஐ %1$s நீக்கினார் %1$s ஐ நீங்கள் நீக்கினீர்கள் + நீங்கள் அறையை விட்டு வெளியேறினீர்கள் + %1$s அறையை விட்டு வெளியேறினார் + நீங்கள் அறையை விட்டு வெளியேறினீர்கள் + %1$s அறையை விட்டு வெளியேறினார் + நீங்கள் சேர்ந்துள்ளீர்கள் + %1$s சேர்ந்துள்ளார் + நீங்கள் அறையில் சேர்ந்துள்ளீர்கள் + %1$s உங்களை அழைத்துள்ளார் + நீங்கள் %1$s ஐ அழைத்துள்ளீர்கள் + %1$s என்பவர் %2$s ஐ அழைத்துள்ளார் + நீங்கள் கலந்துரையாடலை உருவாக்கியுள்ளீர்கள் + %1$s கலந்துரையாடலை உருவாக்கியுள்ளார் + நீங்கள் இந்த அறையை உருவாக்கியுள்ளீர்கள் + %1$s அறையை உருவாக்கியுள்ளார் + உங்கள் அழைப்பிதழ் + %s இன் அழைப்பிதழ் \ No newline at end of file From 913c6b0f140d39e20d7596b4dcbcf7b3a9a83eb2 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 26 May 2022 11:38:55 +0100 Subject: [PATCH 159/244] warning the user when urls contain directional overrides and allowing them to confirm the url --- changelog.d/6163.feature | 1 + .../im/vector/app/core/extensions/String.kt | 26 ++++++++ .../home/room/detail/TimelineFragment.kt | 43 ++++++++------ .../core/extensions/StringExtensionsTest.kt | 59 +++++++++++++++++++ 4 files changed, 112 insertions(+), 17 deletions(-) create mode 100644 changelog.d/6163.feature create mode 100644 vector/src/main/java/im/vector/app/core/extensions/String.kt create mode 100644 vector/src/test/java/im/vector/app/core/extensions/StringExtensionsTest.kt diff --git a/changelog.d/6163.feature b/changelog.d/6163.feature new file mode 100644 index 0000000000..7c64f89b12 --- /dev/null +++ b/changelog.d/6163.feature @@ -0,0 +1 @@ +Security - Asking for user confirmation when tapping URLs which contain unicode directional overrides diff --git a/vector/src/main/java/im/vector/app/core/extensions/String.kt b/vector/src/main/java/im/vector/app/core/extensions/String.kt new file mode 100644 index 0000000000..f035de469c --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/extensions/String.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.core.extensions + +private const val RTL_OVERRIDE_CHAR = '\u202E' +private const val LTR_OVERRIDE_CHAR = '\u202D' + +fun String.ensureEndsLeftToRight() = if (containsRtLOverride()) "$this$LTR_OVERRIDE_CHAR" else this + +fun String.containsRtLOverride() = contains(RTL_OVERRIDE_CHAR) + +fun String.filterDirectionOverrides() = filterNot { it == RTL_OVERRIDE_CHAR || it == LTR_OVERRIDE_CHAR } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index f0cfff4cf8..98818aba92 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -74,6 +74,9 @@ import im.vector.app.core.dialogs.ConfirmationDialogBuilder import im.vector.app.core.dialogs.GalleryOrCameraDialogHelper import im.vector.app.core.epoxy.LayoutManagerStateRestorer import im.vector.app.core.extensions.cleanup +import im.vector.app.core.extensions.containsRtLOverride +import im.vector.app.core.extensions.ensureEndsLeftToRight +import im.vector.app.core.extensions.filterDirectionOverrides import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.setTextOrHide @@ -1922,23 +1925,13 @@ class TimelineFragment @Inject constructor( } }) if (!isManaged) { - if (title.isValidUrl() && url.isValidUrl() && URL(title).host != URL(url).host) { - MaterialAlertDialogBuilder(requireActivity(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_NegativeDestructive) - .setTitle(R.string.external_link_confirmation_title) - .setMessage( - getString(R.string.external_link_confirmation_message, title, url) - .toSpannable() - .colorizeMatchingText(url, colorProvider.getColorFromAttribute(R.attr.vctr_content_tertiary)) - .colorizeMatchingText(title, colorProvider.getColorFromAttribute(R.attr.vctr_content_tertiary)) - ) - .setPositiveButton(R.string._continue) { _, _ -> - openUrlInExternalBrowser(requireContext(), url) - } - .setNegativeButton(R.string.action_cancel, null) - .show() - } else { - // Open in external browser, in a new Tab - openUrlInExternalBrowser(requireContext(), url) + when { + url.containsRtLOverride() || (title.isValidUrl() && url.isValidUrl() && URL(title).host != URL(url).host) -> { + displayUrlConfirmationDialog(title.ensureEndsLeftToRight(), url.filterDirectionOverrides()) + } + else -> { + openUrlInExternalBrowser(requireContext(), url) + } } } } @@ -1946,6 +1939,22 @@ class TimelineFragment @Inject constructor( return true } + private fun displayUrlConfirmationDialog(title: String, url: String) { + MaterialAlertDialogBuilder(requireActivity(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_NegativeDestructive) + .setTitle(R.string.external_link_confirmation_title) + .setMessage( + getString(R.string.external_link_confirmation_message, title, url) + .toSpannable() + .colorizeMatchingText(url, colorProvider.getColorFromAttribute(R.attr.vctr_content_tertiary)) + .colorizeMatchingText(title, colorProvider.getColorFromAttribute(R.attr.vctr_content_tertiary)) + ) + .setPositiveButton(R.string._continue) { _, _ -> + openUrlInExternalBrowser(requireContext(), url) + } + .setNegativeButton(R.string.action_cancel, null) + .show() + } + override fun onUrlLongClicked(url: String): Boolean { if (url != getString(R.string.edited_suffix) && url.isValidUrl()) { // Copy the url to the clipboard diff --git a/vector/src/test/java/im/vector/app/core/extensions/StringExtensionsTest.kt b/vector/src/test/java/im/vector/app/core/extensions/StringExtensionsTest.kt new file mode 100644 index 0000000000..c4c7a2d38a --- /dev/null +++ b/vector/src/test/java/im/vector/app/core/extensions/StringExtensionsTest.kt @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.core.extensions + +import org.amshove.kluent.shouldBeEqualTo +import org.junit.Test + +class StringExtensionsTest { + + @Test + fun `given text with RtL unicode override, when checking contains RtL Override, then returns true`() { + val textWithRtlOverride = "hello\u202Eworld" + + val result = textWithRtlOverride.containsRtLOverride() + + result shouldBeEqualTo true + } + + @Test + fun `given text without RtL unicode override, when checking contains RtL Override, then returns false`() { + val textWithRtlOverride = "hello world" + + val result = textWithRtlOverride.containsRtLOverride() + + result shouldBeEqualTo false + } + + @Test + fun `given text with RtL unicode override, when ensuring ends LtR, then appends a LtR unicode override`() { + val textWithRtlOverride = "123\u202E456" + + val result = textWithRtlOverride.ensureEndsLeftToRight() + + result shouldBeEqualTo "$textWithRtlOverride\u202D" + } + + @Test + fun `given text with unicode direction overrides, when filtering direction overrides, then removes all overrides`() { + val textWithDirectionOverrides = "123\u202E456\u202d789" + + val result = textWithDirectionOverrides.filterDirectionOverrides() + + result shouldBeEqualTo "123456789" + } +} From fe4abf9d78a878a45772fb07511b6aa405c9db12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olive=CC=81r=20Falvai?= Date: Thu, 26 May 2022 14:33:28 +0200 Subject: [PATCH 160/244] Add another false positive --- build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.gradle b/build.gradle index 023f7a909c..cdff79ac37 100644 --- a/build.gradle +++ b/build.gradle @@ -267,5 +267,10 @@ dependencyAnalysis { exclude("androidx.paging:paging-runtime-ktx") // False positive } } + project(":vector") { + onUnusedDependencies { + exclude("org.maplibre.gl:android-sdk", "org.maplibre.gl:android-plugin-annotation-v9") // False positives + } + } } } From 03a8289a1398b03f164d12b4b3e1d6d5fb5d73ca Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Thu, 26 May 2022 15:45:53 +0300 Subject: [PATCH 161/244] Code review fixes. --- .../im/vector/app/core/di/FragmentModule.kt | 6 ++ .../live/map/LocationLiveMapAction.kt | 5 +- .../live/map/LocationLiveMapViewFragment.kt | 57 ++++++++----------- .../live/map/LocationLiveMapViewModel.kt | 24 ++++++-- .../live/map/LocationLiveMapViewState.kt | 6 +- 5 files changed, 56 insertions(+), 42 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt index 3dba8b797b..b08f4b2e9f 100644 --- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt @@ -64,6 +64,7 @@ import im.vector.app.features.home.room.list.RoomListFragment import im.vector.app.features.home.room.threads.list.views.ThreadListFragment import im.vector.app.features.location.LocationPreviewFragment import im.vector.app.features.location.LocationSharingFragment +import im.vector.app.features.location.live.map.LocationLiveMapViewFragment import im.vector.app.features.login.LoginCaptchaFragment import im.vector.app.features.login.LoginFragment import im.vector.app.features.login.LoginGenericTextInputFormFragment @@ -1005,4 +1006,9 @@ interface FragmentModule { @IntoMap @FragmentKey(LocationPreviewFragment::class) fun bindLocationPreviewFragment(fragment: LocationPreviewFragment): Fragment + + @Binds + @IntoMap + @FragmentKey(LocationLiveMapViewFragment::class) + fun bindLocationLiveMapViewFragment(fragment: LocationLiveMapViewFragment): Fragment } diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapAction.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapAction.kt index a31e02611f..16cd3badc6 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapAction.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapAction.kt @@ -18,4 +18,7 @@ package im.vector.app.features.location.live.map import im.vector.app.core.platform.VectorViewModelAction -sealed interface LocationLiveMapAction : VectorViewModelAction +sealed class LocationLiveMapAction : VectorViewModelAction { + data class AddMapSymbol(val key: String, val value: Long) : LocationLiveMapAction() + data class RemoveMapSymbol(val key: String) : LocationLiveMapAction() +} diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt index 46c238ad12..9ade47e321 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt @@ -17,13 +17,10 @@ package im.vector.app.features.location.live.map import android.graphics.drawable.Drawable -import android.os.Bundle import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.core.graphics.drawable.toBitmap import androidx.lifecycle.lifecycleScope -import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.mapbox.mapboxsdk.geometry.LatLng @@ -36,7 +33,6 @@ import com.mapbox.mapboxsdk.maps.SupportMapFragment import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions import com.mapbox.mapboxsdk.style.layers.Property -import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.core.extensions.addChildFragment import im.vector.app.core.platform.VectorBaseFragment @@ -44,6 +40,7 @@ import im.vector.app.databinding.FragmentSimpleContainerBinding import im.vector.app.features.location.UrlMapProvider import im.vector.app.features.location.zoomToBounds import im.vector.app.features.location.zoomToLocation +import kotlinx.coroutines.launch import timber.log.Timber import java.lang.ref.WeakReference import javax.inject.Inject @@ -51,13 +48,9 @@ import javax.inject.Inject /** * Screen showing a map with all the current users sharing their live location in a room. */ -@AndroidEntryPoint -class LocationLiveMapViewFragment : VectorBaseFragment() { - - @Inject - lateinit var urlMapProvider: UrlMapProvider - - private val args: LocationLiveMapViewArgs by args() +class LocationLiveMapViewFragment @Inject constructor( + private var urlMapProvider: UrlMapProvider, +) : VectorBaseFragment() { private val viewModel: LocationLiveMapViewModel by fragmentViewModel() @@ -71,16 +64,15 @@ class LocationLiveMapViewFragment : VectorBaseFragment - lifecycleScope.launchWhenCreated { + lifecycleScope.launch { mapboxMap.setStyle(urlMapProvider.getMapUrl()) { style -> mapStyle = style this@LocationLiveMapViewFragment.mapboxMap = WeakReference(mapboxMap) @@ -108,10 +100,8 @@ class LocationLiveMapViewFragment : VectorBaseFragment) { symbolManager?.let { sManager -> val latLngBoundsBuilder = LatLngBounds.Builder() - userLiveLocations.forEach { userLocation -> createOrUpdateSymbol(userLocation, sManager) - if (isMapFirstUpdate) { val latLng = LatLng(userLocation.locationData.latitude, userLocation.locationData.longitude) latLngBoundsBuilder.include(latLng) @@ -123,10 +113,10 @@ class LocationLiveMapViewFragment : VectorBaseFragment + val symbolId = state.mapSymbolIds[userLocation.userId] - if (symbolId == null) { + if (symbolId == null || symbolManager.annotations.get(symbolId) == null) { createSymbol(userLocation, symbolManager) } else { updateSymbol(symbolId, userLocation, symbolManager) @@ -137,7 +127,7 @@ class LocationLiveMapViewFragment : VectorBaseFragment, symbolManager: SymbolManager) { - val userIdsToRemove = viewModel.mapSymbolIds.keys.subtract(userLiveLocations.map { it.userId }.toSet()) - userIdsToRemove - .mapNotNull { userId -> - removeUserPinFromMapStyle(userId) - viewModel.mapSymbolIds[userId] - viewModel.mapSymbolIds.remove(userId) - } - .forEach { symbolId -> - Timber.d("trying to delete symbol with id: $symbolId") - symbolManager.annotations.get(symbolId)?.let { - symbolManager.delete(it) - } + private fun removeOutdatedSymbols(userLiveLocations: List, symbolManager: SymbolManager) = withState(viewModel) { state -> + val userIdsToRemove = state.mapSymbolIds.keys.subtract(userLiveLocations.map { it.userId }.toSet()) + userIdsToRemove.forEach { userId -> + removeUserPinFromMapStyle(userId) + viewModel.handle(LocationLiveMapAction.RemoveMapSymbol(userId)) + + state.mapSymbolIds[userId]?.let { symbolId -> + Timber.d("trying to delete symbol with id: $symbolId") + symbolManager.annotations.get(symbolId)?.let { + symbolManager.delete(it) } + } + } } private fun updateMapZoomWhenNeeded(userLiveLocations: List, latLngBoundsBuilder: LatLngBounds.Builder) { diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt index 8c5f292f25..b14feea667 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt @@ -38,11 +38,6 @@ class LocationLiveMapViewModel @AssistedInject constructor( companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() - /** - * Map to keep track of symbol ids associated to each user Id. - */ - val mapSymbolIds = mutableMapOf() - init { getListOfUserLiveLocationUseCase.execute(initialState.roomId) .onEach { setState { copy(userLocations = it) } } @@ -50,6 +45,23 @@ class LocationLiveMapViewModel @AssistedInject constructor( } override fun handle(action: LocationLiveMapAction) { - // do nothing, no action for now + when (action) { + is LocationLiveMapAction.AddMapSymbol -> handleAddMapSymbol(action) + is LocationLiveMapAction.RemoveMapSymbol -> handleRemoveMapSymbol(action) + } + } + + private fun handleAddMapSymbol(action: LocationLiveMapAction.AddMapSymbol) = withState { state -> + val newMapSymbolIds = state.mapSymbolIds.toMutableMap().apply { set(action.key, action.value) } + setState { + copy(mapSymbolIds = newMapSymbolIds) + } + } + + private fun handleRemoveMapSymbol(action: LocationLiveMapAction.RemoveMapSymbol) = withState { state -> + val newMapSymbolIds = state.mapSymbolIds.toMutableMap().apply { remove(action.key) } + setState { + copy(mapSymbolIds = newMapSymbolIds) + } } } diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt index 9fa8635d82..6f21f71e80 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewState.kt @@ -22,7 +22,11 @@ import im.vector.app.features.location.LocationData data class LocationLiveMapViewState( val roomId: String, - val userLocations: List = emptyList() + val userLocations: List = emptyList(), + /** + * Map to keep track of symbol ids associated to each user Id. + */ + val mapSymbolIds: Map = emptyMap() ) : MavericksState { constructor(locationLiveMapViewArgs: LocationLiveMapViewArgs) : this( roomId = locationLiveMapViewArgs.roomId From c8b44bfd4cbf11fe0cd7cffadd28f6f5f537e423 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 27 May 2022 10:17:40 +0200 Subject: [PATCH 162/244] fix test post rebase --- .../internal/crypto/replayattack/ReplayAttackTest.kt | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/replayattack/ReplayAttackTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/replayattack/ReplayAttackTest.kt index 09c340a14f..53cf802b91 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/replayattack/ReplayAttackTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/replayattack/ReplayAttackTest.kt @@ -28,8 +28,7 @@ import org.junit.runners.JUnit4 import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.session.crypto.MXCryptoError -import org.matrix.android.sdk.common.CommonTestHelper -import org.matrix.android.sdk.common.CryptoTestHelper +import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest @RunWith(JUnit4::class) @FixMethodOrder(MethodSorters.JVM) @@ -37,9 +36,7 @@ import org.matrix.android.sdk.common.CryptoTestHelper class ReplayAttackTest : InstrumentedTest { @Test - fun replayAttackAlreadyDecryptedEventTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun replayAttackAlreadyDecryptedEventTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val e2eRoomID = cryptoTestData.roomId @@ -77,9 +74,7 @@ class ReplayAttackTest : InstrumentedTest { } @Test - fun replayAttackSameEventTest() { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + fun replayAttackSameEventTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper -> val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val e2eRoomID = cryptoTestData.roomId @@ -110,6 +105,5 @@ class ReplayAttackTest : InstrumentedTest { fail("Shouldn't throw a decryption error for same event") } } - cryptoTestData.cleanUp(testHelper) } } From bbef119f6241da304308056ba9d7eedaaaa3980d Mon Sep 17 00:00:00 2001 From: Anderson Ivanovich Date: Thu, 26 May 2022 08:30:21 +0000 Subject: [PATCH 163/244] Translated using Weblate (Tamil) Currently translated at 3.3% (75 of 2225 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ta/ --- vector/src/main/res/values-ta/strings.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-ta/strings.xml b/vector/src/main/res/values-ta/strings.xml index a044ce5ddd..5150c3e87b 100644 --- a/vector/src/main/res/values-ta/strings.xml +++ b/vector/src/main/res/values-ta/strings.xml @@ -1,7 +1,7 @@ %1$s அறையில் சேர்ந்துள்ளார் - • உடன் பொருந்தக்கூடிய சேவையகங்கள் இப்போது தடைசெய்யப்பட்டுள்ளன. + • IP எழுத்துக்கள் உடன் பொருந்தக்கூடிய சேவையகங்கள் இப்போது தடைசெய்யப்பட்டுள்ளன. • %s உடன் பொருந்தக்கூடிய சேவையகங்கள் இப்போது தடைசெய்யப்பட்டுள்ளன. %d சேவையக-அணுகல் கட்டுப்பாட்டுப் பட்டியல் மாற்றம் @@ -75,4 +75,7 @@ %1$s அறையை உருவாக்கியுள்ளார் உங்கள் அழைப்பிதழ் %s இன் அழைப்பிதழ் + • %s உடன் பொருந்தக்கூடிய சேவையகங்கள் அனுமதிக்கப்பட்ட பட்டியலில் இருந்து நீக்கப்பட்டுள்ளது. + • %s உடன் பொருந்தக்கூடிய சேவையகங்கள் இப்போது அனுமதிக்கப்பட்டுள்ளன. + • %s உடன் பொருந்தக்கூடிய சேவையகங்கள் தடை பட்டியலில் இருந்து நீக்கப்பட்டுள்ளது. \ No newline at end of file From ddd9749177cab437917a3646201958ee26d31f1d Mon Sep 17 00:00:00 2001 From: Anderson Ivanovich Date: Fri, 27 May 2022 07:05:01 +0000 Subject: [PATCH 164/244] Translated using Weblate (Tamil) Currently translated at 5.0% (3 of 60 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/ta/ --- .../android/ta/changelogs/40104140.txt | 2 + .../metadata/android/ta/full_description.txt | 42 +++++++++++++++++++ .../metadata/android/ta/short_description.txt | 1 + fastlane/metadata/android/ta/title.txt | 1 + 4 files changed, 46 insertions(+) create mode 100644 fastlane/metadata/android/ta/changelogs/40104140.txt create mode 100644 fastlane/metadata/android/ta/full_description.txt create mode 100644 fastlane/metadata/android/ta/short_description.txt create mode 100644 fastlane/metadata/android/ta/title.txt diff --git a/fastlane/metadata/android/ta/changelogs/40104140.txt b/fastlane/metadata/android/ta/changelogs/40104140.txt new file mode 100644 index 0000000000..f3196b57b6 --- /dev/null +++ b/fastlane/metadata/android/ta/changelogs/40104140.txt @@ -0,0 +1,2 @@ +இந்த பதிப்பில் உள்ள முதன்மை மாற்றங்கள்: தவிர்க்கப்பட்ட பயனர்களின் மேலாண்மை மேம்படுத்தப்பட்டுள்ளது. வெவ்வேறு வழுக்களைச் சரிசெய்தல் மற்றும் நிலைப்புத்தன்மையை மேம்படுத்தல். +முழு மாற்ற அறிக்கை: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ta/full_description.txt b/fastlane/metadata/android/ta/full_description.txt new file mode 100644 index 0000000000..9aa693bda2 --- /dev/null +++ b/fastlane/metadata/android/ta/full_description.txt @@ -0,0 +1,42 @@ +Element is both a secure messenger and a productivity team collaboration app that is ideal for group chats while remote working. This chat app uses end-to-end encryption to provide powerful video conferencing, file sharing and voice calls. + +Element இன் தனிச்சிறப்புகளுள் சில: +- மேம்பட்ட இயங்கலை தொடர்பு கருவிகள் +- தொலைநிலையில் உள்ள ஊழியர்களுக்கும், பாதுகாப்பான நிறும கருத்து பரிமாற்றங்களை அனுமதிப்பதற்காக, முழுவதுமாக மறைகுறியாக்கப்பட்ட செய்திகள் +- MATRIX திறந்த மூல கட்டமைப்பை அடிப்படையாக கொண்டு செயல்படும் அதிகாரப்பரவலாக்கப்பட்ட அரட்டை +- செயல்திட்டங்களை மேலாண்மை செய்யும் போது, மறைகுறியாக்கப்பட்ட தரவுடன் கூடிய பாதுகாப்பான கோப்பு பகிரல் +- IP மூலம் குரல் (VoIP) மற்றும் திரை பகிரல் உடன் கூடிய குரல் அரட்டைகள் +- உங்கள் மனம் கவர்ந்த இயங்கலை உடனிணைவு கருவிகள், செயல்திட்ட மேலாண்மை கருவிகள், VoIP சேவைகள் மற்றும் இதர குழு தூதுரை செயலிகள் உடன் கூடிய எளிமையான ஒருமைப்பாடு + +Element is completely different from other messaging and collaboration apps. It operates on Matrix, an open network for secure messaging and decentralized communication. It allows self-hosting to give users maximum ownership and control of their data and messages. + +தனியுரிமை மற்றும் மறைகுறியாக்கப்பட்ட செய்தி அனுப்பல் +தேவையில்லாத விளம்பரங்கள், தரவு சுரண்டல் மற்றும் தகவல் கட்டுப்பாடு போன்றவற்றில் இருந்து Element உங்களை பாதுகாக்கிறது. மேலும், இது முனைக்கு-முனை மறைகுறியாக்கம் மற்றும் குறுக்கு-ஒப்பமிடப்பட்ட சாதன சரிபார்ப்பு ஆகியவற்றின் மூலம் உங்கள் எல்லா தரவுகள், ஒன்றுக்கொன்றான காணொளி மற்றும் குரல் அழைப்புகளை பாதுகாக்கிறது. + +Element gives you control over your privacy while allowing you to communicate securely with யாரோனும் ஒருவருடன் on the Matrix network, or other business collaboration tools by integrating with apps such as Slack. + +Element can be self-hosted +To allow more control of your sensitive data and conversations, Element can be self-hosted or you can choose any Matrix-based host - the standard for open source, decentralized communication. Element gives you privacy, security compliance and integration flexibility. + +உங்கள் தரவைச் சொந்தமாக்கிக் கொள்ளுங்கள் +தரவுகள் மற்றும் செய்திகளை எங்கு சேமித்து வைக்க வேண்டும் என்பதை நீங்கள் முடிவு செய்கிறீர்கள். இதன்மூலம், தரவு சுரண்டல் மற்றும் மூன்றாம் தரப்பினர் அனுகல் ஆகிய இடர்களை தவிர்க்கலாம். + +Element வெவ்வேறு வகையில் கட்டுப்பாட்டை உங்களிடம் அளிக்கிறது: +1. Get a free account on the matrix.org public server hosted by the Matrix developers, or choose from thousands of public servers hosted by volunteers +2. Self-host your account by running a server on your own IT infrastructure +3. Sign up for an account on a custom server by simply subscribing to the Element Matrix Services hosting platform + +திறந்த செய்தி அனுப்பல் மற்றும் ஒருமைப்பாடு +You can chat with anyone on the Matrix network, whether they’re using Element, another Matrix app or even if they are using a different messaging app. + +மிகவும் பாதுகாப்பானது +உண்மையான முனைக்கு-முனை மறைகுறியாக்கம் (உரையாடலில் உள்ளவர்கள் மட்டுமே மறைகுறியாக்கத்தை நீக்கி செய்தியை காண இயலும்) மற்றும் குறுக்கு-ஒப்பமிடப்பட்ட சாதன சரிபார்ப்பு. + +முழுமையான தொடர்பு மற்றும் ஒருமைப்பாடு +செய்தி அனுப்பல், காணொளி மற்றும் குரல் அழைப்புகளை, கோப்பு பகிரல், திரை பகிரல் மற்றும் ஒருமைப்பாடுகள், இயலிகள் மற்றும் நிரல் பலகைகளின் மொத்த கொத்து. அறைகள், குழுக்களை உருவாக்கி, அவர்களுடன் உரையாடி, வேலையை எளிமையாக்கவும். + +எங்கு விட்டு சென்றீர்களோ அதிலிருந்த துவங்கவும் +Stay in touch wherever you are with fully synchronised message history across all your devices and on the web at https://app.element.io + +திறந்த மூலம் +Element Android ஒரு திறந்த மூல செயல் திட்டமாகும். இது GitHub இல் தொகுத்து வழங்கப்பட்டுள்ளது. வழுக்கள் ஏதேனும் கண்டறிந்தால் மற்றும்/அல்லது இதன் வளர்ச்சிக்கு பங்களிக்க விரும்பினால், https://github.com/vector-im/element-android என்னும் தளத்திற்கு வருகை தரவும். diff --git a/fastlane/metadata/android/ta/short_description.txt b/fastlane/metadata/android/ta/short_description.txt new file mode 100644 index 0000000000..9c7afb2a37 --- /dev/null +++ b/fastlane/metadata/android/ta/short_description.txt @@ -0,0 +1 @@ +மறைகுறியாக்கப்பட்ட செய்தி அனுப்பல், குழு அரட்டை மற்றும் காணொளி அழைப்புகள் diff --git a/fastlane/metadata/android/ta/title.txt b/fastlane/metadata/android/ta/title.txt new file mode 100644 index 0000000000..ecb9a01c06 --- /dev/null +++ b/fastlane/metadata/android/ta/title.txt @@ -0,0 +1 @@ +Element - பாதுகாப்பான தூதுரை சேவை From 1d36269b03f22db6b6b9e1195b3df04753a1a484 Mon Sep 17 00:00:00 2001 From: ariskotsomitopoulos Date: Fri, 27 May 2022 13:40:53 +0300 Subject: [PATCH 165/244] Fix wrong rendered vector icon --- .../ic_thread_view_in_room_menu_item.xml | 30 ------------------- .../drawable/ic_threads_view_in_room_24.xml | 22 ++++++++++++++ vector/src/main/res/menu/menu_timeline.xml | 2 +- 3 files changed, 23 insertions(+), 31 deletions(-) delete mode 100644 vector/src/main/res/drawable/ic_thread_view_in_room_menu_item.xml create mode 100644 vector/src/main/res/drawable/ic_threads_view_in_room_24.xml diff --git a/vector/src/main/res/drawable/ic_thread_view_in_room_menu_item.xml b/vector/src/main/res/drawable/ic_thread_view_in_room_menu_item.xml deleted file mode 100644 index f408f99713..0000000000 --- a/vector/src/main/res/drawable/ic_thread_view_in_room_menu_item.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - diff --git a/vector/src/main/res/drawable/ic_threads_view_in_room_24.xml b/vector/src/main/res/drawable/ic_threads_view_in_room_24.xml new file mode 100644 index 0000000000..4b73f5c389 --- /dev/null +++ b/vector/src/main/res/drawable/ic_threads_view_in_room_24.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/vector/src/main/res/menu/menu_timeline.xml b/vector/src/main/res/menu/menu_timeline.xml index 8b1ea02a4a..5c35540932 100644 --- a/vector/src/main/res/menu/menu_timeline.xml +++ b/vector/src/main/res/menu/menu_timeline.xml @@ -72,7 +72,7 @@ From 21225b8a284817dcd2657eaa09ca281db7f3e17a Mon Sep 17 00:00:00 2001 From: ariskotsomitopoulos Date: Fri, 27 May 2022 13:56:52 +0300 Subject: [PATCH 166/244] Replace old drawable from --- .../home/room/detail/timeline/action/EventSharedAction.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/EventSharedAction.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/EventSharedAction.kt index 5f12c2f174..e3b10ef8c6 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/EventSharedAction.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/EventSharedAction.kt @@ -52,7 +52,7 @@ sealed class EventSharedAction(@StringRes val titleRes: Int, EventSharedAction(R.string.reply_in_thread, R.drawable.ic_reply_in_thread) object ViewInRoom : - EventSharedAction(R.string.view_in_room, R.drawable.ic_thread_view_in_room_menu_item) + EventSharedAction(R.string.view_in_room, R.drawable.ic_threads_view_in_room_24) data class Share(val eventId: String, val messageContent: MessageContent) : EventSharedAction(R.string.action_share, R.drawable.ic_share) From 453aa28380b688a75f6ef184d92f532eeb4ea97f Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Fri, 27 May 2022 15:25:59 +0300 Subject: [PATCH 167/244] Add required resources. --- .../src/main/res/values/styles_location.xml | 22 +++++++++++++++++++ vector/sampledata/live_location_users.json | 14 ++++++++++++ .../bg_live_location_users_bottom_sheet.xml | 8 +++++++ .../res/drawable/ic_bottom_sheet_handle.xml | 6 +++++ vector/src/main/res/values/strings.xml | 2 ++ 5 files changed, 52 insertions(+) create mode 100644 vector/sampledata/live_location_users.json create mode 100644 vector/src/main/res/drawable/bg_live_location_users_bottom_sheet.xml create mode 100644 vector/src/main/res/drawable/ic_bottom_sheet_handle.xml diff --git a/library/ui-styles/src/main/res/values/styles_location.xml b/library/ui-styles/src/main/res/values/styles_location.xml index 7571265241..9d9fc862f6 100644 --- a/library/ui-styles/src/main/res/values/styles_location.xml +++ b/library/ui-styles/src/main/res/values/styles_location.xml @@ -18,4 +18,26 @@ center + + + + + + + + diff --git a/vector/sampledata/live_location_users.json b/vector/sampledata/live_location_users.json new file mode 100644 index 0000000000..58d0fb5fa1 --- /dev/null +++ b/vector/sampledata/live_location_users.json @@ -0,0 +1,14 @@ +{ + "data": [ + { + "displayName": "Amandine", + "remainingTime": "9min left", + "lastUpdatedAt": "Updated 12min ago" + }, + { + "displayName": "You", + "remainingTime": "19min left", + "lastUpdatedAt": "Updated 1min ago" + } + ] +} diff --git a/vector/src/main/res/drawable/bg_live_location_users_bottom_sheet.xml b/vector/src/main/res/drawable/bg_live_location_users_bottom_sheet.xml new file mode 100644 index 0000000000..e6012ebe42 --- /dev/null +++ b/vector/src/main/res/drawable/bg_live_location_users_bottom_sheet.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/vector/src/main/res/drawable/ic_bottom_sheet_handle.xml b/vector/src/main/res/drawable/ic_bottom_sheet_handle.xml new file mode 100644 index 0000000000..fe3c93497b --- /dev/null +++ b/vector/src/main/res/drawable/ic_bottom_sheet_handle.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 63d4730dc5..c5bdb5694b 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -3037,6 +3037,8 @@ Location sharing is in progress Enable Live Location Sharing Temporary implementation: locations persist in room history + Stop sharing + Updated %1$s ago Show Message bubbles From 88de113a4e4cfd77e4464edbdddda52da0f6c5ea Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Fri, 27 May 2022 15:26:40 +0300 Subject: [PATCH 168/244] Add bottom sheet layout. --- .../fragment_location_live_map_view.xml | 46 ++++++++++++++ .../item_live_location_users_bottom_sheet.xml | 60 +++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 vector/src/main/res/layout/fragment_location_live_map_view.xml create mode 100644 vector/src/main/res/layout/item_live_location_users_bottom_sheet.xml diff --git a/vector/src/main/res/layout/fragment_location_live_map_view.xml b/vector/src/main/res/layout/fragment_location_live_map_view.xml new file mode 100644 index 0000000000..05990744c6 --- /dev/null +++ b/vector/src/main/res/layout/fragment_location_live_map_view.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + diff --git a/vector/src/main/res/layout/item_live_location_users_bottom_sheet.xml b/vector/src/main/res/layout/item_live_location_users_bottom_sheet.xml new file mode 100644 index 0000000000..318db3feb5 --- /dev/null +++ b/vector/src/main/res/layout/item_live_location_users_bottom_sheet.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + +