diff --git a/app/src/main/java/org/unifiedpush/distributor/sunup/AppStore.kt b/app/src/main/java/org/unifiedpush/distributor/sunup/AppStore.kt index ababc19..9c8fefb 100644 --- a/app/src/main/java/org/unifiedpush/distributor/sunup/AppStore.kt +++ b/app/src/main/java/org/unifiedpush/distributor/sunup/AppStore.kt @@ -20,6 +20,22 @@ class AppStore(context: Context) : Store(context, PREF_NAME) { .putOrRemove(PREF_API_URL, value) .apply() + var fallbackIntroShown: Boolean + get() = sharedPreferences + .getBoolean(PREF_FALLBACK_INTRO_SHOWN, false) + set(value) = sharedPreferences + .edit() + .putBoolean(PREF_FALLBACK_INTRO_SHOWN, value) + .apply() + + var fallbackService: String? + get() = sharedPreferences + .getString(PREF_FALLBACK_SERVICE, null) + set(value) = sharedPreferences + .edit() + .putOrRemove(PREF_FALLBACK_SERVICE, value) + .apply() + /** * Show toasts when a new app is registered or an error occurred */ @@ -39,6 +55,8 @@ class AppStore(context: Context) : Store(context, PREF_NAME) { internal const val PREF_NAME = "Sunup" private const val PREF_UAID = "uaid" private const val PREF_API_URL = "api_url" + private const val PREF_FALLBACK_INTRO_SHOWN = "fallback_intro_shown" + private const val PREF_FALLBACK_SERVICE = "fallback_service" private const val PREF_SHOW_TOASTS = "show_toasts" } } diff --git a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/AppAction.kt b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/AppAction.kt index 636a87b..a694436 100644 --- a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/AppAction.kt +++ b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/AppAction.kt @@ -20,6 +20,9 @@ class AppAction(private val action: Action) { class NewPushServer(val url: String) : Action() class ShowToasts(val enable: Boolean) : Action() class DeleteRegistration(val registrations: List) : Action() + data object FallbackIntroShown : Action() + class FallbackDistribSelected(val distributor: String?) : Action() + class MigrateToDistrib(val distributor: String) : Action() } fun handle(context: Context) { @@ -28,6 +31,9 @@ class AppAction(private val action: Action) { is Action.NewPushServer -> newPushServer(context, action) is Action.ShowToasts -> showToasts(context, action) is Action.DeleteRegistration -> deleteRegistration(context, action) + is Action.FallbackIntroShown -> fallbackIntroShown(context) + is Action.FallbackDistribSelected -> fallbackDistribSelected(context, action) + is Action.MigrateToDistrib -> migrateToDistrib(context, action) } } @@ -54,6 +60,33 @@ class AppAction(private val action: Action) { Distributor.deleteApp(context, it) } } + + private fun fallbackIntroShown(context: Context) { + AppStore(context).fallbackIntroShown = true + } + + /** + * Save fallback service + * + * If fallback is disabled and we have already send TEMP_UNAVAILABLE: + * we send the endpoint again + */ + private fun fallbackDistribSelected(context: Context, action: Action.FallbackDistribSelected) { + AppStore(context).fallbackService = action.distributor + action.distributor?.let { + // Fallback is set + if (SourceManager.shouldSendFallback) { + Distributor.sendTempFallbackToAll(context, it) + } + } ?: run { + // Fallback is disabled + Distributor.sendEndpointToAll(context) + } + } + + private fun migrateToDistrib(context: Context, action: Action.MigrateToDistrib) { + Distributor.migrateAll(context, action.distributor) + } } fun ViewModel.publishAction(action: AppAction) { diff --git a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/AppBarViewModel.kt b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/AppBarViewModel.kt index 908fc58..ece2373 100644 --- a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/AppBarViewModel.kt +++ b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/AppBarViewModel.kt @@ -13,10 +13,20 @@ import org.unifiedpush.distributor.sunup.BuildConfig import org.unifiedpush.distributor.sunup.activities.ui.AppBarUiState import org.unifiedpush.distributor.sunup.utils.TAG -class AppBarViewModel(appBarUiState: AppBarUiState) : ViewModel() { +/** + * Controls AppBar and dialogs open from the app bar + * + * The AppBar controls the MigrationView model because it provides + * the migration entry + */ +class AppBarViewModel( + appBarUiState: AppBarUiState, + val migrationViewModel: DistribMigrationViewModel +) : ViewModel() { constructor(context: Context) : this( - AppBarUiState.from(context) + AppBarUiState.from(context), + DistribMigrationViewModel(context) ) var state by mutableStateOf(appBarUiState) diff --git a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/ApplicationRowState.kt b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/ApplicationRowState.kt index 12ed00d..4d4fb8f 100644 --- a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/ApplicationRowState.kt +++ b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/ApplicationRowState.kt @@ -22,4 +22,4 @@ fun Context.applicationRowState(packageName: String, description: String? = null packageName = packageName, description = description ) -} \ No newline at end of file +} diff --git a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/DistribMigrationViewModel.kt b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/DistribMigrationViewModel.kt new file mode 100644 index 0000000..d3ed3b6 --- /dev/null +++ b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/DistribMigrationViewModel.kt @@ -0,0 +1,47 @@ +package org.unifiedpush.distributor.sunup.activities + +import android.content.Context +import org.unifiedpush.android.distributor.ui.compose.DistribMigrationViewModel as UPDistribMigrationViewModel +import org.unifiedpush.android.distributor.ui.compose.state.DistribMigrationState +import org.unifiedpush.distributor.sunup.AppStore +import org.unifiedpush.distributor.utils.listOtherDistributors + +class DistribMigrationViewModel(state: DistribMigrationState) : UPDistribMigrationViewModel(state) { + constructor(context: Context) : this( + stateFrom(context) + ) + + override fun onFallbackDistribSelected(distributor: String?) { + publishAction( + AppAction(AppAction.Action.FallbackDistribSelected(distributor)) + ) + } + + override fun onMigrationDistributorSelected(distributor: String) { + publishAction( + AppAction(AppAction.Action.MigrateToDistrib(distributor)) + ) + } + + override fun onFallbackIntroShown() { + publishAction( + AppAction(AppAction.Action.FallbackIntroShown) + ) + } + + companion object { + fun stateFrom(context: Context): DistribMigrationState { + val store = AppStore(context) + val fallbackDistrib = store.fallbackService + val distributors = context.listOtherDistributors().map { packageName -> + context.applicationRowState(packageName).copy( + selected = fallbackDistrib == packageName + ) + }.toSet() + return DistribMigrationState( + distributors, + store.fallbackIntroShown + ) + } + } +} diff --git a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/MainViewModel.kt b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/MainViewModel.kt index 775637f..0f5eb47 100644 --- a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/MainViewModel.kt +++ b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/MainViewModel.kt @@ -41,6 +41,7 @@ class MainViewModel( viewModelScope.launch { mainUiState = mainUiState.copy(showPermissionDialog = false) } + appBarViewModel.migrationViewModel.mayShowFallbackIntro() } fun refreshRegistrations(context: Context) { viewModelScope.launch { diff --git a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/RegistrationsViewModel.kt b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/RegistrationsViewModel.kt index 79349a8..b017a54 100644 --- a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/RegistrationsViewModel.kt +++ b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/RegistrationsViewModel.kt @@ -8,25 +8,17 @@ import org.unifiedpush.distributor.sunup.DatabaseFactory fun getRegistrationListState(context: Context): RegistrationListState { return RegistrationListState( - list = emptyList() - .toMutableList().also { appList -> - DatabaseFactory.getDb(context).let { db -> - db.listTokens().forEach { - appList.add( - getRegistrationState(context, db, it) - ) - } - } - }.filterNotNull() + list = DatabaseFactory.getDb(context).listApps().map { app -> + getRegistrationState(context, app) + } ) } -fun getRegistrationState(context: Context, db: Database, token: String): RegistrationState? { - val app = db.getAppFromCoToken(token) ?: return null - return RegistrationState( +fun getRegistrationState(context: Context, app: Database.App): RegistrationState { + return RegistrationState( app = context.applicationRowState(app.packageName, app.description), msgCount = app.msgCount, - token = token, + token = app.connectorToken, copyable = false ) } diff --git a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/ui/AppBarUi.kt b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/ui/AppBarUi.kt index 689d156..30a88c7 100644 --- a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/ui/AppBarUi.kt +++ b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/ui/AppBarUi.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import org.unifiedpush.android.distributor.ui.R as LibR +import org.unifiedpush.android.distributor.ui.compose.DistribMigrationUi import org.unifiedpush.distributor.sunup.R import org.unifiedpush.distributor.sunup.activities.AppAction import org.unifiedpush.distributor.sunup.activities.AppBarViewModel @@ -78,6 +79,7 @@ fun AppBarUi(appBarViewModel: AppBarViewModel) { onConfirmation = { appBarViewModel.newPushServer(it) } ) } + DistribMigrationUi(appBarViewModel.migrationViewModel) } @Composable diff --git a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/ui/MainUi.kt b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/ui/MainUi.kt index 535e100..2d14365 100644 --- a/app/src/main/java/org/unifiedpush/distributor/sunup/activities/ui/MainUi.kt +++ b/app/src/main/java/org/unifiedpush/distributor/sunup/activities/ui/MainUi.kt @@ -31,8 +31,10 @@ import org.unifiedpush.android.distributor.ui.compose.RegistrationList import org.unifiedpush.android.distributor.ui.compose.RegistrationListHeading import org.unifiedpush.android.distributor.ui.compose.UnregisterBarUi import org.unifiedpush.android.distributor.ui.compose.previewRegistrationsViewModel +import org.unifiedpush.android.distributor.ui.compose.state.DistribMigrationState import org.unifiedpush.distributor.sunup.BuildConfig import org.unifiedpush.distributor.sunup.activities.AppBarViewModel +import org.unifiedpush.distributor.sunup.activities.DistribMigrationViewModel import org.unifiedpush.distributor.sunup.activities.MainViewModel import org.unifiedpush.distributor.sunup.utils.getDebugInfo @@ -132,7 +134,10 @@ fun MainPreview() { MainUi( MainViewModel( MainUiState(), - AppBarViewModel(AppBarUiState(BuildConfig.DEFAULT_API_URL, false)), + AppBarViewModel( + AppBarUiState(BuildConfig.DEFAULT_API_URL, false), + DistribMigrationViewModel(DistribMigrationState()) + ), BatteryOptimisationViewModel(true), previewRegistrationsViewModel() )