Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add debug button send FCM token #WPB-9476 #3482

Merged
merged 8 commits into from
Oct 10, 2024
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
Loading