Add option to show registrations toasts

This commit is contained in:
sim 2025-08-28 10:46:52 +02:00
parent fb4bb8cbf7
commit 3ad72d1ecc
8 changed files with 84 additions and 6 deletions

View file

@ -20,6 +20,17 @@ class AppStore(context: Context) : Store(context, PREF_NAME) {
.putOrRemove(PREF_API_URL, value) .putOrRemove(PREF_API_URL, value)
.apply() .apply()
/**
* Show toasts when a new app is registered or an error occurred
*/
var showToasts: Boolean
get() = sharedPreferences
.getBoolean(PREF_SHOW_TOASTS, false)
set(value) = sharedPreferences
.edit()
.putBoolean(PREF_SHOW_TOASTS, value)
.apply()
override fun wipe() { override fun wipe() {
uaid = null uaid = null
} }
@ -28,5 +39,6 @@ class AppStore(context: Context) : Store(context, PREF_NAME) {
internal const val PREF_NAME = "Sunup" internal const val PREF_NAME = "Sunup"
private const val PREF_UAID = "uaid" private const val PREF_UAID = "uaid"
private const val PREF_API_URL = "api_url" private const val PREF_API_URL = "api_url"
private const val PREF_SHOW_TOASTS = "show_toasts"
} }
} }

View file

@ -5,6 +5,7 @@ import android.util.Log
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.unifiedpush.distributor.sunup.AppStore
import org.unifiedpush.distributor.sunup.Distributor import org.unifiedpush.distributor.sunup.Distributor
import org.unifiedpush.distributor.sunup.EventBus import org.unifiedpush.distributor.sunup.EventBus
import org.unifiedpush.distributor.sunup.api.ApiUrlCandidate import org.unifiedpush.distributor.sunup.api.ApiUrlCandidate
@ -17,6 +18,7 @@ class AppAction(private val action: Action) {
sealed class Action { sealed class Action {
data object RestartService : Action() data object RestartService : Action()
class NewPushServer(val url: String) : Action() class NewPushServer(val url: String) : Action()
class ShowToasts(val enable: Boolean) : Action()
class DeleteRegistration(val registrations: List<String>) : Action() class DeleteRegistration(val registrations: List<String>) : Action()
} }
@ -24,6 +26,7 @@ class AppAction(private val action: Action) {
when (action) { when (action) {
is Action.RestartService -> restartService(context) is Action.RestartService -> restartService(context)
is Action.NewPushServer -> newPushServer(context, action) is Action.NewPushServer -> newPushServer(context, action)
is Action.ShowToasts -> showToasts(context, action)
is Action.DeleteRegistration -> deleteRegistration(context, action) is Action.DeleteRegistration -> deleteRegistration(context, action)
} }
} }
@ -42,6 +45,10 @@ class AppAction(private val action: Action) {
RestartWorker.run(context, delay = 0) RestartWorker.run(context, delay = 0)
} }
private fun showToasts(context: Context, action: Action.ShowToasts) {
AppStore(context).showToasts = action.enable
}
private fun deleteRegistration(context: Context, action: Action.DeleteRegistration) { private fun deleteRegistration(context: Context, action: Action.DeleteRegistration) {
action.registrations.forEach { action.registrations.forEach {
Distributor.deleteApp(context, it) {} Distributor.deleteApp(context, it) {}

View file

@ -1,5 +1,6 @@
package org.unifiedpush.distributor.sunup.activities package org.unifiedpush.distributor.sunup.activities
import android.content.Context
import android.util.Log import android.util.Log
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@ -14,6 +15,10 @@ import org.unifiedpush.distributor.sunup.utils.TAG
class AppBarViewModel(appBarUiState: AppBarUiState) : ViewModel() { class AppBarViewModel(appBarUiState: AppBarUiState) : ViewModel() {
constructor(context: Context) : this(
AppBarUiState.from(context)
)
var state by mutableStateOf(appBarUiState) var state by mutableStateOf(appBarUiState)
fun toggleMenu() { fun toggleMenu() {
@ -49,4 +54,11 @@ class AppBarViewModel(appBarUiState: AppBarUiState) : ViewModel() {
} }
} }
} }
fun toggleShowToasts() {
viewModelScope.launch {
state = state.copy(showToasts = !state.showToasts)
publishAction(AppAction(AppAction.Action.ShowToasts(state.showToasts)))
}
}
} }

View file

@ -13,7 +13,6 @@ import org.unifiedpush.android.distributor.ui.compose.BatteryOptimisationViewMod
import org.unifiedpush.android.distributor.ui.compose.RegistrationsViewModel import org.unifiedpush.android.distributor.ui.compose.RegistrationsViewModel
import org.unifiedpush.android.distributor.ui.compose.state.RegistrationListState import org.unifiedpush.android.distributor.ui.compose.state.RegistrationListState
import org.unifiedpush.distributor.sunup.AppStore import org.unifiedpush.distributor.sunup.AppStore
import org.unifiedpush.distributor.sunup.activities.ui.AppBarUiState
import org.unifiedpush.distributor.sunup.activities.ui.MainUiState import org.unifiedpush.distributor.sunup.activities.ui.MainUiState
class MainViewModel( class MainViewModel(
@ -24,7 +23,7 @@ class MainViewModel(
) : ViewModel() { ) : ViewModel() {
constructor(context: Context) : this( constructor(context: Context) : this(
mainUiState = MainUiState(), mainUiState = MainUiState(),
appBarViewModel = AppBarViewModel(AppBarUiState(AppStore(context).apiUrl)), appBarViewModel = AppBarViewModel(context),
batteryOptimisationViewModel = BatteryOptimisationViewModel(context), batteryOptimisationViewModel = BatteryOptimisationViewModel(context),
registrationsViewModel = RegistrationsViewModel( registrationsViewModel = RegistrationsViewModel(
getRegistrationListState(context) getRegistrationListState(context)
@ -51,7 +50,7 @@ class MainViewModel(
fun refreshApiUrl(context: Context) { fun refreshApiUrl(context: Context) {
viewModelScope.launch { viewModelScope.launch {
appBarViewModel.state = AppBarUiState(AppStore(context).apiUrl) appBarViewModel.state = appBarViewModel.state.copy(currentApiUrl = AppStore(context).apiUrl)
} }
} }

View file

@ -1,7 +1,10 @@
package org.unifiedpush.distributor.sunup.activities.ui package org.unifiedpush.distributor.sunup.activities.ui
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.Checkbox
import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
@ -12,6 +15,8 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import org.unifiedpush.android.distributor.ui.R as LibR import org.unifiedpush.android.distributor.ui.R as LibR
import org.unifiedpush.distributor.sunup.R import org.unifiedpush.distributor.sunup.R
@ -48,6 +53,7 @@ fun AppBarUi(appBarViewModel: AppBarViewModel) {
} }
Dropdown( Dropdown(
state.menuExpanded, state.menuExpanded,
state.showToasts,
onRestart = { onRestart = {
appBarViewModel.publishAction(AppAction(AppAction.Action.RestartService)) appBarViewModel.publishAction(AppAction(AppAction.Action.RestartService))
appBarViewModel.toggleMenu() appBarViewModel.toggleMenu()
@ -57,6 +63,9 @@ fun AppBarUi(appBarViewModel: AppBarViewModel) {
}, },
onChangeServer = { onChangeServer = {
appBarViewModel.toggleChangeServer() appBarViewModel.toggleChangeServer()
},
onToggleShowToasts = {
appBarViewModel.toggleShowToasts()
} }
) )
} }
@ -72,7 +81,14 @@ fun AppBarUi(appBarViewModel: AppBarViewModel) {
} }
@Composable @Composable
fun Dropdown(expanded: Boolean, onRestart: () -> Unit, onDismiss: () -> Unit, onChangeServer: () -> Unit) { fun Dropdown(
expanded: Boolean,
showToasts: Boolean,
onRestart: () -> Unit,
onDismiss: () -> Unit,
onChangeServer: () -> Unit,
onToggleShowToasts: () -> Unit
) {
DropdownMenu( DropdownMenu(
expanded = expanded, expanded = expanded,
onDismissRequest = onDismiss onDismissRequest = onDismiss
@ -94,5 +110,18 @@ fun Dropdown(expanded: Boolean, onRestart: () -> Unit, onDismiss: () -> Unit, on
) )
} }
) )
DropdownMenuItem(
onClick = onToggleShowToasts,
text = {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(stringResource(LibR.string.app_dropdown_show_toasts))
Spacer(Modifier.weight(1f))
Checkbox(
showToasts,
onCheckedChange = { onToggleShowToasts() }
)
}
}
)
} }
} }

View file

@ -1,7 +1,21 @@
package org.unifiedpush.distributor.sunup.activities.ui package org.unifiedpush.distributor.sunup.activities.ui
import android.content.Context
import org.unifiedpush.distributor.sunup.AppStore
data class AppBarUiState( data class AppBarUiState(
val currentApiUrl: String, val currentApiUrl: String,
val showToasts: Boolean,
val menuExpanded: Boolean = false, val menuExpanded: Boolean = false,
val showChangeServerDialog: Boolean = false val showChangeServerDialog: Boolean = false
) ) {
companion object {
fun from(context: Context): AppBarUiState {
val store = AppStore(context)
return AppBarUiState(
store.apiUrl,
store.showToasts
)
}
}
}

View file

@ -161,7 +161,7 @@ fun MainPreview() {
MainUi( MainUi(
MainViewModel( MainViewModel(
MainUiState(), MainUiState(),
AppBarViewModel(AppBarUiState(BuildConfig.DEFAULT_API_URL)), AppBarViewModel(AppBarUiState(BuildConfig.DEFAULT_API_URL, false)),
BatteryOptimisationViewModel(true), BatteryOptimisationViewModel(true),
RegistrationsViewModel(RegistrationListState(regList)) RegistrationsViewModel(RegistrationListState(regList))
) )

View file

@ -4,6 +4,7 @@ package org.unifiedpush.distributor.sunup.receivers
import android.content.Context import android.content.Context
import org.unifiedpush.distributor.receiver.DistributorReceiver import org.unifiedpush.distributor.receiver.DistributorReceiver
import org.unifiedpush.distributor.sunup.AppStore
import org.unifiedpush.distributor.sunup.Distributor import org.unifiedpush.distributor.sunup.Distributor
import org.unifiedpush.distributor.sunup.callback.NetworkCallbackFactory import org.unifiedpush.distributor.sunup.callback.NetworkCallbackFactory
@ -22,4 +23,8 @@ class RegisterBroadcastReceiver : DistributorReceiver() {
override fun hasInternet(context: Context): Boolean { override fun hasInternet(context: Context): Boolean {
return NetworkCallbackFactory.hasInternet() return NetworkCallbackFactory.hasInternet()
} }
override fun showToasts(context: Context): Boolean {
return AppStore(context).showToasts
}
} }