diff --git a/components/browser/session/src/main/java/mozilla/components/browser/session/Session.kt b/components/browser/session/src/main/java/mozilla/components/browser/session/Session.kt index 9f8012c346b..71e987abb7a 100644 --- a/components/browser/session/src/main/java/mozilla/components/browser/session/Session.kt +++ b/components/browser/session/src/main/java/mozilla/components/browser/session/Session.kt @@ -73,6 +73,7 @@ class Session( fun onCrashStateChanged(session: Session, crashed: Boolean) = Unit fun onIconChanged(session: Session, icon: Bitmap?) = Unit fun onReaderableStateUpdated(session: Session, readerable: Boolean) = Unit + fun onReaderModeChanged(session: Session, enabled: Boolean) = Unit } /** @@ -379,6 +380,13 @@ class Session( notifyObservers { onReaderableStateUpdated(this@Session, new) } } + /** + * Reader mode state, whether or not reader view is enabled, otherwise false. + */ + var readerMode: Boolean by Delegates.observable(false) { _, old, new -> + notifyObservers(old, new) { onReaderModeChanged(this@Session, new) } + } + /** * Returns whether or not this session is used for a Custom Tab. */ diff --git a/components/browser/session/src/test/java/mozilla/components/browser/session/SessionTest.kt b/components/browser/session/src/test/java/mozilla/components/browser/session/SessionTest.kt index 1dcef1471bc..d6b81ff180f 100644 --- a/components/browser/session/src/test/java/mozilla/components/browser/session/SessionTest.kt +++ b/components/browser/session/src/test/java/mozilla/components/browser/session/SessionTest.kt @@ -958,4 +958,21 @@ class SessionTest { assertTrue(session.readerable) } + + @Test + fun `observer is notified when reader mode state changes`() { + val observer = mock(Session.Observer::class.java) + + val session = Session("https://www.mozilla.org") + session.register(observer) + assertFalse(session.readerMode) + + session.readerMode = true + + verify(observer).onReaderModeChanged( + eq(session), + eq(true)) + + assertTrue(session.readerMode) + } } diff --git a/components/feature/readerview/src/main/assets/extensions/readerview/readerview.css b/components/feature/readerview/src/main/assets/extensions/readerview/readerview.css index 1bf5f0196b9..ca42e1e05a1 100644 --- a/components/feature/readerview/src/main/assets/extensions/readerview/readerview.css +++ b/components/feature/readerview/src/main/assets/extensions/readerview/readerview.css @@ -29,12 +29,12 @@ color: #eeeeee; } -.mozac-readerview-body.sans-serif { - font-family: sans-serif; +.mozac-readerview-body.sans-serif * { + font-family: sans-serif !important; } -.mozac-readerview-body.serif { - font-family: serif; +.mozac-readerview-body.serif * { + font-family: serif !important; } /* Override some controls and content styles based on color scheme */ @@ -106,7 +106,6 @@ .mozac-readerview-body > .container > .header > .credits { font-size: 0.9em; - font-family: sans-serif; } .mozac-readerview-body > .container > .header > .domain { @@ -139,6 +138,11 @@ margin-bottom: 32px; } +.mozac-readerview-body > .container > .header > .meta-data { + font-size: 0.65em; + margin: 0 0 15px 0; +} + .mozac-readerview-body > .container > .content { padding-left: 0px; padding-right: 0px; @@ -161,8 +165,22 @@ color: #00acff !important; } +.mozac-readerview-content h1, h2, h3 { + margin-top: 16px; + margin-bottom: 16px; + font-weight: 700; +} + +.mozac-readerview-content h1 { + font-size: 1.6em; +} + .mozac-readerview-content h2 { - margin-bottom: 20px !important; + font-size: 1.2em; +} + +.mozac-readerview-content h3 { + font-size: 1em; } .mozac-readerview-content * { @@ -171,6 +189,7 @@ } .mozac-readerview-content p { + font-size: 1em !important; line-height: 1.4em !important; margin: 0px !important; margin-bottom: 20px !important; diff --git a/components/feature/readerview/src/main/assets/extensions/readerview/readerview.js b/components/feature/readerview/src/main/assets/extensions/readerview/readerview.js index 30e987af583..49ddb646ec6 100644 --- a/components/feature/readerview/src/main/assets/extensions/readerview/readerview.js +++ b/components/feature/readerview/src/main/assets/extensions/readerview/readerview.js @@ -26,7 +26,7 @@ class ReaderView { return false; } - return isProbablyReaderable(document); + return isProbablyReaderable(document, ReaderView._isNodeVisible); } static get MIN_FONT_SIZE() { @@ -37,6 +37,10 @@ class ReaderView { return 9; } + static _isNodeVisible(node) { + return node.clientHeight > 0 && node.clientWidth > 0; + } + constructor(document) { this.document = document; this.originalBody = document.body.outerHTML; @@ -63,6 +67,7 @@ class ReaderView { hide() { document.body.outerHTML = this.originalBody; + location.reload(false) } /** @@ -95,10 +100,6 @@ class ReaderView { * @param fontType the font type to use. */ setFontType(fontType) { - if (this.fontType === fontType) { - return; - } - let bodyClasses = document.body.classList; if (this.fontType) { @@ -121,10 +122,6 @@ class ReaderView { return; } - if (this.colorScheme === colorScheme) { - return; - } - let bodyClasses = document.body.classList; if (this.colorScheme) { @@ -279,16 +276,26 @@ class ReaderView { } } -let port = browser.runtime.connectNative("mozacReaderview"); +let readerView = new ReaderView(document); +let port = browser.runtime.connectNative("mozacReaderview"); port.onMessage.addListener((message) => { switch (message.action) { case 'show': - readerView.show({fontSize: 3, fontType: "serif", colorScheme: "light"}); + readerView.show(message.value); break; case 'hide': readerView.hide(); break; + case 'setColorScheme': + readerView.setColorScheme(message.value.toLowerCase()); + break; + case 'changeFontSize': + readerView.changeFontSize(message.value); + break; + case 'setFontType': + readerView.setFontType(message.value.toLowerCase()); + break; case 'checkReaderable': port.postMessage({readerable: ReaderView.isReaderable()}); break; @@ -296,13 +303,3 @@ port.onMessage.addListener((message) => { console.error(`Received invalid action ${message.action}`); } }); - -// TODO remove hostname check (for testing purposes only) -// e.g. https://blog.mozilla.org/firefox/reader-view -if (ReaderView.isReaderable() && location.hostname.endsWith("blog.mozilla.org")) { - // TODO send message to app to inform that readerview is available - // For now we show reader view for every page on blog.mozilla.org - let readerView = new ReaderView(document); - // TODO Parameters need to be passed down in message to display readerview - readerView.show({fontSize: 3, fontType: "serif", colorScheme: "light"}); -} diff --git a/components/feature/readerview/src/main/java/mozilla/components/feature/readerview/ReaderViewFeature.kt b/components/feature/readerview/src/main/java/mozilla/components/feature/readerview/ReaderViewFeature.kt index 140a8101277..ad0faaa3f58 100644 --- a/components/feature/readerview/src/main/java/mozilla/components/feature/readerview/ReaderViewFeature.kt +++ b/components/feature/readerview/src/main/java/mozilla/components/feature/readerview/ReaderViewFeature.kt @@ -22,7 +22,6 @@ import mozilla.components.support.base.feature.BackHandler import mozilla.components.support.base.feature.LifecycleAwareFeature import mozilla.components.support.base.log.logger.Logger import org.json.JSONObject -import java.lang.IllegalStateException import java.util.WeakHashMap import kotlin.properties.Delegates @@ -51,32 +50,38 @@ class ReaderViewFeature( private val onReaderViewAvailableChange: OnReaderViewAvailableChange = { } ) : SelectionAwareSessionObserver(sessionManager), LifecycleAwareFeature, BackHandler { - private val config = Config(context.getSharedPreferences("mozac_feature_reader_view", Context.MODE_PRIVATE)) + private val config = Config(context.getSharedPreferences("mozac_feature_reader_view", Context.MODE_PRIVATE), this) private val controlsPresenter = ReaderViewControlsPresenter(controlsView, config) private val controlsInteractor = ReaderViewControlsInteractor(controlsView, config) - class Config(prefs: SharedPreferences) { - enum class FontType { SANS_SERIF, SERIF } + class Config(val prefs: SharedPreferences, val readerViewFeature: ReaderViewFeature) { + enum class FontType(val value: String) { SANSSERIF("sans-serif"), SERIF("serif") } enum class ColorScheme { LIGHT, SEPIA, DARK } var colorScheme by Delegates.observable(ColorScheme.valueOf(prefs.getString(COLOR_SCHEME_KEY, "LIGHT")!!)) { - _, old, new -> saveAndSendMessage(old, new, COLOR_SCHEME_KEY) - } - - @Suppress("MagicNumber") - var fontSize by Delegates.observable(prefs.getInt(FONT_SIZE_KEY, 3)) { - _, old, new -> saveAndSendMessage(old, new, FONT_SIZE_KEY) + _, old, new -> + if (old != new) { + val message = JSONObject().put(ACTION_MESSAGE_KEY, ACTION_SET_COLOR_SCHEME).put(ACTION_VALUE, new) + readerViewFeature.sendContentMessage(message) + prefs.edit().putString(COLOR_SCHEME_KEY, new.name).commit() + } } - var fontType by Delegates.observable(FontType.valueOf(prefs.getString(FONT_TYPE_KEY, "SANS_SERIF")!!)) { - _, old, new -> saveAndSendMessage(old, new, FONT_TYPE_KEY) + var fontType by Delegates.observable(FontType.valueOf(prefs.getString(FONT_TYPE_KEY, "SERIF")!!)) { + _, old, new -> + if (old != new) { + val message = JSONObject().put(ACTION_MESSAGE_KEY, ACTION_SET_FONT_TYPE).put(ACTION_VALUE, new.name) + readerViewFeature.sendContentMessage(message) + prefs.edit().putString(FONT_TYPE_KEY, new.name).commit() + } } - @Suppress("UNUSED_PARAMETER") - private fun saveAndSendMessage(old: Any, new: Any, key: String) { + @Suppress("MagicNumber") + var fontSize by Delegates.observable(prefs.getInt(FONT_SIZE_KEY, 3)) { _, old, new -> if (old != new) { - // TODO save shared preference - // TODO send message to reader view web extension + val message = JSONObject().put(ACTION_MESSAGE_KEY, ACTION_CHANGE_FONT_SIZE).put(ACTION_VALUE, new - old) + readerViewFeature.sendContentMessage(message) + prefs.edit().putInt(FONT_SIZE_KEY, new).commit() } } @@ -132,12 +137,16 @@ class ReaderViewFeature( } override fun onBackPressed(): Boolean { - // TODO send message to exit reader view (-> see ReaderView.hide()) - return true + activeSession?.let { + if (it.readerMode) { + hideReaderView() + return true + } + } + return false } override fun onSessionSelected(session: Session) { - // TODO restore selected state of whether the controls are open or not registerContentMessageHandler(activeSession) checkReaderable() super.onSessionSelected(session) @@ -148,22 +157,44 @@ class ReaderViewFeature( } override fun onUrlChanged(session: Session, url: String) { + session.readerMode = false checkReaderable() } + override fun onLoadingStateChanged(session: Session, loading: Boolean) { + // If the page was refreshed and reader mode was turned on before, + // make sure it is still turned on. + if (!loading && activeSession?.readerMode == true) { + showReaderView() + } + } + override fun onReaderableStateUpdated(session: Session, readerable: Boolean) { onReaderViewAvailableChange(readerable) } fun showReaderView() { activeSession?.let { - sendMessage(JSONObject().put(ACTION_MESSAGE_KEY, ACTION_SHOW), it) + val config = JSONObject() + .put(ACTION_VALUE_FONT_SIZE, config.fontSize) + .put(ACTION_VALUE_FONT_TYPE, config.fontType.name.toLowerCase()) + .put(ACTION_VALUE_COLOR_SCHEME, config.colorScheme.name.toLowerCase()) + + val message = JSONObject() + .put(ACTION_MESSAGE_KEY, ACTION_SHOW) + .put(ACTION_VALUE, config) + + sendContentMessage(message, it) + it.readerMode = true } } fun hideReaderView() { activeSession?.let { - sendMessage(JSONObject().put(ACTION_MESSAGE_KEY, ACTION_HIDE), it) + it.readerMode = false + // We will re-determine if the original page is readerable when it's loaded. + it.readerable = false + sendContentMessage(JSONObject().put(ACTION_MESSAGE_KEY, ACTION_HIDE), it) } } @@ -184,40 +215,40 @@ class ReaderViewFeature( internal fun checkReaderable() { activeSession?.let { if (ports.containsKey(sessionManager.getEngineSession(it))) { - sendMessage(JSONObject().put(ACTION_MESSAGE_KEY, ACTION_CHECK_READERABLE), it) + sendContentMessage(JSONObject().put(ACTION_MESSAGE_KEY, ACTION_CHECK_READERABLE), it) } } } - private fun sendMessage(msg: Any, session: Session) { - val port = ports[sessionManager.getEngineSession(session)] - port?.postMessage(msg) ?: throw IllegalStateException("No port connected for the provided session") + private fun sendContentMessage(msg: Any, session: Session? = activeSession) { + session?.let { + val port = ports[sessionManager.getEngineSession(session)] + port?.postMessage(msg) ?: Logger.error("No port connected for the provided session") + } } + @VisibleForTesting companion object { - @VisibleForTesting internal const val READER_VIEW_EXTENSION_ID = "mozacReaderview" - - @VisibleForTesting internal const val READER_VIEW_EXTENSION_URL = "resource://android/assets/extensions/readerview/" - @VisibleForTesting internal const val ACTION_MESSAGE_KEY = "action" - @VisibleForTesting internal const val ACTION_SHOW = "show" - - @VisibleForTesting internal const val ACTION_HIDE = "hide" - - @VisibleForTesting internal const val ACTION_CHECK_READERABLE = "checkReaderable" + internal const val ACTION_SET_COLOR_SCHEME = "setColorScheme" + internal const val ACTION_CHANGE_FONT_SIZE = "changeFontSize" + internal const val ACTION_SET_FONT_TYPE = "setFontType" + + internal const val ACTION_VALUE = "value" + internal const val ACTION_VALUE_FONT_SIZE = "fontSize" + internal const val ACTION_VALUE_FONT_TYPE = "fontType" + internal const val ACTION_VALUE_COLOR_SCHEME = "colorScheme" - @VisibleForTesting internal const val READERABLE_RESPONSE_MESSAGE_KEY = "readerable" @Volatile - @VisibleForTesting internal var installedWebExt: WebExtension? = null @Volatile diff --git a/components/feature/readerview/src/main/java/mozilla/components/feature/readerview/view/ReaderViewControlsBar.kt b/components/feature/readerview/src/main/java/mozilla/components/feature/readerview/view/ReaderViewControlsBar.kt index 67d912da849..e166dd8d052 100644 --- a/components/feature/readerview/src/main/java/mozilla/components/feature/readerview/view/ReaderViewControlsBar.kt +++ b/components/feature/readerview/src/main/java/mozilla/components/feature/readerview/view/ReaderViewControlsBar.kt @@ -54,7 +54,7 @@ class ReaderViewControlsBar @JvmOverloads constructor( override fun setFont(font: FontType) { val selected = when (font) { FontType.SERIF -> R.id.mozac_feature_readerview_font_serif - FontType.SANS_SERIF -> R.id.mozac_feature_readerview_font_sans_serif + FontType.SANSSERIF -> R.id.mozac_feature_readerview_font_sans_serif } fontGroup.check(selected) } @@ -123,7 +123,7 @@ class ReaderViewControlsBar @JvmOverloads constructor( private fun bindViews() { fontGroup = applyCheckedListener(R.id.mozac_feature_readerview_font_group) { checkedId -> val fontType = when (checkedId) { - R.id.mozac_feature_readerview_font_sans_serif -> FontType.SANS_SERIF + R.id.mozac_feature_readerview_font_sans_serif -> FontType.SANSSERIF R.id.mozac_feature_readerview_font_serif -> FontType.SERIF else -> FontType.SERIF } diff --git a/components/feature/readerview/src/test/java/mozilla/components/feature/readerview/internal/ReaderViewControlsInteractorTest.kt b/components/feature/readerview/src/test/java/mozilla/components/feature/readerview/internal/ReaderViewControlsInteractorTest.kt index 5b1521cbe0d..4b25ff44f2a 100644 --- a/components/feature/readerview/src/test/java/mozilla/components/feature/readerview/internal/ReaderViewControlsInteractorTest.kt +++ b/components/feature/readerview/src/test/java/mozilla/components/feature/readerview/internal/ReaderViewControlsInteractorTest.kt @@ -43,9 +43,9 @@ class ReaderViewControlsInteractorTest { val config: ReaderViewFeature.Config = mock() val interactor = ReaderViewControlsInteractor(mock(), config) - interactor.onFontChanged(ReaderViewFeature.Config.FontType.SANS_SERIF) + interactor.onFontChanged(ReaderViewFeature.Config.FontType.SANSSERIF) - verify(config).fontType = ReaderViewFeature.Config.FontType.SANS_SERIF + verify(config).fontType = ReaderViewFeature.Config.FontType.SANSSERIF interactor.onColorSchemeChanged(ReaderViewFeature.Config.ColorScheme.SEPIA) diff --git a/components/feature/readerview/src/test/java/mozilla/components/feature/readerview/view/ReaderViewControlsBarTest.kt b/components/feature/readerview/src/test/java/mozilla/components/feature/readerview/view/ReaderViewControlsBarTest.kt index 1b57f82a30f..f9632a5f70c 100644 --- a/components/feature/readerview/src/test/java/mozilla/components/feature/readerview/view/ReaderViewControlsBarTest.kt +++ b/components/feature/readerview/src/test/java/mozilla/components/feature/readerview/view/ReaderViewControlsBarTest.kt @@ -52,7 +52,7 @@ class ReaderViewControlsBarTest { assertFalse(sansSerifButton.isChecked) - bar.setFont(ReaderViewFeature.Config.FontType.SANS_SERIF) + bar.setFont(ReaderViewFeature.Config.FontType.SANSSERIF) assertTrue(sansSerifButton.isChecked) } @@ -161,7 +161,7 @@ class ReaderViewControlsBarTest { bar.findViewById(R.id.mozac_feature_readerview_font_sans_serif).performClick() - verify(listener).onFontChanged(ReaderViewFeature.Config.FontType.SANS_SERIF) + verify(listener).onFontChanged(ReaderViewFeature.Config.FontType.SANSSERIF) } @Test diff --git a/components/ui/icons/src/main/res/drawable/mozac_ic_font.xml b/components/ui/icons/src/main/res/drawable/mozac_ic_font.xml new file mode 100644 index 00000000000..2dca48b1b9b --- /dev/null +++ b/components/ui/icons/src/main/res/drawable/mozac_ic_font.xml @@ -0,0 +1,11 @@ + + + diff --git a/components/ui/icons/src/main/res/drawable/mozac_ic_reader_mode.xml b/components/ui/icons/src/main/res/drawable/mozac_ic_reader_mode.xml new file mode 100644 index 00000000000..0eb07a07ab7 --- /dev/null +++ b/components/ui/icons/src/main/res/drawable/mozac_ic_reader_mode.xml @@ -0,0 +1,12 @@ + + + + diff --git a/samples/browser/src/main/java/org/mozilla/samples/browser/BrowserFragment.kt b/samples/browser/src/main/java/org/mozilla/samples/browser/BrowserFragment.kt index 0c603902b55..99b19ef3e20 100644 --- a/samples/browser/src/main/java/org/mozilla/samples/browser/BrowserFragment.kt +++ b/samples/browser/src/main/java/org/mozilla/samples/browser/BrowserFragment.kt @@ -157,7 +157,9 @@ class BrowserFragment : Fragment(), BackHandler { requireContext(), components.engine, components.sessionManager, - layout.readerViewBar + layout.toolbar, + layout.readerViewBar, + layout.readerViewAppearanceButton ), owner = this, view = layout @@ -190,11 +192,11 @@ class BrowserFragment : Fragment(), BackHandler { override fun onBackPressed(): Boolean { return when { + readerViewFeature.onBackPressed() -> true findInPageIntegration.onBackPressed() -> true toolbarFeature.onBackPressed() -> true sessionFeature.onBackPressed() -> true customTabsToolbarFeature.onBackPressed() -> true - readerViewFeature.onBackPressed() -> true else -> false } } diff --git a/samples/browser/src/main/java/org/mozilla/samples/browser/DefaultComponents.kt b/samples/browser/src/main/java/org/mozilla/samples/browser/DefaultComponents.kt index 6f42552191e..6a57072b54a 100644 --- a/samples/browser/src/main/java/org/mozilla/samples/browser/DefaultComponents.kt +++ b/samples/browser/src/main/java/org/mozilla/samples/browser/DefaultComponents.kt @@ -32,7 +32,6 @@ import mozilla.components.feature.session.HistoryDelegate import mozilla.components.feature.tabs.TabsUseCases import mozilla.components.lib.fetch.httpurlconnection.HttpURLConnectionClient import org.mozilla.samples.browser.integration.FindInPageIntegration -import org.mozilla.samples.browser.integration.ReaderViewIntegration import org.mozilla.samples.browser.request.SampleRequestInterceptor import java.util.concurrent.TimeUnit @@ -116,9 +115,6 @@ open class DefaultComponents(private val applicationContext: Context) { SimpleBrowserMenuItem("Find In Page") { FindInPageIntegration.launch?.invoke() }, - SimpleBrowserMenuItem("Reader Mode Controls") { - ReaderViewIntegration.launch?.invoke() - }, BrowserMenuDivider(), SimpleBrowserMenuItem("Clear Data") { sessionUseCases.clearData.invoke() diff --git a/samples/browser/src/main/java/org/mozilla/samples/browser/integration/ReaderViewIntegration.kt b/samples/browser/src/main/java/org/mozilla/samples/browser/integration/ReaderViewIntegration.kt index f766edef850..9b022cc2a85 100644 --- a/samples/browser/src/main/java/org/mozilla/samples/browser/integration/ReaderViewIntegration.kt +++ b/samples/browser/src/main/java/org/mozilla/samples/browser/integration/ReaderViewIntegration.kt @@ -7,26 +7,69 @@ package org.mozilla.samples.browser.integration import android.content.Context +import android.support.design.widget.FloatingActionButton +import android.support.v4.content.ContextCompat import mozilla.components.browser.session.SessionManager +import mozilla.components.browser.toolbar.BrowserToolbar import mozilla.components.concept.engine.Engine import mozilla.components.feature.readerview.ReaderViewFeature import mozilla.components.feature.readerview.view.ReaderViewControlsView import mozilla.components.support.base.feature.BackHandler import mozilla.components.support.base.feature.LifecycleAwareFeature +import org.mozilla.samples.browser.R class ReaderViewIntegration( context: Context, engine: Engine, sessionManager: SessionManager, - private val view: ReaderViewControlsView + toolbar: BrowserToolbar, + view: ReaderViewControlsView, + readerViewAppearanceButton: FloatingActionButton ) : LifecycleAwareFeature, BackHandler { - private val feature = ReaderViewFeature(context, engine, sessionManager, view) + private var readerViewButtonVisible = false + + private val readerViewButton: BrowserToolbar.ToggleButton = BrowserToolbar.ToggleButton( + image = context.getDrawable(R.drawable.mozac_ic_reader_mode)!!, + imageSelected = context.getDrawable(R.drawable.mozac_ic_reader_mode)!!.mutate().apply { + setTint(ContextCompat.getColor(context, R.color.photonBlue40)) + }, + contentDescription = context.getString(R.string.mozac_reader_view_description), + contentDescriptionSelected = context.getString(R.string.mozac_reader_view_description_selected), + selected = sessionManager.selectedSession?.readerMode ?: false, + visible = { readerViewButtonVisible } + ) { enabled -> + if (enabled) { + feature.showReaderView() + readerViewAppearanceButton.show() + } else { + feature.hideReaderView() + readerViewAppearanceButton.hide() + } + } + + init { + toolbar.addPageAction(readerViewButton) + readerViewAppearanceButton.setOnClickListener { feature.showControls() } + } + + private val feature = ReaderViewFeature(context, engine, sessionManager, view) { available -> + readerViewButtonVisible = available + + // We've got an update on reader view availability e.g. because the page + // was refreshed or a new session selected. Let's make sure to also update + // the selected state of the reader mode button and the show the appearance + // control button if needed. + val readerModeActive = sessionManager.selectedSession?.readerMode ?: false + readerViewButton.setSelected(readerModeActive) + + if (readerModeActive) readerViewAppearanceButton.show() else readerViewAppearanceButton.hide() + + toolbar.invalidateActions() + } override fun start() { feature.start() - - ReaderViewIntegration.launch = this::launch } override fun stop() { @@ -34,15 +77,7 @@ class ReaderViewIntegration( } override fun onBackPressed(): Boolean { + readerViewButton.setSelected(false) return feature.onBackPressed() } - - private fun launch() { - view.showControls() - } - - companion object { - var launch: (() -> Unit)? = null - private set - } } diff --git a/samples/browser/src/main/res/layout/fragment_browser.xml b/samples/browser/src/main/res/layout/fragment_browser.xml index b26a54619d9..a87daac79e3 100644 --- a/samples/browser/src/main/res/layout/fragment_browser.xml +++ b/samples/browser/src/main/res/layout/fragment_browser.xml @@ -57,7 +57,19 @@ android:visibility="gone" android:layout_gravity="bottom" android:layout_width="match_parent" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + android:paddingBottom="55dp" /> + + diff --git a/samples/browser/src/main/res/values/strings.xml b/samples/browser/src/main/res/values/strings.xml index 86cfc709922..f4d4ca4c51c 100644 --- a/samples/browser/src/main/res/values/strings.xml +++ b/samples/browser/src/main/res/values/strings.xml @@ -6,4 +6,6 @@ Sample Browser Add New Tab + Enable Reader View + Disable Reader View