From 3fe2246473770e5f58666a6b6fadd5ece9d9f1d0 Mon Sep 17 00:00:00 2001 From: cketti Date: Thu, 5 Apr 2018 23:59:08 +0200 Subject: [PATCH 1/4] Add new "general settings" Activity --- gradle.properties | 4 +- k9mail/build.gradle | 4 + k9mail/src/debug/res/values/app-specific.xml | 4 + k9mail/src/main/AndroidManifest.xml | 4 + .../fsck/k9/activity/ColorPickerDialog.java | 2 +- .../com/fsck/k9/helper/NamedThreadFactory.kt | 9 + .../java/com/fsck/k9/ui/FragmentExtras.kt | 27 ++ .../com/fsck/k9/ui/settings/KoinModule.kt | 9 + .../fsck/k9/ui/settings/PreferenceExtras.kt | 11 + .../com/fsck/k9/ui/settings/SettingsAction.kt | 4 +- .../general/GeneralSettingsActivity.kt | 61 +++ .../general/GeneralSettingsDataStore.kt | 257 ++++++++++++ .../general/GeneralSettingsFragment.kt | 127 ++++++ .../ui/settings/general/LanguagePreference.kt | 39 ++ .../src/main/res/layout/general_settings.xml | 5 + ...ialog.xml => holo_color_picker_dialog.xml} | 0 k9mail/src/main/res/values/app-specific.xml | 4 + k9mail/src/main/res/values/arrays.xml | 45 +++ k9mail/src/main/res/values/themes.xml | 2 + k9mail/src/main/res/xml/general_settings.xml | 374 ++++++++++++++++++ 20 files changed, 986 insertions(+), 6 deletions(-) create mode 100644 k9mail/src/debug/res/values/app-specific.xml create mode 100644 k9mail/src/main/java/com/fsck/k9/helper/NamedThreadFactory.kt create mode 100644 k9mail/src/main/java/com/fsck/k9/ui/FragmentExtras.kt create mode 100644 k9mail/src/main/java/com/fsck/k9/ui/settings/PreferenceExtras.kt create mode 100644 k9mail/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsActivity.kt create mode 100644 k9mail/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsDataStore.kt create mode 100644 k9mail/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsFragment.kt create mode 100644 k9mail/src/main/java/com/fsck/k9/ui/settings/general/LanguagePreference.kt create mode 100644 k9mail/src/main/res/layout/general_settings.xml rename k9mail/src/main/res/layout/{color_picker_dialog.xml => holo_color_picker_dialog.xml} (100%) create mode 100644 k9mail/src/main/res/values/app-specific.xml create mode 100644 k9mail/src/main/res/xml/general_settings.xml diff --git a/gradle.properties b/gradle.properties index b170f9cd1..af4a74583 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ kotlinVersion=1.2.31 androidCompileSdkVersion=27 androidBuildToolsVersion=27.0.3 -androidSupportLibraryVersion=27.0.2 +androidSupportLibraryVersion=27.1.1 timberVersion=4.5.1 koinVersion=0.9.1 @@ -10,5 +10,3 @@ junitVersion=4.12 mockitoVersion=2.18.0 okioVersion=1.14.0 truthVersion=0.35 - -android.enableAapt2=false diff --git a/k9mail/build.gradle b/k9mail/build.gradle index bfc565cbf..d2700ce6e 100644 --- a/k9mail/build.gradle +++ b/k9mail/build.gradle @@ -27,8 +27,12 @@ dependencies { implementation 'commons-io:commons-io:2.4' implementation "com.android.support:support-v4:${androidSupportLibraryVersion}" implementation "com.android.support:appcompat-v7:${androidSupportLibraryVersion}" + implementation "com.android.support:preference-v14:${androidSupportLibraryVersion}" + implementation 'com.takisoft.fix:preference-v7-datetimepicker:27.1.1.1' + implementation 'com.takisoft.fix:preference-v7-colorpicker:27.1.1.1' implementation "com.android.support:recyclerview-v7:${androidSupportLibraryVersion}" implementation "android.arch.lifecycle:extensions:1.1.0" + implementation 'androidx.core:core-ktx:0.3' implementation 'org.jsoup:jsoup:1.11.2' implementation 'de.cketti.library.changelog:ckchangelog:1.2.1' implementation 'com.github.bumptech.glide:glide:3.6.1' diff --git a/k9mail/src/debug/res/values/app-specific.xml b/k9mail/src/debug/res/values/app-specific.xml new file mode 100644 index 000000000..3bc22ec0b --- /dev/null +++ b/k9mail/src/debug/res/values/app-specific.xml @@ -0,0 +1,4 @@ + + + com.fsck.k9.debug + diff --git a/k9mail/src/main/AndroidManifest.xml b/k9mail/src/main/AndroidManifest.xml index 51f2f5075..8c9761656 100644 --- a/k9mail/src/main/AndroidManifest.xml +++ b/k9mail/src/main/AndroidManifest.xml @@ -303,6 +303,10 @@ android:name=".ui.settings.AboutActivity" android:label="@string/about_action" /> + + diff --git a/k9mail/src/main/java/com/fsck/k9/activity/ColorPickerDialog.java b/k9mail/src/main/java/com/fsck/k9/activity/ColorPickerDialog.java index 5b1c27c27..9ecd5ee0c 100644 --- a/k9mail/src/main/java/com/fsck/k9/activity/ColorPickerDialog.java +++ b/k9mail/src/main/java/com/fsck/k9/activity/ColorPickerDialog.java @@ -38,7 +38,7 @@ public class ColorPickerDialog extends AlertDialog { mColorChangedListener = listener; @SuppressLint("InflateParams") - View view = LayoutInflater.from(context).inflate(R.layout.color_picker_dialog, null); + View view = LayoutInflater.from(context).inflate(R.layout.holo_color_picker_dialog, null); mColorPicker = (ColorPicker) view.findViewById(R.id.color_picker); mColorPicker.setColor(color); diff --git a/k9mail/src/main/java/com/fsck/k9/helper/NamedThreadFactory.kt b/k9mail/src/main/java/com/fsck/k9/helper/NamedThreadFactory.kt new file mode 100644 index 000000000..265ea4ccc --- /dev/null +++ b/k9mail/src/main/java/com/fsck/k9/helper/NamedThreadFactory.kt @@ -0,0 +1,9 @@ +package com.fsck.k9.helper + +import java.util.concurrent.ThreadFactory + +class NamedThreadFactory(private val threadNamePrefix: String) : ThreadFactory { + var counter: Int = 0 + + override fun newThread(runnable: Runnable) = Thread(runnable, "$threadNamePrefix-${ counter++ }") +} diff --git a/k9mail/src/main/java/com/fsck/k9/ui/FragmentExtras.kt b/k9mail/src/main/java/com/fsck/k9/ui/FragmentExtras.kt new file mode 100644 index 000000000..33acb6242 --- /dev/null +++ b/k9mail/src/main/java/com/fsck/k9/ui/FragmentExtras.kt @@ -0,0 +1,27 @@ +package com.fsck.k9.ui + +import android.support.v4.app.Fragment +import android.support.v4.app.FragmentActivity +import android.support.v4.app.FragmentTransaction +import androidx.core.os.bundleOf + +inline fun FragmentActivity.fragmentTransaction(crossinline block: FragmentTransaction.() -> Unit) { + with(supportFragmentManager.beginTransaction()) { + block() + commit() + } +} + +inline fun FragmentActivity.fragmentTransactionWithBackStack( + name: String? = null, + crossinline block: FragmentTransaction.() -> Unit +) { + fragmentTransaction { + block() + addToBackStack(name) + } +} + +fun Fragment.withArguments(vararg argumentPairs: Pair) = apply { + arguments = bundleOf(*argumentPairs) +} diff --git a/k9mail/src/main/java/com/fsck/k9/ui/settings/KoinModule.kt b/k9mail/src/main/java/com/fsck/k9/ui/settings/KoinModule.kt index 091264672..ce0885b6d 100644 --- a/k9mail/src/main/java/com/fsck/k9/ui/settings/KoinModule.kt +++ b/k9mail/src/main/java/com/fsck/k9/ui/settings/KoinModule.kt @@ -1,10 +1,19 @@ package com.fsck.k9.ui.settings +import com.fsck.k9.helper.FileBrowserHelper +import com.fsck.k9.helper.NamedThreadFactory import com.fsck.k9.ui.account.AccountsLiveData +import com.fsck.k9.ui.settings.general.GeneralSettingsDataStore import org.koin.android.architecture.ext.viewModel import org.koin.dsl.module.applicationContext +import java.util.concurrent.Executors val settingsUiModule = applicationContext { bean { AccountsLiveData(get()) } viewModel { SettingsViewModel(get()) } + bean { FileBrowserHelper.getInstance() } + bean { GeneralSettingsDataStore(get(), get(), get("GeneralSettingsExecutor")) } + bean("GeneralSettingsExecutor") { + Executors.newSingleThreadExecutor(NamedThreadFactory("GeneralSettingsDataStore")) + } } diff --git a/k9mail/src/main/java/com/fsck/k9/ui/settings/PreferenceExtras.kt b/k9mail/src/main/java/com/fsck/k9/ui/settings/PreferenceExtras.kt new file mode 100644 index 000000000..4fb7b1091 --- /dev/null +++ b/k9mail/src/main/java/com/fsck/k9/ui/settings/PreferenceExtras.kt @@ -0,0 +1,11 @@ +package com.fsck.k9.ui.settings + +import android.support.v7.preference.Preference + + +inline fun Preference.onClick(crossinline action: () -> Unit) = setOnPreferenceClickListener { + action() + true +} + +fun Preference.remove() = parent?.removePreference(this) diff --git a/k9mail/src/main/java/com/fsck/k9/ui/settings/SettingsAction.kt b/k9mail/src/main/java/com/fsck/k9/ui/settings/SettingsAction.kt index 7b20a64a5..d65d784b8 100644 --- a/k9mail/src/main/java/com/fsck/k9/ui/settings/SettingsAction.kt +++ b/k9mail/src/main/java/com/fsck/k9/ui/settings/SettingsAction.kt @@ -2,12 +2,12 @@ package com.fsck.k9.ui.settings import android.app.Activity import com.fsck.k9.activity.setup.AccountSetupBasics -import com.fsck.k9.activity.setup.Prefs +import com.fsck.k9.ui.settings.general.GeneralSettingsActivity internal enum class SettingsAction { GENERAL_SETTINGS { override fun execute(activity: Activity) { - Prefs.actionPrefs(activity) + GeneralSettingsActivity.start(activity) } }, ADD_ACCOUNT { diff --git a/k9mail/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsActivity.kt b/k9mail/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsActivity.kt new file mode 100644 index 000000000..7a40ffe95 --- /dev/null +++ b/k9mail/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsActivity.kt @@ -0,0 +1,61 @@ +package com.fsck.k9.ui.settings.general + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.support.v7.preference.PreferenceFragmentCompat +import android.support.v7.preference.PreferenceFragmentCompat.OnPreferenceStartScreenCallback +import android.support.v7.preference.PreferenceScreen +import android.view.MenuItem +import com.fsck.k9.R +import com.fsck.k9.activity.K9Activity +import com.fsck.k9.ui.fragmentTransaction +import com.fsck.k9.ui.fragmentTransactionWithBackStack + +class GeneralSettingsActivity : K9Activity(), OnPreferenceStartScreenCallback { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.general_settings) + + initializeActionBar() + + if (savedInstanceState == null) { + fragmentTransaction { + add(R.id.generalSettingsContainer, GeneralSettingsFragment.create()) + } + } + } + + private fun initializeActionBar() { + val actionBar = supportActionBar ?: throw RuntimeException("getSupportActionBar() == null") + actionBar.setDisplayHomeAsUpEnabled(true) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + if (item.itemId == android.R.id.home) { + onBackPressed() + return true + } + + return super.onOptionsItemSelected(item) + } + + override fun onPreferenceStartScreen( + caller: PreferenceFragmentCompat, preferenceScreen: PreferenceScreen + ): Boolean { + fragmentTransactionWithBackStack { + replace(R.id.generalSettingsContainer, GeneralSettingsFragment.create(preferenceScreen.key)) + } + + return true + } + + + companion object { + fun start(context: Context) { + val intent = Intent(context, GeneralSettingsActivity::class.java) + context.startActivity(intent) + } + } +} diff --git a/k9mail/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsDataStore.kt b/k9mail/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsDataStore.kt new file mode 100644 index 000000000..47fed5c09 --- /dev/null +++ b/k9mail/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsDataStore.kt @@ -0,0 +1,257 @@ +package com.fsck.k9.ui.settings.general + +import android.content.Context +import android.support.v4.app.FragmentActivity +import android.support.v7.preference.PreferenceDataStore +import com.fsck.k9.K9 +import com.fsck.k9.K9.Theme +import com.fsck.k9.Preferences +import com.fsck.k9.service.MailService +import java.util.concurrent.ExecutorService + +class GeneralSettingsDataStore( + private val context: Context, + private val preferences: Preferences, + private val executorService: ExecutorService +) : PreferenceDataStore() { + var activity: FragmentActivity? = null + + override fun getBoolean(key: String, defValue: Boolean): Boolean { + return when (key) { + "fixed_message_view_theme" -> K9.useFixedMessageViewTheme() + "animations" -> K9.showAnimations() + "measure_accounts" -> K9.measureAccounts() + "count_search" -> K9.countSearchMessages() + "hide_special_accounts" -> K9.isHideSpecialAccounts() + "folderlist_wrap_folder_name" -> K9.wrapFolderNames() + "messagelist_stars" -> K9.messageListStars() + "messagelist_checkboxes" -> K9.messageListCheckboxes() + "messagelist_show_correspondent_names" -> K9.showCorrespondentNames() + "messagelist_sender_above_subject" -> K9.messageListSenderAboveSubject() + "messagelist_show_contact_name" -> K9.showContactName() + "messagelist_change_contact_name_color" -> K9.changeContactNameColor() + "messagelist_show_contact_picture" -> K9.showContactPicture() + "messagelist_colorize_missing_contact_pictures" -> K9.isColorizeMissingContactPictures() + "messagelist_background_as_unread_indicator" -> K9.useBackgroundAsUnreadIndicator() + "threaded_view" -> K9.isThreadedViewEnabled() + "messageview_fixedwidth_font" -> K9.messageViewFixedWidthFont() + "messageview_autofit_width" -> K9.autofitWidth() + "start_integrated_inbox" -> K9.startIntegratedInbox() + "gestures" -> K9.gesturesEnabled() + "messageview_return_to_list" -> K9.messageViewReturnToList() + "messageview_show_next" -> K9.messageViewShowNext() + "quiet_time_enabled" -> K9.getQuietTimeEnabled() + "disable_notifications_during_quiet_time" -> K9.isNotificationDuringQuietTimeEnabled() + "privacy_hide_useragent" -> K9.hideUserAgent() + "privacy_hide_timezone" -> K9.hideTimeZone() + "privacy_hide_hostname_when_connecting" -> K9.hideHostnameWhenConnecting() + "debug_logging" -> K9.isDebug() + "sensitive_logging" -> K9.DEBUG_SENSITIVE + else -> defValue + } + } + + override fun putBoolean(key: String, value: Boolean) { + when (key) { + "fixed_message_view_theme" -> K9.setUseFixedMessageViewTheme(value) + "animations" -> K9.setAnimations(value) + "measure_accounts" -> K9.setMeasureAccounts(value) + "count_search" -> K9.setCountSearchMessages(value) + "hide_special_accounts" -> K9.setHideSpecialAccounts(value) + "folderlist_wrap_folder_name" -> K9.setWrapFolderNames(value) + "messagelist_stars" -> K9.setMessageListStars(value) + "messagelist_checkboxes" -> K9.setMessageListCheckboxes(value) + "messagelist_show_correspondent_names" -> K9.setShowCorrespondentNames(value) + "messagelist_sender_above_subject" -> K9.setMessageListSenderAboveSubject(value) + "messagelist_show_contact_name" -> K9.setShowContactName(value) + "messagelist_change_contact_name_color" -> K9.setChangeContactNameColor(value) + "messagelist_show_contact_picture" -> K9.setShowContactPicture(value) + "messagelist_colorize_missing_contact_pictures" -> K9.setColorizeMissingContactPictures(value) + "messagelist_background_as_unread_indicator" -> K9.setUseBackgroundAsUnreadIndicator(value) + "threaded_view" -> K9.setThreadedViewEnabled(value) + "messageview_fixedwidth_font" -> K9.setMessageViewFixedWidthFont(value) + "messageview_autofit_width" -> K9.setAutofitWidth(value) + "start_integrated_inbox" -> K9.setStartIntegratedInbox(value) + "gestures" -> K9.setGesturesEnabled(value) + "messageview_return_to_list" -> K9.setMessageViewReturnToList(value) + "messageview_show_next" -> K9.setMessageViewShowNext(value) + "quiet_time_enabled" -> K9.setQuietTimeEnabled(value) + "disable_notifications_during_quiet_time" -> K9.setNotificationDuringQuietTimeEnabled(value) + "privacy_hide_useragent" -> K9.setHideUserAgent(value) + "privacy_hide_timezone" -> K9.setHideTimeZone(value) + "privacy_hide_hostname_when_connecting" -> K9.hideHostnameWhenConnecting() + "debug_logging" -> K9.setDebug(value) + "sensitive_logging" -> K9.DEBUG_SENSITIVE = value + else -> return + } + + saveSettings() + } + + override fun getInt(key: String?, defValue: Int): Int { + return when (key) { + "messagelist_contact_name_color" -> K9.getContactNameColor() + else -> defValue + } + } + + override fun putInt(key: String?, value: Int) { + when (key) { + "messagelist_contact_name_color" -> K9.setContactNameColor(value) + else -> return + } + + saveSettings() + } + + override fun getString(key: String, defValue: String?): String? { + return when (key) { + "language" -> K9.getK9Language() + "theme" -> themeToString(K9.getK9Theme()) + "fixed_message_view_theme" -> themeToString(K9.getK9MessageViewThemeSetting()) + "message_compose_theme" -> themeToString(K9.getK9ComposerThemeSetting()) + "messageViewTheme" -> themeToString(K9.getK9MessageViewThemeSetting()) + "messagelist_preview_lines" -> K9.messageListPreviewLines().toString() + "splitview_mode" -> K9.getSplitViewMode().name + "notification_quick_delete" -> K9.getNotificationQuickDeleteBehaviour().name + "lock_screen_notification_visibility" -> K9.getLockScreenNotificationVisibility().name + "background_ops" -> K9.getBackgroundOps().name + "notification_hide_subject" -> K9.getNotificationHideSubject().name + "attachment_default_path" -> K9.getAttachmentDefaultPath() + "quiet_time_starts" -> K9.getQuietTimeStarts() + "quiet_time_ends" -> K9.getQuietTimeEnds() + else -> defValue + } + } + + override fun putString(key: String, value: String?) { + if (value == null) return + + when (key) { + "language" -> setLanguage(value) + "theme" -> setTheme(value) + "fixed_message_view_theme" -> K9.setK9MessageViewThemeSetting(stringToTheme(value)) + "message_compose_theme" -> K9.setK9ComposerThemeSetting(stringToTheme(value)) + "messageViewTheme" -> K9.setK9MessageViewThemeSetting(stringToTheme(value)) + "messagelist_preview_lines" -> K9.setMessageListPreviewLines(value.toInt()) + "splitview_mode" -> K9.setSplitViewMode(K9.SplitViewMode.valueOf(value)) + "notification_quick_delete" -> K9.setNotificationQuickDeleteBehaviour(K9.NotificationQuickDelete.valueOf(value)) + "lock_screen_notification_visibility" -> K9.setLockScreenNotificationVisibility(K9.LockScreenNotificationVisibility.valueOf(value)) + "background_ops" -> setBackgroundOps(value) + "notification_hide_subject" -> K9.setNotificationHideSubject(K9.NotificationHideSubject.valueOf(value)) + "attachment_default_path" -> K9.setAttachmentDefaultPath(value) + "quiet_time_starts" -> K9.setQuietTimeStarts(value) + "quiet_time_ends" -> K9.setQuietTimeEnds(value) + else -> return + } + + saveSettings() + } + + override fun getStringSet(key: String, defValues: Set?): Set? { + return when (key) { + "confirm_actions" -> { + mutableSetOf().apply { + if (K9.confirmDelete()) add("delete") + if (K9.confirmDeleteStarred()) add("delete_starred") + if (K9.confirmDeleteFromNotification()) add("delete_notif") + if (K9.confirmSpam()) add("spam") + if (K9.confirmDiscardMessage()) add("discard") + if (K9.confirmMarkAllRead()) add("mark_all_read") + } + } + "messageview_visible_refile_actions" -> { + mutableSetOf().apply { + if (K9.isMessageViewDeleteActionVisible()) add("delete") + if (K9.isMessageViewArchiveActionVisible()) add("archive") + if (K9.isMessageViewMoveActionVisible()) add("move") + if (K9.isMessageViewCopyActionVisible()) add("copy") + if (K9.isMessageViewSpamActionVisible()) add("spam") + } + } + "volume_navigation" -> { + mutableSetOf().apply { + if (K9.useVolumeKeysForNavigationEnabled()) add("message") + if (K9.useVolumeKeysForListNavigationEnabled()) add("list") + } + } + else -> defValues + } + } + + override fun putStringSet(key: String, values: MutableSet?) { + val checkedValues = values ?: emptySet() + when (key) { + "confirm_actions" -> { + K9.setConfirmDelete("delete" in checkedValues) + K9.setConfirmDeleteStarred("delete_starred" in checkedValues) + K9.setConfirmDeleteFromNotification("delete_notif" in checkedValues) + K9.setConfirmSpam("spam" in checkedValues) + K9.setConfirmDiscardMessage("discard" in checkedValues) + K9.setConfirmMarkAllRead("mark_all_read" in checkedValues) + } + "messageview_visible_refile_actions" -> { + K9.setMessageViewDeleteActionVisible("delete" in checkedValues) + K9.setMessageViewArchiveActionVisible("archive" in checkedValues) + K9.setMessageViewMoveActionVisible("move" in checkedValues) + K9.setMessageViewCopyActionVisible("copy" in checkedValues) + K9.setMessageViewSpamActionVisible("spam" in checkedValues) + } + "volume_navigation" -> { + K9.setUseVolumeKeysForNavigation("message" in checkedValues) + K9.setUseVolumeKeysForListNavigation("list" in checkedValues) + } + else -> return + } + + saveSettings() + } + + private fun saveSettings() { + val editor = preferences.storage.edit() + K9.save(editor) + + executorService.execute { + editor.commit() + } + } + + private fun setTheme(value: String?) { + K9.setK9Theme(stringToTheme(value)) + recreateActivity() + } + + private fun setLanguage(language: String?) { + K9.setK9Language(language) + recreateActivity() + } + + private fun themeToString(theme: Theme) = when (theme) { + Theme.LIGHT -> "light" + Theme.DARK -> "dark" + Theme.USE_GLOBAL -> "global" + } + + private fun stringToTheme(theme: String?) = when (theme) { + "light" -> Theme.LIGHT + "dark" -> Theme.DARK + "global" -> Theme.USE_GLOBAL + else -> throw AssertionError() + } + + private fun setBackgroundOps(value: String) { + val newBackgroundOps = K9.BACKGROUND_OPS.valueOf(value) + if (newBackgroundOps != K9.getBackgroundOps()) { + K9.setBackgroundOps(value) + resetMailService() + } + } + + private fun resetMailService() { + MailService.actionReset(context, null) + } + + private fun recreateActivity() { + activity?.recreate() + } +} diff --git a/k9mail/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsFragment.kt b/k9mail/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsFragment.kt new file mode 100644 index 000000000..67ee400fa --- /dev/null +++ b/k9mail/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsFragment.kt @@ -0,0 +1,127 @@ +package com.fsck.k9.ui.settings.general + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import android.support.v14.preference.MultiSelectListPreference +import android.support.v7.preference.Preference +import com.fsck.k9.R +import com.fsck.k9.helper.FileBrowserHelper +import com.fsck.k9.notification.NotificationController +import com.fsck.k9.ui.settings.onClick +import com.fsck.k9.ui.settings.remove +import com.fsck.k9.ui.withArguments +import com.takisoft.fix.support.v7.preference.PreferenceFragmentCompat +import org.koin.android.ext.android.inject +import java.io.File + +class GeneralSettingsFragment : PreferenceFragmentCompat() { + private val dataStore: GeneralSettingsDataStore by inject() + private val fileBrowserHelper: FileBrowserHelper by inject() + + private lateinit var attachmentDefaultPathPreference: Preference + + + override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) { + preferenceManager.preferenceDataStore = dataStore + + setPreferencesFromResource(R.xml.general_settings, rootKey) + + initializeAttachmentDefaultPathPreference() + initializeStartInUnifiedInbox() + initializeConfirmActions() + initializeLockScreenNotificationVisibility() + initializeNotificationQuickDelete() + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + activity?.title = preferenceScreen.title + dataStore.activity = activity + } + + private fun initializeAttachmentDefaultPathPreference() { + findPreference(PREFERENCE_ATTACHMENT_DEFAULT_PATH)?.apply { + attachmentDefaultPathPreference = this + + summary = attachmentDefaultPath() + onClick { + fileBrowserHelper.showFileBrowserActivity(this@GeneralSettingsFragment, + File(attachmentDefaultPath()), REQUEST_PICK_DIRECTORY, + object : FileBrowserHelper.FileBrowserFailOverCallback { + override fun onPathEntered(path: String) { + setAttachmentDefaultPath(path) + } + + override fun onCancel() = Unit + } + ) + } + } + } + + private fun initializeStartInUnifiedInbox() { + findPreference(PREFERENCE_START_IN_UNIFIED_INBOX)?.apply { + if (hideSpecialAccounts()) { + isEnabled = false + } + } + } + + private fun initializeConfirmActions() { + val notificationActionsSupported = NotificationController.platformSupportsExtendedNotifications() + if (!notificationActionsSupported) { + (findPreference(PREFERENCE_CONFIRM_ACTIONS) as? MultiSelectListPreference)?.apply { + val deleteIndex = entryValues.indexOf(CONFIRM_ACTION_DELETE_FROM_NOTIFICATION) + entries = entries.filterIndexed { index, _ -> index != deleteIndex }.toTypedArray() + entryValues = entryValues.filterIndexed { index, _ -> index != deleteIndex }.toTypedArray() + } + } + } + + private fun initializeLockScreenNotificationVisibility() { + val lockScreenNotificationsSupported = NotificationController.platformSupportsLockScreenNotifications() + if (!lockScreenNotificationsSupported) { + findPreference(PREFERENCE_LOCK_SCREEN_NOTIFICATION_VISIBILITY)?.apply { remove() } + } + } + + private fun initializeNotificationQuickDelete() { + val notificationActionsSupported = NotificationController.platformSupportsExtendedNotifications() + if (!notificationActionsSupported) { + findPreference(PREFERENCE_NOTIFICATION_QUICK_DELETE)?.apply { remove() } + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) { + if (requestCode == REQUEST_PICK_DIRECTORY && resultCode == Activity.RESULT_OK && result != null) { + result.data?.path?.let { + setAttachmentDefaultPath(it) + } + } + } + + private fun attachmentDefaultPath() = dataStore.getString(PREFERENCE_ATTACHMENT_DEFAULT_PATH, "") + + private fun setAttachmentDefaultPath(path: String) { + attachmentDefaultPathPreference.summary = path + dataStore.putString(PREFERENCE_ATTACHMENT_DEFAULT_PATH, path) + } + + private fun hideSpecialAccounts() = dataStore.getBoolean(PREFERENCE_HIDE_SPECIAL_ACCOUNTS, false) + + + companion object { + private const val REQUEST_PICK_DIRECTORY = 1 + private const val PREFERENCE_ATTACHMENT_DEFAULT_PATH = "attachment_default_path" + private const val PREFERENCE_START_IN_UNIFIED_INBOX = "start_integrated_inbox" + private const val PREFERENCE_HIDE_SPECIAL_ACCOUNTS = "hide_special_accounts" + private const val PREFERENCE_CONFIRM_ACTIONS = "confirm_actions" + private const val PREFERENCE_LOCK_SCREEN_NOTIFICATION_VISIBILITY = "lock_screen_notification_visibility" + private const val PREFERENCE_NOTIFICATION_QUICK_DELETE = "notification_quick_delete" + private const val CONFIRM_ACTION_DELETE_FROM_NOTIFICATION = "delete_notif" + + fun create(rootKey: String? = null) = GeneralSettingsFragment().withArguments( + PreferenceFragmentCompat.ARG_PREFERENCE_ROOT to rootKey) + } +} diff --git a/k9mail/src/main/java/com/fsck/k9/ui/settings/general/LanguagePreference.kt b/k9mail/src/main/java/com/fsck/k9/ui/settings/general/LanguagePreference.kt new file mode 100644 index 000000000..b99df7ae2 --- /dev/null +++ b/k9mail/src/main/java/com/fsck/k9/ui/settings/general/LanguagePreference.kt @@ -0,0 +1,39 @@ +package com.fsck.k9.ui.settings.general + + +import android.annotation.SuppressLint +import android.content.Context +import android.support.v4.content.res.TypedArrayUtils +import android.support.v7.preference.ListPreference +import android.util.AttributeSet +import com.fsck.k9.R + + +class LanguagePreference +@JvmOverloads +@SuppressLint("RestrictedApi") +constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = TypedArrayUtils.getAttr(context, + android.support.v7.preference.R.attr.dialogPreferenceStyle, + android.R.attr.dialogPreferenceStyle), + defStyleRes: Int = 0 +) : ListPreference(context, attrs, defStyleAttr, defStyleRes ) { + + init { + val supportedLanguages = context.resources.getStringArray(R.array.supported_languages).toSet() + + val newEntries = mutableListOf() + val newEntryValues = mutableListOf() + entryValues.forEachIndexed { index, language -> + if (language in supportedLanguages) { + newEntries.add(entries[index]) + newEntryValues.add(entryValues[index]) + } + } + + entries = newEntries.toTypedArray() + entryValues = newEntryValues.toTypedArray() + } +} diff --git a/k9mail/src/main/res/layout/general_settings.xml b/k9mail/src/main/res/layout/general_settings.xml new file mode 100644 index 000000000..23638c59a --- /dev/null +++ b/k9mail/src/main/res/layout/general_settings.xml @@ -0,0 +1,5 @@ + + diff --git a/k9mail/src/main/res/layout/color_picker_dialog.xml b/k9mail/src/main/res/layout/holo_color_picker_dialog.xml similarity index 100% rename from k9mail/src/main/res/layout/color_picker_dialog.xml rename to k9mail/src/main/res/layout/holo_color_picker_dialog.xml diff --git a/k9mail/src/main/res/values/app-specific.xml b/k9mail/src/main/res/values/app-specific.xml new file mode 100644 index 000000000..448f15fe9 --- /dev/null +++ b/k9mail/src/main/res/values/app-specific.xml @@ -0,0 +1,4 @@ + + + com.fsck.k9 + diff --git a/k9mail/src/main/res/values/arrays.xml b/k9mail/src/main/res/values/arrays.xml index 997da075c..188f56740 100644 --- a/k9mail/src/main/res/values/arrays.xml +++ b/k9mail/src/main/res/values/arrays.xml @@ -779,4 +779,49 @@ NEVER WHEN_IN_LANDSCAPE + + + @string/global_settings_confirm_action_delete + @string/global_settings_confirm_action_delete_starred + @string/global_settings_confirm_action_delete_notif + @string/global_settings_confirm_action_spam + @string/global_settings_confirm_menu_discard + @string/global_settings_confirm_menu_mark_all_read + + + + delete + delete_starred + delete_notif + spam + discard + mark_all_read + + + + @string/delete_action + @string/archive_action + @string/move_action + @string/copy_action + @string/spam_action + + + + delete + archive + move + copy + spam + + + + @string/volume_navigation_message + @string/volume_navigation_list + + + + message + list + + diff --git a/k9mail/src/main/res/values/themes.xml b/k9mail/src/main/res/values/themes.xml index 2f4c83f5d..27e08885b 100644 --- a/k9mail/src/main/res/values/themes.xml +++ b/k9mail/src/main/res/values/themes.xml @@ -10,6 +10,7 @@