diff --git a/app/src/main/java/com/chiller3/basicsync/Notifications.kt b/app/src/main/java/com/chiller3/basicsync/Notifications.kt
index f889bbb6..ba8b981a 100644
--- a/app/src/main/java/com/chiller3/basicsync/Notifications.kt
+++ b/app/src/main/java/com/chiller3/basicsync/Notifications.kt
@@ -118,7 +118,7 @@ class Notifications(private val context: Context) {
setOngoing(true)
setOnlyAlertOnce(true)
- if (runState.showFolderStates) {
+ if (state.showDetails && runState.showFolderStates) {
setContentText(buildString {
append(context.resources.getQuantityString(
R.plurals.device_state_connected,
diff --git a/app/src/main/java/com/chiller3/basicsync/Preferences.kt b/app/src/main/java/com/chiller3/basicsync/Preferences.kt
index cc4c44cd..b214efa7 100644
--- a/app/src/main/java/com/chiller3/basicsync/Preferences.kt
+++ b/app/src/main/java/com/chiller3/basicsync/Preferences.kt
@@ -20,9 +20,10 @@ class Preferences(context: Context) {
const val PREF_RESPECT_BATTERY_SAVER = "respect_battery_saver"
const val PREF_RESPECT_AUTO_SYNC_DATA = "respect_auto_sync_data"
const val PREF_KEEP_ALIVE = "keep_alive"
+ const val PREF_SHOW_DETAILS = "show_details"
+ const val PREF_SHOW_EXIT = "show_exit"
const val PREF_REMOTE_CONTROL = "remote_control"
const val PREF_ALLOW_AUTO_MODE = "allow_auto_mode"
- const val PREF_SHOW_EXIT = "show_exit"
const val PREF_START_ON_BOOT = "start_on_boot"
const val PREF_REQUIRE_UNMETERED_NETWORK = "require_unmetered_network"
const val PREF_NETWORK_ALLOW_WIFI = "network_allow_wifi"
@@ -74,6 +75,14 @@ class Preferences(context: Context) {
get() = prefs.getBoolean(PREF_KEEP_ALIVE, true)
set(enabled) = prefs.edit { putBoolean(PREF_KEEP_ALIVE, enabled) }
+ var showDetails: Boolean
+ get() = prefs.getBoolean(PREF_SHOW_DETAILS, true)
+ set(enabled) = prefs.edit { putBoolean(PREF_SHOW_DETAILS, enabled) }
+
+ var showExit: Boolean
+ get() = prefs.getBoolean(PREF_SHOW_EXIT, false)
+ set(enabled) = prefs.edit { putBoolean(PREF_SHOW_EXIT, enabled) }
+
var remoteControl: Boolean
get() = prefs.getBoolean(PREF_REMOTE_CONTROL, false)
set(enabled) = prefs.edit { putBoolean(PREF_REMOTE_CONTROL, enabled) }
@@ -82,10 +91,6 @@ class Preferences(context: Context) {
get() = prefs.getBoolean(PREF_ALLOW_AUTO_MODE, true)
set(enabled) = prefs.edit { putBoolean(PREF_ALLOW_AUTO_MODE, enabled) }
- var showExit: Boolean
- get() = prefs.getBoolean(PREF_SHOW_EXIT, false)
- set(enabled) = prefs.edit { putBoolean(PREF_SHOW_EXIT, enabled) }
-
var startOnBoot: Boolean
get() = prefs.getBoolean(PREF_START_ON_BOOT, true)
set(enabled) = prefs.edit { putBoolean(PREF_START_ON_BOOT, enabled) }
diff --git a/app/src/main/java/com/chiller3/basicsync/settings/SettingsScreen.kt b/app/src/main/java/com/chiller3/basicsync/settings/SettingsScreen.kt
index 048c5ba0..3dbb0648 100644
--- a/app/src/main/java/com/chiller3/basicsync/settings/SettingsScreen.kt
+++ b/app/src/main/java/com/chiller3/basicsync/settings/SettingsScreen.kt
@@ -108,9 +108,10 @@ fun SettingsScreen(
val respectBatterySaver = remember(reloadPrefs) { prefs.respectBatterySaver }
val respectAutoSyncData = remember(reloadPrefs) { prefs.respectAutoSyncData }
val keepAlive = remember(reloadPrefs) { prefs.keepAlive }
+ val showDetails = remember(reloadPrefs) { prefs.showDetails }
+ val showExit = remember(reloadPrefs) { prefs.showExit }
val remoteControl = remember(reloadPrefs) { prefs.remoteControl }
val allowAutoMode = remember(reloadPrefs) { prefs.allowAutoMode }
- val showExit = remember(reloadPrefs) { prefs.showExit }
val startOnBoot = remember(reloadPrefs) { prefs.startOnBoot }
val isDebugMode = remember(reloadPrefs) { prefs.isDebugMode }
@@ -330,9 +331,10 @@ fun SettingsScreen(
respectBatterySaver = respectBatterySaver,
respectAutoSyncData = respectAutoSyncData,
keepAlive = keepAlive,
+ showDetails = showDetails,
+ showExit = showExit,
remoteControl = remoteControl,
allowAutoMode = allowAutoMode,
- showExit = showExit,
startOnBoot = startOnBoot,
isDebugMode = isDebugMode,
onInhibitBatteryOptGrant = {
@@ -440,6 +442,14 @@ fun SettingsScreen(
prefs.keepAlive = enabled
reloadPrefs++
},
+ onShowDetailsChange = { enabled ->
+ prefs.showDetails = enabled
+ reloadPrefs++
+ },
+ onShowExitChange = { enabled ->
+ prefs.showExit = enabled
+ reloadPrefs++
+ },
onRemoteControlChange = { enabled ->
prefs.remoteControl = enabled
reloadPrefs++
@@ -456,10 +466,6 @@ fun SettingsScreen(
SyncthingService.start(context, action)
},
- onShowExitChange = { enabled ->
- prefs.showExit = enabled
- reloadPrefs++
- },
onStartOnBootChange = { enabled ->
prefs.startOnBoot = enabled
reloadPrefs++
@@ -566,9 +572,10 @@ private fun SettingsContent(
respectBatterySaver: Boolean,
respectAutoSyncData: Boolean,
keepAlive: Boolean,
+ showDetails: Boolean,
+ showExit: Boolean,
remoteControl: Boolean,
allowAutoMode: Boolean,
- showExit: Boolean,
startOnBoot: Boolean,
isDebugMode: Boolean,
onInhibitBatteryOptGrant: () -> Unit,
@@ -590,9 +597,10 @@ private fun SettingsContent(
onRespectAutoSyncDataChange: (Boolean) -> Unit,
onSyncScheduleSettingsOpen: () -> Unit,
onKeepAliveChange: (Boolean) -> Unit,
+ onShowDetailsChange: (Boolean) -> Unit,
+ onShowExitChange: (Boolean) -> Unit,
onRemoteControlChange: (Boolean) -> Unit,
onAllowAutoModeChange: (Boolean) -> Unit,
- onShowExitChange: (Boolean) -> Unit,
onStartOnBootChange: (Boolean) -> Unit,
onDebugModeChange: (Boolean) -> Unit,
onSourceRepoOpen: () -> Unit,
@@ -844,6 +852,35 @@ private fun SettingsContent(
)
}
+ item(key = "notifications") {
+ PreferenceCategory(
+ title = { Text(text = stringResource(R.string.pref_header_notifications)) },
+ modifier = Modifier.animateItem(),
+ )
+ }
+
+ item(key = "show_details") {
+ SwitchPreference(
+ checked = showDetails,
+ onCheckedChange = onShowDetailsChange,
+ shapes = BetterSegmentedShapes.top(),
+ title = { Text(text = stringResource(R.string.pref_show_details_name)) },
+ summary = { Text(text = stringResource(R.string.pref_show_details_desc)) },
+ modifier = Modifier.animateItem(),
+ )
+ }
+
+ item(key = "show_exit") {
+ SwitchPreference(
+ checked = showExit,
+ onCheckedChange = onShowExitChange,
+ shapes = BetterSegmentedShapes.bottom(),
+ title = { Text(text = stringResource(R.string.pref_show_exit_name)) },
+ summary = { Text(text = stringResource(R.string.pref_show_exit_desc)) },
+ modifier = Modifier.animateItem(),
+ )
+ }
+
item(key = "advanced") {
PreferenceCategory(
title = { Text(text = stringResource(R.string.pref_header_advanced)) },
@@ -873,17 +910,6 @@ private fun SettingsContent(
)
}
- item(key = "show_exit") {
- SwitchPreference(
- checked = showExit,
- onCheckedChange = onShowExitChange,
- shapes = BetterSegmentedShapes.middle(),
- title = { Text(text = stringResource(R.string.pref_show_exit_name)) },
- summary = { Text(text = stringResource(R.string.pref_show_exit_desc)) },
- modifier = Modifier.animateItem(),
- )
- }
-
item(key = "start_on_boot") {
SwitchPreference(
checked = startOnBoot,
@@ -1016,6 +1042,7 @@ private fun PreviewSettingsScreen() {
manualMode = false,
allowAutoMode = true,
preRunAction = null,
+ showDetails = true,
showExit = false,
folderStates = SyncthingService.FolderStates(),
deviceStates = SyncthingService.DeviceStates(),
@@ -1042,9 +1069,10 @@ private fun PreviewSettingsScreen() {
respectBatterySaver = true,
respectAutoSyncData = true,
keepAlive = false,
+ showDetails = true,
+ showExit = false,
remoteControl = false,
allowAutoMode = true,
- showExit = false,
startOnBoot = true,
isDebugMode = true,
onInhibitBatteryOptGrant = {},
@@ -1066,9 +1094,10 @@ private fun PreviewSettingsScreen() {
onRespectAutoSyncDataChange = {},
onSyncScheduleSettingsOpen = {},
onKeepAliveChange = {},
+ onShowDetailsChange = {},
+ onShowExitChange = {},
onRemoteControlChange = {},
onAllowAutoModeChange = {},
- onShowExitChange = {},
onStartOnBootChange = {},
onDebugModeChange = {},
onSourceRepoOpen = {},
diff --git a/app/src/main/java/com/chiller3/basicsync/syncthing/SyncthingService.kt b/app/src/main/java/com/chiller3/basicsync/syncthing/SyncthingService.kt
index 7909d2be..a2f38404 100644
--- a/app/src/main/java/com/chiller3/basicsync/syncthing/SyncthingService.kt
+++ b/app/src/main/java/com/chiller3/basicsync/syncthing/SyncthingService.kt
@@ -52,6 +52,7 @@ class SyncthingService : Service(), SyncthingStatusReceiver, DeviceStateListener
)
private val STATE_CHANGE_PREFS = arrayOf(
Preferences.PREF_KEEP_ALIVE,
+ Preferences.PREF_SHOW_DETAILS,
Preferences.PREF_SHOW_EXIT,
)
@@ -174,10 +175,25 @@ class SyncthingService : Service(), SyncthingStatusReceiver, DeviceStateListener
private val manualMode: Boolean,
private val allowAutoMode: Boolean,
private val preRunAction: PreRunAction?,
+ val showDetails: Boolean,
private val showExit: Boolean,
val folderStates: FolderStates,
val deviceStates: DeviceStates,
) {
+ fun equivalent(prev: ServiceState?): Boolean =
+ prev != null
+ && keepAlive == prev.keepAlive
+ && blockedReasons == prev.blockedReasons
+ && isStarted == prev.isStarted
+ && isResumed == prev.isResumed
+ && manualMode == prev.manualMode
+ && allowAutoMode == prev.allowAutoMode
+ && preRunAction == prev.preRunAction
+ && showDetails == prev.showDetails
+ && showExit == prev.showExit
+ && (!showDetails || (folderStates == prev.folderStates
+ && deviceStates == prev.deviceStates))
+
private val shouldResume: Boolean
get() = blockedReasons.isEmpty()
@@ -654,7 +670,7 @@ class SyncthingService : Service(), SyncthingStatusReceiver, DeviceStateListener
return
}
- val notificationState = ServiceState(
+ val serviceState = ServiceState(
keepAlive = prefs.keepAlive,
blockedReasons = blockedReasons,
isStarted = isStarted,
@@ -662,43 +678,49 @@ class SyncthingService : Service(), SyncthingStatusReceiver, DeviceStateListener
manualMode = prefs.isManualMode,
allowAutoMode = prefs.allowAutoMode,
preRunAction = currentPreRunAction,
+ showDetails = prefs.showDetails,
showExit = prefs.showExit,
folderStates = syncthingFolderStates,
deviceStates = syncthingDeviceStates,
)
- val wasChanged = notificationState != lastServiceState
+ val wasChanged = serviceState != lastServiceState
if (wasChanged || forceShowNotification) {
if (wasChanged) {
- deviceStateTracker.updateBusyFolders(notificationState.folderStates)
- deviceStateTracker.updateConnectedDevices(notificationState.deviceStates)
+ deviceStateTracker.updateBusyFolders(serviceState.folderStates)
+ deviceStateTracker.updateConnectedDevices(serviceState.deviceStates)
val guiInfo = guiInfo
- allListeners { it.onRunStateChanged(notificationState, guiInfo) }
+ allListeners { it.onRunStateChanged(serviceState, guiInfo) }
}
- val (id, notification) = notifications.createPersistentNotification(notificationState)
val useLocation = deviceStateTracker.canUseLocation()
- var type = 0
+ val locationChanged = useLocation != lastUseLocation
+ val notificationChanged = !serviceState.equivalent(lastServiceState)
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
- type = type or ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
- }
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && useLocation) {
- type = type or ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION
- }
+ if (locationChanged || notificationChanged || forceShowNotification) {
+ val (id, notification) = notifications.createPersistentNotification(serviceState)
+ var type = 0
- ServiceCompat.startForeground(this, id, notification, type)
- notifications.cancelOppositePersistentNotification(id)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ type = type or ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && useLocation) {
+ type = type or ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION
+ }
+
+ ServiceCompat.startForeground(this, id, notification, type)
+ notifications.cancelOppositePersistentNotification(id)
+ }
- if (lastUseLocation != useLocation) {
+ if (locationChanged) {
deviceStateTracker.refreshNetworkState()
lastUseLocation = useLocation
}
- lastServiceState = notificationState
+ lastServiceState = serviceState
}
}
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8c7157e2..764bb35f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -10,6 +10,8 @@
Configuration
Run conditions
+
+ Notifications
Advanced
@@ -100,6 +102,10 @@
Show Exit button
Show an Exit button in the persistent notification. The app will automatically start again after a reboot or when receiving a remote control command.
+
+ Detailed notifications
+
+ Show the status of shared folders and connected devices in the persistent notification.
Start on boot