mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-25 14:35:40 +03:00
Migrating away from StoreBox to DataStore
- Added DataStore dependencies - Created AppPreferencesImpl Signed-off-by: Julius Linus <julius.linus@nextcloud.com>
This commit is contained in:
parent
128e57dbf7
commit
11f1d5fc7e
7 changed files with 742 additions and 394 deletions
|
@ -164,6 +164,8 @@ configurations.all {
|
|||
|
||||
dependencies {
|
||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||
implementation 'androidx.datastore:datastore-core:1.0.0'
|
||||
implementation 'androidx.datastore:datastore-preferences:1.0.0'
|
||||
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.1")
|
||||
|
||||
implementation fileTree(include: ['*'], dir: 'libs')
|
||||
|
@ -237,7 +239,6 @@ dependencies {
|
|||
implementation "androidx.room:room-ktx:${roomVersion}"
|
||||
|
||||
implementation "org.parceler:parceler-api:$parcelerVersion"
|
||||
implementation 'net.orange-box.storebox:storebox-lib:1.4.0'
|
||||
implementation 'eu.davidea:flexible-adapter:5.1.0'
|
||||
implementation 'eu.davidea:flexible-adapter-ui:1.0.0'
|
||||
implementation 'org.apache.commons:commons-lang3:3.13.0'
|
||||
|
|
|
@ -25,25 +25,33 @@ import android.content.Context;
|
|||
|
||||
import com.nextcloud.talk.data.source.local.TalkDatabase;
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferences;
|
||||
|
||||
import net.orange_box.storebox.StoreBox;
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferencesImpl;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.OptIn;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi;
|
||||
|
||||
@Module
|
||||
@OptIn(markerClass = ExperimentalCoroutinesApi.class)
|
||||
public class DatabaseModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
public AppPreferences providePreferences(@NonNull final Context poContext) {
|
||||
AppPreferences preferences = StoreBox.create(poContext, AppPreferences.class);
|
||||
AppPreferences preferences = new AppPreferencesImpl(poContext);
|
||||
preferences.removeLinkPreviews();
|
||||
return preferences;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public AppPreferencesImpl providePreferencesImpl(@NonNull final Context poContext) {
|
||||
return new AppPreferencesImpl(poContext);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public TalkDatabase provideTalkDatabase(@NonNull final Context context,
|
||||
|
|
|
@ -22,20 +22,26 @@
|
|||
|
||||
package com.nextcloud.talk.remotefilebrowser.viewmodels
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
|
||||
import com.nextcloud.talk.remotefilebrowser.repositories.RemoteFileBrowserItemsRepository
|
||||
import com.nextcloud.talk.utils.FileSortOrder
|
||||
import com.nextcloud.talk.utils.Mimetype.FOLDER
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferencesImpl
|
||||
import io.reactivex.Observer
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import net.orange_box.storebox.listeners.OnPreferenceValueChangedListener
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -52,9 +58,12 @@ import javax.inject.Inject
|
|||
* FinishState --> [*]
|
||||
* @enduml
|
||||
*/
|
||||
class RemoteFileBrowserItemsViewModel @Inject constructor(
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class RemoteFileBrowserItemsViewModel
|
||||
@Inject
|
||||
constructor(
|
||||
private val repository: RemoteFileBrowserItemsRepository,
|
||||
private val appPreferences: AppPreferences
|
||||
private val appPreferences: AppPreferencesImpl
|
||||
) :
|
||||
ViewModel() {
|
||||
|
||||
|
@ -66,7 +75,8 @@ class RemoteFileBrowserItemsViewModel @Inject constructor(
|
|||
class FinishState(val selectedPaths: Set<String>) : ViewState
|
||||
|
||||
private val initialSortOrder = FileSortOrder.getFileSortOrder(appPreferences.sorting)
|
||||
private val sortingPrefListener: SortChangeListener = SortChangeListener()
|
||||
|
||||
private var sortingFlow: Flow<String>
|
||||
|
||||
private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState)
|
||||
val viewState: LiveData<ViewState>
|
||||
|
@ -86,20 +96,19 @@ class RemoteFileBrowserItemsViewModel @Inject constructor(
|
|||
get() = _selectedPaths
|
||||
|
||||
init {
|
||||
appPreferences.registerSortingChangeListener(sortingPrefListener)
|
||||
}
|
||||
|
||||
inner class SortChangeListener : OnPreferenceValueChangedListener<String> {
|
||||
override fun onChanged(newValue: String) {
|
||||
onSelectSortOrder(newValue)
|
||||
val key = Resources.getSystem().getString(R.string.nc_file_browser_sort_by_key)
|
||||
sortingFlow = appPreferences.readString(key)
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
var state = appPreferences.sorting
|
||||
sortingFlow.collect { newString ->
|
||||
if (newString != state) {
|
||||
state = newString
|
||||
onSelectSortOrder(newString)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
appPreferences.unregisterSortingChangeListener(sortingPrefListener)
|
||||
}
|
||||
|
||||
fun loadItems() {
|
||||
_viewState.value = LoadingItemsState
|
||||
repository.listFolder(currentPath.value!!).subscribeOn(Schedulers.io())
|
||||
|
|
|
@ -27,7 +27,6 @@ package com.nextcloud.talk.settings
|
|||
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.app.Activity
|
||||
import android.app.KeyguardManager
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
|
@ -90,12 +89,17 @@ import com.nextcloud.talk.utils.NotificationUtils.getMessageRingtoneUri
|
|||
import com.nextcloud.talk.utils.SecurityUtils
|
||||
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
|
||||
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferencesImpl
|
||||
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
|
||||
import io.reactivex.Observer
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import net.orange_box.storebox.listeners.OnPreferenceValueChangedListener
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import java.net.URI
|
||||
|
@ -119,15 +123,15 @@ class SettingsActivity : BaseActivity() {
|
|||
|
||||
private var currentUser: User? = null
|
||||
private var credentials: String? = null
|
||||
private var proxyTypeChangeListener: OnPreferenceValueChangedListener<String>? = null
|
||||
private var proxyCredentialsChangeListener: OnPreferenceValueChangedListener<Boolean>? = null
|
||||
private var screenSecurityChangeListener: OnPreferenceValueChangedListener<Boolean>? = null
|
||||
private var screenLockChangeListener: OnPreferenceValueChangedListener<Boolean>? = null
|
||||
private var screenLockTimeoutChangeListener: OnPreferenceValueChangedListener<String?>? = null
|
||||
private var themeChangeListener: OnPreferenceValueChangedListener<String?>? = null
|
||||
private var readPrivacyChangeListener: OnPreferenceValueChangedListener<Boolean>? = null
|
||||
private var typingStatusChangeListener: OnPreferenceValueChangedListener<Boolean>? = null
|
||||
private var phoneBookIntegrationChangeListener: OnPreferenceValueChangedListener<Boolean>? = null
|
||||
private lateinit var proxyTypeFlow: Flow<String>
|
||||
private lateinit var proxyCredentialFlow: Flow<Boolean>
|
||||
private lateinit var screenSecurityFlow: Flow<Boolean>
|
||||
private lateinit var screenLockFlow: Flow<Boolean>
|
||||
private lateinit var screenLockTimeoutFlow: Flow<String>
|
||||
private lateinit var themeFlow: Flow<String>
|
||||
private lateinit var readPrivacyFlow: Flow<Boolean>
|
||||
private lateinit var typingStatusFlow: Flow<Boolean>
|
||||
private lateinit var phoneBookIntegrationFlow: Flow<Boolean>
|
||||
private var profileQueryDisposable: Disposable? = null
|
||||
private var dbQueryDisposable: Disposable? = null
|
||||
|
||||
|
@ -144,7 +148,6 @@ class SettingsActivity : BaseActivity() {
|
|||
|
||||
getCurrentUser()
|
||||
|
||||
// setupSettingsScreen()
|
||||
setupLicenceSetting()
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
|
@ -381,59 +384,53 @@ class SettingsActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
private fun registerChangeListeners() {
|
||||
appPreferences.registerProxyTypeListener(ProxyTypeChangeListener().also { proxyTypeChangeListener = it })
|
||||
appPreferences.registerProxyCredentialsListener(
|
||||
ProxyCredentialsChangeListener().also {
|
||||
proxyCredentialsChangeListener = it
|
||||
}
|
||||
)
|
||||
appPreferences.registerScreenSecurityListener(
|
||||
ScreenSecurityChangeListener().also {
|
||||
screenSecurityChangeListener = it
|
||||
}
|
||||
)
|
||||
val appPreferences = AppPreferencesImpl(context)
|
||||
proxyTypeFlow = appPreferences.readString(AppPreferencesImpl.PROXY_TYPE)
|
||||
proxyCredentialFlow = appPreferences.readBoolean(AppPreferencesImpl.PROXY_CRED)
|
||||
screenSecurityFlow = appPreferences.readBoolean(AppPreferencesImpl.SCREEN_SECURITY)
|
||||
screenLockFlow = appPreferences.readBoolean(AppPreferencesImpl.SCREEN_LOCK)
|
||||
screenLockTimeoutFlow = appPreferences.readString(AppPreferencesImpl.SCREEN_LOCK_TIMEOUT)
|
||||
|
||||
val themeKey = context.resources.getString(R.string.nc_settings_theme_key)
|
||||
themeFlow = appPreferences.readString(themeKey)
|
||||
|
||||
val privacyKey = context.resources.getString(R.string.nc_settings_read_privacy_key)
|
||||
readPrivacyFlow = appPreferences.readBoolean(privacyKey)
|
||||
|
||||
typingStatusFlow = appPreferences.readBoolean(AppPreferencesImpl.TYPING_STATUS)
|
||||
phoneBookIntegrationFlow = appPreferences.readBoolean(AppPreferencesImpl.PHONE_BOOK_INTEGRATION)
|
||||
|
||||
var pos = resources.getStringArray(R.array.screen_lock_timeout_entry_values).indexOf(
|
||||
appPreferences.screenLockTimeout
|
||||
)
|
||||
binding.settingsScreenLockTimeoutLayoutDropdown.setText(
|
||||
resources.getStringArray(R.array.screen_lock_timeout_descriptions)[pos]
|
||||
)
|
||||
|
||||
binding.settingsScreenLockTimeoutLayoutDropdown.setSimpleItems(R.array.screen_lock_timeout_descriptions)
|
||||
binding.settingsScreenLockTimeoutLayoutDropdown.setOnItemClickListener { _, _, position, _ ->
|
||||
val entryVal: String = resources.getStringArray(R.array.screen_lock_timeout_entry_values)[position]
|
||||
appPreferences.screenLockTimeout = entryVal
|
||||
SecurityUtils.createKey(entryVal)
|
||||
}
|
||||
appPreferences.registerScreenLockListener(ScreenLockListener().also { screenLockChangeListener = it })
|
||||
appPreferences.registerScreenLockTimeoutListener(
|
||||
ScreenLockTimeoutListener().also {
|
||||
screenLockTimeoutChangeListener = it
|
||||
}
|
||||
)
|
||||
pos = resources.getStringArray(R.array.theme_entry_values).indexOf(appPreferences.theme)
|
||||
binding.settingsTheme.setText(resources.getStringArray(R.array.theme_descriptions)[pos])
|
||||
|
||||
binding.settingsTheme.setSimpleItems(R.array.theme_descriptions)
|
||||
binding.settingsTheme.setOnItemClickListener { _, _, position, _ ->
|
||||
val entryVal: String = resources.getStringArray(R.array.theme_entry_values)[position]
|
||||
appPreferences.theme = entryVal
|
||||
}
|
||||
appPreferences.registerThemeChangeListener(ThemeChangeListener().also { themeChangeListener = it })
|
||||
appPreferences.registerPhoneBookIntegrationChangeListener(
|
||||
PhoneBookIntegrationChangeListener(this).also {
|
||||
phoneBookIntegrationChangeListener = it
|
||||
}
|
||||
)
|
||||
appPreferences.registerReadPrivacyChangeListener(
|
||||
ReadPrivacyChangeListener().also {
|
||||
readPrivacyChangeListener = it
|
||||
}
|
||||
)
|
||||
|
||||
appPreferences.registerTypingStatusChangeListener(
|
||||
TypingStatusChangeListener().also {
|
||||
typingStatusChangeListener = it
|
||||
}
|
||||
)
|
||||
observeProxyType()
|
||||
observeProxyCredential()
|
||||
observeScreenSecurity()
|
||||
observeScreenLock()
|
||||
observeTheme()
|
||||
observeReadPrivacy()
|
||||
observeTypingStatus()
|
||||
}
|
||||
|
||||
fun sendLogs() {
|
||||
|
@ -694,10 +691,10 @@ class SettingsActivity : BaseActivity() {
|
|||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
binding.settingsIncognitoKeyboardSwitch.isChecked = appPreferences.isKeyboardIncognito
|
||||
} else {
|
||||
binding.settingsIncognitoKeyboardSwitch.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.settingsIncognitoKeyboardSwitch.isChecked = appPreferences.isKeyboardIncognito
|
||||
|
||||
if (CapabilitiesUtilNew.isReadStatusAvailable(currentUser!!)) {
|
||||
binding.settingsReadPrivacySwitch.isChecked = !CapabilitiesUtilNew.isReadStatusPrivate(currentUser!!)
|
||||
} else {
|
||||
|
@ -738,6 +735,13 @@ class SettingsActivity : BaseActivity() {
|
|||
val isChecked = binding.settingsPhoneBookIntegrationSwitch.isChecked
|
||||
binding.settingsPhoneBookIntegrationSwitch.isChecked = !isChecked
|
||||
appPreferences.setPhoneBookIntegration(!isChecked)
|
||||
if (!isChecked) {
|
||||
if (checkPermission(this@SettingsActivity, (context))) {
|
||||
checkForPhoneNumber()
|
||||
}
|
||||
} else {
|
||||
deleteAll()
|
||||
}
|
||||
}
|
||||
|
||||
binding.settingsScreenSecurity.setOnClickListener {
|
||||
|
@ -798,15 +802,15 @@ class SettingsActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
public override fun onDestroy() {
|
||||
appPreferences.unregisterProxyTypeListener(proxyTypeChangeListener)
|
||||
appPreferences.unregisterProxyCredentialsListener(proxyCredentialsChangeListener)
|
||||
appPreferences.unregisterScreenSecurityListener(screenSecurityChangeListener)
|
||||
appPreferences.unregisterScreenLockListener(screenLockChangeListener)
|
||||
appPreferences.unregisterScreenLockTimeoutListener(screenLockTimeoutChangeListener)
|
||||
appPreferences.unregisterThemeChangeListener(themeChangeListener)
|
||||
appPreferences.unregisterReadPrivacyChangeListener(readPrivacyChangeListener)
|
||||
appPreferences.unregisterTypingStatusChangeListener(typingStatusChangeListener)
|
||||
appPreferences.unregisterPhoneBookIntegrationChangeListener(phoneBookIntegrationChangeListener)
|
||||
// appPreferences.unregisterProxyTypeListener(proxyTypeChangeListener)
|
||||
// appPreferences.unregisterProxyCredentialsListener(proxyCredentialsChangeListener)
|
||||
// appPreferences.unregisterScreenSecurityListener(screenSecurityChangeListener)
|
||||
// appPreferences.unregisterScreenLockListener(screenLockChangeListener)
|
||||
// appPreferences.unregisterScreenLockTimeoutListener(screenLockTimeoutChangeListener)
|
||||
// appPreferences.unregisterThemeChangeListener(themeChangeListener)
|
||||
// appPreferences.unregisterReadPrivacyChangeListener(readPrivacyChangeListener)
|
||||
// appPreferences.unregisterTypingStatusChangeListener(typingStatusChangeListener)
|
||||
// appPreferences.unregisterPhoneBookIntegrationChangeListener(phoneBookIntegrationChangeListener)
|
||||
|
||||
super.onDestroy()
|
||||
}
|
||||
|
@ -819,8 +823,7 @@ class SettingsActivity : BaseActivity() {
|
|||
appPreferences.removeProxyPassword()
|
||||
binding.settingsProxyHostLayout.visibility = View.GONE
|
||||
binding.settingsProxyPortLayout.visibility = View.GONE
|
||||
binding.settingsProxyUseCredentials.visibility =
|
||||
View.GONE
|
||||
binding.settingsProxyUseCredentials.visibility = View.GONE
|
||||
hideProxyCredentials()
|
||||
}
|
||||
|
||||
|
@ -896,86 +899,98 @@ class SettingsActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private inner class ScreenLockTimeoutListener : OnPreferenceValueChangedListener<String?> {
|
||||
override fun onChanged(newValue: String?) {
|
||||
SecurityUtils.createKey(appPreferences.screenLockTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ScreenLockListener : OnPreferenceValueChangedListener<Boolean> {
|
||||
override fun onChanged(newValue: Boolean) {
|
||||
binding.settingsScreenLockTimeout.isEnabled = newValue
|
||||
if (newValue) {
|
||||
binding.settingsScreenLockTimeout.alpha = ENABLED_ALPHA
|
||||
} else {
|
||||
binding.settingsScreenLockTimeout.alpha = DISABLED_ALPHA
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ScreenSecurityChangeListener : OnPreferenceValueChangedListener<Boolean> {
|
||||
override fun onChanged(newValue: Boolean) {
|
||||
if (newValue) {
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||
} else {
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ProxyCredentialsChangeListener : OnPreferenceValueChangedListener<Boolean> {
|
||||
override fun onChanged(newValue: Boolean) {
|
||||
if (newValue) {
|
||||
showProxyCredentials()
|
||||
} else {
|
||||
hideProxyCredentials()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ProxyTypeChangeListener : OnPreferenceValueChangedListener<String> {
|
||||
@Suppress("Detekt.TooGenericExceptionCaught")
|
||||
override fun onChanged(newValue: String) {
|
||||
if (("No proxy" == newValue)) {
|
||||
hideProxySettings()
|
||||
} else {
|
||||
when (newValue) {
|
||||
"HTTP" -> {
|
||||
binding.settingsProxyPortEdit.setText(getString(R.string.nc_settings_http_value))
|
||||
appPreferences.proxyPort = getString(R.string.nc_settings_http_value)
|
||||
}
|
||||
|
||||
"DIRECT" -> {
|
||||
binding.settingsProxyPortEdit.setText(getString(R.string.nc_settings_direct_value))
|
||||
appPreferences.proxyPort = getString(R.string.nc_settings_direct_value)
|
||||
}
|
||||
"SOCKS" -> {
|
||||
binding.settingsProxyPortEdit.setText(getString(R.string.nc_settings_socks_value))
|
||||
appPreferences.proxyPort = getString(R.string.nc_settings_socks_value)
|
||||
}
|
||||
else -> {
|
||||
private fun observeScreenLock() {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
var state = appPreferences.isScreenLocked
|
||||
screenLockFlow.collect { newBoolean ->
|
||||
if (newBoolean != state) {
|
||||
state = newBoolean
|
||||
binding.settingsScreenLockTimeout.isEnabled = newBoolean
|
||||
if (newBoolean) {
|
||||
binding.settingsScreenLockTimeout.alpha = ENABLED_ALPHA
|
||||
} else {
|
||||
binding.settingsScreenLockTimeout.alpha = DISABLED_ALPHA
|
||||
}
|
||||
}
|
||||
showProxySettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ThemeChangeListener : OnPreferenceValueChangedListener<String?> {
|
||||
override fun onChanged(newValue: String?) {
|
||||
setAppTheme((newValue)!!)
|
||||
private fun observeScreenSecurity() {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
var state = appPreferences.isScreenSecured
|
||||
screenSecurityFlow.collect { newBoolean ->
|
||||
if (newBoolean != state) {
|
||||
state = newBoolean
|
||||
if (newBoolean) {
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||
} else {
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class PhoneBookIntegrationChangeListener(private val activity: Activity) :
|
||||
OnPreferenceValueChangedListener<Boolean> {
|
||||
override fun onChanged(isEnabled: Boolean) {
|
||||
if (isEnabled) {
|
||||
if (checkPermission(activity, (context))) {
|
||||
checkForPhoneNumber()
|
||||
private fun observeProxyCredential() {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
var state = appPreferences.proxyCredentials
|
||||
proxyCredentialFlow.collect { newBoolean ->
|
||||
if (newBoolean != state) {
|
||||
state = newBoolean
|
||||
if (newBoolean) {
|
||||
showProxyCredentials()
|
||||
} else {
|
||||
hideProxyCredentials()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeProxyType() {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
var state = appPreferences.proxyType
|
||||
proxyTypeFlow.collect { newString ->
|
||||
if (newString != state) {
|
||||
state = newString
|
||||
if (("No proxy" == newString) || newString.isEmpty()) {
|
||||
hideProxySettings()
|
||||
} else {
|
||||
when (newString) {
|
||||
"HTTP" -> {
|
||||
binding.settingsProxyPortEdit.setText(getString(R.string.nc_settings_http_value))
|
||||
appPreferences.proxyPort = getString(R.string.nc_settings_http_value)
|
||||
}
|
||||
|
||||
"DIRECT" -> {
|
||||
binding.settingsProxyPortEdit.setText(getString(R.string.nc_settings_direct_value))
|
||||
appPreferences.proxyPort = getString(R.string.nc_settings_direct_value)
|
||||
}
|
||||
|
||||
"SOCKS" -> {
|
||||
binding.settingsProxyPortEdit.setText(getString(R.string.nc_settings_socks_value))
|
||||
appPreferences.proxyPort = getString(R.string.nc_settings_socks_value)
|
||||
}
|
||||
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
showProxySettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeTheme() {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
var state = appPreferences.theme
|
||||
themeFlow.collect { newString ->
|
||||
if (newString != state) {
|
||||
state = newString
|
||||
setAppTheme(newString)
|
||||
}
|
||||
} else {
|
||||
deleteAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1112,68 +1127,80 @@ class SettingsActivity : BaseActivity() {
|
|||
})
|
||||
}
|
||||
|
||||
private inner class ReadPrivacyChangeListener : OnPreferenceValueChangedListener<Boolean> {
|
||||
override fun onChanged(newValue: Boolean) {
|
||||
val booleanValue = if (newValue) "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<GenericOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
private fun observeReadPrivacy() {
|
||||
CoroutineScope(Dispatchers.Main).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}"
|
||||
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<GenericOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(genericOverall: GenericOverall) {
|
||||
// unused atm
|
||||
}
|
||||
override fun onNext(genericOverall: GenericOverall) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
appPreferences.setReadPrivacy(!newValue)
|
||||
binding.settingsReadPrivacySwitch.isChecked = !newValue
|
||||
}
|
||||
override fun onError(e: Throwable) {
|
||||
appPreferences.setReadPrivacy(!newBoolean)
|
||||
binding.settingsReadPrivacySwitch.isChecked = !newBoolean
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class TypingStatusChangeListener : OnPreferenceValueChangedListener<Boolean> {
|
||||
override fun onChanged(newValue: Boolean) {
|
||||
val booleanValue = if (newValue) "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<GenericOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
private fun observeTypingStatus() {
|
||||
CoroutineScope(Dispatchers.Main).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}"
|
||||
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<GenericOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(genericOverall: GenericOverall) {
|
||||
loadCapabilitiesAndUpdateSettings()
|
||||
Log.i(TAG, "onNext called typing status set")
|
||||
}
|
||||
override fun onNext(genericOverall: GenericOverall) {
|
||||
loadCapabilitiesAndUpdateSettings()
|
||||
Log.i(TAG, "onNext called typing status set")
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
appPreferences.setTypingStatus(!newValue)
|
||||
binding.settingsTypingStatusSwitch.isChecked = !newValue
|
||||
}
|
||||
override fun onError(e: Throwable) {
|
||||
appPreferences.typingStatus = !newBoolean
|
||||
binding.settingsTypingStatusSwitch.isChecked = !newBoolean
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,333 +26,147 @@ package com.nextcloud.talk.utils.preferences;
|
|||
|
||||
import android.annotation.SuppressLint;
|
||||
|
||||
import com.nextcloud.talk.R;
|
||||
|
||||
import net.orange_box.storebox.annotations.method.ClearMethod;
|
||||
import net.orange_box.storebox.annotations.method.DefaultValue;
|
||||
import net.orange_box.storebox.annotations.method.KeyByResource;
|
||||
import net.orange_box.storebox.annotations.method.KeyByString;
|
||||
import net.orange_box.storebox.annotations.method.RegisterChangeListenerMethod;
|
||||
import net.orange_box.storebox.annotations.method.RemoveMethod;
|
||||
import net.orange_box.storebox.annotations.method.UnregisterChangeListenerMethod;
|
||||
import net.orange_box.storebox.annotations.option.SaveOption;
|
||||
import net.orange_box.storebox.enums.SaveMode;
|
||||
import net.orange_box.storebox.listeners.OnPreferenceValueChangedListener;
|
||||
|
||||
@SuppressLint("NonConstantResourceId")
|
||||
@SaveOption(SaveMode.APPLY)
|
||||
public interface AppPreferences {
|
||||
|
||||
@KeyByString("proxy_type")
|
||||
@RegisterChangeListenerMethod
|
||||
void registerProxyTypeListener(OnPreferenceValueChangedListener<String> listener);
|
||||
|
||||
@KeyByString("proxy_type")
|
||||
@UnregisterChangeListenerMethod
|
||||
void unregisterProxyTypeListener(OnPreferenceValueChangedListener<String> listener);
|
||||
|
||||
@KeyByString("proxy_type")
|
||||
String getProxyType();
|
||||
|
||||
@KeyByString("proxy_type")
|
||||
void setProxyType(String proxyType);
|
||||
|
||||
@KeyByString("proxy_server")
|
||||
@RemoveMethod
|
||||
void removeProxyType();
|
||||
|
||||
@KeyByString("proxy_host")
|
||||
String getProxyHost();
|
||||
|
||||
@KeyByString("proxy_host")
|
||||
void setProxyHost(String proxyHost);
|
||||
|
||||
@KeyByString("proxy_host")
|
||||
@RemoveMethod
|
||||
void removeProxyHost();
|
||||
|
||||
@KeyByString("proxy_port")
|
||||
String getProxyPort();
|
||||
|
||||
@KeyByString("proxy_port")
|
||||
void setProxyPort(String proxyPort);
|
||||
|
||||
@KeyByString("proxy_port")
|
||||
@RemoveMethod
|
||||
void removeProxyPort();
|
||||
|
||||
@KeyByString("proxy_credentials")
|
||||
@RegisterChangeListenerMethod
|
||||
void registerProxyCredentialsListener(OnPreferenceValueChangedListener<Boolean> listener);
|
||||
|
||||
@KeyByString("proxy_credentials")
|
||||
@UnregisterChangeListenerMethod
|
||||
void unregisterProxyCredentialsListener(OnPreferenceValueChangedListener<Boolean> listener);
|
||||
|
||||
@KeyByString("proxy_credentials")
|
||||
boolean getProxyCredentials();
|
||||
|
||||
@KeyByString("proxy_credentials")
|
||||
void setProxyNeedsCredentials(boolean proxyNeedsCredentials);
|
||||
|
||||
@KeyByString("proxy_credentials")
|
||||
@RemoveMethod
|
||||
void removeProxyCredentials();
|
||||
|
||||
@KeyByString("proxy_username")
|
||||
String getProxyUsername();
|
||||
|
||||
@KeyByString("proxy_username")
|
||||
void setProxyUsername(String proxyUsername);
|
||||
|
||||
@KeyByString("proxy_username")
|
||||
@RemoveMethod
|
||||
void removeProxyUsername();
|
||||
|
||||
@KeyByString("proxy_password")
|
||||
String getProxyPassword();
|
||||
|
||||
@KeyByString("proxy_password")
|
||||
void setProxyPassword(String proxyPassword);
|
||||
|
||||
@KeyByString("proxy_password")
|
||||
@RemoveMethod
|
||||
void removeProxyPassword();
|
||||
|
||||
@KeyByString("push_token")
|
||||
String getPushToken();
|
||||
|
||||
@KeyByString("push_token")
|
||||
void setPushToken(String pushToken);
|
||||
|
||||
@KeyByString("push_token")
|
||||
@RemoveMethod
|
||||
void removePushToken();
|
||||
|
||||
@KeyByString("tempClientCertAlias")
|
||||
String getTemporaryClientCertAlias();
|
||||
|
||||
@KeyByString("tempClientCertAlias")
|
||||
void setTemporaryClientCertAlias(String alias);
|
||||
|
||||
@KeyByString("tempClientCertAlias")
|
||||
@RemoveMethod
|
||||
void removeTemporaryClientCertAlias();
|
||||
|
||||
@KeyByString("pushToTalk_intro_shown")
|
||||
boolean getPushToTalkIntroShown();
|
||||
|
||||
@KeyByString("pushToTalk_intro_shown")
|
||||
void setPushToTalkIntroShown(boolean shown);
|
||||
|
||||
@KeyByString("pushToTalk_intro_shown")
|
||||
@RemoveMethod
|
||||
void removePushToTalkIntroShown();
|
||||
|
||||
@KeyByString("call_ringtone")
|
||||
String getCallRingtoneUri();
|
||||
|
||||
@KeyByString("call_ringtone")
|
||||
void setCallRingtoneUri(String value);
|
||||
|
||||
@KeyByString("call_ringtone")
|
||||
@RemoveMethod
|
||||
void removeCallRingtoneUri();
|
||||
|
||||
@KeyByString("message_ringtone")
|
||||
String getMessageRingtoneUri();
|
||||
|
||||
@KeyByString("message_ringtone")
|
||||
void setMessageRingtoneUri(String value);
|
||||
|
||||
@KeyByString("message_ringtone")
|
||||
@RemoveMethod
|
||||
void removeMessageRingtoneUri();
|
||||
|
||||
@KeyByString("notification_channels_upgrade_to_v2")
|
||||
boolean getIsNotificationChannelUpgradedToV2();
|
||||
|
||||
@KeyByString("notification_channels_upgrade_to_v2")
|
||||
void setNotificationChannelIsUpgradedToV2(boolean value);
|
||||
|
||||
@KeyByString("notification_channels_upgrade_to_v2")
|
||||
@RemoveMethod
|
||||
void removeNotificationChannelUpgradeToV2();
|
||||
|
||||
@KeyByString("notification_channels_upgrade_to_v3")
|
||||
boolean getIsNotificationChannelUpgradedToV3();
|
||||
|
||||
@KeyByString("notification_channels_upgrade_to_v3")
|
||||
void setNotificationChannelIsUpgradedToV3(boolean value);
|
||||
|
||||
@KeyByString("notification_channels_upgrade_to_v3")
|
||||
@RemoveMethod
|
||||
void removeNotificationChannelUpgradeToV3();
|
||||
|
||||
@KeyByString("screen_security")
|
||||
@DefaultValue(R.bool.value_false)
|
||||
boolean getIsScreenSecured();
|
||||
|
||||
@KeyByString("screen_security")
|
||||
void setScreenSecurity(boolean value);
|
||||
|
||||
@KeyByString("screen_security")
|
||||
@RemoveMethod
|
||||
void removeScreenSecurity();
|
||||
|
||||
@KeyByString("screen_security")
|
||||
@RegisterChangeListenerMethod
|
||||
void registerScreenSecurityListener(OnPreferenceValueChangedListener<Boolean> listener);
|
||||
|
||||
@KeyByString("screen_security")
|
||||
@UnregisterChangeListenerMethod
|
||||
void unregisterScreenSecurityListener(OnPreferenceValueChangedListener<Boolean> listener);
|
||||
|
||||
@KeyByString("screen_lock")
|
||||
@DefaultValue(R.bool.value_false)
|
||||
boolean getIsScreenLocked();
|
||||
|
||||
@KeyByString("screen_lock")
|
||||
void setScreenLock(boolean value);
|
||||
|
||||
@KeyByString("screen_lock")
|
||||
@RemoveMethod
|
||||
void removeScreenLock();
|
||||
|
||||
@KeyByString("screen_lock")
|
||||
@RegisterChangeListenerMethod
|
||||
void registerScreenLockListener(OnPreferenceValueChangedListener<Boolean> listener);
|
||||
|
||||
@KeyByString("screen_lock")
|
||||
@UnregisterChangeListenerMethod
|
||||
void unregisterScreenLockListener(OnPreferenceValueChangedListener<Boolean> listener);
|
||||
|
||||
@KeyByString("incognito_keyboard")
|
||||
@DefaultValue(R.bool.value_true)
|
||||
boolean getIsKeyboardIncognito();
|
||||
|
||||
@KeyByString("incognito_keyboard")
|
||||
void setIncognitoKeyboard(boolean value);
|
||||
|
||||
@KeyByString("incognito_keyboard")
|
||||
@RemoveMethod
|
||||
void removeIncognitoKeyboard();
|
||||
|
||||
@KeyByString("phone_book_integration")
|
||||
@DefaultValue(R.bool.value_false)
|
||||
|
||||
boolean isPhoneBookIntegrationEnabled();
|
||||
|
||||
@KeyByString("phone_book_integration")
|
||||
|
||||
void setPhoneBookIntegration(boolean value);
|
||||
|
||||
// TODO Remove in 13.0.0
|
||||
@KeyByString("link_previews")
|
||||
@RemoveMethod
|
||||
void removeLinkPreviews();
|
||||
|
||||
@KeyByString("screen_lock_timeout")
|
||||
@DefaultValue(R.string.nc_screen_lock_timeout_sixty)
|
||||
String getScreenLockTimeout();
|
||||
|
||||
@KeyByString("screen_lock_timeout")
|
||||
void setScreenLockTimeout(String value);
|
||||
|
||||
@KeyByString("screen_lock_timeout")
|
||||
@RemoveMethod
|
||||
void removeScreenLockTimeout();
|
||||
|
||||
@KeyByString("screen_lock_timeout")
|
||||
@RegisterChangeListenerMethod
|
||||
void registerScreenLockTimeoutListener(OnPreferenceValueChangedListener<String> listener);
|
||||
|
||||
@KeyByString("screen_lock_timeout")
|
||||
@UnregisterChangeListenerMethod
|
||||
void unregisterScreenLockTimeoutListener(OnPreferenceValueChangedListener<String> listener);
|
||||
|
||||
@KeyByResource(R.string.nc_settings_theme_key)
|
||||
@DefaultValue(R.string.nc_default_theme)
|
||||
String getTheme();
|
||||
|
||||
@KeyByResource(R.string.nc_settings_theme_key)
|
||||
void setTheme(String newValue);
|
||||
|
||||
@KeyByResource(R.string.nc_settings_theme_key)
|
||||
@RemoveMethod
|
||||
void removeTheme();
|
||||
|
||||
@KeyByResource(R.string.nc_settings_theme_key)
|
||||
@RegisterChangeListenerMethod
|
||||
void registerThemeChangeListener(OnPreferenceValueChangedListener<String> listener);
|
||||
|
||||
@KeyByResource(R.string.nc_settings_theme_key)
|
||||
@UnregisterChangeListenerMethod
|
||||
void unregisterThemeChangeListener(OnPreferenceValueChangedListener<String> listener);
|
||||
|
||||
@KeyByString("db_cypher_v4_upgrade")
|
||||
@DefaultValue(R.bool.value_true)
|
||||
boolean isDbCypherToUpgrade();
|
||||
|
||||
@KeyByString("db_cypher_v4_upgrade")
|
||||
void setDbCypherToUpgrade(boolean value);
|
||||
|
||||
@KeyByString("db_room_migrated")
|
||||
@DefaultValue(R.bool.value_false)
|
||||
boolean getIsDbRoomMigrated();
|
||||
|
||||
@KeyByString("db_room_migrated")
|
||||
void setIsDbRoomMigrated(boolean value);
|
||||
|
||||
@KeyByResource(R.string.nc_settings_phone_book_integration_key)
|
||||
@RegisterChangeListenerMethod
|
||||
void registerPhoneBookIntegrationChangeListener(OnPreferenceValueChangedListener<Boolean> listener);
|
||||
|
||||
@KeyByResource(R.string.nc_settings_phone_book_integration_key)
|
||||
@UnregisterChangeListenerMethod
|
||||
void unregisterPhoneBookIntegrationChangeListener(OnPreferenceValueChangedListener<Boolean> listener);
|
||||
|
||||
@KeyByString("phone_book_integration_last_run")
|
||||
void setPhoneBookIntegrationLastRun(long currentTimeMillis);
|
||||
|
||||
@KeyByString("phone_book_integration_last_run")
|
||||
long getPhoneBookIntegrationLastRun(Long defaultValue);
|
||||
|
||||
@KeyByResource(R.string.nc_settings_read_privacy_key)
|
||||
void setReadPrivacy(boolean value);
|
||||
|
||||
@KeyByString("typing_status")
|
||||
boolean getReadPrivacy();
|
||||
|
||||
void setTypingStatus(boolean value);
|
||||
|
||||
@KeyByResource(R.string.nc_settings_read_privacy_key)
|
||||
@RegisterChangeListenerMethod
|
||||
void registerReadPrivacyChangeListener(OnPreferenceValueChangedListener<Boolean> listener);
|
||||
|
||||
@KeyByResource(R.string.nc_settings_read_privacy_key)
|
||||
@UnregisterChangeListenerMethod
|
||||
void unregisterReadPrivacyChangeListener(OnPreferenceValueChangedListener<Boolean> listener);
|
||||
boolean getTypingStatus();
|
||||
|
||||
@KeyByString("typing_status")
|
||||
@RegisterChangeListenerMethod
|
||||
void registerTypingStatusChangeListener(OnPreferenceValueChangedListener<Boolean> listener);
|
||||
|
||||
@KeyByString("typing_status")
|
||||
@UnregisterChangeListenerMethod
|
||||
void unregisterTypingStatusChangeListener(OnPreferenceValueChangedListener<Boolean> listener);
|
||||
|
||||
@KeyByResource(R.string.nc_file_browser_sort_by_key)
|
||||
void setSorting(String value);
|
||||
|
||||
@KeyByResource(R.string.nc_file_browser_sort_by_key)
|
||||
@DefaultValue(R.string.nc_file_browser_sort_by_default)
|
||||
String getSorting();
|
||||
|
||||
@KeyByResource(R.string.nc_file_browser_sort_by_key)
|
||||
@RegisterChangeListenerMethod
|
||||
void registerSortingChangeListener(OnPreferenceValueChangedListener<String> listener);
|
||||
|
||||
@KeyByResource(R.string.nc_file_browser_sort_by_key)
|
||||
@UnregisterChangeListenerMethod
|
||||
void unregisterSortingChangeListener(OnPreferenceValueChangedListener<String> listener);
|
||||
|
||||
@ClearMethod
|
||||
void clear();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,491 @@
|
|||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Julius Linus
|
||||
* Copyright (C) 2023 Julius Linus <julius.linus@nextcloud.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.utils.preferences
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.longPreferencesKey
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import com.nextcloud.talk.R
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
@Suppress("TooManyFunctions", "DeferredResultUnused", "EmptyFunctionBlock")
|
||||
class AppPreferencesImpl(val context: Context) : AppPreferences {
|
||||
|
||||
override fun getProxyType(): String {
|
||||
return runBlocking { async { readString(PROXY_TYPE, "No proxy").first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setProxyType(proxyType: String?) = runBlocking<Unit> {
|
||||
async {
|
||||
if (proxyType != null) {
|
||||
writeString(PROXY_TYPE, proxyType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeProxyType() {
|
||||
proxyType = ""
|
||||
}
|
||||
|
||||
override fun getProxyHost(): String {
|
||||
return runBlocking { async { readString(PROXY_HOST).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setProxyHost(proxyHost: String?) = runBlocking<Unit> {
|
||||
async {
|
||||
if (proxyHost != null) {
|
||||
writeString(PROXY_HOST, proxyHost)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeProxyHost() {
|
||||
proxyHost = ""
|
||||
}
|
||||
|
||||
override fun getProxyPort(): String {
|
||||
return runBlocking { async { readString(PROXY_PORT).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setProxyPort(proxyPort: String?) = runBlocking<Unit> {
|
||||
async {
|
||||
if (proxyPort != null) {
|
||||
writeString(PROXY_PORT, proxyPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeProxyPort() {
|
||||
proxyPort = ""
|
||||
}
|
||||
|
||||
override fun getProxyCredentials(): Boolean {
|
||||
return runBlocking { async { readBoolean(PROXY_CRED).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setProxyNeedsCredentials(proxyNeedsCredentials: Boolean) = runBlocking<Unit> {
|
||||
async {
|
||||
writeBoolean(PROXY_CRED, proxyNeedsCredentials)
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeProxyCredentials() {
|
||||
setProxyNeedsCredentials(false)
|
||||
}
|
||||
|
||||
override fun getProxyUsername(): String {
|
||||
return runBlocking { async { readString(PROXY_USERNAME).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setProxyUsername(proxyUsername: String?) = runBlocking<Unit> {
|
||||
async {
|
||||
if (proxyUsername != null) {
|
||||
writeString(PROXY_USERNAME, proxyUsername)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeProxyUsername() {
|
||||
proxyUsername = ""
|
||||
}
|
||||
|
||||
override fun getProxyPassword(): String {
|
||||
return runBlocking { async { readString(PROXY_PASSWORD).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setProxyPassword(proxyPassword: String?) = runBlocking<Unit> {
|
||||
async {
|
||||
if (proxyPassword != null) {
|
||||
writeString(PROXY_PASSWORD, proxyPassword)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeProxyPassword() {
|
||||
proxyPassword = ""
|
||||
}
|
||||
|
||||
override fun getPushToken(): String {
|
||||
return runBlocking { async { readString(PUSH_TOKEN).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setPushToken(pushToken: String?) = runBlocking<Unit> {
|
||||
async {
|
||||
if (pushToken != null) {
|
||||
writeString(PUSH_TOKEN, pushToken)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun removePushToken() {
|
||||
pushToken = ""
|
||||
}
|
||||
|
||||
override fun getTemporaryClientCertAlias(): String {
|
||||
return runBlocking { async { readString(TEMP_CLIENT_CERT_ALIAS).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setTemporaryClientCertAlias(alias: String?) = runBlocking<Unit> {
|
||||
async {
|
||||
if (alias != null) {
|
||||
writeString(TEMP_CLIENT_CERT_ALIAS, alias)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeTemporaryClientCertAlias() {
|
||||
temporaryClientCertAlias = ""
|
||||
}
|
||||
|
||||
override fun getPushToTalkIntroShown(): Boolean {
|
||||
return runBlocking { async { readBoolean(PUSH_TO_TALK_INTRO_SHOWN).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setPushToTalkIntroShown(shown: Boolean) = runBlocking<Unit> {
|
||||
async {
|
||||
writeBoolean(PUSH_TO_TALK_INTRO_SHOWN, shown)
|
||||
}
|
||||
}
|
||||
|
||||
override fun removePushToTalkIntroShown() {
|
||||
pushToTalkIntroShown = false
|
||||
}
|
||||
|
||||
override fun getCallRingtoneUri(): String {
|
||||
return runBlocking { async { readString(CALL_RINGTONE).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setCallRingtoneUri(value: String?) = runBlocking<Unit> {
|
||||
async {
|
||||
if (value != null) {
|
||||
writeString(CALL_RINGTONE, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeCallRingtoneUri() {
|
||||
callRingtoneUri = ""
|
||||
}
|
||||
|
||||
override fun getMessageRingtoneUri(): String {
|
||||
return runBlocking { async { readString(MESSAGE_RINGTONE).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setMessageRingtoneUri(value: String?) = runBlocking<Unit> {
|
||||
async {
|
||||
if (value != null) {
|
||||
writeString(MESSAGE_RINGTONE, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeMessageRingtoneUri() {
|
||||
messageRingtoneUri = ""
|
||||
}
|
||||
|
||||
override fun getIsNotificationChannelUpgradedToV2(): Boolean {
|
||||
return runBlocking { async { readBoolean(NOTIFY_UPGRADE_V2).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setNotificationChannelIsUpgradedToV2(value: Boolean) = runBlocking<Unit> {
|
||||
async {
|
||||
writeBoolean(NOTIFY_UPGRADE_V2, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeNotificationChannelUpgradeToV2() {
|
||||
setNotificationChannelIsUpgradedToV2(false)
|
||||
}
|
||||
|
||||
override fun getIsNotificationChannelUpgradedToV3(): Boolean {
|
||||
return runBlocking { async { readBoolean(NOTIFY_UPGRADE_V3).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setNotificationChannelIsUpgradedToV3(value: Boolean) = runBlocking<Unit> {
|
||||
async {
|
||||
writeBoolean(NOTIFY_UPGRADE_V3, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeNotificationChannelUpgradeToV3() {
|
||||
setNotificationChannelIsUpgradedToV3(false)
|
||||
}
|
||||
|
||||
override fun getIsScreenSecured(): Boolean {
|
||||
return runBlocking { async { readBoolean(SCREEN_SECURITY).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setScreenSecurity(value: Boolean) = runBlocking<Unit> {
|
||||
async {
|
||||
writeBoolean(SCREEN_SECURITY, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeScreenSecurity() {
|
||||
setScreenSecurity(false)
|
||||
}
|
||||
|
||||
override fun getIsScreenLocked(): Boolean {
|
||||
return runBlocking { async { readBoolean(SCREEN_LOCK).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setScreenLock(value: Boolean) = runBlocking<Unit> {
|
||||
async {
|
||||
writeBoolean(SCREEN_LOCK, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeScreenLock() {
|
||||
setScreenLock(false)
|
||||
}
|
||||
|
||||
override fun getIsKeyboardIncognito(): Boolean {
|
||||
val read = runBlocking { async { readBoolean(INCOGNITO_KEYBOARD).first() } }.getCompleted()
|
||||
return read
|
||||
}
|
||||
|
||||
override fun setIncognitoKeyboard(value: Boolean) = runBlocking<Unit> {
|
||||
async {
|
||||
writeBoolean(INCOGNITO_KEYBOARD, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeIncognitoKeyboard() {
|
||||
setIncognitoKeyboard(false)
|
||||
}
|
||||
|
||||
override fun isPhoneBookIntegrationEnabled(): Boolean {
|
||||
return runBlocking { async { readBoolean(PHONE_BOOK_INTEGRATION).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setPhoneBookIntegration(value: Boolean) = runBlocking<Unit> {
|
||||
async {
|
||||
writeBoolean(PHONE_BOOK_INTEGRATION, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeLinkPreviews() = runBlocking<Unit> {
|
||||
async {
|
||||
writeBoolean(LINK_PREVIEWS, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getScreenLockTimeout(): String {
|
||||
val default = context.resources.getString(R.string.nc_screen_lock_timeout_sixty)
|
||||
val read = runBlocking { async { readString(SCREEN_LOCK_TIMEOUT).first() } }.getCompleted()
|
||||
return read.ifEmpty { default }
|
||||
}
|
||||
|
||||
override fun setScreenLockTimeout(value: String?) = runBlocking<Unit> {
|
||||
async {
|
||||
if (value != null) {
|
||||
writeString(SCREEN_LOCK_TIMEOUT, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeScreenLockTimeout() {
|
||||
screenLockTimeout = ""
|
||||
}
|
||||
|
||||
override fun getTheme(): String {
|
||||
val key = context.resources.getString(R.string.nc_settings_theme_key)
|
||||
val default = context.resources.getString(R.string.nc_default_theme)
|
||||
val read = runBlocking { async { readString(key).first() } }.getCompleted()
|
||||
return read.ifEmpty { default }
|
||||
}
|
||||
|
||||
override fun setTheme(value: String?) = runBlocking<Unit> {
|
||||
async {
|
||||
if (value != null) {
|
||||
val key = context.resources.getString(R.string.nc_settings_theme_key)
|
||||
writeString(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeTheme() {
|
||||
theme = ""
|
||||
}
|
||||
|
||||
override fun isDbCypherToUpgrade(): Boolean {
|
||||
val read = runBlocking { async { readBoolean(DB_CYPHER_V4_UPGRADE).first() } }.getCompleted()
|
||||
return read
|
||||
}
|
||||
|
||||
override fun setDbCypherToUpgrade(value: Boolean) = runBlocking<Unit> {
|
||||
async {
|
||||
writeBoolean(DB_CYPHER_V4_UPGRADE, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIsDbRoomMigrated(): Boolean {
|
||||
return runBlocking { async { readBoolean(DB_ROOM_MIGRATED).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setIsDbRoomMigrated(value: Boolean) = runBlocking<Unit> {
|
||||
async {
|
||||
writeBoolean(DB_ROOM_MIGRATED, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setPhoneBookIntegrationLastRun(currentTimeMillis: Long) = runBlocking<Unit> {
|
||||
async {
|
||||
writeLong(PHONE_BOOK_INTEGRATION_LAST_RUN, currentTimeMillis)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPhoneBookIntegrationLastRun(defaultValue: Long?): Long {
|
||||
val result = if (defaultValue != null) {
|
||||
runBlocking { async { readLong(PHONE_BOOK_INTEGRATION_LAST_RUN, defaultValue = defaultValue).first() } }
|
||||
.getCompleted()
|
||||
} else {
|
||||
runBlocking { async { readLong(PHONE_BOOK_INTEGRATION_LAST_RUN).first() } }.getCompleted()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun setReadPrivacy(value: Boolean) = runBlocking<Unit> {
|
||||
val key = context.resources.getString(R.string.nc_settings_read_privacy_key)
|
||||
async {
|
||||
writeBoolean(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getReadPrivacy(): Boolean {
|
||||
val key = context.resources.getString(R.string.nc_settings_read_privacy_key)
|
||||
return runBlocking { async { readBoolean(key).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setTypingStatus(value: Boolean) = runBlocking<Unit> {
|
||||
async {
|
||||
writeBoolean(TYPING_STATUS, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTypingStatus(): Boolean {
|
||||
return runBlocking { async { readBoolean(TYPING_STATUS).first() } }.getCompleted()
|
||||
}
|
||||
|
||||
override fun setSorting(value: String?) = runBlocking<Unit> {
|
||||
val key = context.resources.getString(R.string.nc_file_browser_sort_by_key)
|
||||
async {
|
||||
if (value != null) {
|
||||
writeString(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSorting(): String {
|
||||
val key = context.resources.getString(R.string.nc_file_browser_sort_by_key)
|
||||
val default = context.resources.getString(R.string.nc_file_browser_sort_by_default)
|
||||
val read = runBlocking { async { readString(key).first() } }.getCompleted()
|
||||
return read.ifEmpty { default }
|
||||
}
|
||||
|
||||
override fun clear() {}
|
||||
|
||||
private suspend fun writeString(key: String, value: String) = context.dataStore.edit { settings ->
|
||||
settings[
|
||||
stringPreferencesKey(
|
||||
key
|
||||
)
|
||||
] = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Flow of type String
|
||||
* @param key the key of the persisted data to be observed
|
||||
*/
|
||||
fun readString(key: String, defaultValue: String = ""): Flow<String> = context.dataStore.data.map { preferences ->
|
||||
preferences[stringPreferencesKey(key)] ?: defaultValue
|
||||
}
|
||||
|
||||
private suspend fun writeBoolean(key: String, value: Boolean) = context.dataStore.edit { settings ->
|
||||
settings[
|
||||
booleanPreferencesKey(
|
||||
key
|
||||
)
|
||||
] = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Flow of type Boolean
|
||||
* @param key the key of the persisted data to be observed
|
||||
*/
|
||||
fun readBoolean(key: String, defaultValue: Boolean = false): Flow<Boolean> =
|
||||
context.dataStore.data.map { preferences ->
|
||||
preferences[booleanPreferencesKey(key)] ?: defaultValue
|
||||
}
|
||||
|
||||
private suspend fun writeLong(key: String, value: Long) = context.dataStore.edit { settings ->
|
||||
settings[
|
||||
longPreferencesKey(
|
||||
key
|
||||
)
|
||||
] = value
|
||||
}
|
||||
|
||||
private fun readLong(key: String, defaultValue: Long = 0): Flow<Long> = context.dataStore.data.map { preferences ->
|
||||
preferences[longPreferencesKey(key)] ?: defaultValue
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Suppress("UnusedPrivateProperty")
|
||||
private val TAG = AppPreferencesImpl::class.simpleName
|
||||
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
|
||||
const val PROXY_TYPE = "proxy_type"
|
||||
const val PROXY_SERVER = "proxy_server"
|
||||
const val PROXY_HOST = "proxy_host"
|
||||
const val PROXY_PORT = "proxy_port"
|
||||
const val PROXY_CRED = "proxy_credentials"
|
||||
const val PROXY_USERNAME = "proxy_username"
|
||||
const val PROXY_PASSWORD = "proxy_password"
|
||||
const val PUSH_TOKEN = "push_token"
|
||||
const val TEMP_CLIENT_CERT_ALIAS = "tempClientCertAlias"
|
||||
const val PUSH_TO_TALK_INTRO_SHOWN = "pushToTalk_intro_shown"
|
||||
const val CALL_RINGTONE = "call_ringtone"
|
||||
const val MESSAGE_RINGTONE = "message_ringtone"
|
||||
const val NOTIFY_UPGRADE_V2 = "notification_channels_upgrade_to_v2"
|
||||
const val NOTIFY_UPGRADE_V3 = "notification_channels_upgrade_to_v3"
|
||||
const val SCREEN_SECURITY = "screen_security"
|
||||
const val SCREEN_LOCK = "screen_lock"
|
||||
const val INCOGNITO_KEYBOARD = "incognito_keyboard"
|
||||
const val PHONE_BOOK_INTEGRATION = "phone_book_integration"
|
||||
const val LINK_PREVIEWS = "link_previews"
|
||||
const val SCREEN_LOCK_TIMEOUT = "screen_lock_timeout"
|
||||
const val DB_CYPHER_V4_UPGRADE = "db_cypher_v4_upgrade"
|
||||
const val DB_ROOM_MIGRATED = "db_room_migrated"
|
||||
const val PHONE_BOOK_INTEGRATION_LAST_RUN = "phone_book_integration_last_run"
|
||||
const val TYPING_STATUS = "typing_status"
|
||||
}
|
||||
}
|
|
@ -147,7 +147,6 @@ How to translate with transifex:
|
|||
<string name="nc_settings_screen_security_key" translatable="false">screen_security</string>
|
||||
<string name="nc_settings_incognito_keyboard_title">Incognito keyboard</string>
|
||||
<string name="nc_settings_incognito_keyboard_desc">Instructs keyboard to disable personalized learning (without guarantees)</string>
|
||||
<string name="nc_settings_incognito_keyboard_key" translatable="false">incognito_keyboard</string>
|
||||
<string name="nc_settings_read_privacy_key" translatable="false">read_privacy</string>
|
||||
<string name="nc_locked_tap_to_unlock">Tap to unlock</string>
|
||||
<string name="nc_locked">Locked</string>
|
||||
|
@ -510,7 +509,6 @@ How to translate with transifex:
|
|||
<string name="nc_voice_message_missing_audio_permission">Permission for audio recording is required</string>
|
||||
|
||||
<!-- Phonebook Integration -->
|
||||
<string name="nc_settings_phone_book_integration_key" translatable="false">phone_book_integration</string>
|
||||
<string name="nc_settings_phone_book_integration_desc">Match contacts based on phone number to integrate Talk shortcut into system contacts app</string>
|
||||
<string name="nc_settings_phone_book_integration_title">Phone number integration</string>
|
||||
<string name="nc_settings_phone_book_integration_phone_number_dialog_title">Phone number</string>
|
||||
|
|
Loading…
Reference in a new issue