From 2bdaf31198b7b90053188946f88fd4aebf7da5f5 Mon Sep 17 00:00:00 2001 From: Daniel Petrov Date: Thu, 12 Sep 2024 14:34:11 +0300 Subject: [PATCH] Add "delete account" button in settings --- .../smartbirds/pro/backend/SmartBirdsApi.java | 6 ++ .../pro/backend/dto/BaseResponse.java | 24 +++++++ .../pro/ui/fragment/SettingsFragment.kt | 72 +++++++++++++++++++ .../main/res/layout/dialog_delete_account.xml | 37 ++++++++++ app/src/main/res/values-bg/strings.xml | 2 + app/src/main/res/values/strings.xml | 8 +++ app/src/main/res/xml/settings.xml | 6 ++ 7 files changed, 155 insertions(+) create mode 100644 app/src/main/java/org/bspb/smartbirds/pro/backend/dto/BaseResponse.java create mode 100644 app/src/main/res/layout/dialog_delete_account.xml diff --git a/app/src/main/java/org/bspb/smartbirds/pro/backend/SmartBirdsApi.java b/app/src/main/java/org/bspb/smartbirds/pro/backend/SmartBirdsApi.java index 1bceb85f..a9d09475 100644 --- a/app/src/main/java/org/bspb/smartbirds/pro/backend/SmartBirdsApi.java +++ b/app/src/main/java/org/bspb/smartbirds/pro/backend/SmartBirdsApi.java @@ -2,6 +2,7 @@ import com.google.gson.JsonObject; +import org.bspb.smartbirds.pro.backend.dto.BaseResponse; import org.bspb.smartbirds.pro.backend.dto.CheckSessionRequest; import org.bspb.smartbirds.pro.backend.dto.DownloadsResponse; import org.bspb.smartbirds.pro.backend.dto.FileId; @@ -17,11 +18,13 @@ import okhttp3.MultipartBody; import retrofit2.Call; import retrofit2.http.Body; +import retrofit2.http.DELETE; import retrofit2.http.GET; import retrofit2.http.Multipart; import retrofit2.http.POST; import retrofit2.http.PUT; import retrofit2.http.Part; +import retrofit2.http.Path; import retrofit2.http.Query; import retrofit2.http.Url; @@ -96,4 +99,7 @@ public interface SmartBirdsApi { @POST("bats") Call createBat(@Body JsonObject request); + + @DELETE("user/{id}") + Call deleteUser(@Path("id") long id); } diff --git a/app/src/main/java/org/bspb/smartbirds/pro/backend/dto/BaseResponse.java b/app/src/main/java/org/bspb/smartbirds/pro/backend/dto/BaseResponse.java new file mode 100644 index 00000000..2bb541e7 --- /dev/null +++ b/app/src/main/java/org/bspb/smartbirds/pro/backend/dto/BaseResponse.java @@ -0,0 +1,24 @@ +package org.bspb.smartbirds.pro.backend.dto; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class BaseResponse { + + @Expose + @SerializedName("error") + public String error; + + @Expose + @SerializedName("success") + public boolean success; + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("BaseResponse{"); + sb.append("error='").append(error).append('\''); + sb.append(", success=").append(success); + sb.append('}'); + return sb.toString(); + } +} diff --git a/app/src/main/kotlin/org/bspb/smartbirds/pro/ui/fragment/SettingsFragment.kt b/app/src/main/kotlin/org/bspb/smartbirds/pro/ui/fragment/SettingsFragment.kt index 74925397..d9c858d5 100644 --- a/app/src/main/kotlin/org/bspb/smartbirds/pro/ui/fragment/SettingsFragment.kt +++ b/app/src/main/kotlin/org/bspb/smartbirds/pro/ui/fragment/SettingsFragment.kt @@ -1,7 +1,9 @@ package org.bspb.smartbirds.pro.ui.fragment +import android.content.Intent import android.os.Bundle import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AlertDialog import androidx.preference.ListPreference import androidx.preference.MultiSelectListPreference import androidx.preference.Preference @@ -10,13 +12,21 @@ import androidx.preference.PreferenceFragmentCompat import androidx.preference.SwitchPreferenceCompat import com.google.gson.reflect.TypeToken import org.bspb.smartbirds.pro.R +import org.bspb.smartbirds.pro.backend.Backend +import org.bspb.smartbirds.pro.backend.dto.BaseResponse import org.bspb.smartbirds.pro.backend.dto.MapLayerItem import org.bspb.smartbirds.pro.prefs.SmartBirdsPrefs +import org.bspb.smartbirds.pro.prefs.UserPrefs import org.bspb.smartbirds.pro.tools.DBExporter import org.bspb.smartbirds.pro.tools.SBGsonParser +import org.bspb.smartbirds.pro.ui.MainActivity import org.bspb.smartbirds.pro.ui.map.MapProvider import org.bspb.smartbirds.pro.utils.KmlUtils +import org.bspb.smartbirds.pro.utils.debugLog import org.bspb.smartbirds.pro.utils.showAlert +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response class SettingsFragment : PreferenceFragmentCompat() { @@ -26,7 +36,12 @@ class SettingsFragment : PreferenceFragmentCompat() { private var exportPreference: Preference? = null private var showKmlPreference: SwitchPreferenceCompat? = null private var importedKmlPreference: Preference? = null + private var deleteAccountPreference: Preference? = null + private var prefs: SmartBirdsPrefs? = null + private var userPrefs: UserPrefs? = null + + private val backend: Backend by lazy { Backend.getInstance() } private val pickKml = registerForActivityResult(ActivityResultContracts.GetContent()) { it ?: return@registerForActivityResult @@ -41,6 +56,7 @@ class SettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.settings, rootKey) prefs = SmartBirdsPrefs(requireContext()) + userPrefs = UserPrefs(requireContext()) initPreferences() updateMapType(MapProvider.ProviderType.valueOf(providerPreference?.value as String)) } @@ -50,6 +66,7 @@ class SettingsFragment : PreferenceFragmentCompat() { mapTypePreference = findPreference("mapType") enabledFormsPreference = findPreference("formsEnabled") exportPreference = findPreference("exportDB") + deleteAccountPreference = findPreference("deleteAccount") providerPreference?.onPreferenceChangeListener = Preference.OnPreferenceChangeListener() { _: Preference, newValue: Any -> @@ -93,6 +110,12 @@ class SettingsFragment : PreferenceFragmentCompat() { return@setOnPreferenceClickListener true } + deleteAccountPreference?.onPreferenceClickListener = + Preference.OnPreferenceClickListener { _: Preference -> + showDeleteAccountConfirmation() + return@OnPreferenceClickListener true + } + updateImportedKmlPreference() initMapLayersSettings() } @@ -152,4 +175,53 @@ class SettingsFragment : PreferenceFragmentCompat() { mapTypePreference?.isEnabled = true } } + + private fun showDeleteAccountConfirmation() { + debugLog("Show delete account confirmation") + AlertDialog.Builder(requireContext()) + .setView(R.layout.dialog_delete_account) + .setPositiveButton(R.string.dialog_delete_account_btn_yes) { _, _ -> + deleteAccount() + } + .setNegativeButton(android.R.string.cancel) { _, _ -> } + .show() + } + + private fun deleteAccount() { + userPrefs?.getUserId() ?: return + + val loadingDialog = LoadingDialog.newInstance(getString(R.string.deleting_account_progress)) + loadingDialog.show(parentFragmentManager, "deleting") + + backend.api().deleteUser(userPrefs!!.getUserId().toLong()) + .enqueue(object : Callback { + override fun onResponse( + call: Call, + response: Response, + ) { + loadingDialog.dismiss() + if (response.isSuccessful && response.body()?.success == true) { + userPrefs?.clear() + startActivity(Intent(context, MainActivity::class.java)) + } else { + showDeleteAccountError() + } + + } + + override fun onFailure(call: Call, error: Throwable) { + loadingDialog.dismiss() + debugLog("Delete account failed ${error.message}") + } + }) + } + + private fun showDeleteAccountError() { + context?.showAlert( + R.string.delete_account_dialog_title, + R.string.delete_account_dialog_error_message, + null, + null + ) + } } \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_delete_account.xml b/app/src/main/res/layout/dialog_delete_account.xml new file mode 100644 index 00000000..7a50d274 --- /dev/null +++ b/app/src/main/res/layout/dialog_delete_account.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index a1d577a1..daf41bb0 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -343,6 +343,8 @@ "Допълнителни" "Експорт на Базата данни" "Експортиране на Базата данни в Downloads." + "Изтриване на профил" + "Тази операция ще изтрие потребителският ви профил и всички данни свързани с него. Операцията е необратима!" "Внимание" "Трябва да изберете поне една активна форма за наблюдение." "Успех" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d98bd2ae..17478b72 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -344,6 +344,8 @@ Do you really want to cancel the monitoring?" "Advanced" "Export DB" "Export the DB in Downloads." + "Delete account" + "This operation will delete your account and all related data. It cannot be undone! " "Warning" "You have to select at least one active monitoring form." "Success" @@ -503,4 +505,10 @@ Do you really want to cancel the monitoring?" "Current location zone" "Notification permission is required for starting a monitoring" "Total length (TL) class, cm" + Delete account + Are you sure you want to delete your account? + Warning: This action cannot be undone. + Failed to delete account + Deleting account... + Yes, delete account. \ No newline at end of file diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index f8a54bf1..70533af4 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -148,6 +148,12 @@ app:key="exportDB" app:summary="@string/settings_export_db_summary" app:title="@string/settings_export_db" /> + + \ No newline at end of file