feat: add notification for list content updates and manage preferences in SettingsScreen
This commit is contained in:
+11
@@ -42,6 +42,9 @@ class PreferencesManager(
|
||||
private val _notifyListRemoved = MutableStateFlow(isNotifyListRemovedEnabled())
|
||||
val notifyListRemoved: StateFlow<Boolean> = _notifyListRemoved.asStateFlow()
|
||||
|
||||
private val _notifyListContentUpdated = MutableStateFlow(isNotifyListContentUpdatedEnabled())
|
||||
val notifyListContentUpdated: StateFlow<Boolean> = _notifyListContentUpdated.asStateFlow()
|
||||
|
||||
fun getServerUrl(): String = prefs.getString(KEY_SERVER_URL, DEFAULT_SERVER_URL) ?: DEFAULT_SERVER_URL
|
||||
|
||||
fun setServerUrl(url: String) {
|
||||
@@ -169,6 +172,13 @@ class PreferencesManager(
|
||||
_notifyListRemoved.value = enabled
|
||||
}
|
||||
|
||||
private fun isNotifyListContentUpdatedEnabled(): Boolean = prefs.getBoolean(KEY_NOTIFY_LIST_CONTENT_UPDATED, true)
|
||||
|
||||
fun setNotifyListContentUpdatedEnabled(enabled: Boolean) {
|
||||
prefs.edit().putBoolean(KEY_NOTIFY_LIST_CONTENT_UPDATED, enabled).apply()
|
||||
_notifyListContentUpdated.value = enabled
|
||||
}
|
||||
|
||||
// Persist per-list column widths (fieldId -> widthDp)
|
||||
// Stored as a JSON object string in SharedPreferences under key: COLUMN_WIDTHS_PREFIX + listId
|
||||
fun getColumnWidths(listId: String): Map<String, Float> {
|
||||
@@ -261,6 +271,7 @@ class PreferencesManager(
|
||||
private const val KEY_NOTIFY_LIST_ADDED = "notify_list_added"
|
||||
private const val KEY_NOTIFY_LIST_EDITED = "notify_list_edited"
|
||||
private const val KEY_NOTIFY_LIST_REMOVED = "notify_list_removed"
|
||||
private const val KEY_NOTIFY_LIST_CONTENT_UPDATED = "notify_list_content_updated"
|
||||
private const val KEY_LAST_LIST_NOTIFY_CHECK_TS = "last_list_notify_check_ts"
|
||||
private const val COLUMN_WIDTHS_PREFIX = "column_widths_" // + listId
|
||||
private const val COLUMN_ALIGN_PREFIX = "column_align_" // + listId
|
||||
|
||||
+7
@@ -57,6 +57,12 @@ object NotificationHelper {
|
||||
name: String,
|
||||
) = showEvent(context, listId, "remove", "List removed", "\"$name\" was deleted")
|
||||
|
||||
fun showListContentUpdated(
|
||||
context: Context,
|
||||
listId: String,
|
||||
name: String,
|
||||
) = showEvent(context, listId, "content", "List updated", "\"$name\" content changed")
|
||||
|
||||
private fun showEvent(
|
||||
context: Context,
|
||||
listId: String,
|
||||
@@ -102,6 +108,7 @@ object NotificationHelper {
|
||||
"add" -> "Added • $text"
|
||||
"edit" -> "Edited • $text"
|
||||
"remove" -> "Removed • $text"
|
||||
"content" -> "Updated • $text"
|
||||
else -> text
|
||||
}
|
||||
synchronized(recentEventLines) {
|
||||
|
||||
+2
-2
@@ -563,8 +563,8 @@ fun ListDetailScreen(
|
||||
}
|
||||
}
|
||||
|
||||
// Loading overlay during initial content load
|
||||
if (isLoading) {
|
||||
// Loading overlay only while nothing is available to render yet
|
||||
if (isLoading && stableFields.isEmpty() && stableItems.isEmpty()) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center,
|
||||
|
||||
+21
@@ -3,6 +3,8 @@ package com.collabtable.app.ui.screens
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import androidx.room.withTransaction
|
||||
import com.collabtable.app.data.database.CollabTableDatabase
|
||||
import com.collabtable.app.data.model.CollabList
|
||||
@@ -120,6 +122,19 @@ class ListDetailViewModel(
|
||||
syncRepository.performSync()
|
||||
}
|
||||
|
||||
private fun isInForeground(): Boolean {
|
||||
val state = ProcessLifecycleOwner.get().lifecycle.currentState
|
||||
return state.isAtLeast(Lifecycle.State.STARTED)
|
||||
}
|
||||
|
||||
private fun maybeNotifyListContentUpdated() {
|
||||
val prefs = com.collabtable.app.data.preferences.PreferencesManager.getInstance(context)
|
||||
if (prefs.notifyListContentUpdated.value && !isInForeground()) {
|
||||
val name = _list.value?.name ?: "Table"
|
||||
com.collabtable.app.notifications.NotificationHelper.showListContentUpdated(context, listId, name)
|
||||
}
|
||||
}
|
||||
|
||||
fun renameList(newName: String) {
|
||||
viewModelScope.launch {
|
||||
val currentList = _list.value
|
||||
@@ -184,6 +199,7 @@ class ListDetailViewModel(
|
||||
}
|
||||
|
||||
performSync()
|
||||
maybeNotifyListContentUpdated()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +213,7 @@ class ListDetailViewModel(
|
||||
}
|
||||
}
|
||||
performSync()
|
||||
maybeNotifyListContentUpdated()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +241,7 @@ class ListDetailViewModel(
|
||||
}
|
||||
}
|
||||
performSync()
|
||||
maybeNotifyListContentUpdated()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -260,6 +278,7 @@ class ListDetailViewModel(
|
||||
}
|
||||
}
|
||||
performSync()
|
||||
maybeNotifyListContentUpdated()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,6 +314,7 @@ class ListDetailViewModel(
|
||||
}
|
||||
}
|
||||
performSync()
|
||||
maybeNotifyListContentUpdated()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,6 +352,7 @@ class ListDetailViewModel(
|
||||
}
|
||||
}
|
||||
performSync()
|
||||
maybeNotifyListContentUpdated()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ fun SettingsScreen(
|
||||
val notifyListAdded by preferencesManager.notifyListAdded.collectAsState()
|
||||
val notifyListEdited by preferencesManager.notifyListEdited.collectAsState()
|
||||
val notifyListRemoved by preferencesManager.notifyListRemoved.collectAsState()
|
||||
val notifyListContentUpdated by preferencesManager.notifyListContentUpdated.collectAsState()
|
||||
val displayUrl = remember(serverUrl) { formatServerUrlForDisplay(serverUrl) }
|
||||
var showLeaveDialog by remember { mutableStateOf(false) }
|
||||
var isLeaving by remember { mutableStateOf(false) }
|
||||
@@ -379,6 +380,32 @@ fun SettingsScreen(
|
||||
},
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text("List content updated")
|
||||
Text(
|
||||
text = "Notify when fields or items change (add/edit/delete)",
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
Switch(
|
||||
checked = notifyListContentUpdated,
|
||||
onCheckedChange = { checked ->
|
||||
if (checked) {
|
||||
ensureNotificationPermission {
|
||||
preferencesManager.setNotifyListContentUpdatedEnabled(true)
|
||||
}
|
||||
} else {
|
||||
preferencesManager.setNotifyListContentUpdatedEnabled(false)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
|
||||
+3
-2
@@ -50,8 +50,9 @@ class ListChangeNotificationWorker(
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if (prefs.notifyListEdited.value) {
|
||||
NotificationHelper.showListEdited(applicationContext, list.id, list.name)
|
||||
// Background diff cannot distinguish rename vs content. Treat as content update here.
|
||||
if (prefs.notifyListContentUpdated.value) {
|
||||
NotificationHelper.showListContentUpdated(applicationContext, list.id, list.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user