diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingThemePickerViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingThemePickerViewHolder.kt index f8bb568aa..8ae858d2a 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingThemePickerViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingThemePickerViewHolder.kt @@ -6,9 +6,14 @@ package org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding import android.content.Context import android.view.View +import androidx.appcompat.app.AppCompatDelegate import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.onboarding_section_header.view.* +import kotlinx.android.synthetic.main.onboarding_theme_picker.view.* import org.mozilla.fenix.R +import org.mozilla.fenix.ext.asActivity +import org.mozilla.fenix.ext.components +import org.mozilla.fenix.utils.Settings class OnboardingThemePickerViewHolder(private val view: View) : RecyclerView.ViewHolder(view) { @@ -19,4 +24,71 @@ class OnboardingThemePickerViewHolder(private val view: View) : RecyclerView.Vie companion object { const val LAYOUT_ID = R.layout.onboarding_theme_picker } + + init { + val radioLightTheme = view.theme_light_radio_button + val radioDarkTheme = view.theme_dark_radio_button + val radioFollowDeviceTheme = view.theme_automatic_radio_button + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { + radioFollowDeviceTheme?.key = R.string.pref_key_follow_device_theme + } else { + radioFollowDeviceTheme?.key = R.string.pref_key_auto_battery_theme + } + + radioLightTheme.addToRadioGroup(radioDarkTheme) + radioDarkTheme.addToRadioGroup(radioLightTheme) + + radioLightTheme.addToRadioGroup(radioFollowDeviceTheme) + radioDarkTheme.addToRadioGroup(radioFollowDeviceTheme) + + radioFollowDeviceTheme.addToRadioGroup(radioDarkTheme) + radioFollowDeviceTheme.addToRadioGroup(radioLightTheme) + + view.theme_dark_image.setOnClickListener { + radioDarkTheme.performClick() + } + + view.theme_light_image.setOnClickListener { + radioLightTheme.performClick() + } + + view.clickable_region_automatic.setOnClickListener { + radioFollowDeviceTheme.performClick() + } + + radioLightTheme.onClickListener { + setNewTheme(AppCompatDelegate.MODE_NIGHT_NO) + } + + radioDarkTheme.onClickListener { + setNewTheme(AppCompatDelegate.MODE_NIGHT_YES) + } + + radioFollowDeviceTheme.onClickListener { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { + setNewTheme(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) + } else { + setNewTheme(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY) + } + } + + with(Settings.getInstance(view.context)) { + when { + this.shouldFollowDeviceTheme -> radioFollowDeviceTheme.isChecked = true + this.shouldUseLightTheme -> radioLightTheme.isChecked = true + else -> radioDarkTheme.isChecked = true + } + } + } + + private fun setNewTheme(mode: Int) { + if (AppCompatDelegate.getDefaultNightMode() == mode) return + AppCompatDelegate.setDefaultNightMode(mode) + view.context?.asActivity()?.recreate() + view.context?.components?.core?.let { + it.engine.settings.preferredColorScheme = it.getPreferredColorScheme() + } + view.context?.components?.useCases?.sessionUseCases?.reload?.invoke() + } } diff --git a/app/src/main/java/org/mozilla/fenix/onboarding/OnboardingRadioButton.kt b/app/src/main/java/org/mozilla/fenix/onboarding/OnboardingRadioButton.kt new file mode 100644 index 000000000..7c8902703 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/onboarding/OnboardingRadioButton.kt @@ -0,0 +1,64 @@ +package org.mozilla.fenix.onboarding + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import android.content.Context +import android.util.AttributeSet +import android.widget.RadioButton +import org.mozilla.fenix.R +import org.mozilla.fenix.utils.Settings + +class OnboardingRadioButton : RadioButton { + private val radioGroups = mutableListOf() + private var clickListener: (() -> Unit)? = null + var key: Int = 0 + + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { + attrs.let { + context.theme.obtainStyledAttributes( + it, + R.styleable.OnboardingRadioButton, + 0, 0 + ).apply { + try { + key = getResourceId( + R.styleable.OnboardingRadioButton_onboardingKey, 0 + ) + } finally { + recycle() + } + } + } + } + + fun addToRadioGroup(radioButton: OnboardingRadioButton) { + radioGroups.add(radioButton) + } + + fun onClickListener(listener: (() -> Unit)) { + clickListener = listener + } + + init { + setOnClickListener { + updateRadioValue(true) + toggleRadioGroups() + clickListener?.invoke() + true + } + } + + private fun updateRadioValue(isChecked: Boolean) { + this.isChecked = isChecked + Settings.getInstance(context).preferences.edit().putBoolean(context.getString(key), isChecked) + .apply() + } + + private fun toggleRadioGroups() { + if (this.isChecked) { + radioGroups.forEach { it.updateRadioValue(false) } + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/settings/RadioButtonPreference.kt b/app/src/main/java/org/mozilla/fenix/settings/RadioButtonPreference.kt index 399aa4e0f..237cde361 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/RadioButtonPreference.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/RadioButtonPreference.kt @@ -4,17 +4,17 @@ package org.mozilla.fenix.settings -import android.view.View -import androidx.preference.PreferenceViewHolder -import android.widget.TextView import android.content.Context import android.content.res.TypedArray import android.text.TextUtils import android.util.AttributeSet +import android.view.View import android.widget.RadioButton +import android.widget.TextView import androidx.core.content.res.TypedArrayUtils import androidx.core.text.HtmlCompat import androidx.preference.Preference +import androidx.preference.PreferenceViewHolder import org.mozilla.fenix.R import org.mozilla.fenix.utils.Settings @@ -69,13 +69,13 @@ class RadioButtonPreference : Preference { private fun updateRadioValue(isChecked: Boolean) { persistBoolean(isChecked) radioButton.isChecked = isChecked - Settings.getInstance(summaryView.context).preferences.edit().putBoolean(key, isChecked) + Settings.getInstance(context).preferences.edit().putBoolean(key, isChecked) .apply() } private fun bindRadioButton(holder: PreferenceViewHolder) { radioButton = holder.findViewById(R.id.radio_button) as RadioButton - radioButton.isChecked = getPersistedBoolean(defaultValue) + radioButton.isChecked = Settings.getInstance(context).preferences.getBoolean(key, false) } private fun initDefaultValue(typedArray: TypedArray) { diff --git a/app/src/main/java/org/mozilla/fenix/settings/ThemeFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/ThemeFragment.kt index 2dd0127e0..e36c66e0d 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/ThemeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/ThemeFragment.kt @@ -98,6 +98,7 @@ class ThemeFragment : PreferenceFragmentCompat() { } private fun setNewTheme(mode: Int) { + if (AppCompatDelegate.getDefaultNightMode() == mode) return AppCompatDelegate.setDefaultNightMode(mode) activity?.recreate() with(requireComponents.core) { diff --git a/app/src/main/res/drawable-mdpi/onboarding_dark_theme.png b/app/src/main/res/drawable-mdpi/onboarding_dark_theme.png new file mode 100644 index 000000000..58fd05121 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/onboarding_dark_theme.png differ diff --git a/app/src/main/res/drawable-mdpi/onboarding_light_theme.png b/app/src/main/res/drawable-mdpi/onboarding_light_theme.png new file mode 100644 index 000000000..d2efde385 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/onboarding_light_theme.png differ diff --git a/app/src/main/res/drawable-xhdpi/onboarding_dark_theme.png b/app/src/main/res/drawable-xhdpi/onboarding_dark_theme.png new file mode 100644 index 000000000..baa6f0319 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/onboarding_dark_theme.png differ diff --git a/app/src/main/res/drawable-xhdpi/onboarding_light_theme.png b/app/src/main/res/drawable-xhdpi/onboarding_light_theme.png new file mode 100644 index 000000000..e23a3b4e8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/onboarding_light_theme.png differ diff --git a/app/src/main/res/drawable/onboarding_rounded_bottom_corners_ripple.xml b/app/src/main/res/drawable/onboarding_rounded_bottom_corners_ripple.xml new file mode 100644 index 000000000..1744473a8 --- /dev/null +++ b/app/src/main/res/drawable/onboarding_rounded_bottom_corners_ripple.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/rounded_ripple.xml b/app/src/main/res/drawable/rounded_ripple.xml new file mode 100644 index 000000000..2c2157760 --- /dev/null +++ b/app/src/main/res/drawable/rounded_ripple.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/onboarding_theme_picker.xml b/app/src/main/res/layout/onboarding_theme_picker.xml index be0475f94..7ee491c96 100644 --- a/app/src/main/res/layout/onboarding_theme_picker.xml +++ b/app/src/main/res/layout/onboarding_theme_picker.xml @@ -2,24 +2,168 @@ - + android:layout_marginBottom="16dp" + android:background="@drawable/onboarding_card_background_light" + android:paddingTop="16dp"> + + android:textAppearance="@style/HeaderTextStyle" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + - \ No newline at end of file + android:textAppearance="@style/Body14TextStyle" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/header_text" /> + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 3caf6afe5..cf0801024 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -32,4 +32,8 @@ + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index de330cdda..8bc85c3b3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -488,4 +488,15 @@ The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. Make text on websites larger or smaller Font Size + + + + + Automatic + + Adapts to your device settings + + Dark Theme + + Light Theme