This commit is contained in:
sim 2025-09-26 16:12:11 +02:00
parent a1fd80366e
commit 36826185b8
14 changed files with 64 additions and 43 deletions

View file

@ -3,3 +3,4 @@ ktlint_code_style = android_studio
ktlint_function_naming_ignore_when_annotated_with=Composable ktlint_function_naming_ignore_when_annotated_with=Composable
max_line_length = 140 max_line_length = 140
ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than=3 ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than=3
ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than=3

View file

@ -89,7 +89,6 @@ dependencies {
implementation(libs.androidx.material3.android) implementation(libs.androidx.material3.android)
implementation(libs.kotlinx.serialization.json) implementation(libs.kotlinx.serialization.json)
implementation(libs.androidx.ui.tooling.preview.android) implementation(libs.androidx.ui.tooling.preview.android)
implementation(libs.androidx.navigation.runtime.ktx)
implementation(libs.androidx.navigation.compose) implementation(libs.androidx.navigation.compose)
debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.tooling)
} }

View file

@ -12,8 +12,8 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.unifiedpush.distributor.sunup.EventBus import org.unifiedpush.distributor.sunup.EventBus
import org.unifiedpush.distributor.sunup.Migrations import org.unifiedpush.distributor.sunup.Migrations
import org.unifiedpush.distributor.sunup.activities.ThemeViewModel
import org.unifiedpush.distributor.sunup.activities.ui.App import org.unifiedpush.distributor.sunup.activities.ui.App
import org.unifiedpush.distributor.sunup.activities.ui.ThemeViewModel
import org.unifiedpush.distributor.sunup.activities.ui.theme.AppTheme import org.unifiedpush.distributor.sunup.activities.ui.theme.AppTheme
import org.unifiedpush.distributor.sunup.services.RestartWorker import org.unifiedpush.distributor.sunup.services.RestartWorker
import org.unifiedpush.distributor.sunup.utils.TAG import org.unifiedpush.distributor.sunup.utils.TAG

View file

@ -20,6 +20,14 @@ class MainViewModel(
val registrationsViewModel: RegistrationsViewModel, val registrationsViewModel: RegistrationsViewModel,
val application: Application? = null val application: Application? = null
) : ViewModel() { ) : ViewModel() {
constructor(application: Application) : this(
mainUiState = MainUiState(),
batteryOptimisationViewModel = BatteryOptimisationViewModel(application),
registrationsViewModel = RegistrationsViewModel(
getRegistrationListState(application)
),
application
)
var mainUiState by mutableStateOf(mainUiState) var mainUiState by mutableStateOf(mainUiState)
private set private set
@ -78,17 +86,4 @@ class MainViewModel(
fun restartService() { fun restartService() {
publishAction(AppAction(AppAction.Action.RestartService)) publishAction(AppAction(AppAction.Action.RestartService))
} }
companion object {
fun from(application: Application): MainViewModel {
return MainViewModel(
mainUiState = MainUiState(),
batteryOptimisationViewModel = BatteryOptimisationViewModel(application),
registrationsViewModel = RegistrationsViewModel(
getRegistrationListState(application)
),
application
)
}
}
} }

View file

@ -7,17 +7,14 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import java.net.URL
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.unifiedpush.distributor.sunup.AppStore import org.unifiedpush.distributor.sunup.AppStore
import org.unifiedpush.distributor.sunup.BuildConfig import org.unifiedpush.distributor.sunup.BuildConfig
import org.unifiedpush.distributor.sunup.activities.ui.SettingsState import org.unifiedpush.distributor.sunup.activities.ui.SettingsState
import org.unifiedpush.distributor.sunup.utils.TAG import org.unifiedpush.distributor.sunup.utils.TAG
import java.net.URL
class SettingsViewModel( class SettingsViewModel(state: SettingsState, val application: Application? = null) : ViewModel() {
state: SettingsState,
val application: Application? = null
): ViewModel() {
constructor(application: Application) : this( constructor(application: Application) : this(
SettingsState.from(application), SettingsState.from(application),
application application
@ -26,10 +23,9 @@ class SettingsViewModel(
var state by mutableStateOf(state) var state by mutableStateOf(state)
private set private set
fun toggleChangeServer() { fun toggleChangeServer() {
viewModelScope.launch { viewModelScope.launch {
state = state.copy(showChangeServerDialog = !state.showChangeServerDialog,) state = state.copy(showChangeServerDialog = !state.showChangeServerDialog)
} }
} }
@ -52,7 +48,7 @@ class SettingsViewModel(
URL(url) URL(url)
state = state.copy( state = state.copy(
currentApiUrl = url, currentApiUrl = url,
showChangeServerDialog = false, showChangeServerDialog = false
) )
publishAction(AppAction(AppAction.Action.NewPushServer(url))) publishAction(AppAction(AppAction.Action.NewPushServer(url)))
} catch (e: Exception) { } catch (e: Exception) {
@ -75,4 +71,4 @@ class SettingsViewModel(
publishAction(AppAction(AppAction.Action.ShowToasts(state.showToasts))) publishAction(AppAction(AppAction.Action.ShowToasts(state.showToasts)))
} }
} }
} }

View file

@ -0,0 +1,25 @@
package org.unifiedpush.distributor.sunup.activities
import android.app.Application
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
import org.unifiedpush.distributor.sunup.AppStore
class ThemeViewModel(val application: Application? = null) : ViewModel() {
var dynamicColors by mutableStateOf(
application?.let { AppStore(it).dynamicColors } ?: false
)
fun toggleDynamicColors() {
viewModelScope.launch {
dynamicColors = !dynamicColors
application?.run {
AppStore(this).dynamicColors = dynamicColors
}
}
}
}

View file

@ -8,13 +8,13 @@ import org.unifiedpush.android.distributor.ui.compose.BatteryOptimisationViewMod
import org.unifiedpush.android.distributor.ui.compose.previewRegistrationsViewModel import org.unifiedpush.android.distributor.ui.compose.previewRegistrationsViewModel
import org.unifiedpush.android.distributor.ui.compose.state.DistribMigrationState import org.unifiedpush.android.distributor.ui.compose.state.DistribMigrationState
import org.unifiedpush.distributor.sunup.BuildConfig import org.unifiedpush.distributor.sunup.BuildConfig
import org.unifiedpush.distributor.sunup.activities.ThemeViewModel
import org.unifiedpush.distributor.sunup.activities.ui.MainUiState import org.unifiedpush.distributor.sunup.activities.ui.MainUiState
import org.unifiedpush.distributor.sunup.activities.ui.SettingsState import org.unifiedpush.distributor.sunup.activities.ui.SettingsState
import org.unifiedpush.distributor.sunup.activities.ui.ThemeViewModel
class ViewModelFactory(val application: Application) : ViewModelProvider.Factory { class ViewModelFactory(val application: Application) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T = when { override fun <T : ViewModel> create(modelClass: Class<T>): T = when {
modelClass.isAssignableFrom(MainViewModel::class.java) -> MainViewModel.from(application) modelClass.isAssignableFrom(MainViewModel::class.java) -> MainViewModel(application)
modelClass.isAssignableFrom(SettingsViewModel::class.java) -> SettingsViewModel( modelClass.isAssignableFrom(SettingsViewModel::class.java) -> SettingsViewModel(
application application
) )
@ -36,9 +36,9 @@ class PreviewFactory(val context: Context) : ViewModelProvider.Factory {
modelClass.isAssignableFrom(SettingsViewModel::class.java) -> { modelClass.isAssignableFrom(SettingsViewModel::class.java) -> {
SettingsViewModel( SettingsViewModel(
SettingsState( SettingsState(
BuildConfig.DEFAULT_API_URL, BuildConfig.DEFAULT_API_URL,
false false
), )
) )
} }
modelClass.isAssignableFrom(ThemeViewModel::class.java) -> ThemeViewModel() modelClass.isAssignableFrom(ThemeViewModel::class.java) -> ThemeViewModel()
@ -47,4 +47,4 @@ class PreviewFactory(val context: Context) : ViewModelProvider.Factory {
} }
else -> throw IllegalArgumentException("Unknown ViewModel class") else -> throw IllegalArgumentException("Unknown ViewModel class")
} as T } as T
} }

View file

@ -34,8 +34,8 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import org.unifiedpush.android.distributor.ui.compose.AppBar
import org.unifiedpush.android.distributor.ui.R as LibR import org.unifiedpush.android.distributor.ui.R as LibR
import org.unifiedpush.android.distributor.ui.compose.AppBar
import org.unifiedpush.android.distributor.ui.compose.CardDisableBatteryOptimisation import org.unifiedpush.android.distributor.ui.compose.CardDisableBatteryOptimisation
import org.unifiedpush.android.distributor.ui.compose.CardDisabledForMigration import org.unifiedpush.android.distributor.ui.compose.CardDisabledForMigration
import org.unifiedpush.android.distributor.ui.compose.DistribMigrationUi import org.unifiedpush.android.distributor.ui.compose.DistribMigrationUi
@ -67,7 +67,6 @@ fun MainAppBarOrSelection(viewModel: MainViewModel, onGoToSettings: () -> Unit)
} }
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun MainAppBar(viewModel: MainViewModel, onGoToSettings: () -> Unit) { fun MainAppBar(viewModel: MainViewModel, onGoToSettings: () -> Unit) {

View file

@ -25,6 +25,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import org.unifiedpush.android.distributor.ui.R as LibR
import org.unifiedpush.android.distributor.ui.compose.AboutHeading import org.unifiedpush.android.distributor.ui.compose.AboutHeading
import org.unifiedpush.android.distributor.ui.compose.DistribMigrationUi import org.unifiedpush.android.distributor.ui.compose.DistribMigrationUi
import org.unifiedpush.android.distributor.ui.compose.Heading import org.unifiedpush.android.distributor.ui.compose.Heading
@ -34,8 +35,8 @@ import org.unifiedpush.distributor.sunup.R
import org.unifiedpush.distributor.sunup.activities.DistribMigrationViewModel import org.unifiedpush.distributor.sunup.activities.DistribMigrationViewModel
import org.unifiedpush.distributor.sunup.activities.PreviewFactory import org.unifiedpush.distributor.sunup.activities.PreviewFactory
import org.unifiedpush.distributor.sunup.activities.SettingsViewModel import org.unifiedpush.distributor.sunup.activities.SettingsViewModel
import org.unifiedpush.distributor.sunup.activities.ThemeViewModel
import org.unifiedpush.distributor.sunup.activities.UiAction import org.unifiedpush.distributor.sunup.activities.UiAction
import org.unifiedpush.android.distributor.ui.R as LibR
@Composable @Composable
fun SettingsScreen( fun SettingsScreen(
@ -92,7 +93,7 @@ fun SettingsScreen(
} }
) )
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
Preference( Preference(
stringResource(LibR.string.dynamic_colors), stringResource(LibR.string.dynamic_colors),
stringResource(LibR.string.clicklabel_dynamic_colors), stringResource(LibR.string.clicklabel_dynamic_colors),
@ -162,7 +163,7 @@ fun Preference(
warning: Boolean = false, warning: Boolean = false,
onSelect: () -> Unit onSelect: () -> Unit
) { ) {
Row ( Row(
Modifier.clickable( Modifier.clickable(
true, true,
onclickLabel, onclickLabel,
@ -207,4 +208,4 @@ fun PreviewSettingsScreen() {
val themeVM = viewModel<ThemeViewModel>(factory = factory) val themeVM = viewModel<ThemeViewModel>(factory = factory)
val migrationVM = viewModel<DistribMigrationViewModel>(factory = factory) val migrationVM = viewModel<DistribMigrationViewModel>(factory = factory)
SettingsScreen(settVM, themeVM, migrationVM) SettingsScreen(settVM, themeVM, migrationVM)
} }

View file

@ -18,4 +18,4 @@ data class SettingsState(
) )
} }
} }
} }

View file

@ -261,8 +261,7 @@ fun AppTheme(
// Dynamic color is available on Android 12+ // Dynamic color is available on Android 12+
dynamicColor: Boolean = false, dynamicColor: Boolean = false,
content: content:
@Composable() @Composable () -> Unit
() -> Unit
) { ) {
val colorScheme = when { val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {

View file

@ -1,10 +1,10 @@
package org.unifiedpush.distributor.sunup.api package org.unifiedpush.distributor.sunup.api
import android.content.Context import android.content.Context
import java.util.concurrent.atomic.AtomicReference
import org.unifiedpush.distributor.sunup.DatabaseFactory import org.unifiedpush.distributor.sunup.DatabaseFactory
import org.unifiedpush.distributor.sunup.services.RestartWorker import org.unifiedpush.distributor.sunup.services.RestartWorker
import org.unifiedpush.distributor.sunup.services.SourceManager import org.unifiedpush.distributor.sunup.services.SourceManager
import java.util.concurrent.atomic.AtomicReference
/** /**
* Candidate for a new API url * Candidate for a new API url

View file

@ -159,7 +159,11 @@ class ServerConnection(private val context: Context, private val releaseLock: ()
Distributor.deleteChannelFromServer(context, message.channelID) Distributor.deleteChannelFromServer(context, message.channelID)
} }
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { override fun onClosed(
webSocket: WebSocket,
code: Int,
reason: String
) {
Log.d(TAG, "onClosed: $webSocket") Log.d(TAG, "onClosed: $webSocket")
webSocket.cancel() webSocket.cancel()
releaseLock() releaseLock()
@ -168,7 +172,11 @@ class ServerConnection(private val context: Context, private val releaseLock: ()
} }
} }
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { override fun onFailure(
webSocket: WebSocket,
t: Throwable,
response: Response?
) {
Log.d(TAG, "onFailure: An error occurred: $t") Log.d(TAG, "onFailure: An error occurred: $t")
response?.let { response?.let {
Log.d(TAG, "onFailure: ${it.code}") Log.d(TAG, "onFailure: ${it.code}")

View file

@ -13,7 +13,6 @@ material3Android = "1.3.2"
okhttp = "5.1.0" okhttp = "5.1.0"
uiTooling = "1.9.1" uiTooling = "1.9.1"
runtimeAndroid = "1.9.1" runtimeAndroid = "1.9.1"
navigationRuntimeKtx = "2.9.4"
navigationCompose = "2.9.4" navigationCompose = "2.9.4"
[libraries] [libraries]
@ -31,7 +30,6 @@ kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serializa
ktlint-gradle = { module = "org.jlleitschuh.gradle:ktlint-gradle", version.ref = "ktlint"} ktlint-gradle = { module = "org.jlleitschuh.gradle:ktlint-gradle", version.ref = "ktlint"}
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
androidx-runtime-android = { group = "androidx.compose.runtime", name = "runtime-android", version.ref = "runtimeAndroid" } androidx-runtime-android = { group = "androidx.compose.runtime", name = "runtime-android", version.ref = "runtimeAndroid" }
androidx-navigation-runtime-ktx = { group = "androidx.navigation", name = "navigation-runtime-ktx", version.ref = "navigationRuntimeKtx" }
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" } androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
[plugins] [plugins]