diff options
Diffstat (limited to 'app/src/main/kotlin')
17 files changed, 114 insertions, 64 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt index 40333d25..059b2a0e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt @@ -26,6 +26,7 @@ import ca.allanwang.kau.logging.KL import ca.allanwang.kau.utils.buildIsLollipopAndUp import com.pitchedapps.frost.db.FrostDatabase import com.pitchedapps.frost.facebook.FbCookie +import com.pitchedapps.frost.injectors.ThemeProvider import com.pitchedapps.frost.prefs.Prefs import com.pitchedapps.frost.services.scheduleNotificationsFromPrefs import com.pitchedapps.frost.services.setupNotificationChannels @@ -58,7 +59,8 @@ class FrostApp : Application(), KoinComponent { FrostDatabase.module(), prefFactoryModule(), Prefs.module(), - FbCookie.module() + FbCookie.module(), + ThemeProvider.module() ) ) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt index 0cb037a5..e352b2fc 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt @@ -202,7 +202,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, } drawerWrapperBinding.mainContainer.addView(contentBinding.root) with(contentBinding) { - setFrostColors(prefs) { + setFrostColors { toolbar(toolbar) themeWindow = false header(appbar) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt index 54baa184..6067fa82 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt @@ -71,7 +71,7 @@ class DebugActivity : KauBaseActivity() { } setTitle(R.string.debug_frost) - setFrostColors(prefs) { + setFrostColors { toolbar(toolbar) } debugWebview.loadUrl(FbItem.FEED.url) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt index bcfd9c99..ea81bcde 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt @@ -222,7 +222,7 @@ class ImageActivity : KauBaseActivity() { loadError(e) } }) - setFrostColors(prefs) { + setFrostColors { themeWindow = false } dragHelper = ViewDragHelper.create(imageDrag, ViewDragCallback()).apply { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt index be53f2c2..601516de 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt @@ -80,7 +80,7 @@ class LoginActivity : BaseActivity() { setContentView(R.layout.activity_login) setSupportActionBar(toolbar) setTitle(R.string.kau_login) - setFrostColors(prefs) { + setFrostColors { toolbar(toolbar) } profileLoader = GlideApp.with(profile) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt index a0e3ae42..33215c7e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt @@ -67,7 +67,7 @@ class SelectorActivity : BaseActivity() { } } }) - setFrostColors(prefs) { + setFrostColors { text(text) background(container) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt index a016ca22..ee0cd669 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt @@ -43,6 +43,7 @@ import com.pitchedapps.frost.R import com.pitchedapps.frost.db.NotificationDao import com.pitchedapps.frost.enums.Support import com.pitchedapps.frost.facebook.FbCookie +import com.pitchedapps.frost.injectors.ThemeProvider import com.pitchedapps.frost.prefs.Prefs import com.pitchedapps.frost.settings.getAppearancePrefs import com.pitchedapps.frost.settings.getBehaviourPrefs @@ -73,6 +74,7 @@ class SettingsActivity : KPrefActivity() { val fbCookie: FbCookie by inject() val notifDao: NotificationDao by inject() val prefs: Prefs by inject() + val themeProvider: ThemeProvider by inject() private var resultFlag = Activity.RESULT_CANCELED diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/TabCustomizerActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/TabCustomizerActivity.kt index 11126803..589289ab 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/TabCustomizerActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/TabCustomizerActivity.kt @@ -107,7 +107,7 @@ class TabCustomizerActivity : BaseActivity() { fabCancel.setIcon(GoogleMaterial.Icon.gmd_close, prefs.iconColor) fabCancel.backgroundTintList = ColorStateList.valueOf(prefs.accentColor) fabCancel.setOnClickListener { finish() } - setFrostColors(prefs) { + setFrostColors { themeWindow = true } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt index abc07d57..c21f7362 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt @@ -205,7 +205,7 @@ abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT toolbar.navigationIcon = GoogleMaterial.Icon.gmd_close.toDrawable(this, 16, prefs.iconColor) toolbar.setNavigationOnClickListener { finishSlideOut() } - setFrostColors(prefs) { + setFrostColors { toolbar(toolbar) themeWindow = false } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/enums/Theme.kt b/app/src/main/kotlin/com/pitchedapps/frost/enums/Theme.kt index bb2514f5..3dccc446 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/enums/Theme.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/enums/Theme.kt @@ -18,11 +18,10 @@ package com.pitchedapps.frost.enums import android.graphics.Color import androidx.annotation.StringRes +import androidx.annotation.VisibleForTesting import com.pitchedapps.frost.R -import com.pitchedapps.frost.injectors.CssAssets -import com.pitchedapps.frost.injectors.InjectorContract -import com.pitchedapps.frost.injectors.JsActions import com.pitchedapps.frost.prefs.sections.ThemePrefs +import java.util.Locale /** * Created by Allan Wang on 2017-06-14. @@ -32,7 +31,7 @@ const val BLUE_LIGHT = 0xff5d86dd.toInt() enum class Theme( @StringRes val textRes: Int, - val injector: InjectorContract, + file: String?, val textColorGetter: (ThemePrefs) -> Int, val accentColorGetter: (ThemePrefs) -> Int, val backgroundColorGetter: (ThemePrefs) -> Int, @@ -41,7 +40,7 @@ enum class Theme( ) { DEFAULT(R.string.kau_default, - JsActions.EMPTY, + null, { 0xde000000.toInt() }, { FACEBOOK_BLUE }, { 0xfffafafa.toInt() }, @@ -49,7 +48,7 @@ enum class Theme( { Color.WHITE }), LIGHT(R.string.kau_light, - CssAssets.MATERIAL_LIGHT, + "material_light", { 0xde000000.toInt() }, { FACEBOOK_BLUE }, { 0xfffafafa.toInt() }, @@ -57,7 +56,7 @@ enum class Theme( { Color.WHITE }), DARK(R.string.kau_dark, - CssAssets.MATERIAL_DARK, + "material_dark", { Color.WHITE }, { BLUE_LIGHT }, { 0xff303030.toInt() }, @@ -65,7 +64,7 @@ enum class Theme( { Color.WHITE }), AMOLED(R.string.kau_amoled, - CssAssets.MATERIAL_AMOLED, + "material_amoled", { Color.WHITE }, { BLUE_LIGHT }, { Color.BLACK }, @@ -73,7 +72,7 @@ enum class Theme( { Color.WHITE }), GLASS(R.string.kau_glass, - CssAssets.MATERIAL_GLASS, + "material_glass", { Color.WHITE }, { BLUE_LIGHT }, { 0x80000000.toInt() }, @@ -81,15 +80,26 @@ enum class Theme( { Color.WHITE }), CUSTOM(R.string.kau_custom, - CssAssets.CUSTOM, + "custom", { it.customTextColor }, { it.customAccentColor }, { it.customBackgroundColor }, { it.customHeaderColor }, { it.customIconColor }); + @VisibleForTesting + internal val file = file?.let { "${it}.css" } + companion object { val values = values() // save one instance operator fun invoke(index: Int) = values[index] } } + +enum class ThemeCategory { + FACEBOOK, MESSENGER + ; + + @VisibleForTesting + internal val folder = name.toLowerCase(Locale.CANADA) +} diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssSmallAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAsset.kt index 30ee7a8f..b384efad 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssSmallAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAsset.kt @@ -22,7 +22,7 @@ import com.pitchedapps.frost.prefs.Prefs /** * Small misc inline css assets */ -enum class CssSmallAssets(private val content: String) : InjectorContract { +enum class CssAsset(private val content: String) : InjectorContract { FullSizeImage("div._4prr[style*=\"max-width\"][style*=\"max-height\"]{max-width:none !important;max-height:none !important}") ; diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/ThemeProvider.kt index e012de3f..5a9576d2 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/ThemeProvider.kt @@ -18,53 +18,82 @@ package com.pitchedapps.frost.injectors import android.content.Context import android.graphics.Color -import android.webkit.WebView -import androidx.annotation.VisibleForTesting import ca.allanwang.kau.utils.adjustAlpha import ca.allanwang.kau.utils.colorToBackground import ca.allanwang.kau.utils.colorToForeground +import ca.allanwang.kau.utils.isColorVisibleOn import ca.allanwang.kau.utils.toRgbaString import ca.allanwang.kau.utils.use import ca.allanwang.kau.utils.withAlpha +import com.pitchedapps.frost.enums.FACEBOOK_BLUE +import com.pitchedapps.frost.enums.Theme +import com.pitchedapps.frost.enums.ThemeCategory import com.pitchedapps.frost.prefs.Prefs import com.pitchedapps.frost.utils.L import java.io.BufferedReader import java.io.FileNotFoundException -import java.util.Locale import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -private const val THEME_FOLDER = "themes" - /** * Created by Allan Wang on 2017-05-31. * Mapping of the available assets * The enum name must match the css file name */ -enum class CssAssets(val folder: String = THEME_FOLDER) : InjectorContract { - MATERIAL_LIGHT, MATERIAL_DARK, MATERIAL_AMOLED, MATERIAL_GLASS, CUSTOM - ; +class ThemeProvider(private val context: Context, private val prefs: Prefs) { + + var theme: Theme = Theme.values[prefs.theme] + + private val injectors: MutableMap<ThemeCategory, InjectorContract> = mutableMapOf() + + val textColor: Int + get() = theme.textColorGetter(prefs) + + val accentColor: Int + get() = theme.accentColorGetter(prefs) + + val accentColorForWhite: Int + get() = when { + accentColor.isColorVisibleOn(Color.WHITE) -> accentColor + textColor.isColorVisibleOn(Color.WHITE) -> textColor + else -> FACEBOOK_BLUE + } + + val nativeBgColor: Int + get() = bgColor.withAlpha(30) + + fun nativeBgColor(unread: Boolean) = bgColor + .colorToForeground(if (unread) 0.7f else 0.0f) + .withAlpha(30) + + val bgColor: Int + get() = theme.backgroundColorGetter(prefs) - @VisibleForTesting - internal val file = "${name.toLowerCase(Locale.CANADA)}.css" + val headerColor: Int + get() = theme.headerColorGetter(prefs) + + val iconColor: Int + get() = theme.iconColorGetter(prefs) + + val isCustomTheme: Boolean + get() = theme == Theme.CUSTOM /** - * Note that while this can be loaded from any thread, it is typically done through [load] + * Note that while this can be loaded from any thread, it is typically done through [preload]] */ - private var injector: JsInjector? = null - - private fun injector(context: Context, prefs: Prefs): JsInjector = - injector ?: createInjector(context, prefs).also { injector = it } + fun injector(category: ThemeCategory): InjectorContract = + injectors.getOrPut(category) { createInjector(category) } /** - * Note that while this can be loaded from any thread, it is typically done through [load] + * Note that while this can be loaded from any thread, it is typically done through [preload] */ - private fun createInjector(context: Context, prefs: Prefs): JsInjector = + private fun createInjector(category: ThemeCategory): InjectorContract { + val file = theme.file ?: return JsActions.EMPTY try { var content = - context.assets.open("css/$folder/$file").bufferedReader() + context.assets.open("css/${category.folder}/theme/${file}").bufferedReader() .use(BufferedReader::readText) - if (this == CUSTOM) { + if (theme == Theme.CUSTOM) { val bt = if (Color.alpha(prefs.bgColor) == 255) prefs.bgColor.toRgbaString() else @@ -86,30 +115,32 @@ enum class CssAssets(val folder: String = THEME_FOLDER) : InjectorContract { .replace("\$TI\$", bb.withAlpha(60).toRgbaString()) .replace("\$C\$", bt) } - JsBuilder().css(content).build() + return JsBuilder().css(content).build() } catch (e: FileNotFoundException) { L.e(e) { "CssAssets file not found" } - JsInjector(JsActions.EMPTY.function) + return JsActions.EMPTY } + } - override fun inject(webView: WebView, prefs: Prefs) = - injector(webView.context, prefs).inject(webView, prefs) + fun setTheme(id: Int) { + theme = Theme.values[id] + reset() + } fun reset() { - injector = null + injectors.clear() } - companion object { + suspend fun preload() { + withContext(Dispatchers.IO) { + reset() + ThemeCategory.values().forEach { injector(it) } + } + } - // Ensures that all non themes and the selected theme are loaded - suspend fun load(context: Context, prefs: Prefs) { - withContext(Dispatchers.IO) { - val currentTheme = prefs.themeInjector as? CssAssets - val (themes, others) = values().partition { it.folder == THEME_FOLDER } - themes.filter { it != currentTheme }.forEach { it.reset() } - currentTheme?.injector(context, prefs) - others.forEach { it.injector(context, prefs) } - } + companion object { + fun module() = org.koin.dsl.module { + single { ThemeProvider(get(), get()) } } } }
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ThemePrefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ThemePrefs.kt index 84f64435..a5a66ee9 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ThemePrefs.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ThemePrefs.kt @@ -106,7 +106,7 @@ class ThemePrefsImpl( private val loader = lazyResettable { Theme.values[theme] } - private val t: Theme by loader + val t: Theme by loader override val textColor: Int get() = t.textColorGetter(this) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt index 65e24ab8..a5f7ec28 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt @@ -27,7 +27,7 @@ import com.pitchedapps.frost.R import com.pitchedapps.frost.activities.SettingsActivity import com.pitchedapps.frost.enums.MainActivityLayout import com.pitchedapps.frost.enums.Theme -import com.pitchedapps.frost.injectors.CssAssets +import com.pitchedapps.frost.injectors.ThemeProvider import com.pitchedapps.frost.utils.REQUEST_NAV import com.pitchedapps.frost.utils.REQUEST_TEXT_ZOOM import com.pitchedapps.frost.utils.frostEvent @@ -44,7 +44,7 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { header(R.string.theme_customization) - text(R.string.theme, prefs::theme, { prefs.theme = it }) { + text(R.string.theme, prefs::theme, { prefs.theme = it; themeProvider.setTheme(it) }) { onClick = { materialDialog { title(R.string.theme) @@ -76,7 +76,7 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { } fun invalidateCustomTheme() { - CssAssets.CUSTOM.reset() + themeProvider.reset() } colorPicker(R.string.text_color, prefs::customTextColor, { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt index ebefa4ca..63483da0 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt @@ -67,7 +67,7 @@ import com.pitchedapps.frost.facebook.FbUrlFormatter.Companion.VIDEO_REDIRECT import com.pitchedapps.frost.facebook.USER_AGENT import com.pitchedapps.frost.facebook.formattedFbUri import com.pitchedapps.frost.facebook.formattedFbUrl -import com.pitchedapps.frost.injectors.CssAssets +import com.pitchedapps.frost.injectors.ThemeProvider import com.pitchedapps.frost.injectors.JsAssets import com.pitchedapps.frost.prefs.Prefs import java.io.File @@ -84,6 +84,8 @@ import org.apache.commons.text.StringEscapeUtils import org.jsoup.Jsoup import org.jsoup.nodes.Document import org.jsoup.nodes.Element +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject /** * Created by Allan Wang on 2017-06-03. @@ -191,7 +193,10 @@ fun Activity.setFrostTheme(prefs: Prefs, forceTransparent: Boolean = false) { } } -class ActivityThemeUtils(val prefs: Prefs) { +class ActivityThemeUtils : KoinComponent { + + private val prefs: Prefs by inject() + private val themeProvider: ThemeProvider by inject() private var toolbar: Toolbar? = null var themeWindow = true @@ -455,6 +460,6 @@ fun String.unescapeHtml(): String = .replace("\\\"", "\"") suspend fun Context.loadAssets(prefs: Prefs): Unit = coroutineScope { - CssAssets.load(this@loadAssets, prefs) + ThemeProvider.load(this@loadAssets, prefs) JsAssets.load(this@loadAssets) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt index 17ab77a7..c68d3f57 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt @@ -26,7 +26,7 @@ import android.webkit.WebView import ca.allanwang.kau.utils.withAlpha import com.pitchedapps.frost.facebook.USER_AGENT import com.pitchedapps.frost.injectors.CssHider -import com.pitchedapps.frost.injectors.CssSmallAssets +import com.pitchedapps.frost.injectors.CssAsset import com.pitchedapps.frost.injectors.jsInject import com.pitchedapps.frost.prefs.Prefs import com.pitchedapps.frost.utils.L @@ -117,7 +117,7 @@ class DebugWebView @JvmOverloads constructor( (url?.contains("?sk=h_chr") ?: false) && prefs.aggressiveRecents ), - CssSmallAssets.FullSizeImage.maybe(prefs.fullSizeImage), + CssAsset.FullSizeImage.maybe(prefs.fullSizeImage), prefs = prefs ) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt index 324af69b..cf248baf 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt @@ -29,7 +29,7 @@ import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.facebook.WWW_FACEBOOK_COM import com.pitchedapps.frost.facebook.formattedFbUrl import com.pitchedapps.frost.injectors.CssHider -import com.pitchedapps.frost.injectors.CssSmallAssets +import com.pitchedapps.frost.injectors.CssAsset import com.pitchedapps.frost.injectors.JsActions import com.pitchedapps.frost.injectors.JsAssets import com.pitchedapps.frost.injectors.jsInject @@ -118,7 +118,7 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { CssHider.ADS.maybe(!prefs.showFacebookAds), CssHider.POST_ACTIONS.maybe(!prefs.showPostActions), CssHider.POST_REACTIONS.maybe(!prefs.showPostReactions), - CssSmallAssets.FullSizeImage.maybe(prefs.fullSizeImage), + CssAsset.FullSizeImage.maybe(prefs.fullSizeImage), JsAssets.DOCUMENT_WATCHER, JsAssets.HORIZONTAL_SCROLLING, JsAssets.AUTO_RESIZE_TEXTAREA.maybe(prefs.autoExpandTextBox), |