mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-23 20:48:43 +00:00
Clean up chat folder records.
This commit is contained in:
committed by
Cody Henthorne
parent
247c5de140
commit
82bb18e218
@@ -73,7 +73,6 @@ class ChatFolderTablesTest {
|
|||||||
showUnread = true,
|
showUnread = true,
|
||||||
showMutedChats = true,
|
showMutedChats = true,
|
||||||
showGroupChats = true,
|
showGroupChats = true,
|
||||||
isMuted = true,
|
|
||||||
folderType = ChatFolderRecord.FolderType.GROUP
|
folderType = ChatFolderRecord.FolderType.GROUP
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -96,7 +95,6 @@ class ChatFolderTablesTest {
|
|||||||
val updatedFolder = folder.copy(
|
val updatedFolder = folder.copy(
|
||||||
name = "updatedFolder2",
|
name = "updatedFolder2",
|
||||||
position = 1,
|
position = 1,
|
||||||
isMuted = true,
|
|
||||||
includedChats = listOf(aliceThread, charlieThread),
|
includedChats = listOf(aliceThread, charlieThread),
|
||||||
excludedChats = listOf(bobThread)
|
excludedChats = listOf(bobThread)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.thoughtcrime.securesms.components.settings.app.chats.folders
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information needed when creating/updating a chat folder. Used in [ChatFoldersSettingsState]
|
||||||
|
*/
|
||||||
|
data class ChatFolder(
|
||||||
|
val folderRecord: ChatFolderRecord = ChatFolderRecord(),
|
||||||
|
val includedRecipients: Set<Recipient> = emptySet(),
|
||||||
|
val excludedRecipients: Set<Recipient> = emptySet()
|
||||||
|
)
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.components.settings.app.chats.folders
|
package org.thoughtcrime.securesms.components.settings.app.chats.folders
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import kotlinx.parcelize.IgnoredOnParcel
|
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an entry in the [org.thoughtcrime.securesms.database.ChatFolderTables].
|
* Represents an entry in the [org.thoughtcrime.securesms.database.ChatFolderTables].
|
||||||
@@ -15,17 +13,11 @@ data class ChatFolderRecord(
|
|||||||
val position: Int = -1,
|
val position: Int = -1,
|
||||||
val includedChats: List<Long> = emptyList(),
|
val includedChats: List<Long> = emptyList(),
|
||||||
val excludedChats: List<Long> = emptyList(),
|
val excludedChats: List<Long> = emptyList(),
|
||||||
@IgnoredOnParcel
|
|
||||||
val includedRecipients: Set<Recipient> = emptySet(),
|
|
||||||
@IgnoredOnParcel
|
|
||||||
val excludedRecipients: Set<Recipient> = emptySet(),
|
|
||||||
val showUnread: Boolean = false,
|
val showUnread: Boolean = false,
|
||||||
val showMutedChats: Boolean = true,
|
val showMutedChats: Boolean = true,
|
||||||
val showIndividualChats: Boolean = false,
|
val showIndividualChats: Boolean = false,
|
||||||
val showGroupChats: Boolean = false,
|
val showGroupChats: Boolean = false,
|
||||||
val isMuted: Boolean = false,
|
val folderType: FolderType = FolderType.CUSTOM
|
||||||
val folderType: FolderType = FolderType.CUSTOM,
|
|
||||||
val unreadCount: Int = 0
|
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
enum class FolderType(val value: Int) {
|
enum class FolderType(val value: Int) {
|
||||||
/** Folder containing all chats */
|
/** Folder containing all chats */
|
||||||
|
|||||||
@@ -404,7 +404,6 @@ private fun ChatFolderPreview() {
|
|||||||
showIndividualChats = true,
|
showIndividualChats = true,
|
||||||
showGroupChats = true,
|
showGroupChats = true,
|
||||||
showMutedChats = true,
|
showMutedChats = true,
|
||||||
isMuted = false,
|
|
||||||
folderType = ChatFolderRecord.FolderType.CUSTOM
|
folderType = ChatFolderRecord.FolderType.CUSTOM
|
||||||
),
|
),
|
||||||
ChatFolderRecord(
|
ChatFolderRecord(
|
||||||
@@ -415,7 +414,6 @@ private fun ChatFolderPreview() {
|
|||||||
showIndividualChats = true,
|
showIndividualChats = true,
|
||||||
showGroupChats = false,
|
showGroupChats = false,
|
||||||
showMutedChats = false,
|
showMutedChats = false,
|
||||||
isMuted = false,
|
|
||||||
folderType = ChatFolderRecord.FolderType.CUSTOM
|
folderType = ChatFolderRecord.FolderType.CUSTOM
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,19 +1,24 @@
|
|||||||
package org.thoughtcrime.securesms.components.settings.app.chats.folders
|
package org.thoughtcrime.securesms.components.settings.app.chats.folders
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||||
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repository for chat folders that handles creation, deletion, listing, etc.,
|
* Repository for chat folders that handles creation, deletion, listing, etc.,
|
||||||
*/
|
*/
|
||||||
object ChatFoldersRepository {
|
object ChatFoldersRepository {
|
||||||
|
|
||||||
fun getCurrentFolders(includeUnreadAndMutedCounts: Boolean = false): List<ChatFolderRecord> {
|
fun getCurrentFolders(): List<ChatFolderRecord> {
|
||||||
return SignalDatabase.chatFolders.getChatFolders(includeUnreadAndMutedCounts)
|
return SignalDatabase.chatFolders.getChatFolders()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createFolder(folder: ChatFolderRecord) {
|
fun getUnreadCountAndMutedStatusForFolders(folders: List<ChatFolderRecord>): HashMap<Long, Pair<Int, Boolean>> {
|
||||||
val includedChats = folder.includedRecipients.map { recipient -> SignalDatabase.threads.getOrCreateThreadIdFor(recipient) }
|
return SignalDatabase.chatFolders.getUnreadCountAndMutedStatusForFolders(folders)
|
||||||
val excludedChats = folder.excludedRecipients.map { recipient -> SignalDatabase.threads.getOrCreateThreadIdFor(recipient) }
|
}
|
||||||
|
|
||||||
|
fun createFolder(folder: ChatFolderRecord, includedRecipients: Set<Recipient>, excludedRecipients: Set<Recipient>) {
|
||||||
|
val includedChats = includedRecipients.map { recipient -> SignalDatabase.threads.getOrCreateThreadIdFor(recipient) }
|
||||||
|
val excludedChats = excludedRecipients.map { recipient -> SignalDatabase.threads.getOrCreateThreadIdFor(recipient) }
|
||||||
val updatedFolder = folder.copy(
|
val updatedFolder = folder.copy(
|
||||||
includedChats = includedChats,
|
includedChats = includedChats,
|
||||||
excludedChats = excludedChats
|
excludedChats = excludedChats
|
||||||
@@ -22,9 +27,9 @@ object ChatFoldersRepository {
|
|||||||
SignalDatabase.chatFolders.createFolder(updatedFolder)
|
SignalDatabase.chatFolders.createFolder(updatedFolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateFolder(folder: ChatFolderRecord) {
|
fun updateFolder(folder: ChatFolderRecord, includedRecipients: Set<Recipient>, excludedRecipients: Set<Recipient>) {
|
||||||
val includedChats = folder.includedRecipients.map { recipient -> SignalDatabase.threads.getOrCreateThreadIdFor(recipient) }
|
val includedChats = includedRecipients.map { recipient -> SignalDatabase.threads.getOrCreateThreadIdFor(recipient) }
|
||||||
val excludedChats = folder.excludedRecipients.map { recipient -> SignalDatabase.threads.getOrCreateThreadIdFor(recipient) }
|
val excludedChats = excludedRecipients.map { recipient -> SignalDatabase.threads.getOrCreateThreadIdFor(recipient) }
|
||||||
val updatedFolder = folder.copy(
|
val updatedFolder = folder.copy(
|
||||||
includedChats = includedChats,
|
includedChats = includedChats,
|
||||||
excludedChats = excludedChats
|
excludedChats = excludedChats
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import org.thoughtcrime.securesms.recipients.RecipientId
|
|||||||
data class ChatFoldersSettingsState(
|
data class ChatFoldersSettingsState(
|
||||||
val folders: List<ChatFolderRecord> = emptyList(),
|
val folders: List<ChatFolderRecord> = emptyList(),
|
||||||
val suggestedFolders: List<ChatFolderRecord> = emptyList(),
|
val suggestedFolders: List<ChatFolderRecord> = emptyList(),
|
||||||
val originalFolder: ChatFolderRecord = ChatFolderRecord(),
|
val originalFolder: ChatFolder = ChatFolder(),
|
||||||
val currentFolder: ChatFolderRecord = ChatFolderRecord(),
|
val currentFolder: ChatFolder = ChatFolder(),
|
||||||
val showDeleteDialog: Boolean = false,
|
val showDeleteDialog: Boolean = false,
|
||||||
val showConfirmationDialog: Boolean = false,
|
val showConfirmationDialog: Boolean = false,
|
||||||
val pendingIncludedRecipients: Set<RecipientId> = emptySet(),
|
val pendingIncludedRecipients: Set<RecipientId> = emptySet(),
|
||||||
|
|||||||
@@ -24,15 +24,15 @@ class ChatFoldersViewModel : ViewModel() {
|
|||||||
|
|
||||||
fun loadCurrentFolders(context: Context) {
|
fun loadCurrentFolders(context: Context) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val folders = ChatFoldersRepository.getCurrentFolders(includeUnreadAndMutedCounts = false)
|
val folders = ChatFoldersRepository.getCurrentFolders()
|
||||||
val suggestedFolders = getSuggestedFolders(context, folders)
|
val suggestedFolders = getSuggestedFolders(context, folders)
|
||||||
|
|
||||||
internalState.update {
|
internalState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
folders = folders,
|
folders = folders,
|
||||||
suggestedFolders = suggestedFolders,
|
suggestedFolders = suggestedFolders,
|
||||||
currentFolder = ChatFolderRecord(),
|
currentFolder = ChatFolder(),
|
||||||
originalFolder = ChatFolderRecord()
|
originalFolder = ChatFolder()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,8 @@ class ChatFoldersViewModel : ViewModel() {
|
|||||||
SignalDatabase.threads.getRecipientForThreadId(threadId)
|
SignalDatabase.threads.getRecipientForThreadId(threadId)
|
||||||
}
|
}
|
||||||
|
|
||||||
val updatedFolder = folder.copy(
|
val updatedFolder = ChatFolder(
|
||||||
|
folderRecord = folder,
|
||||||
includedRecipients = includedRecipients.toSet(),
|
includedRecipients = includedRecipients.toSet(),
|
||||||
excludedRecipients = excludedRecipients.toSet()
|
excludedRecipients = excludedRecipients.toSet()
|
||||||
)
|
)
|
||||||
@@ -112,32 +113,32 @@ class ChatFoldersViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun updateName(name: String) {
|
fun updateName(name: String) {
|
||||||
val updatedFolder = internalState.value.currentFolder.copy(
|
val updatedFolder = internalState.value.currentFolder.folderRecord.copy(
|
||||||
name = name.substring(0, minOf(name.length, 32))
|
name = name.substring(0, minOf(name.length, 32))
|
||||||
)
|
)
|
||||||
|
|
||||||
internalState.update {
|
internalState.update {
|
||||||
it.copy(currentFolder = updatedFolder)
|
it.copy(currentFolder = it.currentFolder.copy(folderRecord = updatedFolder))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleShowUnread(showUnread: Boolean) {
|
fun toggleShowUnread(showUnread: Boolean) {
|
||||||
val updatedFolder = internalState.value.currentFolder.copy(
|
val updatedFolder = internalState.value.currentFolder.folderRecord.copy(
|
||||||
showUnread = showUnread
|
showUnread = showUnread
|
||||||
)
|
)
|
||||||
|
|
||||||
internalState.update {
|
internalState.update {
|
||||||
it.copy(currentFolder = updatedFolder)
|
it.copy(currentFolder = it.currentFolder.copy(folderRecord = updatedFolder))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleShowMutedChats(showMuted: Boolean) {
|
fun toggleShowMutedChats(showMuted: Boolean) {
|
||||||
val updatedFolder = internalState.value.currentFolder.copy(
|
val updatedFolder = internalState.value.currentFolder.folderRecord.copy(
|
||||||
showMutedChats = showMuted
|
showMutedChats = showMuted
|
||||||
)
|
)
|
||||||
|
|
||||||
internalState.update {
|
internalState.update {
|
||||||
it.copy(currentFolder = updatedFolder)
|
it.copy(currentFolder = it.currentFolder.copy(folderRecord = updatedFolder))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +150,7 @@ class ChatFoldersViewModel : ViewModel() {
|
|||||||
|
|
||||||
fun deleteFolder(context: Context) {
|
fun deleteFolder(context: Context) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
ChatFoldersRepository.deleteFolder(internalState.value.originalFolder)
|
ChatFoldersRepository.deleteFolder(internalState.value.originalFolder.folderRecord)
|
||||||
|
|
||||||
loadCurrentFolders(context)
|
loadCurrentFolders(context)
|
||||||
internalState.update {
|
internalState.update {
|
||||||
@@ -166,8 +167,8 @@ class ChatFoldersViewModel : ViewModel() {
|
|||||||
|
|
||||||
fun createFolder(context: Context, folder: ChatFolderRecord? = null) {
|
fun createFolder(context: Context, folder: ChatFolderRecord? = null) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val currentFolder = folder ?: internalState.value.currentFolder
|
val currentFolder = if (folder != null) ChatFolder(folder) else internalState.value.currentFolder
|
||||||
ChatFoldersRepository.createFolder(currentFolder)
|
ChatFoldersRepository.createFolder(currentFolder.folderRecord, currentFolder.includedRecipients, currentFolder.excludedRecipients)
|
||||||
loadCurrentFolders(context)
|
loadCurrentFolders(context)
|
||||||
|
|
||||||
internalState.update {
|
internalState.update {
|
||||||
@@ -192,7 +193,8 @@ class ChatFoldersViewModel : ViewModel() {
|
|||||||
|
|
||||||
fun updateFolder(context: Context) {
|
fun updateFolder(context: Context) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
ChatFoldersRepository.updateFolder(internalState.value.currentFolder)
|
val currentFolder = internalState.value.currentFolder
|
||||||
|
ChatFoldersRepository.updateFolder(currentFolder.folderRecord, currentFolder.includedRecipients, currentFolder.excludedRecipients)
|
||||||
loadCurrentFolders(context)
|
loadCurrentFolders(context)
|
||||||
|
|
||||||
internalState.update {
|
internalState.update {
|
||||||
@@ -208,10 +210,10 @@ class ChatFoldersViewModel : ViewModel() {
|
|||||||
val excludedChats = currentFolder.excludedRecipients.map { recipient -> recipient.id }.toMutableSet()
|
val excludedChats = currentFolder.excludedRecipients.map { recipient -> recipient.id }.toMutableSet()
|
||||||
|
|
||||||
val chatTypes: MutableSet<ChatType> = mutableSetOf()
|
val chatTypes: MutableSet<ChatType> = mutableSetOf()
|
||||||
if (currentFolder.showIndividualChats) {
|
if (currentFolder.folderRecord.showIndividualChats) {
|
||||||
chatTypes.add(ChatType.INDIVIDUAL)
|
chatTypes.add(ChatType.INDIVIDUAL)
|
||||||
}
|
}
|
||||||
if (currentFolder.showGroupChats) {
|
if (currentFolder.folderRecord.showGroupChats) {
|
||||||
chatTypes.add(ChatType.GROUPS)
|
chatTypes.add(ChatType.GROUPS)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,11 +311,13 @@ class ChatFoldersViewModel : ViewModel() {
|
|||||||
internalState.update {
|
internalState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
currentFolder = updatedFolder.copy(
|
currentFolder = updatedFolder.copy(
|
||||||
includedRecipients = includedRecipients,
|
folderRecord = updatedFolder.folderRecord.copy(
|
||||||
excludedRecipients = excludedRecipients,
|
|
||||||
showIndividualChats = showIndividualChats,
|
showIndividualChats = showIndividualChats,
|
||||||
showGroupChats = showGroupChats
|
showGroupChats = showGroupChats
|
||||||
),
|
),
|
||||||
|
includedRecipients = includedRecipients,
|
||||||
|
excludedRecipients = excludedRecipients
|
||||||
|
),
|
||||||
pendingIncludedRecipients = emptySet(),
|
pendingIncludedRecipients = emptySet(),
|
||||||
pendingExcludedRecipients = emptySet()
|
pendingExcludedRecipients = emptySet()
|
||||||
)
|
)
|
||||||
@@ -331,8 +335,8 @@ class ChatFoldersViewModel : ViewModel() {
|
|||||||
val currentFolder = state.value.currentFolder
|
val currentFolder = state.value.currentFolder
|
||||||
val originalFolder = state.value.originalFolder
|
val originalFolder = state.value.originalFolder
|
||||||
|
|
||||||
return if (currentFolder.id == -1L) {
|
return if (currentFolder.folderRecord.id == -1L) {
|
||||||
currentFolder.includedRecipients.isNotEmpty() || currentFolder.showIndividualChats || currentFolder.showGroupChats
|
currentFolder.includedRecipients.isNotEmpty() || currentFolder.folderRecord.showIndividualChats || currentFolder.folderRecord.showGroupChats
|
||||||
} else {
|
} else {
|
||||||
originalFolder != currentFolder ||
|
originalFolder != currentFolder ||
|
||||||
originalFolder.includedRecipients != currentFolder.includedRecipients ||
|
originalFolder.includedRecipients != currentFolder.includedRecipients ||
|
||||||
@@ -350,6 +354,6 @@ class ChatFoldersViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun hasEmptyName(): Boolean {
|
fun hasEmptyName(): Boolean {
|
||||||
return state.value.currentFolder.name.isEmpty()
|
return state.value.currentFolder.folderRecord.name.isEmpty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ class CreateFoldersFragment : ComposeFragment() {
|
|||||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||||
val navController: NavController by remember { mutableStateOf(findNavController()) }
|
val navController: NavController by remember { mutableStateOf(findNavController()) }
|
||||||
val focusRequester = remember { FocusRequester() }
|
val focusRequester = remember { FocusRequester() }
|
||||||
val isNewFolder = state.originalFolder.id == -1L
|
val isNewFolder = state.originalFolder.folderRecord.id == -1L
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
if (state.originalFolder == state.currentFolder) {
|
if (state.originalFolder == state.currentFolder) {
|
||||||
@@ -221,7 +221,7 @@ fun CreateFolderScreen(
|
|||||||
LazyColumn {
|
LazyColumn {
|
||||||
item {
|
item {
|
||||||
TextField(
|
TextField(
|
||||||
value = state.currentFolder.name,
|
value = state.currentFolder.folderRecord.name,
|
||||||
label = { Text(text = stringResource(id = R.string.CreateFoldersFragment__folder_name)) },
|
label = { Text(text = stringResource(id = R.string.CreateFoldersFragment__folder_name)) },
|
||||||
onValueChange = onNameChange,
|
onValueChange = onNameChange,
|
||||||
keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences),
|
keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences),
|
||||||
@@ -245,7 +245,7 @@ fun CreateFolderScreen(
|
|||||||
onClick = onAddChat
|
onClick = onAddChat
|
||||||
)
|
)
|
||||||
|
|
||||||
if (state.currentFolder.showIndividualChats) {
|
if (state.currentFolder.folderRecord.showIndividualChats) {
|
||||||
FolderRow(
|
FolderRow(
|
||||||
icon = R.drawable.symbol_person_light_24,
|
icon = R.drawable.symbol_person_light_24,
|
||||||
title = stringResource(R.string.ChatFoldersFragment__one_on_one_chats),
|
title = stringResource(R.string.ChatFoldersFragment__one_on_one_chats),
|
||||||
@@ -253,7 +253,7 @@ fun CreateFolderScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.currentFolder.showGroupChats) {
|
if (state.currentFolder.folderRecord.showGroupChats) {
|
||||||
FolderRow(
|
FolderRow(
|
||||||
icon = R.drawable.symbol_group_light_20,
|
icon = R.drawable.symbol_group_light_20,
|
||||||
title = stringResource(R.string.ChatFoldersFragment__groups),
|
title = stringResource(R.string.ChatFoldersFragment__groups),
|
||||||
@@ -366,12 +366,12 @@ fun CreateFolderScreen(
|
|||||||
|
|
||||||
Buttons.MediumTonal(
|
Buttons.MediumTonal(
|
||||||
colors = ButtonDefaults.filledTonalButtonColors(
|
colors = ButtonDefaults.filledTonalButtonColors(
|
||||||
contentColor = if (state.currentFolder.name.isEmpty()) {
|
contentColor = if (state.currentFolder.folderRecord.name.isEmpty()) {
|
||||||
MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)
|
MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)
|
||||||
} else {
|
} else {
|
||||||
MaterialTheme.colorScheme.onSurface
|
MaterialTheme.colorScheme.onSurface
|
||||||
},
|
},
|
||||||
containerColor = if (state.currentFolder.name.isEmpty()) {
|
containerColor = if (state.currentFolder.folderRecord.name.isEmpty()) {
|
||||||
MaterialTheme.colorScheme.surfaceVariant
|
MaterialTheme.colorScheme.surfaceVariant
|
||||||
} else {
|
} else {
|
||||||
MaterialTheme.colorScheme.primaryContainer
|
MaterialTheme.colorScheme.primaryContainer
|
||||||
@@ -380,7 +380,7 @@ fun CreateFolderScreen(
|
|||||||
),
|
),
|
||||||
enabled = hasChanges,
|
enabled = hasChanges,
|
||||||
onClick = {
|
onClick = {
|
||||||
if (state.currentFolder.name.isEmpty()) {
|
if (state.currentFolder.folderRecord.name.isEmpty()) {
|
||||||
onShowToast()
|
onShowToast()
|
||||||
} else {
|
} else {
|
||||||
onCreateConfirmed()
|
onCreateConfirmed()
|
||||||
@@ -419,7 +419,7 @@ private fun ShowUnreadSection(state: ChatFoldersSettingsState, onToggleShowUnrea
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
Switch(
|
Switch(
|
||||||
checked = state.currentFolder.showUnread,
|
checked = state.currentFolder.folderRecord.showUnread,
|
||||||
onCheckedChange = onToggleShowUnread
|
onCheckedChange = onToggleShowUnread
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -440,7 +440,7 @@ private fun ShowMutedSection(state: ChatFoldersSettingsState, onToggleShowMuted:
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
Switch(
|
Switch(
|
||||||
checked = state.currentFolder.showMutedChats,
|
checked = state.currentFolder.folderRecord.showMutedChats,
|
||||||
onCheckedChange = onToggleShowMuted
|
onCheckedChange = onToggleShowMuted
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -449,7 +449,7 @@ private fun ShowMutedSection(state: ChatFoldersSettingsState, onToggleShowMuted:
|
|||||||
@SignalPreview
|
@SignalPreview
|
||||||
@Composable
|
@Composable
|
||||||
private fun CreateFolderPreview() {
|
private fun CreateFolderPreview() {
|
||||||
val previewFolder = ChatFolderRecord(id = 1, name = "WIP")
|
val previewFolder = ChatFolder(ChatFolderRecord(id = 1, name = "WIP"))
|
||||||
|
|
||||||
Previews.Preview {
|
Previews.Preview {
|
||||||
CreateFolderScreen(
|
CreateFolderScreen(
|
||||||
@@ -463,7 +463,7 @@ private fun CreateFolderPreview() {
|
|||||||
@SignalPreview
|
@SignalPreview
|
||||||
@Composable
|
@Composable
|
||||||
private fun EditFolderPreview() {
|
private fun EditFolderPreview() {
|
||||||
val previewFolder = ChatFolderRecord(id = 1, name = "Work")
|
val previewFolder = ChatFolder(ChatFolderRecord(id = 1, name = "Work"))
|
||||||
|
|
||||||
Previews.Preview {
|
Previews.Preview {
|
||||||
CreateFolderScreen(
|
CreateFolderScreen(
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ class ChatFolderAdapter(val callbacks: Callbacks) : MappingAdapter() {
|
|||||||
|
|
||||||
val folder = model.chatFolder
|
val folder = model.chatFolder
|
||||||
name.text = getName(itemView.context, folder)
|
name.text = getName(itemView.context, folder)
|
||||||
unreadCount.visible = folder.unreadCount > 0
|
unreadCount.visible = model.unreadCount > 0
|
||||||
unreadCount.text = if (folder.unreadCount > 99) itemView.context.getString(R.string.ChatFolderAdapter__99p) else folder.unreadCount.toString()
|
unreadCount.text = if (model.unreadCount > 99) itemView.context.getString(R.string.ChatFolderAdapter__99p) else model.unreadCount.toString()
|
||||||
itemView.setOnClickListener {
|
itemView.setOnClickListener {
|
||||||
callbacks.onChatFolderClicked(model.chatFolder)
|
callbacks.onChatFolderClicked(model.chatFolder)
|
||||||
}
|
}
|
||||||
@@ -42,8 +42,8 @@ class ChatFolderAdapter(val callbacks: Callbacks) : MappingAdapter() {
|
|||||||
context = itemView.context,
|
context = itemView.context,
|
||||||
anchorView = view,
|
anchorView = view,
|
||||||
folderType = model.chatFolder.folderType,
|
folderType = model.chatFolder.folderType,
|
||||||
unreadCount = folder.unreadCount,
|
unreadCount = model.unreadCount,
|
||||||
isMuted = folder.isMuted,
|
isMuted = model.isMuted,
|
||||||
onEdit = { callbacks.onEdit(model.chatFolder) },
|
onEdit = { callbacks.onEdit(model.chatFolder) },
|
||||||
onMuteAll = { callbacks.onMuteAll(model.chatFolder) },
|
onMuteAll = { callbacks.onMuteAll(model.chatFolder) },
|
||||||
onUnmuteAll = { callbacks.onUnmuteAll(model.chatFolder) },
|
onUnmuteAll = { callbacks.onUnmuteAll(model.chatFolder) },
|
||||||
|
|||||||
@@ -3,8 +3,13 @@ package org.thoughtcrime.securesms.conversationlist
|
|||||||
import org.thoughtcrime.securesms.components.settings.app.chats.folders.ChatFolderRecord
|
import org.thoughtcrime.securesms.components.settings.app.chats.folders.ChatFolderRecord
|
||||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel
|
import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping model of folders used in [ChatFolderAdapter]
|
||||||
|
*/
|
||||||
data class ChatFolderMappingModel(
|
data class ChatFolderMappingModel(
|
||||||
val chatFolder: ChatFolderRecord,
|
val chatFolder: ChatFolderRecord,
|
||||||
|
val unreadCount: Int,
|
||||||
|
val isMuted: Boolean,
|
||||||
val isSelected: Boolean
|
val isSelected: Boolean
|
||||||
) : MappingModel<ChatFolderMappingModel> {
|
) : MappingModel<ChatFolderMappingModel> {
|
||||||
override fun areItemsTheSame(newItem: ChatFolderMappingModel): Boolean {
|
override fun areItemsTheSame(newItem: ChatFolderMappingModel): Boolean {
|
||||||
@@ -12,6 +17,9 @@ data class ChatFolderMappingModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun areContentsTheSame(newItem: ChatFolderMappingModel): Boolean {
|
override fun areContentsTheSame(newItem: ChatFolderMappingModel): Boolean {
|
||||||
return chatFolder == newItem.chatFolder && isSelected == newItem.isSelected
|
return chatFolder == newItem.chatFolder &&
|
||||||
|
unreadCount == newItem.unreadCount &&
|
||||||
|
isMuted == newItem.isMuted &&
|
||||||
|
isSelected == newItem.isSelected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,7 +218,8 @@ class ConversationListViewModel(
|
|||||||
|
|
||||||
private fun loadCurrentFolders() {
|
private fun loadCurrentFolders() {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val folders = ChatFoldersRepository.getCurrentFolders(includeUnreadAndMutedCounts = true)
|
val folders = ChatFoldersRepository.getCurrentFolders()
|
||||||
|
val unreadCountAndMutedStatus = ChatFoldersRepository.getUnreadCountAndMutedStatusForFolders(folders)
|
||||||
|
|
||||||
val selectedFolderId = if (currentFolder.id == -1L) {
|
val selectedFolderId = if (currentFolder.id == -1L) {
|
||||||
folders.firstOrNull()?.id
|
folders.firstOrNull()?.id
|
||||||
@@ -226,7 +227,12 @@ class ConversationListViewModel(
|
|||||||
currentFolder.id
|
currentFolder.id
|
||||||
}
|
}
|
||||||
val chatFolders = folders.map { folder ->
|
val chatFolders = folders.map { folder ->
|
||||||
ChatFolderMappingModel(folder, selectedFolderId == folder.id)
|
ChatFolderMappingModel(
|
||||||
|
chatFolder = folder,
|
||||||
|
unreadCount = unreadCountAndMutedStatus[folder.id]?.first ?: 0,
|
||||||
|
isMuted = unreadCountAndMutedStatus[folder.id]?.second ?: false,
|
||||||
|
isSelected = selectedFolderId == folder.id
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
store.update {
|
store.update {
|
||||||
|
|||||||
@@ -140,7 +140,6 @@ class ChatFolderTables(context: Context?, databaseHelper: SignalDatabase?) : Dat
|
|||||||
showMutedChats = cursor.requireBoolean(ChatFolderTable.SHOW_MUTED),
|
showMutedChats = cursor.requireBoolean(ChatFolderTable.SHOW_MUTED),
|
||||||
showIndividualChats = cursor.requireBoolean(ChatFolderTable.SHOW_INDIVIDUAL),
|
showIndividualChats = cursor.requireBoolean(ChatFolderTable.SHOW_INDIVIDUAL),
|
||||||
showGroupChats = cursor.requireBoolean(ChatFolderTable.SHOW_GROUPS),
|
showGroupChats = cursor.requireBoolean(ChatFolderTable.SHOW_GROUPS),
|
||||||
isMuted = cursor.requireBoolean(ChatFolderTable.IS_MUTED),
|
|
||||||
folderType = ChatFolderRecord.FolderType.deserialize(cursor.requireInt(ChatFolderTable.FOLDER_TYPE)),
|
folderType = ChatFolderRecord.FolderType.deserialize(cursor.requireInt(ChatFolderTable.FOLDER_TYPE)),
|
||||||
includedChats = includedChats[id] ?: emptyList(),
|
includedChats = includedChats[id] ?: emptyList(),
|
||||||
excludedChats = excludedChats[id] ?: emptyList()
|
excludedChats = excludedChats[id] ?: emptyList()
|
||||||
@@ -153,7 +152,7 @@ class ChatFolderTables(context: Context?, databaseHelper: SignalDatabase?) : Dat
|
|||||||
/**
|
/**
|
||||||
* Maps the chat folder ids to its corresponding chat folder
|
* Maps the chat folder ids to its corresponding chat folder
|
||||||
*/
|
*/
|
||||||
fun getChatFolders(includeUnreadAndMutedCount: Boolean = false): List<ChatFolderRecord> {
|
fun getChatFolders(): List<ChatFolderRecord> {
|
||||||
val includedChats: Map<Long, List<Long>> = getIncludedChats()
|
val includedChats: Map<Long, List<Long>> = getIncludedChats()
|
||||||
val excludedChats: Map<Long, List<Long>> = getExcludedChats()
|
val excludedChats: Map<Long, List<Long>> = getExcludedChats()
|
||||||
|
|
||||||
@@ -172,23 +171,26 @@ class ChatFolderTables(context: Context?, databaseHelper: SignalDatabase?) : Dat
|
|||||||
showMutedChats = cursor.requireBoolean(ChatFolderTable.SHOW_MUTED),
|
showMutedChats = cursor.requireBoolean(ChatFolderTable.SHOW_MUTED),
|
||||||
showIndividualChats = cursor.requireBoolean(ChatFolderTable.SHOW_INDIVIDUAL),
|
showIndividualChats = cursor.requireBoolean(ChatFolderTable.SHOW_INDIVIDUAL),
|
||||||
showGroupChats = cursor.requireBoolean(ChatFolderTable.SHOW_GROUPS),
|
showGroupChats = cursor.requireBoolean(ChatFolderTable.SHOW_GROUPS),
|
||||||
isMuted = cursor.requireBoolean(ChatFolderTable.IS_MUTED),
|
|
||||||
folderType = ChatFolderRecord.FolderType.deserialize(cursor.requireInt(ChatFolderTable.FOLDER_TYPE)),
|
folderType = ChatFolderRecord.FolderType.deserialize(cursor.requireInt(ChatFolderTable.FOLDER_TYPE)),
|
||||||
includedChats = includedChats[id] ?: emptyList(),
|
includedChats = includedChats[id] ?: emptyList(),
|
||||||
excludedChats = excludedChats[id] ?: emptyList()
|
excludedChats = excludedChats[id] ?: emptyList()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeUnreadAndMutedCount) {
|
return folders
|
||||||
return folders.map { folder ->
|
|
||||||
folder.copy(
|
|
||||||
unreadCount = SignalDatabase.threads.getUnreadCountByChatFolder(folder),
|
|
||||||
isMuted = !SignalDatabase.threads.hasUnmutedChatsInFolder(folder)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return folders
|
/**
|
||||||
|
* Given a list of folders, maps a folder id to the folder's unread count and whether all the chats in the folder are muted
|
||||||
|
*/
|
||||||
|
fun getUnreadCountAndMutedStatusForFolders(folders: List<ChatFolderRecord>): HashMap<Long, Pair<Int, Boolean>> {
|
||||||
|
val map: HashMap<Long, Pair<Int, Boolean>> = hashMapOf()
|
||||||
|
folders.map { folder ->
|
||||||
|
val unreadCount = SignalDatabase.threads.getUnreadCountByChatFolder(folder)
|
||||||
|
val isMuted = !SignalDatabase.threads.hasUnmutedChatsInFolder(folder)
|
||||||
|
map[folder.id] = Pair(unreadCount, isMuted)
|
||||||
|
}
|
||||||
|
return map
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -263,7 +265,6 @@ class ChatFolderTables(context: Context?, databaseHelper: SignalDatabase?) : Dat
|
|||||||
ChatFolderTable.SHOW_MUTED to chatFolder.showMutedChats,
|
ChatFolderTable.SHOW_MUTED to chatFolder.showMutedChats,
|
||||||
ChatFolderTable.SHOW_INDIVIDUAL to chatFolder.showIndividualChats,
|
ChatFolderTable.SHOW_INDIVIDUAL to chatFolder.showIndividualChats,
|
||||||
ChatFolderTable.SHOW_GROUPS to chatFolder.showGroupChats,
|
ChatFolderTable.SHOW_GROUPS to chatFolder.showGroupChats,
|
||||||
ChatFolderTable.IS_MUTED to chatFolder.isMuted,
|
|
||||||
ChatFolderTable.POSITION to position
|
ChatFolderTable.POSITION to position
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -304,8 +305,7 @@ class ChatFolderTables(context: Context?, databaseHelper: SignalDatabase?) : Dat
|
|||||||
ChatFolderTable.SHOW_UNREAD to chatFolder.showUnread,
|
ChatFolderTable.SHOW_UNREAD to chatFolder.showUnread,
|
||||||
ChatFolderTable.SHOW_MUTED to chatFolder.showMutedChats,
|
ChatFolderTable.SHOW_MUTED to chatFolder.showMutedChats,
|
||||||
ChatFolderTable.SHOW_INDIVIDUAL to chatFolder.showIndividualChats,
|
ChatFolderTable.SHOW_INDIVIDUAL to chatFolder.showIndividualChats,
|
||||||
ChatFolderTable.SHOW_GROUPS to chatFolder.showGroupChats,
|
ChatFolderTable.SHOW_GROUPS to chatFolder.showGroupChats
|
||||||
ChatFolderTable.IS_MUTED to chatFolder.isMuted
|
|
||||||
)
|
)
|
||||||
.where("${ChatFolderTable.ID} = ?", chatFolder.id)
|
.where("${ChatFolderTable.ID} = ?", chatFolder.id)
|
||||||
.run(SQLiteDatabase.CONFLICT_IGNORE)
|
.run(SQLiteDatabase.CONFLICT_IGNORE)
|
||||||
|
|||||||
@@ -291,15 +291,11 @@ class UnarchivedConversationListDataSourceTest {
|
|||||||
position = -1,
|
position = -1,
|
||||||
includedChats = emptyList(),
|
includedChats = emptyList(),
|
||||||
excludedChats = emptyList(),
|
excludedChats = emptyList(),
|
||||||
includedRecipients = emptySet(),
|
|
||||||
excludedRecipients = emptySet(),
|
|
||||||
showUnread = false,
|
showUnread = false,
|
||||||
showMutedChats = false,
|
showMutedChats = false,
|
||||||
showIndividualChats = false,
|
showIndividualChats = false,
|
||||||
showGroupChats = false,
|
showGroupChats = false,
|
||||||
isMuted = false,
|
folderType = ChatFolderRecord.FolderType.ALL
|
||||||
folderType = ChatFolderRecord.FolderType.ALL,
|
|
||||||
unreadCount = 0
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user