Set Webview as an activity

This way it will not reload on orientation change or theme switching
Webview toolbar now also has history buttons in toolbar, pressing back now reverses in history
Webview title is also now the websites title
This commit is contained in:
Jay 2019-11-17 18:46:12 -08:00
parent 75324a3614
commit 65804ebb3a
29 changed files with 328 additions and 95 deletions

View File

@ -124,7 +124,7 @@ dependencies {
implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.multidex:multidex:2.0.1'
standardImplementation 'com.google.firebase:firebase-core:11.8.0' standardImplementation 'com.google.firebase:firebase-core:17.2.1'
// ReactiveX // ReactiveX
implementation 'io.reactivex:rxandroid:1.2.1' implementation 'io.reactivex:rxandroid:1.2.1'

View File

@ -47,6 +47,9 @@
</activity> </activity>
<activity <activity
android:name=".ui.reader.ReaderActivity" /> android:name=".ui.reader.ReaderActivity" />
<activity
android:name=".ui.manga.info.WebViewActivity"
android:configChanges="uiMode|orientation|screenSize"/>
<activity <activity
android:name=".widget.CustomLayoutPickerActivity" android:name=".widget.CustomLayoutPickerActivity"
android:label="@string/app_name" android:label="@string/app_name"

View File

@ -2,14 +2,18 @@ package eu.kanade.tachiyomi.ui.catalogue.browse
import android.content.res.Configuration import android.content.res.Configuration
import android.os.Bundle import android.os.Bundle
import com.google.android.material.snackbar.Snackbar import android.view.LayoutInflater
import androidx.drawerlayout.widget.DrawerLayout import android.view.Menu
import androidx.appcompat.widget.* import android.view.MenuInflater
import android.view.* import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView
import androidx.core.view.GravityCompat import androidx.core.view.GravityCompat
import com.afollestad.materialdialogs.MaterialDialog import androidx.drawerlayout.widget.DrawerLayout
import com.f2prateek.rx.preferences.Preference import com.f2prateek.rx.preferences.Preference
import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar
import com.jakewharton.rxbinding.support.v7.widget.queryTextChangeEvents import com.jakewharton.rxbinding.support.v7.widget.queryTextChangeEvents
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.flexibleadapter.items.IFlexible
@ -27,11 +31,20 @@ import eu.kanade.tachiyomi.ui.library.ChangeMangaCategoriesDialog
import eu.kanade.tachiyomi.ui.library.HeightTopWindowInsetsListener import eu.kanade.tachiyomi.ui.library.HeightTopWindowInsetsListener
import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.manga.info.MangaWebViewController import eu.kanade.tachiyomi.ui.manga.info.WebViewActivity
import eu.kanade.tachiyomi.util.* import eu.kanade.tachiyomi.util.RecyclerWindowInsetsListener
import eu.kanade.tachiyomi.util.connectivityManager
import eu.kanade.tachiyomi.util.doOnApplyWindowInsets
import eu.kanade.tachiyomi.util.gone
import eu.kanade.tachiyomi.util.inflate
import eu.kanade.tachiyomi.util.marginTop
import eu.kanade.tachiyomi.util.openInBrowser
import eu.kanade.tachiyomi.util.snack
import eu.kanade.tachiyomi.util.updateLayoutParams
import eu.kanade.tachiyomi.util.updatePaddingRelative
import eu.kanade.tachiyomi.util.visible
import eu.kanade.tachiyomi.widget.AutofitRecyclerView import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import kotlinx.android.synthetic.main.catalogue_controller.* import kotlinx.android.synthetic.main.catalogue_controller.*
import kotlinx.android.synthetic.main.categories_item.view.*
import kotlinx.android.synthetic.main.main_activity.* import kotlinx.android.synthetic.main.main_activity.*
import rx.Observable import rx.Observable
import rx.Subscription import rx.Subscription
@ -310,9 +323,10 @@ open class BrowseCatalogueController(bundle: Bundle) :
private fun openInWebView() { private fun openInWebView() {
val source = presenter.source as? HttpSource ?: return val source = presenter.source as? HttpSource ?: return
val activity = activity ?: return
router.pushController(MangaWebViewController(source.id, source.baseUrl) val intent = WebViewActivity.newIntent(activity, source.id, source.baseUrl, presenter
.withFadeTransaction()) .source.name)
startActivity(intent)
} }
/** /**

View File

@ -178,12 +178,12 @@ class MainActivity : BaseActivity() {
// if in landscape with 2/3 button mode, fully opaque nav bar // if in landscape with 2/3 button mode, fully opaque nav bar
else if (v.rootWindowInsets.systemWindowInsetLeft > 0 else if (v.rootWindowInsets.systemWindowInsetLeft > 0
|| v.rootWindowInsets.systemWindowInsetRight > 0) { || v.rootWindowInsets.systemWindowInsetRight > 0) {
v.context.getResourceColor(android.R.attr.colorBackground) getResourceColor(android.R.attr.colorBackground)
} }
// if in portrait with 2/3 button mode, translucent nav bar // if in portrait with 2/3 button mode, translucent nav bar
else { else {
ColorUtils.setAlphaComponent( ColorUtils.setAlphaComponent(
v.context.getResourceColor(android.R.attr.colorBackground), 179) getResourceColor(android.R.attr.colorBackground), 179)
} }
v.setPadding(insets.systemWindowInsetLeft, insets.systemWindowInsetTop, v.setPadding(insets.systemWindowInsetLeft, insets.systemWindowInsetTop,
insets.systemWindowInsetRight, 0) insets.systemWindowInsetRight, 0)

View File

@ -335,8 +335,9 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
return return
} }
parentController?.router?.pushController(MangaWebViewController(source.id, url) val activity = activity ?: return
.withFadeTransaction()) val intent = WebViewActivity.newIntent(activity, source.id, url, presenter.manga.title)
startActivity(intent)
} }
/** /**

View File

@ -1,72 +0,0 @@
package eu.kanade.tachiyomi.ui.manga.info
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.webkit.WebView
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.util.RecyclerWindowInsetsListener
import eu.kanade.tachiyomi.util.WebViewClientCompat
import eu.kanade.tachiyomi.util.doOnApplyWindowInsets
import eu.kanade.tachiyomi.util.marginBottom
import eu.kanade.tachiyomi.util.updateLayoutParams
import uy.kohesive.injekt.injectLazy
class MangaWebViewController(bundle: Bundle? = null) : BaseController(bundle) {
private val sourceManager by injectLazy<SourceManager>()
constructor(sourceId: Long, url: String) : this(Bundle().apply {
putLong(SOURCE_KEY, sourceId)
putString(URL_KEY, url)
})
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return WebView(applicationContext)// inflater.inflate(R.layout.manga_info_web_controller, container,
// false)
}
override fun onViewCreated(view: View) {
super.onViewCreated(view)
val source = sourceManager.get(args.getLong(SOURCE_KEY)) as? HttpSource ?: return
val url = args.getString(URL_KEY) ?: return
val headers = source.headers.toMultimap().mapValues { it.value.getOrNull(0) ?: "" }
val web = view as WebView
web.webViewClient = object : WebViewClientCompat() {
override fun shouldOverrideUrlCompat(view: WebView, url: String): Boolean {
view.loadUrl(url)
return true
}
}
val marginB = view.marginBottom
view.doOnApplyWindowInsets{ v, insets, _ ->
val bottomInset = if (Build.VERSION.SDK_INT >= 29) insets.tappableElementInsets.bottom
else insets.systemWindowInsetBottom
v.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = marginB + bottomInset
}
}
web.settings.javaScriptEnabled = true
web.settings.userAgentString = source.headers["User-Agent"]
web.loadUrl(url, headers)
}
override fun onDestroyView(view: View) {
val web = view as WebView
web.stopLoading()
web.destroy()
super.onDestroyView(view)
}
private companion object {
const val SOURCE_KEY = "source_key"
const val URL_KEY = "url_key"
}
}

View File

@ -0,0 +1,216 @@
package eu.kanade.tachiyomi.ui.manga.info
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.webkit.WebView
import android.widget.LinearLayout
import androidx.core.graphics.ColorUtils
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
import eu.kanade.tachiyomi.util.WebViewClientCompat
import eu.kanade.tachiyomi.util.doOnApplyWindowInsets
import eu.kanade.tachiyomi.util.getResourceColor
import eu.kanade.tachiyomi.util.marginBottom
import eu.kanade.tachiyomi.util.updateLayoutParams
import eu.kanade.tachiyomi.util.updatePadding
import kotlinx.android.synthetic.main.webview_activity.*
import uy.kohesive.injekt.injectLazy
class WebViewActivity : BaseActivity() {
private val sourceManager by injectLazy<SourceManager>()
private var bundle:Bundle? = null
val preferences: PreferencesHelper by injectLazy()
companion object {
const val SOURCE_KEY = "source_key"
const val URL_KEY = "url_key"
const val TITLE_KEY = "title_key"
fun newIntent(context: Context, sourceId: Long, url: String, title:String?): Intent {
val intent = Intent(context, WebViewActivity::class.java)
intent.putExtra(SOURCE_KEY, sourceId)
intent.putExtra(URL_KEY, url)
intent.putExtra(TITLE_KEY, title)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
return intent
}
}
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(when (preferences.theme()) {
3, 6 -> R.style.Theme_Tachiyomi_Amoled
4, 7 -> R.style.Theme_Tachiyomi_DarkBlue
else -> R.style.Theme_Tachiyomi
})
super.onCreate(savedInstanceState)
setContentView(R.layout.webview_activity)
title = intent.extras?.getString(TITLE_KEY)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
toolbar.setNavigationOnClickListener {
super.onBackPressed()
}
val container:ViewGroup = findViewById(R.id.web_view_layout)
val content: LinearLayout = findViewById(R.id.web_linear_layout)
container.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
content.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
container.setOnApplyWindowInsetsListener { v, insets ->
val contextView = window?.decorView?.findViewById<View>(R.id.action_mode_bar)
contextView?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
leftMargin = insets.systemWindowInsetLeft
rightMargin = insets.systemWindowInsetRight
}
// Consume any horizontal insets and pad all content in. There's not much we can do
// with horizontal insets
v.updatePadding(
left = insets.systemWindowInsetLeft,
right = insets.systemWindowInsetRight
)
insets.replaceSystemWindowInsets(
0, insets.systemWindowInsetTop,
0, insets.systemWindowInsetBottom
)
}
window.statusBarColor = getResourceColor(R.attr.colorPrimary)
content.setOnApplyWindowInsetsListener { v, insets ->
window.navigationBarColor =
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
v.context.getResourceColor(android.R.attr.colorPrimary)
}
// if the android q+ device has gesture nav, transparent nav bar
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
&& (v.rootWindowInsets.systemWindowInsetBottom != v.rootWindowInsets
.tappableElementInsets.bottom)) {
getColor(android.R.color.transparent)
} else {
v.context.getResourceColor(android.R.attr.colorBackground)
}
v.setPadding(insets.systemWindowInsetLeft, insets.systemWindowInsetTop,
insets.systemWindowInsetRight, 0)
insets
}
val currentNightMode = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
if (Build.VERSION.SDK_INT >= 26 && currentNightMode == Configuration.UI_MODE_NIGHT_NO) {
content.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
}
if (bundle == null) {
val source = sourceManager.get(intent.extras!!.getLong(SOURCE_KEY)) as? HttpSource ?: return
val url = intent.extras!!.getString(URL_KEY) ?: return
val headers = source.headers.toMultimap().mapValues { it.value.getOrNull(0) ?: "" }
webview.webViewClient = object : WebViewClientCompat() {
override fun shouldOverrideUrlCompat(view: WebView, url: String): Boolean {
view.loadUrl(url)
return true
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
invalidateOptionsMenu()
title = view?.title
}
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
invalidateOptionsMenu()
}
}
val marginB = webview.marginBottom
webview.doOnApplyWindowInsets { v, insets, _ ->
val bottomInset =
if (Build.VERSION.SDK_INT >= 29) insets.tappableElementInsets.bottom
else insets.systemWindowInsetBottom
v.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = marginB + bottomInset
}
}
webview.settings.javaScriptEnabled = true
webview.settings.userAgentString = source.headers["User-Agent"]
webview.loadUrl(url, headers)
}
else {
webview.restoreState(bundle)
}
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
window.statusBarColor = getResourceColor(R.attr.colorPrimary)
toolbar.setBackgroundColor(getResourceColor(R.attr.colorPrimary))
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
window.navigationBarColor = getResourceColor(android.R.attr.colorPrimary)
else if (window.navigationBarColor != getColor(android.R.color.transparent))
window.navigationBarColor = getResourceColor(android.R.attr.colorBackground)
val currentNightMode = newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
if (Build.VERSION.SDK_INT >= 26) {
if (currentNightMode == Configuration.UI_MODE_NIGHT_NO) {
web_linear_layout.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
} else {
web_linear_layout.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
}
}
}
/**
* Called when the options menu of the toolbar is being created. It adds our custom menu.
*/
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.webview, menu)
return true
}
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
val backItem = toolbar.menu.findItem(R.id.action_web_back)
val forwardItem = toolbar.menu.findItem(R.id.action_web_forward)
backItem?.isEnabled = webview.canGoBack()
forwardItem?.isEnabled = webview.canGoForward()
val hasHistory = webview.canGoBack() || webview.canGoForward()
backItem?.isVisible = hasHistory
forwardItem?.isVisible = hasHistory
val translucentWhite = ColorUtils.setAlphaComponent(Color.WHITE, 127)
backItem.icon?.setTint(if (webview.canGoBack()) Color.WHITE else translucentWhite)
forwardItem?.icon?.setTint(if (webview.canGoForward()) Color.WHITE else translucentWhite)
return super.onPrepareOptionsMenu(menu)
}
override fun onBackPressed() {
if (webview.canGoBack()) webview.goBack()
else super.onBackPressed()
}
/**
* Called when an item of the options menu was clicked. Used to handle clicks on our menu
* entries.
*/
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_web_back -> webview.goBack()
R.id.action_web_forward -> webview.goForward()
else -> return super.onOptionsItemSelected(item)
}
return true
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<WebView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</WebView>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/web_view_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:orientation="vertical"
android:id="@+id/web_linear_layout"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="?attr/actionBarTheme"
app:navigationIcon="@drawable/baseline_close_white_24"/>
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</WebView>
</LinearLayout>
</FrameLayout>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_web_back"
android:icon="@drawable/baseline_arrow_back_white_24"
android:title="@string/action_webview_back"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_web_forward"
android:icon="@drawable/baseline_arrow_forward_white_24"
android:title="@string/action_webview_forward"
app:showAsAction="ifRoom"
/>
</menu>

View File

@ -98,6 +98,8 @@
<string name="action_restore">Restore</string> <string name="action_restore">Restore</string>
<string name="action_open">Open</string> <string name="action_open">Open</string>
<string name="action_login">Log in</string> <string name="action_login">Log in</string>
<string name="action_webview_back">Back</string>
<string name="action_webview_forward">Forward</string>
<!-- Operations --> <!-- Operations -->
<string name="deleting">Deleting…</string> <string name="deleting">Deleting…</string>