Merge branch 'develop' into poljar/log-olm-trace

This commit is contained in:
Jorge Martin Espinosa 2024-02-08 09:50:58 +01:00 committed by GitHub
commit 1288c42bb2
19 changed files with 69 additions and 100 deletions

View file

@ -28,6 +28,7 @@ import io.element.android.features.rageshake.test.crash.FakeCrashDataStore
import io.element.android.features.rageshake.test.rageshake.FakeRageShake import io.element.android.features.rageshake.test.rageshake.FakeRageShake
import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataStore import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataStore
import io.element.android.features.rageshake.test.screenshot.FakeScreenshotHolder import io.element.android.features.rageshake.test.screenshot.FakeScreenshotHolder
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.services.apperror.api.AppErrorState import io.element.android.services.apperror.api.AppErrorState
import io.element.android.services.apperror.api.AppErrorStateService import io.element.android.services.apperror.api.AppErrorStateService
import io.element.android.services.apperror.impl.DefaultAppErrorStateService import io.element.android.services.apperror.impl.DefaultAppErrorStateService
@ -83,6 +84,7 @@ class RootPresenterTest {
val rageshake = FakeRageShake() val rageshake = FakeRageShake()
val screenshotHolder = FakeScreenshotHolder() val screenshotHolder = FakeScreenshotHolder()
val crashDetectionPresenter = DefaultCrashDetectionPresenter( val crashDetectionPresenter = DefaultCrashDetectionPresenter(
buildMeta = aBuildMeta(),
crashDataStore = crashDataStore crashDataStore = crashDataStore
) )
val rageshakeDetectionPresenter = DefaultRageshakeDetectionPresenter( val rageshakeDetectionPresenter = DefaultRageshakeDetectionPresenter(

View file

@ -57,7 +57,6 @@ import io.element.android.libraries.designsystem.theme.components.ButtonSize
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.temporaryColorBgSpecial import io.element.android.libraries.designsystem.theme.temporaryColorBgSpecial
import io.element.android.libraries.designsystem.utils.LogCompositions
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
@ -67,7 +66,6 @@ fun AnalyticsOptInView(
onClickTerms: () -> Unit, onClickTerms: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
LogCompositions(tag = "Analytics", msg = "Root")
val eventSink = state.eventSink val eventSink = state.eventSink
fun onTermsAccepted() { fun onTermsAccepted() {

View file

@ -86,7 +86,7 @@ fun LogoutView(
onForceLogoutClicked = { onForceLogoutClicked = {
eventSink(LogoutEvents.Logout(ignoreSdkError = true)) eventSink(LogoutEvents.Logout(ignoreSdkError = true))
}, },
onDismissError = { onDismissDialog = {
eventSink(LogoutEvents.CloseDialogs) eventSink(LogoutEvents.CloseDialogs)
}, },
onSuccessLogout = { onSuccessLogout = {

View file

@ -41,7 +41,7 @@ class DefaultDirectLogoutView @Inject constructor() : DirectLogoutView {
onForceLogoutClicked = { onForceLogoutClicked = {
eventSink(DirectLogoutEvents.Logout(ignoreSdkError = true)) eventSink(DirectLogoutEvents.Logout(ignoreSdkError = true))
}, },
onDismissError = { onDismissDialog = {
eventSink(DirectLogoutEvents.CloseDialogs) eventSink(DirectLogoutEvents.CloseDialogs)
}, },
onSuccessLogout = { onSuccessLogout = {

View file

@ -32,8 +32,7 @@ fun LogoutActionDialog(
state: AsyncAction<String?>, state: AsyncAction<String?>,
onConfirmClicked: () -> Unit, onConfirmClicked: () -> Unit,
onForceLogoutClicked: () -> Unit, onForceLogoutClicked: () -> Unit,
// TODO Rename onDismissDialog: () -> Unit,
onDismissError: () -> Unit,
onSuccessLogout: (String?) -> Unit, onSuccessLogout: (String?) -> Unit,
) { ) {
when (state) { when (state) {
@ -42,7 +41,7 @@ fun LogoutActionDialog(
AsyncAction.Confirming -> AsyncAction.Confirming ->
LogoutConfirmationDialog( LogoutConfirmationDialog(
onSubmitClicked = onConfirmClicked, onSubmitClicked = onConfirmClicked,
onDismiss = onDismissError onDismiss = onDismissDialog
) )
is AsyncAction.Loading -> is AsyncAction.Loading ->
ProgressDialog(text = stringResource(id = R.string.screen_signout_in_progress_dialog_content)) ProgressDialog(text = stringResource(id = R.string.screen_signout_in_progress_dialog_content))
@ -52,7 +51,7 @@ fun LogoutActionDialog(
content = stringResource(id = CommonStrings.error_unknown), content = stringResource(id = CommonStrings.error_unknown),
retryText = stringResource(id = CommonStrings.action_signout_anyway), retryText = stringResource(id = CommonStrings.action_signout_anyway),
onRetry = onForceLogoutClicked, onRetry = onForceLogoutClicked,
onDismiss = onDismissError, onDismiss = onDismissDialog,
) )
is AsyncAction.Success -> { is AsyncAction.Success -> {
val latestOnSuccessLogout by rememberUpdatedState(onSuccessLogout) val latestOnSuccessLogout by rememberUpdatedState(onSuccessLogout)

View file

@ -102,7 +102,6 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.KeepScreenOn import io.element.android.libraries.designsystem.utils.KeepScreenOn
import io.element.android.libraries.designsystem.utils.LogCompositions
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
@ -127,8 +126,6 @@ fun MessagesView(
onJoinCallClicked: () -> Unit, onJoinCallClicked: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
LogCompositions(tag = "MessagesScreen", msg = "Root")
OnLifecycleEvent { _, event -> OnLifecycleEvent { _, event ->
state.voiceMessageComposerState.eventSink(VoiceMessageComposerEvents.LifecycleEvent(event)) state.voiceMessageComposerState.eventSink(VoiceMessageComposerEvents.LifecycleEvent(event))
} }
@ -146,8 +143,6 @@ fun MessagesView(
// This is needed because the composer is inside an AndroidView that can't be affected by the FocusManager in Compose // This is needed because the composer is inside an AndroidView that can't be affected by the FocusManager in Compose
val localView = LocalView.current val localView = LocalView.current
LogCompositions(tag = "MessagesScreen", msg = "Content")
fun onMessageClicked(event: TimelineItem.Event) { fun onMessageClicked(event: TimelineItem.Event) {
Timber.v("OnMessageClicked= ${event.id}") Timber.v("OnMessageClicked= ${event.id}")
val hideKeyboard = onEventClicked(event) val hideKeyboard = onEventClicked(event)

View file

@ -20,6 +20,7 @@ import androidx.compose.runtime.Immutable
@Immutable @Immutable
data class CrashDetectionState( data class CrashDetectionState(
val appName: String,
val crashDetected: Boolean, val crashDetected: Boolean,
val eventSink: (CrashDetectionEvents) -> Unit val eventSink: (CrashDetectionEvents) -> Unit
) )

View file

@ -17,6 +17,7 @@
package io.element.android.features.rageshake.api.crash package io.element.android.features.rageshake.api.crash
fun aCrashDetectionState() = CrashDetectionState( fun aCrashDetectionState() = CrashDetectionState(
appName = "Element",
crashDetected = false, crashDetected = false,
eventSink = {} eventSink = {}
) )

View file

@ -22,7 +22,6 @@ import io.element.android.features.rageshake.api.R
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.utils.LogCompositions
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
@ -30,17 +29,13 @@ fun CrashDetectionView(
state: CrashDetectionState, state: CrashDetectionState,
onOpenBugReport: () -> Unit = { }, onOpenBugReport: () -> Unit = { },
) { ) {
LogCompositions(
tag = "Crash",
msg = "CrashDetectionScreen"
)
fun onPopupDismissed() { fun onPopupDismissed() {
state.eventSink(CrashDetectionEvents.ResetAllCrashData) state.eventSink(CrashDetectionEvents.ResetAllCrashData)
} }
if (state.crashDetected) { if (state.crashDetected) {
CrashDetectionContent( CrashDetectionContent(
appName = state.appName,
onYesClicked = onOpenBugReport, onYesClicked = onOpenBugReport,
onNoClicked = ::onPopupDismissed, onNoClicked = ::onPopupDismissed,
onDismiss = ::onPopupDismissed, onDismiss = ::onPopupDismissed,
@ -50,14 +45,14 @@ fun CrashDetectionView(
@Composable @Composable
private fun CrashDetectionContent( private fun CrashDetectionContent(
appName: String,
onNoClicked: () -> Unit = { }, onNoClicked: () -> Unit = { },
onYesClicked: () -> Unit = { }, onYesClicked: () -> Unit = { },
onDismiss: () -> Unit = { }, onDismiss: () -> Unit = { },
) { ) {
ConfirmationDialog( ConfirmationDialog(
title = stringResource(id = CommonStrings.action_report_bug), title = stringResource(id = CommonStrings.action_report_bug),
// TODO Replace with app name content = stringResource(id = R.string.crash_detection_dialog_content, appName),
content = stringResource(id = R.string.crash_detection_dialog_content, "Element"),
submitText = stringResource(id = CommonStrings.action_yes), submitText = stringResource(id = CommonStrings.action_yes),
cancelText = stringResource(id = CommonStrings.action_no), cancelText = stringResource(id = CommonStrings.action_no),
onCancelClicked = onNoClicked, onCancelClicked = onNoClicked,

View file

@ -31,7 +31,6 @@ import io.element.android.libraries.androidutils.hardware.vibrate
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.utils.LogCompositions
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -40,10 +39,6 @@ fun RageshakeDetectionView(
state: RageshakeDetectionState, state: RageshakeDetectionState,
onOpenBugReport: () -> Unit = { }, onOpenBugReport: () -> Unit = { },
) { ) {
LogCompositions(
tag = "Rageshake",
msg = "RageshakeDetectionScreen"
)
val eventSink = state.eventSink val eventSink = state.eventSink
val context = LocalContext.current val context = LocalContext.current
OnLifecycleEvent { _, event -> OnLifecycleEvent { _, event ->

View file

@ -51,7 +51,6 @@ import io.element.android.libraries.designsystem.preview.debugPlaceholderBackgro
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.LogCompositions
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
@ -62,7 +61,6 @@ fun BugReportView(
onBackPressed: () -> Unit, onBackPressed: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
LogCompositions(tag = "Rageshake", msg = "Root")
val eventSink = state.eventSink val eventSink = state.eventSink
Box(modifier = modifier) { Box(modifier = modifier) {

View file

@ -24,13 +24,17 @@ import io.element.android.features.rageshake.api.crash.CrashDataStore
import io.element.android.features.rageshake.api.crash.CrashDetectionEvents import io.element.android.features.rageshake.api.crash.CrashDetectionEvents
import io.element.android.features.rageshake.api.crash.CrashDetectionPresenter import io.element.android.features.rageshake.api.crash.CrashDetectionPresenter
import io.element.android.features.rageshake.api.crash.CrashDetectionState import io.element.android.features.rageshake.api.crash.CrashDetectionState
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
class DefaultCrashDetectionPresenter @Inject constructor(private val crashDataStore: CrashDataStore) : class DefaultCrashDetectionPresenter @Inject constructor(
private val buildMeta: BuildMeta,
private val crashDataStore: CrashDataStore,
) :
CrashDetectionPresenter { CrashDetectionPresenter {
@Composable @Composable
override fun present(): CrashDetectionState { override fun present(): CrashDetectionState {
@ -45,6 +49,7 @@ class DefaultCrashDetectionPresenter @Inject constructor(private val crashDataSt
} }
return CrashDetectionState( return CrashDetectionState(
appName = buildMeta.applicationName,
crashDetected = crashDetected.value, crashDetected = crashDetected.value,
eventSink = ::handleEvents eventSink = ::handleEvents
) )

View file

@ -24,6 +24,8 @@ import io.element.android.features.rageshake.api.crash.CrashDetectionEvents
import io.element.android.features.rageshake.impl.crash.DefaultCrashDetectionPresenter import io.element.android.features.rageshake.impl.crash.DefaultCrashDetectionPresenter
import io.element.android.features.rageshake.test.crash.A_CRASH_DATA import io.element.android.features.rageshake.test.crash.A_CRASH_DATA
import io.element.android.features.rageshake.test.crash.FakeCrashDataStore import io.element.android.features.rageshake.test.crash.FakeCrashDataStore
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Rule import org.junit.Rule
@ -35,9 +37,7 @@ class CrashDetectionPresenterTest {
@Test @Test
fun `present - initial state no crash`() = runTest { fun `present - initial state no crash`() = runTest {
val presenter = DefaultCrashDetectionPresenter( val presenter = createPresenter()
FakeCrashDataStore()
)
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
}.test { }.test {
@ -48,7 +48,7 @@ class CrashDetectionPresenterTest {
@Test @Test
fun `present - initial state crash`() = runTest { fun `present - initial state crash`() = runTest {
val presenter = DefaultCrashDetectionPresenter( val presenter = createPresenter(
FakeCrashDataStore(appHasCrashed = true) FakeCrashDataStore(appHasCrashed = true)
) )
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
@ -62,7 +62,7 @@ class CrashDetectionPresenterTest {
@Test @Test
fun `present - reset app has crashed`() = runTest { fun `present - reset app has crashed`() = runTest {
val presenter = DefaultCrashDetectionPresenter( val presenter = createPresenter(
FakeCrashDataStore(appHasCrashed = true) FakeCrashDataStore(appHasCrashed = true)
) )
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
@ -78,7 +78,7 @@ class CrashDetectionPresenterTest {
@Test @Test
fun `present - reset all crash data`() = runTest { fun `present - reset all crash data`() = runTest {
val presenter = DefaultCrashDetectionPresenter( val presenter = createPresenter(
FakeCrashDataStore(appHasCrashed = true, crashData = A_CRASH_DATA) FakeCrashDataStore(appHasCrashed = true, crashData = A_CRASH_DATA)
) )
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
@ -91,4 +91,12 @@ class CrashDetectionPresenterTest {
assertThat(awaitItem().crashDetected).isFalse() assertThat(awaitItem().crashDetected).isFalse()
} }
} }
private fun createPresenter(
crashDataStore: FakeCrashDataStore = FakeCrashDataStore(),
buildMeta: BuildMeta = aBuildMeta(),
) = DefaultCrashDetectionPresenter(
buildMeta = buildMeta,
crashDataStore = crashDataStore,
)
} }

View file

@ -67,7 +67,6 @@ import io.element.android.libraries.designsystem.theme.components.IconSource
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.designsystem.utils.LogCompositions
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
@ -190,11 +189,6 @@ private fun RoomListContent(
} }
} }
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(appBarState) val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(appBarState)
LogCompositions(
tag = "RoomListScreen",
msg = "Content"
)
val nestedScrollConnection = remember { val nestedScrollConnection = remember {
object : NestedScrollConnection { object : NestedScrollConnection {
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity { override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {

View file

@ -69,7 +69,6 @@ import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.MediumTopAppBar import io.element.android.libraries.designsystem.theme.components.MediumTopAppBar
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.LogCompositions
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.model.getAvatarData
@ -92,11 +91,6 @@ fun RoomListTopBar(
scrollBehavior: TopAppBarScrollBehavior, scrollBehavior: TopAppBarScrollBehavior,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
LogCompositions(
tag = "RoomListScreen",
msg = "TopBar"
)
fun closeFilter() { fun closeFilter() {
onFilterChanged("") onFilterChanged("")
} }

View file

@ -142,7 +142,7 @@ coil = { module = "io.coil-kt:coil", version.ref = "coil" }
coil_compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" } coil_compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
coil_gif = { module = "io.coil-kt:coil-gif", version.ref = "coil" } coil_gif = { module = "io.coil-kt:coil-gif", version.ref = "coil" }
coil_test = { module = "io.coil-kt:coil-test", version.ref = "coil" } coil_test = { module = "io.coil-kt:coil-test", version.ref = "coil" }
compound = { module = "io.element.android:compound-android", version = "0.0.3" } compound = { module = "io.element.android:compound-android", version = "0.0.4" }
datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime" } datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime" }
serialization_json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization_json" } serialization_json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization_json" }
kotlinx_collections_immutable = "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.7" kotlinx_collections_immutable = "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.7"
@ -152,7 +152,7 @@ jsoup = "org.jsoup:jsoup:1.17.2"
appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" }
molecule-runtime = "app.cash.molecule:molecule-runtime:1.3.2" molecule-runtime = "app.cash.molecule:molecule-runtime:1.3.2"
timber = "com.jakewharton.timber:timber:5.0.1" timber = "com.jakewharton.timber:timber:5.0.1"
matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.97" matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.98"
matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" }
matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" }
sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" }

View file

@ -1,39 +0,0 @@
/*
* Copyright (c) 2023 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 io.element.android.libraries.designsystem.utils
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.remember
import io.element.android.libraries.designsystem.BuildConfig
import timber.log.Timber
// Note the inline function below which ensures that this function is essentially
// copied at the call site to ensure that its logging only recompositions from the
// original call site.
@Composable
fun LogCompositions(tag: String, msg: String) {
if (BuildConfig.DEBUG) {
val ref = remember { Ref() }
SideEffect { ref.value++ }
Timber.tag(tag).d("Compositions: $msg ${ref.value}")
}
}
private class Ref {
var value: Int = 0
}

View file

@ -60,6 +60,7 @@ import io.element.android.libraries.matrix.impl.roomlist.roomOrNull
import io.element.android.libraries.matrix.impl.sync.RustSyncService import io.element.android.libraries.matrix.impl.sync.RustSyncService
import io.element.android.libraries.matrix.impl.usersearch.UserProfileMapper import io.element.android.libraries.matrix.impl.usersearch.UserProfileMapper
import io.element.android.libraries.matrix.impl.usersearch.UserSearchResultMapper import io.element.android.libraries.matrix.impl.usersearch.UserSearchResultMapper
import io.element.android.libraries.matrix.impl.util.SessionDirectoryNameProvider
import io.element.android.libraries.matrix.impl.util.cancelAndDestroy import io.element.android.libraries.matrix.impl.util.cancelAndDestroy
import io.element.android.libraries.matrix.impl.verification.RustSessionVerificationService import io.element.android.libraries.matrix.impl.verification.RustSessionVerificationService
import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.api.SessionStore
@ -134,6 +135,7 @@ class RustMatrixClient(
sessionCoroutineScope = sessionCoroutineScope, sessionCoroutineScope = sessionCoroutineScope,
dispatchers = dispatchers, dispatchers = dispatchers,
).apply { start() } ).apply { start() }
private val sessionDirectoryNameProvider = SessionDirectoryNameProvider()
private val isLoggingOut = AtomicBoolean(false) private val isLoggingOut = AtomicBoolean(false)
@ -397,13 +399,12 @@ class RustMatrixClient(
} }
override suspend fun getCacheSize(): Long { override suspend fun getCacheSize(): Long {
// Do not use client.userId since it can throw if client has been closed (during clear cache) return baseDirectory.getCacheSize()
return baseDirectory.getCacheSize(userID = sessionId.value)
} }
override suspend fun clearCache() { override suspend fun clearCache() {
close() close()
baseDirectory.deleteSessionDirectory(userID = sessionId.value, deleteCryptoDb = false) baseDirectory.deleteSessionDirectory(deleteCryptoDb = false)
} }
override suspend fun logout(ignoreSdkError: Boolean): String? = doLogout( override suspend fun logout(ignoreSdkError: Boolean): String? = doLogout(
@ -432,7 +433,7 @@ class RustMatrixClient(
} }
} }
close() close()
baseDirectory.deleteSessionDirectory(userID = sessionId.value, deleteCryptoDb = true) baseDirectory.deleteSessionDirectory(deleteCryptoDb = true)
if (removeSession) { if (removeSession) {
sessionStore.removeSession(sessionId.value) sessionStore.removeSession(sessionId.value)
} }
@ -478,12 +479,10 @@ class RustMatrixClient(
override fun roomMembershipObserver(): RoomMembershipObserver = roomMembershipObserver override fun roomMembershipObserver(): RoomMembershipObserver = roomMembershipObserver
private suspend fun File.getCacheSize( private suspend fun File.getCacheSize(
userID: String,
includeCryptoDb: Boolean = false, includeCryptoDb: Boolean = false,
): Long = withContext(sessionDispatcher) { ): Long = withContext(sessionDispatcher) {
// Rust sanitises the user ID replacing invalid characters with an _ val sessionDirectoryName = sessionDirectoryNameProvider.provides(sessionId)
val sanitisedUserID = userID.replace(":", "_") val sessionDirectory = File(this@getCacheSize, sessionDirectoryName)
val sessionDirectory = File(this@getCacheSize, sanitisedUserID)
if (includeCryptoDb) { if (includeCryptoDb) {
sessionDirectory.getSizeOfFiles() sessionDirectory.getSizeOfFiles()
} else { } else {
@ -500,12 +499,10 @@ class RustMatrixClient(
} }
private suspend fun File.deleteSessionDirectory( private suspend fun File.deleteSessionDirectory(
userID: String,
deleteCryptoDb: Boolean = false, deleteCryptoDb: Boolean = false,
): Boolean = withContext(sessionDispatcher) { ): Boolean = withContext(sessionDispatcher) {
// Rust sanitises the user ID replacing invalid characters with an _ val sessionDirectoryName = sessionDirectoryNameProvider.provides(sessionId)
val sanitisedUserID = userID.replace(":", "_") val sessionDirectory = File(this@deleteSessionDirectory, sessionDirectoryName)
val sessionDirectory = File(this@deleteSessionDirectory, sanitisedUserID)
if (deleteCryptoDb) { if (deleteCryptoDb) {
// Delete the folder and all its content // Delete the folder and all its content
sessionDirectory.deleteRecursively() sessionDirectory.deleteRecursively()

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2024 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 io.element.android.libraries.matrix.impl.util
import io.element.android.libraries.matrix.api.core.SessionId
class SessionDirectoryNameProvider {
// Rust sanitises the user ID replacing invalid characters with an _
fun provides(sessionId: SessionId): String {
return sessionId.value.replace(":", "_")
}
}