mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 10:25:35 +03:00
Merge branch 'develop' into feature/ons/live_location_service
* develop: (152 commits) Remove exhaustive. fixing the onboarding sanity test failing - adds tapping the new take me home button within the sanity test Fix lint issues on weblate sync fixing view model tests not collecting flow results - the switch from runBlockingTest to runTest means we need to provide a separate scope from the test in order to asynchronously collect the flow results Do not suggest collapse if there is only one section Translated using Weblate (Spanish) Translated using Weblate (Spanish) runBlocking -> runTest https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-test/MIGRATION.md runBlockingTest -> runTest https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-test/MIGRATION.md Small cleanup The `.exhaustive` trick is not needed anymore in Kotlin 1.6.0 https://kotlinlang.org/docs/whatsnew16.html#stable-exhaustive-when-statements-for-enum-sealed-and-boolean-subjects Also upgrade the coroutine lib Fix compilation warning (exhaustive when) Fix compilation warning (exhaustive when) Format file (no other change) Fix compilation warning (exhaustive when) Bump moshi from 1.12.0 to 1.13.0 Bump kotlin-gradle-plugin from 1.5.31 to 1.6.0 Code review fixes. fixing presence icon anchoring to the middle of the room icon - creates a secondary verification shield and aligns to the start of the room title when presence is present ... # Conflicts: # vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt # vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt # vector/src/main/res/values/strings.xml
This commit is contained in:
commit
f18a107df8
260 changed files with 3817 additions and 1446 deletions
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
|
@ -26,7 +26,7 @@ jobs:
|
|||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
|
@ -50,7 +50,7 @@ jobs:
|
|||
# Only runs on main, no concurrency.
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
|
|
17
.github/workflows/nightly.yml
vendored
17
.github/workflows/nightly.yml
vendored
|
@ -34,7 +34,7 @@ jobs:
|
|||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: 3.8
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
|
@ -43,7 +43,7 @@ jobs:
|
|||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Start synapse server
|
||||
uses: michaelkaye/setup-matrix-synapse@v0.3.0
|
||||
uses: michaelkaye/setup-matrix-synapse@v0.4.0
|
||||
with:
|
||||
uploadLogs: true
|
||||
httpPort: 8080
|
||||
|
@ -221,7 +221,7 @@ jobs:
|
|||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: 3.8
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
|
@ -230,7 +230,7 @@ jobs:
|
|||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Start synapse server
|
||||
uses: michaelkaye/setup-matrix-synapse@v0.3.0
|
||||
uses: michaelkaye/setup-matrix-synapse@v0.4.0
|
||||
with:
|
||||
uploadLogs: true
|
||||
httpPort: 8080
|
||||
|
@ -265,6 +265,7 @@ jobs:
|
|||
failure_screenshots/
|
||||
|
||||
codecov-units:
|
||||
name: Unit tests with code coverage
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
@ -272,7 +273,7 @@ jobs:
|
|||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
|
@ -290,6 +291,7 @@ jobs:
|
|||
build/reports/jacoco/allCodeCoverageReport/allCodeCoverageReport.xml
|
||||
|
||||
sonarqube:
|
||||
name: Sonarqube upload
|
||||
runs-on: macos-latest
|
||||
if: always()
|
||||
needs:
|
||||
|
@ -300,7 +302,7 @@ jobs:
|
|||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
|
@ -319,6 +321,7 @@ jobs:
|
|||
|
||||
# Notify the channel about scheduled runs, do not notify for manually triggered runs
|
||||
notify:
|
||||
name: Notify matrix
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- integration-tests
|
||||
|
@ -333,4 +336,4 @@ jobs:
|
|||
matrix_access_token: ${{ secrets.ELEMENT_ANDROID_NOTIFICATION_ACCESS_TOKEN }}
|
||||
matrix_room_id: ${{ secrets.ELEMENT_ANDROID_INTERNAL_ROOM_ID }}
|
||||
text_template: "Nightly test run: {{#each job_statuses }}{{#with this }}{{#if completed }} {{name}} {{conclusion}} at {{completed_at}}, {{/if}}{{/with}}{{/each}}"
|
||||
html_template: "Nightly test run results: {{#each job_statuses }}{{#with this }}{{#if completed }}<br />{{name}} {{conclusion}} at {{completed_at}} <a href=\"{{html_url}}\">[details]</a>{{/if}}{{/with}}{{/each}}"
|
||||
html_template: "Nightly test run results: {{#each job_statuses }}{{#with this }}{{#if completed }}<br />{{icon conclusion}} {{name}} <font color='{{color conclusion}}'>{{conclusion}} at {{completed_at}} <a href=\"{{html_url}}\">[details]</a></font>{{/if}}{{/with}}{{/each}}"
|
||||
|
|
4
.github/workflows/quality.yml
vendored
4
.github/workflows/quality.yml
vendored
|
@ -97,7 +97,7 @@ jobs:
|
|||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
|
@ -130,7 +130,7 @@ jobs:
|
|||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
|
|
4
.github/workflows/tests.yml
vendored
4
.github/workflows/tests.yml
vendored
|
@ -25,7 +25,7 @@ jobs:
|
|||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: 11
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
|
@ -45,7 +45,7 @@ jobs:
|
|||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
|
|
1
changelog.d/5347.misc
Normal file
1
changelog.d/5347.misc
Normal file
|
@ -0,0 +1 @@
|
|||
[Rooms list] Do not suggest collapse the unique section
|
1
changelog.d/5408.misc
Normal file
1
changelog.d/5408.misc
Normal file
|
@ -0,0 +1 @@
|
|||
Improved onboarding registration unit test coverage
|
1
changelog.d/5426.feature
Normal file
1
changelog.d/5426.feature
Normal file
|
@ -0,0 +1 @@
|
|||
Allow scrolling position of Voice Message playback
|
1
changelog.d/5489.bugfix
Normal file
1
changelog.d/5489.bugfix
Normal file
|
@ -0,0 +1 @@
|
|||
Fix presence indicator being aligned to the center of the room image
|
1
changelog.d/5513.misc
Normal file
1
changelog.d/5513.misc
Normal file
|
@ -0,0 +1 @@
|
|||
Added online presence indicator attribute online to match offline styling
|
1
changelog.d/5551.bugfix
Normal file
1
changelog.d/5551.bugfix
Normal file
|
@ -0,0 +1 @@
|
|||
Fix local echos not being shown when re-opening rooms
|
1
changelog.d/5564.bugfix
Normal file
1
changelog.d/5564.bugfix
Normal file
|
@ -0,0 +1 @@
|
|||
Fix sometimes read marker not properly updating
|
1
changelog.d/5571.feature
Normal file
1
changelog.d/5571.feature
Normal file
|
@ -0,0 +1 @@
|
|||
Live location sharing: Adding indicator view when enabled
|
2
changelog.d/5572.misc
Normal file
2
changelog.d/5572.misc
Normal file
|
@ -0,0 +1,2 @@
|
|||
Show stickers on click
|
||||
|
|
@ -9,13 +9,13 @@ ext.versions = [
|
|||
|
||||
def gradle = "7.0.4"
|
||||
// Ref: https://kotlinlang.org/releases.html
|
||||
def kotlin = "1.5.31"
|
||||
def kotlinCoroutines = "1.5.2"
|
||||
def kotlin = "1.6.0"
|
||||
def kotlinCoroutines = "1.6.0"
|
||||
def dagger = "2.40.5"
|
||||
def retrofit = "2.9.0"
|
||||
def arrow = "0.8.2"
|
||||
def markwon = "4.6.2"
|
||||
def moshi = "1.12.0"
|
||||
def moshi = "1.13.0"
|
||||
def lifecycle = "2.4.0"
|
||||
def flowBinding = "1.2.0"
|
||||
def epoxy = "4.6.2"
|
||||
|
|
2
fastlane/metadata/android/es-ES/changelogs/40104000.txt
Normal file
2
fastlane/metadata/android/es-ES/changelogs/40104000.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Principales cambios de esta versión: primera implementación de los hilos de mensajes. Burbujas de mensajes.
|
||||
Todos los cambios en: https://github.com/vector-im/element-android/releases/tag/v1.4.0
|
2
fastlane/metadata/android/es-ES/changelogs/40104020.txt
Normal file
2
fastlane/metadata/android/es-ES/changelogs/40104020.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Principales cambios de esta versión: añadir @room, encuestas cerradas y muchos cambios menores más.
|
||||
Todos los cambios en: https://github.com/vector-im/element-android/releases/tag/v1.4.2
|
2
fastlane/metadata/android/fa/changelogs/40104000.txt
Normal file
2
fastlane/metadata/android/fa/changelogs/40104000.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
تغییرات اصلی در این نگارش: پیاده سازی نخستین پیامهای رشتهای. حبابهای پیام.
|
||||
گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.4.0
|
2
fastlane/metadata/android/fa/changelogs/40104020.txt
Normal file
2
fastlane/metadata/android/fa/changelogs/40104020.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
تغییرات اصلی در این نگارش: افزودن پشتیبانی به @room و نظرسنجیهای فاش نشده در کنار تغییرات کوچک دیگر.
|
||||
گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.4.2
|
|
@ -8,12 +8,13 @@ Az Element egy biztonságos üzenetküldő, és egy csapatmunka app, amely távo
|
|||
- Videochat, VoIP, és képernyőmegosztási lehetőséggel
|
||||
- Egyszerű integráció a kedvenc online kollaborációs eszközeiddel, projektkezelési eszközökkel, VoIP szolgáltatásokkal, és más csoportos üzenetküldő alkalmazásokkal
|
||||
|
||||
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.
|
||||
Az Element teljesen más, mint az összes többi üzenetküldő és kollaborációs alkalmazás. A biztonságos üzenetküldést és decentralizált kommunikációt biztosító Matrix platformot használja. Akár egyénileg üzemeltetett szervereket is lehet használni az adatok teljes kontrollálása érdekében.
|
||||
|
||||
<b>Privacy and encrypted messaging</b>
|
||||
Element protects you from unwanted ads, data mining and walled gardens. It also secures all your data, one-to-one video and voice communication through end-to-end encryption and cross-signed device verification.
|
||||
<b>Magánszféra és titkosított csevegés</b>
|
||||
Az Element megvéd a nemkívánatos hirdetésektől, adatbányászattól, és a zárt platformoktól. Ezeken felül biztonságban tartja az összes adatod és 1:1 hívásod a végponti titkosításnak és az eszközök-közti hitelesítésnek köszönhetően.
|
||||
|
||||
Az Element átadja neked az irányítást a magánszférád felett, miközben lehetővé teszi, hogy biztonságosan kommunikálj bárkivel a Matrix hálózatban, vagy a többi üzleti kommunikációs eszközt használókkal, az olyan appok integrálásának köszönhetően, mint például a Slack.
|
||||
|
||||
Element gives you control over your privacy while allowing you to communicate securely with anyone on the Matrix network, or other business collaboration tools by integrating with apps such as Slack.
|
||||
|
||||
<b>Element can be self-hosted</b>
|
||||
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.
|
||||
|
|
2
fastlane/metadata/android/ru-RU/changelogs/40104000.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/40104000.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Основные изменения в этой версии: Начальная реализация веток сообщений. Сообщения пузыри.
|
||||
Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.4.0
|
2
fastlane/metadata/android/ru-RU/changelogs/40104020.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/40104020.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Основные изменения в этой версии: добавлена поддержка @room и нераскрытых опросов, а также множество других мелких изменений.
|
||||
Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.4.2
|
|
@ -59,7 +59,7 @@ dependencies {
|
|||
implementation libs.jetbrains.coroutinesCore
|
||||
implementation libs.jetbrains.coroutinesAndroid
|
||||
|
||||
testImplementation 'org.json:json:20211205'
|
||||
testImplementation 'org.json:json:20220320'
|
||||
testImplementation libs.tests.junit
|
||||
androidTestImplementation libs.androidx.junit
|
||||
androidTestImplementation libs.androidx.espressoCore
|
||||
|
|
|
@ -20,7 +20,6 @@ import android.content.Context
|
|||
import android.view.View
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Success
|
||||
import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
|
||||
import me.gujun.android.span.Span
|
||||
import me.gujun.android.span.span
|
||||
|
@ -44,10 +43,8 @@ internal class JSonViewerEpoxyController(private val context: Context) :
|
|||
text(async.error.localizedMessage?.toEpoxyCharSequence())
|
||||
}
|
||||
}
|
||||
is Success -> {
|
||||
val model = data.root.invoke()
|
||||
|
||||
model?.let {
|
||||
else -> {
|
||||
async.invoke()?.let {
|
||||
buildRec(it, 0, "")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,4 @@ dependencies {
|
|||
implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta12'
|
||||
// dialpad dimen
|
||||
implementation 'im.dlg:android-dialer:1.2.5'
|
||||
// AudioRecordView attr
|
||||
implementation 'com.github.Armen101:AudioRecordView:1.0.5'
|
||||
}
|
|
@ -122,6 +122,10 @@
|
|||
<color name="vctr_presence_indicator_offline_light">@color/palette_gray_100</color>
|
||||
<color name="vctr_presence_indicator_offline_dark">@color/palette_gray_450</color>
|
||||
|
||||
<attr name="vctr_presence_indicator_online" format="color" />
|
||||
<color name="vctr_presence_indicator_online_light">@color/palette_element_green</color>
|
||||
<color name="vctr_presence_indicator_online_dark">@color/palette_element_green</color>
|
||||
|
||||
<!-- Location sharing colors -->
|
||||
<attr name="vctr_live_location" format="color" />
|
||||
<color name="vctr_live_location_light">@color/palette_prune</color>
|
||||
|
|
|
@ -53,5 +53,4 @@
|
|||
<color name="element_room_01">@color/palette_verde</color>
|
||||
<color name="element_room_02">@color/palette_azure</color>
|
||||
<color name="element_room_03">@color/palette_grape</color>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="AudioWaveformView">
|
||||
|
||||
<attr name="alignment" format="enum">
|
||||
<enum name="center" value="0" />
|
||||
<enum name="bottom" value="1" />
|
||||
<enum name="top" value="2" />
|
||||
</attr>
|
||||
<attr name="flow" format="enum">
|
||||
<enum name="leftToRight" value="0" />
|
||||
<enum name="rightToLeft" value="1" />
|
||||
</attr>
|
||||
<attr name="verticalPadding" format="dimension" />
|
||||
<attr name="horizontalPadding" format="dimension" />
|
||||
|
||||
<attr name="barWidth" format="dimension" />
|
||||
<attr name="barSpace" format="dimension" />
|
||||
<attr name="barMinHeight" format="dimension" />
|
||||
<attr name="isBarRounded" format="boolean" />
|
||||
</declare-styleable>
|
||||
</resources>
|
11
library/ui-styles/src/main/res/values/styles_location.xml
Normal file
11
library/ui-styles/src/main/res/values/styles_location.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Widget.Vector.Button.Text.OnPrimary.LocationLive">
|
||||
<item name="android:background">?selectableItemBackground</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
<item name="android:padding">0dp</item>
|
||||
<item name="android:gravity">center</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -2,14 +2,14 @@
|
|||
<resources>
|
||||
|
||||
<style name="VoicePlaybackWaveform">
|
||||
<item name="chunkColor">?vctr_content_secondary</item>
|
||||
<item name="chunkAlignTo">center</item>
|
||||
<item name="chunkMinHeight">1dp</item>
|
||||
<item name="chunkRoundedCorners">true</item>
|
||||
<item name="chunkSoftTransition">true</item>
|
||||
<item name="chunkSpace">2dp</item>
|
||||
<item name="chunkWidth">2dp</item>
|
||||
<item name="direction">rightToLeft</item>
|
||||
<item name="alignment">center</item>
|
||||
<item name="flow">leftToRight</item>
|
||||
<item name="verticalPadding">4dp</item>
|
||||
<item name="horizontalPadding">4dp</item>
|
||||
<item name="barWidth">2dp</item>
|
||||
<item name="barSpace">2dp</item>
|
||||
<item name="barMinHeight">1dp</item>
|
||||
<item name="isBarRounded">true</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
<!-- Presence Indicator colors -->
|
||||
<item name="vctr_presence_indicator_offline">@color/vctr_presence_indicator_offline_dark</item>
|
||||
<item name="vctr_presence_indicator_online">@color/vctr_presence_indicator_online_dark</item>
|
||||
|
||||
<!-- Some aliases -->
|
||||
<item name="vctr_header_background">?vctr_system</item>
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
<!-- Presence Indicator colors -->
|
||||
<item name="vctr_presence_indicator_offline">@color/vctr_presence_indicator_offline_light</item>
|
||||
<item name="vctr_presence_indicator_online">@color/vctr_presence_indicator_online_light</item>
|
||||
|
||||
<!-- Some aliases -->
|
||||
<item name="vctr_header_background">?vctr_system</item>
|
||||
|
|
|
@ -64,7 +64,11 @@ data class MatrixConfiguration(
|
|||
/**
|
||||
* True to enable presence information sync (if available). False to disable regardless of server setting.
|
||||
*/
|
||||
val presenceSyncEnabled: Boolean = true
|
||||
val presenceSyncEnabled: Boolean = true,
|
||||
/**
|
||||
* Thread messages default enable/disabled value
|
||||
*/
|
||||
val threadMessagesEnabledDefault: Boolean = false,
|
||||
) {
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64Safe
|
|||
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
||||
import org.matrix.android.sdk.internal.crypto.verification.DefaultVerificationTransaction
|
||||
import org.matrix.android.sdk.internal.crypto.verification.ValidVerificationInfoStart
|
||||
import org.matrix.android.sdk.internal.util.exhaustive
|
||||
import timber.log.Timber
|
||||
|
||||
internal class DefaultQrCodeVerificationTransaction(
|
||||
|
@ -129,7 +128,7 @@ internal class DefaultQrCodeVerificationTransaction(
|
|||
// Nothing special here, we will send a reciprocate start event, and then the other session will trust it's view of the MSK
|
||||
}
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
val toVerifyDeviceIds = mutableListOf<String>()
|
||||
|
||||
|
@ -174,7 +173,7 @@ internal class DefaultQrCodeVerificationTransaction(
|
|||
Unit
|
||||
}
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
if (!canTrustOtherUserMasterKey && toVerifyDeviceIds.isEmpty()) {
|
||||
// Nothing to verify
|
||||
|
@ -272,6 +271,7 @@ internal class DefaultQrCodeVerificationTransaction(
|
|||
// I now know that i can trust my MSK
|
||||
trust(true, emptyList(), true)
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,15 +19,19 @@ package org.matrix.android.sdk.internal.database.lightweight
|
|||
import android.content.Context
|
||||
import androidx.core.content.edit
|
||||
import androidx.preference.PreferenceManager
|
||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* The purpose of this class is to provide an alternative and lightweight way to store settings/data
|
||||
* on the sdi without using the database. This should be used just for sdk/user preferences and
|
||||
* on the sdk without using the database. This should be used just for sdk/user preferences and
|
||||
* not for large data sets
|
||||
*/
|
||||
|
||||
class LightweightSettingsStorage @Inject constructor(context: Context) {
|
||||
class LightweightSettingsStorage @Inject constructor(
|
||||
context: Context,
|
||||
private val matrixConfiguration: MatrixConfiguration
|
||||
) {
|
||||
|
||||
private val sdkDefaultPrefs = PreferenceManager.getDefaultSharedPreferences(context.applicationContext)
|
||||
|
||||
|
@ -38,7 +42,7 @@ class LightweightSettingsStorage @Inject constructor(context: Context) {
|
|||
}
|
||||
|
||||
fun areThreadMessagesEnabled(): Boolean {
|
||||
return sdkDefaultPrefs.getBoolean(MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED, false)
|
||||
return sdkDefaultPrefs.getBoolean(MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED, matrixConfiguration.threadMessagesEnabledDefault)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -80,8 +80,8 @@ internal class WorkManagerProvider @Inject constructor(
|
|||
workManager.enqueue(checkWorkerRequest)
|
||||
val checkWorkerLiveState = workManager.getWorkInfoByIdLiveData(checkWorkerRequest.id)
|
||||
val observer = object : Observer<WorkInfo> {
|
||||
override fun onChanged(workInfo: WorkInfo) {
|
||||
if (workInfo.state.isFinished) {
|
||||
override fun onChanged(workInfo: WorkInfo?) {
|
||||
if (workInfo?.state?.isFinished == true) {
|
||||
checkWorkerLiveState.removeObserver(this)
|
||||
if (workInfo.state == WorkInfo.State.FAILED) {
|
||||
throw RuntimeException("MatrixWorkerFactory is not being set on your worker configuration.\n" +
|
||||
|
|
|
@ -44,7 +44,7 @@ internal interface FetchThreadSummariesTask : Task<FetchThreadSummariesTask.Para
|
|||
data class Params(
|
||||
val roomId: String,
|
||||
val from: String = "",
|
||||
val limit: Int = 100,
|
||||
val limit: Int = 500,
|
||||
val isUserParticipating: Boolean = true
|
||||
)
|
||||
}
|
||||
|
|
|
@ -314,6 +314,7 @@ internal class RoomSummaryDataSource @Inject constructor(
|
|||
RoomCategoryFilter.ONLY_ROOMS -> query.equalTo(RoomSummaryEntityFields.IS_DIRECT, false)
|
||||
RoomCategoryFilter.ONLY_WITH_NOTIFICATIONS -> query.greaterThan(RoomSummaryEntityFields.NOTIFICATION_COUNT, 0)
|
||||
RoomCategoryFilter.ALL -> Unit // nop
|
||||
null -> Unit
|
||||
}
|
||||
|
||||
// Timber.w("VAL: activeSpaceId : ${queryParams.activeSpaceId}")
|
||||
|
|
|
@ -55,6 +55,7 @@ internal class RealmSendingEventsDataSource(
|
|||
roomEntity = RoomEntity.where(safeRealm, roomId = roomId).findFirst()
|
||||
sendingTimelineEvents = roomEntity?.sendingTimelineEvents
|
||||
sendingTimelineEvents?.addChangeListener(sendingTimelineEventsListener)
|
||||
updateFrozenResults(sendingTimelineEvents)
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
|
|
|
@ -83,11 +83,15 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity,
|
|||
isLastBackward.set(chunkEntity.isLastBackward)
|
||||
}
|
||||
if (changeSet.isFieldChanged(ChunkEntityFields.NEXT_CHUNK.`$`)) {
|
||||
nextChunk = createTimelineChunk(chunkEntity.nextChunk)
|
||||
nextChunk = createTimelineChunk(chunkEntity.nextChunk).also {
|
||||
it?.prevChunk = this
|
||||
}
|
||||
nextChunkLatch?.complete(Unit)
|
||||
}
|
||||
if (changeSet.isFieldChanged(ChunkEntityFields.PREV_CHUNK.`$`)) {
|
||||
prevChunk = createTimelineChunk(chunkEntity.prevChunk)
|
||||
prevChunk = createTimelineChunk(chunkEntity.prevChunk).also {
|
||||
it?.nextChunk = this
|
||||
}
|
||||
prevChunkLatch?.complete(Unit)
|
||||
}
|
||||
}
|
||||
|
@ -194,7 +198,9 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity,
|
|||
when {
|
||||
nextChunkEntity != null -> {
|
||||
if (nextChunk == null) {
|
||||
nextChunk = createTimelineChunk(nextChunkEntity)
|
||||
nextChunk = createTimelineChunk(nextChunkEntity).also {
|
||||
it?.prevChunk = this
|
||||
}
|
||||
}
|
||||
nextChunk?.loadMore(offsetCount, direction, fetchFromServerIfNeeded) ?: LoadMoreResult.FAILURE
|
||||
}
|
||||
|
@ -210,7 +216,9 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity,
|
|||
when {
|
||||
prevChunkEntity != null -> {
|
||||
if (prevChunk == null) {
|
||||
prevChunk = createTimelineChunk(prevChunkEntity)
|
||||
prevChunk = createTimelineChunk(prevChunkEntity).also {
|
||||
it?.nextChunk = this
|
||||
}
|
||||
}
|
||||
prevChunk?.loadMore(offsetCount, direction, fetchFromServerIfNeeded) ?: LoadMoreResult.FAILURE
|
||||
}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* Copyright 2020 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.util
|
||||
|
||||
// Trick to ensure that when block is exhaustive
|
||||
internal val <T> T.exhaustive: T get() = this
|
|
@ -16,7 +16,8 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.session.pushers
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.amshove.kluent.internal.assertFailsWith
|
||||
import org.amshove.kluent.shouldBeEqualTo
|
||||
import org.junit.Test
|
||||
|
@ -39,6 +40,7 @@ private val A_JSON_PUSHER = JsonPusher(
|
|||
data = JsonPusherData(brand = "Element")
|
||||
)
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
class DefaultAddPusherTaskTest {
|
||||
|
||||
private val pushersAPI = FakePushersAPI()
|
||||
|
@ -55,7 +57,7 @@ class DefaultAddPusherTaskTest {
|
|||
fun `given no persisted pusher when adding Pusher then updates api and inserts result with Registered state`() {
|
||||
monarchy.givenWhereReturns<PusherEntity>(result = null)
|
||||
|
||||
runBlocking { addPusherTask.execute(AddPusherTask.Params(A_JSON_PUSHER)) }
|
||||
runTest { addPusherTask.execute(AddPusherTask.Params(A_JSON_PUSHER)) }
|
||||
|
||||
pushersAPI.verifySetPusher(A_JSON_PUSHER)
|
||||
monarchy.verifyInsertOrUpdate<PusherEntity> {
|
||||
|
@ -70,7 +72,7 @@ class DefaultAddPusherTaskTest {
|
|||
val realmResult = PusherEntity(appDisplayName = null)
|
||||
monarchy.givenWhereReturns(result = realmResult)
|
||||
|
||||
runBlocking { addPusherTask.execute(AddPusherTask.Params(A_JSON_PUSHER)) }
|
||||
runTest { addPusherTask.execute(AddPusherTask.Params(A_JSON_PUSHER)) }
|
||||
|
||||
pushersAPI.verifySetPusher(A_JSON_PUSHER)
|
||||
|
||||
|
@ -85,7 +87,7 @@ class DefaultAddPusherTaskTest {
|
|||
pushersAPI.givenSetPusherErrors(SocketException())
|
||||
|
||||
assertFailsWith<SocketException> {
|
||||
runBlocking { addPusherTask.execute(AddPusherTask.Params(A_JSON_PUSHER)) }
|
||||
runTest { addPusherTask.execute(AddPusherTask.Params(A_JSON_PUSHER)) }
|
||||
}
|
||||
|
||||
realmResult.state shouldBeEqualTo PusherState.FAILED_TO_REGISTER
|
||||
|
@ -97,7 +99,7 @@ class DefaultAddPusherTaskTest {
|
|||
pushersAPI.givenSetPusherErrors(SocketException())
|
||||
|
||||
assertFailsWith<SocketException> {
|
||||
runBlocking { addPusherTask.execute(AddPusherTask.Params(A_JSON_PUSHER)) }
|
||||
runTest { addPusherTask.execute(AddPusherTask.Params(A_JSON_PUSHER)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package org.matrix.android.sdk.internal.session.space
|
||||
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||
import org.amshove.kluent.shouldBeEqualTo
|
||||
import org.junit.Test
|
||||
|
@ -35,7 +35,7 @@ internal class DefaultResolveSpaceInfoTaskTest {
|
|||
private val resolveSpaceInfoTask = DefaultResolveSpaceInfoTask(spaceApi.instance, globalErrorReceiver)
|
||||
|
||||
@Test
|
||||
fun `given stable endpoint works, when execute, then return stable api data`() = runBlockingTest {
|
||||
fun `given stable endpoint works, when execute, then return stable api data`() = runTest {
|
||||
spaceApi.givenStableEndpointReturns(response)
|
||||
|
||||
val result = resolveSpaceInfoTask.execute(spaceApi.params)
|
||||
|
@ -44,7 +44,7 @@ internal class DefaultResolveSpaceInfoTaskTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `given stable endpoint fails, when execute, then fallback to unstable endpoint`() = runBlockingTest {
|
||||
fun `given stable endpoint fails, when execute, then fallback to unstable endpoint`() = runTest {
|
||||
spaceApi.givenStableEndpointThrows(httpException)
|
||||
spaceApi.givenUnstableEndpointReturns(response)
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import kotlinx.coroutines.asCoroutineDispatcher
|
|||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.joinAll
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.matrix.android.sdk.MatrixTest
|
||||
|
@ -51,7 +51,7 @@ class CoroutineSequencersTest : MatrixTest {
|
|||
.also { results.add(it) }
|
||||
}
|
||||
)
|
||||
runBlocking {
|
||||
runTest {
|
||||
jobs.joinAll()
|
||||
}
|
||||
assertEquals(3, results.size)
|
||||
|
@ -81,7 +81,7 @@ class CoroutineSequencersTest : MatrixTest {
|
|||
.also { results.add(it) }
|
||||
}
|
||||
)
|
||||
runBlocking {
|
||||
runTest {
|
||||
jobs.joinAll()
|
||||
}
|
||||
assertEquals(3, results.size)
|
||||
|
@ -109,7 +109,7 @@ class CoroutineSequencersTest : MatrixTest {
|
|||
)
|
||||
// We are canceling the second job
|
||||
jobs[1].cancel()
|
||||
runBlocking {
|
||||
runTest {
|
||||
jobs.joinAll()
|
||||
}
|
||||
assertEquals(2, results.size)
|
||||
|
|
|
@ -13,6 +13,7 @@ print("::group::Arguments")
|
|||
print(f"{sys.argv}")
|
||||
print("::endgroup::")
|
||||
for xmlfile in xmlfiles:
|
||||
try:
|
||||
tree = ET.parse(xmlfile)
|
||||
|
||||
root = tree.getroot()
|
||||
|
@ -40,5 +41,7 @@ for xmlfile in xmlfiles:
|
|||
print(child.text)
|
||||
body = f" passed={success} failures={failures} errors={errors} skipped={skipped}"
|
||||
print(f"::set-output name={suitename}::={body}")
|
||||
except FileNotFoundError:
|
||||
print(f"::error::Unable to open test results file {xmlfile} - check if the tests completed")
|
||||
print("::endgroup::")
|
||||
|
||||
|
|
|
@ -2056,7 +2056,9 @@
|
|||
"disappear",
|
||||
"dissolve",
|
||||
"liquid",
|
||||
"melt"
|
||||
"melt",
|
||||
"hot",
|
||||
"heat"
|
||||
]
|
||||
},
|
||||
"winking-face": {
|
||||
|
@ -2351,7 +2353,10 @@
|
|||
"disbelief",
|
||||
"embarrass",
|
||||
"scared",
|
||||
"surprise"
|
||||
"surprise",
|
||||
"silence",
|
||||
"secret",
|
||||
"shock"
|
||||
]
|
||||
},
|
||||
"face-with-peeking-eye": {
|
||||
|
@ -2360,7 +2365,10 @@
|
|||
"j": [
|
||||
"captivated",
|
||||
"peep",
|
||||
"stare"
|
||||
"stare",
|
||||
"scared",
|
||||
"frightening",
|
||||
"embarrassing"
|
||||
]
|
||||
},
|
||||
"shushing-face": {
|
||||
|
@ -2392,7 +2400,8 @@
|
|||
"salute",
|
||||
"sunny",
|
||||
"troops",
|
||||
"yes"
|
||||
"yes",
|
||||
"respect"
|
||||
]
|
||||
},
|
||||
"zippermouth-face": {
|
||||
|
@ -2467,7 +2476,10 @@
|
|||
"disappear",
|
||||
"hide",
|
||||
"introvert",
|
||||
"invisible"
|
||||
"invisible",
|
||||
"lonely",
|
||||
"isolation",
|
||||
"depression"
|
||||
]
|
||||
},
|
||||
"face-in-clouds": {
|
||||
|
@ -2863,7 +2875,11 @@
|
|||
"disappointed",
|
||||
"meh",
|
||||
"skeptical",
|
||||
"unsure"
|
||||
"unsure",
|
||||
"skeptic",
|
||||
"confuse",
|
||||
"frustrated",
|
||||
"indifferent"
|
||||
]
|
||||
},
|
||||
"worried-face": {
|
||||
|
@ -2969,7 +2985,9 @@
|
|||
"cry",
|
||||
"proud",
|
||||
"resist",
|
||||
"sad"
|
||||
"sad",
|
||||
"touched",
|
||||
"gratitude"
|
||||
]
|
||||
},
|
||||
"frowning-face-with-open-mouth": {
|
||||
|
@ -4065,7 +4083,9 @@
|
|||
"j": [
|
||||
"hand",
|
||||
"right",
|
||||
"rightward"
|
||||
"rightward",
|
||||
"palm",
|
||||
"offer"
|
||||
]
|
||||
},
|
||||
"leftwards-hand": {
|
||||
|
@ -4074,7 +4094,9 @@
|
|||
"j": [
|
||||
"hand",
|
||||
"left",
|
||||
"leftward"
|
||||
"leftward",
|
||||
"palm",
|
||||
"offer"
|
||||
]
|
||||
},
|
||||
"palm-down-hand": {
|
||||
|
@ -4083,7 +4105,8 @@
|
|||
"j": [
|
||||
"dismiss",
|
||||
"drop",
|
||||
"shoo"
|
||||
"shoo",
|
||||
"palm"
|
||||
]
|
||||
},
|
||||
"palm-up-hand": {
|
||||
|
@ -4093,7 +4116,9 @@
|
|||
"beckon",
|
||||
"catch",
|
||||
"come",
|
||||
"offer"
|
||||
"offer",
|
||||
"lift",
|
||||
"demand"
|
||||
]
|
||||
},
|
||||
"ok-hand": {
|
||||
|
@ -4290,7 +4315,8 @@
|
|||
"b": "1FAF5",
|
||||
"j": [
|
||||
"point",
|
||||
"you"
|
||||
"you",
|
||||
"recruit"
|
||||
]
|
||||
},
|
||||
"thumbs-up": {
|
||||
|
@ -4404,7 +4430,9 @@
|
|||
"a": "⊛ Heart Hands",
|
||||
"b": "1FAF6",
|
||||
"j": [
|
||||
"love"
|
||||
"love",
|
||||
"appreciation",
|
||||
"support"
|
||||
]
|
||||
},
|
||||
"open-hands": {
|
||||
|
@ -4662,7 +4690,11 @@
|
|||
"flirting",
|
||||
"nervous",
|
||||
"uncomfortable",
|
||||
"worried"
|
||||
"worried",
|
||||
"flirt",
|
||||
"sexy",
|
||||
"pain",
|
||||
"worry"
|
||||
]
|
||||
},
|
||||
"baby": {
|
||||
|
@ -6058,7 +6090,8 @@
|
|||
"monarch",
|
||||
"noble",
|
||||
"regal",
|
||||
"royalty"
|
||||
"royalty",
|
||||
"power"
|
||||
]
|
||||
},
|
||||
"prince": {
|
||||
|
@ -6231,7 +6264,8 @@
|
|||
"belly",
|
||||
"bloated",
|
||||
"full",
|
||||
"pregnant"
|
||||
"pregnant",
|
||||
"baby"
|
||||
]
|
||||
},
|
||||
"pregnant-person": {
|
||||
|
@ -6241,7 +6275,8 @@
|
|||
"belly",
|
||||
"bloated",
|
||||
"full",
|
||||
"pregnant"
|
||||
"pregnant",
|
||||
"baby"
|
||||
]
|
||||
},
|
||||
"breastfeeding": {
|
||||
|
@ -6635,7 +6670,8 @@
|
|||
"j": [
|
||||
"fairy tale",
|
||||
"fantasy",
|
||||
"monster"
|
||||
"monster",
|
||||
"mystical"
|
||||
]
|
||||
},
|
||||
"person-getting-massage": {
|
||||
|
@ -9374,7 +9410,8 @@
|
|||
"b": "1FAB8",
|
||||
"j": [
|
||||
"ocean",
|
||||
"reef"
|
||||
"reef",
|
||||
"sea"
|
||||
]
|
||||
},
|
||||
"snail": {
|
||||
|
@ -9587,7 +9624,9 @@
|
|||
"Hinduism",
|
||||
"India",
|
||||
"purity",
|
||||
"Vietnam"
|
||||
"Vietnam",
|
||||
"calm",
|
||||
"meditation"
|
||||
]
|
||||
},
|
||||
"rosette": {
|
||||
|
@ -9832,14 +9871,16 @@
|
|||
"a": "⊛ Empty Nest",
|
||||
"b": "1FAB9",
|
||||
"j": [
|
||||
"nesting"
|
||||
"nesting",
|
||||
"bird"
|
||||
]
|
||||
},
|
||||
"nest-with-eggs": {
|
||||
"a": "⊛ Nest with Eggs",
|
||||
"b": "1FABA",
|
||||
"j": [
|
||||
"nesting"
|
||||
"nesting",
|
||||
"bird"
|
||||
]
|
||||
},
|
||||
"grapes": {
|
||||
|
@ -11187,7 +11228,9 @@
|
|||
"drink",
|
||||
"empty",
|
||||
"glass",
|
||||
"spill"
|
||||
"spill",
|
||||
"cup",
|
||||
"water"
|
||||
]
|
||||
},
|
||||
"cup-with-straw": {
|
||||
|
@ -12003,7 +12046,9 @@
|
|||
"b": "1F6DD",
|
||||
"j": [
|
||||
"amusement park",
|
||||
"play"
|
||||
"play",
|
||||
"fun",
|
||||
"park"
|
||||
]
|
||||
},
|
||||
"ferris-wheel": {
|
||||
|
@ -12533,7 +12578,9 @@
|
|||
"j": [
|
||||
"circle",
|
||||
"tire",
|
||||
"turn"
|
||||
"turn",
|
||||
"car",
|
||||
"transport"
|
||||
]
|
||||
},
|
||||
"police-car-light": {
|
||||
|
@ -14666,7 +14713,8 @@
|
|||
"hand",
|
||||
"Mary",
|
||||
"Miriam",
|
||||
"protection"
|
||||
"protection",
|
||||
"religion"
|
||||
]
|
||||
},
|
||||
"video-game": {
|
||||
|
@ -15864,7 +15912,9 @@
|
|||
"b": "1FAAB",
|
||||
"j": [
|
||||
"electronic",
|
||||
"low energy"
|
||||
"low energy",
|
||||
"drained",
|
||||
"dead"
|
||||
]
|
||||
},
|
||||
"electric-plug": {
|
||||
|
@ -17508,7 +17558,9 @@
|
|||
"disability",
|
||||
"hurt",
|
||||
"mobility aid",
|
||||
"stick"
|
||||
"stick",
|
||||
"accessibility",
|
||||
"assist"
|
||||
]
|
||||
},
|
||||
"stethoscope": {
|
||||
|
@ -17528,7 +17580,9 @@
|
|||
"bones",
|
||||
"doctor",
|
||||
"medical",
|
||||
"skeleton"
|
||||
"skeleton",
|
||||
"x-ray",
|
||||
"medicine"
|
||||
]
|
||||
},
|
||||
"door": {
|
||||
|
@ -17733,7 +17787,10 @@
|
|||
"burp",
|
||||
"clean",
|
||||
"soap",
|
||||
"underwater"
|
||||
"underwater",
|
||||
"fun",
|
||||
"carbonation",
|
||||
"sparkling"
|
||||
]
|
||||
},
|
||||
"toothbrush": {
|
||||
|
@ -17856,7 +17913,8 @@
|
|||
"credentials",
|
||||
"ID",
|
||||
"license",
|
||||
"security"
|
||||
"security",
|
||||
"document"
|
||||
]
|
||||
},
|
||||
"atm-sign": {
|
||||
|
|
|
@ -7,7 +7,6 @@ import com.airbnb.mvrx.ViewModelContext
|
|||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import dagger.assisted.AssistedFactory
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
|
||||
<#if createViewEvents>
|
||||
|
@ -42,6 +41,6 @@ class ${viewModelClass} @AssistedInject constructor(@Assisted initialState: ${vi
|
|||
override fun handle(action: ${actionClass}) {
|
||||
when (action) {
|
||||
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,8 +36,9 @@
|
|||
<!-- Level 1: Security and Privacy -->
|
||||
|
||||
<!-- Level 1: Labs -->
|
||||
<bool name="settings_labs_thread_messages_default">false</bool>
|
||||
|
||||
<!-- Level 1: Advcanced settings -->
|
||||
<!-- Level 1: Advanced settings -->
|
||||
|
||||
<!-- Level 1: Help and about -->
|
||||
|
||||
|
|
|
@ -411,7 +411,6 @@ dependencies {
|
|||
implementation 'jp.wasabeef:glide-transformations:4.3.0'
|
||||
implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta12'
|
||||
implementation 'com.github.hyuwah:DraggableView:1.0.0'
|
||||
implementation 'com.github.Armen101:AudioRecordView:1.0.5'
|
||||
|
||||
// Custom Tab
|
||||
implementation 'androidx.browser:browser:1.4.0'
|
||||
|
|
|
@ -21,6 +21,7 @@ import androidx.test.espresso.Espresso.onView
|
|||
import androidx.test.espresso.Espresso.pressBack
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isRoot
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import com.adevinta.android.barista.assertion.BaristaEnabledAssertions.assertDisabled
|
||||
import com.adevinta.android.barista.assertion.BaristaEnabledAssertions.assertEnabled
|
||||
import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed
|
||||
|
@ -55,6 +56,8 @@ class OnboardingRobot {
|
|||
|
||||
fun createAccount(userId: String, password: String = "password", homeServerUrl: String = "http://10.0.2.2:8080") {
|
||||
initSession(true, userId, password, homeServerUrl)
|
||||
waitUntilViewVisible(withText(R.string.ftue_account_created_congratulations_title))
|
||||
clickOn(R.string.ftue_account_created_take_me_home)
|
||||
}
|
||||
|
||||
fun login(userId: String, password: String = "password", homeServerUrl: String = "http://10.0.2.2:8080") {
|
||||
|
|
|
@ -22,7 +22,6 @@ 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.extensions.exhaustive
|
||||
import im.vector.app.core.platform.EmptyViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.analytics.store.AnalyticsStore
|
||||
|
@ -53,7 +52,7 @@ class DebugAnalyticsViewModel @AssistedInject constructor(
|
|||
override fun handle(action: DebugAnalyticsViewActions) {
|
||||
when (action) {
|
||||
DebugAnalyticsViewActions.ResetAnalyticsOptInDisplayed -> handleResetAnalyticsOptInDisplayed()
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleResetAnalyticsOptInDisplayed() {
|
||||
|
|
|
@ -22,7 +22,6 @@ 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.extensions.exhaustive
|
||||
import im.vector.app.core.platform.EmptyViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.debug.features.DebugVectorOverrides
|
||||
|
@ -71,7 +70,7 @@ class DebugPrivateSettingsViewModel @AssistedInject constructor(
|
|||
is DebugPrivateSettingsViewActions.SetForceLoginFallbackEnabled -> handleSetForceLoginFallbackEnabled(action)
|
||||
is SetDisplayNameCapabilityOverride -> handSetDisplayNameCapabilityOverride(action)
|
||||
is SetAvatarCapabilityOverride -> handSetAvatarCapabilityOverride(action)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSetDialPadVisibility(action: DebugPrivateSettingsViewActions.SetDialPadVisibility) {
|
||||
|
|
|
@ -437,11 +437,6 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
<br/>
|
||||
Copyright (c) 2017-present, dialog LLC <info@dlg.im>
|
||||
</li>
|
||||
<li>
|
||||
<b>Armen101 / AudioRecordView</b>
|
||||
<br/>
|
||||
Copyright 2019 Armen Gevorgyan
|
||||
</li>
|
||||
</ul>
|
||||
<pre>
|
||||
Apache License
|
||||
|
|
|
@ -46,6 +46,7 @@ import im.vector.app.features.navigation.Navigator
|
|||
import im.vector.app.features.pin.PinCodeStore
|
||||
import im.vector.app.features.pin.SharedPrefPinCodeStore
|
||||
import im.vector.app.features.room.VectorRoomDisplayNameFallbackProvider
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import im.vector.app.features.ui.SharedPreferencesUiStateRepository
|
||||
import im.vector.app.features.ui.UiStateRepository
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
@ -113,10 +114,13 @@ object VectorStaticModule {
|
|||
}
|
||||
|
||||
@Provides
|
||||
fun providesMatrixConfiguration(vectorRoomDisplayNameFallbackProvider: VectorRoomDisplayNameFallbackProvider): MatrixConfiguration {
|
||||
fun providesMatrixConfiguration(
|
||||
vectorPreferences: VectorPreferences,
|
||||
vectorRoomDisplayNameFallbackProvider: VectorRoomDisplayNameFallbackProvider): MatrixConfiguration {
|
||||
return MatrixConfiguration(
|
||||
applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION,
|
||||
roomDisplayNameFallbackProvider = vectorRoomDisplayNameFallbackProvider,
|
||||
threadMessagesEnabledDefault = vectorPreferences.areThreadMessagesEnabled(),
|
||||
presenceSyncEnabled = BuildConfig.PRESENCE_SYNC_ENABLED
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* Copyright 2020 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
|
||||
|
||||
// Trick to ensure that when block is exhaustive
|
||||
val <T> T.exhaustive: T get() = this
|
|
@ -54,7 +54,6 @@ import im.vector.app.core.di.ActiveSessionHolder
|
|||
import im.vector.app.core.di.ActivityEntryPoint
|
||||
import im.vector.app.core.dialogs.DialogLocker
|
||||
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.extensions.observeEvent
|
||||
import im.vector.app.core.extensions.observeNotNull
|
||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||
|
@ -267,7 +266,7 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
|||
is GlobalError.CertificateError ->
|
||||
handleCertificateError(globalError)
|
||||
GlobalError.ExpiredAccount -> Unit // TODO Handle account expiration
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCertificateError(certificateError: GlobalError.CertificateError) {
|
||||
|
|
|
@ -83,6 +83,7 @@ class PushRulePreference : VectorPreference {
|
|||
NotificationIndex.NOISY -> {
|
||||
radioGroup?.check(R.id.bingPreferenceRadioBingRuleNoisy)
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
|
||||
radioGroup?.setOnCheckedChangeListener { _, checkedId ->
|
||||
|
|
|
@ -77,13 +77,10 @@ class KeysBackupBanner @JvmOverloads constructor(
|
|||
|
||||
override fun onClick(v: View?) {
|
||||
when (state) {
|
||||
is State.Setup -> {
|
||||
delegate?.setupKeysBackup()
|
||||
}
|
||||
is State.Setup -> delegate?.setupKeysBackup()
|
||||
is State.Update,
|
||||
is State.Recover -> {
|
||||
delegate?.recoverKeysBackup()
|
||||
}
|
||||
is State.Recover -> delegate?.recoverKeysBackup()
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ import androidx.core.text.italic
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.onClick
|
||||
import im.vector.app.core.error.ResourceLimitErrorFormatter
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.utils.DimensionConverter
|
||||
import im.vector.app.databinding.ViewNotificationAreaBinding
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
|
@ -77,7 +76,7 @@ class NotificationAreaView @JvmOverloads constructor(
|
|||
is State.UnsupportedAlgorithm -> renderUnsupportedAlgorithm(newState)
|
||||
is State.Tombstone -> renderTombstone()
|
||||
is State.ResourceLimitExceededError -> renderResourceLimitExceededError(newState)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
// PRIVATE METHODS ****************************************************************************************************************************************
|
||||
|
|
|
@ -49,6 +49,7 @@ class PresenceStateImageView @JvmOverloads constructor(
|
|||
setImageResource(R.drawable.ic_presence_offline)
|
||||
contentDescription = context.getString(R.string.a11y_presence_offline)
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ class ShieldImageView @JvmOverloads constructor(
|
|||
contentDescription = context.getString(R.string.a11y_trust_level_trusted)
|
||||
setImageResource(R.drawable.ic_warning_badge)
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -241,7 +241,7 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
|
|||
// We have a session.
|
||||
// Check it can be opened
|
||||
if (sessionHolder.getActiveSession().isOpenable) {
|
||||
HomeActivity.newIntent(this)
|
||||
HomeActivity.newIntent(this, existingSession = true)
|
||||
} else {
|
||||
// The token is still invalid
|
||||
navigator.softLogout(this)
|
||||
|
|
|
@ -22,7 +22,6 @@ 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.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.analytics.VectorAnalytics
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -55,7 +54,7 @@ class AnalyticsConsentViewModel @AssistedInject constructor(
|
|||
override fun handle(action: AnalyticsConsentViewActions) {
|
||||
when (action) {
|
||||
is AnalyticsConsentViewActions.SetUserConsent -> handleSetUserConsent(action)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSetUserConsent(action: AnalyticsConsentViewActions.SetUserConsent) {
|
||||
|
|
|
@ -19,7 +19,6 @@ package im.vector.app.features.analytics.ui.consent
|
|||
import com.airbnb.mvrx.viewModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.core.extensions.addFragment
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.ScreenOrientationLocker
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.databinding.ActivitySimpleBinding
|
||||
|
@ -48,7 +47,7 @@ class AnalyticsOptInActivity : VectorBaseActivity<ActivitySimpleBinding>() {
|
|||
viewModel.observeViewEvents {
|
||||
when (it) {
|
||||
AnalyticsOptInViewEvents.OnDataSaved -> finish()
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package im.vector.app.features.attachments.preview
|
||||
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
|
||||
class AttachmentsPreviewViewModel(initialState: AttachmentsPreviewViewState) :
|
||||
|
@ -28,7 +27,7 @@ class AttachmentsPreviewViewModel(initialState: AttachmentsPreviewViewState) :
|
|||
is AttachmentsPreviewAction.SetCurrentAttachment -> handleSetCurrentAttachment(action)
|
||||
is AttachmentsPreviewAction.UpdatePathOfCurrentAttachment -> handleUpdatePathOfCurrentAttachment(action)
|
||||
AttachmentsPreviewAction.RemoveCurrentAttachment -> handleRemoveCurrentAttachment()
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRemoveCurrentAttachment() = withState {
|
||||
|
|
|
@ -111,6 +111,7 @@ class CallControlsView @JvmOverloads constructor(
|
|||
views.ringingControls.isVisible = false
|
||||
views.connectedControls.isVisible = false
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -525,8 +525,7 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
|
|||
navigator.openCallTransfer(this, callTransferActivityResultLauncher, callId)
|
||||
}
|
||||
is VectorCallViewEvents.FailToTransfer -> showSnackbar(getString(R.string.call_transfer_failure))
|
||||
null -> {
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ 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.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.call.audio.CallAudioManager
|
||||
import im.vector.app.features.call.dialpad.DialPadLookup
|
||||
|
@ -343,7 +342,7 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||
setState { VectorCallViewState(action.callArgs) }
|
||||
setupCallWithCurrentState()
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCallTransfer() {
|
||||
|
@ -358,7 +357,7 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||
when (result) {
|
||||
is CallTransferResult.ConnectWithUserId -> connectWithUserId(result)
|
||||
is CallTransferResult.ConnectWithPhoneNumber -> connectWithPhoneNumber(result)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun connectWithUserId(result: CallTransferResult.ConnectWithUserId) {
|
||||
|
|
|
@ -27,7 +27,6 @@ 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.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
|
@ -103,7 +102,7 @@ class JitsiCallViewModel @AssistedInject constructor(
|
|||
when (action) {
|
||||
is JitsiCallViewActions.SwitchTo -> handleSwitchTo(action)
|
||||
JitsiCallViewActions.OnConferenceLeft -> handleOnConferenceLeft()
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSwitchTo(action: JitsiCallViewActions.SwitchTo) = withState { state ->
|
||||
|
|
|
@ -35,7 +35,6 @@ import com.facebook.react.modules.core.PermissionListener
|
|||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.databinding.ActivityJitsiBinding
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
@ -79,7 +78,7 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
|
|||
JitsiCallViewEvents.FailJoiningConference -> handleFailJoining()
|
||||
JitsiCallViewEvents.Finish -> finish()
|
||||
JitsiCallViewEvents.LeaveConference -> handleLeaveConference()
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
lifecycle.addObserver(ConferenceEventObserver(this, this::onBroadcastEvent))
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import com.google.android.material.tabs.TabLayoutMediator
|
|||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.error.ErrorFormatter
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.databinding.ActivityCallTransferBinding
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
@ -57,7 +56,7 @@ class CallTransferActivity : VectorBaseActivity<ActivityCallTransferBinding>() {
|
|||
callTransferViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is CallTransferViewEvents.Complete -> handleComplete()
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
sectionsPagerAdapter = CallTransferPagerAdapter(this)
|
||||
|
|
|
@ -26,7 +26,6 @@ import com.airbnb.mvrx.activityViewModel
|
|||
import com.airbnb.mvrx.withState
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.utils.showIdentityServerConsentDialog
|
||||
|
@ -73,7 +72,7 @@ class ContactsBookFragment @Inject constructor(
|
|||
when (it) {
|
||||
is ContactsBookViewEvents.Failure -> showFailure(it.throwable)
|
||||
is ContactsBookViewEvents.OnPoliciesRetrieved -> showConsentDialog(it)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ import im.vector.app.core.contacts.ContactsDataSource
|
|||
import im.vector.app.core.contacts.MappedContact
|
||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.discovery.fetchIdentityServerWithTerms
|
||||
|
@ -165,7 +164,7 @@ class ContactsBookViewModel @AssistedInject constructor(
|
|||
is ContactsBookAction.OnlyBoundContacts -> handleOnlyBoundContacts(action)
|
||||
ContactsBookAction.UserConsentGranted -> handleUserConsentGranted()
|
||||
ContactsBookAction.UserConsentRequest -> handleUserConsentRequest()
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleUserConsentRequest() {
|
||||
|
|
|
@ -28,6 +28,7 @@ import com.airbnb.mvrx.Async
|
|||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import com.airbnb.mvrx.viewModel
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
@ -35,7 +36,6 @@ import im.vector.app.R
|
|||
import im.vector.app.core.error.ErrorFormatter
|
||||
import im.vector.app.core.extensions.addFragment
|
||||
import im.vector.app.core.extensions.addFragmentToBackstack
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.SimpleFragmentActivity
|
||||
import im.vector.app.core.platform.WaitingViewData
|
||||
import im.vector.app.core.utils.PERMISSIONS_FOR_MEMBERS_SEARCH
|
||||
|
@ -84,7 +84,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
|
|||
is UserListSharedAction.OnMenuItemSelected -> onMenuItemSelected(action)
|
||||
UserListSharedAction.OpenPhoneBook -> openPhoneBook()
|
||||
UserListSharedAction.AddByQrCode -> openAddByQrCode()
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
.launchIn(lifecycleScope)
|
||||
if (isFirstCreation()) {
|
||||
|
@ -111,7 +111,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
|
|||
Toast.makeText(this, R.string.cannot_dm_self, Toast.LENGTH_SHORT).show()
|
||||
finish()
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
qrViewModel.observeViewEvents {
|
||||
|
@ -124,7 +124,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
|
|||
finish()
|
||||
}
|
||||
else -> Unit
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,6 +167,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
|
|||
|
||||
private fun renderCreateAndInviteState(state: Async<String>) {
|
||||
when (state) {
|
||||
Uninitialized,
|
||||
is Loading -> renderCreationLoading()
|
||||
is Success -> renderCreationSuccess(state())
|
||||
is Fail -> renderCreationFailure(state.error)
|
||||
|
|
|
@ -24,7 +24,6 @@ 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.extensions.exhaustive
|
||||
import im.vector.app.core.mvrx.runCatchingToAsync
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.raw.wellknown.getElementWellknown
|
||||
|
@ -56,7 +55,7 @@ class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted
|
|||
when (action) {
|
||||
is CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers -> onSubmitInvitees(action.selections)
|
||||
is CreateDirectRoomAction.QrScannedAction -> onCodeParsed(action)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun onCodeParsed(action: CreateDirectRoomAction.QrScannedAction) {
|
||||
|
@ -108,7 +107,7 @@ class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted
|
|||
when (it) {
|
||||
is PendingSelection.UserPendingSelection -> invitedUserIds.add(it.user.userId)
|
||||
is PendingSelection.ThreePidPendingSelection -> invite3pids.add(it.threePid)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
setDirectMessage()
|
||||
enableEncryptionIfInvitedUsersSupportIt = adminE2EByDefault
|
||||
|
|
|
@ -140,6 +140,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(
|
|||
|
||||
isBackupAlreadySetup = true
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
|
||||
if (isBackupAlreadySetup) {
|
||||
|
|
|
@ -116,12 +116,13 @@ class SharedSecureStorageActivity :
|
|||
is SharedSecureStorageViewEvent.FinishSuccess -> {
|
||||
val dataResult = Intent()
|
||||
dataResult.putExtra(EXTRA_DATA_RESULT, it.cypherResult)
|
||||
setResult(Activity.RESULT_OK, dataResult)
|
||||
setResult(RESULT_OK, dataResult)
|
||||
finish()
|
||||
}
|
||||
is SharedSecureStorageViewEvent.ShowResetBottomSheet -> {
|
||||
navigator.open4SSetup(this, SetupMode.HARD_RESET)
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ import dagger.assisted.AssistedInject
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.platform.WaitingViewData
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
|
@ -142,7 +141,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
|
|||
SharedSecureStorageAction.Back -> handleBack()
|
||||
SharedSecureStorageAction.ForgotResetAll -> handleResetAll()
|
||||
SharedSecureStorageAction.DoResetAll -> handleDoResetAll()
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleDoResetAll() {
|
||||
|
|
|
@ -77,6 +77,7 @@ class SharedSecuredStorageKeyFragment @Inject constructor() : VectorBaseFragment
|
|||
is SharedSecureStorageViewEvent.KeyInlineError -> {
|
||||
views.ssssKeyEnterTil.error = it.message
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ class SharedSecuredStoragePassphraseFragment @Inject constructor(
|
|||
is SharedSecureStorageViewEvent.InlineError -> {
|
||||
views.ssssPassphraseEnterTil.error = it.message
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.commitTransaction
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||
import im.vector.app.core.extensions.toMvRxBundle
|
||||
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
|
||||
|
@ -209,7 +208,7 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetBoot
|
|||
views.bootstrapTitleText.text = getString(R.string.upgrade_security)
|
||||
showFragment(BootstrapMigrateBackupFragment::class)
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
super.invalidate()
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ import im.vector.app.R
|
|||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.error.ErrorFormatter
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.platform.WaitingViewData
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
|
@ -259,7 +258,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
|||
copy(step = BootstrapStep.AccountReAuth(stringProvider.getString(R.string.authentication_error)))
|
||||
}
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleStart(action: BootstrapActions.Start) = withState {
|
||||
|
@ -344,7 +343,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
|||
)
|
||||
}
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -449,7 +448,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -533,7 +532,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
|||
)
|
||||
}
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun BackupToQuadSMigrationTask.Result.Failure.toHumanReadable(): String {
|
||||
|
|
|
@ -30,7 +30,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.commitTransaction
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||
import im.vector.app.core.extensions.toMvRxBundle
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
|
@ -118,7 +117,7 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetV
|
|||
activity.navigator.openSettings(activity, VectorSettingsActivity.EXTRA_DIRECT_ACCESS_SECURITY_PRIVACY)
|
||||
}
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,6 +251,7 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetV
|
|||
VerificationConclusionFragment.Args(false, state.sasTransactionState.cancelCode.value, state.isMe)
|
||||
)
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
|
||||
return@withState
|
||||
|
|
|
@ -28,7 +28,6 @@ import dagger.assisted.AssistedInject
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -365,7 +364,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
|||
copy(verifyingFrom4S = false)
|
||||
}
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSecretBackFromSSSS(action: VerificationAction.GotResultFromSsss) {
|
||||
|
|
|
@ -139,6 +139,7 @@ class VerificationEmojiCodeViewModel @AssistedInject constructor(
|
|||
)
|
||||
}
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package im.vector.app.features.crypto.verification.request
|
|||
|
||||
import androidx.core.text.toSpannable
|
||||
import com.airbnb.epoxy.EpoxyController
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
|
@ -153,6 +154,7 @@ class VerificationRequestController @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
is Fail -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ import com.airbnb.mvrx.withState
|
|||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.extensions.replaceFragment
|
||||
import im.vector.app.core.platform.SimpleFragmentActivity
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
|
@ -79,7 +78,7 @@ class RoomDevToolActivity : SimpleFragmentActivity(), FragmentManager.OnBackStac
|
|||
Unit
|
||||
}
|
||||
is DevToolsViewEvents.ShowSnackMessage -> showSnackbar(it.message)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
supportFragmentManager.addOnBackStackChangedListener(this)
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ class DiscoverySettingsController @Inject constructor(
|
|||
|
||||
override fun buildModels(data: DiscoverySettingsState) {
|
||||
when (data.identityServer) {
|
||||
Uninitialized,
|
||||
is Loading -> {
|
||||
loadingItem {
|
||||
id("identityServerLoading")
|
||||
|
@ -209,7 +210,8 @@ class DiscoverySettingsController @Inject constructor(
|
|||
titleResId(R.string.settings_discovery_emails_title)
|
||||
}
|
||||
when (emails) {
|
||||
is Incomplete -> {
|
||||
Uninitialized,
|
||||
is Loading -> {
|
||||
loadingItem {
|
||||
id("emailsLoading")
|
||||
}
|
||||
|
@ -277,7 +279,8 @@ class DiscoverySettingsController @Inject constructor(
|
|||
}
|
||||
|
||||
when (msisdns) {
|
||||
is Incomplete -> {
|
||||
Uninitialized,
|
||||
is Loading -> {
|
||||
loadingItem {
|
||||
id("msisdnLoading")
|
||||
}
|
||||
|
@ -353,6 +356,7 @@ class DiscoverySettingsController @Inject constructor(
|
|||
colorProvider(host.colorProvider)
|
||||
stringProvider(host.stringProvider)
|
||||
when (pidInfo.isShared) {
|
||||
Uninitialized,
|
||||
is Loading -> {
|
||||
buttonIndeterminate(true)
|
||||
}
|
||||
|
@ -384,6 +388,7 @@ class DiscoverySettingsController @Inject constructor(
|
|||
else -> iconMode(IconMode.NONE)
|
||||
}
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.extensions.observeEvent
|
||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
|
@ -70,7 +69,7 @@ class DiscoverySettingsFragment @Inject constructor(
|
|||
when (it) {
|
||||
is DiscoverySharedViewModelAction.ChangeIdentityServer ->
|
||||
viewModel.handle(DiscoverySettingsAction.ChangeIdentityServer(it.newUrl))
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.observeViewEvents {
|
||||
|
@ -78,7 +77,7 @@ class DiscoverySettingsFragment @Inject constructor(
|
|||
is DiscoverySettingsViewEvents.Failure -> {
|
||||
displayErrorDialog(it.throwable)
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
if (discoveryArgs.expandIdentityPolicies) {
|
||||
viewModel.handle(DiscoverySettingsAction.SetPoliciesExpandState(expanded = true))
|
||||
|
|
|
@ -27,7 +27,6 @@ import dagger.assisted.AssistedInject
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
|
@ -113,7 +112,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
|
|||
is DiscoverySettingsAction.FinalizeBind3pid -> finalizeBind3pid(action, true)
|
||||
is DiscoverySettingsAction.SubmitMsisdnToken -> submitMsisdnToken(action)
|
||||
is DiscoverySettingsAction.CancelBinding -> cancelBinding(action)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleUpdateUserConsent(action: DiscoverySettingsAction.UpdateUserConsent) {
|
||||
|
@ -235,7 +234,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
|
|||
when (action.threePid) {
|
||||
is ThreePid.Email -> revokeEmail(action.threePid)
|
||||
is ThreePid.Msisdn -> revokeMsisdn(action.threePid)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun revokeEmail(threePid: ThreePid.Email) = withState { state ->
|
||||
|
|
|
@ -34,7 +34,6 @@ import im.vector.app.core.epoxy.attributes.ButtonStyle
|
|||
import im.vector.app.core.epoxy.attributes.ButtonType
|
||||
import im.vector.app.core.epoxy.attributes.IconMode
|
||||
import im.vector.app.core.epoxy.onClick
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
|
@ -122,7 +121,7 @@ abstract class SettingsTextButtonSingleLineItem : EpoxyModelWithHolder<SettingsT
|
|||
ButtonStyle.DESTRUCTIVE -> {
|
||||
holder.mainButton.setTextColor(colorProvider.getColorFromAttribute(R.attr.colorError))
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
holder.mainButton.onClick(buttonClickListener)
|
||||
}
|
||||
ButtonType.SWITCH -> {
|
||||
|
@ -133,7 +132,7 @@ abstract class SettingsTextButtonSingleLineItem : EpoxyModelWithHolder<SettingsT
|
|||
checked?.let { holder.switchButton.isChecked = it }
|
||||
holder.switchButton.setOnCheckedChangeListener(switchChangeListener)
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
when (iconMode) {
|
||||
|
|
|
@ -29,7 +29,6 @@ import com.airbnb.mvrx.fragmentViewModel
|
|||
import com.airbnb.mvrx.withState
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||
import im.vector.app.core.extensions.toReducedUrl
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
|
@ -132,7 +131,7 @@ class SetIdentityServerFragment @Inject constructor(
|
|||
it.identityServerUrl,
|
||||
null)
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ import im.vector.app.R
|
|||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.SingletonEntryPoint
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.core.utils.ensureProtocol
|
||||
|
@ -67,7 +66,7 @@ class SetIdentityServerViewModel @AssistedInject constructor(
|
|||
when (action) {
|
||||
SetIdentityServerAction.UseDefaultIdentityServer -> useDefault()
|
||||
is SetIdentityServerAction.UseCustomIdentityServer -> usedCustomIdentityServerUrl(action)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun useDefault() = withState { state ->
|
||||
|
|
|
@ -38,7 +38,6 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||
import im.vector.app.AppStateHandler
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||
import im.vector.app.core.extensions.replaceFragment
|
||||
|
@ -90,6 +89,7 @@ import javax.inject.Inject
|
|||
data class HomeActivityArgs(
|
||||
val clearNotification: Boolean,
|
||||
val accountCreation: Boolean,
|
||||
val hasExistingSession: Boolean = false,
|
||||
val inviteNotificationRoomId: String? = null
|
||||
) : Parcelable
|
||||
|
||||
|
@ -106,6 +106,7 @@ class HomeActivity :
|
|||
|
||||
@Suppress("UNUSED")
|
||||
private val analyticsAccountDataViewModel: AnalyticsAccountDataViewModel by viewModel()
|
||||
|
||||
@Suppress("UNUSED")
|
||||
private val userColorAccountDataViewModel: UserColorAccountDataViewModel by viewModel()
|
||||
|
||||
|
@ -231,7 +232,7 @@ class HomeActivity :
|
|||
HomeActivitySharedAction.SendSpaceFeedBack -> {
|
||||
bugReporter.openBugReportScreen(this, ReportType.SPACE_BETA_FEEDBACK)
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
|
@ -253,7 +254,9 @@ class HomeActivity :
|
|||
HomeActivityViewEvents.PromptToEnableSessionPush -> handlePromptToEnablePush()
|
||||
is HomeActivityViewEvents.OnCrossSignedInvalidated -> handleCrossSigningInvalidated(it)
|
||||
HomeActivityViewEvents.ShowAnalyticsOptIn -> handleShowAnalyticsOptIn()
|
||||
}.exhaustive
|
||||
HomeActivityViewEvents.NotifyUserForThreadsMigration -> handleNotifyUserForThreadsMigration()
|
||||
is HomeActivityViewEvents.MigrateThreads -> migrateThreadsIfNeeded(it.checkSession)
|
||||
}
|
||||
}
|
||||
homeActivityViewModel.onEach { renderState(it) }
|
||||
|
||||
|
@ -269,6 +272,48 @@ class HomeActivity :
|
|||
navigator.openAnalyticsOptIn(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrating from old threads io.element.thread to new m.thread needs an initial sync to
|
||||
* sync and display existing messages appropriately
|
||||
*/
|
||||
private fun migrateThreadsIfNeeded(checkSession: Boolean) {
|
||||
if (checkSession) {
|
||||
// We should check session to ensure we will only clear cache if needed
|
||||
val args = intent.getParcelableExtra<HomeActivityArgs>(Mavericks.KEY_ARG)
|
||||
if (args?.hasExistingSession == true) {
|
||||
// existingSession --> Will be true only if we came from an existing active session
|
||||
Timber.i("----> Migrating threads from an existing session..")
|
||||
handleThreadsMigration()
|
||||
} else {
|
||||
// We came from a new session and not an existing one,
|
||||
// so there is no need to migrate threads while an initial synced performed
|
||||
Timber.i("----> No thread migration needed, we are ok")
|
||||
vectorPreferences.setShouldMigrateThreads(shouldMigrate = false)
|
||||
}
|
||||
} else {
|
||||
// Proceed with migration
|
||||
handleThreadsMigration()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cache and restart to invoke an initial sync for threads migration
|
||||
*/
|
||||
private fun handleThreadsMigration() {
|
||||
Timber.i("----> Threads Migration detected, clearing cache and sync...")
|
||||
vectorPreferences.setShouldMigrateThreads(shouldMigrate = false)
|
||||
MainActivity.restartApp(this, MainActivityArgs(clearCache = true))
|
||||
}
|
||||
|
||||
private fun handleNotifyUserForThreadsMigration() {
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle(R.string.threads_notice_migration_title)
|
||||
.setMessage(R.string.threads_notice_migration_message)
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(R.string.sas_got_it) { _, _ -> }
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun handleIntent(intent: Intent?) {
|
||||
intent?.dataString?.let { deepLink ->
|
||||
val resolvedLink = when {
|
||||
|
@ -329,7 +374,7 @@ class HomeActivity :
|
|||
// Idle or Incremental sync status
|
||||
views.waitingView.root.isVisible = false
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleAskPasswordToInitCrossSigning(events: HomeActivityViewEvents.AskPasswordToInitCrossSigning) {
|
||||
|
@ -546,11 +591,13 @@ class HomeActivity :
|
|||
fun newIntent(context: Context,
|
||||
clearNotification: Boolean = false,
|
||||
accountCreation: Boolean = false,
|
||||
existingSession: Boolean = false,
|
||||
inviteNotificationRoomId: String? = null
|
||||
): Intent {
|
||||
val args = HomeActivityArgs(
|
||||
clearNotification = clearNotification,
|
||||
accountCreation = accountCreation,
|
||||
hasExistingSession = existingSession,
|
||||
inviteNotificationRoomId = inviteNotificationRoomId
|
||||
)
|
||||
|
||||
|
|
|
@ -25,4 +25,6 @@ sealed interface HomeActivityViewEvents : VectorViewEvents {
|
|||
data class OnCrossSignedInvalidated(val userItem: MatrixItem.UserItem) : HomeActivityViewEvents
|
||||
object PromptToEnableSessionPush : HomeActivityViewEvents
|
||||
object ShowAnalyticsOptIn : HomeActivityViewEvents
|
||||
object NotifyUserForThreadsMigration : HomeActivityViewEvents
|
||||
data class MigrateThreads(val checkSession: Boolean) : HomeActivityViewEvents
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import im.vector.app.config.analyticsConfig
|
|||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.analytics.store.AnalyticsStore
|
||||
import im.vector.app.features.login.ReAuthHelper
|
||||
|
@ -51,6 +50,7 @@ import org.matrix.android.sdk.api.util.toMatrixItem
|
|||
import org.matrix.android.sdk.flow.flow
|
||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||
import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
|
||||
import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
|
||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||
import timber.log.Timber
|
||||
import kotlin.coroutines.Continuation
|
||||
|
@ -62,6 +62,7 @@ class HomeActivityViewModel @AssistedInject constructor(
|
|||
private val activeSessionHolder: ActiveSessionHolder,
|
||||
private val reAuthHelper: ReAuthHelper,
|
||||
private val analyticsStore: AnalyticsStore,
|
||||
private val lightweightSettingsStorage: LightweightSettingsStorage,
|
||||
private val vectorPreferences: VectorPreferences
|
||||
) : VectorViewModel<HomeActivityViewState, HomeActivityViewActions, HomeActivityViewEvents>(initialState) {
|
||||
|
||||
|
@ -84,6 +85,7 @@ class HomeActivityViewModel @AssistedInject constructor(
|
|||
checkSessionPushIsOn()
|
||||
observeCrossSigningReset()
|
||||
observeAnalytics()
|
||||
initThreadsMigration()
|
||||
}
|
||||
|
||||
private fun observeAnalytics() {
|
||||
|
@ -130,6 +132,46 @@ class HomeActivityViewModel @AssistedInject constructor(
|
|||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle threads migration. The migration includes:
|
||||
* - Notify users that had io.element.thread enabled from labs
|
||||
* - Re-Enable m.thread to those users (that they had enabled labs threads)
|
||||
* - Handle migration when threads are enabled by default
|
||||
*/
|
||||
private fun initThreadsMigration() {
|
||||
// When we would like to enable threads for all users
|
||||
// if(vectorPreferences.shouldMigrateThreads()) {
|
||||
// vectorPreferences.setThreadMessagesEnabled()
|
||||
// lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled())
|
||||
// }
|
||||
|
||||
when {
|
||||
// Notify users
|
||||
vectorPreferences.shouldNotifyUserAboutThreads() && vectorPreferences.areThreadMessagesEnabled() -> {
|
||||
Timber.i("----> Notify users about threads")
|
||||
// Notify the user if needed that we migrated to support m.thread
|
||||
// instead of io.element.thread so old thread messages will be displayed as normal timeline messages
|
||||
_viewEvents.post(HomeActivityViewEvents.NotifyUserForThreadsMigration)
|
||||
vectorPreferences.userNotifiedAboutThreads()
|
||||
}
|
||||
// Migrate users with enabled lab settings
|
||||
vectorPreferences.shouldNotifyUserAboutThreads() && vectorPreferences.shouldMigrateThreads() -> {
|
||||
Timber.i("----> Migrate threads with enabled labs")
|
||||
// If user had io.element.thread enabled then enable the new thread support,
|
||||
// clear cache to sync messages appropriately
|
||||
vectorPreferences.setThreadMessagesEnabled()
|
||||
lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled())
|
||||
// Clear Cache
|
||||
_viewEvents.post(HomeActivityViewEvents.MigrateThreads(checkSession = false))
|
||||
}
|
||||
// Enable all users
|
||||
vectorPreferences.shouldMigrateThreads() && vectorPreferences.areThreadMessagesEnabled() -> {
|
||||
Timber.i("----> Try to migrate threads")
|
||||
_viewEvents.post(HomeActivityViewEvents.MigrateThreads(checkSession = true))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeInitialSync() {
|
||||
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
||||
|
||||
|
@ -263,6 +305,6 @@ class HomeActivityViewModel @AssistedInject constructor(
|
|||
HomeActivityViewActions.ViewStarted -> {
|
||||
initialize()
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -273,6 +273,7 @@ class HomeDetailViewModel @AssistedInject constructor(
|
|||
)
|
||||
}
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
.launchIn(viewModelScope)
|
||||
|
|
|
@ -72,7 +72,6 @@ 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.exhaustive
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
|
@ -177,6 +176,7 @@ import im.vector.app.features.html.PillsPostProcessor
|
|||
import im.vector.app.features.invite.VectorInviteView
|
||||
import im.vector.app.features.location.LocationSharingMode
|
||||
import im.vector.app.features.location.toLocationData
|
||||
import im.vector.app.features.media.AttachmentData
|
||||
import im.vector.app.features.media.ImageContentRenderer
|
||||
import im.vector.app.features.media.VideoContentRenderer
|
||||
import im.vector.app.features.notifications.NotificationDrawerManager
|
||||
|
@ -445,7 +445,7 @@ class TimelineFragment @Inject constructor(
|
|||
}
|
||||
showErrorInSnackbar(it.throwable)
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
timelineViewModel.observeViewEvents {
|
||||
|
@ -482,7 +482,7 @@ class TimelineFragment @Inject constructor(
|
|||
RoomDetailViewEvents.StopChatEffects -> handleStopChatEffects()
|
||||
is RoomDetailViewEvents.DisplayAndAcceptCall -> acceptIncomingCall(it)
|
||||
RoomDetailViewEvents.RoomReplacementStarted -> handleRoomReplacement()
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
|
@ -783,6 +783,18 @@ class TimelineFragment @Inject constructor(
|
|||
updateRecordingUiState(RecordingUiState.Draft)
|
||||
}
|
||||
|
||||
override fun onVoiceWaveformTouchedUp(percentage: Float, duration: Int) {
|
||||
messageComposerViewModel.handle(
|
||||
MessageComposerAction.VoiceWaveformTouchedUp(VoiceMessagePlaybackTracker.RECORDING_ID, duration, percentage)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onVoiceWaveformMoved(percentage: Float, duration: Int) {
|
||||
messageComposerViewModel.handle(
|
||||
MessageComposerAction.VoiceWaveformTouchedUp(VoiceMessagePlaybackTracker.RECORDING_ID, duration, percentage)
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateRecordingUiState(state: RecordingUiState) {
|
||||
messageComposerViewModel.handle(
|
||||
MessageComposerAction.OnVoiceRecordingUiStateChanged(state))
|
||||
|
@ -874,7 +886,7 @@ class TimelineFragment @Inject constructor(
|
|||
onContentAttachmentsReady(sharedData.attachmentData)
|
||||
}
|
||||
null -> Timber.v("No share data to process")
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSpaceShare() {
|
||||
|
@ -1240,7 +1252,7 @@ class TimelineFragment @Inject constructor(
|
|||
insertUserDisplayNameInTextEditor(roomDetailPendingAction.userId)
|
||||
is RoomDetailPendingAction.OpenRoom ->
|
||||
handleOpenRoom(RoomDetailViewEvents.OpenRoom(roomDetailPendingAction.roomId, roomDetailPendingAction.closeCurrentRoom))
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
|
@ -1612,11 +1624,10 @@ class TimelineFragment @Inject constructor(
|
|||
views.includeRoomToolbar.roomToolbarContentView.isClickable = roomSummary.membership == Membership.JOIN
|
||||
views.includeRoomToolbar.roomToolbarTitleView.text = roomSummary.displayName
|
||||
avatarRenderer.render(roomSummary.toMatrixItem(), views.includeRoomToolbar.roomToolbarAvatarImageView)
|
||||
views.includeRoomToolbar.roomToolbarDecorationImageView.render(roomSummary.roomEncryptionTrustLevel)
|
||||
views.includeRoomToolbar.roomToolbarPresenceImageView.render(
|
||||
roomSummary.isDirect && matrixConfiguration.presenceSyncEnabled,
|
||||
roomSummary.directUserPresence
|
||||
)
|
||||
val showPresence = roomSummary.isDirect && matrixConfiguration.presenceSyncEnabled
|
||||
views.includeRoomToolbar.roomToolbarPresenceImageView.render(showPresence, roomSummary.directUserPresence)
|
||||
val shieldView = if (showPresence) views.includeRoomToolbar.roomToolbarTitleShield else views.includeRoomToolbar.roomToolbarAvatarShield
|
||||
shieldView.render(roomSummary.roomEncryptionTrustLevel)
|
||||
views.includeRoomToolbar.roomToolbarPublicImageView.isVisible = roomSummary.isPublic && !roomSummary.isDirect
|
||||
}
|
||||
} else {
|
||||
|
@ -1658,7 +1669,7 @@ class TimelineFragment @Inject constructor(
|
|||
is MessageComposerViewEvents.SlashCommandNotSupportedInThreads -> {
|
||||
displayCommandError(getString(R.string.command_not_supported_in_threads, sendMessageResult.command.command))
|
||||
}
|
||||
} // .exhaustive
|
||||
} //
|
||||
|
||||
lockSendButton = false
|
||||
}
|
||||
|
@ -1782,6 +1793,7 @@ class TimelineFragment @Inject constructor(
|
|||
transactionId = data.transactionId,
|
||||
).show(parentFragmentManager, "REQ")
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1871,12 +1883,16 @@ class TimelineFragment @Inject constructor(
|
|||
vectorBaseActivity.notImplemented("encrypted message click")
|
||||
}
|
||||
|
||||
override fun onImageMessageClicked(messageImageContent: MessageImageInfoContent, mediaData: ImageContentRenderer.Data, view: View) {
|
||||
override fun onImageMessageClicked(messageImageContent: MessageImageInfoContent,
|
||||
mediaData: ImageContentRenderer.Data,
|
||||
view: View,
|
||||
inMemory: List<AttachmentData>) {
|
||||
navigator.openMediaViewer(
|
||||
activity = requireActivity(),
|
||||
roomId = timelineArgs.roomId,
|
||||
mediaData = mediaData,
|
||||
view = view
|
||||
view = view,
|
||||
inMemory = inMemory
|
||||
) { pairs ->
|
||||
pairs.add(Pair(views.roomToolbar, ViewCompat.getTransitionName(views.roomToolbar) ?: ""))
|
||||
pairs.add(Pair(views.composerLayout, ViewCompat.getTransitionName(views.composerLayout) ?: ""))
|
||||
|
@ -2047,6 +2063,14 @@ class TimelineFragment @Inject constructor(
|
|||
messageComposerViewModel.handle(MessageComposerAction.PlayOrPauseVoicePlayback(eventId, messageAudioContent))
|
||||
}
|
||||
|
||||
override fun onVoiceWaveformTouchedUp(eventId: String, duration: Int, percentage: Float) {
|
||||
messageComposerViewModel.handle(MessageComposerAction.VoiceWaveformTouchedUp(eventId, duration, percentage))
|
||||
}
|
||||
|
||||
override fun onVoiceWaveformMovedTo(eventId: String, duration: Int, percentage: Float) {
|
||||
messageComposerViewModel.handle(MessageComposerAction.VoiceWaveformMovedTo(eventId, duration, percentage))
|
||||
}
|
||||
|
||||
private fun onShareActionClicked(action: EventSharedAction.Share) {
|
||||
when (action.messageContent) {
|
||||
is MessageTextContent -> shareText(requireContext(), action.messageContent.body)
|
||||
|
@ -2232,6 +2256,8 @@ class TimelineFragment @Inject constructor(
|
|||
is EventSharedAction.EndPoll -> {
|
||||
askConfirmationToEndPoll(action.eventId)
|
||||
}
|
||||
is EventSharedAction.ReportContent -> Unit /* Not clickable */
|
||||
EventSharedAction.Separator -> Unit /* Not clickable */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2430,7 +2456,7 @@ class TimelineFragment @Inject constructor(
|
|||
locationOwnerId = session.myUserId
|
||||
)
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
// AttachmentsHelper.Callback
|
||||
|
|
|
@ -33,7 +33,6 @@ import im.vector.app.BuildConfig
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.mvrx.runCatchingToAsync
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
|
@ -440,7 +439,7 @@ class TimelineViewModel @AssistedInject constructor(
|
|||
_viewEvents.post(RoomDetailViewEvents.OpenRoom(action.replacementRoomId, closeCurrentRoom = true))
|
||||
}
|
||||
is RoomDetailAction.EndPoll -> handleEndPoll(action.eventId)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleJitsiCallJoinStatus(action: RoomDetailAction.UpdateJoinJitsiCallStatus) = withState { state ->
|
||||
|
|
|
@ -40,4 +40,6 @@ sealed class MessageComposerAction : VectorViewModelAction {
|
|||
data class PlayOrPauseVoicePlayback(val eventId: String, val messageAudioContent: MessageAudioContent) : MessageComposerAction()
|
||||
object PlayOrPauseRecordingPlayback : MessageComposerAction()
|
||||
data class EndAllVoiceActions(val deleteRecord: Boolean = true) : MessageComposerAction()
|
||||
data class VoiceWaveformTouchedUp(val eventId: String, val duration: Int, val percentage: Float) : MessageComposerAction()
|
||||
data class VoiceWaveformMovedTo(val eventId: String, val duration: Int, val percentage: Float) : MessageComposerAction()
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import dagger.assisted.AssistedInject
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.analytics.AnalyticsTracker
|
||||
|
@ -109,6 +108,8 @@ class MessageComposerViewModel @AssistedInject constructor(
|
|||
is MessageComposerAction.EndAllVoiceActions -> handleEndAllVoiceActions(action.deleteRecord)
|
||||
is MessageComposerAction.InitializeVoiceRecorder -> handleInitializeVoiceRecorder(action.attachmentData)
|
||||
is MessageComposerAction.OnEntersBackground -> handleEntersBackground(action.composerText)
|
||||
is MessageComposerAction.VoiceWaveformTouchedUp -> handleVoiceWaveformTouchedUp(action)
|
||||
is MessageComposerAction.VoiceWaveformMovedTo -> handleVoiceWaveformMovedTo(action)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -463,7 +464,7 @@ class MessageComposerViewModel @AssistedInject constructor(
|
|||
_viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
|
||||
popDraft()
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
is SendMode.Edit -> {
|
||||
// is original event a reply?
|
||||
|
@ -536,7 +537,7 @@ class MessageComposerViewModel @AssistedInject constructor(
|
|||
is SendMode.Voice -> {
|
||||
// do nothing
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -869,12 +870,23 @@ class MessageComposerViewModel @AssistedInject constructor(
|
|||
voiceMessageHelper.pauseRecording()
|
||||
}
|
||||
|
||||
private fun handleVoiceWaveformTouchedUp(action: MessageComposerAction.VoiceWaveformTouchedUp) {
|
||||
voiceMessageHelper.movePlaybackTo(action.eventId, action.percentage, action.duration)
|
||||
}
|
||||
|
||||
private fun handleVoiceWaveformMovedTo(action: MessageComposerAction.VoiceWaveformMovedTo) {
|
||||
voiceMessageHelper.movePlaybackTo(action.eventId, action.percentage, action.duration)
|
||||
}
|
||||
|
||||
private fun handleEntersBackground(composerText: String) {
|
||||
// Always stop all voice actions. It may be playing in timeline or active recording
|
||||
val playingAudioContent = voiceMessageHelper.stopAllVoiceActions(deleteRecord = false)
|
||||
voiceMessageHelper.clearTracker()
|
||||
|
||||
val isVoiceRecording = com.airbnb.mvrx.withState(this) { it.isVoiceRecording }
|
||||
if (isVoiceRecording) {
|
||||
voiceMessageHelper.clearTracker()
|
||||
viewModelScope.launch {
|
||||
voiceMessageHelper.stopAllVoiceActions(deleteRecord = false)?.toContentAttachmentData()?.let { voiceDraft ->
|
||||
playingAudioContent?.toContentAttachmentData()?.let { voiceDraft ->
|
||||
val content = voiceDraft.toJsonString()
|
||||
room.saveDraft(UserDraft.Voice(content))
|
||||
setState { copy(sendMode = SendMode.Voice(content)) }
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue