Merge branch 'develop' into poljar/log-olm-trace
This commit is contained in:
commit
1288c42bb2
19 changed files with 69 additions and 100 deletions
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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 = {
|
||||||
|
|
|
||||||
|
|
@ -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 = {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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 = {}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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 ->
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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("")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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" }
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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(":", "_")
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue