Skip to content

Commit

Permalink
feat: Add debug button send FCM token #WPB-9476 (#3482)
Browse files Browse the repository at this point in the history
  • Loading branch information
damian-kaczmarek authored Oct 10, 2024
1 parent db79f55 commit 0b8afe7
Show file tree
Hide file tree
Showing 9 changed files with 374 additions and 24 deletions.
5 changes: 5 additions & 0 deletions app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -487,4 +487,9 @@ class UseCaseModule {
@Provides
fun provideBreakSessionUseCase(@KaliumCoreLogic coreLogic: CoreLogic, @CurrentAccount currentAccount: UserId): BreakSessionUseCase =
coreLogic.getSessionScope(currentAccount).debug.breakSession

@ViewModelScoped
@Provides
fun provideSendFCMTokenToAPIUseCase(@KaliumCoreLogic coreLogic: CoreLogic, @CurrentAccount currentAccount: UserId) =
coreLogic.getSessionScope(currentAccount).debug.sendFCMTokenToServer
}
58 changes: 54 additions & 4 deletions app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.wire.android.BuildConfig
import com.wire.android.R
import com.wire.android.di.hiltViewModelScoped
Expand All @@ -38,9 +39,12 @@ import com.wire.android.ui.common.WireDialogButtonType
import com.wire.android.ui.common.WireSwitch
import com.wire.android.ui.common.button.WirePrimaryButton
import com.wire.android.ui.common.dimensions
import com.wire.android.ui.common.snackbar.LocalSnackbarHostState
import com.wire.android.ui.common.snackbar.collectAndShowSnackbar
import com.wire.android.ui.e2eiEnrollment.GetE2EICertificateUI
import com.wire.android.ui.home.conversationslist.common.FolderHeader
import com.wire.android.ui.home.settings.SettingsItem
import com.wire.android.ui.theme.WireTheme
import com.wire.android.ui.theme.wireColorScheme
import com.wire.android.ui.theme.wireDimensions
import com.wire.android.ui.theme.wireTypography
Expand All @@ -59,6 +63,7 @@ fun DebugDataOptions(
hiltViewModelScoped<DebugDataOptionsViewModelImpl, DebugDataOptionsViewModel, DebugDataOptions>(DebugDataOptions),
onManualMigrationPressed: (currentAccount: UserId) -> Unit
) {
LocalSnackbarHostState.current.collectAndShowSnackbar(snackbarFlow = viewModel.infoMessage)
DebugDataOptionsContent(
state = viewModel.state(),
appVersion = appVersion,
Expand All @@ -73,6 +78,7 @@ fun DebugDataOptions(
handleE2EIEnrollmentResult = viewModel::handleE2EIEnrollmentResult,
dismissCertificateDialog = viewModel::dismissCertificateDialog,
checkCrlRevocationList = viewModel::checkCrlRevocationList,
onResendFCMToken = viewModel::forceSendFCMToken
)
}

Expand All @@ -92,8 +98,10 @@ fun DebugDataOptionsContent(
handleE2EIEnrollmentResult: (Either<CoreFailure, E2EIEnrollmentResult>) -> Unit,
dismissCertificateDialog: () -> Unit,
checkCrlRevocationList: () -> Unit,
onResendFCMToken: () -> Unit,
modifier: Modifier = Modifier,
) {
Column {
Column(modifier = modifier) {

FolderHeader(stringResource(R.string.label_debug_data))

Expand Down Expand Up @@ -194,7 +202,8 @@ fun DebugDataOptionsContent(
onDisableEventProcessingChange = onDisableEventProcessingChange,
onRestartSlowSyncForRecovery = onRestartSlowSyncForRecovery,
onForceUpdateApiVersions = onForceUpdateApiVersions,
checkCrlRevocationList = checkCrlRevocationList
checkCrlRevocationList = checkCrlRevocationList,
onResendFCMToken = onResendFCMToken,
)
}

Expand Down Expand Up @@ -357,13 +366,30 @@ private fun EnableEncryptedProteusStorageSwitch(
//endregion

//region Debug Tools

@Preview
@Composable
private fun DebugToolsOptionsPreview() {
WireTheme {
DebugToolsOptions(
isEventProcessingEnabled = true,
onDisableEventProcessingChange = {},
onRestartSlowSyncForRecovery = {},
onForceUpdateApiVersions = {},
checkCrlRevocationList = {},
onResendFCMToken = {},
)
}
}

@Composable
private fun DebugToolsOptions(
isEventProcessingEnabled: Boolean,
onDisableEventProcessingChange: (Boolean) -> Unit,
onRestartSlowSyncForRecovery: () -> Unit,
onForceUpdateApiVersions: () -> Unit,
checkCrlRevocationList: () -> Unit
checkCrlRevocationList: () -> Unit,
onResendFCMToken: () -> Unit,
) {
FolderHeader(stringResource(R.string.label_debug_tools_title))
Column {
Expand Down Expand Up @@ -434,6 +460,29 @@ private fun DebugToolsOptions(
)
}
)

if (BuildConfig.PRIVATE_BUILD) {
RowItemTemplate(
modifier = Modifier.wrapContentWidth(),
title = {
Text(
style = MaterialTheme.wireTypography.body01,
color = MaterialTheme.wireColorScheme.onBackground,
text = stringResource(R.string.debug_settings_register_fcm_push_token),
modifier = Modifier.padding(start = dimensions().spacing8x)
)
},
actions = {
WirePrimaryButton(
minSize = MaterialTheme.wireDimensions.buttonMediumMinSize,
minClickableSize = MaterialTheme.wireDimensions.buttonMinClickableSize,
onClick = onResendFCMToken,
text = stringResource(R.string.debug_settings_force_api_versioning_update_button_text),
fillMaxWidth = false
)
}
)
}
}
}

Expand Down Expand Up @@ -469,7 +518,7 @@ private fun DisableEventProcessingSwitch(

@PreviewMultipleThemes
@Composable
fun PreviewOtherDebugOptions() {
fun PreviewOtherDebugOptions() = WireTheme {
DebugDataOptionsContent(
appVersion = "1.0.0",
buildVariant = "debug",
Expand All @@ -492,5 +541,6 @@ fun PreviewOtherDebugOptions() {
handleE2EIEnrollmentResult = {},
dismissCertificateDialog = {},
checkCrlRevocationList = {},
onResendFCMToken = {}
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ import com.wire.android.di.CurrentAccount
import com.wire.android.di.ScopedArgs
import com.wire.android.di.ViewModelScopedPreview
import com.wire.android.migration.failure.UserMigrationStatus
import com.wire.android.util.dispatchers.DispatcherProvider
import com.wire.android.util.getDeviceIdString
import com.wire.android.util.getGitBuildId
import com.wire.android.util.ui.UIText
import com.wire.kalium.logic.CoreFailure
import com.wire.kalium.logic.E2EIFailure
import com.wire.kalium.logic.data.user.UserId
Expand All @@ -38,20 +40,26 @@ import com.wire.kalium.logic.feature.e2ei.CheckCrlRevocationListUseCase
import com.wire.kalium.logic.feature.e2ei.usecase.E2EIEnrollmentResult
import com.wire.kalium.logic.feature.keypackage.MLSKeyPackageCountResult
import com.wire.kalium.logic.feature.keypackage.MLSKeyPackageCountUseCase
import com.wire.kalium.logic.feature.notificationToken.SendFCMTokenError
import com.wire.kalium.logic.feature.notificationToken.SendFCMTokenUseCase
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.fold
import com.wire.kalium.logic.sync.periodic.UpdateApiVersionsScheduler
import com.wire.kalium.logic.sync.slow.RestartSlowSyncProcessForRecoveryUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
import javax.inject.Inject

@ViewModelScopedPreview
interface DebugDataOptionsViewModel {

val infoMessage: SharedFlow<UIText> get() = MutableSharedFlow()
fun state(): DebugDataOptionsState = DebugDataOptionsState()
fun currentAccount(): UserId = UserId("value", "domain")
fun checkCrlRevocationList() {}
Expand All @@ -62,6 +70,7 @@ interface DebugDataOptionsViewModel {
fun dismissCertificateDialog() {}
fun forceUpdateApiVersions() {}
fun disableEventProcessing(disabled: Boolean) {}
fun forceSendFCMToken() {}
}

@Suppress("LongParameterList", "TooManyFunctions")
Expand All @@ -75,13 +84,18 @@ class DebugDataOptionsViewModelImpl
private val mlsKeyPackageCount: MLSKeyPackageCountUseCase,
private val restartSlowSyncProcessForRecovery: RestartSlowSyncProcessForRecoveryUseCase,
private val checkCrlRevocationList: CheckCrlRevocationListUseCase,
private val getCurrentAnalyticsTrackingIdentifier: GetCurrentAnalyticsTrackingIdentifierUseCase
private val getCurrentAnalyticsTrackingIdentifier: GetCurrentAnalyticsTrackingIdentifierUseCase,
private val sendFCMToken: SendFCMTokenUseCase,
private val dispatcherProvider: DispatcherProvider,
) : ViewModel(), DebugDataOptionsViewModel {

var state by mutableStateOf(
DebugDataOptionsState()
)

private val _infoMessage = MutableSharedFlow<UIText>()
override val infoMessage = _infoMessage.asSharedFlow()

init {
observeEncryptedProteusStorageState()
observeMlsMetadata()
Expand Down Expand Up @@ -181,6 +195,34 @@ class DebugDataOptionsViewModelImpl
}
}

override fun forceSendFCMToken() {
viewModelScope.launch {
withContext(dispatcherProvider.io()) {
val result = sendFCMToken()
result.fold(
{
when (it.status) {
SendFCMTokenError.Reason.CANT_GET_CLIENT_ID -> {
_infoMessage.emit(UIText.DynamicString("Can't get client ID, error: ${it.error}"))
}

SendFCMTokenError.Reason.CANT_GET_NOTIFICATION_TOKEN -> {
_infoMessage.emit(UIText.DynamicString("Can't get notification token, error: ${it.error}"))
}

SendFCMTokenError.Reason.CANT_REGISTER_TOKEN -> {
_infoMessage.emit(UIText.DynamicString("Can't register token, error: ${it.error}"))
}
}
},
{
_infoMessage.emit(UIText.DynamicString("Token registered"))
}
)
}
}
}

//region Private
private fun observeEncryptedProteusStorageState() {
viewModelScope.launch {
Expand Down
29 changes: 26 additions & 3 deletions app/src/main/kotlin/com/wire/android/ui/debug/DebugScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,21 @@ import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import com.ramcosta.composedestinations.annotation.RootNavGraph
import com.wire.android.BuildConfig
import com.wire.android.R
import com.wire.android.navigation.BackStackMode
import com.wire.android.navigation.NavigationCommand
import com.wire.android.navigation.Navigator
import com.wire.android.navigation.WireDestination
import com.wire.android.ui.common.dimensions
import com.wire.android.ui.common.scaffold.WireScaffold
import com.wire.android.navigation.WireDestination
import com.wire.android.ui.common.topappbar.NavigationIconType
import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar
import com.wire.android.ui.destinations.MigrationScreenDestination
import com.wire.android.ui.theme.WireTheme
import com.wire.android.util.getMimeType
import com.wire.android.util.getUrisOfFilesInDirectory
import com.wire.android.util.multipleFileSharingIntent
Expand All @@ -61,7 +63,12 @@ fun DebugScreen(navigator: Navigator, userDebugViewModel: UserDebugViewModel = h
UserDebugContent(
onNavigationPressed = navigator::navigateBack,
onManualMigrationPressed = {
navigator.navigate(NavigationCommand(MigrationScreenDestination(it), BackStackMode.CLEAR_WHOLE))
navigator.navigate(
NavigationCommand(
MigrationScreenDestination(it),
BackStackMode.CLEAR_WHOLE
)
)
},
state = userDebugViewModel.state,
onLoggingEnabledChange = userDebugViewModel::setLoggingEnabledState,
Expand Down Expand Up @@ -146,7 +153,8 @@ data class DebugContentState(

fun shareLogs() {
val dir = File(logPath).parentFile
val fileUris = context.getUrisOfFilesInDirectory(dir)
val fileUris =
if (dir != null && dir.exists()) context.getUrisOfFilesInDirectory(dir) else arrayListOf()
val intent = context.multipleFileSharingIntent(fileUris)
// The first log file is simply text, not compressed. Get its mime type separately
// and set it as the mime type for the intent.
Expand All @@ -157,3 +165,18 @@ data class DebugContentState(
context.startActivity(intent)
}
}

@Preview(heightDp = 1400)
@Composable
internal fun PreviewUserDebugContent() = WireTheme {
UserDebugContent(
state = UserDebugState(
isLoggingEnabled = true,
logPath = "/data/user/0/com.wire.android/files/logs"
),
onNavigationPressed = {},
onManualMigrationPressed = {},
onLoggingEnabledChange = {},
onDeleteLogs = {}
)
}
9 changes: 5 additions & 4 deletions app/src/main/kotlin/com/wire/android/ui/debug/LogOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ fun LogOptions(
isLoggingEnabled: Boolean,
onLoggingEnabledChange: (Boolean) -> Unit,
onDeleteLogs: () -> Unit,
onShareLogs: () -> Unit
onShareLogs: () -> Unit,
modifier: Modifier = Modifier,
) {
Column {
Column(modifier = modifier) {
FolderHeader(stringResource(R.string.label_logs_option_title))
EnableLoggingSwitch(
isEnabled = isLoggingEnabled,
Expand Down Expand Up @@ -82,9 +83,9 @@ fun LogOptions(

@Composable
private fun EnableLoggingSwitch(
isEnabled: Boolean = false,
onCheckedChange: ((Boolean) -> Unit)?,
modifier: Modifier = Modifier
modifier: Modifier = Modifier,
isEnabled: Boolean = false
) {
SurfaceBackgroundWrapper {
Column(Modifier.padding(dimensions().spacing16x)) {
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/kotlin/com/wire/android/util/FileUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -383,10 +383,9 @@ fun isText(mimeType: String?): Boolean {
return mimeType != null && mimeType.startsWith("text/")
}

@Suppress("MagicNumber")
fun Context.getDeviceIdString(): String? {

if (Build.VERSION.SDK_INT >= 26) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return Settings.Secure.getString(this.contentResolver, Settings.Secure.ANDROID_ID)
}

Expand Down
16 changes: 10 additions & 6 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,7 @@
<string name="settings_wire_website_label">Wire Website</string>
<string name="label_copyright">Copyright</string>
<string name="label_copyright_value" translatable="false">© Wire Swiss GmbH</string>
<string name="debug_settings_screen_title">Debug Settings</string>
<string name="debug_settings_api_versioning_title" translatable="false">API VERSIONING</string>
<string name="debug_settings_e2ei_enrollment_title" translatable="false">E2EI Manual Enrollment</string>
<string name="debug_settings_force_api_versioning_update" translatable="false">Force API versioning update</string>
<string name="debug_settings_break_session" translatable="false">⚠️ Break Session</string>
<string name="item_dependencies_title">Dependencies:</string>
<string name="debug_settings_force_api_versioning_update_button_text" translatable="false">Update</string>
<string name="support_screen_title">Support</string>
<string name="backup_and_restore_screen_title">Back up &amp; Restore Conversations</string>
<string name="search_bar_conversations_hint">Search conversations</string>
Expand Down Expand Up @@ -1482,4 +1476,14 @@ In group conversations, the group admin can overwrite this setting.</string>
<string name="call_feedback_dialog_label_bad">Bad</string>
<string name="call_feedback_dialog_label_fair">Fair</string>
<string name="call_feedback_dialog_label_excellent">Excellent</string>


<!-- Debug Settings -->
<string name="debug_settings_register_fcm_push_token" translatable="false">Register FCM push token</string>
<string name="debug_settings_screen_title">Debug Settings</string>
<string name="debug_settings_api_versioning_title" translatable="false">API VERSIONING</string>
<string name="debug_settings_e2ei_enrollment_title" translatable="false">E2EI Manual Enrollment</string>
<string name="debug_settings_force_api_versioning_update" translatable="false">Force API versioning update</string>
<string name="debug_settings_break_session" translatable="false">⚠️ Break Session</string>
<string name="debug_settings_force_api_versioning_update_button_text" translatable="false">Update</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,11 @@ class WireFirebaseMessagingService : FirebaseMessagingService() {
return userIdValue
}

override fun onNewToken(p0: String) {
super.onNewToken(p0)
override fun onNewToken(token: String) {
super.onNewToken(token)
scope.launch {
coreLogic.globalScope {
saveNotificationToken(p0, "GCM", BuildConfig.FIREBASE_PUSH_SENDER_ID)
saveNotificationToken(token, "GCM", BuildConfig.FIREBASE_PUSH_SENDER_ID)
}.let { result ->
when (result) {
is Result.Failure.Generic ->
Expand Down
Loading

0 comments on commit 0b8afe7

Please sign in to comment.