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)
.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() {
uaid = null
}
@ -28,5 +39,6 @@ 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_SHOW_TOASTS = "show_toasts"
}
}

View file

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

View file

@ -1,5 +1,6 @@
package org.unifiedpush.distributor.sunup.activities
import android.content.Context
import android.util.Log
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -14,6 +15,10 @@ import org.unifiedpush.distributor.sunup.utils.TAG
class AppBarViewModel(appBarUiState: AppBarUiState) : ViewModel() {
constructor(context: Context) : this(
AppBarUiState.from(context)
)
var state by mutableStateOf(appBarUiState)
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.state.RegistrationListState
import org.unifiedpush.distributor.sunup.AppStore
import org.unifiedpush.distributor.sunup.activities.ui.AppBarUiState
import org.unifiedpush.distributor.sunup.activities.ui.MainUiState
class MainViewModel(
@ -24,7 +23,7 @@ class MainViewModel(
) : ViewModel() {
constructor(context: Context) : this(
mainUiState = MainUiState(),
appBarViewModel = AppBarViewModel(AppBarUiState(AppStore(context).apiUrl)),
appBarViewModel = AppBarViewModel(context),
batteryOptimisationViewModel = BatteryOptimisationViewModel(context),
registrationsViewModel = RegistrationsViewModel(
getRegistrationListState(context)
@ -51,7 +50,7 @@ class MainViewModel(
fun refreshApiUrl(context: Context) {
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
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.Checkbox
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
@ -12,6 +15,8 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
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.distributor.sunup.R
@ -48,6 +53,7 @@ fun AppBarUi(appBarViewModel: AppBarViewModel) {
}
Dropdown(
state.menuExpanded,
state.showToasts,
onRestart = {
appBarViewModel.publishAction(AppAction(AppAction.Action.RestartService))
appBarViewModel.toggleMenu()
@ -57,6 +63,9 @@ fun AppBarUi(appBarViewModel: AppBarViewModel) {
},
onChangeServer = {
appBarViewModel.toggleChangeServer()
},
onToggleShowToasts = {
appBarViewModel.toggleShowToasts()
}
)
}
@ -72,7 +81,14 @@ fun AppBarUi(appBarViewModel: AppBarViewModel) {
}
@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(
expanded = expanded,
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
import android.content.Context
import org.unifiedpush.distributor.sunup.AppStore
data class AppBarUiState(
val currentApiUrl: String,
val showToasts: Boolean,
val menuExpanded: 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(
MainViewModel(
MainUiState(),
AppBarViewModel(AppBarUiState(BuildConfig.DEFAULT_API_URL)),
AppBarViewModel(AppBarUiState(BuildConfig.DEFAULT_API_URL, false)),
BatteryOptimisationViewModel(true),
RegistrationsViewModel(RegistrationListState(regList))
)

View file

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