From 6707a16cdad0ad4b28b191432c4248436cad4e61 Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Tue, 20 May 2025 18:10:17 +0200 Subject: [PATCH] mark conversation as important / unimportant Signed-off-by: sowjanyakch --- .../14.json | 12 ++- .../ConversationInfoActivity.kt | 84 ++++++++++++++++--- .../viewmodel/ConversationInfoViewModel.kt | 51 +++++++++++ .../DatabaseStorageModule.kt | 28 +++---- .../res/layout/item_notification_settings.xml | 3 +- app/src/main/res/values/strings.xml | 3 +- 6 files changed, 150 insertions(+), 31 deletions(-) diff --git a/app/schemas/com.nextcloud.talk.data.source.local.TalkDatabase/14.json b/app/schemas/com.nextcloud.talk.data.source.local.TalkDatabase/14.json index cc73f1e94..dfabb1af3 100644 --- a/app/schemas/com.nextcloud.talk.data.source.local.TalkDatabase/14.json +++ b/app/schemas/com.nextcloud.talk.data.source.local.TalkDatabase/14.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 14, - "identityHash": "506abc931eb3b657cafe6ad1b25f635d", + "identityHash": "d977dea7f7b5cc6d466a4aeb68c538fb", "entities": [ { "tableName": "User", @@ -122,7 +122,7 @@ }, { "tableName": "Conversations", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`internalId` TEXT NOT NULL, `accountId` INTEGER NOT NULL, `token` TEXT NOT NULL, `displayName` TEXT NOT NULL, `actorId` TEXT NOT NULL, `actorType` TEXT NOT NULL, `avatarVersion` TEXT NOT NULL, `callFlag` INTEGER NOT NULL, `callRecording` INTEGER NOT NULL, `callStartTime` INTEGER NOT NULL, `canDeleteConversation` INTEGER NOT NULL, `canLeaveConversation` INTEGER NOT NULL, `canStartCall` INTEGER NOT NULL, `description` TEXT NOT NULL, `hasCall` INTEGER NOT NULL, `hasPassword` INTEGER NOT NULL, `isCustomAvatar` INTEGER NOT NULL, `isFavorite` INTEGER NOT NULL, `lastActivity` INTEGER NOT NULL, `lastCommonReadMessage` INTEGER NOT NULL, `lastMessage` TEXT, `lastPing` INTEGER NOT NULL, `lastReadMessage` INTEGER NOT NULL, `lobbyState` TEXT NOT NULL, `lobbyTimer` INTEGER NOT NULL, `messageExpiration` INTEGER NOT NULL, `name` TEXT NOT NULL, `notificationCalls` INTEGER NOT NULL, `notificationLevel` TEXT NOT NULL, `objectType` TEXT NOT NULL, `objectId` TEXT NOT NULL, `participantType` TEXT NOT NULL, `permissions` INTEGER NOT NULL, `readOnly` TEXT NOT NULL, `recordingConsent` INTEGER NOT NULL, `remoteServer` TEXT, `remoteToken` TEXT, `sessionId` TEXT NOT NULL, `status` TEXT, `statusClearAt` INTEGER, `statusIcon` TEXT, `statusMessage` TEXT, `type` TEXT NOT NULL, `unreadMention` INTEGER NOT NULL, `unreadMentionDirect` INTEGER NOT NULL, `unreadMessages` INTEGER NOT NULL, `hasArchived` INTEGER NOT NULL, PRIMARY KEY(`internalId`), FOREIGN KEY(`accountId`) REFERENCES `User`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`internalId` TEXT NOT NULL, `accountId` INTEGER NOT NULL, `token` TEXT NOT NULL, `displayName` TEXT NOT NULL, `actorId` TEXT NOT NULL, `actorType` TEXT NOT NULL, `avatarVersion` TEXT NOT NULL, `callFlag` INTEGER NOT NULL, `callRecording` INTEGER NOT NULL, `callStartTime` INTEGER NOT NULL, `canDeleteConversation` INTEGER NOT NULL, `canLeaveConversation` INTEGER NOT NULL, `canStartCall` INTEGER NOT NULL, `description` TEXT NOT NULL, `hasCall` INTEGER NOT NULL, `hasPassword` INTEGER NOT NULL, `isCustomAvatar` INTEGER NOT NULL, `isFavorite` INTEGER NOT NULL, `lastActivity` INTEGER NOT NULL, `lastCommonReadMessage` INTEGER NOT NULL, `lastMessage` TEXT, `lastPing` INTEGER NOT NULL, `lastReadMessage` INTEGER NOT NULL, `lobbyState` TEXT NOT NULL, `lobbyTimer` INTEGER NOT NULL, `messageExpiration` INTEGER NOT NULL, `name` TEXT NOT NULL, `notificationCalls` INTEGER NOT NULL, `notificationLevel` TEXT NOT NULL, `objectType` TEXT NOT NULL, `objectId` TEXT NOT NULL, `participantType` TEXT NOT NULL, `permissions` INTEGER NOT NULL, `readOnly` TEXT NOT NULL, `recordingConsent` INTEGER NOT NULL, `remoteServer` TEXT, `remoteToken` TEXT, `sessionId` TEXT NOT NULL, `status` TEXT, `statusClearAt` INTEGER, `statusIcon` TEXT, `statusMessage` TEXT, `type` TEXT NOT NULL, `unreadMention` INTEGER NOT NULL, `unreadMentionDirect` INTEGER NOT NULL, `unreadMessages` INTEGER NOT NULL, `hasArchived` INTEGER NOT NULL, `hasImportant` INTEGER NOT NULL, PRIMARY KEY(`internalId`), FOREIGN KEY(`accountId`) REFERENCES `User`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )", "fields": [ { "fieldPath": "internalId", @@ -398,6 +398,12 @@ "columnName": "hasArchived", "affinity": "INTEGER", "notNull": true + }, + { + "fieldPath": "hasImportant", + "columnName": "hasImportant", + "affinity": "INTEGER", + "notNull": true } ], "primaryKey": { @@ -713,7 +719,7 @@ ], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '506abc931eb3b657cafe6ad1b25f635d')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd977dea7f7b5cc6d466a4aeb68c538fb')" ] } } \ No newline at end of file diff --git a/app/src/main/java/com/nextcloud/talk/conversationinfo/ConversationInfoActivity.kt b/app/src/main/java/com/nextcloud/talk/conversationinfo/ConversationInfoActivity.kt index ff5acdbe4..8db02892e 100644 --- a/app/src/main/java/com/nextcloud/talk/conversationinfo/ConversationInfoActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/conversationinfo/ConversationInfoActivity.kt @@ -252,6 +252,8 @@ class ConversationInfoActivity : initClearChatHistoryObserver() initMarkConversationAsSensitiveObserver() initMarkConversationAsInsensitiveObserver() + initMarkConversationAsImportantObserver() + initMarkConversationAsUnimportantObserver() } private fun initMarkConversationAsSensitiveObserver() { @@ -381,7 +383,46 @@ class ConversationInfoActivity : } } - @SuppressLint("SetTextI18n") + private fun initMarkConversationAsImportantObserver() { + viewModel.markAsImportantResult.observe(this) { uiState -> + when (uiState) { + is ConversationInfoViewModel.MarkConversationAsImportantViewState.Success -> { + binding.root, + context.getString(R.string.nc_mark_conversation_as_important), + Snackbar.LENGTH_LONG + ).show() + } + is ConversationInfoViewModel.MarkConversationAsImportantViewState.Error -> { + Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show() + Log.e(TAG, "failed to mark conversation as important", uiState.exception) + } + else -> { + } + } + } + } + + + private fun initMarkConversationAsUnimportantObserver() { + viewModel.markAsUnimportantResult.observe(this) { uiState -> + when (uiState) { + is ConversationInfoViewModel.MarkConversationAsUnimportantViewState.Success -> { + Snackbar.make( + binding.root, + context.getString(R.string.nc_mark_conversation_as_unimportant), + Snackbar.LENGTH_LONG + ).show() + } + is ConversationInfoViewModel.MarkConversationAsUnimportantViewState.Error -> { + Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show() + Log.e(TAG, "failed to mark conversation as unimportant", uiState.exception) + } + else -> { + } + } + } + } + private fun initViewStateObserver() { viewModel.viewState.observe(this) { state -> when (state) { @@ -1025,6 +1066,29 @@ class ConversationInfoActivity : } } + binding.notificationSettingsView.importantConversationSwitch.isChecked = conversation!!.hasImportant + + binding.notificationSettingsView.importantConversationSwitch.setOnCheckedChangeListener { _, isChecked -> + if (isChecked) { + viewModel.markConversationAsImportant( + credentials, + conversationUser.baseUrl!!, + conversation?.token!! + ) + } else { + viewModel.markConversationAsUnimportant( + credentials, + conversationUser.baseUrl!!, + conversation?.token!! + ) + } + } + if (hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.IMPORTANT_CONVERSATIONS)) { + binding.notificationSettingsView.notificationSettingsImportantConversation.visibility = VISIBLE + } else { + binding.notificationSettingsView.notificationSettingsImportantConversation.visibility = GONE + } + if (!hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.ARCHIVE_CONVERSATIONS)) { binding.archiveConversationBtn.visibility = GONE binding.archiveConversationTextHint.visibility = GONE @@ -1756,13 +1820,13 @@ class ConversationInfoActivity : } private fun setUpNotificationSettings(module: DatabaseStorageModule) { - binding.notificationSettingsView.notificationSettingsImportantConversation.setOnClickListener { - val isChecked = binding.notificationSettingsView.importantConversationSwitch.isChecked - binding.notificationSettingsView.importantConversationSwitch.isChecked = !isChecked - lifecycleScope.launch { - module.saveBoolean("important_conversation_switch", !isChecked) - } - } + // binding.notificationSettingsView.notificationSettingsImportantConversation.setOnClickListener { + // val isChecked = binding.notificationSettingsView.importantConversationSwitch.isChecked + // binding.notificationSettingsView.importantConversationSwitch.isChecked = !isChecked + // lifecycleScope.launch { + // module.saveBoolean("important_conversation_switch", !isChecked) + // } + // } binding.notificationSettingsView.notificationSettingsCallNotifications.setOnClickListener { val isChecked = binding.notificationSettingsView.callNotificationsSwitch.isChecked binding.notificationSettingsView.callNotificationsSwitch.isChecked = !isChecked @@ -1780,8 +1844,8 @@ class ConversationInfoActivity : } } - binding.notificationSettingsView.importantConversationSwitch.isChecked = module - .getBoolean("important_conversation_switch", false) + // binding.notificationSettingsView.importantConversationSwitch.isChecked = module + // .getBoolean("important_conversation_switch", false) if (conversation!!.remoteServer.isNullOrEmpty()) { binding.notificationSettingsView.notificationSettingsCallNotifications.visibility = VISIBLE diff --git a/app/src/main/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModel.kt b/app/src/main/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModel.kt index b9008c91a..ea67f57d4 100644 --- a/app/src/main/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModel.kt +++ b/app/src/main/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModel.kt @@ -124,6 +124,16 @@ class ConversationInfoViewModel @Inject constructor( val getConversationReadOnlyState: LiveData get() = _getConversationReadOnlyState + private val _markConversationAsImportantResult = + MutableLiveData(MarkConversationAsImportantViewState.None) + val markAsImportantResult: LiveData + get() = _markConversationAsImportantResult + + private val _markConversationAsUnimportantResult = + MutableLiveData(MarkConversationAsUnimportantViewState.None) + val markAsUnimportantResult: LiveData + get() = _markConversationAsUnimportantResult + private val _createRoomViewState = MutableLiveData(CreateRoomUIState.None) val createRoomViewState: LiveData get() = _createRoomViewState @@ -356,6 +366,35 @@ class ConversationInfoViewModel @Inject constructor( conversationsRepository.unarchiveConversation(user.getCredentials(), url) } + + @Suppress("Detekt.TooGenericExceptionCaught") + fun markConversationAsImportant(credentials: String, baseUrl: String, roomToken: String) { + viewModelScope.launch { + try { + val response = conversationsRepository.markConversationAsImportant(credentials, baseUrl, roomToken) + _markConversationAsImportantResult.value = + MarkConversationAsImportantViewState.Success(response.ocs?.meta?.statusCode!!) + } catch (exception: Exception) { + _markConversationAsImportantResult.value = + MarkConversationAsImportantViewState.Error(exception) + } + } + } + + @Suppress("Detekt.TooGenericExceptionCaught") + fun markConversationAsUnimportant(credentials: String, baseUrl: String, roomToken: String) { + viewModelScope.launch { + try { + val response = conversationsRepository.markConversationAsImportant(credentials, baseUrl, roomToken) + _markConversationAsUnimportantResult.value = + MarkConversationAsUnimportantViewState.Success(response.ocs?.meta?.statusCode!!) + } catch (exception: Exception) { + _markConversationAsUnimportantResult.value = + MarkConversationAsUnimportantViewState.Error(exception) + } + } + } + @Suppress("Detekt.TooGenericExceptionCaught") fun clearChatHistory(apiVersion: Int, roomToken: String) { viewModelScope.launch { @@ -480,4 +519,16 @@ class ConversationInfoViewModel @Inject constructor( data object Success : PasswordUiState() data class Error(val exception: Exception) : PasswordUiState() } + + sealed class MarkConversationAsImportantViewState { + data object None : MarkConversationAsImportantViewState() + data class Success(val statusCode: Int) : MarkConversationAsImportantViewState() + data class Error(val exception: Exception) : MarkConversationAsImportantViewState() + } + + sealed class MarkConversationAsUnimportantViewState { + data object None : MarkConversationAsUnimportantViewState() + data class Success(val statusCode: Int) : MarkConversationAsUnimportantViewState() + data class Error(val exception: Exception) : MarkConversationAsUnimportantViewState() + } } diff --git a/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageModule.kt b/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageModule.kt index 1bfe577f7..080c909b3 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageModule.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageModule.kt @@ -65,20 +65,20 @@ class DatabaseStorageModule(conversationUser: User, conversationToken: String) { @Suppress("Detekt.TooGenericExceptionCaught") suspend fun saveBoolean(key: String, value: Boolean) { - if ("call_notifications_switch" == key) { - val apiVersion = getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.API_V4)) - val url = getUrlForRoomNotificationCalls(apiVersion, conversationUser.baseUrl, conversationToken) - val credentials = getCredentials(conversationUser.username, conversationUser.token) - val notificationLevel = if (value) 1 else 0 - withContext(Dispatchers.IO) { - try { - ncApiCoroutines!!.notificationCalls(credentials!!, url, notificationLevel) - Log.d(TAG, "Toggled notification calls") - } catch (e: Exception) { - Log.e(TAG, "Error when trying to toggle notification calls", e) - } - } - } + // if ("call_notifications_switch" == key) { + // val apiVersion = getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.API_V4)) + // val url = getUrlForRoomNotificationCalls(apiVersion, conversationUser.baseUrl, conversationToken) + // val credentials = getCredentials(conversationUser.username, conversationUser.token) + // val notificationLevel = if (value) 1 else 0 + // withContext(Dispatchers.IO) { + // try { + // ncApiCoroutines!!.notificationCalls(credentials!!, url, notificationLevel) + // Log.d(TAG, "Toggled notification calls") + // } catch (e: Exception) { + // Log.e(TAG, "Error when trying to toggle notification calls", e) + // } + // } + // } if ("lobby_switch" != key) { arbitraryStorageManager!!.storeStorageSetting( accountIdentifier, diff --git a/app/src/main/res/layout/item_notification_settings.xml b/app/src/main/res/layout/item_notification_settings.xml index c5a958b7e..b22268a22 100644 --- a/app/src/main/res/layout/item_notification_settings.xml +++ b/app/src/main/res/layout/item_notification_settings.xml @@ -61,8 +61,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:layout_marginStart="@dimen/standard_margin" - android:clickable="false" /> + android:layout_marginStart="@dimen/standard_margin" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b292ac92f..230d168bd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -352,8 +352,7 @@ How to translate with transifex: Sensitive conversation Message preview will be disabled in conversation list and notifications Important conversation - Ignore Do not disturb - Notifications in this conversation will override Do Not Disturb settings + \"Do not disturb\" user status is ignored for important conversations OK, all done! OK