diff --git a/app/src/main/java/com/etesync/syncadapter/EtebaseLocalCache.kt b/app/src/main/java/com/etesync/syncadapter/EtebaseLocalCache.kt index 036726ed..b51c2756 100644 --- a/app/src/main/java/com/etesync/syncadapter/EtebaseLocalCache.kt +++ b/app/src/main/java/com/etesync/syncadapter/EtebaseLocalCache.kt @@ -153,6 +153,7 @@ class EtebaseLocalCache private constructor(context: Context, username: String) } } + // FIXME: If we ever cache this we need to cache bust on changePassword fun getEtebase(context: Context, httpClient: OkHttpClient, settings: AccountSettings): Account { val client = Client.create(httpClient, settings.uri?.toString()) return Account.restore(client, settings.etebaseSession!!, null) diff --git a/app/src/main/java/com/etesync/syncadapter/ui/AccountSettingsActivity.kt b/app/src/main/java/com/etesync/syncadapter/ui/AccountSettingsActivity.kt index e190a5a5..ea8e8e3f 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/AccountSettingsActivity.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/AccountSettingsActivity.kt @@ -18,11 +18,11 @@ import android.provider.CalendarContract import android.text.TextUtils import android.view.MenuItem import androidx.core.app.NavUtils +import androidx.fragment.app.Fragment import androidx.loader.app.LoaderManager import androidx.loader.content.AsyncTaskLoader import androidx.loader.content.Loader import androidx.preference.* -import at.bitfire.ical4android.TaskProvider import at.bitfire.ical4android.TaskProvider.Companion.OPENTASK_PROVIDERS import com.etesync.syncadapter.* import com.etesync.syncadapter.Constants.KEY_ACCOUNT @@ -43,7 +43,8 @@ class AccountSettingsActivity : BaseActivity() { supportActionBar!!.setDisplayHomeAsUpEnabled(true) if (savedInstanceState == null) { - val frag = AccountSettingsFragment() + val settings = AccountSettings(this, account) + val frag: Fragment = if (settings.isLegacy) LegacyAccountSettingsFragment() else AccountSettingsFragment() frag.arguments = intent.extras supportFragmentManager.beginTransaction() .replace(android.R.id.content, frag) @@ -60,139 +61,226 @@ class AccountSettingsActivity : BaseActivity() { } else return false } +} - class AccountSettingsFragment : PreferenceFragmentCompat(), LoaderManager.LoaderCallbacks { - internal lateinit var account: Account +class AccountSettingsFragment() : PreferenceFragmentCompat(), LoaderManager.LoaderCallbacks { + internal lateinit var account: Account - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) - account = arguments?.getParcelable(KEY_ACCOUNT)!! + account = arguments?.getParcelable(KEY_ACCOUNT)!! - loaderManager.initLoader(0, arguments, this) - } + loaderManager.initLoader(0, arguments, this) + } - override fun onCreatePreferences(bundle: Bundle, s: String) { - addPreferencesFromResource(R.xml.settings_account) - } + override fun onCreatePreferences(bundle: Bundle, s: String) { + addPreferencesFromResource(R.xml.settings_account) + } - override fun onCreateLoader(id: Int, args: Bundle?): Loader { - return AccountSettingsLoader(context!!, args!!.getParcelable(KEY_ACCOUNT) as Account) - } + override fun onCreateLoader(id: Int, args: Bundle?): Loader { + return AccountSettingsLoader(context!!, args!!.getParcelable(KEY_ACCOUNT) as Account) + } - override fun onLoadFinished(loader: Loader, settings: AccountSettings?) { - if (settings == null) { - activity!!.finish() - return - } + override fun onLoadFinished(loader: Loader, settings: AccountSettings?) { + if (settings == null) { + activity!!.finish() + return + } + // Category: dashboard + val prefManageAccount = findPreference("manage_account") + prefManageAccount.onPreferenceClickListener = Preference.OnPreferenceClickListener { _ -> + WebViewActivity.openUrl(activity!!, Constants.dashboard.buildUpon().appendQueryParameter("email", account.name).build()) + true + } - // Category: dashboard - val prefManageAccount = findPreference("manage_account") - prefManageAccount.onPreferenceClickListener = Preference.OnPreferenceClickListener { _ -> - WebViewActivity.openUrl(activity!!, Constants.dashboard.buildUpon().appendQueryParameter("email", account.name).build()) - true - } + // Category: encryption + val prefEncryptionPassword = findPreference("password") + prefEncryptionPassword.onPreferenceClickListener = Preference.OnPreferenceClickListener { _ -> + startActivity(ChangeEncryptionPasswordActivity.newIntent(activity!!, account)) + true + } - // category: authentication - val prefPassword = findPreference("password") as EditTextPreference - prefPassword.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> - val credentials = if (newValue != null) LoginCredentials(settings.uri, account.name, newValue as String) else null - LoginCredentialsChangeFragment.newInstance(account, credentials!!).show(fragmentManager!!, null) + val prefSync = findPreference("sync_interval") as ListPreference + val syncInterval = settings.getSyncInterval(CalendarContract.AUTHORITY) // Calendar is the baseline interval + if (syncInterval != null) { + prefSync.value = syncInterval.toString() + if (syncInterval == AccountSettings.SYNC_INTERVAL_MANUALLY) + prefSync.setSummary(R.string.settings_sync_summary_manually) + else + prefSync.summary = getString(R.string.settings_sync_summary_periodically, prefSync.entry) + prefSync.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> + val newInterval = java.lang.Long.parseLong(newValue as String) + settings.setSyncInterval(App.addressBooksAuthority, newInterval) + settings.setSyncInterval(CalendarContract.AUTHORITY, newInterval) + OPENTASK_PROVIDERS.forEach { + settings.setSyncInterval(it.authority, newInterval) + } loaderManager.restartLoader(0, arguments, this@AccountSettingsFragment) false } + } else { + prefSync.isEnabled = false + prefSync.setSummary(R.string.settings_sync_summary_not_available) + } - // Category: encryption - val prefEncryptionPassword = findPreference("encryption_password") - prefEncryptionPassword.onPreferenceClickListener = Preference.OnPreferenceClickListener { _ -> - startActivity(ChangeEncryptionPasswordActivity.newIntent(activity!!, account)) - true - } + val prefWifiOnly = findPreference("sync_wifi_only") as SwitchPreferenceCompat + prefWifiOnly.isChecked = settings.syncWifiOnly + prefWifiOnly.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, wifiOnly -> + settings.setSyncWiFiOnly(wifiOnly as Boolean) + loaderManager.restartLoader(0, arguments, this@AccountSettingsFragment) + false + } - val prefSync = findPreference("sync_interval") as ListPreference - val syncInterval = settings.getSyncInterval(CalendarContract.AUTHORITY) // Calendar is the baseline interval - if (syncInterval != null) { - prefSync.value = syncInterval.toString() - if (syncInterval == AccountSettings.SYNC_INTERVAL_MANUALLY) - prefSync.setSummary(R.string.settings_sync_summary_manually) - else - prefSync.summary = getString(R.string.settings_sync_summary_periodically, prefSync.entry) - prefSync.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> - val newInterval = java.lang.Long.parseLong(newValue as String) - settings.setSyncInterval(App.addressBooksAuthority, newInterval) - settings.setSyncInterval(CalendarContract.AUTHORITY, newInterval) - OPENTASK_PROVIDERS.forEach { - settings.setSyncInterval(it.authority, newInterval) - } - loaderManager.restartLoader(0, arguments, this@AccountSettingsFragment) - false - } - } else { - prefSync.isEnabled = false - prefSync.setSummary(R.string.settings_sync_summary_not_available) - } + val prefWifiOnlySSID = findPreference("sync_wifi_only_ssid") as EditTextPreference + val onlySSID = settings.syncWifiOnlySSID + prefWifiOnlySSID.text = onlySSID + if (onlySSID != null) + prefWifiOnlySSID.summary = getString(R.string.settings_sync_wifi_only_ssid_on, onlySSID) + else + prefWifiOnlySSID.setSummary(R.string.settings_sync_wifi_only_ssid_off) + prefWifiOnlySSID.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> + val ssid = newValue as String + settings.syncWifiOnlySSID = if (!TextUtils.isEmpty(ssid)) ssid else null + loaderManager.restartLoader(0, arguments, this@AccountSettingsFragment) + false + } + } - val prefWifiOnly = findPreference("sync_wifi_only") as SwitchPreferenceCompat - prefWifiOnly.isChecked = settings.syncWifiOnly - prefWifiOnly.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, wifiOnly -> - settings.setSyncWiFiOnly(wifiOnly as Boolean) - loaderManager.restartLoader(0, arguments, this@AccountSettingsFragment) - false - } + override fun onLoaderReset(loader: Loader) {} - val prefWifiOnlySSID = findPreference("sync_wifi_only_ssid") as EditTextPreference - val onlySSID = settings.syncWifiOnlySSID - prefWifiOnlySSID.text = onlySSID - if (onlySSID != null) - prefWifiOnlySSID.summary = getString(R.string.settings_sync_wifi_only_ssid_on, onlySSID) - else - prefWifiOnlySSID.setSummary(R.string.settings_sync_wifi_only_ssid_off) - prefWifiOnlySSID.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> - val ssid = newValue as String - settings.syncWifiOnlySSID = if (!TextUtils.isEmpty(ssid)) ssid else null - loaderManager.restartLoader(0, arguments, this@AccountSettingsFragment) - false - } - } +} + + + +class LegacyAccountSettingsFragment : PreferenceFragmentCompat(), LoaderManager.LoaderCallbacks { + internal lateinit var account: Account - override fun onLoaderReset(loader: Loader) {} + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + account = arguments?.getParcelable(KEY_ACCOUNT)!! + + loaderManager.initLoader(0, arguments, this) } + override fun onCreatePreferences(bundle: Bundle, s: String) { + addPreferencesFromResource(R.xml.settings_account_legacy) + } - private class AccountSettingsLoader(context: Context, internal val account: Account) : AsyncTaskLoader(context), SyncStatusObserver { - internal lateinit var listenerHandle: Any + override fun onCreateLoader(id: Int, args: Bundle?): Loader { + return AccountSettingsLoader(context!!, args!!.getParcelable(KEY_ACCOUNT) as Account) + } - override fun onStartLoading() { - forceLoad() - listenerHandle = ContentResolver.addStatusChangeListener(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, this) + override fun onLoadFinished(loader: Loader, settings: AccountSettings?) { + if (settings == null) { + activity!!.finish() + return } - override fun onStopLoading() { - ContentResolver.removeStatusChangeListener(listenerHandle) + // Category: dashboard + val prefManageAccount = findPreference("manage_account") + prefManageAccount.onPreferenceClickListener = Preference.OnPreferenceClickListener { _ -> + WebViewActivity.openUrl(activity!!, Constants.dashboard.buildUpon().appendQueryParameter("email", account.name).build()) + true } - override fun abandon() { - onStopLoading() + // category: authentication + val prefPassword = findPreference("password") as EditTextPreference + prefPassword.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> + val credentials = if (newValue != null) LoginCredentials(settings.uri, account.name, newValue as String) else null + LoginCredentialsChangeFragment.newInstance(account, credentials!!).show(fragmentManager!!, null) + loaderManager.restartLoader(0, arguments, this@LegacyAccountSettingsFragment) + false } - override fun loadInBackground(): AccountSettings? { - val settings: AccountSettings - try { - settings = AccountSettings(context, account) - } catch (e: InvalidAccountException) { - return null - } + // Category: encryption + val prefEncryptionPassword = findPreference("encryption_password") + prefEncryptionPassword.onPreferenceClickListener = Preference.OnPreferenceClickListener { _ -> + startActivity(ChangeEncryptionPasswordActivity.newIntent(activity!!, account)) + true + } - return settings + val prefSync = findPreference("sync_interval") as ListPreference + val syncInterval = settings.getSyncInterval(CalendarContract.AUTHORITY) // Calendar is the baseline interval + if (syncInterval != null) { + prefSync.value = syncInterval.toString() + if (syncInterval == AccountSettings.SYNC_INTERVAL_MANUALLY) + prefSync.setSummary(R.string.settings_sync_summary_manually) + else + prefSync.summary = getString(R.string.settings_sync_summary_periodically, prefSync.entry) + prefSync.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> + val newInterval = java.lang.Long.parseLong(newValue as String) + settings.setSyncInterval(App.addressBooksAuthority, newInterval) + settings.setSyncInterval(CalendarContract.AUTHORITY, newInterval) + OPENTASK_PROVIDERS.forEach { + settings.setSyncInterval(it.authority, newInterval) + } + loaderManager.restartLoader(0, arguments, this@LegacyAccountSettingsFragment) + false + } + } else { + prefSync.isEnabled = false + prefSync.setSummary(R.string.settings_sync_summary_not_available) } - override fun onStatusChanged(which: Int) { - Logger.log.fine("Reloading account settings") - forceLoad() + val prefWifiOnly = findPreference("sync_wifi_only") as SwitchPreferenceCompat + prefWifiOnly.isChecked = settings.syncWifiOnly + prefWifiOnly.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, wifiOnly -> + settings.setSyncWiFiOnly(wifiOnly as Boolean) + loaderManager.restartLoader(0, arguments, this@LegacyAccountSettingsFragment) + false } + val prefWifiOnlySSID = findPreference("sync_wifi_only_ssid") as EditTextPreference + val onlySSID = settings.syncWifiOnlySSID + prefWifiOnlySSID.text = onlySSID + if (onlySSID != null) + prefWifiOnlySSID.summary = getString(R.string.settings_sync_wifi_only_ssid_on, onlySSID) + else + prefWifiOnlySSID.setSummary(R.string.settings_sync_wifi_only_ssid_off) + prefWifiOnlySSID.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> + val ssid = newValue as String + settings.syncWifiOnlySSID = if (!TextUtils.isEmpty(ssid)) ssid else null + loaderManager.restartLoader(0, arguments, this@LegacyAccountSettingsFragment) + false + } } + override fun onLoaderReset(loader: Loader) {} } + +private class AccountSettingsLoader(context: Context, internal val account: Account) : AsyncTaskLoader(context), SyncStatusObserver { + internal lateinit var listenerHandle: Any + + override fun onStartLoading() { + forceLoad() + listenerHandle = ContentResolver.addStatusChangeListener(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, this) + } + + override fun onStopLoading() { + ContentResolver.removeStatusChangeListener(listenerHandle) + } + + override fun abandon() { + onStopLoading() + } + + override fun loadInBackground(): AccountSettings? { + val settings: AccountSettings + try { + settings = AccountSettings(context, account) + } catch (e: InvalidAccountException) { + return null + } + + return settings + } + + override fun onStatusChanged(which: Int) { + Logger.log.fine("Reloading account settings") + forceLoad() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/etesync/syncadapter/ui/ChangeEncryptionPasswordActivity.kt b/app/src/main/java/com/etesync/syncadapter/ui/ChangeEncryptionPasswordActivity.kt index 983efee1..5b14cde2 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/ChangeEncryptionPasswordActivity.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/ChangeEncryptionPasswordActivity.kt @@ -15,6 +15,7 @@ import android.content.Intent import android.os.Bundle import android.view.View import androidx.appcompat.app.AlertDialog +import com.etebase.client.Client import com.etesync.syncadapter.AccountSettings import com.etesync.syncadapter.HttpClient import com.etesync.syncadapter.R @@ -53,7 +54,7 @@ open class ChangeEncryptionPasswordActivity : BaseActivity() { AlertDialog.Builder(this) .setTitle(R.string.wrong_encryption_password) .setIcon(R.drawable.ic_error_dark) - .setMessage(getString(R.string.wrong_encryption_password_content, e.localizedMessage)) + .setMessage(e.localizedMessage) .setPositiveButton(android.R.string.ok) { _, _ -> // dismiss }.show() @@ -62,6 +63,45 @@ open class ChangeEncryptionPasswordActivity : BaseActivity() { fun changePasswordDo(old_password: String, new_password: String) { val settings = AccountSettings(this, account) + if (settings.isLegacy) { + legacyChangePasswordDo(settings, old_password, new_password) + return + } + + doAsync { + val httpClient = HttpClient.sharedClient + + try { + Logger.log.info("Loging in with old password") + val client = Client.create(httpClient, settings.uri?.toString()) + val etebase = com.etebase.client.Account.login(client, account.name, old_password) + Logger.log.info("Login successful") + + etebase.changePassword(new_password) + + settings.etebaseSession = etebase.save(null) + + uiThread { + progress.dismiss() + AlertDialog.Builder(this@ChangeEncryptionPasswordActivity) + .setTitle(R.string.change_encryption_password_success_title) + .setMessage(R.string.change_encryption_password_success_body) + .setPositiveButton(android.R.string.ok) { _, _ -> + this@ChangeEncryptionPasswordActivity.finish() + }.show() + + requestSync(applicationContext, account) + } + } catch (e: Exception) { + uiThread { + changePasswordError(e) + } + return@doAsync + } + } + } + + fun legacyChangePasswordDo(settings: AccountSettings, old_password: String, new_password: String) { doAsync { val httpClient = HttpClient.Builder(this@ChangeEncryptionPasswordActivity, settings).setForeground(false).build().okHttpClient diff --git a/app/src/main/res/xml/settings_account.xml b/app/src/main/res/xml/settings_account.xml index fa996801..a8ffeddf 100644 --- a/app/src/main/res/xml/settings_account.xml +++ b/app/src/main/res/xml/settings_account.xml @@ -18,25 +18,12 @@ - - + - - - - - + /> + + + + + + + + + + + + + + + + + + + + + + + + + +