diff options
70 files changed, 835 insertions, 570 deletions
diff --git a/app/build.gradle b/app/build.gradle index f36aa430..63ada71b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -48,7 +48,7 @@ android { throw new GradleException("Version name mismatch, expected ${androidGitVersion.name()}, got $versionName") } multiDexEnabled true - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "com.pitchedapps.frost.FrostTestRunner" javaCompileOptions { annotationProcessorOptions { arguments = ["room.schemaLocation": "$projectDir/src/schemas".toString()] diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/FrostTestApp.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/FrostTestApp.kt new file mode 100644 index 00000000..607adbf1 --- /dev/null +++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/FrostTestApp.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2020 Allan Wang + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package com.pitchedapps.frost + +import android.app.Application +import android.content.Context +import androidx.test.runner.AndroidJUnitRunner +import ca.allanwang.kau.kpref.KPrefFactory +import ca.allanwang.kau.kpref.KPrefFactoryInMemory +import com.pitchedapps.frost.db.FrostDatabase +import com.pitchedapps.frost.facebook.FbCookie +import com.pitchedapps.frost.utils.Prefs +import com.pitchedapps.frost.utils.Showcase +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runners.model.Statement +import org.koin.android.ext.koin.androidContext +import org.koin.android.ext.koin.androidLogger +import org.koin.core.KoinComponent +import org.koin.core.context.startKoin +import org.koin.core.get +import org.koin.core.module.Module +import org.koin.dsl.module + +class FrostTestRunner : AndroidJUnitRunner() { + override fun newApplication( + cl: ClassLoader?, + className: String?, + context: Context? + ): Application { + return super.newApplication(cl, FrostTestApp::class.java.name, context) + } +} + +class FrostTestRule : TestRule { + override fun apply(base: Statement, description: Description): Statement = + object : Statement(), KoinComponent { + override fun evaluate() { + + // Reset prefs + get<Prefs>().reset() + get<Showcase>().reset() + + base.evaluate() + } + } +} + +class FrostTestApp : Application() { + + override fun onCreate() { + super.onCreate() + startKoin { + androidLogger() + androidContext(this@FrostTestApp) + modules( + listOf( + FrostDatabase.module(), + prefFactoryModule(), + Prefs.module(), + Showcase.module(), + FbCookie.module() + ) + ) + } + } + + companion object { + fun prefFactoryModule(): Module = module { + single<KPrefFactory> { + KPrefFactoryInMemory + } + } + } +} diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/activities/ImageActivityTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/activities/ImageActivityTest.kt index cd8aaa24..5f1735f5 100644 --- a/app/src/androidTest/kotlin/com/pitchedapps/frost/activities/ImageActivityTest.kt +++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/activities/ImageActivityTest.kt @@ -19,6 +19,7 @@ package com.pitchedapps.frost.activities import android.content.Intent import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.rule.ActivityTestRule +import com.pitchedapps.frost.FrostTestRule import com.pitchedapps.frost.helper.getResource import com.pitchedapps.frost.utils.ARG_COOKIE import com.pitchedapps.frost.utils.ARG_IMAGE_URL @@ -39,17 +40,21 @@ import org.junit.After import org.junit.Before import org.junit.Rule import org.junit.Test +import org.junit.rules.RuleChain +import org.junit.rules.TestRule import org.junit.rules.Timeout import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ImageActivityTest { - @get:Rule val activity: ActivityTestRule<ImageActivity> = ActivityTestRule(ImageActivity::class.java, true, false) @get:Rule + val rule: TestRule = RuleChain.outerRule(FrostTestRule()).around(activity) + + @get:Rule val globalTimeout: Timeout = Timeout.seconds(15) private fun launchActivity(imageUrl: String, text: String? = null, cookie: String? = null) { @@ -124,7 +129,6 @@ class ImageActivityTest { fun invalidImageTest() { launchActivity(mockServer.url("text").toString()) mockServer.takeRequest() - activity.activity.isFinishing with(activity.activity) { assertEquals(1, mockServer.requestCount, "One http request expected") assertEquals( diff --git a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt index a11006e2..34808e65 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt @@ -19,11 +19,15 @@ package com.pitchedapps.frost import android.app.Activity import android.app.Application import android.os.Bundle +import android.util.Log +import ca.allanwang.kau.kpref.KPrefFactory +import ca.allanwang.kau.kpref.KPrefFactoryAndroid import ca.allanwang.kau.logging.KL import ca.allanwang.kau.utils.buildIsLollipopAndUp import com.bugsnag.android.Bugsnag import com.bugsnag.android.Configuration import com.pitchedapps.frost.db.FrostDatabase +import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.services.scheduleNotificationsFromPrefs import com.pitchedapps.frost.services.setupNotificationChannels import com.pitchedapps.frost.utils.BuildUtils @@ -34,18 +38,42 @@ import com.pitchedapps.frost.utils.Showcase import java.util.Random import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidLogger +import org.koin.core.KoinComponent import org.koin.core.context.startKoin +import org.koin.core.get +import org.koin.core.module.Module +import org.koin.dsl.module /** * Created by Allan Wang on 2017-05-28. */ -class FrostApp : Application() { +class FrostApp : Application(), KoinComponent { + + private lateinit var showcasePrefs: Showcase + private lateinit var prefs: Prefs override fun onCreate() { + startKoin { + if (BuildConfig.DEBUG) { + androidLogger() + } + androidContext(this@FrostApp) + modules( + listOf( + FrostDatabase.module(), + prefFactoryModule(), + Prefs.module(), + Showcase.module(), + FbCookie.module() + ) + ) + } if (!buildIsLollipopAndUp) { // not supported super.onCreate() return } + prefs = get() + showcasePrefs = get() initPrefs() initBugsnag() @@ -54,9 +82,9 @@ class FrostApp : Application() { super.onCreate() - setupNotificationChannels(applicationContext) + setupNotificationChannels(this, prefs) - scheduleNotificationsFromPrefs() + scheduleNotificationsFromPrefs(prefs) if (BuildConfig.DEBUG) { registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks { @@ -77,27 +105,27 @@ class FrostApp : Application() { } }) } - startKoin { - if (BuildConfig.DEBUG) { - androidLogger() - } - androidContext(this@FrostApp) - modules(FrostDatabase.module(this@FrostApp)) - } } private fun initPrefs() { - Showcase.initialize(this, "${BuildConfig.APPLICATION_ID}.showcase") - Prefs.initialize(this, "${BuildConfig.APPLICATION_ID}.prefs") + prefs.deleteKeys("search_bar") + showcasePrefs.deleteKeys("shown_release", "experimental_by_default") KL.shouldLog = { BuildConfig.DEBUG } - Prefs.verboseLogging = false - if (Prefs.installDate == -1L) { - Prefs.installDate = System.currentTimeMillis() + L.shouldLog = { + when (it) { + Log.VERBOSE -> BuildConfig.DEBUG + Log.INFO, Log.ERROR -> true + else -> BuildConfig.DEBUG || prefs.verboseLogging + } + } + prefs.verboseLogging = false + if (prefs.installDate == -1L) { + prefs.installDate = System.currentTimeMillis() } - if (Prefs.identifier == -1) { - Prefs.identifier = Random().nextInt(Int.MAX_VALUE) + if (prefs.identifier == -1) { + prefs.identifier = Random().nextInt(Int.MAX_VALUE) } - Prefs.lastLaunch = System.currentTimeMillis() + prefs.lastLaunch = System.currentTimeMillis() } private fun initBugsnag() { @@ -113,12 +141,12 @@ class FrostApp : Application() { appVersion = version.versionName releaseStage = BuildUtils.getStage(BuildConfig.BUILD_TYPE) notifyReleaseStages = BuildUtils.getAllStages() - autoCaptureSessions = Prefs.analytics - enableExceptionHandler = Prefs.analytics + autoCaptureSessions = prefs.analytics + enableExceptionHandler = prefs.analytics } Bugsnag.init(this, config) - L.bugsnagInit = true - Bugsnag.setUserId(Prefs.frostId) + L.hasAnalytics = { prefs.analytics } + Bugsnag.setUserId(prefs.frostId) Bugsnag.addToTab("Build", "Application", BuildConfig.APPLICATION_ID) Bugsnag.addToTab("Build", "Version", BuildConfig.VERSION_NAME) @@ -129,4 +157,12 @@ class FrostApp : Application() { } } } + + companion object { + fun prefFactoryModule(): Module = module { + single<KPrefFactory> { + KPrefFactoryAndroid(get()) + } + } + } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt index fb23413e..40fe422e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt @@ -52,6 +52,8 @@ import org.koin.android.ext.android.inject */ class StartActivity : KauBaseActivity() { + private val fbCookie: FbCookie by inject() + private val prefs: Prefs by inject() private val cookieDao: CookieDao by inject() private val genericDao: GenericDao by inject() @@ -67,13 +69,14 @@ class StartActivity : KauBaseActivity() { // TODO add better descriptions CookieManager.getInstance() } catch (e: Exception) { + L.e(e) { "No cookiemanager instance" } showInvalidWebView() } launch { try { - val authDefer = BiometricUtils.authenticate(this@StartActivity) - FbCookie.switchBackUser() + val authDefer = BiometricUtils.authenticate(this@StartActivity, prefs) + fbCookie.switchBackUser() val cookies = ArrayList(cookieDao.selectAll()) L.i { "Cookies loaded at time ${System.currentTimeMillis()}" } L._d { @@ -82,12 +85,12 @@ class StartActivity : KauBaseActivity() { transform = CookieEntity::toSensitiveString )}" } - loadAssets() + loadAssets(prefs) authDefer.await() when { cookies.isEmpty() -> launchNewTask<LoginActivity>() // Has cookies but no selected account - Prefs.userId == -1L -> launchNewTask<SelectorActivity>(cookies) + prefs.userId == -1L -> launchNewTask<SelectorActivity>(cookies) else -> startActivity<MainActivity>(intentBuilder = { putParcelableArrayListExtra(EXTRA_COOKIES, cookies) flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt index 17b475da..04c0334d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt @@ -49,20 +49,25 @@ import com.pitchedapps.frost.BuildConfig import com.pitchedapps.frost.R import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs +import org.koin.android.ext.android.inject /** * Created by Allan Wang on 2017-06-26. */ -class AboutActivity : AboutActivityBase(null, { - textColor = Prefs.textColor - accentColor = Prefs.accentColor - backgroundColor = Prefs.bgColor.withMinAlpha(200) - cutoutForeground = Prefs.accentColor - cutoutDrawableRes = R.drawable.frost_f_200 - faqPageTitleRes = R.string.faq_title - faqXmlRes = R.xml.frost_faq - faqParseNewLine = false -}) { +class AboutActivity : AboutActivityBase(null) { + + private val prefs: Prefs by inject() + + override fun Configs.buildConfigs() { + textColor = prefs.textColor + accentColor = prefs.accentColor + backgroundColor = prefs.bgColor.withMinAlpha(200) + cutoutForeground = prefs.accentColor + cutoutDrawableRes = R.drawable.frost_f_200 + faqPageTitleRes = R.string.faq_title + faqXmlRes = R.xml.frost_faq + faqParseNewLine = false + } override fun getLibraries(libs: Libs): List<Library> { val include = arrayOf( @@ -121,8 +126,8 @@ class AboutActivity : AboutActivityBase(null, { clickCount++ lastClick = now if (clickCount == 8) { - if (!Prefs.debugSettings) { - Prefs.debugSettings = true + if (!prefs.debugSettings) { + prefs.debugSettings = true L.d { "Debugging section enabled" } toast(R.string.debug_toast_enabled) } else { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt index e514fa14..af49cb33 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt @@ -21,13 +21,19 @@ import android.os.Bundle import ca.allanwang.kau.internal.KauBaseActivity import ca.allanwang.kau.searchview.SearchViewHolder import com.pitchedapps.frost.contracts.VideoViewHolder +import com.pitchedapps.frost.facebook.FbCookie +import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.setFrostTheme +import org.koin.android.ext.android.inject /** * Created by Allan Wang on 2017-06-12. */ abstract class BaseActivity : KauBaseActivity() { + val fbCookie: FbCookie by inject() + val prefs: Prefs by inject() + /** * Inherited consumer to customize back press */ 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 0b422991..b22ef999 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt @@ -93,7 +93,6 @@ import com.pitchedapps.frost.db.GenericDao import com.pitchedapps.frost.db.currentCookie import com.pitchedapps.frost.db.getTabs import com.pitchedapps.frost.enums.MainActivityLayout -import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.facebook.parsers.FrostSearch import com.pitchedapps.frost.facebook.parsers.SearchParser @@ -108,7 +107,6 @@ import com.pitchedapps.frost.utils.BiometricUtils import com.pitchedapps.frost.utils.EXTRA_COOKIES import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.MAIN_TIMEOUT_DURATION -import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.REQUEST_FAB import com.pitchedapps.frost.utils.REQUEST_NAV import com.pitchedapps.frost.utils.REQUEST_NOTIFICATION @@ -177,7 +175,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, val start = System.currentTimeMillis() drawerWrapperBinding = ActivityMainDrawerWrapperBinding.inflate(layoutInflater) setContentView(drawerWrapperBinding.root) - contentBinding = when (Prefs.mainActivityLayout) { + contentBinding = when (prefs.mainActivityLayout) { MainActivityLayout.TOP_BAR -> { val binding = ActivityMainBinding.inflate(layoutInflater) object : ActivityMainContentBinding { @@ -203,7 +201,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, } drawerWrapperBinding.mainContainer.addView(contentBinding.root) with(contentBinding) { - setFrostColors { + setFrostColors(prefs) { toolbar(toolbar) themeWindow = false header(appbar) @@ -211,7 +209,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, } setSupportActionBar(toolbar) viewpager.adapter = adapter - tabs.setBackgroundColor(Prefs.mainActivityLayout.backgroundColor()) + tabs.setBackgroundColor(prefs.mainActivityLayout.backgroundColor(prefs)) } onNestedCreate(savedInstanceState) L.i { "Main finished loading UI in ${System.currentTimeMillis() - start} ms" } @@ -219,18 +217,18 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, adapter.setPages(genericDao.getTabs()) } controlWebview = WebView(this) - if (BuildConfig.VERSION_CODE > Prefs.versionCode) { - Prefs.prevVersionCode = Prefs.versionCode - Prefs.versionCode = BuildConfig.VERSION_CODE + if (BuildConfig.VERSION_CODE > prefs.versionCode) { + prefs.prevVersionCode = prefs.versionCode + prefs.versionCode = BuildConfig.VERSION_CODE if (!BuildConfig.DEBUG) { frostChangelog() frostEvent( "Version", "Version code" to BuildConfig.VERSION_CODE, - "Prev version code" to Prefs.prevVersionCode, + "Prev version code" to prefs.prevVersionCode, "Version name" to BuildConfig.VERSION_NAME, "Build type" to BuildConfig.BUILD_TYPE, - "Frost id" to Prefs.frostId + "Frost id" to prefs.frostId ) } } @@ -289,7 +287,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, drawer.addDrawerListener(toggle) toggle.syncState() - val foregroundColor = ColorStateList.valueOf(Prefs.textColor) + val foregroundColor = ColorStateList.valueOf(prefs.textColor) with(navigation) { FrostMenuBuilder(this@BaseMainActivity, menu).apply { @@ -315,12 +313,12 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, val item = FbItem.values[it.itemId] frostEvent("Drawer Tab", "name" to item.name) drawer.closeDrawer(navigation) - launchWebOverlay(item.url) + launchWebOverlay(item.url, fbCookie) false } - val navBg = Prefs.bgColor.withMinAlpha(200) + val navBg = prefs.bgColor.withMinAlpha(200) setBackgroundColor(navBg) - itemBackground = createNavDrawable(Prefs.accentColor, navBg) + itemBackground = createNavDrawable(prefs.accentColor, navBg) itemTextColor = foregroundColor itemIconTintList = foregroundColor @@ -332,7 +330,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, private fun ActivityMainContentBinding.initFab() { hasFab = false shouldShow = false - fab.backgroundTintList = ColorStateList.valueOf(Prefs.headerColor.withMinAlpha(200)) + fab.backgroundTintList = ColorStateList.valueOf(prefs.headerColor.withMinAlpha(200)) fab.hide() appbar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset -> if (!hasFab) return@OnOffsetChangedListener @@ -352,12 +350,12 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, if (shouldShow) { if (fab.isShown) { fab.fadeScaleTransition { - setIcon(iicon, color = Prefs.iconColor) + setIcon(iicon, color = prefs.iconColor) } return } } - fab.setIcon(iicon, color = Prefs.iconColor) + fab.setIcon(iicon, color = prefs.iconColor) fab.showIf(shouldShow) } } @@ -384,12 +382,12 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, private var pendingUpdate: Boolean = false private val binding = ViewNavHeaderBinding.inflate(layoutInflater) val root: View get() = binding.root - private val optionsBackground = Prefs.bgColor.withMinAlpha(200).colorToForeground( + private val optionsBackground = prefs.bgColor.withMinAlpha(200).colorToForeground( 0.1f ) init { - setPrimary(Prefs.userId) + setPrimary(prefs.userId) binding.updateAccounts() with(drawerWrapperBinding) { drawer.addDrawerListener(object : DrawerLayout.SimpleDrawerListener() { @@ -449,7 +447,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, animator.start() } - val textColor = Prefs.textColor + val textColor = prefs.textColor fun TextView.setOptionsIcon(iicon: IIcon) { setCompoundDrawablesRelativeWithIntrinsicBounds( @@ -459,7 +457,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, null ) setTextColor(textColor) - background = createNavDrawable(Prefs.accentColor, optionsBackground) + background = createNavDrawable(prefs.accentColor, optionsBackground) } with(optionsLogout) { @@ -469,7 +467,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, val currentCookie = cookieDao.currentCookie() if (currentCookie == null) { toast(R.string.account_not_found) - FbCookie.reset() + fbCookie.reset() launchLogin(cookies(), true) } else { materialDialog { @@ -478,12 +476,12 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, text = String.format( string(R.string.kau_logout_confirm_as_x), - currentCookie.name ?: Prefs.userId.toString() + currentCookie.name ?: prefs.userId.toString() ) ) positiveButton(R.string.kau_yes) { this@BaseMainActivity.launch { - FbCookie.logout(this@BaseMainActivity) + fbCookie.logout(this@BaseMainActivity) } } negativeButton(R.string.kau_no) @@ -507,7 +505,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, arrow.setImageDrawable( GoogleMaterial.Icon.gmd_arrow_drop_down.toDrawable( this@BaseMainActivity, - color = Prefs.textColor + color = prefs.textColor ) ) } @@ -532,10 +530,10 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, avatarTertiary.setAccount(orderedAccounts.getOrNull(2), false) optionsAccountsContainer.removeAllViews() name.text = orderedAccounts.getOrNull(0)?.name - name.setTextColor(Prefs.textColor) + name.setTextColor(prefs.textColor) val glide = Glide.with(root) val accountSize = dimenPixelSize(R.dimen.drawer_account_avatar_size) - val textColor = Prefs.textColor + val textColor = prefs.textColor orderedAccounts.forEach { cookie -> val tv = TextView( @@ -569,7 +567,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, }) tv.text = cookie.name tv.setTextColor(textColor) - tv.background = createNavDrawable(Prefs.accentColor, optionsBackground) + tv.background = createNavDrawable(prefs.accentColor, optionsBackground) tv.setOnClickListener { switchAccount(cookie.id) } @@ -598,7 +596,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, .into(this) setOnClickListener { if (primary) { - launchWebOverlay(FbItem.PROFILE.url) + launchWebOverlay(FbItem.PROFILE.url, fbCookie) } else { switchAccount(cookie.id) } @@ -608,12 +606,12 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, } private fun switchAccount(id: Long) { - if (Prefs.userId == id) return + if (prefs.userId == id) return setPrimary(id) pendingUpdate = true closeDrawer() launch { - FbCookie.switchUser(id) + fbCookie.switchUser(id) tabsForEachView { _, view -> view.badgeText = null } refreshAll() } @@ -627,9 +625,9 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_main, menu) - contentBinding.toolbar.tint(Prefs.iconColor) + contentBinding.toolbar.tint(prefs.iconColor) setMenuIcons( - menu, Prefs.iconColor, + menu, prefs.iconColor, R.id.action_settings to GoogleMaterial.Icon.gmd_settings, R.id.action_search to GoogleMaterial.Icon.gmd_search ) @@ -639,13 +637,13 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, private fun bindSearchView(menu: Menu) { searchViewBindIfNull { - bindSearchView(menu, R.id.action_search, Prefs.iconColor) { + bindSearchView(menu, R.id.action_search, prefs.iconColor) { textCallback = { query, searchView -> val results = searchViewCache[query] if (results != null) searchView.results = results else { - val data = SearchParser.query(FbCookie.webCookie, query)?.data?.results + val data = SearchParser.query(fbCookie.webCookie, query)?.data?.results if (data != null) { val items = data.mapTo(mutableListOf(), FrostSearch::toSearchItem) if (items.isNotEmpty()) @@ -663,11 +661,11 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, } textDebounceInterval = 300 searchCallback = - { query, _ -> launchWebOverlay("${FbItem._SEARCH.url}/?q=$query"); true } + { query, _ -> launchWebOverlay("${FbItem._SEARCH.url}/?q=$query", fbCookie); true } closeListener = { _ -> searchViewCache.clear() } - foregroundColor = Prefs.textColor - backgroundColor = Prefs.bgColor.withMinAlpha(200) - onItemClick = { _, key, _, _ -> launchWebOverlay(key) } + foregroundColor = prefs.textColor + backgroundColor = prefs.bgColor.withMinAlpha(200) + onItemClick = { _, key, _, _ -> launchWebOverlay(key, fbCookie) } } } } @@ -737,7 +735,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, fragmentChannel.offer(lastPosition) } if (hasRequest(REQUEST_NOTIFICATION)) { - scheduleNotificationsFromPrefs() + scheduleNotificationsFromPrefs(prefs) } } } @@ -758,10 +756,10 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, lastAccessTime = System.currentTimeMillis() // precaution to avoid loops controlWebview?.resumeTimers() launch { - val authDefer = BiometricUtils.authenticate(this@BaseMainActivity) - FbCookie.switchBackUser() + val authDefer = BiometricUtils.authenticate(this@BaseMainActivity, prefs) + fbCookie.switchBackUser() authDefer.await() - if (shouldReload && Prefs.autoRefreshFeed) { + if (shouldReload && prefs.autoRefreshFeed) { refreshAll() } } @@ -794,14 +792,14 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, } } if (currentFragment.onBackPressed()) return true - if (Prefs.exitConfirmation) { + if (prefs.exitConfirmation) { materialDialog { title(R.string.kau_exit) message(R.string.kau_exit_confirmation) positiveButton(R.string.kau_yes) { finish() } negativeButton(R.string.kau_no) checkBoxPrompt(R.string.kau_do_not_show_again, isCheckedDefault = false) { - Prefs.exitConfirmation = !it + prefs.exitConfirmation = !it } } return true @@ -879,6 +877,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, val item = pages[position] return BaseFragment( item.fragmentCreator, + prefs, forcedFallbacks.contains(item.name), item, position @@ -901,7 +900,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, override val lowerVideoPadding: PointF get() { - if (Prefs.mainActivityLayout == MainActivityLayout.BOTTOM_BAR) + if (prefs.mainActivityLayout == MainActivityLayout.BOTTOM_BAR) lowerVideoPaddingPointF.set(0f, contentBinding.toolbar.height.toFloat()) else lowerVideoPaddingPointF.set(0f, 0f) 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 47b096ab..51b1134a 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt @@ -38,6 +38,8 @@ import java.io.File import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine import kotlinx.coroutines.CoroutineExceptionHandler +import org.koin.android.ext.android.inject +import org.koin.core.inject /** * Created by Allan Wang on 05/01/18. @@ -51,6 +53,8 @@ class DebugActivity : KauBaseActivity() { fun baseDir(context: Context) = File(context.externalCacheDir, "offline_debug") } + private val prefs: Prefs by inject() + lateinit var binding: ActivityDebugBinding override fun onCreate(savedInstanceState: Bundle?) { @@ -68,7 +72,7 @@ class DebugActivity : KauBaseActivity() { } setTitle(R.string.debug_frost) - setFrostColors { + setFrostColors(prefs) { toolbar(toolbar) } debugWebview.loadUrl(FbItem.FEED.url) @@ -76,8 +80,8 @@ class DebugActivity : KauBaseActivity() { swipeRefresh.setOnRefreshListener(debugWebview::reload) - fab.visible().setIcon(GoogleMaterial.Icon.gmd_bug_report, Prefs.iconColor) - fab.backgroundTintList = ColorStateList.valueOf(Prefs.accentColor) + fab.visible().setIcon(GoogleMaterial.Icon.gmd_bug_report, prefs.iconColor) + fab.backgroundTintList = ColorStateList.valueOf(prefs.accentColor) fab.setOnClickListener { _ -> fab.hide() 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 ef82b3f5..6ae7622d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt @@ -81,12 +81,16 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.koin.android.ext.android.inject +import org.koin.core.inject /** * Created by Allan Wang on 2017-07-15. */ class ImageActivity : KauBaseActivity() { + private val prefs: Prefs by inject() + @Volatile internal var errorRef: Throwable? = null @@ -106,7 +110,7 @@ class ImageActivity : KauBaseActivity() { set(value) { if (field == value) return field = value - value.update(binding.imageFab) + value.update(binding.imageFab, prefs) } private lateinit var dragHelper: ViewDragHelper @@ -144,8 +148,8 @@ class ImageActivity : KauBaseActivity() { private lateinit var binding: ActivityImageBinding private var bottomBehavior: BottomSheetBehavior<View>? = null - private val baseBackgroundColor = if (Prefs.blackMediaBg) Color.BLACK - else Prefs.bgColor.withMinAlpha(235) + private val baseBackgroundColor = if (prefs.blackMediaBg) Color.BLACK + else prefs.bgColor.withMinAlpha(235) private fun loadError(e: Throwable) { if (e.message?.contains("<!DOCTYPE html>") == true) { @@ -195,9 +199,9 @@ class ImageActivity : KauBaseActivity() { if (text.isNullOrBlank()) { imageText.gone() } else { - imageText.setTextColor(if (Prefs.blackMediaBg) Color.WHITE else Prefs.textColor) + imageText.setTextColor(if (prefs.blackMediaBg) Color.WHITE else prefs.textColor) imageText.setBackgroundColor( - (if (Prefs.blackMediaBg) Color.BLACK else Prefs.bgColor) + (if (prefs.blackMediaBg) Color.BLACK else prefs.bgColor) .colorToForeground(0.2f).withAlpha(255) ) imageText.text = text @@ -217,7 +221,7 @@ class ImageActivity : KauBaseActivity() { imageText.bringToFront() } } - imageProgress.tint(if (Prefs.blackMediaBg) Color.WHITE else Prefs.accentColor) + imageProgress.tint(if (prefs.blackMediaBg) Color.WHITE else prefs.accentColor) imageFab.setOnClickListener { fabAction.onClick(this@ImageActivity) } imagePhoto.setOnImageEventListener(object : SubsamplingScaleImageView.DefaultOnImageEventListener() { @@ -225,7 +229,7 @@ class ImageActivity : KauBaseActivity() { loadError(e) } }) - setFrostColors { + setFrostColors(prefs) { themeWindow = false } dragHelper = ViewDragHelper.create(imageDrag, ViewDragCallback()).apply { @@ -405,10 +409,10 @@ class ImageActivity : KauBaseActivity() { internal enum class FabStates( val iicon: IIcon, - val iconColor: Int = Prefs.iconColor, + val iconColorProvider: (Prefs) -> Int = { it.iconColor }, val backgroundTint: Int = Int.MAX_VALUE ) { - ERROR(GoogleMaterial.Icon.gmd_error, Color.WHITE, Color.RED) { + ERROR(GoogleMaterial.Icon.gmd_error, { Color.WHITE }, Color.RED) { override fun onClick(activity: ImageActivity) { val err = activity.errorRef?.takeIf { it !is FileNotFoundException && it.message != "Image failed to decode using JPEG decoder" } @@ -460,8 +464,9 @@ internal enum class FabStates( * https://github.com/AllanWang/KAU/issues/184 * */ - fun update(fab: FloatingActionButton) { - val tint = if (backgroundTint != Int.MAX_VALUE) backgroundTint else Prefs.accentColor + fun update(fab: FloatingActionButton, prefs: Prefs) { + val tint = if (backgroundTint != Int.MAX_VALUE) backgroundTint else prefs.accentColor + val iconColor = iconColorProvider(prefs) if (fab.isHidden) { fab.setIcon(iicon, color = iconColor) fab.backgroundTintList = ColorStateList.valueOf(tint) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt index c76cad16..d594963e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt @@ -55,6 +55,7 @@ import com.pitchedapps.frost.utils.setFrostTheme import com.pitchedapps.frost.widgets.NotificationWidget import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.launch +import org.koin.android.ext.android.inject /** * Created by Allan Wang on 2017-07-25. @@ -62,8 +63,10 @@ import kotlinx.coroutines.launch * A beautiful intro activity * Phone showcases are drawn via layers */ -class IntroActivity : KauBaseActivity(), ViewPager.PageTransformer, ViewPager.OnPageChangeListener { +class IntroActivity : KauBaseActivity(), ViewPager.PageTransformer, + ViewPager.OnPageChangeListener { + private val prefs: Prefs by inject() lateinit var binding: ActivityIntroBinding private var barHasNext = true @@ -97,17 +100,17 @@ class IntroActivity : KauBaseActivity(), ViewPager.PageTransformer, ViewPager.On else finish(next.x + next.pivotX, next.y + next.pivotY) } skip.setOnClickListener { finish() } - ripple.set(Prefs.bgColor) + ripple.set(prefs.bgColor) theme() } fun theme() { - statusBarColor = Prefs.headerColor - navigationBarColor = Prefs.headerColor + statusBarColor = prefs.headerColor + navigationBarColor = prefs.headerColor with(binding) { - skip.setTextColor(Prefs.textColor) - next.imageTintList = ColorStateList.valueOf(Prefs.textColor) - indicator.setColour(Prefs.textColor) + skip.setTextColor(prefs.textColor) + next.imageTintList = ColorStateList.valueOf(prefs.textColor) + indicator.setColour(prefs.textColor) indicator.invalidate() } fragments.forEach { it.themeFragment() } @@ -149,21 +152,21 @@ class IntroActivity : KauBaseActivity(), ViewPager.PageTransformer, ViewPager.On ).forEach { it?.animate()?.alpha(0f)?.setDuration(600)?.start() } - if (Prefs.textColor != Color.WHITE) { + if (prefs.textColor != Color.WHITE) { val f = lastView?.findViewById<ImageView>(R.id.intro_image)?.drawable if (f != null) ValueAnimator.ofFloat(0f, 1f).apply { addUpdateListener { - f.setTint(Prefs.textColor.blendWith(Color.WHITE, it.animatedValue as Float)) + f.setTint(prefs.textColor.blendWith(Color.WHITE, it.animatedValue as Float)) } duration = 600 start() } } - if (Prefs.headerColor != blue) { + if (prefs.headerColor != blue) { ValueAnimator.ofFloat(0f, 1f).apply { addUpdateListener { - val c = Prefs.headerColor.blendWith(blue, it.animatedValue as Float) + val c = prefs.headerColor.blendWith(blue, it.animatedValue as Float) statusBarColor = c navigationBarColor = c } @@ -175,7 +178,7 @@ class IntroActivity : KauBaseActivity(), ViewPager.PageTransformer, ViewPager.On override fun finish() { launch(NonCancellable) { - loadAssets() + loadAssets(prefs) NotificationWidget.forceUpdate(this@IntroActivity) launchNewTask<MainActivity>(cookies(), false) super.finish() @@ -206,7 +209,7 @@ class IntroActivity : KauBaseActivity(), ViewPager.PageTransformer, ViewPager.On binding.next.fadeScaleTransition { setIcon( if (barHasNext) GoogleMaterial.Icon.gmd_navigate_next else GoogleMaterial.Icon.gmd_done, - color = Prefs.textColor + color = prefs.textColor ) } binding.skip.animate().scaleXY(if (barHasNext) 1f else 0f) 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 0579315a..25a97ae2 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt @@ -36,7 +36,6 @@ import com.pitchedapps.frost.db.CookieDao import com.pitchedapps.frost.db.CookieEntity import com.pitchedapps.frost.db.save import com.pitchedapps.frost.db.selectAll -import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.facebook.profilePictureUrl import com.pitchedapps.frost.glide.FrostGlide @@ -73,6 +72,7 @@ class LoginActivity : BaseActivity() { private val textview: AppCompatTextView by bindView(R.id.textview) private val profile: ImageView by bindView(R.id.profile) private val cookieDao: CookieDao by inject() + private val showcasePrefs: Showcase by inject() private lateinit var profileLoader: RequestManager private val refreshChannel = Channel<Boolean>(10) @@ -82,7 +82,7 @@ class LoginActivity : BaseActivity() { setContentView(R.layout.activity_login) setSupportActionBar(toolbar) setTitle(R.string.kau_login) - setFrostColors { + setFrostColors(prefs) { toolbar(toolbar) } profileLoader = GlideApp.with(profile) @@ -96,7 +96,7 @@ class LoginActivity : BaseActivity() { launch { val cookie = web.loadLogin { refresh(it != 100) }.await() L.d { "Login found" } - FbCookie.save(cookie.id) + fbCookie.save(cookie.id) webFadeOut() profile.fadeIn() loadInfo(cookie) @@ -138,7 +138,7 @@ class LoginActivity : BaseActivity() { */ val cookies = ArrayList(cookieDao.selectAll()) delay(1000) - if (Showcase.intro) + if (showcasePrefs.intro) launchNewTask<IntroActivity>(cookies, true) else launchNewTask<MainActivity>(cookies, true) 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 87fb1b17..a0e3ae42 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt @@ -27,7 +27,6 @@ import com.mikepenz.fastadapter.FastAdapter import com.mikepenz.fastadapter.adapters.FastItemAdapter import com.mikepenz.fastadapter.listeners.ClickEventHook import com.pitchedapps.frost.R -import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.utils.cookies import com.pitchedapps.frost.utils.launchNewTask import com.pitchedapps.frost.utils.setFrostColors @@ -63,12 +62,12 @@ class SelectorActivity : BaseActivity() { ) { if (item.cookie == null) this@SelectorActivity.launchNewTask<LoginActivity>() else launch { - FbCookie.switchUser(item.cookie) + fbCookie.switchUser(item.cookie) launchNewTask<MainActivity>(cookies()) } } }) - setFrostColors { + setFrostColors(prefs) { 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 42964bce..55ff3fba 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt @@ -41,6 +41,7 @@ import com.mikepenz.iconics.typeface.library.community.material.CommunityMateria import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.pitchedapps.frost.R import com.pitchedapps.frost.enums.Support +import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.settings.getAppearancePrefs import com.pitchedapps.frost.settings.getBehaviourPrefs import com.pitchedapps.frost.settings.getDebugPrefs @@ -61,12 +62,16 @@ import com.pitchedapps.frost.utils.loadAssets import com.pitchedapps.frost.utils.setFrostTheme import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.launch +import org.koin.android.ext.android.inject /** * Created by Allan Wang on 2017-06-06. */ class SettingsActivity : KPrefActivity() { + val fbCookie: FbCookie by inject() + val prefs: Prefs by inject() + private var resultFlag = Activity.RESULT_CANCELED companion object { @@ -117,11 +122,11 @@ class SettingsActivity : KPrefActivity() { } when (requestCode) { REQUEST_NOTIFICATION_RINGTONE -> { - Prefs.notificationRingtone = uriString + prefs.notificationRingtone = uriString reloadByTitle(R.string.notification_ringtone) } REQUEST_MESSAGE_RINGTONE -> { - Prefs.messageRingtone = uriString + prefs.messageRingtone = uriString reloadByTitle(R.string.message_ringtone) } } @@ -129,8 +134,8 @@ class SettingsActivity : KPrefActivity() { } override fun kPrefCoreAttributes(): CoreAttributeContract.() -> Unit = { - textColor = { Prefs.textColor } - accentColor = { Prefs.accentColor } + textColor = { prefs.textColor } + accentColor = { prefs.accentColor } } override fun onCreateKPrefs(savedInstanceState: Bundle?): KPrefAdapterBuilder.() -> Unit = { @@ -195,7 +200,7 @@ class SettingsActivity : KPrefActivity() { subItems(R.string.debug_frost, getDebugPrefs()) { descRes = R.string.debug_frost_desc iicon = CommunityMaterial.Icon.cmd_android_debug_bridge - visible = { Prefs.debugSettings } + visible = { prefs.debugSettings } } } @@ -215,15 +220,15 @@ class SettingsActivity : KPrefActivity() { override fun onCreate(savedInstanceState: Bundle?) { setFrostTheme(true) super.onCreate(savedInstanceState) - animate = Prefs.animate + animate = prefs.animate themeExterior(false) } fun themeExterior(animate: Boolean = true) { - if (animate) bgCanvas.fade(Prefs.bgColor) - else bgCanvas.set(Prefs.bgColor) - if (animate) toolbarCanvas.ripple(Prefs.headerColor, RippleCanvas.MIDDLE, RippleCanvas.END) - else toolbarCanvas.set(Prefs.headerColor) + if (animate) bgCanvas.fade(prefs.bgColor) + else bgCanvas.set(prefs.bgColor) + if (animate) toolbarCanvas.ripple(prefs.headerColor, RippleCanvas.MIDDLE, RippleCanvas.END) + else toolbarCanvas.set(prefs.headerColor) frostNavigationBar() } @@ -231,7 +236,7 @@ class SettingsActivity : KPrefActivity() { if (!super.backPress()) { setResult(resultFlag) launch(NonCancellable) { - loadAssets() + loadAssets(prefs) finishSlideOut() } } @@ -239,9 +244,9 @@ class SettingsActivity : KPrefActivity() { override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_settings, menu) - toolbar.tint(Prefs.iconColor) + toolbar.tint(prefs.iconColor) setMenuIcons( - menu, Prefs.iconColor, + menu, prefs.iconColor, R.id.action_email to GoogleMaterial.Icon.gmd_email, R.id.action_changelog to GoogleMaterial.Icon.gmd_info ) 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 ec9ea73d..11126803 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/TabCustomizerActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/TabCustomizerActivity.kt @@ -42,7 +42,6 @@ import com.pitchedapps.frost.db.saveTabs import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.iitems.TabIItem import com.pitchedapps.frost.utils.L -import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.setFrostColors import java.util.Collections import kotlinx.coroutines.NonCancellable @@ -70,15 +69,15 @@ class TabCustomizerActivity : BaseActivity() { } fun ActivityTabCustomizerBinding.init() { - pseudoToolbar.setBackgroundColor(Prefs.headerColor) + pseudoToolbar.setBackgroundColor(prefs.headerColor) tabRecycler.layoutManager = GridLayoutManager(this@TabCustomizerActivity, TAB_COUNT, RecyclerView.VERTICAL, false) tabRecycler.adapter = adapter tabRecycler.setHasFixedSize(true) - divider.setBackgroundColor(Prefs.textColor.withAlpha(30)) - instructions.setTextColor(Prefs.textColor) + divider.setBackgroundColor(prefs.textColor.withAlpha(30)) + instructions.setTextColor(prefs.textColor) launch { val tabs = genericDao.getTabs().toMutableList() @@ -95,8 +94,8 @@ class TabCustomizerActivity : BaseActivity() { setResult(Activity.RESULT_CANCELED) - fabSave.setIcon(GoogleMaterial.Icon.gmd_check, Prefs.iconColor) - fabSave.backgroundTintList = ColorStateList.valueOf(Prefs.accentColor) + fabSave.setIcon(GoogleMaterial.Icon.gmd_check, prefs.iconColor) + fabSave.backgroundTintList = ColorStateList.valueOf(prefs.accentColor) fabSave.setOnClickListener { launchMain(NonCancellable) { val tabs = adapter.adapterItems.subList(0, TAB_COUNT).map(TabIItem::item) @@ -105,10 +104,10 @@ class TabCustomizerActivity : BaseActivity() { finish() } } - fabCancel.setIcon(GoogleMaterial.Icon.gmd_close, Prefs.iconColor) - fabCancel.backgroundTintList = ColorStateList.valueOf(Prefs.accentColor) + fabCancel.setIcon(GoogleMaterial.Icon.gmd_close, prefs.iconColor) + fabCancel.backgroundTintList = ColorStateList.valueOf(prefs.accentColor) fabCancel.setOnClickListener { finish() } - setFrostColors { + setFrostColors(prefs) { 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 64051929..01fad8fa 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt @@ -56,7 +56,6 @@ import com.pitchedapps.frost.contracts.FrostContentContainer import com.pitchedapps.frost.contracts.VideoViewHolder import com.pitchedapps.frost.enums.OverlayContext import com.pitchedapps.frost.facebook.FB_URL_BASE -import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.facebook.USER_AGENT import com.pitchedapps.frost.facebook.USER_AGENT_DESKTOP_CONST @@ -67,7 +66,6 @@ import com.pitchedapps.frost.utils.ARG_URL import com.pitchedapps.frost.utils.ARG_USER_ID import com.pitchedapps.frost.utils.BiometricUtils import com.pitchedapps.frost.utils.L -import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.Showcase import com.pitchedapps.frost.utils.frostSnackbar import com.pitchedapps.frost.utils.setFrostColors @@ -78,6 +76,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch import okhttp3.HttpUrl.Companion.toHttpUrlOrNull +import org.koin.android.ext.android.inject /** * Created by Allan Wang on 2017-06-01. @@ -170,6 +169,8 @@ abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT get() = content.coreView private val coordinator: CoordinatorLayout by bindView(R.id.overlay_main_content) + private val showcasePrefs: Showcase by inject() + private inline val urlTest: String? get() = intent.getStringExtra(ARG_URL) ?: intent.dataString @@ -184,7 +185,7 @@ abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT override val baseEnum: FbItem? = null private inline val userId: Long - get() = intent.getLongExtra(ARG_USER_ID, Prefs.userId) + get() = intent.getLongExtra(ARG_USER_ID, prefs.userId) private val overlayContext: OverlayContext? get() = OverlayContext[intent.extras] @@ -205,14 +206,14 @@ abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT setSupportActionBar(toolbar) supportActionBar?.setDisplayShowHomeEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true) - toolbar.navigationIcon = GoogleMaterial.Icon.gmd_close.toDrawable(this, 16, Prefs.iconColor) + toolbar.navigationIcon = GoogleMaterial.Icon.gmd_close.toDrawable(this, 16, prefs.iconColor) toolbar.setNavigationOnClickListener { finishSlideOut() } - setFrostColors { + setFrostColors(prefs) { toolbar(toolbar) themeWindow = false } - coordinator.setBackgroundColor(Prefs.bgColor.withAlpha(255)) + coordinator.setBackgroundColor(prefs.bgColor.withAlpha(255)) content.bind(this) @@ -222,15 +223,15 @@ abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT with(web) { userAgentString = userAgent - Prefs.prevId = Prefs.userId + prefs.prevId = prefs.userId launch { - val authDefer = BiometricUtils.authenticate(this@WebOverlayActivityBase) - if (userId != Prefs.userId) { - FbCookie.switchUser(userId) + val authDefer = BiometricUtils.authenticate(this@WebOverlayActivityBase, prefs) + if (userId != prefs.userId) { + fbCookie.switchUser(userId) } authDefer.await() reloadBase(true) - if (Showcase.firstWebOverlay) { + if (showcasePrefs.firstWebOverlay) { coordinator.frostSnackbar(R.string.web_overlay_swipe_hint) { duration = BaseTransientBottomBar.LENGTH_INDEFINITE setAction(R.string.kau_got_it) { dismiss() } @@ -240,7 +241,7 @@ abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT } swipeBack = kauSwipeOnCreate { - if (!Prefs.overlayFullScreenSwipe) edgeSize = 20.dpToPx + if (!prefs.overlayFullScreenSwipe) edgeSize = 20.dpToPx transitionSystemBars = false } } @@ -271,13 +272,13 @@ abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT * Our theme for the overlay should be fully opaque */ fun theme() { - val opaqueAccent = Prefs.headerColor.withAlpha(255) + val opaqueAccent = prefs.headerColor.withAlpha(255) statusBarColor = opaqueAccent.darken() navigationBarColor = opaqueAccent toolbar.setBackgroundColor(opaqueAccent) - toolbar.setTitleTextColor(Prefs.iconColor) - coordinator.setBackgroundColor(Prefs.bgColor.withAlpha(255)) - toolbar.overflowIcon?.setTint(Prefs.iconColor) + toolbar.setTitleTextColor(prefs.iconColor) + coordinator.setBackgroundColor(prefs.bgColor.withAlpha(255)) + toolbar.overflowIcon?.setTint(prefs.iconColor) } override fun onResume() { @@ -312,7 +313,7 @@ abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_web, menu) overlayContext?.onMenuCreate(this, menu) - toolbar.tint(Prefs.iconColor) + toolbar.tint(prefs.iconColor) return true } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt b/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt index d90ff3de..1b90b1e3 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt @@ -68,4 +68,4 @@ suspend fun CookieDao.selectById(id: Long) = dao { _selectById(id) } suspend fun CookieDao.save(cookie: CookieEntity) = dao { _save(cookie) } suspend fun CookieDao.save(cookies: List<CookieEntity>) = dao { _save(cookies) } suspend fun CookieDao.deleteById(id: Long) = dao { _deleteById(id) } -suspend fun CookieDao.currentCookie() = selectById(Prefs.userId) +suspend fun CookieDao.currentCookie() = selectById(Prefs.get().userId) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt b/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt index 5519f6a8..e54daa69 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt @@ -93,8 +93,8 @@ class FrostDatabase( return FrostDatabase(privateDb, publicDb) } - fun module(context: Context) = module { - single { create(context) } + fun module() = module { + single { create(get()) } single { get<FrostDatabase>().cookieDao() } single { get<FrostDatabase>().cacheDao() } single { get<FrostDatabase>().notifDao() } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/enums/MainActivityLayout.kt b/app/src/main/kotlin/com/pitchedapps/frost/enums/MainActivityLayout.kt index 92aa93ab..4f6d6a29 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/enums/MainActivityLayout.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/enums/MainActivityLayout.kt @@ -24,17 +24,17 @@ import com.pitchedapps.frost.utils.Prefs */ enum class MainActivityLayout( val titleRes: Int, - val backgroundColor: () -> Int, - val iconColor: () -> Int + val backgroundColor: (Prefs) -> Int, + val iconColor: (Prefs) -> Int ) { TOP_BAR(R.string.top_bar, - { Prefs.headerColor }, - { Prefs.iconColor }), + { it.headerColor }, + { it.iconColor }), BOTTOM_BAR(R.string.bottom_bar, - { Prefs.bgColor }, - { Prefs.textColor }); + { it.bgColor }, + { it.textColor }); companion object { val values = values() // save one instance 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 6c911e9c..23fa2ebf 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/enums/Theme.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/enums/Theme.kt @@ -33,11 +33,11 @@ const val BLUE_LIGHT = 0xff5d86dd.toInt() enum class Theme( @StringRes val textRes: Int, val injector: InjectorContract, - private val textColorGetter: () -> Int, - private val accentColorGetter: () -> Int, - private val backgroundColorGetter: () -> Int, - private val headerColorGetter: () -> Int, - private val iconColorGetter: () -> Int + val textColorGetter: (Prefs) -> Int, + val accentColorGetter: (Prefs) -> Int, + val backgroundColorGetter: (Prefs) -> Int, + val headerColorGetter: (Prefs) -> Int, + val iconColorGetter: (Prefs) -> Int ) { DEFAULT(R.string.kau_default, @@ -82,26 +82,11 @@ enum class Theme( CUSTOM(R.string.kau_custom, CssAssets.CUSTOM, - { Prefs.customTextColor }, - { Prefs.customAccentColor }, - { Prefs.customBackgroundColor }, - { Prefs.customHeaderColor }, - { Prefs.customIconColor }); - - val textColor: Int - get() = textColorGetter() - - val accentColor: Int - get() = accentColorGetter() - - val bgColor: Int - get() = backgroundColorGetter() - - val headerColor: Int - get() = headerColorGetter() - - val iconColor: Int - get() = iconColorGetter() + { it.customTextColor }, + { it.customAccentColor }, + { it.customBackgroundColor }, + { it.customHeaderColor }, + { it.customIconColor }); companion object { val values = values() // save one instance diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt index 8d827947..23f67b3e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt @@ -21,7 +21,6 @@ import android.content.Context import android.webkit.CookieManager import com.pitchedapps.frost.db.CookieDao import com.pitchedapps.frost.db.CookieEntity -import com.pitchedapps.frost.db.FrostDatabase import com.pitchedapps.frost.db.deleteById import com.pitchedapps.frost.db.save import com.pitchedapps.frost.db.selectById @@ -35,27 +34,30 @@ import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.withContext +import org.koin.dsl.module /** * Created by Allan Wang on 2017-05-30. * * The following component manages all cookie transfers. */ -object FbCookie { +class FbCookie(private val prefs: Prefs, private val cookieDao: CookieDao) { - const val COOKIE_DOMAIN = FB_URL_BASE + companion object { + private const val COOKIE_DOMAIN = FB_URL_BASE + + fun module() = module { + single { FbCookie(get(), get()) } + } + } /** * Retrieves the facebook cookie if it exists * Note that this is a synchronized call */ - inline val webCookie: String? + val webCookie: String? get() = CookieManager.getInstance().getCookie(COOKIE_DOMAIN) - private val cookieDao: CookieDao by lazy { - FrostDatabase.get().cookieDao() - } - private suspend fun CookieManager.suspendSetWebCookie(cookie: String?): Boolean { cookie ?: return true return withContext(NonCancellable) { @@ -86,14 +88,14 @@ object FbCookie { suspend fun save(id: Long) { L.d { "New cookie found" } - Prefs.userId = id + prefs.userId = id CookieManager.getInstance().flush() - val cookie = CookieEntity(Prefs.userId, null, webCookie) + val cookie = CookieEntity(prefs.userId, null, webCookie) cookieDao.save(cookie) } suspend fun reset() { - Prefs.userId = -1L + prefs.userId = -1L with(CookieManager.getInstance()) { removeAllCookies() flush() @@ -112,7 +114,7 @@ object FbCookie { } withContext(NonCancellable) { L.d { "Switching User" } - Prefs.userId = cookie.id + prefs.userId = cookie.id CookieManager.getInstance().suspendSetWebCookie(cookie.cookie) } } @@ -124,8 +126,8 @@ object FbCookie { suspend fun logout(context: Context) { val cookies = arrayListOf<CookieEntity>() if (context is Activity) - cookies.addAll(context.cookies().filter { it.id != Prefs.userId }) - logout(Prefs.userId) + cookies.addAll(context.cookies().filter { it.id != prefs.userId }) + logout(prefs.userId) context.launchLogin(cookies, true) } @@ -145,13 +147,13 @@ object FbCookie { * When coming back to the main app, switch back to our original account before continuing */ suspend fun switchBackUser() { - if (Prefs.prevId == -1L) return - val prevId = Prefs.prevId - Prefs.prevId = -1L - if (prevId != Prefs.userId) { + if (prefs.prevId == -1L) return + val prevId = prefs.prevId + prefs.prevId = -1L + if (prevId != prefs.userId) { switchUser(prevId) L.d { "Switch back user" } - L._d { "${Prefs.userId} to $prevId" } + L._d { "${prefs.userId} to $prevId" } } } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt index a2399d7c..257611e8 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt @@ -32,6 +32,7 @@ import com.pitchedapps.frost.contracts.FrostContentParent import com.pitchedapps.frost.contracts.MainActivityContract import com.pitchedapps.frost.contracts.MainFabContract import com.pitchedapps.frost.enums.FeedSort +import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.utils.ARG_URL import com.pitchedapps.frost.utils.L @@ -47,6 +48,7 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.channels.ReceiveChannel import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +import org.koin.android.ext.android.inject /** * Created by Allan Wang on 2017-11-07. @@ -55,7 +57,8 @@ import kotlinx.coroutines.launch * Must be attached to activities implementing [MainActivityContract] */ @UseExperimental(ExperimentalCoroutinesApi::class) -abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract, DynamicUiContract { +abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract, + DynamicUiContract { companion object { private const val ARG_POSITION = "arg_position" @@ -63,12 +66,13 @@ abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract, Dyna internal operator fun invoke( base: () -> BaseFragment, + prefs: Prefs, useFallback: Boolean, data: FbItem, position: Int ): BaseFragment { val fragment = if (useFallback) WebFragment() else base() - val d = if (data == FbItem.FEED) FeedSort(Prefs.feedSort).item else data + val d = if (data == FbItem.FEED) FeedSort(prefs.feedSort).item else data fragment.withArguments( ARG_URL to d.url, ARG_POSITION to position @@ -78,6 +82,8 @@ abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract, Dyna } } + protected val fbCookie: FbCookie by inject() + protected val prefs: Prefs by inject() open lateinit var job: Job override val coroutineContext: CoroutineContext get() = ContextHelper.dispatcher + job @@ -195,10 +201,10 @@ abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract, Dyna protected fun FloatingActionButton.update(iicon: IIcon, click: () -> Unit) { if (isShown) { fadeScaleTransition { - setIcon(iicon, Prefs.iconColor) + setIcon(iicon, prefs.iconColor) } } else { - setIcon(iicon, Prefs.iconColor) + setIcon(iicon, prefs.iconColor) show() } setOnClickListener { click() } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt index 21ba17ae..51beab93 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt @@ -23,7 +23,6 @@ import com.mikepenz.fastadapter.GenericItem import com.mikepenz.fastadapter.adapters.ItemAdapter import com.mikepenz.fastadapter.adapters.ModelAdapter import com.pitchedapps.frost.R -import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.parsers.FrostParser import com.pitchedapps.frost.facebook.parsers.ParseData import com.pitchedapps.frost.facebook.parsers.ParseResponse @@ -130,7 +129,7 @@ abstract class FrostParserFragment<T : ParseData, Item : GenericItem> : override suspend fun reloadImpl(progress: (Int) -> Unit): List<Item>? = withContext(Dispatchers.IO) { progress(10) - val cookie = FbCookie.webCookie + val cookie = fbCookie.webCookie val doc = getDoc(cookie) progress(60) val response = try { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt index f45ffa6d..35b390c4 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt @@ -40,6 +40,6 @@ class NotificationFragment : FrostParserFragment<FrostNotifs, NotificationIItem> response.data.notifs.map { NotificationIItem(it, response.cookie) } override fun bindImpl(recyclerView: FrostRecyclerView) { - NotificationIItem.bindEvents(adapter) + NotificationIItem.bindEvents(adapter, fbCookie) } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt index a6b4eae7..502c37fb 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt @@ -23,7 +23,6 @@ import com.pitchedapps.frost.contracts.MainFabContract import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.injectors.JsActions import com.pitchedapps.frost.utils.L -import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.views.FrostWebView import com.pitchedapps.frost.web.FrostWebViewClient import com.pitchedapps.frost.web.FrostWebViewClientMenu @@ -52,9 +51,9 @@ class WebFragment : BaseFragment() { L.e { "Webview not found in fragment $baseEnum" } return super.updateFab(contract) } - if (baseEnum.isFeed && Prefs.showCreateFab) { + if (baseEnum.isFeed && prefs.showCreateFab) { contract.showFab(GoogleMaterial.Icon.gmd_edit) { - JsActions.CREATE_POST.inject(web) + JsActions.CREATE_POST.inject(web, prefs) } return } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/glide/GlideUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/glide/GlideUtils.kt index 537ad89c..1ae46c15 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/glide/GlideUtils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/glide/GlideUtils.kt @@ -30,6 +30,8 @@ import com.pitchedapps.frost.facebook.FbCookie import okhttp3.Interceptor import okhttp3.OkHttpClient import okhttp3.Response +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 28/12/17. @@ -63,10 +65,13 @@ class FrostGlideModule : AppGlideModule() { private fun getFrostHttpClient(): OkHttpClient = OkHttpClient.Builder().addInterceptor(FrostCookieInterceptor()).build() -class FrostCookieInterceptor : Interceptor { +class FrostCookieInterceptor : Interceptor, KoinComponent { + + private val fbCookie: FbCookie by inject() + override fun intercept(chain: Interceptor.Chain): Response { val origRequest = chain.request() - val cookie = FbCookie.webCookie ?: return chain.proceed(origRequest) + val cookie = fbCookie.webCookie ?: return chain.proceed(origRequest) val request = origRequest.newBuilder().addHeader("Cookie", cookie).build() return chain.proceed(request) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/iitems/GenericIItems.kt b/app/src/main/kotlin/com/pitchedapps/frost/iitems/GenericIItems.kt index ca8bf352..1262c078 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/iitems/GenericIItems.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/iitems/GenericIItems.kt @@ -27,8 +27,11 @@ import com.mikepenz.fastadapter.GenericItem import com.mikepenz.fastadapter.IAdapter import com.mikepenz.fastadapter.select.selectExtension import com.pitchedapps.frost.R +import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.launchWebOverlay +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 30/12/17. @@ -41,20 +44,20 @@ interface ClickableIItemContract { val url: String? - fun click(context: Context) { + fun click(context: Context, fbCookie: FbCookie) { val url = url ?: return - context.launchWebOverlay(url) + context.launchWebOverlay(url, fbCookie) } companion object { - fun bindEvents(adapter: IAdapter<GenericItem>) { + fun bindEvents(adapter: IAdapter<GenericItem>, fbCookie: FbCookie) { adapter.fastAdapter?.apply { selectExtension { isSelectable = false } onClickListener = { v, _, item, _ -> if (item is ClickableIItemContract) { - item.click(v!!.context) + item.click(v!!.context, fbCookie) true } else false @@ -73,14 +76,16 @@ open class HeaderIItem( itemId: Int = R.layout.iitem_header ) : KauIItem<HeaderIItem.ViewHolder>(R.layout.iitem_header, ::ViewHolder, itemId) { - class ViewHolder(itemView: View) : FastAdapter.ViewHolder<HeaderIItem>(itemView) { + class ViewHolder(itemView: View) : FastAdapter.ViewHolder<HeaderIItem>(itemView), KoinComponent { + + private val prefs: Prefs by inject() val text: TextView by bindView(R.id.item_header_text) override fun bindView(item: HeaderIItem, payloads: MutableList<Any>) { - text.setTextColor(Prefs.accentColor) + text.setTextColor(prefs.accentColor) text.text = item.text - text.setBackgroundColor(Prefs.nativeBgColor) + text.setBackgroundColor(prefs.nativeBgColor) } override fun unbindView(item: HeaderIItem) { @@ -100,14 +105,16 @@ open class TextIItem( ) : KauIItem<TextIItem.ViewHolder>(R.layout.iitem_text, ::ViewHolder, itemId), ClickableIItemContract { - class ViewHolder(itemView: View) : FastAdapter.ViewHolder<TextIItem>(itemView) { + class ViewHolder(itemView: View) : FastAdapter.ViewHolder<TextIItem>(itemView), KoinComponent { + + private val prefs: Prefs by inject() val text: TextView by bindView(R.id.item_text_view) override fun bindView(item: TextIItem, payloads: MutableList<Any>) { - text.setTextColor(Prefs.textColor) + text.setTextColor(prefs.textColor) text.text = item.text - text.background = createSimpleRippleDrawable(Prefs.bgColor, Prefs.nativeBgColor) + text.background = createSimpleRippleDrawable(prefs.bgColor, prefs.nativeBgColor) } override fun unbindView(item: TextIItem) { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt b/app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt index b2d328ec..8624fff0 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt @@ -31,6 +31,7 @@ import com.mikepenz.fastadapter.adapters.ItemAdapter import com.mikepenz.fastadapter.diff.DiffCallback import com.mikepenz.fastadapter.select.selectExtension import com.pitchedapps.frost.R +import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.facebook.parsers.FrostNotif import com.pitchedapps.frost.glide.FrostGlide @@ -38,6 +39,8 @@ import com.pitchedapps.frost.glide.GlideApp import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.isIndependent import com.pitchedapps.frost.utils.launchWebOverlay +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 27/12/17. @@ -48,7 +51,7 @@ class NotificationIItem(val notification: FrostNotif, val cookie: String) : ) { companion object { - fun bindEvents(adapter: ItemAdapter<NotificationIItem>) { + fun bindEvents(adapter: ItemAdapter<NotificationIItem>, fbCookie: FbCookie) { adapter.fastAdapter?.apply { selectExtension { isSelectable = false @@ -62,7 +65,7 @@ class NotificationIItem(val notification: FrostNotif, val cookie: String) : ) } // TODO temp fix. If url is dependent, we cannot load it directly - v!!.context.launchWebOverlay(if (notif.url.isIndependent) notif.url else FbItem.NOTIFICATIONS.url) + v!!.context.launchWebOverlay(if (notif.url.isIndependent) notif.url else FbItem.NOTIFICATIONS.url, fbCookie) true } } @@ -93,7 +96,9 @@ class NotificationIItem(val notification: FrostNotif, val cookie: String) : } } - class ViewHolder(itemView: View) : FastAdapter.ViewHolder<NotificationIItem>(itemView) { + class ViewHolder(itemView: View) : FastAdapter.ViewHolder<NotificationIItem>(itemView), KoinComponent { + + private val prefs: Prefs by inject() private val frame: ViewGroup by bindView(R.id.item_frame) private val avatar: ImageView by bindView(R.id.item_avatar) @@ -107,11 +112,11 @@ class NotificationIItem(val notification: FrostNotif, val cookie: String) : override fun bindView(item: NotificationIItem, payloads: MutableList<Any>) { val notif = item.notification frame.background = createSimpleRippleDrawable( - Prefs.textColor, - Prefs.nativeBgColor(notif.unread) + prefs.textColor, + prefs.nativeBgColor(notif.unread) ) - content.setTextColor(Prefs.textColor) - date.setTextColor(Prefs.textColor.withAlpha(150)) + content.setTextColor(prefs.textColor) + date.setTextColor(prefs.textColor.withAlpha(150)) val glide = glide glide.load(notif.img) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/iitems/TabIItem.kt b/app/src/main/kotlin/com/pitchedapps/frost/iitems/TabIItem.kt index 186e6288..c1998c04 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/iitems/TabIItem.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/iitems/TabIItem.kt @@ -30,6 +30,8 @@ import com.mikepenz.fastadapter.drag.IDraggable import com.pitchedapps.frost.R import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.utils.Prefs +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 26/11/17. @@ -41,14 +43,16 @@ class TabIItem(val item: FbItem) : KauIItem<TabIItem.ViewHolder>( override val isDraggable: Boolean = true - class ViewHolder(itemView: View) : FastAdapter.ViewHolder<TabIItem>(itemView) { + class ViewHolder(itemView: View) : FastAdapter.ViewHolder<TabIItem>(itemView), KoinComponent { + + private val prefs: Prefs by inject() val image: ImageView by bindView(R.id.image) val text: TextView by bindView(R.id.text) override fun bindView(item: TabIItem, payloads: MutableList<Any>) { val isInToolbar = adapterPosition < 4 - val color = if (isInToolbar) Prefs.iconColor else Prefs.textColor + val color = if (isInToolbar) prefs.iconColor else prefs.textColor image.setIcon(item.item.icon, 20, color) if (isInToolbar) text.invisible() diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt index 1b210251..b485c04c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt @@ -20,7 +20,6 @@ import android.content.Context import android.graphics.Color import android.webkit.WebView import androidx.annotation.VisibleForTesting -import ca.allanwang.kau.kotlin.lazyContext import ca.allanwang.kau.utils.adjustAlpha import ca.allanwang.kau.utils.colorToBackground import ca.allanwang.kau.utils.colorToForeground @@ -50,29 +49,38 @@ enum class CssAssets(val folder: String = THEME_FOLDER) : InjectorContract { /** * Note that while this can be loaded from any thread, it is typically done through [load] */ - private val injector = lazyContext { + private var injector: JsInjector? = null + + private fun injector(context: Context, prefs: Prefs): JsInjector = + injector ?: createInjector(context, prefs).also { injector = it } + + /** + * Note that while this can be loaded from any thread, it is typically done through [load] + */ + private fun createInjector(context: Context, prefs: Prefs): JsInjector = try { var content = - it.assets.open("css/$folder/$file").bufferedReader().use(BufferedReader::readText) + context.assets.open("css/$folder/$file").bufferedReader() + .use(BufferedReader::readText) if (this == CUSTOM) { - val bt = if (Color.alpha(Prefs.bgColor) == 255) - Prefs.bgColor.toRgbaString() + val bt = if (Color.alpha(prefs.bgColor) == 255) + prefs.bgColor.toRgbaString() else "transparent" - val bb = Prefs.bgColor.colorToForeground(0.35f) + val bb = prefs.bgColor.colorToForeground(0.35f) content = content - .replace("\$T\$", Prefs.textColor.toRgbaString()) - .replace("\$TT\$", Prefs.textColor.colorToBackground(0.05f).toRgbaString()) - .replace("\$A\$", Prefs.accentColor.toRgbaString()) - .replace("\$AT\$", Prefs.iconColor.toRgbaString()) - .replace("\$B\$", Prefs.bgColor.toRgbaString()) + .replace("\$T\$", prefs.textColor.toRgbaString()) + .replace("\$TT\$", prefs.textColor.colorToBackground(0.05f).toRgbaString()) + .replace("\$A\$", prefs.accentColor.toRgbaString()) + .replace("\$AT\$", prefs.iconColor.toRgbaString()) + .replace("\$B\$", prefs.bgColor.toRgbaString()) .replace("\$BT\$", bt) .replace("\$BBT\$", bb.withAlpha(51).toRgbaString()) - .replace("\$O\$", Prefs.bgColor.withAlpha(255).toRgbaString()) + .replace("\$O\$", prefs.bgColor.withAlpha(255).toRgbaString()) .replace("\$OO\$", bb.withAlpha(255).toRgbaString()) - .replace("\$D\$", Prefs.textColor.adjustAlpha(0.3f).toRgbaString()) + .replace("\$D\$", prefs.textColor.adjustAlpha(0.3f).toRgbaString()) .replace("\$TI\$", bb.withAlpha(60).toRgbaString()) .replace("\$C\$", bt) } @@ -81,24 +89,24 @@ enum class CssAssets(val folder: String = THEME_FOLDER) : InjectorContract { L.e(e) { "CssAssets file not found" } JsInjector(JsActions.EMPTY.function) } - } - override fun inject(webView: WebView) = - injector(webView.context).inject(webView) + override fun inject(webView: WebView, prefs: Prefs) = + injector(webView.context, prefs).inject(webView, prefs) fun reset() { - injector.invalidate() + injector = null } companion object { + // Ensures that all non themes and the selected theme are loaded - suspend fun load(context: Context) { + suspend fun load(context: Context, prefs: Prefs) { withContext(Dispatchers.IO) { - val currentTheme = Prefs.t.injector as? CssAssets + val currentTheme = prefs.t.injector as? CssAssets val (themes, others) = CssAssets.values().partition { it.folder == THEME_FOLDER } themes.filter { it != currentTheme }.forEach { it.reset() } - currentTheme?.injector?.invoke(context) - others.forEach { it.injector.invoke(context) } + currentTheme?.injector(context, prefs) + others.forEach { it.injector(context, prefs) } } } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt index 4c53dcda..94367853 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt @@ -17,6 +17,7 @@ package com.pitchedapps.frost.injectors import android.webkit.WebView +import com.pitchedapps.frost.utils.Prefs /** * Created by Allan Wang on 2017-05-31. @@ -53,6 +54,6 @@ enum class CssHider(vararg val items: String) : InjectorContract { .single(name).build() } - override fun inject(webView: WebView) = - injector.inject(webView) + override fun inject(webView: WebView, prefs: Prefs) = + injector.inject(webView, prefs) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt index 175837ca..72138f5b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt @@ -18,6 +18,7 @@ package com.pitchedapps.frost.injectors import android.webkit.WebView import com.pitchedapps.frost.facebook.FB_URL_BASE +import com.pitchedapps.frost.utils.Prefs /** * Created by Allan Wang on 2017-05-31. @@ -42,8 +43,8 @@ enum class JsActions(body: String) : InjectorContract { val function = "(function(){$body})();" - override fun inject(webView: WebView) = - JsInjector(function).inject(webView) + override fun inject(webView: WebView, prefs: Prefs) = + JsInjector(function).inject(webView, prefs) } @Suppress("NOTHING_TO_INLINE") diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt index f5a0713f..03ab6e96 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt @@ -21,6 +21,7 @@ import android.webkit.WebView import androidx.annotation.VisibleForTesting import ca.allanwang.kau.kotlin.lazyContext import com.pitchedapps.frost.utils.L +import com.pitchedapps.frost.utils.Prefs import java.io.BufferedReader import java.io.FileNotFoundException import java.util.Locale @@ -49,14 +50,14 @@ enum class JsAssets : InjectorContract { } } - override fun inject(webView: WebView) = - injector(webView.context).inject(webView) + override fun inject(webView: WebView, prefs: Prefs) = + injector(webView.context).inject(webView, prefs) companion object { // Ensures that all non themes and the selected theme are loaded suspend fun load(context: Context) { withContext(Dispatchers.IO) { - JsAssets.values().forEach { it.injector.invoke(context) } + values().forEach { it.injector.invoke(context) } } } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt index 586ff393..18c51161 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt @@ -19,6 +19,7 @@ package com.pitchedapps.frost.injectors import android.webkit.WebView import androidx.annotation.VisibleForTesting import com.pitchedapps.frost.utils.L +import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.web.FrostWebViewClient import kotlin.random.Random import org.apache.commons.text.StringEscapeUtils @@ -83,7 +84,7 @@ class JsBuilder { * Contract for all injectors to allow it to interact properly with a webview */ interface InjectorContract { - fun inject(webView: WebView) + fun inject(webView: WebView, prefs: Prefs) /** * Toggle the injector (usually through Prefs * If false, will fallback to an empty action @@ -94,19 +95,19 @@ interface InjectorContract { /** * Helper method to inject multiple functions simultaneously with a single callback */ -fun WebView.jsInject(vararg injectors: InjectorContract) { +fun WebView.jsInject(vararg injectors: InjectorContract, prefs: Prefs) { injectors.filter { it != JsActions.EMPTY }.forEach { - it.inject(this) + it.inject(this, prefs) } } -fun FrostWebViewClient.jsInject(vararg injectors: InjectorContract) = web.jsInject(*injectors) +fun FrostWebViewClient.jsInject(vararg injectors: InjectorContract, prefs: Prefs) = web.jsInject(*injectors, prefs = prefs) /** * Wrapper class to convert a function into an injector */ class JsInjector(val function: String) : InjectorContract { - override fun inject(webView: WebView) = + override fun inject(webView: WebView, prefs: Prefs) = webView.evaluateJavascript(function, null) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroFragmentTheme.kt b/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroFragmentTheme.kt index 4561fa6e..6e735e5b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroFragmentTheme.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroFragmentTheme.kt @@ -23,7 +23,6 @@ import com.pitchedapps.frost.R import com.pitchedapps.frost.activities.IntroActivity import com.pitchedapps.frost.databinding.IntroThemeBinding import com.pitchedapps.frost.enums.Theme -import com.pitchedapps.frost.utils.Prefs /** * Created by Allan Wang on 2017-07-28. @@ -56,7 +55,7 @@ class IntroFragmentTheme : BaseIntroFragment(R.layout.intro_theme) { introThemeDark.setThemeClick(Theme.DARK) introThemeAmoled.setThemeClick(Theme.AMOLED) introThemeGlass.setThemeClick(Theme.GLASS) - val currentTheme = Prefs.theme - 1 + val currentTheme = prefs.theme - 1 if (currentTheme in 0..3) themeList.forEachIndexed { index, v -> v.scaleXY = if (index == currentTheme) 1.6f else 0.8f @@ -65,9 +64,9 @@ class IntroFragmentTheme : BaseIntroFragment(R.layout.intro_theme) { private fun View.setThemeClick(theme: Theme) { setOnClickListener { v -> - Prefs.theme = theme.ordinal + prefs.theme = theme.ordinal (activity as IntroActivity).apply { - binding.ripple.ripple(Prefs.bgColor, v.x + v.pivotX, v.y + v.pivotY) + binding.ripple.ripple(prefs.bgColor, v.x + v.pivotX, v.y + v.pivotY) theme() } themeList.forEach { it.animate().scaleXY(if (it == this) 1.6f else 0.8f).start() } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroImageFragments.kt b/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroImageFragments.kt index 9a4ec0c1..429171dd 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroImageFragments.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroImageFragments.kt @@ -29,7 +29,6 @@ import ca.allanwang.kau.utils.visible import ca.allanwang.kau.utils.withAlpha import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.pitchedapps.frost.R -import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.launchTabCustomizerActivity import kotlin.math.abs @@ -58,10 +57,10 @@ abstract class BaseImageIntroFragment( override fun themeFragmentImpl() { super.themeFragmentImpl() - title.setTextColor(Prefs.textColor) - desc.setTextColor(Prefs.textColor) - phone.tint(Prefs.textColor) - screen.tint(Prefs.bgColor) + title.setTextColor(prefs.textColor) + desc.setTextColor(prefs.textColor) + phone.tint(prefs.textColor) + screen.tint(prefs.bgColor) } fun themeImageComponent(color: Int, vararg id: Int) { @@ -97,9 +96,9 @@ class IntroAccountFragment : BaseImageIntroFragment( override fun themeFragmentImpl() { super.themeFragmentImpl() - themeImageComponent(Prefs.iconColor, R.id.intro_phone_avatar_1, R.id.intro_phone_avatar_2) - themeImageComponent(Prefs.bgColor.colorToForeground(), R.id.intro_phone_nav) - themeImageComponent(Prefs.headerColor, R.id.intro_phone_header) + themeImageComponent(prefs.iconColor, R.id.intro_phone_avatar_1, R.id.intro_phone_avatar_2) + themeImageComponent(prefs.bgColor.colorToForeground(), R.id.intro_phone_nav) + themeImageComponent(prefs.headerColor, R.id.intro_phone_header) } override fun onPageScrolledImpl(positionOffset: Float) { @@ -123,14 +122,14 @@ class IntroTabTouchFragment : BaseImageIntroFragment( override fun themeFragmentImpl() { super.themeFragmentImpl() themeImageComponent( - Prefs.iconColor, + prefs.iconColor, R.id.intro_phone_icon_1, R.id.intro_phone_icon_2, R.id.intro_phone_icon_3, R.id.intro_phone_icon_4 ) - themeImageComponent(Prefs.headerColor, R.id.intro_phone_tab) - themeImageComponent(Prefs.textColor.withAlpha(80), R.id.intro_phone_icon_ripple) + themeImageComponent(prefs.headerColor, R.id.intro_phone_tab) + themeImageComponent(prefs.textColor.withAlpha(80), R.id.intro_phone_icon_ripple) } } @@ -142,21 +141,21 @@ class IntroTabContextFragment : BaseImageIntroFragment( override fun themeFragmentImpl() { super.themeFragmentImpl() - themeImageComponent(Prefs.headerColor, R.id.intro_phone_toolbar) - themeImageComponent(Prefs.bgColor.colorToForeground(0.1f), R.id.intro_phone_image) + themeImageComponent(prefs.headerColor, R.id.intro_phone_toolbar) + themeImageComponent(prefs.bgColor.colorToForeground(0.1f), R.id.intro_phone_image) themeImageComponent( - Prefs.bgColor.colorToForeground(0.2f), + prefs.bgColor.colorToForeground(0.2f), R.id.intro_phone_like, R.id.intro_phone_share ) - themeImageComponent(Prefs.bgColor.colorToForeground(0.3f), R.id.intro_phone_comment) + themeImageComponent(prefs.bgColor.colorToForeground(0.3f), R.id.intro_phone_comment) themeImageComponent( - Prefs.bgColor.colorToForeground(0.1f), + prefs.bgColor.colorToForeground(0.1f), R.id.intro_phone_card_1, R.id.intro_phone_card_2 ) themeImageComponent( - Prefs.textColor, + prefs.textColor, R.id.intro_phone_image_indicator, R.id.intro_phone_comment_indicator, R.id.intro_phone_card_indicator diff --git a/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroMainFragments.kt b/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroMainFragments.kt index c86e560c..4c01f5e0 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroMainFragments.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroMainFragments.kt @@ -38,6 +38,7 @@ import com.pitchedapps.frost.activities.IntroActivity import com.pitchedapps.frost.databinding.IntroAnalyticsBinding import com.pitchedapps.frost.utils.Prefs import kotlin.math.abs +import org.koin.android.ext.android.inject /** * Created by Allan Wang on 2017-07-28. @@ -50,6 +51,8 @@ import kotlin.math.abs */ abstract class BaseIntroFragment(val layoutRes: Int) : Fragment() { + protected val prefs: Prefs by inject() + val screenWidth get() = resources.displayMetrics.widthPixels @@ -105,7 +108,7 @@ abstract class BaseIntroFragment(val layoutRes: Int) : Fragment() { } protected open fun themeFragmentImpl() { - (view as? ViewGroup)?.children?.forEach { (it as? TextView)?.setTextColor(Prefs.textColor) } + (view as? ViewGroup)?.children?.forEach { (it as? TextView)?.setTextColor(prefs.textColor) } } protected val viewArray: Array<Array<out View>> by lazyResettableRegistered { viewArray() } @@ -134,7 +137,7 @@ class IntroFragmentWelcome : BaseIntroFragment(R.layout.intro_welcome) { override fun themeFragmentImpl() { super.themeFragmentImpl() - image.imageTintList = ColorStateList.valueOf(Prefs.textColor) + image.imageTintList = ColorStateList.valueOf(prefs.textColor) } } @@ -153,7 +156,7 @@ class IntroFragmentAnalytics : BaseIntroFragment(R.layout.intro_analytics) { override fun themeFragmentImpl() { super.themeFragmentImpl() - image.imageTintList = ColorStateList.valueOf(Prefs.textColor) + image.imageTintList = ColorStateList.valueOf(prefs.textColor) } @SuppressLint("ClickableViewAccessibility") @@ -165,9 +168,9 @@ class IntroFragmentAnalytics : BaseIntroFragment(R.layout.intro_analytics) { private fun IntroAnalyticsBinding.init() { image.setIcon(GoogleMaterial.Icon.gmd_bug_report, 120) - introSwitch.isSelected = Prefs.analytics + introSwitch.isSelected = prefs.analytics introSwitch.setOnCheckedChangeListener { _, isChecked -> - Prefs.analytics = isChecked + prefs.analytics = isChecked } } } @@ -180,7 +183,7 @@ class IntroFragmentEnd : BaseIntroFragment(R.layout.intro_end) { override fun themeFragmentImpl() { super.themeFragmentImpl() - image.imageTintList = ColorStateList.valueOf(Prefs.textColor) + image.imageTintList = ColorStateList.valueOf(prefs.textColor) } @SuppressLint("ClickableViewAccessibility") diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt index 955d6482..7b20e07c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt @@ -67,7 +67,7 @@ enum class NotificationType( private val overlayContext: OverlayContext, private val fbItem: FbItem, private val parser: FrostParser<ParseNotification>, - private val ringtone: () -> String + private val ringtoneProvider: (Prefs) -> String ) { GENERAL( @@ -75,7 +75,7 @@ enum class NotificationType( OverlayContext.NOTIFICATION, FbItem.NOTIFICATIONS, NotifParser, - Prefs::notificationRingtone + { it.notificationRingtone } ), MESSAGE( @@ -83,7 +83,7 @@ enum class NotificationType( OverlayContext.MESSAGE, FbItem.MESSAGES, MessageParser, - Prefs::messageRingtone + { it.messageRingtone } ); private val groupPrefix = "frost_${name.toLowerCase(Locale.CANADA)}" @@ -112,7 +112,7 @@ enum class NotificationType( * Returns the number of notifications generated, * or -1 if an error occurred */ - suspend fun fetch(context: Context, data: CookieEntity): Int { + suspend fun fetch(context: Context, data: CookieEntity, prefs: Prefs): Int { val notifDao = FrostDatabase.get().notifDao() val response = try { parser.parse(data.cookie) @@ -129,7 +129,7 @@ enum class NotificationType( */ fun validText(text: String?): Boolean { val t = text ?: return true - return Prefs.notificationKeywords.none { + return prefs.notificationKeywords.none { t.contains(it, true) } } @@ -167,7 +167,7 @@ enum class NotificationType( frostEvent("Notifications", "Type" to name, "Count" to notifs.size) if (notifs.size > 1) summaryNotification(context, userId, notifs.size).notify(context) - val ringtone = ringtone() + val ringtone = ringtoneProvider(prefs) notifs.forEachIndexed { i, notif -> // Ring at most twice notif.withAlert(context, i < 2, ringtone).notify(context) @@ -316,9 +316,9 @@ data class FrostNotification( NotificationManagerCompat.from(context).notify(tag, id, notif.build()) } -fun Context.scheduleNotificationsFromPrefs(): Boolean { - val shouldSchedule = Prefs.hasNotifications - return if (shouldSchedule) scheduleNotifications(Prefs.notificationFreq) +fun Context.scheduleNotificationsFromPrefs(prefs: Prefs): Boolean { + val shouldSchedule = prefs.hasNotifications + return if (shouldSchedule) scheduleNotifications(prefs.notificationFreq) else scheduleNotifications(-1) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt index 95726974..73c97b5e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt @@ -34,6 +34,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlinx.coroutines.yield import org.koin.android.ext.android.inject +import org.koin.core.inject /** * Created by Allan Wang on 2017-06-14. @@ -45,7 +46,8 @@ import org.koin.android.ext.android.inject */ class NotificationService : BaseJobService() { - val cookieDao: CookieDao by inject() + private val prefs: Prefs by inject() + private val cookieDao: CookieDao by inject() override fun onStopJob(params: JobParameters?): Boolean { super.onStopJob(params) @@ -64,7 +66,7 @@ class NotificationService : BaseJobService() { frostEvent( "NotificationTime", "Type" to (if (abrupt) "Service force stop" else "Service"), - "IM Included" to Prefs.notificationsInstantMessages, + "IM Included" to prefs.notificationsInstantMessages, "Duration" to time ) } @@ -86,7 +88,7 @@ class NotificationService : BaseJobService() { private suspend fun sendNotifications(params: JobParameters?): Unit = withContext(Dispatchers.Default) { - val currentId = Prefs.userId + val currentId = prefs.userId val cookies = cookieDao.selectAll() yield() val jobId = params?.extras?.getInt(NOTIFICATION_PARAM_ID, -1) ?: -1 @@ -94,12 +96,12 @@ class NotificationService : BaseJobService() { for (cookie in cookies) { yield() val current = cookie.id == currentId - if (Prefs.notificationsGeneral && - (current || Prefs.notificationAllAccounts) + if (prefs.notificationsGeneral && + (current || prefs.notificationAllAccounts) ) notifCount += fetch(jobId, NotificationType.GENERAL, cookie) - if (Prefs.notificationsInstantMessages && - (current || Prefs.notificationsImAllAccounts) + if (prefs.notificationsInstantMessages && + (current || prefs.notificationsImAllAccounts) ) notifCount += fetch(jobId, NotificationType.MESSAGE, cookie) } @@ -117,7 +119,7 @@ class NotificationService : BaseJobService() { * Also normalized the output to return the number of notifications received */ private suspend fun fetch(jobId: Int, type: NotificationType, cookie: CookieEntity): Int { - val count = type.fetch(this, cookie) + val count = type.fetch(this, cookie, prefs) if (count < 0) { if (jobId == NOTIFICATION_JOB_NOW) generalNotification(666, R.string.error_notification, BuildConfig.DEBUG) @@ -133,7 +135,7 @@ class NotificationService : BaseJobService() { private fun generalNotification(id: Int, textRes: Int, withDefaults: Boolean) { val notifBuilder = frostNotification(NOTIF_CHANNEL_GENERAL) - .setFrostAlert(this, withDefaults, Prefs.notificationRingtone) + .setFrostAlert(this, withDefaults, prefs.notificationRingtone) .setContentTitle(string(R.string.frost_name)) .setContentText(string(textRes)) NotificationManagerCompat.from(this).notify(id, notifBuilder.build()) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationUtils.kt index 7352082d..5f01dfd2 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationUtils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationUtils.kt @@ -41,13 +41,13 @@ import com.pitchedapps.frost.utils.frostUri const val NOTIF_CHANNEL_GENERAL = "general" const val NOTIF_CHANNEL_MESSAGES = "messages" -fun setupNotificationChannels(c: Context) { +fun setupNotificationChannels(c: Context, prefs: Prefs) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return val manager = c.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val appName = c.string(R.string.frost_name) val msg = c.string(R.string.messages) - manager.createNotificationChannel(NOTIF_CHANNEL_GENERAL, appName) - manager.createNotificationChannel(NOTIF_CHANNEL_MESSAGES, "$appName: $msg") + manager.createNotificationChannel(NOTIF_CHANNEL_GENERAL, appName, prefs) + manager.createNotificationChannel(NOTIF_CHANNEL_MESSAGES, "$appName: $msg", prefs) manager.notificationChannels .filter { it.id != NOTIF_CHANNEL_GENERAL && @@ -60,14 +60,15 @@ fun setupNotificationChannels(c: Context) { @RequiresApi(Build.VERSION_CODES.O) private fun NotificationManager.createNotificationChannel( id: String, - name: String + name: String, + prefs: Prefs ): NotificationChannel { val channel = NotificationChannel( id, name, NotificationManager.IMPORTANCE_DEFAULT ) channel.enableLights(true) - channel.lightColor = Prefs.accentColor + channel.lightColor = prefs.accentColor channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC createNotificationChannel(channel) return channel @@ -93,6 +94,8 @@ fun NotificationCompat.Builder.setFrostAlert( enable: Boolean, ringtone: String ): NotificationCompat.Builder { + val prefs = Prefs.get() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { setGroupAlertBehavior( if (enable) NotificationCompat.GROUP_ALERT_CHILDREN @@ -102,12 +105,12 @@ fun NotificationCompat.Builder.setFrostAlert( setDefaults(0) } else { var defaults = 0 - if (Prefs.notificationVibrate) defaults = defaults or Notification.DEFAULT_VIBRATE - if (Prefs.notificationSound) { + if (prefs.notificationVibrate) defaults = defaults or Notification.DEFAULT_VIBRATE + if (prefs.notificationSound) { if (ringtone.isNotBlank()) setSound(context.frostUri(ringtone)) else defaults = defaults or Notification.DEFAULT_SOUND } - if (Prefs.notificationLights) defaults = defaults or Notification.DEFAULT_LIGHTS + if (prefs.notificationLights) defaults = defaults or Notification.DEFAULT_LIGHTS setDefaults(defaults) } return this diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/UpdateReceiver.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/UpdateReceiver.kt index 2dbe6b6b..4c419e52 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/UpdateReceiver.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/UpdateReceiver.kt @@ -21,17 +21,21 @@ import android.content.Context import android.content.Intent import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 2017-05-31. * * Receiver that is triggered whenever the app updates so it can bind the notifications again */ -class UpdateReceiver : BroadcastReceiver() { +class UpdateReceiver : BroadcastReceiver(), KoinComponent { + + private val prefs: Prefs by inject() override fun onReceive(context: Context, intent: Intent) { if (intent.action != Intent.ACTION_MY_PACKAGE_REPLACED) return L.d { "Frost has updated" } - context.scheduleNotifications(Prefs.notificationFreq) // Update notifications + context.scheduleNotifications(prefs.notificationFreq) // Update notifications } } 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 4391b3ca..8c83850b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt @@ -28,7 +28,6 @@ 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.utils.Prefs import com.pitchedapps.frost.utils.REQUEST_NAV import com.pitchedapps.frost.utils.REQUEST_TEXT_ZOOM import com.pitchedapps.frost.utils.frostEvent @@ -45,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 }) { onClick = { materialDialog { title(R.string.theme) @@ -71,7 +70,7 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { } fun KPrefColorPicker.KPrefColorContract.dependsOnCustom() { - enabler = Prefs::isCustomTheme + enabler = prefs::isCustomTheme onDisabledClick = { frostSnackbar(R.string.requires_custom_theme) } allowCustom = true } @@ -80,8 +79,8 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { CssAssets.CUSTOM.reset() } - colorPicker(R.string.text_color, Prefs::customTextColor, { - Prefs.customTextColor = it + colorPicker(R.string.text_color, prefs::customTextColor, { + prefs.customTextColor = it reload() invalidateCustomTheme() shouldRestartMain() @@ -90,8 +89,8 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { allowCustomAlpha = false } - colorPicker(R.string.accent_color, Prefs::customAccentColor, { - Prefs.customAccentColor = it + colorPicker(R.string.accent_color, prefs::customAccentColor, { + prefs.customAccentColor = it reload() invalidateCustomTheme() shouldRestartMain() @@ -100,8 +99,8 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { allowCustomAlpha = false } - colorPicker(R.string.background_color, Prefs::customBackgroundColor, { - Prefs.customBackgroundColor = it + colorPicker(R.string.background_color, prefs::customBackgroundColor, { + prefs.customBackgroundColor = it bgCanvas.ripple(it, duration = 500L) invalidateCustomTheme() setFrostTheme(true) @@ -111,8 +110,8 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { allowCustomAlpha = true } - colorPicker(R.string.header_color, Prefs::customHeaderColor, { - Prefs.customHeaderColor = it + colorPicker(R.string.header_color, prefs::customHeaderColor, { + prefs.customHeaderColor = it frostNavigationBar() toolbarCanvas.ripple(it, RippleCanvas.MIDDLE, RippleCanvas.END, duration = 500L) reload() @@ -122,8 +121,8 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { allowCustomAlpha = true } - colorPicker(R.string.icon_color, Prefs::customIconColor, { - Prefs.customIconColor = it + colorPicker(R.string.icon_color, prefs::customIconColor, { + prefs.customIconColor = it invalidateOptionsMenu() shouldRestartMain() }) { @@ -135,9 +134,9 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { text( R.string.main_activity_layout, - Prefs::mainActivityLayoutType, - { Prefs.mainActivityLayoutType = it }) { - textGetter = { string(Prefs.mainActivityLayout.titleRes) } + prefs::mainActivityLayoutType, + { prefs.mainActivityLayoutType = it }) { + textGetter = { string(prefs.mainActivityLayout.titleRes) } onClick = { materialDialog { title(R.string.main_activity_layout_desc) @@ -160,8 +159,8 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { onClick = { launchTabCustomizerActivity() } } - checkbox(R.string.tint_nav, Prefs::tintNavBar, { - Prefs.tintNavBar = it + checkbox(R.string.tint_nav, prefs::tintNavBar, { + prefs.tintNavBar = it frostNavigationBar() setFrostResult(REQUEST_NAV) }) { @@ -172,15 +171,15 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { KPrefTextSeekbar( KPrefSeekbar.KPrefSeekbarBuilder( globalOptions, - R.string.web_text_scaling, Prefs::webTextScaling + R.string.web_text_scaling, prefs::webTextScaling ) { - Prefs.webTextScaling = it + prefs.webTextScaling = it setFrostResult(REQUEST_TEXT_ZOOM) }) ) - checkbox(R.string.enforce_black_media_bg, Prefs::blackMediaBg, { - Prefs.blackMediaBg = it + checkbox(R.string.enforce_black_media_bg, prefs::blackMediaBg, { + prefs.blackMediaBg = it }) { descRes = R.string.enforce_black_media_bg_desc } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt index 8f57b539..f6110756 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt @@ -19,54 +19,53 @@ package com.pitchedapps.frost.settings import ca.allanwang.kau.kpref.activity.KPrefAdapterBuilder import com.pitchedapps.frost.R import com.pitchedapps.frost.activities.SettingsActivity -import com.pitchedapps.frost.utils.Prefs /** * Created by Allan Wang on 2017-06-30. */ fun SettingsActivity.getBehaviourPrefs(): KPrefAdapterBuilder.() -> Unit = { - checkbox(R.string.auto_refresh_feed, Prefs::autoRefreshFeed, { Prefs.autoRefreshFeed = it }) { + checkbox(R.string.auto_refresh_feed, prefs::autoRefreshFeed, { prefs.autoRefreshFeed = it }) { descRes = R.string.auto_refresh_feed_desc } - checkbox(R.string.fancy_animations, Prefs::animate, { Prefs.animate = it; animate = it }) { + checkbox(R.string.fancy_animations, prefs::animate, { prefs.animate = it; animate = it }) { descRes = R.string.fancy_animations_desc } checkbox( R.string.overlay_swipe, - Prefs::overlayEnabled, - { Prefs.overlayEnabled = it; shouldRefreshMain() }) { + prefs::overlayEnabled, + { prefs.overlayEnabled = it; shouldRefreshMain() }) { descRes = R.string.overlay_swipe_desc } checkbox( R.string.overlay_full_screen_swipe, - Prefs::overlayFullScreenSwipe, - { Prefs.overlayFullScreenSwipe = it }) { + prefs::overlayFullScreenSwipe, + { prefs.overlayFullScreenSwipe = it }) { descRes = R.string.overlay_full_screen_swipe_desc } checkbox( R.string.open_links_in_default, - Prefs::linksInDefaultApp, - { Prefs.linksInDefaultApp = it }) { + prefs::linksInDefaultApp, + { prefs.linksInDefaultApp = it }) { descRes = R.string.open_links_in_default_desc } - checkbox(R.string.viewpager_swipe, Prefs::viewpagerSwipe, { Prefs.viewpagerSwipe = it }) { + checkbox(R.string.viewpager_swipe, prefs::viewpagerSwipe, { prefs.viewpagerSwipe = it }) { descRes = R.string.viewpager_swipe_desc } checkbox( R.string.force_message_bottom, - Prefs::messageScrollToBottom, - { Prefs.messageScrollToBottom = it }) { + prefs::messageScrollToBottom, + { prefs.messageScrollToBottom = it }) { descRes = R.string.force_message_bottom_desc } - checkbox(R.string.enable_pip, Prefs::enablePip, { Prefs.enablePip = it }) { + checkbox(R.string.enable_pip, prefs::enablePip, { prefs.enablePip = it }) { descRes = R.string.enable_pip_desc } @@ -78,11 +77,11 @@ fun SettingsActivity.getBehaviourPrefs(): KPrefAdapterBuilder.() -> Unit = { // } // } - checkbox(R.string.exit_confirmation, Prefs::exitConfirmation, { Prefs.exitConfirmation = it }) { + checkbox(R.string.exit_confirmation, prefs::exitConfirmation, { prefs.exitConfirmation = it }) { descRes = R.string.exit_confirmation_desc } - checkbox(R.string.analytics, Prefs::analytics, { Prefs.analytics = it }) { + checkbox(R.string.analytics, prefs::analytics, { prefs.analytics = it }) { descRes = R.string.analytics_desc } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt index d250f036..9a4751b8 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt @@ -32,7 +32,6 @@ import com.pitchedapps.frost.activities.SettingsActivity import com.pitchedapps.frost.activities.SettingsActivity.Companion.ACTIVITY_REQUEST_DEBUG import com.pitchedapps.frost.debugger.OfflineWebsite import com.pitchedapps.frost.facebook.FB_URL_BASE -import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.parsers.FrostParser import com.pitchedapps.frost.facebook.parsers.MessageParser import com.pitchedapps.frost.facebook.parsers.NotifParser @@ -87,7 +86,7 @@ fun SettingsActivity.getDebugPrefs(): KPrefAdapterBuilder.() -> Unit = { attempt = launch(Dispatchers.IO) { try { - val data = parser.parse(FbCookie.webCookie) + val data = parser.parse(fbCookie.webCookie) withMainContext { loading.dismiss() createEmail(parser, data?.data) @@ -113,7 +112,8 @@ private const val ZIP_NAME = "debug" fun SettingsActivity.sendDebug(url: String, html: String?) { val downloader = OfflineWebsite( - url, FbCookie.webCookie ?: "", + url, + cookie = fbCookie.webCookie ?: "", baseUrl = FB_URL_BASE, html = html, baseDir = DebugActivity.baseDir(this) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt index 9814fd76..30b16f81 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt @@ -21,7 +21,6 @@ import ca.allanwang.kau.kpref.activity.KPrefAdapterBuilder import ca.allanwang.kau.logging.KL import com.pitchedapps.frost.R import com.pitchedapps.frost.activities.SettingsActivity -import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.REQUEST_RESTART_APPLICATION /** @@ -37,8 +36,8 @@ fun SettingsActivity.getExperimentalPrefs(): KPrefAdapterBuilder.() -> Unit = { // Experimental content ends here -------------------- - checkbox(R.string.verbose_logging, Prefs::verboseLogging, { - Prefs.verboseLogging = it + checkbox(R.string.verbose_logging, prefs::verboseLogging, { + prefs.verboseLogging = it KL.shouldLog = { it != Log.VERBOSE } }) { descRes = R.string.verbose_logging_desc diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt index d1350df5..15a0633b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt @@ -23,7 +23,6 @@ import com.afollestad.materialdialogs.list.listItemsSingleChoice import com.pitchedapps.frost.R import com.pitchedapps.frost.activities.SettingsActivity import com.pitchedapps.frost.enums.FeedSort -import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.REQUEST_FAB /** @@ -31,7 +30,7 @@ import com.pitchedapps.frost.utils.REQUEST_FAB */ fun SettingsActivity.getFeedPrefs(): KPrefAdapterBuilder.() -> Unit = { - text(R.string.newsfeed_sort, Prefs::feedSort, { Prefs.feedSort = it }) { + text(R.string.newsfeed_sort, prefs::feedSort, { prefs.feedSort = it }) { descRes = R.string.newsfeed_sort_desc onClick = { materialDialog { @@ -50,50 +49,50 @@ fun SettingsActivity.getFeedPrefs(): KPrefAdapterBuilder.() -> Unit = { textGetter = { string(FeedSort(it).textRes) } } - checkbox(R.string.aggressive_recents, Prefs::aggressiveRecents, { - Prefs.aggressiveRecents = it + checkbox(R.string.aggressive_recents, prefs::aggressiveRecents, { + prefs.aggressiveRecents = it shouldRefreshMain() }) { descRes = R.string.aggressive_recents_desc } - checkbox(R.string.composer, Prefs::showComposer, { - Prefs.showComposer = it + checkbox(R.string.composer, prefs::showComposer, { + prefs.showComposer = it shouldRefreshMain() }) { descRes = R.string.composer_desc } - checkbox(R.string.create_fab, Prefs::showCreateFab, { - Prefs.showCreateFab = it + checkbox(R.string.create_fab, prefs::showCreateFab, { + prefs.showCreateFab = it setFrostResult(REQUEST_FAB) }) { descRes = R.string.create_fab_desc } - checkbox(R.string.suggested_friends, Prefs::showSuggestedFriends, { - Prefs.showSuggestedFriends = it + checkbox(R.string.suggested_friends, prefs::showSuggestedFriends, { + prefs.showSuggestedFriends = it shouldRefreshMain() }) { descRes = R.string.suggested_friends_desc } - checkbox(R.string.suggested_groups, Prefs::showSuggestedGroups, { - Prefs.showSuggestedGroups = it + checkbox(R.string.suggested_groups, prefs::showSuggestedGroups, { + prefs.showSuggestedGroups = it shouldRefreshMain() }) { descRes = R.string.suggested_groups_desc } - checkbox(R.string.show_stories, Prefs::showStories, { - Prefs.showStories = it + checkbox(R.string.show_stories, prefs::showStories, { + prefs.showStories = it shouldRefreshMain() }) { descRes = R.string.show_stories_desc } - checkbox(R.string.facebook_ads, Prefs::showFacebookAds, { - Prefs.showFacebookAds = it + checkbox(R.string.facebook_ads, prefs::showFacebookAds, { + prefs.showFacebookAds = it shouldRefreshMain() }) { descRes = R.string.facebook_ads_desc diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Network.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Network.kt index a1ec33e6..c275227f 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Network.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Network.kt @@ -19,7 +19,6 @@ package com.pitchedapps.frost.settings import ca.allanwang.kau.kpref.activity.KPrefAdapterBuilder import com.pitchedapps.frost.R import com.pitchedapps.frost.activities.SettingsActivity -import com.pitchedapps.frost.utils.Prefs /** * Created by Allan Wang on 2017-08-08. @@ -28,8 +27,8 @@ fun SettingsActivity.getNetworkPrefs(): KPrefAdapterBuilder.() -> Unit = { checkbox( R.string.network_media_on_metered, - { !Prefs.loadMediaOnMeteredNetwork }, - { Prefs.loadMediaOnMeteredNetwork = !it }) { + { !prefs.loadMediaOnMeteredNetwork }, + { prefs.loadMediaOnMeteredNetwork = !it }) { descRes = R.string.network_media_on_metered_desc } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt index b8a80e8d..06159ba5 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt @@ -41,6 +41,7 @@ import com.pitchedapps.frost.utils.frostSnackbar import com.pitchedapps.frost.utils.frostUri import com.pitchedapps.frost.views.Keywords import kotlinx.coroutines.launch +import org.koin.android.ext.android.get /** * Created by Allan Wang on 2017-06-29. @@ -54,8 +55,8 @@ fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = { text( R.string.notification_frequency, - Prefs::notificationFreq, - { Prefs.notificationFreq = it }) { + prefs::notificationFreq, + { prefs.notificationFreq = it }) { val options = longArrayOf(15, 30, 60, 120, 180, 300, 1440, 2880) val texts = options.map { if (it <= 0) string(R.string.no_notifications) else minuteToText(it) } @@ -71,7 +72,7 @@ fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = { } } } - enabler = { Prefs.hasNotifications } + enabler = { prefs.hasNotifications } textGetter = { minuteToText(it) } } @@ -88,36 +89,36 @@ fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = { } } - checkbox(R.string.notification_general, Prefs::notificationsGeneral, + checkbox(R.string.notification_general, prefs::notificationsGeneral, { - Prefs.notificationsGeneral = it + prefs.notificationsGeneral = it reloadByTitle(R.string.notification_general_all_accounts) - if (!Prefs.notificationsInstantMessages) + if (!prefs.notificationsInstantMessages) reloadByTitle(R.string.notification_frequency) }) { descRes = R.string.notification_general_desc } - checkbox(R.string.notification_general_all_accounts, Prefs::notificationAllAccounts, - { Prefs.notificationAllAccounts = it }) { + checkbox(R.string.notification_general_all_accounts, prefs::notificationAllAccounts, + { prefs.notificationAllAccounts = it }) { descRes = R.string.notification_general_all_accounts_desc - enabler = { Prefs.notificationsGeneral } + enabler = { prefs.notificationsGeneral } } - checkbox(R.string.notification_messages, Prefs::notificationsInstantMessages, + checkbox(R.string.notification_messages, prefs::notificationsInstantMessages, { - Prefs.notificationsInstantMessages = it + prefs.notificationsInstantMessages = it reloadByTitle(R.string.notification_messages_all_accounts) - if (!Prefs.notificationsGeneral) + if (!prefs.notificationsGeneral) reloadByTitle(R.string.notification_frequency) }) { descRes = R.string.notification_messages_desc } - checkbox(R.string.notification_messages_all_accounts, Prefs::notificationsImAllAccounts, - { Prefs.notificationsImAllAccounts = it }) { + checkbox(R.string.notification_messages_all_accounts, prefs::notificationsImAllAccounts, + { prefs.notificationsImAllAccounts = it }) { descRes = R.string.notification_messages_all_accounts_desc - enabler = { Prefs.notificationsInstantMessages } + enabler = { prefs.notificationsInstantMessages } } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @@ -130,8 +131,8 @@ fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = { } } } else { - checkbox(R.string.notification_sound, Prefs::notificationSound, { - Prefs.notificationSound = it + checkbox(R.string.notification_sound, prefs::notificationSound, { + prefs.notificationSound = it reloadByTitle( R.string.notification_ringtone, R.string.message_ringtone @@ -139,7 +140,7 @@ fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = { }) fun KPrefText.KPrefTextContract<String>.ringtone(code: Int) { - enabler = Prefs::notificationSound + enabler = prefs::notificationSound textGetter = { if (it.isBlank()) string(R.string.kau_default) else RingtoneManager.getRingtone(this@getNotificationPrefs, frostUri(it)) @@ -163,21 +164,21 @@ fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = { } } - text(R.string.notification_ringtone, Prefs::notificationRingtone, - { Prefs.notificationRingtone = it }) { + text(R.string.notification_ringtone, prefs::notificationRingtone, + { prefs.notificationRingtone = it }) { ringtone(SettingsActivity.REQUEST_NOTIFICATION_RINGTONE) } - text(R.string.message_ringtone, Prefs::messageRingtone, - { Prefs.messageRingtone = it }) { + text(R.string.message_ringtone, prefs::messageRingtone, + { prefs.messageRingtone = it }) { ringtone(SettingsActivity.REQUEST_MESSAGE_RINGTONE) } - checkbox(R.string.notification_vibrate, Prefs::notificationVibrate, - { Prefs.notificationVibrate = it }) + checkbox(R.string.notification_vibrate, prefs::notificationVibrate, + { prefs.notificationVibrate = it }) - checkbox(R.string.notification_lights, Prefs::notificationLights, - { Prefs.notificationLights = it }) + checkbox(R.string.notification_lights, prefs::notificationLights, + { prefs.notificationLights = it }) } if (BuildConfig.DEBUG) { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Security.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Security.kt index 754e19de..aa38fffd 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Security.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Security.kt @@ -20,7 +20,6 @@ import ca.allanwang.kau.kpref.activity.KPrefAdapterBuilder import com.pitchedapps.frost.R import com.pitchedapps.frost.activities.SettingsActivity import com.pitchedapps.frost.utils.BiometricUtils -import com.pitchedapps.frost.utils.Prefs import kotlinx.coroutines.launch /** @@ -32,15 +31,15 @@ fun SettingsActivity.getSecurityPrefs(): KPrefAdapterBuilder.() -> Unit = { descRes = R.string.security_disclaimer_info } - checkbox(R.string.enable_biometrics, Prefs::biometricsEnabled, { + checkbox(R.string.enable_biometrics, prefs::biometricsEnabled, { launch { /* * For security, we should request authentication when: * - enabling to ensure that it is supported * - disabling to ensure that it is permitted */ - BiometricUtils.authenticate(this@getSecurityPrefs, force = true).await() - Prefs.biometricsEnabled = it + BiometricUtils.authenticate(this@getSecurityPrefs, prefs, force = true).await() + prefs.biometricsEnabled = it reloadByTitle(R.string.enable_biometrics) } }) { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/BiometricUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/BiometricUtils.kt index c5b336bf..ab64ff55 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/BiometricUtils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/BiometricUtils.kt @@ -64,8 +64,8 @@ object BiometricUtils { private fun getOrCreatePoolSync(): Executor = pool ?: Executors.newSingleThreadExecutor().also { pool = it } - private fun shouldPrompt(context: Context): Boolean { - return Prefs.biometricsEnabled && System.currentTimeMillis() - lastUnlockTime > UNLOCK_TIME_INTERVAL + private fun shouldPrompt(context: Context, prefs: Prefs): Boolean { + return prefs.biometricsEnabled && System.currentTimeMillis() - lastUnlockTime > UNLOCK_TIME_INTERVAL } /** @@ -73,9 +73,9 @@ object BiometricUtils { * Note that the underlying request will call [androidx.fragment.app.FragmentTransaction.commit], * so this cannot happen after onSaveInstanceState. */ - fun authenticate(activity: FragmentActivity, force: Boolean = false): BiometricDeferred { + fun authenticate(activity: FragmentActivity, prefs: Prefs, force: Boolean = false): BiometricDeferred { val deferred: BiometricDeferred = CompletableDeferred() - if (!force && !shouldPrompt(activity)) { + if (!force && !shouldPrompt(activity, prefs)) { deferred.complete(null) return deferred } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt index 389cb6b7..974047e8 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt @@ -16,7 +16,6 @@ */ package com.pitchedapps.frost.utils -import android.util.Log import ca.allanwang.kau.logging.KauLogger import ca.allanwang.kau.logging.KauLoggerExtension import com.bugsnag.android.Bugsnag @@ -27,13 +26,7 @@ import com.pitchedapps.frost.BuildConfig * * Logging for frost */ -object L : KauLogger("Frost", { - when (it) { - Log.VERBOSE -> BuildConfig.DEBUG - Log.INFO, Log.ERROR -> true - else -> BuildConfig.DEBUG || Prefs.verboseLogging - } -}) { +object L : KauLogger("Frost") { inline fun test(message: () -> Any?) { _d { @@ -59,7 +52,7 @@ object L : KauLogger("Frost", { } } - var bugsnagInit = false + var hasAnalytics: () -> Boolean = { false } override fun logImpl(priority: Int, message: String?, t: Throwable?) { /* @@ -67,7 +60,7 @@ object L : KauLogger("Frost", { * bugsnagInit is changed per application and helps prevent crashes (if calling pre init) * analytics is changed by the user, and may be toggled throughout the app */ - if (BuildConfig.DEBUG || !bugsnagInit || !Prefs.analytics) { + if (BuildConfig.DEBUG || !hasAnalytics()) { super.logImpl(priority, message, t) } else { if (message != null) { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt index eb8e4b35..8052533b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt @@ -19,6 +19,7 @@ package com.pitchedapps.frost.utils import android.graphics.Color import ca.allanwang.kau.kotlin.lazyResettable import ca.allanwang.kau.kpref.KPref +import ca.allanwang.kau.kpref.KPrefFactory import ca.allanwang.kau.utils.colorToForeground import ca.allanwang.kau.utils.isColorVisibleOn import ca.allanwang.kau.utils.withAlpha @@ -29,13 +30,15 @@ import com.pitchedapps.frost.enums.FeedSort import com.pitchedapps.frost.enums.MainActivityLayout import com.pitchedapps.frost.enums.Theme import com.pitchedapps.frost.injectors.InjectorContract +import org.koin.core.context.GlobalContext +import org.koin.dsl.module /** * Created by Allan Wang on 2017-05-28. * * Shared Preference object with lazy cached retrievals */ -object Prefs : KPref() { +class Prefs(factory: KPrefFactory) : KPref("${BuildConfig.APPLICATION_ID}.prefs", factory) { var lastLaunch: Long by kpref("last_launch", -1L) @@ -69,15 +72,15 @@ object Prefs : KPref() { var identifier: Int by kpref("identifier", -1) - private val loader = lazyResettable { Theme.values[Prefs.theme] } + private val loader = lazyResettable { Theme.values[theme] } val t: Theme by loader val textColor: Int - get() = t.textColor + get() = t.textColorGetter(this) val accentColor: Int - get() = t.accentColor + get() = t.accentColorGetter(this) inline val accentColorForWhite: Int get() = when { @@ -87,20 +90,20 @@ object Prefs : KPref() { } inline val nativeBgColor: Int - get() = Prefs.bgColor.withAlpha(30) + get() = bgColor.withAlpha(30) - fun nativeBgColor(unread: Boolean) = Prefs.bgColor + fun nativeBgColor(unread: Boolean) = bgColor .colorToForeground(if (unread) 0.7f else 0.0f) .withAlpha(30) val bgColor: Int - get() = t.bgColor + get() = t.backgroundColorGetter(this) val headerColor: Int - get() = t.headerColor + get() = t.headerColorGetter(this) val iconColor: Int - get() = t.iconColor + get() = t.iconColorGetter(this) val themeInjector: InjectorContract get() = t.injector @@ -155,6 +158,10 @@ object Prefs : KPref() { var enablePip: Boolean by kpref("enable_pip", true) + /** + * Despite the naming, this toggle currently only enables debug logging. + * Verbose is never logged in release builds. + */ var verboseLogging: Boolean by kpref("verbose_logging", false) var analytics: Boolean by kpref("analytics", false) { @@ -194,5 +201,11 @@ object Prefs : KPref() { inline val mainActivityLayout: MainActivityLayout get() = MainActivityLayout(mainActivityLayoutType) - override fun deleteKeys() = arrayOf("search_bar") + companion object { + fun get(): Prefs = GlobalContext.get().koin.get() + + fun module() = module { + single { Prefs(get()) } + } + } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Showcase.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Showcase.kt index edbe7682..423eda97 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Showcase.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Showcase.kt @@ -17,18 +17,25 @@ package com.pitchedapps.frost.utils import ca.allanwang.kau.kpref.KPref +import ca.allanwang.kau.kpref.KPrefFactory +import com.pitchedapps.frost.BuildConfig +import org.koin.dsl.module /** * Created by Allan Wang on 2017-07-03. * * Showcase prefs that offer one time helpers to guide new users */ -object Showcase : KPref() { +class Showcase(factory: KPrefFactory) : KPref("${BuildConfig.APPLICATION_ID}.showcase", factory) { // check if this is the first time launching the web overlay; show snackbar if true val firstWebOverlay: Boolean by kprefSingle("first_web_overlay") val intro: Boolean by kprefSingle("intro_pages") - override fun deleteKeys() = arrayOf("shown_release", "experimental_by_default") + companion object { + fun module() = module { + single { Showcase(get()) } + } + } } 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 66cc6a9e..1f266eb9 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt @@ -123,27 +123,34 @@ fun Activity.cookies(): ArrayList<CookieEntity> { * Note that most requests may need to first check if the url can be launched as an overlay * See [requestWebOverlay] to verify the launch */ -private inline fun <reified T : WebOverlayActivityBase> Context.launchWebOverlayImpl(url: String) { +private inline fun <reified T : WebOverlayActivityBase> Context.launchWebOverlayImpl( + url: String, + fbCookie: FbCookie +) { + val prefs = Prefs.get() val argUrl = url.formattedFbUrl L.v { "Launch received: $url\nLaunch web overlay: $argUrl" } if (argUrl.isFacebookUrl && argUrl.contains("/logout.php")) { L.d { "Logout php found" } ctxCoroutine.launch { - FbCookie.logout(this@launchWebOverlayImpl) + fbCookie.logout(this@launchWebOverlayImpl) } - } else if (!(Prefs.linksInDefaultApp && resolveActivityForUri(Uri.parse(argUrl)))) + } else if (!(prefs.linksInDefaultApp && resolveActivityForUri(Uri.parse(argUrl)))) { startActivity<T>(false, intentBuilder = { putExtra(ARG_URL, argUrl) }) + } } -fun Context.launchWebOverlay(url: String) = launchWebOverlayImpl<WebOverlayActivity>(url) +fun Context.launchWebOverlay(url: String, fbCookie: FbCookie) = + launchWebOverlayImpl<WebOverlayActivity>(url, fbCookie) // TODO Currently, default is overlay. Switch this if default changes -fun Context.launchWebOverlayDesktop(url: String) = launchWebOverlay(url) +fun Context.launchWebOverlayDesktop(url: String, fbCookie: FbCookie) = + launchWebOverlay(url, fbCookie) -fun Context.launchWebOverlayMobile(url: String) = - launchWebOverlayImpl<WebOverlayMobileActivity>(url) +fun Context.launchWebOverlayMobile(url: String, fbCookie: FbCookie) = + launchWebOverlayImpl<WebOverlayMobileActivity>(url, fbCookie) private fun Context.fadeBundle() = ActivityOptions.makeCustomAnimation( this, @@ -172,16 +179,17 @@ fun WebOverlayActivity.url(): String { } fun Activity.setFrostTheme(forceTransparent: Boolean = false) { + val prefs = Prefs.get() val isTransparent = - forceTransparent || (Color.alpha(Prefs.bgColor) != 255) || (Color.alpha(Prefs.headerColor) != 255) - if (Prefs.bgColor.isColorDark) { + forceTransparent || (Color.alpha(prefs.bgColor) != 255) || (Color.alpha(prefs.headerColor) != 255) + if (prefs.bgColor.isColorDark) { setTheme(if (isTransparent) R.style.FrostTheme_Transparent else R.style.FrostTheme) } else { setTheme(if (isTransparent) R.style.FrostTheme_Light_Transparent else R.style.FrostTheme_Light) } } -class ActivityThemeUtils { +class ActivityThemeUtils(val prefs: Prefs) { private var toolbar: Toolbar? = null var themeWindow = true @@ -207,21 +215,21 @@ class ActivityThemeUtils { fun theme(activity: Activity) { with(activity) { - statusBarColor = Prefs.headerColor.darken(0.1f).withAlpha(255) - if (Prefs.tintNavBar) navigationBarColor = Prefs.headerColor - if (themeWindow) window.setBackgroundDrawable(ColorDrawable(Prefs.bgColor)) - toolbar?.setBackgroundColor(Prefs.headerColor) - toolbar?.setTitleTextColor(Prefs.iconColor) - toolbar?.overflowIcon?.setTint(Prefs.iconColor) - texts.forEach { it.setTextColor(Prefs.textColor) } - headers.forEach { it.setBackgroundColor(Prefs.headerColor) } - backgrounds.forEach { it.setBackgroundColor(Prefs.bgColor) } + statusBarColor = prefs.headerColor.darken(0.1f).withAlpha(255) + if (prefs.tintNavBar) navigationBarColor = prefs.headerColor + if (themeWindow) window.setBackgroundDrawable(ColorDrawable(prefs.bgColor)) + toolbar?.setBackgroundColor(prefs.headerColor) + toolbar?.setTitleTextColor(prefs.iconColor) + toolbar?.overflowIcon?.setTint(prefs.iconColor) + texts.forEach { it.setTextColor(prefs.textColor) } + headers.forEach { it.setBackgroundColor(prefs.headerColor) } + backgrounds.forEach { it.setBackgroundColor(prefs.bgColor) } } } } -inline fun Activity.setFrostColors(builder: ActivityThemeUtils.() -> Unit) { - val themer = ActivityThemeUtils() +inline fun Activity.setFrostColors(prefs: Prefs, builder: ActivityThemeUtils.() -> Unit) { + val themer = ActivityThemeUtils(prefs) themer.builder() themer.theme(this) } @@ -248,18 +256,20 @@ fun View.frostSnackbar(@StringRes text: Int, builder: Snackbar.() -> Unit = {}) @SuppressLint("RestrictedApi") private inline fun frostSnackbar(crossinline builder: Snackbar.() -> Unit): Snackbar.() -> Unit = { + val prefs = Prefs.get() builder() // hacky workaround, but it has proper checks and shouldn't crash ((view as? FrameLayout)?.getChildAt(0) as? SnackbarContentLayout)?.apply { - messageView.setTextColor(Prefs.textColor) - actionView.setTextColor(Prefs.accentColor) + messageView.setTextColor(prefs.textColor) + actionView.setTextColor(prefs.accentColor) // only set if previous text colors are set - view.setBackgroundColor(Prefs.bgColor.withAlpha(255).colorToForeground(0.1f)) + view.setBackgroundColor(prefs.bgColor.withAlpha(255).colorToForeground(0.1f)) } } fun Activity.frostNavigationBar() { - navigationBarColor = if (Prefs.tintNavBar) Prefs.headerColor else Color.BLACK + val prefs = Prefs.get() + navigationBarColor = if (prefs.tintNavBar) prefs.headerColor else Color.BLACK } @Throws(IOException::class) @@ -393,15 +403,14 @@ inline fun Context.sendFrostEmail(subjectId: String, crossinline builder: EmailB } fun EmailBuilder.addFrostDetails() { - addItem("Prev version", Prefs.prevVersionCode.toString()) + val prefs = Prefs.get() + addItem("Prev version", prefs.prevVersionCode.toString()) val proTag = "FO" // if (IS_FROST_PRO) "TY" else "FP" - addItem("Random Frost ID", "${Prefs.frostId}-$proTag") + addItem("Random Frost ID", "${prefs.frostId}-$proTag") addItem("Locale", Locale.getDefault().displayName) } -fun frostJsoup(url: String): Document = frostJsoup(FbCookie.webCookie, url) - fun frostJsoup(cookie: String?, url: String): Document = Jsoup.connect(url).run { if (cookie.isNullOrBlank()) this @@ -438,7 +447,7 @@ fun String.unescapeHtml(): String = .replace("\\u003C", "<") .replace("\\\"", "\"") -suspend fun Context.loadAssets(): Unit = coroutineScope { - CssAssets.load(this@loadAssets) +suspend fun Context.loadAssets(prefs: Prefs): Unit = coroutineScope { + CssAssets.load(this@loadAssets, prefs) JsAssets.load(this@loadAssets) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt index 61e2c11f..d6e8f9e9 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt @@ -25,12 +25,13 @@ import com.afollestad.materialdialogs.callbacks.onDismiss import com.afollestad.materialdialogs.list.listItems import com.pitchedapps.frost.R import com.pitchedapps.frost.activities.MainActivity +import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.formattedFbUrl /** * Created by Allan Wang on 2017-07-07. */ -fun Context.showWebContextMenu(wc: WebContext) { +fun Context.showWebContextMenu(wc: WebContext, fbCookie: FbCookie) { if (wc.isEmpty) return var title = wc.url ?: string(R.string.menu) title = @@ -43,7 +44,7 @@ fun Context.showWebContextMenu(wc: WebContext) { materialDialog { title(text = title) listItems(items = menuItems.map { string(it.textId) }) { _, position, _ -> - menuItems[position].onClick(this@showWebContextMenu, wc) + menuItems[position].onClick(this@showWebContextMenu, wc, fbCookie) } onDismiss { // showing the dialog interrupts the touch down event, so we must ensure that the viewpager's swipe is enabled @@ -65,16 +66,16 @@ class WebContext(val unformattedUrl: String?, val text: String?) { enum class WebContextType( val textId: Int, val constraint: (wc: WebContext) -> Boolean, - val onClick: (c: Context, wc: WebContext) -> Unit + val onClick: (c: Context, wc: WebContext, fc: FbCookie) -> Unit ) { OPEN_LINK( R.string.open_link, { it.hasUrl }, - { c, wc -> c.launchWebOverlay(wc.url!!) }), - COPY_LINK(R.string.copy_link, { it.hasUrl }, { c, wc -> c.copyToClipboard(wc.url) }), - COPY_TEXT(R.string.copy_text, { it.hasText }, { c, wc -> c.copyToClipboard(wc.text) }), - SHARE_LINK(R.string.share_link, { it.hasUrl }, { c, wc -> c.shareText(wc.url) }), - DEBUG_LINK(R.string.debug_link, { it.hasUrl }, { c, wc -> + { c, wc, fc -> c.launchWebOverlay(wc.url!!, fc) }), + COPY_LINK(R.string.copy_link, { it.hasUrl }, { c, wc, _ -> c.copyToClipboard(wc.url) }), + COPY_TEXT(R.string.copy_text, { it.hasText }, { c, wc, _ -> c.copyToClipboard(wc.text) }), + SHARE_LINK(R.string.share_link, { it.hasUrl }, { c, wc, _ -> c.shareText(wc.url) }), + DEBUG_LINK(R.string.debug_link, { it.hasUrl }, { c, wc, _ -> c.materialDialog { title(R.string.debug_link) message(R.string.debug_link_desc) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt index 1f4e62ab..8a76c424 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt @@ -38,18 +38,23 @@ import com.pitchedapps.frost.facebook.profilePictureUrl import com.pitchedapps.frost.glide.FrostGlide import com.pitchedapps.frost.glide.GlideApp import com.pitchedapps.frost.utils.Prefs +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 2017-06-05. */ -class AccountItem(val cookie: CookieEntity?) : KauIItem<AccountItem.ViewHolder> - (R.layout.view_account, { ViewHolder(it) }, R.id.item_account) { +class AccountItem(val cookie: CookieEntity?) : + KauIItem<AccountItem.ViewHolder>(R.layout.view_account, { ViewHolder(it) }, R.id.item_account), +KoinComponent { + + private val prefs: Prefs by inject() override fun bindView(holder: ViewHolder, payloads: MutableList<Any>) { super.bindView(holder, payloads) with(holder) { text.invisible() - text.setTextColor(Prefs.textColor) + text.setTextColor(prefs.textColor) if (cookie != null) { text.text = cookie.name GlideApp.with(itemView).load(profilePictureUrl(cookie.id)) @@ -81,7 +86,7 @@ class AccountItem(val cookie: CookieEntity?) : KauIItem<AccountItem.ViewHolder> GoogleMaterial.Icon.gmd_add_circle_outline.toDrawable( itemView.context, 100, - Prefs.textColor + prefs.textColor ) ) text.text = itemView.context.getString(R.string.kau_add_account) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt index 097aea32..462f09ae 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt @@ -30,6 +30,8 @@ import ca.allanwang.kau.utils.withAlpha import com.mikepenz.iconics.typeface.IIcon import com.pitchedapps.frost.databinding.ViewBadgedIconBinding import com.pitchedapps.frost.utils.Prefs +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 2017-06-19. @@ -38,8 +40,9 @@ class BadgedIcon @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : ConstraintLayout(context, attrs, defStyleAttr) { +) : ConstraintLayout(context, attrs, defStyleAttr), KoinComponent { + private val prefs: Prefs by inject() private val binding: ViewBadgedIconBinding = ViewBadgedIconBinding.inflate(LayoutInflater.from(context), this, true) @@ -49,7 +52,7 @@ class BadgedIcon @JvmOverloads constructor( fun ViewBadgedIconBinding.init() { val badgeColor = - Prefs.mainActivityLayout.backgroundColor().withAlpha(255).colorToForeground(0.2f) + prefs.mainActivityLayout.backgroundColor(prefs).withAlpha(255).colorToForeground(0.2f) val badgeBackground = GradientDrawable( GradientDrawable.Orientation.BOTTOM_TOP, @@ -57,7 +60,7 @@ class BadgedIcon @JvmOverloads constructor( ) badgeBackground.cornerRadius = 13.dpToPx.toFloat() badgeText.background = badgeBackground - badgeText.setTextColor(Prefs.mainActivityLayout.iconColor()) + badgeText.setTextColor(prefs.mainActivityLayout.iconColor(prefs)) } var iicon: IIcon? = null @@ -67,13 +70,13 @@ class BadgedIcon @JvmOverloads constructor( value?.toDrawable( context, sizeDp = 20, - color = Prefs.mainActivityLayout.iconColor() + color = prefs.mainActivityLayout.iconColor(prefs) ) ) } fun setAllAlpha(alpha: Float) { - // badgeTextView.setTextColor(Prefs.textColor.withAlpha(alpha.toInt())) + // badgeTextView.setTextColor(prefs.textColor.withAlpha(alpha.toInt())) binding.badgeImage.drawable.alpha = alpha.toInt() } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostContentView.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostContentView.kt index baf9421f..4fbf1482 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostContentView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostContentView.kt @@ -47,6 +47,8 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.BroadcastChannel import kotlinx.coroutines.channels.ConflatedBroadcastChannel import kotlinx.coroutines.channels.ReceiveChannel +import org.koin.core.KoinComponent +import org.koin.core.inject class FrostContentWeb @JvmOverloads constructor( context: Context, @@ -75,8 +77,9 @@ abstract class FrostContentView<out T> @JvmOverloads constructor( defStyleAttr: Int = 0, defStyleRes: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr, defStyleRes), - FrostContentParent where T : View, T : FrostContentCore { + FrostContentParent, KoinComponent where T : View, T : FrostContentCore { + private val prefs: Prefs by inject() private val refresh: SwipeRefreshLayout by bindView(R.id.content_refresh) private val progress: ProgressBar by bindView(R.id.content_progress) val coreView: T by bindView(R.id.content_core) @@ -153,9 +156,9 @@ abstract class FrostContentView<out T> @JvmOverloads constructor( } override fun reloadThemeSelf() { - progress.tint(Prefs.textColor.withAlpha(180)) - refresh.setColorSchemeColors(Prefs.iconColor) - refresh.setProgressBackgroundColorSchemeColor(Prefs.headerColor.withAlpha(255)) + progress.tint(prefs.textColor.withAlpha(180)) + refresh.setColorSchemeColors(prefs.iconColor) + refresh.setProgressBackgroundColorSchemeColor(prefs.headerColor.withAlpha(255)) } override fun reloadTextSizeSelf() { @@ -192,7 +195,7 @@ abstract class FrostContentView<out T> @JvmOverloads constructor( if (isVisible) fadeOut(duration = 200L) } else if (loading) { - if (animate && Prefs.animate) circularReveal(offset = WEB_LOAD_DELAY) + if (animate && prefs.animate) circularReveal(offset = WEB_LOAD_DELAY) else fadeIn(duration = 200L, offset = WEB_LOAD_DELAY) L.v { "Transition loaded in ${System.currentTimeMillis() - transitionStart} ms" } receiver.cancel() diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt index 5e82f0e9..6b156cc4 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt @@ -30,6 +30,8 @@ import com.pitchedapps.frost.fragments.RecyclerContentContract import com.pitchedapps.frost.utils.Prefs import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 2017-05-29. @@ -41,8 +43,11 @@ class FrostRecyclerView @JvmOverloads constructor( attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : RecyclerView(context, attrs, defStyleAttr), + KoinComponent, FrostContentCore { + private val prefs: Prefs by inject() + override fun reload(animate: Boolean) = reloadBase(animate) override lateinit var parent: FrostContentParent @@ -71,13 +76,13 @@ class FrostRecyclerView @JvmOverloads constructor( var onReloadClear: () -> Unit = {} override fun reloadBase(animate: Boolean) { - if (Prefs.animate) fadeOut(onFinish = onReloadClear) + if (prefs.animate) fadeOut(onFinish = onReloadClear) scope.launch { parent.refreshChannel.offer(true) recyclerContract.reload { parent.progressChannel.offer(it) } parent.progressChannel.offer(100) parent.refreshChannel.offer(false) - if (Prefs.animate) circularReveal() + if (prefs.animate) circularReveal() } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt index bc565527..16df7f8e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt @@ -47,6 +47,8 @@ import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.ctxCoroutine import com.pitchedapps.frost.utils.frostDownload +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 2017-10-13. @@ -55,7 +57,7 @@ class FrostVideoViewer @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : FrameLayout(context, attrs, defStyleAttr), FrostVideoViewerContract { +) : FrameLayout(context, attrs, defStyleAttr), FrostVideoViewerContract, KoinComponent { companion object { /** @@ -85,6 +87,8 @@ class FrostVideoViewer @JvmOverloads constructor( } } + private val prefs: Prefs by inject() + private val binding: ViewVideoBinding = ViewVideoBinding.inflate(LayoutInflater.from(context), this, true) @@ -95,8 +99,8 @@ class FrostVideoViewer @JvmOverloads constructor( fun ViewVideoBinding.init() { alpha = 0f videoBackground.setBackgroundColor( - if (!Prefs.blackMediaBg && Prefs.bgColor.isColorDark) - Prefs.bgColor.withMinAlpha(200) + if (!prefs.blackMediaBg && prefs.bgColor.isColorDark) + prefs.bgColor.withMinAlpha(200) else Color.BLACK ) @@ -104,7 +108,7 @@ class FrostVideoViewer @JvmOverloads constructor( video.pause() videoToolbar.inflateMenu(R.menu.menu_video) context.setMenuIcons( - videoToolbar.menu, Prefs.iconColor, + videoToolbar.menu, prefs.iconColor, R.id.action_pip to GoogleMaterial.Icon.gmd_picture_in_picture_alt, R.id.action_download to GoogleMaterial.Icon.gmd_file_download ) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostViewPager.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostViewPager.kt index bf2f771d..819ec68a 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostViewPager.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostViewPager.kt @@ -22,6 +22,8 @@ import android.util.AttributeSet import android.view.MotionEvent import androidx.viewpager.widget.ViewPager import com.pitchedapps.frost.utils.Prefs +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 2017-07-07. @@ -29,12 +31,14 @@ import com.pitchedapps.frost.utils.Prefs * Basic override to allow us to control swiping */ class FrostViewPager @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : - ViewPager(context, attrs) { + ViewPager(context, attrs), KoinComponent { + + private val prefs: Prefs by inject() var enableSwipe = true override fun onInterceptTouchEvent(ev: MotionEvent?) = try { - Prefs.viewpagerSwipe && enableSwipe && super.onInterceptTouchEvent(ev) + prefs.viewpagerSwipe && enableSwipe && super.onInterceptTouchEvent(ev) } catch (e: IllegalArgumentException) { false } @@ -42,7 +46,7 @@ class FrostViewPager @JvmOverloads constructor(context: Context, attrs: Attribut @SuppressLint("ClickableViewAccessibility") override fun onTouchEvent(ev: MotionEvent?): Boolean = try { - Prefs.viewpagerSwipe && enableSwipe && super.onTouchEvent(ev) + prefs.viewpagerSwipe && enableSwipe && super.onTouchEvent(ev) } catch (e: IllegalArgumentException) { false } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt index 8cba5e11..dd31d303 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt @@ -31,6 +31,7 @@ import com.pitchedapps.frost.contracts.FrostContentParent import com.pitchedapps.frost.db.FrostDatabase import com.pitchedapps.frost.db.currentCookie import com.pitchedapps.frost.facebook.FB_HOME_URL +import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.USER_AGENT import com.pitchedapps.frost.fragments.WebFragment import com.pitchedapps.frost.utils.L @@ -44,6 +45,8 @@ import com.pitchedapps.frost.web.NestedWebView import kotlin.math.abs import kotlin.math.max import kotlin.math.min +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 2017-05-29. @@ -54,7 +57,11 @@ class FrostWebView @JvmOverloads constructor( attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : NestedWebView(context, attrs, defStyleAttr), - FrostContentCore { + FrostContentCore, + KoinComponent { + + val fbCookie: FbCookie by inject() + val prefs: Prefs by inject() override fun reload(animate: Boolean) { if (parent.registerTransition(false, animate)) @@ -75,7 +82,7 @@ class FrostWebView @JvmOverloads constructor( javaScriptEnabled = true mediaPlaybackRequiresUserGesture = false // TODO check if we need this allowFileAccess = true - textZoom = Prefs.webTextScaling + textZoom = prefs.webTextScaling domStorageEnabled = true } setLayerType(LAYER_TYPE_HARDWARE, null) @@ -208,7 +215,7 @@ class FrostWebView @JvmOverloads constructor( } override fun reloadTextSizeSelf() { - settings.textZoom = Prefs.webTextScaling + settings.textZoom = prefs.webTextScaling } override fun destroy() { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt index 8f0309cb..ff8a5bb7 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt @@ -38,6 +38,8 @@ import com.mikepenz.iconics.typeface.IIcon import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.pitchedapps.frost.R import com.pitchedapps.frost.utils.Prefs +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 2017-06-19. @@ -46,8 +48,9 @@ class Keywords @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : ConstraintLayout(context, attrs, defStyleAttr) { +) : ConstraintLayout(context, attrs, defStyleAttr), KoinComponent { + private val prefs: Prefs by inject() val editText: AppCompatEditText by bindView(R.id.edit_text) val addIcon: ImageView by bindView(R.id.add_icon) val recycler: RecyclerView by bindView(R.id.recycler) @@ -55,8 +58,8 @@ class Keywords @JvmOverloads constructor( init { inflate(context, R.layout.view_keywords, this) - editText.tint(Prefs.textColor) - addIcon.setImageDrawable(GoogleMaterial.Icon.gmd_add.keywordDrawable(context)) + editText.tint(prefs.textColor) + addIcon.setImageDrawable(GoogleMaterial.Icon.gmd_add.keywordDrawable(context, prefs)) addIcon.setOnClickListener { if (editText.text.isNullOrEmpty()) editText.error = context.string(R.string.empty_keyword) @@ -65,7 +68,7 @@ class Keywords @JvmOverloads constructor( editText.text?.clear() } } - adapter.add(Prefs.notificationKeywords.map { KeywordItem(it) }) + adapter.add(prefs.notificationKeywords.map { KeywordItem(it) }) recycler.layoutManager = LinearLayoutManager(context) recycler.adapter = adapter adapter.addEventHook(object : ClickEventHook<KeywordItem>() { @@ -84,12 +87,12 @@ class Keywords @JvmOverloads constructor( } fun save() { - Prefs.notificationKeywords = adapter.adapterItems.mapTo(mutableSetOf()) { it.keyword } + prefs.notificationKeywords = adapter.adapterItems.mapTo(mutableSetOf()) { it.keyword } } } -private fun IIcon.keywordDrawable(context: Context): Drawable = - toDrawable(context, 20, Prefs.textColor) +private fun IIcon.keywordDrawable(context: Context, prefs: Prefs): Drawable = + toDrawable(context, 20, prefs.textColor) class KeywordItem(val keyword: String) : AbstractItem<KeywordItem.ViewHolder>() { @@ -111,13 +114,15 @@ class KeywordItem(val keyword: String) : AbstractItem<KeywordItem.ViewHolder>() holder.text.text = null } - class ViewHolder(v: View) : RecyclerView.ViewHolder(v) { + class ViewHolder(v: View) : RecyclerView.ViewHolder(v), KoinComponent { + + private val prefs: Prefs by inject() val text: AppCompatTextView by bindView(R.id.keyword_text) val delete: ImageView by bindView(R.id.keyword_delete) init { - text.setTextColor(Prefs.textColor) - delete.setImageDrawable(GoogleMaterial.Icon.gmd_delete.keywordDrawable(itemView.context)) + text.setTextColor(prefs.textColor) + delete.setImageDrawable(GoogleMaterial.Icon.gmd_delete.keywordDrawable(itemView.context, prefs)) } } } 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 3ab954c6..8d4deef8 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt @@ -34,6 +34,8 @@ import com.pitchedapps.frost.utils.isFacebookUrl import java.io.File import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 2018-01-05. @@ -44,8 +46,9 @@ class DebugWebView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : WebView(context, attrs, defStyleAttr) { +) : WebView(context, attrs, defStyleAttr), KoinComponent { + private val prefs: Prefs by inject() var onPageFinished: (String?) -> Unit = {} init { @@ -93,7 +96,7 @@ class DebugWebView @JvmOverloads constructor( private fun injectBackgroundColor() { setBackgroundColor( - if (url.isFacebookUrl) Prefs.bgColor.withAlpha(255) + if (url.isFacebookUrl) prefs.bgColor.withAlpha(255) else Color.WHITE ) } @@ -104,15 +107,16 @@ class DebugWebView @JvmOverloads constructor( if (url.isFacebookUrl) view.jsInject( // CssHider.CORE, - CssHider.COMPOSER.maybe(!Prefs.showComposer), - CssHider.STORIES.maybe(!Prefs.showStories), - CssHider.PEOPLE_YOU_MAY_KNOW.maybe(!Prefs.showSuggestedFriends), - CssHider.SUGGESTED_GROUPS.maybe(!Prefs.showSuggestedGroups), - Prefs.themeInjector, + CssHider.COMPOSER.maybe(!prefs.showComposer), + CssHider.STORIES.maybe(!prefs.showStories), + CssHider.PEOPLE_YOU_MAY_KNOW.maybe(!prefs.showSuggestedFriends), + CssHider.SUGGESTED_GROUPS.maybe(!prefs.showSuggestedGroups), + prefs.themeInjector, CssHider.NON_RECENT.maybe( (url?.contains("?sk=h_chr") ?: false) && - Prefs.aggressiveRecents - ) + prefs.aggressiveRecents + ), + prefs = prefs ) } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt index c8e551a3..05248153 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt @@ -41,6 +41,8 @@ import kotlinx.coroutines.launch */ class FrostJSI(val web: FrostWebView) { + private val fbCookie: FbCookie get() = web.fbCookie + private val prefs: Prefs get() = web.prefs private val context: Context = web.context private val activity: MainActivity? = context as? MainActivity private val header: SendChannel<String>? = activity?.headerBadgeChannel @@ -57,7 +59,7 @@ class FrostJSI(val web: FrostWebView) { @JavascriptInterface fun loadVideo(url: String?, isGif: Boolean): Boolean = - if (url != null && Prefs.enablePip) { + if (url != null && prefs.enablePip) { web.post { (context as? VideoViewHolder)?.showVideo(url, isGif) ?: L.e { "Could not load video; contract not implemented" } @@ -79,7 +81,7 @@ class FrostJSI(val web: FrostWebView) { @JavascriptInterface fun contextMenu(url: String?, text: String?) { // url will be formatted through webcontext - web.post { context.showWebContextMenu(WebContext(url.takeIf { it.isIndependent }, text)) } + web.post { context.showWebContextMenu(WebContext(url.takeIf { it.isIndependent }, text), fbCookie) } } /** @@ -113,7 +115,7 @@ class FrostJSI(val web: FrostWebView) { fun loadLogin() { L.d { "Sign up button found; load login" } context.ctxCoroutine.launch { - FbCookie.logout(context) + fbCookie.logout(context) } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt index 9e5e6c63..b4dd93da 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt @@ -20,12 +20,10 @@ import ca.allanwang.kau.utils.runOnUiThread import com.pitchedapps.frost.activities.WebOverlayActivity import com.pitchedapps.frost.activities.WebOverlayActivityBase import com.pitchedapps.frost.contracts.VideoViewHolder -import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.facebook.USER_AGENT_DESKTOP_CONST import com.pitchedapps.frost.facebook.formattedFbUrl import com.pitchedapps.frost.utils.L -import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.isFacebookUrl import com.pitchedapps.frost.utils.isImageUrl import com.pitchedapps.frost.utils.isIndependent @@ -69,32 +67,32 @@ fun FrostWebView.requestWebOverlay(url: String): Boolean { } if (url.isIndirectImageUrl) { L.d { "Found indirect fb image" } - context.launchImageActivity(url, cookie = FbCookie.webCookie) + context.launchImageActivity(url, cookie = fbCookie.webCookie) return true } if (!url.isIndependent) { L.d { "Forbid overlay switch" } return false } - if (!Prefs.overlayEnabled) return false + if (!prefs.overlayEnabled) return false if (context is WebOverlayActivityBase) { val shouldUseDesktop = url.isFacebookUrl // already overlay; manage user agent if (userAgentString != USER_AGENT_DESKTOP_CONST && shouldUseDesktop) { L._i { "Switch to desktop agent overlay" } - context.launchWebOverlayDesktop(url) + context.launchWebOverlayDesktop(url, fbCookie) return true } if (userAgentString == USER_AGENT_DESKTOP_CONST && !shouldUseDesktop) { L._i { "Switch from desktop agent" } - context.launchWebOverlayMobile(url) + context.launchWebOverlayMobile(url, fbCookie) return true } L._i { "return false switch" } return false } L.v { "Request web overlay passed" } - context.launchWebOverlay(url) + context.launchWebOverlay(url, fbCookie) return true } 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 2cd4c5db..a3c61323 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt @@ -67,6 +67,8 @@ open class BaseWebViewClient : WebViewClient() { */ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { + private val fbCookie: FbCookie get() = web.fbCookie + private val prefs: Prefs get() = web.prefs private val refresh: SendChannel<Boolean> = web.parent.refreshChannel private val isMain = web.parent.baseEnum != null /** @@ -102,7 +104,7 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { web.setBackgroundColor( when { isMain -> Color.TRANSPARENT - web.url.isFacebookUrl -> Prefs.bgColor.withAlpha(255) + web.url.isFacebookUrl -> prefs.bgColor.withAlpha(255) else -> Color.WHITE } ) @@ -115,21 +117,22 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { view.jsInject( // CssHider.CORE, CssHider.HEADER, - CssHider.COMPOSER.maybe(!Prefs.showComposer), - CssHider.STORIES.maybe(!Prefs.showStories), - CssHider.PEOPLE_YOU_MAY_KNOW.maybe(!Prefs.showSuggestedFriends), - CssHider.SUGGESTED_GROUPS.maybe(!Prefs.showSuggestedGroups), - Prefs.themeInjector, + CssHider.COMPOSER.maybe(!prefs.showComposer), + CssHider.STORIES.maybe(!prefs.showStories), + CssHider.PEOPLE_YOU_MAY_KNOW.maybe(!prefs.showSuggestedFriends), + CssHider.SUGGESTED_GROUPS.maybe(!prefs.showSuggestedGroups), + prefs.themeInjector, CssHider.NON_RECENT.maybe( (web.url?.contains("?sk=h_chr") ?: false) && - Prefs.aggressiveRecents + prefs.aggressiveRecents ), JsAssets.DOCUMENT_WATCHER, JsAssets.HORIZONTAL_SCROLLING, JsAssets.CLICK_A, - CssHider.ADS.maybe(!Prefs.showFacebookAds), + CssHider.ADS.maybe(!prefs.showFacebookAds), JsAssets.CONTEXT_A, - JsAssets.MEDIA + JsAssets.MEDIA, + prefs = prefs ) } else { refresh.offer(false) @@ -147,7 +150,7 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { } internal open fun onPageFinishedActions(url: String) { - if (url.startsWith("${FbItem.MESSAGES.url}/read/") && Prefs.messageScrollToBottom) { + if (url.startsWith("${FbItem.MESSAGES.url}/read/") && prefs.messageScrollToBottom) { web.pageDown(true) } injectAndFinish() @@ -160,7 +163,8 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { web.jsInject( JsActions.LOGIN_CHECK, JsAssets.TEXTAREA_LISTENER, - JsAssets.HEADER_BADGES.maybe(isMain) + JsAssets.HEADER_BADGES.maybe(isMain), + prefs = prefs ) } @@ -202,12 +206,12 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { return launchRequest(request) } if (url.isIndirectImageUrl) { - return launchImage(url.formattedFbUrl, cookie = FbCookie.webCookie) + return launchImage(url.formattedFbUrl, cookie = fbCookie.webCookie) } if (url.isImageUrl) { return launchImage(url.formattedFbUrl) } - if (Prefs.linksInDefaultApp && view.context.resolveActivityForUri(request.url)) { + if (prefs.linksInDefaultApp && view.context.resolveActivityForUri(request.url)) { return true } // Convert desktop urls to mobile ones @@ -229,12 +233,14 @@ private const val EMIT_FINISH = 0 */ class FrostWebViewClientMenu(web: FrostWebView) : FrostWebViewClient(web) { + private val prefs: Prefs get() = web.prefs + override fun onPageFinished(view: WebView, url: String?) { super.onPageFinished(view, url) if (url == null) { return } - jsInject(JsAssets.MENU) + jsInject(JsAssets.MENU, prefs = prefs) } override fun emit(flag: Int) { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt index 33a4875f..37e06db9 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt @@ -42,6 +42,8 @@ import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.isFacebookUrl import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.coroutineScope +import org.koin.core.KoinComponent +import org.koin.core.inject /** * Created by Allan Wang on 2017-05-29. @@ -50,8 +52,10 @@ class LoginWebView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : WebView(context, attrs, defStyleAttr) { +) : WebView(context, attrs, defStyleAttr), KoinComponent { + private val fbCookie: FbCookie by inject() + private val prefs: Prefs by inject() private val completable: CompletableDeferred<CookieEntity> = CompletableDeferred() private lateinit var progressCallback: (Int) -> Unit @@ -69,7 +73,7 @@ class LoginWebView @JvmOverloads constructor( this@LoginWebView.progressCallback = progressCallback L.d { "Begin loading login" } launchMain { - FbCookie.reset() + fbCookie.reset() setupWebview() loadUrl(FB_LOGIN_URL) } @@ -101,7 +105,8 @@ class LoginWebView @JvmOverloads constructor( if (url.isFacebookUrl) view.jsInject( CssHider.CORE, - Prefs.themeInjector + prefs.themeInjector, + prefs = prefs ) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt b/app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt index 7a37370d..fc62ef44 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt @@ -50,7 +50,9 @@ import com.pitchedapps.frost.utils.toReadableTime import org.koin.core.KoinComponent import org.koin.core.inject -class NotificationWidget : AppWidgetProvider() { +class NotificationWidget : AppWidgetProvider(), KoinComponent { + + private val prefs: Prefs by inject() override fun onUpdate( context: Context, @@ -59,19 +61,19 @@ class NotificationWidget : AppWidgetProvider() { ) { super.onUpdate(context, appWidgetManager, appWidgetIds) val type = NotificationType.GENERAL - val userId = Prefs.userId + val userId = prefs.userId val intent = NotificationWidgetService.createIntent(context, type, userId) for (id in appWidgetIds) { val views = RemoteViews(context.packageName, R.layout.widget_notifications) - views.setBackgroundColor(R.id.widget_layout_toolbar, Prefs.headerColor) - views.setIcon(R.id.img_frost, context, R.drawable.frost_f_24, Prefs.iconColor) + views.setBackgroundColor(R.id.widget_layout_toolbar, prefs.headerColor) + views.setIcon(R.id.img_frost, context, R.drawable.frost_f_24, prefs.iconColor) views.setOnClickPendingIntent( R.id.img_frost, PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), 0) ) - views.setBackgroundColor(R.id.widget_notification_list, Prefs.bgColor) + views.setBackgroundColor(R.id.widget_notification_list, prefs.bgColor) views.setRemoteAdapter(R.id.widget_notification_list, intent) val pendingIntentTemplate = PendingIntent.getActivity( @@ -149,6 +151,8 @@ class NotificationWidgetDataProvider(val context: Context, val intent: Intent) : RemoteViewsService.RemoteViewsFactory, KoinComponent { + private val prefs: Prefs by inject() + private val notifDao: NotificationDao by inject() @Volatile private var content: List<NotificationContent> = emptyList() @@ -182,10 +186,10 @@ class NotificationWidgetDataProvider(val context: Context, val intent: Intent) : val views = RemoteViews(context.packageName, R.layout.widget_notification_item) try { val notif = content[position] - views.setBackgroundColor(R.id.item_frame, Prefs.nativeBgColor(notif.unread)) - views.setTextColor(R.id.item_content, Prefs.textColor) + views.setBackgroundColor(R.id.item_frame, prefs.nativeBgColor(notif.unread)) + views.setTextColor(R.id.item_content, prefs.textColor) views.setTextViewText(R.id.item_content, notif.text) - views.setTextColor(R.id.item_date, Prefs.textColor.withAlpha(150)) + views.setTextColor(R.id.item_date, prefs.textColor.withAlpha(150)) views.setTextViewText(R.id.item_date, notif.timestamp.toReadableTime(context)) val avatar = glide.load(notif.profileUrl).transform(FrostGlide.circleCrop) diff --git a/gradle.properties b/gradle.properties index bc29a7b5..1fe7b114 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,7 +16,7 @@ org.gradle.daemon = true APP_ID=Frost APP_GROUP=com.pitchedapps -KAU=e4bba6f +KAU=5038b93 android.useAndroidX=true android.enableJetifier=true |