From 25a09bc44612e582fd7fe37ca36b4a8df655ade6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 27 Jan 2023 13:29:00 +0100 Subject: [PATCH 1/6] Add a debug slash command to crash the application from the timeline screen. --- library/ui-strings/src/main/res/values/donottranslate.xml | 2 ++ .../main/java/im/vector/app/features/command/Command.kt | 1 + .../java/im/vector/app/features/command/CommandParser.kt | 8 +++++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values/donottranslate.xml b/library/ui-strings/src/main/res/values/donottranslate.xml index bfe751ef5a5..910ce31c41d 100755 --- a/library/ui-strings/src/main/res/values/donottranslate.xml +++ b/library/ui-strings/src/main/res/values/donottranslate.xml @@ -10,6 +10,8 @@ Cut the slack from teams. + Crash the application. + © MapTiler © OpenStreetMap contributors diff --git a/vector/src/main/java/im/vector/app/features/command/Command.kt b/vector/src/main/java/im/vector/app/features/command/Command.kt index 324029c45bb..b112751f68e 100644 --- a/vector/src/main/java/im/vector/app/features/command/Command.kt +++ b/vector/src/main/java/im/vector/app/features/command/Command.kt @@ -32,6 +32,7 @@ enum class Command( val isDevCommand: Boolean, val isThreadCommand: Boolean ) { + CRASH_APP("/crash", null, "", R.string.command_description_crash_application, true, true), EMOTE("/me", null, "", R.string.command_description_emote, false, true), BAN_USER("/ban", null, " [reason]", R.string.command_description_ban_user, false, false), UNBAN_USER("/unban", null, " [reason]", R.string.command_description_unban_user, false, false), diff --git a/vector/src/main/java/im/vector/app/features/command/CommandParser.kt b/vector/src/main/java/im/vector/app/features/command/CommandParser.kt index e08bc9fb640..298387c324c 100644 --- a/vector/src/main/java/im/vector/app/features/command/CommandParser.kt +++ b/vector/src/main/java/im/vector/app/features/command/CommandParser.kt @@ -20,13 +20,16 @@ import im.vector.app.core.extensions.isEmail import im.vector.app.core.extensions.isMsisdn import im.vector.app.core.extensions.orEmpty import im.vector.app.features.home.room.detail.ChatEffect +import im.vector.app.features.settings.VectorPreferences import org.matrix.android.sdk.api.MatrixPatterns import org.matrix.android.sdk.api.MatrixUrls.isMxcUrl import org.matrix.android.sdk.api.session.identity.ThreePid import timber.log.Timber import javax.inject.Inject -class CommandParser @Inject constructor() { +class CommandParser @Inject constructor( + private val vectorPreferences: VectorPreferences +) { /** * Convert the text message into a Slash command. @@ -404,6 +407,9 @@ class CommandParser @Inject constructor() { ParsedCommand.ErrorSyntax(Command.UPGRADE_ROOM) } } + Command.CRASH_APP.matches(slashCommand) && vectorPreferences.developerMode() -> { + throw RuntimeException("Application crashed from user demand") + } else -> { // Unknown command ParsedCommand.ErrorUnknownSlashCommand(slashCommand) From 8f927a46ca14aaf317fc60d508c1710051659723 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 27 Jan 2023 15:41:23 +0100 Subject: [PATCH 2/6] Fix issue of `Idle` displayed after pausing and resuming the app. --- .../src/main/java/org/matrix/android/sdk/flow/FlowSession.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt index 80ed3119017..64cb0acb2dd 100644 --- a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt +++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt @@ -80,6 +80,9 @@ class FlowSession(private val session: Session) { fun liveSyncState(): Flow { return session.syncService().getSyncStateLive().asFlow() + .startWith(session.coroutineDispatchers.io) { + session.syncService().getSyncState() + } } fun livePushers(): Flow> { From 366ce8665d43ab264896aab8abe60af54162c355 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 27 Jan 2023 16:40:20 +0100 Subject: [PATCH 3/6] Do not show unknown data. --- .../im/vector/app/features/home/HomeDetailViewState.kt | 4 ++-- .../features/home/room/detail/RoomDetailViewState.kt | 4 ++-- .../vector/app/features/sync/widget/SyncStateView.kt | 10 ++++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt index 7fbd5b2bf62..dcf4d87894e 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt @@ -38,8 +38,8 @@ data class HomeDetailViewState( val notificationCountRooms: Int = 0, val notificationHighlightRooms: Boolean = false, val hasUnreadMessages: Boolean = false, - val syncState: SyncState = SyncState.Idle, - val incrementalSyncRequestState: SyncRequestState.IncrementalSyncRequestState = SyncRequestState.IncrementalSyncIdle, + val syncState: SyncState? = null, + val incrementalSyncRequestState: SyncRequestState.IncrementalSyncRequestState? = null, val pushCounter: Int = 0, val pstnSupportFlag: Boolean = false, val forceDialPadTab: Boolean = false diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt index 897594ffadb..f4919a59068 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt @@ -60,8 +60,8 @@ data class RoomDetailViewState( val formattedTypingUsers: String? = null, val tombstoneEvent: Event? = null, val joinUpgradedRoomAsync: Async = Uninitialized, - val syncState: SyncState = SyncState.Idle, - val incrementalSyncRequestState: SyncRequestState.IncrementalSyncRequestState = SyncRequestState.IncrementalSyncIdle, + val syncState: SyncState? = null, + val incrementalSyncRequestState: SyncRequestState.IncrementalSyncRequestState? = null, val pushCounter: Int = 0, val highlightedEventId: String? = null, val unreadState: UnreadState = UnreadState.Unknown, diff --git a/vector/src/main/java/im/vector/app/features/sync/widget/SyncStateView.kt b/vector/src/main/java/im/vector/app/features/sync/widget/SyncStateView.kt index a71f4458598..a40b70b8a69 100755 --- a/vector/src/main/java/im/vector/app/features/sync/widget/SyncStateView.kt +++ b/vector/src/main/java/im/vector/app/features/sync/widget/SyncStateView.kt @@ -40,8 +40,8 @@ class SyncStateView @JvmOverloads constructor(context: Context, attrs: Attribute @SuppressLint("SetTextI18n") fun render( - newState: SyncState, - incrementalSyncRequestState: SyncRequestState.IncrementalSyncRequestState, + newState: SyncState?, + incrementalSyncRequestState: SyncRequestState.IncrementalSyncRequestState?, pushCounter: Int, showDebugInfo: Boolean ) { @@ -64,8 +64,9 @@ class SyncStateView @JvmOverloads constructor(context: Context, attrs: Attribute } } - private fun SyncState.toHumanReadable(): String { + private fun SyncState?.toHumanReadable(): String { return when (this) { + null -> "Unknown" SyncState.Idle -> "Idle" SyncState.InvalidToken -> "InvalidToken" SyncState.Killed -> "Killed" @@ -76,8 +77,9 @@ class SyncStateView @JvmOverloads constructor(context: Context, attrs: Attribute } } - private fun SyncRequestState.IncrementalSyncRequestState.toHumanReadable(): String { + private fun SyncRequestState.IncrementalSyncRequestState?.toHumanReadable(): String { return when (this) { + null -> "Unknown" SyncRequestState.IncrementalSyncIdle -> "Idle" is SyncRequestState.IncrementalSyncParsing -> "Parsing ${this.rooms} room(s) ${this.toDevice} toDevice(s)" SyncRequestState.IncrementalSyncError -> "Error" From 5a62e31c86ac55256d7915606b11d25cf830e12f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 27 Jan 2023 16:44:35 +0100 Subject: [PATCH 4/6] Ensure sync thread is started when recovering from crash. --- .../session/EnsureSessionSyncingUseCase.kt | 38 +++++++++++++++++++ .../features/home/HomeActivityViewModel.kt | 4 ++ 2 files changed, 42 insertions(+) create mode 100644 vector/src/main/java/im/vector/app/core/session/EnsureSessionSyncingUseCase.kt diff --git a/vector/src/main/java/im/vector/app/core/session/EnsureSessionSyncingUseCase.kt b/vector/src/main/java/im/vector/app/core/session/EnsureSessionSyncingUseCase.kt new file mode 100644 index 00000000000..c53795d18d9 --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/session/EnsureSessionSyncingUseCase.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.core.session + +import android.content.Context +import dagger.hilt.android.qualifiers.ApplicationContext +import im.vector.app.core.di.ActiveSessionHolder +import im.vector.app.core.extensions.startSyncing +import org.matrix.android.sdk.api.session.sync.SyncState +import timber.log.Timber +import javax.inject.Inject + +class EnsureSessionSyncingUseCase @Inject constructor( + @ApplicationContext private val context: Context, + private val activeSessionHolder: ActiveSessionHolder, +) { + fun execute() { + val session = activeSessionHolder.getSafeActiveSession() ?: return + if (session.syncService().getSyncState() == SyncState.Idle) { + Timber.w("EnsureSessionSyncingUseCase: start syncing") + session.startSyncing(context) + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt index 8f16121a306..f961cc5da6d 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt @@ -30,6 +30,7 @@ import im.vector.app.core.pushers.EnsureFcmTokenIsRetrievedUseCase import im.vector.app.core.pushers.PushersManager import im.vector.app.core.pushers.RegisterUnifiedPushUseCase import im.vector.app.core.pushers.UnregisterUnifiedPushUseCase +import im.vector.app.core.session.EnsureSessionSyncingUseCase import im.vector.app.features.analytics.AnalyticsConfig import im.vector.app.features.analytics.AnalyticsTracker import im.vector.app.features.analytics.extensions.toAnalyticsType @@ -95,6 +96,7 @@ class HomeActivityViewModel @AssistedInject constructor( private val registerUnifiedPushUseCase: RegisterUnifiedPushUseCase, private val unregisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase, private val ensureFcmTokenIsRetrievedUseCase: EnsureFcmTokenIsRetrievedUseCase, + private val ensureSessionSyncingUseCase: EnsureSessionSyncingUseCase, ) : VectorViewModel(initialState) { @AssistedFactory @@ -118,6 +120,8 @@ class HomeActivityViewModel @AssistedInject constructor( private fun initialize() { if (isInitialized) return isInitialized = true + // Ensure Session is syncing + ensureSessionSyncingUseCase.execute() registerUnifiedPushIfNeeded() cleanupFiles() observeInitialSync() From d6712b7c93d11f50f001c663ab017706b0afec8c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 27 Jan 2023 17:01:52 +0100 Subject: [PATCH 5/6] Fix layout issue with `Messages failed to send` banner. --- .../src/main/res/layout/fragment_timeline.xml | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/vector/src/main/res/layout/fragment_timeline.xml b/vector/src/main/res/layout/fragment_timeline.xml index 6e83dbe8fd0..a022ad2744d 100644 --- a/vector/src/main/res/layout/fragment_timeline.xml +++ b/vector/src/main/res/layout/fragment_timeline.xml @@ -17,7 +17,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="48dp" - android:visibility="gone" /> + android:visibility="gone" + tools:visibility="visible" /> + android:layout_height="match_parent"> - - + + + android:translationZ="10dp" + android:visibility="visible" /> From 0c89245392673ddcf3cf36dd32735798061a2410 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 27 Jan 2023 18:13:27 +0100 Subject: [PATCH 6/6] Fix test compilation --- .../java/im/vector/app/features/command/CommandParserTest.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vector/src/test/java/im/vector/app/features/command/CommandParserTest.kt b/vector/src/test/java/im/vector/app/features/command/CommandParserTest.kt index f502db85caa..ef6a99aa49a 100644 --- a/vector/src/test/java/im/vector/app/features/command/CommandParserTest.kt +++ b/vector/src/test/java/im/vector/app/features/command/CommandParserTest.kt @@ -16,12 +16,15 @@ package im.vector.app.features.command +import im.vector.app.test.fakes.FakeVectorPreferences import org.amshove.kluent.shouldBeEqualTo import org.junit.Test private const val A_SPACE_ID = "!my-space-id" class CommandParserTest { + private val fakeVectorPreferences = FakeVectorPreferences() + @Test fun parseSlashCommandEmpty() { test("/", ParsedCommand.ErrorEmptySlashCommand) @@ -70,7 +73,7 @@ class CommandParserTest { } private fun test(message: String, expectedResult: ParsedCommand) { - val commandParser = CommandParser() + val commandParser = CommandParser(fakeVectorPreferences.instance) val result = commandParser.parseSlashCommand(message, null, false) result shouldBeEqualTo expectedResult }