1
0
Fork 0
fenix/app/src/main/java/org/mozilla/fenix/theme/ThemeManager.kt

124 lines
4.4 KiB
Kotlin

/* 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/. */
package org.mozilla.fenix.theme
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color
import android.os.Build
import android.os.Build.VERSION.SDK_INT
import android.util.TypedValue
import android.view.View
import android.view.Window
import androidx.annotation.StyleRes
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.ext.getColorFromAttr
abstract class ThemeManager {
abstract var currentTheme: BrowsingMode
/**
* Returns the style resource corresponding to the [currentTheme].
*/
@get:StyleRes
val currentThemeResource get() = when (currentTheme) {
BrowsingMode.Normal -> R.style.NormalTheme
BrowsingMode.Private -> R.style.PrivateTheme
}
/**
* Handles status bar theme change since the window does not dynamically recreate
*/
fun applyStatusBarTheme(activity: Activity) = applyStatusBarTheme(activity.window, activity)
fun applyStatusBarTheme(window: Window, context: Context) {
when (currentTheme) {
BrowsingMode.Normal -> {
when (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_UNDEFINED, // We assume light here per Android doc's recommendation
Configuration.UI_MODE_NIGHT_NO -> {
updateLightSystemBars(window, context)
}
Configuration.UI_MODE_NIGHT_YES -> {
clearLightSystemBars(window)
updateNavigationBar(window, context)
}
}
}
BrowsingMode.Private -> {
clearLightSystemBars(window)
updateNavigationBar(window, context)
}
}
}
fun setActivityTheme(activity: Activity) {
activity.setTheme(currentThemeResource)
}
companion object {
fun resolveAttribute(attribute: Int, context: Context): Int {
val typedValue = TypedValue()
val theme = context.theme
theme.resolveAttribute(attribute, typedValue, true)
return typedValue.resourceId
}
private fun updateLightSystemBars(window: Window, context: Context) {
if (SDK_INT >= Build.VERSION_CODES.M) {
window.statusBarColor = context.getColorFromAttr(android.R.attr.statusBarColor)
window.decorView.systemUiVisibility =
window.decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else {
window.statusBarColor = Color.BLACK
}
if (SDK_INT >= Build.VERSION_CODES.O) {
// API level can display handle light navigation bar color
window.decorView.systemUiVisibility =
window.decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
updateNavigationBar(window, context)
}
}
private fun clearLightSystemBars(window: Window) {
if (SDK_INT >= Build.VERSION_CODES.M) {
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility and
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() and
View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv()
}
}
private fun updateNavigationBar(window: Window, context: Context) {
window.navigationBarColor = context.getColorFromAttr(R.attr.foundation)
}
}
}
class DefaultThemeManager(
currentTheme: BrowsingMode,
private val activity: Activity
) : ThemeManager() {
override var currentTheme: BrowsingMode = currentTheme
set(value) {
if (currentTheme != value) {
field = value
setActivityTheme(activity)
val intent = activity.intent ?: Intent().also { activity.intent = it }
intent.putExtra(HomeActivity.PRIVATE_BROWSING_MODE, value == BrowsingMode.Private)
activity.recreate()
}
}
}