Merge branch 'develop' into feature/fga/space_invite_notification
This commit is contained in:
commit
07d02fd076
89 changed files with 855 additions and 490 deletions
|
|
@ -17,16 +17,22 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
|||
|
||||
@Composable
|
||||
fun SaveChangesDialog(
|
||||
onSubmitClick: () -> Unit,
|
||||
onSaveClick: () -> Unit,
|
||||
onDiscardClick: () -> Unit,
|
||||
onDismiss: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
title: String = stringResource(CommonStrings.dialog_unsaved_changes_title),
|
||||
content: String = stringResource(CommonStrings.dialog_unsaved_changes_description_android),
|
||||
content: String = stringResource(CommonStrings.dialog_unsaved_changes_description),
|
||||
submitText: String = stringResource(CommonStrings.action_save),
|
||||
cancelText: String = stringResource(CommonStrings.action_discard),
|
||||
) = ConfirmationDialog(
|
||||
modifier = modifier,
|
||||
title = title,
|
||||
content = content,
|
||||
onSubmitClick = onSubmitClick,
|
||||
submitText = submitText,
|
||||
cancelText = cancelText,
|
||||
onSubmitClick = onSaveClick,
|
||||
onCancelClick = onDiscardClick,
|
||||
onDismiss = onDismiss,
|
||||
)
|
||||
|
||||
|
|
@ -34,7 +40,8 @@ fun SaveChangesDialog(
|
|||
@Composable
|
||||
internal fun SaveChangesDialogPreview() = ElementPreview {
|
||||
SaveChangesDialog(
|
||||
onSubmitClick = {},
|
||||
onSaveClick = {},
|
||||
onDiscardClick = {},
|
||||
onDismiss = {}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.di.annotations
|
||||
|
||||
@JvmInline
|
||||
value class SentrySdkDsn(val value: String)
|
||||
|
|
@ -14,4 +14,5 @@ data class TracingConfiguration(
|
|||
val traceLogPacks: Set<TraceLogPack>,
|
||||
val writesToLogcat: Boolean,
|
||||
val writesToFilesConfiguration: WriteToFilesConfiguration,
|
||||
val sdkSentryDsn: String?,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.analytics
|
||||
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.services.analytics.api.AnalyticsSdkManager
|
||||
import io.element.android.services.analytics.api.AnalyticsSdkSpan
|
||||
import org.matrix.rustcomponents.sdk.enableSentryLogging
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class RustAnalyticsSdkManager : AnalyticsSdkManager {
|
||||
override fun enableSdkAnalytics(enabled: Boolean) {
|
||||
enableSentryLogging(enabled)
|
||||
}
|
||||
|
||||
override fun startSpan(name: String, parentTraceId: String?): AnalyticsSdkSpan {
|
||||
return RustAnalyticsSdkSpan(name = name, parentTraceId = parentTraceId)
|
||||
}
|
||||
|
||||
override fun bridge(parentTraceId: String?): AnalyticsSdkSpan {
|
||||
// A bridge span has no name
|
||||
return RustAnalyticsSdkSpan(name = null, parentTraceId = parentTraceId)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.analytics
|
||||
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.services.analytics.api.AnalyticsSdkSpan
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import org.matrix.rustcomponents.sdk.LogLevel
|
||||
import org.matrix.rustcomponents.sdk.Span
|
||||
import timber.log.Timber
|
||||
|
||||
class RustAnalyticsSdkSpan(
|
||||
name: String? = null,
|
||||
private val parentTraceId: String?,
|
||||
) : AnalyticsSdkSpan {
|
||||
private val inner = if (name != null) {
|
||||
Span(
|
||||
target = "elementx",
|
||||
name = name,
|
||||
file = "-",
|
||||
line = null,
|
||||
level = LogLevel.WARN,
|
||||
bridgeTraceId = parentTraceId,
|
||||
)
|
||||
} else {
|
||||
Span.newBridgeSpan(
|
||||
target = "elementx",
|
||||
parentTraceId = parentTraceId,
|
||||
)
|
||||
}
|
||||
|
||||
override fun enter() {
|
||||
if (Span.current().isNone()) {
|
||||
inner.enter()
|
||||
} else {
|
||||
Timber.w("Not entering span sentry.trace='$parentTraceId' because another span is already active")
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
override fun exit() {
|
||||
inner.exit()
|
||||
runCatchingExceptions { inner.destroy() }
|
||||
Timber.d("Exited span sentry.trace='$parentTraceId'")
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ import io.element.android.libraries.matrix.impl.room.preview.RoomPreviewInfoMapp
|
|||
import io.element.android.libraries.matrix.impl.roomlist.roomOrNull
|
||||
import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import io.element.android.services.analytics.api.inBridgeSdkSpan
|
||||
import io.element.android.services.analytics.api.recordTransaction
|
||||
import io.element.android.services.analyticsproviders.api.recordChildTransaction
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
|
|
@ -127,17 +128,19 @@ class RustRoomFactory(
|
|||
val timeline = transaction.recordChildTransaction(
|
||||
operation = "sdkRoom.timelineWithConfiguration",
|
||||
description = "Get timeline from the SDK",
|
||||
) {
|
||||
sdkRoom.timelineWithConfiguration(
|
||||
TimelineConfiguration(
|
||||
focus = TimelineFocus.Live(hideThreadedEvents = hideThreadedEvents),
|
||||
filter = eventFilters?.let(TimelineFilter::EventTypeFilter) ?: TimelineFilter.All,
|
||||
internalIdPrefix = "live",
|
||||
dateDividerMode = DateDividerMode.DAILY,
|
||||
trackReadReceipts = TimelineReadReceiptTracking.ALL_EVENTS,
|
||||
reportUtds = true,
|
||||
) { timelineTransaction ->
|
||||
analyticsService.inBridgeSdkSpan(parentTraceId = timelineTransaction.traceId()) {
|
||||
sdkRoom.timelineWithConfiguration(
|
||||
TimelineConfiguration(
|
||||
focus = TimelineFocus.Live(hideThreadedEvents = hideThreadedEvents),
|
||||
filter = eventFilters?.let(TimelineFilter::EventTypeFilter) ?: TimelineFilter.All,
|
||||
internalIdPrefix = "live",
|
||||
dateDividerMode = DateDividerMode.DAILY,
|
||||
trackReadReceipts = TimelineReadReceiptTracking.ALL_EVENTS,
|
||||
reportUtds = true,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
GetRoomResult.Joined(
|
||||
|
|
|
|||
|
|
@ -60,5 +60,5 @@ fun TracingConfiguration.map(): org.matrix.rustcomponents.sdk.TracingConfigurati
|
|||
extraTargets = extraTargets,
|
||||
traceLogPacks = traceLogPacks.map(),
|
||||
writeToFiles = writesToFilesConfiguration.toTracingFileConfiguration(),
|
||||
sentryDsn = null,
|
||||
sentryDsn = sdkSentryDsn,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.test.analytics
|
||||
|
||||
import io.element.android.services.analytics.api.AnalyticsSdkManager
|
||||
import io.element.android.services.analytics.api.AnalyticsSdkSpan
|
||||
import io.element.android.services.analytics.api.NoopAnalyticsSdkSpan
|
||||
import io.element.android.tests.testutils.lambda.lambdaError
|
||||
|
||||
class FakeAnalyticsSdkManager(
|
||||
private val enableSdkAnalyticsLambda: ((Boolean) -> Unit) = { lambdaError() },
|
||||
) : AnalyticsSdkManager {
|
||||
override fun enableSdkAnalytics(enabled: Boolean) {
|
||||
enableSdkAnalyticsLambda(enabled)
|
||||
}
|
||||
|
||||
override fun startSpan(name: String, parentTraceId: String?): AnalyticsSdkSpan = NoopAnalyticsSdkSpan
|
||||
override fun bridge(parentTraceId: String?): AnalyticsSdkSpan = NoopAnalyticsSdkSpan
|
||||
}
|
||||
|
|
@ -392,6 +392,7 @@ Are you sure you want to continue?"</string>
|
|||
<string name="dialog_title_error">"Error"</string>
|
||||
<string name="dialog_title_success">"Success"</string>
|
||||
<string name="dialog_title_warning">"Warning"</string>
|
||||
<string name="dialog_unsaved_changes_description">"You have unsaved changes."</string>
|
||||
<string name="dialog_unsaved_changes_description_android">"Your changes have not been saved. Are you sure you want to go back?"</string>
|
||||
<string name="dialog_unsaved_changes_title">"Save changes?"</string>
|
||||
<string name="dialog_video_quality_selector_subtitle_file_size">"The max file size allowed is: %1$s"</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue