From 91a18e27f9e01a27ebe46b7da87d76793e9c249c Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Tue, 12 Nov 2024 13:36:34 +0100 Subject: [PATCH 1/6] implement API in NcApiCoroutines Signed-off-by: sowjanyakch --- .../com/nextcloud/talk/api/NcApiCoroutines.kt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt b/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt index 8d399f1ec1..41e957885f 100644 --- a/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt +++ b/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt @@ -11,7 +11,10 @@ import com.nextcloud.talk.models.json.autocomplete.AutocompleteOverall import com.nextcloud.talk.models.json.conversations.RoomOverall import com.nextcloud.talk.models.json.generic.GenericOverall import com.nextcloud.talk.models.json.participants.AddParticipantOverall +import io.reactivex.Observable import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.Body import retrofit2.http.DELETE import retrofit2.http.Field import retrofit2.http.FormUrlEncoded @@ -116,4 +119,18 @@ interface NcApiCoroutines { @DELETE suspend fun unarchiveConversation(@Header("Authorization") authorization: String, @Url url: String): GenericOverall + + @POST + fun setReadStatusPrivacy( + @Header("Authorization") authorization: String, + @Url url: String, + @Body body: RequestBody + ): GenericOverall + + @POST + fun setTypingStatusPrivacy( + @Header("Authorization") authorization: String?, + @Url url: String, + @Body body: RequestBody + ): GenericOverall } From 99d73e15e02de05cc735875f7af45d29ffe9d33e Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Tue, 12 Nov 2024 16:06:47 +0100 Subject: [PATCH 2/6] migration to coroutines Signed-off-by: sowjanyakch --- .../com/nextcloud/talk/api/NcApiCoroutines.kt | 7 +- .../talk/settings/SettingsActivity.kt | 81 +++++++------------ 2 files changed, 33 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt b/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt index 41e957885f..bb68691a09 100644 --- a/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt +++ b/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt @@ -11,7 +11,6 @@ import com.nextcloud.talk.models.json.autocomplete.AutocompleteOverall import com.nextcloud.talk.models.json.conversations.RoomOverall import com.nextcloud.talk.models.json.generic.GenericOverall import com.nextcloud.talk.models.json.participants.AddParticipantOverall -import io.reactivex.Observable import okhttp3.MultipartBody import okhttp3.RequestBody import retrofit2.http.Body @@ -121,14 +120,14 @@ interface NcApiCoroutines { suspend fun unarchiveConversation(@Header("Authorization") authorization: String, @Url url: String): GenericOverall @POST - fun setReadStatusPrivacy( - @Header("Authorization") authorization: String, + suspend fun setReadStatusPrivacy( + @Header("Authorization") authorization: String?, @Url url: String, @Body body: RequestBody ): GenericOverall @POST - fun setTypingStatusPrivacy( + suspend fun setTypingStatusPrivacy( @Header("Authorization") authorization: String?, @Url url: String, @Body body: RequestBody diff --git a/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt b/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt index e86439a59a..152f2106e3 100644 --- a/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt @@ -49,6 +49,7 @@ import com.nextcloud.talk.R import com.nextcloud.talk.activities.BaseActivity import com.nextcloud.talk.activities.MainActivity import com.nextcloud.talk.api.NcApi +import com.nextcloud.talk.api.NcApiCoroutines import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.setAppTheme import com.nextcloud.talk.conversationlist.ConversationsListActivity @@ -103,6 +104,9 @@ class SettingsActivity : BaseActivity(), SetPhoneNumberDialogFragment.SetPhoneNu @Inject lateinit var ncApi: NcApi + @Inject + lateinit var ncApiCoroutines: NcApiCoroutines + @Inject lateinit var userManager: UserManager @@ -123,6 +127,7 @@ class SettingsActivity : BaseActivity(), SetPhoneNumberDialogFragment.SetPhoneNu private var profileQueryDisposable: Disposable? = null private var dbQueryDisposable: Disposable? = null + @SuppressLint("StringFormatInvalid") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) @@ -260,6 +265,7 @@ class SettingsActivity : BaseActivity(), SetPhoneNumberDialogFragment.SetPhoneNu setupNotificationPermissionSettings() } + @SuppressLint("StringFormatInvalid") @Suppress("LongMethod") private fun setupNotificationPermissionSettings() { if (ClosedInterfaceImpl().isGooglePlayServicesAvailable) { @@ -603,7 +609,7 @@ class SettingsActivity : BaseActivity(), SetPhoneNumberDialogFragment.SetPhoneNu } } - @SuppressLint("CheckResult") + @SuppressLint("CheckResult", "StringFormatInvalid") private fun removeCurrentAccount() { userManager.scheduleUserForDeletionWithId(currentUser!!.id!!).blockingGet() val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build() @@ -1278,31 +1284,17 @@ class SettingsActivity : BaseActivity(), SetPhoneNumberDialogFragment.SetPhoneNu state = newBoolean val booleanValue = if (newBoolean) "0" else "1" val json = "{\"key\": \"read_status_privacy\", \"value\" : $booleanValue}" - ncApi.setReadStatusPrivacy( - ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token), - ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), - json.toRequestBody("application/json".toMediaTypeOrNull()) - ) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(object : Observer { - override fun onSubscribe(d: Disposable) { - // unused atm - } - - override fun onNext(genericOverall: GenericOverall) { - // unused atm - } - - override fun onError(e: Throwable) { - appPreferences.setReadPrivacy(!newBoolean) - binding.settingsReadPrivacySwitch.isChecked = !newBoolean - } - - override fun onComplete() { - // unused atm - } - }) + try { + ncApiCoroutines.setReadStatusPrivacy( + ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token), + ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), + json.toRequestBody("application/json".toMediaTypeOrNull()) + ) + Log.i(TAG, "reading status set") + } catch (e: Exception) { + appPreferences.setReadPrivacy(!newBoolean) + binding.settingsReadPrivacySwitch.isChecked = !newBoolean + } } } } @@ -1316,32 +1308,19 @@ class SettingsActivity : BaseActivity(), SetPhoneNumberDialogFragment.SetPhoneNu state = newBoolean val booleanValue = if (newBoolean) "0" else "1" val json = "{\"key\": \"typing_privacy\", \"value\" : $booleanValue}" - ncApi.setTypingStatusPrivacy( - ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token), - ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), - json.toRequestBody("application/json".toMediaTypeOrNull()) - ) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(object : Observer { - override fun onSubscribe(d: Disposable) { - // unused atm - } - - override fun onNext(genericOverall: GenericOverall) { - loadCapabilitiesAndUpdateSettings() - Log.i(TAG, "onNext called typing status set") - } - override fun onError(e: Throwable) { - appPreferences.typingStatus = !newBoolean - binding.settingsTypingStatusSwitch.isChecked = !newBoolean - } - - override fun onComplete() { - // unused atm - } - }) + try { + ncApiCoroutines.setTypingStatusPrivacy( + ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token), + ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), + json.toRequestBody("application/json".toMediaTypeOrNull()) + ) + loadCapabilitiesAndUpdateSettings() + Log.i(TAG, "typing status set") + } catch (e: Exception) { + appPreferences.typingStatus = !newBoolean + binding.settingsTypingStatusSwitch.isChecked = !newBoolean + } } } } From 9f3bbf6ebfaf77115ce7a2f491e203d586c3c106 Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Tue, 12 Nov 2024 16:53:29 +0100 Subject: [PATCH 3/6] refactor code Signed-off-by: sowjanyakch --- .../com/nextcloud/talk/api/NcApiCoroutines.kt | 4 +-- .../talk/settings/SettingsActivity.kt | 25 +++++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt b/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt index bb68691a09..5707ae3972 100644 --- a/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt +++ b/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt @@ -121,14 +121,14 @@ interface NcApiCoroutines { @POST suspend fun setReadStatusPrivacy( - @Header("Authorization") authorization: String?, + @Header("Authorization") authorization: String, @Url url: String, @Body body: RequestBody ): GenericOverall @POST suspend fun setTypingStatusPrivacy( - @Header("Authorization") authorization: String?, + @Header("Authorization") authorization: String, @Url url: String, @Body body: RequestBody ): GenericOverall diff --git a/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt b/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt index 152f2106e3..adb4183bd4 100644 --- a/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt @@ -1285,11 +1285,13 @@ class SettingsActivity : BaseActivity(), SetPhoneNumberDialogFragment.SetPhoneNu val booleanValue = if (newBoolean) "0" else "1" val json = "{\"key\": \"read_status_privacy\", \"value\" : $booleanValue}" try { - ncApiCoroutines.setReadStatusPrivacy( - ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token), - ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), - json.toRequestBody("application/json".toMediaTypeOrNull()) - ) + credentials?.let { credentials -> + ncApiCoroutines.setReadStatusPrivacy( + credentials, + ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), + json.toRequestBody("application/json".toMediaTypeOrNull()) + ) + } Log.i(TAG, "reading status set") } catch (e: Exception) { appPreferences.setReadPrivacy(!newBoolean) @@ -1310,11 +1312,14 @@ class SettingsActivity : BaseActivity(), SetPhoneNumberDialogFragment.SetPhoneNu val json = "{\"key\": \"typing_privacy\", \"value\" : $booleanValue}" try { - ncApiCoroutines.setTypingStatusPrivacy( - ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token), - ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), - json.toRequestBody("application/json".toMediaTypeOrNull()) - ) + credentials?.let { credentials -> + ncApiCoroutines.setTypingStatusPrivacy( + credentials, + ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), + json.toRequestBody("application/json".toMediaTypeOrNull()) + ) + } + loadCapabilitiesAndUpdateSettings() Log.i(TAG, "typing status set") } catch (e: Exception) { From dce609b8312a6c7f83b517c5fc71a4b4c1d834b4 Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Tue, 12 Nov 2024 16:58:52 +0100 Subject: [PATCH 4/6] remove unused used from NcApi Signed-off-by: sowjanyakch --- app/src/main/java/com/nextcloud/talk/api/NcApi.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/api/NcApi.java b/app/src/main/java/com/nextcloud/talk/api/NcApi.java index e4811c780f..297bba392e 100644 --- a/app/src/main/java/com/nextcloud/talk/api/NcApi.java +++ b/app/src/main/java/com/nextcloud/talk/api/NcApi.java @@ -459,16 +459,6 @@ Observable setLobbyForConversation(@Header("Authorization") Stri @Field("state") Integer state, @Field("timer") Long timer); - @POST - Observable setReadStatusPrivacy(@Header("Authorization") String authorization, - @Url String url, - @Body RequestBody body); - - @POST - Observable setTypingStatusPrivacy(@Header("Authorization") String authorization, - @Url String url, - @Body RequestBody body); - @POST Observable searchContactsByPhoneNumber(@Header("Authorization") String authorization, @Url String url, From 240bdd67715a8a0f3c16e0432708cdcf02209550 Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Tue, 12 Nov 2024 17:37:40 +0100 Subject: [PATCH 5/6] handle errors Signed-off-by: sowjanyakch --- .../talk/settings/SettingsActivity.kt | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt b/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt index adb4183bd4..99bac3ba3f 100644 --- a/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt @@ -91,6 +91,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody.Companion.toRequestBody +import retrofit2.HttpException import java.net.URI import java.net.URISyntaxException import java.util.Locale @@ -1291,11 +1292,16 @@ class SettingsActivity : BaseActivity(), SetPhoneNumberDialogFragment.SetPhoneNu ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), json.toRequestBody("application/json".toMediaTypeOrNull()) ) + Log.i(TAG, "reading status set") } - Log.i(TAG, "reading status set") } catch (e: Exception) { appPreferences.setReadPrivacy(!newBoolean) binding.settingsReadPrivacySwitch.isChecked = !newBoolean + if (e is HttpException && e.code() == HTTP_ERROR_CODE_BAD_REQUEST) { + Log.e(TAG, "read_status_privacy : Key or value is invalid") + } else { + Log.e(TAG, "Error updating read status", e) + } } } } @@ -1318,13 +1324,17 @@ class SettingsActivity : BaseActivity(), SetPhoneNumberDialogFragment.SetPhoneNu ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), json.toRequestBody("application/json".toMediaTypeOrNull()) ) + loadCapabilitiesAndUpdateSettings() + Log.i(TAG, "typing status set") } - - loadCapabilitiesAndUpdateSettings() - Log.i(TAG, "typing status set") } catch (e: Exception) { appPreferences.typingStatus = !newBoolean binding.settingsTypingStatusSwitch.isChecked = !newBoolean + if (e is HttpException && e.code() == HTTP_ERROR_CODE_BAD_REQUEST) { + Log.e(TAG, "typing_privacy : Key or value is invalid") + } else { + Log.e(TAG, "Error updating typing status", e) + } } } } @@ -1338,5 +1348,6 @@ class SettingsActivity : BaseActivity(), SetPhoneNumberDialogFragment.SetPhoneNu private const val DISABLED_ALPHA: Float = 0.38f private const val ENABLED_ALPHA: Float = 1.0f const val HTTP_CODE_OK: Int = 200 + const val HTTP_ERROR_CODE_BAD_REQUEST: Int = 400 } } From 4439da9bd1c1bc2dbd1f7bc2c191ac406cd451c3 Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Tue, 12 Nov 2024 21:56:00 +0100 Subject: [PATCH 6/6] use lifecycleScope Signed-off-by: sowjanyakch --- .../talk/settings/SettingsActivity.kt | 83 +++++++++++-------- 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt b/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt index 99bac3ba3f..c7ea56607f 100644 --- a/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt @@ -36,6 +36,7 @@ import androidx.appcompat.app.AlertDialog import androidx.core.content.ContextCompat import androidx.core.content.res.ResourcesCompat import androidx.core.view.ViewCompat +import androidx.lifecycle.lifecycleScope import androidx.work.OneTimeWorkRequest import androidx.work.WorkInfo import androidx.work.WorkManager @@ -89,6 +90,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody.Companion.toRequestBody import retrofit2.HttpException @@ -1278,29 +1280,33 @@ class SettingsActivity : BaseActivity(), SetPhoneNumberDialogFragment.SetPhoneNu } private fun observeReadPrivacy() { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch { var state = appPreferences.readPrivacy readPrivacyFlow.collect { newBoolean -> if (state != newBoolean) { state = newBoolean val booleanValue = if (newBoolean) "0" else "1" val json = "{\"key\": \"read_status_privacy\", \"value\" : $booleanValue}" - try { - credentials?.let { credentials -> - ncApiCoroutines.setReadStatusPrivacy( - credentials, - ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), - json.toRequestBody("application/json".toMediaTypeOrNull()) - ) - Log.i(TAG, "reading status set") - } - } catch (e: Exception) { - appPreferences.setReadPrivacy(!newBoolean) - binding.settingsReadPrivacySwitch.isChecked = !newBoolean - if (e is HttpException && e.code() == HTTP_ERROR_CODE_BAD_REQUEST) { - Log.e(TAG, "read_status_privacy : Key or value is invalid") - } else { - Log.e(TAG, "Error updating read status", e) + withContext(Dispatchers.IO) { + try { + credentials?.let { credentials -> + ncApiCoroutines.setReadStatusPrivacy( + credentials, + ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), + json.toRequestBody("application/json".toMediaTypeOrNull()) + ) + Log.i(TAG, "reading status set") + } + } catch (e: Exception) { + withContext(Dispatchers.Main) { + appPreferences.setReadPrivacy(!newBoolean) + binding.settingsReadPrivacySwitch.isChecked = !newBoolean + } + if (e is HttpException && e.code() == HTTP_ERROR_CODE_BAD_REQUEST) { + Log.e(TAG, "read_status_privacy : Key or value is invalid") + } else { + Log.e(TAG, "Error setting read status", e) + } } } } @@ -1309,31 +1315,36 @@ class SettingsActivity : BaseActivity(), SetPhoneNumberDialogFragment.SetPhoneNu } private fun observeTypingStatus() { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch { var state = appPreferences.typingStatus typingStatusFlow.collect { newBoolean -> if (state != newBoolean) { state = newBoolean val booleanValue = if (newBoolean) "0" else "1" val json = "{\"key\": \"typing_privacy\", \"value\" : $booleanValue}" - - try { - credentials?.let { credentials -> - ncApiCoroutines.setTypingStatusPrivacy( - credentials, - ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), - json.toRequestBody("application/json".toMediaTypeOrNull()) - ) - loadCapabilitiesAndUpdateSettings() - Log.i(TAG, "typing status set") - } - } catch (e: Exception) { - appPreferences.typingStatus = !newBoolean - binding.settingsTypingStatusSwitch.isChecked = !newBoolean - if (e is HttpException && e.code() == HTTP_ERROR_CODE_BAD_REQUEST) { - Log.e(TAG, "typing_privacy : Key or value is invalid") - } else { - Log.e(TAG, "Error updating typing status", e) + withContext(Dispatchers.IO) { + try { + credentials?.let { credentials -> + ncApiCoroutines.setTypingStatusPrivacy( + credentials, + ApiUtils.getUrlForUserSettings(currentUser!!.baseUrl!!), + json.toRequestBody("application/json".toMediaTypeOrNull()) + ) + } + withContext(Dispatchers.Main) { + loadCapabilitiesAndUpdateSettings() + Log.i(TAG, "typing status set") + } + } catch (e: Exception) { + withContext(Dispatchers.Main) { + appPreferences.typingStatus = !newBoolean + binding.settingsTypingStatusSwitch.isChecked = !newBoolean + } + if (e is HttpException && e.code() == HTTP_ERROR_CODE_BAD_REQUEST) { + Log.e(TAG, "typing_privacy : Key or value is invalid") + } else { + Log.e(TAG, "Error setting typing status", e) + } } } }