diff options
Diffstat (limited to 'app/src/main/kotlin')
10 files changed, 173 insertions, 64 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt index 17840a14..f60d31a0 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt @@ -2,6 +2,7 @@ package com.pitchedapps.frost import android.graphics.drawable.ColorDrawable import android.os.Bundle +import android.support.design.widget.AppBarLayout import android.support.design.widget.FloatingActionButton import android.support.design.widget.Snackbar import android.support.design.widget.TabLayout @@ -11,7 +12,7 @@ import android.support.v4.view.ViewPager import android.support.v7.widget.Toolbar import android.view.Menu import android.view.MenuItem -import android.view.ViewTreeObserver +import android.widget.ImageButton import ca.allanwang.kau.utils.* import co.zsmb.materialdrawerkt.builders.Builder import co.zsmb.materialdrawerkt.builders.accountHeader @@ -33,6 +34,7 @@ import com.pitchedapps.frost.services.requestNotifications import com.pitchedapps.frost.utils.* import io.reactivex.disposables.Disposable import io.reactivex.subjects.PublishSubject +import org.jetbrains.anko.childrenSequence class MainActivity : BaseActivity() { @@ -41,6 +43,7 @@ class MainActivity : BaseActivity() { val viewPager: ViewPager by bindView(R.id.container) val fab: FloatingActionButton by bindView(R.id.fab) val tabs: TabLayout by bindView(R.id.tabs) + val appBar: AppBarLayout by bindView(R.id.appbar) lateinit var drawer: Drawer lateinit var drawerHeader: AccountHeader var titleDisposable: Disposable? = null @@ -78,12 +81,23 @@ class MainActivity : BaseActivity() { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show() } - viewPager.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { - override fun onGlobalLayout() { - viewPager.viewTreeObserver.removeOnGlobalLayoutListener(this) - updateTitleListener() - } - }) + viewPager.post { updateTitleListener() } + theme() + } + + fun theme() { + val darkAccent = Prefs.headerColor.darken() + statusBarColor = darkAccent.withAlpha(255) + navigationBarColor = darkAccent + tabs.setBackgroundColor(darkAccent) + appBar.setBackgroundColor(darkAccent) + toolbar.setBackgroundColor(darkAccent) + toolbar.setTitleTextColor(Prefs.iconColor) +// toolbar.tint + viewPager.setBackgroundColor(Prefs.bgColor) + window.setBackgroundDrawable(ColorDrawable(Prefs.bgColor)) + toolbar.overflowIcon?.setTint(Prefs.iconColor) + drawer } fun updateTitleListener() { @@ -99,23 +113,27 @@ class MainActivity : BaseActivity() { currentFragment.web.scrollOrRefresh() } }) - adapter.pages.forEach { tabs.addTab(tabs.newTab().setIcon(it.icon.toDrawable(this))) } + adapter.pages.forEach { tabs.addTab(tabs.newTab().setIcon(it.icon.toDrawable(this, color = Prefs.iconColor))) } } fun setupDrawer(savedInstanceState: Bundle?) { + val navBg = Prefs.bgColor.withMinAlpha(200).toLong() + val navHeader = Prefs.headerColor.withMinAlpha(200) drawer = drawer { toolbar = this@MainActivity.toolbar savedInstance = savedInstanceState translucentStatusBar = false - sliderBackgroundColor = Prefs.bgColor.withMinAlpha(200).toLong() + sliderBackgroundColor = navBg drawerHeader = accountHeader { - textColor = Prefs.textColor.toLong() - backgroundDrawable = ColorDrawable(Prefs.headerColor) + textColor = Prefs.iconColor.toLong() + backgroundDrawable = ColorDrawable(navHeader) + selectionSecondLineShown = false cookies().forEach { (id, name) -> profile(name = name ?: "") { iconUrl = PROFILE_PICTURE_URL(id) textColor = Prefs.textColor.toLong() selectedTextColor = Prefs.textColor.toLong() + selectedColor = 0x00000001.toLong() identifier = id } } @@ -167,6 +185,7 @@ class MainActivity : BaseActivity() { override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_main, menu) + toolbar.childrenSequence().forEach { (it as? ImageButton)?.setColorFilter(Prefs.iconColor) } return true } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt index 60499c4a..4543074e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt @@ -5,7 +5,6 @@ import ca.allanwang.kau.kpref.KPrefActivity import ca.allanwang.kau.kpref.KPrefAdapterBuilder import ca.allanwang.kau.utils.* import ca.allanwang.kau.views.RippleCanvas -import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.pitchedapps.frost.utils.EXTRA_COOKIES import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.Theme @@ -30,6 +29,7 @@ class SettingsActivity : KPrefActivity() { if (item.pref != which) { item.pref = which reload() + themeExterior() } true }) @@ -40,43 +40,79 @@ class SettingsActivity : KPrefActivity() { setter = { Prefs.theme = it } }, textGetter = { this@SettingsActivity.string(Theme(it).textRes) }) colorPicker(title = R.string.text_color, itemBuilder = { - getter = { Prefs.textColor } - setter = { Prefs.textColor = it; reload() } + getter = { Prefs.customTextColor } + setter = { Prefs.customTextColor = it; reload() } + enabler = { Prefs.isCustomTheme } + onDisabledClick = { itemView, _, _ -> + itemView.snackbar(R.string.requires_custom_theme) + true + } }, colorBuilder = { + allowCustomAlpha = false allowCustom = true }) - colorPicker(title = R.string.background_color, coreBuilder = { - iicon = GoogleMaterial.Icon.gmd_colorize - }, itemBuilder = { - getter = { Prefs.bgColor } - setter = { Prefs.bgColor = it; bgCanvas.ripple(it, duration = 500L) } + colorPicker(title = R.string.background_color, itemBuilder = { + getter = { Prefs.customBackgroundColor } + setter = { Prefs.customBackgroundColor = it; bgCanvas.ripple(it, duration = 500L) } + enabler = { Prefs.isCustomTheme } + onDisabledClick = { itemView, _, _ -> + itemView.snackbar(R.string.requires_custom_theme) + true + } }, colorBuilder = { - allowCustomAlpha = false + allowCustomAlpha = true allowCustom = true }) colorPicker(title = R.string.header_color, itemBuilder = { - getter = { Prefs.headerColor } + getter = { Prefs.customHeaderColor } setter = { - Prefs.headerColor = it + Prefs.customHeaderColor = it val darkerColor = it.darken() this@SettingsActivity.navigationBarColor = darkerColor toolbarCanvas.ripple(darkerColor, RippleCanvas.MIDDLE, RippleCanvas.END, duration = 500L) } + enabler = { Prefs.isCustomTheme } + onDisabledClick = { itemView, _, _ -> + itemView.snackbar(R.string.requires_custom_theme) + true + } }, colorBuilder = { - allowCustom = false + allowCustomAlpha = true + allowCustom = true + }) + + colorPicker(title = R.string.icon_color, itemBuilder = { + getter = { Prefs.customIconColor } + setter = { Prefs.customIconColor = it; toolbar.setTitleTextColor(it) } + enabler = { Prefs.isCustomTheme } + onDisabledClick = { itemView, _, _ -> + itemView.snackbar(R.string.requires_custom_theme) + true + } + }, colorBuilder = { + allowCustomAlpha = false + allowCustom = true }) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - bgCanvas.set(Prefs.bgColor) + themeExterior(false) + } + + fun themeExterior(animate: Boolean = true) { + if (animate) bgCanvas.fade(Prefs.bgColor) + else bgCanvas.set(Prefs.bgColor) val darkAccent = Prefs.headerColor.darken() - toolbarCanvas.set(darkAccent) + if (animate) toolbarCanvas.ripple(darkAccent, RippleCanvas.MIDDLE, RippleCanvas.END) + else toolbarCanvas.set(darkAccent) this.navigationBarColor = darkAccent } + private fun relativeDuration(canvas: RippleCanvas): Long = Math.hypot(canvas.height.toDouble(), canvas.width.toDouble() / 2).toLong() + override fun onBackPressed() { startActivitySlideOut(MainActivity::class.java, clearStack = true, intentBuilder = { putParcelableArrayListExtra(EXTRA_COOKIES, cookies()) 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 7ef358f3..45ece582 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt @@ -10,7 +10,7 @@ import com.pitchedapps.frost.utils.L * //TODO add folder mapping using Prefs */ enum class CssAssets(val folder: String = "themes") : InjectorContract { - LOGIN("core"), MATERIAL_LIGHT, MATERIAL_DARK, MATERIAL_AMOLED, MATERIAL_GLASS + LOGIN("core"), MATERIAL_LIGHT, MATERIAL_DARK, MATERIAL_AMOLED, MATERIAL_GLASS, CUSTOM ; var file = "${name.toLowerCase()}.compact.css" 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 7d59f797..17d7ca81 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt @@ -5,14 +5,15 @@ import android.webkit.WebView /** * Created by Allan Wang on 2017-05-31. */ -enum class JsActions(body: String) { +enum class JsActions(body: String) : InjectorContract { /** * Redirects to login activity if create account is found * see [com.pitchedapps.frost.web.FrostJSI.loadLogin] */ - LOGIN_CHECK("document.getElementById('signup-button')&&Frost.loadLogin();"); + LOGIN_CHECK("document.getElementById('signup-button')&&Frost.loadLogin();"), + EMPTY(""); val function = "!function(){$body}();" - fun inject(webView: WebView, callback: ((String) -> Unit)? = null) = JsInjector(function).inject(webView, callback) + override fun inject(webView: WebView, callback: ((String) -> Unit)?) = JsInjector(function).inject(webView, callback) }
\ No newline at end of file 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 e0a9dd3d..d0bf9deb 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt @@ -9,14 +9,14 @@ import com.pitchedapps.frost.utils.L * The enum name must match the css file name * //TODO add folder mapping using Prefs */ -enum class JsAssets { - MENU, MENU_CLICK +enum class JsAssets : InjectorContract { + MENU, MENU_CLICK, CLICK_INTERCEPTOR ; var file = "${name.toLowerCase()}.min.js" var injector: JsInjector? = null - fun inject(webView: WebView, callback: ((String) -> Unit)?) { + override fun inject(webView: WebView, callback: ((String) -> Unit)?) { if (injector == null) { val content = webView.context.assets.open("js/$file").bufferedReader().use { it.readText() } injector = JsBuilder().js(content).build() 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 3bbecb4f..28aadf21 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt @@ -1,6 +1,7 @@ package com.pitchedapps.frost.services import android.app.IntentService +import android.app.Notification import android.app.PendingIntent import android.content.Context import android.content.Intent @@ -10,10 +11,7 @@ import android.support.v4.app.NotificationManagerCompat import ca.allanwang.kau.utils.string import com.pitchedapps.frost.R import com.pitchedapps.frost.WebOverlayActivity -import com.pitchedapps.frost.dbflow.NotificationModel -import com.pitchedapps.frost.dbflow.lastNotificationTime -import com.pitchedapps.frost.dbflow.loadFbCookie -import com.pitchedapps.frost.dbflow.saveNotificationTime +import com.pitchedapps.frost.dbflow.* import com.pitchedapps.frost.facebook.FACEBOOK_COM import com.pitchedapps.frost.facebook.FB_URL_BASE import com.pitchedapps.frost.facebook.FbTab @@ -46,7 +44,7 @@ class NotificationService : IntentService(NotificationService::class.java.simple L.i("Latest Epoch $latestEpoch") unreadNotifications.forEach { elem -> - val notif = parseNotification(data.id, elem) + val notif = parseNotification(data, elem) if (notif != null) { if (notif.timestamp <= latestEpoch) return@forEach notif.createNotification(this) @@ -54,11 +52,11 @@ class NotificationService : IntentService(NotificationService::class.java.simple notifCount++ } } - saveNotificationTime(NotificationModel(data.id, latestEpoch)) + if (notifCount > 0) saveNotificationTime(NotificationModel(data.id, latestEpoch)) summaryNotification(data.id, notifCount) } - fun parseNotification(userId: Long, element: Element): NotificationContent? { + fun parseNotification(data: CookieModel, element: Element): NotificationContent? { val a = element.getElementsByTag("a").first() ?: return null val dataStore = a.attr("data-store") val notifId = if (dataStore == null) System.currentTimeMillis() @@ -70,15 +68,16 @@ class NotificationService : IntentService(NotificationService::class.java.simple text = text.trim() val abbrData = abbr?.attr("data-store") val epoch = if (abbrData == null) -1L else epochMatcher.find(abbrData)?.groups?.get(1)?.value?.toLong() ?: -1L - return NotificationContent(userId, notifId.toInt(), a.attr("href"), text, epoch) + return NotificationContent(data, notifId.toInt(), a.attr("href"), text, epoch) } - data class NotificationContent(val userId: Long, val notifId: Int, val href: String, val text: String, val timestamp: Long) { + data class NotificationContent(val data: CookieModel, val notifId: Int, val href: String, val text: String, val timestamp: Long) { fun createNotification(context: Context) { val intent = Intent(context, WebOverlayActivity::class.java) -// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP or PendingIntent.FLAG_ONE_SHOT) + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) intent.putExtra(ARG_URL, "$FB_URL_BASE$href") intent.action = System.currentTimeMillis().toString() //dummy action + val group = "frost_${data.id}" val bundle = ActivityOptionsCompat.makeCustomAnimation(context, R.anim.slide_in_right, R.anim.slide_out_right).toBundle() val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT, bundle) val notifBuilder = NotificationCompat.Builder(context) @@ -86,12 +85,15 @@ class NotificationService : IntentService(NotificationService::class.java.simple .setContentTitle(context.string(R.string.app_name)) .setContentText(text) .setContentIntent(pendingIntent) - .setGroup("frost_$userId") + .setCategory(Notification.CATEGORY_SOCIAL) + .setSubText(data.name) + .setGroup(group) .setAutoCancel(true) +// .setColor(context.color(R.color.facebook_blue)) if (timestamp != -1L) notifBuilder.setWhen(timestamp * 1000) - NotificationManagerCompat.from(context).notify("frost_$userId", notifId, notifBuilder.build()) + NotificationManagerCompat.from(context).notify(group, notifId, notifBuilder.build()) } } 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 115f981a..396b4471 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt @@ -3,6 +3,7 @@ package com.pitchedapps.frost.utils import android.graphics.Color import ca.allanwang.kau.kpref.KPref import ca.allanwang.kau.kpref.kpref +import com.pitchedapps.frost.injectors.InjectorContract /** * Created by Allan Wang on 2017-05-28. @@ -15,15 +16,39 @@ object Prefs : KPref() { var userId: Long by kpref("user_id", -1L) - var theme: Int by kpref("theme", 0) + var theme: Int by kpref("theme", 0, postSetter = { value: Int -> + loader.invalidate() + }) - var textColor: Int by kpref("color_text", Color.BLACK) + var customTextColor: Int by kpref("color_text", Color.BLACK) - var bgColor: Int by kpref("color_bg", Color.WHITE) + var customBackgroundColor: Int by kpref("color_bg", 0xfffafafa.toInt()) - var headerColor: Int by kpref("color_header", 0xff3b5998.toInt()) + var customHeaderColor: Int by kpref("color_header", 0xff3b5998.toInt()) - var iconColor: Int by kpref("color_icons", Color.WHITE) + var customIconColor: Int by kpref("color_icons", Color.WHITE) var exitConfirmation: Boolean by kpref("exit_confirmation", true) + + private val loader = lazyResettable { Theme.values[Prefs.theme] } + + private val t: Theme by loader + + val textColor: Int + get() = t.textColor + + val bgColor: Int + get() = t.bgColor + + val headerColor: Int + get() = t.headerColor + + val iconColor: Int + get() = t.iconColor + + val themeInjector: InjectorContract + get() = t.injector + + val isCustomTheme: Boolean + get() = t == Theme.CUSTOM } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Theme.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Theme.kt index 4a0ffd8f..1eff6780 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Theme.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Theme.kt @@ -1,19 +1,39 @@ package com.pitchedapps.frost.utils +import android.graphics.Color import com.pitchedapps.frost.R +import com.pitchedapps.frost.injectors.CssAssets +import com.pitchedapps.frost.injectors.InjectorContract +import com.pitchedapps.frost.injectors.JsActions /** * Created by Allan Wang on 2017-06-14. */ -enum class Theme(val textRes: Int) { - DEFAULT(R.string._default), - LIGHT(R.string.light), - DARK(R.string.dark), - AMOLED(R.string.amoled), - GLASS(R.string.glass), - CUSTOM(R.string.custom); +enum class Theme(val textRes: Int, val injector: InjectorContract, + private val textColorGetter: () -> Int, private val backgroundColorGetter: () -> Int, + private val headerColorGetter: () -> Int, private val iconColorGetter: () -> Int) { + DEFAULT(R.string._default, JsActions.EMPTY, { Color.BLACK }, { 0xfffafafa.toInt() }, { 0xff3b5998.toInt() }, { Color.WHITE }), + LIGHT(R.string.light, CssAssets.MATERIAL_LIGHT, { Color.BLACK }, { 0xfffafafa.toInt() }, { 0xff3b5998.toInt() }, { Color.WHITE }), + DARK(R.string.dark, CssAssets.MATERIAL_DARK, { Color.WHITE }, { 0xff303030.toInt() }, { 0xff3b5998.toInt() }, { Color.WHITE }), + AMOLED(R.string.amoled, CssAssets.MATERIAL_AMOLED, { Color.WHITE }, { Color.BLACK }, { Color.BLACK }, { Color.WHITE }), + GLASS(R.string.glass, CssAssets.MATERIAL_GLASS, { Color.WHITE }, { 0x80000000.toInt() }, { 0xb3000000.toInt() }, { Color.WHITE }), + CUSTOM(R.string.custom, JsActions.EMPTY, { Prefs.customTextColor }, { Prefs.customBackgroundColor }, { Prefs.customHeaderColor }, { Prefs.customIconColor }); + //todo create custom + + val textColor: Int + get() = textColorGetter.invoke() + + val bgColor: Int + get() = backgroundColorGetter.invoke() + + val headerColor: Int + get() = headerColorGetter.invoke() + + val iconColor: Int + get() = iconColorGetter.invoke() companion object { - operator fun invoke(index: Int) = values()[index] + val values = values() //save one instance + operator fun invoke(index: Int) = values[index] } }
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt index 1ae17cde..c3eb0a1f 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt @@ -10,7 +10,10 @@ import com.pitchedapps.frost.MainActivity import com.pitchedapps.frost.SelectorActivity import com.pitchedapps.frost.facebook.FACEBOOK_COM import com.pitchedapps.frost.facebook.FbCookie -import com.pitchedapps.frost.injectors.* +import com.pitchedapps.frost.injectors.CssHider +import com.pitchedapps.frost.injectors.JsActions +import com.pitchedapps.frost.injectors.JsAssets +import com.pitchedapps.frost.injectors.jsInject import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.cookies @@ -62,13 +65,14 @@ open class FrostWebViewClient(val refreshObservable: Subject<Boolean>) : WebView internal fun onPageFinishedReveal(view: FrostWebViewCore, animate: Boolean) { L.d("Page finished reveal") view.jsInject(CssHider.HEADER, -// CssAssets.MATERIAL_DARK, + Prefs.themeInjector, + JsAssets.CLICK_INTERCEPTOR, callback = { - L.d("Finished ${it.contentToString()}") - refreshObservable.onNext(false) - if (animate) view.circularReveal(offset = 150L) - else view.fadeIn(duration = 100L) - }) + L.d("Finished ${it.contentToString()}") + refreshObservable.onNext(false) + if (animate) view.circularReveal(offset = 150L) + else view.fadeIn(duration = 100L) + }) } open fun handleHtml(html: String) { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt index 8d057db1..db5f877d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt @@ -3,6 +3,7 @@ package com.pitchedapps.frost.web import android.animation.ValueAnimator import android.annotation.SuppressLint import android.content.Context +import android.graphics.Color import android.support.v4.view.NestedScrollingChild import android.support.v4.view.NestedScrollingChildHelper import android.support.v4.view.ViewCompat @@ -61,6 +62,7 @@ class FrostWebViewCore @JvmOverloads constructor( webViewClient = frostWebClient webChromeClient = FrostChromeClient(progressObservable, titleObservable) addJavascriptInterface(FrostJSI(context, this), "Frost") + setBackgroundColor(Color.TRANSPARENT) } override fun loadUrl(url: String?) { |