Introduce incognito open-in-browser support
This commit is contained in:
parent
d9d71c8745
commit
411dda0e75
1
app/.gitignore
vendored
1
app/.gitignore
vendored
@ -3,3 +3,4 @@
|
|||||||
*.iml
|
*.iml
|
||||||
custom.gradle
|
custom.gradle
|
||||||
google-services.json
|
google-services.json
|
||||||
|
output.json
|
@ -213,7 +213,7 @@ dependencies {
|
|||||||
|
|
||||||
// Conductor
|
// Conductor
|
||||||
implementation "com.github.inorichi.Conductor:conductor:be8b3c5"
|
implementation "com.github.inorichi.Conductor:conductor:be8b3c5"
|
||||||
implementation ("com.bluelinelabs:conductor-support:2.1.5-SNAPSHOT") {
|
implementation("com.bluelinelabs:conductor-support:2.1.5-SNAPSHOT") {
|
||||||
exclude group: "com.bluelinelabs", module: "conductor"
|
exclude group: "com.bluelinelabs", module: "conductor"
|
||||||
exclude group: "com.android.support"
|
exclude group: "com.android.support"
|
||||||
}
|
}
|
||||||
@ -246,7 +246,7 @@ dependencies {
|
|||||||
implementation 'com.andrognito.pinlockview:pinlockview:2.1.0'
|
implementation 'com.andrognito.pinlockview:pinlockview:2.1.0'
|
||||||
|
|
||||||
// Reprint (EH)
|
// Reprint (EH)
|
||||||
implementation 'com.github.ajalt.reprint:core:3.2.1@aar' // required: supports marshmallow devices
|
implementation 'com.github.ajalt.reprint:core:3.2.1@aar'
|
||||||
implementation 'com.github.ajalt.reprint:rxjava:3.2.1@aar' // optional: the RxJava 1 interface
|
implementation 'com.github.ajalt.reprint:rxjava:3.2.1@aar' // optional: the RxJava 1 interface
|
||||||
|
|
||||||
// Swirl (EH)
|
// Swirl (EH)
|
||||||
|
@ -12,31 +12,35 @@
|
|||||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||||
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
||||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||||
<uses-permission android:name="android.permission.GET_TASKS"/>
|
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||||
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
|
<uses-permission
|
||||||
|
android:name="android.permission.PACKAGE_USAGE_STATS"
|
||||||
tools:ignore="ProtectedPermissions" />
|
tools:ignore="ProtectedPermissions" />
|
||||||
<!-- Lock vibrate -->
|
<!-- Lock vibrate -->
|
||||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".App"
|
android:name=".App"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:largeHeap="true"
|
android:largeHeap="true"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:theme="@style/Theme.Tachiyomi">
|
android:theme="@style/Theme.Tachiyomi">
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.main.MainActivity"
|
android:name=".ui.main.MainActivity"
|
||||||
android:launchMode="singleTop">
|
android:launchMode="singleTop">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<!--suppress AndroidDomInspection -->
|
<!-- suppress AndroidDomInspection -->
|
||||||
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts"/>
|
<meta-data
|
||||||
|
android:name="android.app.shortcuts"
|
||||||
|
android:resource="@xml/shortcuts" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.reader.ReaderActivity"
|
android:name=".ui.reader.ReaderActivity"
|
||||||
@ -61,7 +65,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".extension.util.ExtensionInstallActivity"
|
android:name=".extension.util.ExtensionInstallActivity"
|
||||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
|
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="android.support.v4.content.FileProvider"
|
android:name="android.support.v4.content.FileProvider"
|
||||||
@ -72,14 +76,12 @@
|
|||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
android:resource="@xml/provider_paths" />
|
android:resource="@xml/provider_paths" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="eu.kanade.tachiyomi.util.ZipContentProvider"
|
android:name=".util.ZipContentProvider"
|
||||||
android:authorities="${applicationId}.zip-provider"
|
android:authorities="${applicationId}.zip-provider"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="eu.kanade.tachiyomi.util.RarContentProvider"
|
android:name=".util.RarContentProvider"
|
||||||
android:authorities="${applicationId}.rar-provider"
|
android:authorities="${applicationId}.rar-provider"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
@ -90,22 +92,18 @@
|
|||||||
<service
|
<service
|
||||||
android:name=".data.library.LibraryUpdateService"
|
android:name=".data.library.LibraryUpdateService"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".data.download.DownloadService"
|
android:name=".data.download.DownloadService"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".data.updater.UpdaterService"
|
android:name=".data.updater.UpdaterService"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".data.backup.BackupCreateService"
|
android:name=".data.backup.BackupCreateService"
|
||||||
android:exported="false"/>
|
android:exported="false" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".data.backup.BackupRestoreService"
|
android:name=".data.backup.BackupRestoreService"
|
||||||
android:exported="false"/>
|
android:exported="false" />
|
||||||
|
|
||||||
<!-- EH -->
|
<!-- EH -->
|
||||||
<activity
|
<activity
|
||||||
@ -113,97 +111,97 @@
|
|||||||
android:label="TachiyomiEH"
|
android:label="TachiyomiEH"
|
||||||
android:theme="@style/Theme.EHIntercept">
|
android:theme="@style/Theme.EHIntercept">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
<data
|
<data
|
||||||
android:host="g.e-hentai.org"
|
android:host="g.e-hentai.org"
|
||||||
android:pathPrefix="/g/"
|
android:pathPrefix="/g/"
|
||||||
android:scheme="http"/>
|
android:scheme="http" />
|
||||||
<data
|
<data
|
||||||
android:host="g.e-hentai.org"
|
android:host="g.e-hentai.org"
|
||||||
android:pathPrefix="/g/"
|
android:pathPrefix="/g/"
|
||||||
android:scheme="https"/>
|
android:scheme="https" />
|
||||||
<data
|
<data
|
||||||
android:host="e-hentai.org"
|
android:host="e-hentai.org"
|
||||||
android:pathPrefix="/g/"
|
android:pathPrefix="/g/"
|
||||||
android:scheme="http"/>
|
android:scheme="http" />
|
||||||
<data
|
<data
|
||||||
android:host="e-hentai.org"
|
android:host="e-hentai.org"
|
||||||
android:pathPrefix="/g/"
|
android:pathPrefix="/g/"
|
||||||
android:scheme="https"/>
|
android:scheme="https" />
|
||||||
<data
|
<data
|
||||||
android:host="exhentai.org"
|
android:host="exhentai.org"
|
||||||
android:pathPrefix="/g/"
|
android:pathPrefix="/g/"
|
||||||
android:scheme="http"/>
|
android:scheme="http" />
|
||||||
<data
|
<data
|
||||||
android:host="exhentai.org"
|
android:host="exhentai.org"
|
||||||
android:pathPrefix="/g/"
|
android:pathPrefix="/g/"
|
||||||
android:scheme="https"/>
|
android:scheme="https" />
|
||||||
<data
|
<data
|
||||||
android:host="nhentai.net"
|
android:host="nhentai.net"
|
||||||
android:pathPrefix="/g/"
|
android:pathPrefix="/g/"
|
||||||
android:scheme="http"/>
|
android:scheme="http" />
|
||||||
<data
|
<data
|
||||||
android:host="nhentai.net"
|
android:host="nhentai.net"
|
||||||
android:pathPrefix="/g/"
|
android:pathPrefix="/g/"
|
||||||
android:scheme="https"/>
|
android:scheme="https" />
|
||||||
<data
|
<data
|
||||||
android:host="www.perveden.com"
|
android:host="www.perveden.com"
|
||||||
android:pathPattern="/.*/.*-manga/.*"
|
android:pathPattern="/.*/.*-manga/.*"
|
||||||
android:scheme="http"/>
|
android:scheme="http" />
|
||||||
<data
|
<data
|
||||||
android:host="www.perveden.com"
|
android:host="www.perveden.com"
|
||||||
android:pathPattern="/.*/.*-manga/.*"
|
android:pathPattern="/.*/.*-manga/.*"
|
||||||
android:scheme="https"/>
|
android:scheme="https" />
|
||||||
<data
|
<data
|
||||||
android:host="hentai.cafe"
|
android:host="hentai.cafe"
|
||||||
android:pathPattern="/.*/.*"
|
android:pathPattern="/.*/.*"
|
||||||
android:scheme="http"/>
|
android:scheme="http" />
|
||||||
<data
|
<data
|
||||||
android:host="hentai.cafe"
|
android:host="hentai.cafe"
|
||||||
android:pathPattern="/.*/.*"
|
android:pathPattern="/.*/.*"
|
||||||
android:scheme="https"/>
|
android:scheme="https" />
|
||||||
<data
|
<data
|
||||||
android:host="www.tsumino.com"
|
android:host="www.tsumino.com"
|
||||||
android:pathPrefix="/Book/Info/"
|
android:pathPrefix="/Book/Info/"
|
||||||
android:scheme="http"/>
|
android:scheme="http" />
|
||||||
<data
|
<data
|
||||||
android:host="www.tsumino.com"
|
android:host="www.tsumino.com"
|
||||||
android:pathPrefix="/Book/Info/"
|
android:pathPrefix="/Book/Info/"
|
||||||
android:scheme="https"/>
|
android:scheme="https" />
|
||||||
<data
|
<data
|
||||||
android:host="www.tsumino.com"
|
android:host="www.tsumino.com"
|
||||||
android:pathPrefix="/Read/View/"
|
android:pathPrefix="/Read/View/"
|
||||||
android:scheme="http"/>
|
android:scheme="http" />
|
||||||
<data
|
<data
|
||||||
android:host="www.tsumino.com"
|
android:host="www.tsumino.com"
|
||||||
android:pathPrefix="/Read/View/"
|
android:pathPrefix="/Read/View/"
|
||||||
android:scheme="https"/>
|
android:scheme="https" />
|
||||||
<data
|
<data
|
||||||
android:host="hitomi.la"
|
android:host="hitomi.la"
|
||||||
android:pathPrefix="/galleries/"
|
android:pathPrefix="/galleries/"
|
||||||
android:scheme="http"/>
|
android:scheme="http" />
|
||||||
<data
|
<data
|
||||||
android:host="hitomi.la"
|
android:host="hitomi.la"
|
||||||
android:pathPrefix="/reader/"
|
android:pathPrefix="/reader/"
|
||||||
android:scheme="http"/>
|
android:scheme="http" />
|
||||||
<data
|
<data
|
||||||
android:host="hitomi.la"
|
android:host="hitomi.la"
|
||||||
android:pathPrefix="/galleries/"
|
android:pathPrefix="/galleries/"
|
||||||
android:scheme="https"/>
|
android:scheme="https" />
|
||||||
<data
|
<data
|
||||||
android:host="hitomi.la"
|
android:host="hitomi.la"
|
||||||
android:pathPrefix="/reader/"
|
android:pathPrefix="/reader/"
|
||||||
android:scheme="https"/>
|
android:scheme="https" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name="exh.ui.captcha.SolveCaptchaActivity"
|
android:name="exh.ui.captcha.SolveCaptchaActivity"
|
||||||
android:launchMode="singleInstance" />
|
android:launchMode="singleInstance" />
|
||||||
|
<activity android:name="exh.ui.webview.WebViewActivity"></activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
@ -178,4 +178,6 @@ object PreferenceKeys {
|
|||||||
const val eh_cacheSize = "eh_cache_size"
|
const val eh_cacheSize = "eh_cache_size"
|
||||||
|
|
||||||
const val eh_preserveReadingPosition = "eh_preserve_reading_position"
|
const val eh_preserveReadingPosition = "eh_preserve_reading_position"
|
||||||
|
|
||||||
|
const val eh_incogWebview = "eh_incognito_webview"
|
||||||
}
|
}
|
||||||
|
@ -249,4 +249,6 @@ class PreferencesHelper(val context: Context) {
|
|||||||
fun eh_cacheSize() = rxPrefs.getString(Keys.eh_cacheSize, "75")
|
fun eh_cacheSize() = rxPrefs.getString(Keys.eh_cacheSize, "75")
|
||||||
|
|
||||||
fun eh_preserveReadingPosition() = rxPrefs.getBoolean(Keys.eh_preserveReadingPosition, false)
|
fun eh_preserveReadingPosition() = rxPrefs.getBoolean(Keys.eh_preserveReadingPosition, false)
|
||||||
|
|
||||||
|
fun eh_incogWebview() = rxPrefs.getBoolean(Keys.eh_incogWebview, false)
|
||||||
}
|
}
|
||||||
|
@ -20,19 +20,18 @@ import android.widget.Toast
|
|||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||||
import com.bumptech.glide.load.resource.bitmap.TransformationUtils.centerCrop
|
|
||||||
import com.bumptech.glide.request.target.SimpleTarget
|
import com.bumptech.glide.request.target.SimpleTarget
|
||||||
import com.bumptech.glide.request.transition.Transition
|
import com.bumptech.glide.request.transition.Transition
|
||||||
import com.jakewharton.rxbinding.support.v4.widget.refreshes
|
import com.jakewharton.rxbinding.support.v4.widget.refreshes
|
||||||
import com.jakewharton.rxbinding.view.clicks
|
import com.jakewharton.rxbinding.view.clicks
|
||||||
import com.jakewharton.rxbinding.view.longClicks
|
import com.jakewharton.rxbinding.view.longClicks
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.R.id.*
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Category
|
import eu.kanade.tachiyomi.data.database.models.Category
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
@ -50,6 +49,7 @@ import eu.kanade.tachiyomi.util.toast
|
|||||||
import eu.kanade.tachiyomi.util.truncateCenter
|
import eu.kanade.tachiyomi.util.truncateCenter
|
||||||
import exh.EH_SOURCE_ID
|
import exh.EH_SOURCE_ID
|
||||||
import exh.EXH_SOURCE_ID
|
import exh.EXH_SOURCE_ID
|
||||||
|
import exh.ui.webview.WebViewActivity
|
||||||
import jp.wasabeef.glide.transformations.CropSquareTransformation
|
import jp.wasabeef.glide.transformations.CropSquareTransformation
|
||||||
import jp.wasabeef.glide.transformations.MaskTransformation
|
import jp.wasabeef.glide.transformations.MaskTransformation
|
||||||
import kotlinx.android.synthetic.main.manga_info_controller.*
|
import kotlinx.android.synthetic.main.manga_info_controller.*
|
||||||
@ -310,11 +310,20 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
|||||||
val source = presenter.source as? HttpSource ?: return
|
val source = presenter.source as? HttpSource ?: return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val url = Uri.parse(source.mangaDetailsRequest(presenter.manga).url().toString())
|
// --> EH
|
||||||
val intent = CustomTabsIntent.Builder()
|
val urlString = source.mangaDetailsRequest(presenter.manga).url().toString()
|
||||||
.setToolbarColor(context.getResourceColor(R.attr.colorPrimary))
|
if(preferences.eh_incogWebview().getOrDefault()) {
|
||||||
.build()
|
activity?.startActivity(Intent(activity, WebViewActivity::class.java).apply {
|
||||||
intent.launchUrl(activity, url)
|
putExtra(WebViewActivity.KEY_URL, urlString)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
val url = Uri.parse(urlString)
|
||||||
|
val intent = CustomTabsIntent.Builder()
|
||||||
|
.setToolbarColor(context.getResourceColor(R.attr.colorPrimary))
|
||||||
|
.build()
|
||||||
|
intent.launchUrl(activity, url)
|
||||||
|
}
|
||||||
|
// <-- EH
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
context.toast(e.message)
|
context.toast(e.message)
|
||||||
}
|
}
|
||||||
|
@ -186,6 +186,13 @@ class SettingsGeneralController : SettingsController() {
|
|||||||
defaultValue = false
|
defaultValue = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switchPreference {
|
||||||
|
key = Keys.eh_incogWebview
|
||||||
|
title = "Incognito 'Open in browser'"
|
||||||
|
summary = "Prevent pages viewed from the 'Open in browser' menu option from being placed into Chrome's browsing history. Some browser features will be unavailable."
|
||||||
|
defaultValue = false
|
||||||
|
}
|
||||||
|
|
||||||
preferenceCategory {
|
preferenceCategory {
|
||||||
title = "Application lock"
|
title = "Application lock"
|
||||||
|
|
||||||
|
@ -3,11 +3,8 @@ package eu.kanade.tachiyomi.util
|
|||||||
import android.app.ActivityManager
|
import android.app.ActivityManager
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.BroadcastReceiver
|
import android.content.*
|
||||||
import android.content.Context
|
|
||||||
import android.content.Context.VIBRATOR_SERVICE
|
import android.content.Context.VIBRATOR_SERVICE
|
||||||
import android.content.Intent
|
|
||||||
import android.content.IntentFilter
|
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
@ -129,6 +126,14 @@ val Context.powerManager: PowerManager
|
|||||||
val Context.wifiManager: WifiManager
|
val Context.wifiManager: WifiManager
|
||||||
get() = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
get() = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||||
|
|
||||||
|
// --> EH
|
||||||
|
/**
|
||||||
|
* Property to get the wifi manager from the context.
|
||||||
|
*/
|
||||||
|
val Context.clipboardManager: ClipboardManager
|
||||||
|
get() = applicationContext.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
// <-- EH
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function used to send a local broadcast asynchronous
|
* Function used to send a local broadcast asynchronous
|
||||||
*
|
*
|
||||||
|
126
app/src/main/java/exh/ui/webview/NestedWebView.java
Normal file
126
app/src/main/java/exh/ui/webview/NestedWebView.java
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
package exh.ui.webview;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.v4.view.MotionEventCompat;
|
||||||
|
import android.support.v4.view.NestedScrollingChild;
|
||||||
|
import android.support.v4.view.NestedScrollingChildHelper;
|
||||||
|
import android.support.v4.view.ViewCompat;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
|
||||||
|
public class NestedWebView extends WebView implements NestedScrollingChild {
|
||||||
|
private int mLastY;
|
||||||
|
private final int[] mScrollOffset = new int[2];
|
||||||
|
private final int[] mScrollConsumed = new int[2];
|
||||||
|
private int mNestedOffsetY;
|
||||||
|
private NestedScrollingChildHelper mChildHelper;
|
||||||
|
|
||||||
|
public NestedWebView(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NestedWebView(Context context, AttributeSet attrs) {
|
||||||
|
this(context, attrs, android.R.attr.webViewStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NestedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
mChildHelper = new NestedScrollingChildHelper(this);
|
||||||
|
setNestedScrollingEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent ev) {
|
||||||
|
boolean returnValue = false;
|
||||||
|
|
||||||
|
MotionEvent event = MotionEvent.obtain(ev);
|
||||||
|
final int action = MotionEventCompat.getActionMasked(event);
|
||||||
|
if (action == MotionEvent.ACTION_DOWN) {
|
||||||
|
mNestedOffsetY = 0;
|
||||||
|
}
|
||||||
|
int eventY = (int) event.getY();
|
||||||
|
event.offsetLocation(0, mNestedOffsetY);
|
||||||
|
switch (action) {
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
int deltaY = mLastY - eventY;
|
||||||
|
// NestedPreScroll
|
||||||
|
if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
|
||||||
|
deltaY -= mScrollConsumed[1];
|
||||||
|
mLastY = eventY - mScrollOffset[1];
|
||||||
|
event.offsetLocation(0, -mScrollOffset[1]);
|
||||||
|
mNestedOffsetY += mScrollOffset[1];
|
||||||
|
}
|
||||||
|
returnValue = super.onTouchEvent(event);
|
||||||
|
|
||||||
|
// NestedScroll
|
||||||
|
if (dispatchNestedScroll(0, mScrollOffset[1], 0, deltaY, mScrollOffset)) {
|
||||||
|
event.offsetLocation(0, mScrollOffset[1]);
|
||||||
|
mNestedOffsetY += mScrollOffset[1];
|
||||||
|
mLastY -= mScrollOffset[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
returnValue = super.onTouchEvent(event);
|
||||||
|
mLastY = eventY;
|
||||||
|
// start NestedScroll
|
||||||
|
startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
case MotionEvent.ACTION_CANCEL:
|
||||||
|
returnValue = super.onTouchEvent(event);
|
||||||
|
// end NestedScroll
|
||||||
|
stopNestedScroll();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nested Scroll implements
|
||||||
|
@Override
|
||||||
|
public void setNestedScrollingEnabled(boolean enabled) {
|
||||||
|
mChildHelper.setNestedScrollingEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNestedScrollingEnabled() {
|
||||||
|
return mChildHelper.isNestedScrollingEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean startNestedScroll(int axes) {
|
||||||
|
return mChildHelper.startNestedScroll(axes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopNestedScroll() {
|
||||||
|
mChildHelper.stopNestedScroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNestedScrollingParent() {
|
||||||
|
return mChildHelper.hasNestedScrollingParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed,
|
||||||
|
int[] offsetInWindow) {
|
||||||
|
return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
|
||||||
|
return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
|
||||||
|
return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
|
||||||
|
return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
191
app/src/main/java/exh/ui/webview/WebViewActivity.kt
Normal file
191
app/src/main/java/exh/ui/webview/WebViewActivity.kt
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
package exh.ui.webview
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.webkit.CookieManager
|
||||||
|
import android.webkit.WebView
|
||||||
|
import android.webkit.WebViewClient
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
|
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
||||||
|
import eu.kanade.tachiyomi.util.clipboardManager
|
||||||
|
import eu.kanade.tachiyomi.util.toast
|
||||||
|
import exh.ui.login.LoginController
|
||||||
|
import kotlinx.android.synthetic.main.activity_webview.*
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
|
class WebViewActivity : BaseActivity() {
|
||||||
|
private val prefs: PreferencesHelper by injectLazy()
|
||||||
|
private var mobileUserAgent: String? = null
|
||||||
|
private var isDesktop: Boolean = false
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
setTheme(when (prefs.theme()) {
|
||||||
|
2 -> R.style.Theme_Tachiyomi_Dark
|
||||||
|
3 -> R.style.Theme_Tachiyomi_Amoled
|
||||||
|
else -> R.style.Theme_Tachiyomi
|
||||||
|
})
|
||||||
|
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_webview)
|
||||||
|
setSupportActionBar(toolbar)
|
||||||
|
|
||||||
|
// Opaque status bar
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
val typedValue = TypedValue()
|
||||||
|
theme.resolveAttribute(R.attr.colorPrimaryDark, typedValue, true)
|
||||||
|
window.statusBarColor = typedValue.data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show close button
|
||||||
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_close_white_24dp)
|
||||||
|
|
||||||
|
val url = intent.getStringExtra(KEY_URL)
|
||||||
|
|
||||||
|
// Set immediately (required for correct title after rotation)
|
||||||
|
title = url
|
||||||
|
// Configure webview
|
||||||
|
webview.settings.javaScriptEnabled = true
|
||||||
|
webview.settings.domStorageEnabled = true
|
||||||
|
webview.settings.databaseEnabled = true
|
||||||
|
webview.webViewClient = object : WebViewClient() {
|
||||||
|
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
|
||||||
|
super.onPageStarted(view, url, favicon)
|
||||||
|
invalidateOptionsMenu()
|
||||||
|
appbar.setExpanded(true, true)
|
||||||
|
title = "Loading: $url"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPageFinished(view: WebView?, url: String?) {
|
||||||
|
super.onPageFinished(view, url)
|
||||||
|
title = url
|
||||||
|
invalidateOptionsMenu()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure E-Hentai/ExHentai cookies
|
||||||
|
for(domain in listOf(
|
||||||
|
"www.exhentai.org",
|
||||||
|
"exhentai.org",
|
||||||
|
"www.e-hentai.org",
|
||||||
|
"e-hentai.org",
|
||||||
|
"g.e-hentai.org"
|
||||||
|
)) {
|
||||||
|
for(cookie in listOf(
|
||||||
|
LoginController.MEMBER_ID_COOKIE to prefs.memberIdVal().getOrDefault(),
|
||||||
|
LoginController.PASS_HASH_COOKIE to prefs.passHashVal().getOrDefault(),
|
||||||
|
LoginController.IGNEOUS_COOKIE to prefs.igneousVal().getOrDefault()
|
||||||
|
)) {
|
||||||
|
val cookieString = "${cookie.first}=${cookie.second}; domain=$domain; path=/;"
|
||||||
|
CookieManager.getInstance().setCookie(domain, cookieString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Long-click to copy URL
|
||||||
|
toolbar.setOnLongClickListener {
|
||||||
|
toast("URL copied.")
|
||||||
|
clipboardManager.primaryClip = ClipData.newUri(
|
||||||
|
contentResolver,
|
||||||
|
webview.title,
|
||||||
|
Uri.parse(webview.url)
|
||||||
|
)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
if(savedInstanceState == null) {
|
||||||
|
mobileUserAgent = webview.settings.userAgentString
|
||||||
|
|
||||||
|
if(url == null) {
|
||||||
|
toast("No URL supplied!")
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
webview.loadUrl(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
|
||||||
|
super.onRestoreInstanceState(savedInstanceState)
|
||||||
|
savedInstanceState?.getString(STATE_KEY_MOBILE_USER_AGENT)?.let {
|
||||||
|
mobileUserAgent = it
|
||||||
|
}
|
||||||
|
savedInstanceState?.getBoolean(STATE_KEY_IS_DESKTOP)?.let {
|
||||||
|
isDesktop = it
|
||||||
|
}
|
||||||
|
webview.restoreState(savedInstanceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle?) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
outState?.putString(STATE_KEY_MOBILE_USER_AGENT, mobileUserAgent)
|
||||||
|
outState?.putBoolean(STATE_KEY_IS_DESKTOP, isDesktop)
|
||||||
|
webview.saveState(outState)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
|
||||||
|
menu?.findItem(R.id.action_forward)?.isEnabled = webview.canGoForward()
|
||||||
|
menu?.findItem(R.id.action_desktop_site)?.isChecked = isDesktop
|
||||||
|
|
||||||
|
return super.onPrepareOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.menu_webview, menu)
|
||||||
|
return super.onCreateOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBackPressed() {
|
||||||
|
if(webview.canGoBack())
|
||||||
|
webview.goBack()
|
||||||
|
else
|
||||||
|
super.onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
||||||
|
when(item?.itemId) {
|
||||||
|
android.R.id.home -> finish()
|
||||||
|
R.id.action_refresh -> webview.reload()
|
||||||
|
R.id.action_forward -> webview.goForward()
|
||||||
|
R.id.action_desktop_site -> {
|
||||||
|
isDesktop = !item.isChecked
|
||||||
|
item.isChecked = isDesktop
|
||||||
|
|
||||||
|
(if(isDesktop) {
|
||||||
|
mobileUserAgent?.replace("\\([^(]*(Mobile|Android)[^)]*\\)"
|
||||||
|
.toRegex(RegexOption.IGNORE_CASE), "")
|
||||||
|
?.replace("Mobile", "", true)
|
||||||
|
?.replace("Android", "", true)
|
||||||
|
} else {
|
||||||
|
mobileUserAgent
|
||||||
|
})?.let {
|
||||||
|
webview.settings.userAgentString = it
|
||||||
|
}
|
||||||
|
|
||||||
|
webview.settings.useWideViewPort = isDesktop
|
||||||
|
webview.settings.loadWithOverviewMode = isDesktop
|
||||||
|
|
||||||
|
webview.reload()
|
||||||
|
}
|
||||||
|
R.id.action_open_in_browser ->
|
||||||
|
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(webview.url)))
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val KEY_URL = "url"
|
||||||
|
|
||||||
|
const val STATE_KEY_MOBILE_USER_AGENT = "mobile_user_agent"
|
||||||
|
const val STATE_KEY_IS_DESKTOP = "is_desktop"
|
||||||
|
}
|
||||||
|
}
|
9
app/src/main/res/drawable/ic_close_white_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_close_white_24dp.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
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>
|
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M21,2L3,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h7v2L8,20v2h8v-2h-2v-2h7c1.1,0 2,-0.9 2,-2L23,4c0,-1.1 -0.9,-2 -2,-2zM21,16L3,16L3,4h18v12z"/>
|
||||||
|
</vector>
|
37
app/src/main/res/layout/activity_webview.xml
Normal file
37
app/src/main/res/layout/activity_webview.xml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:fitsSystemWindows="false">
|
||||||
|
|
||||||
|
<android.support.design.widget.AppBarLayout
|
||||||
|
android:id="@+id/appbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:theme="?attr/actionBarTheme">
|
||||||
|
|
||||||
|
<android.support.v7.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
app:layout_scrollFlags="scroll|enterAlways"
|
||||||
|
android:layout_height="?attr/actionBarSize">
|
||||||
|
|
||||||
|
</android.support.v7.widget.Toolbar>
|
||||||
|
</android.support.design.widget.AppBarLayout>
|
||||||
|
|
||||||
|
<android.support.v4.widget.NestedScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:fillViewport="true"
|
||||||
|
app:layout_behavior="android.support.design.widget.AppBarLayout$ScrollingViewBehavior">
|
||||||
|
|
||||||
|
<exh.ui.webview.NestedWebView
|
||||||
|
android:id="@+id/webview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:isScrollContainer="false" />
|
||||||
|
</android.support.v4.widget.NestedScrollView>
|
||||||
|
</android.support.design.widget.CoordinatorLayout>
|
19
app/src/main/res/menu/menu_webview.xml
Normal file
19
app/src/main/res/menu/menu_webview.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_refresh"
|
||||||
|
android:title="Refresh" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_forward"
|
||||||
|
android:title="Forward" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_desktop_site"
|
||||||
|
android:checkable="true"
|
||||||
|
android:title="Desktop site" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_open_in_browser"
|
||||||
|
android:title="Open in browser" />
|
||||||
|
</menu>
|
@ -102,7 +102,7 @@
|
|||||||
<string name="short_recent_updates">Updates</string>
|
<string name="short_recent_updates">Updates</string>
|
||||||
|
|
||||||
<!-- Preferences -->
|
<!-- Preferences -->
|
||||||
<!-- Subsections -->
|
<!-- Subsections -->
|
||||||
<string name="pref_category_general">General</string>
|
<string name="pref_category_general">General</string>
|
||||||
<string name="pref_category_reader">Reader</string>
|
<string name="pref_category_reader">Reader</string>
|
||||||
<string name="pref_category_downloads">Downloads</string>
|
<string name="pref_category_downloads">Downloads</string>
|
||||||
@ -111,7 +111,7 @@
|
|||||||
<string name="pref_category_advanced">Advanced</string>
|
<string name="pref_category_advanced">Advanced</string>
|
||||||
<string name="pref_category_about">About</string>
|
<string name="pref_category_about">About</string>
|
||||||
|
|
||||||
<!-- General section -->
|
<!-- General section -->
|
||||||
<string name="pref_library_columns">Library manga per row</string>
|
<string name="pref_library_columns">Library manga per row</string>
|
||||||
<string name="portrait">Portrait</string>
|
<string name="portrait">Portrait</string>
|
||||||
<string name="landscape">Landscape</string>
|
<string name="landscape">Landscape</string>
|
||||||
@ -166,7 +166,7 @@
|
|||||||
<string name="ext_language_info">Language: %1$s</string>
|
<string name="ext_language_info">Language: %1$s</string>
|
||||||
<string name="ext_empty_preferences">There are no preferences to edit for this extension</string>
|
<string name="ext_empty_preferences">There are no preferences to edit for this extension</string>
|
||||||
|
|
||||||
<!-- Reader section -->
|
<!-- Reader section -->
|
||||||
<string name="pref_fullscreen">Fullscreen</string>
|
<string name="pref_fullscreen">Fullscreen</string>
|
||||||
<string name="pref_lock_orientation">Lock orientation</string>
|
<string name="pref_lock_orientation">Lock orientation</string>
|
||||||
<string name="pref_page_transitions">Page transitions</string>
|
<string name="pref_page_transitions">Page transitions</string>
|
||||||
@ -217,7 +217,7 @@
|
|||||||
<string name="color_filter_a_value">A</string>
|
<string name="color_filter_a_value">A</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Downloads section -->
|
<!-- Downloads section -->
|
||||||
<string name="pref_download_directory">Downloads directory</string>
|
<string name="pref_download_directory">Downloads directory</string>
|
||||||
<string name="pref_download_only_over_wifi">Only download over Wi-Fi</string>
|
<string name="pref_download_only_over_wifi">Only download over Wi-Fi</string>
|
||||||
<string name="pref_remove_after_marked_as_read">Remove when marked as read</string>
|
<string name="pref_remove_after_marked_as_read">Remove when marked as read</string>
|
||||||
@ -232,7 +232,7 @@
|
|||||||
<string name="pref_download_new">Download new chapters</string>
|
<string name="pref_download_new">Download new chapters</string>
|
||||||
<string name="pref_download_new_categories">Categories to include in download</string>
|
<string name="pref_download_new_categories">Categories to include in download</string>
|
||||||
|
|
||||||
<!-- Sync section -->
|
<!-- Sync section -->
|
||||||
<string name="services">Services</string>
|
<string name="services">Services</string>
|
||||||
|
|
||||||
<!-- Backup section -->
|
<!-- Backup section -->
|
||||||
@ -258,7 +258,7 @@
|
|||||||
<string name="restoring_backup">Restoring backup</string>
|
<string name="restoring_backup">Restoring backup</string>
|
||||||
<string name="creating_backup">Creating backup</string>
|
<string name="creating_backup">Creating backup</string>
|
||||||
|
|
||||||
<!-- Advanced section -->
|
<!-- Advanced section -->
|
||||||
<string name="pref_clear_chapter_cache">Clear chapter cache</string>
|
<string name="pref_clear_chapter_cache">Clear chapter cache</string>
|
||||||
<string name="used_cache">Used: %1$s</string>
|
<string name="used_cache">Used: %1$s</string>
|
||||||
<string name="cache_deleted">Cache cleared. %1$d files have been deleted</string>
|
<string name="cache_deleted">Cache cleared. %1$d files have been deleted</string>
|
||||||
@ -275,7 +275,7 @@
|
|||||||
<string name="pref_refresh_library_tracking">Refresh tracking metadata</string>
|
<string name="pref_refresh_library_tracking">Refresh tracking metadata</string>
|
||||||
<string name="pref_refresh_library_tracking_summary">Updates status, score and last chapter read from the tracking services</string>
|
<string name="pref_refresh_library_tracking_summary">Updates status, score and last chapter read from the tracking services</string>
|
||||||
|
|
||||||
<!-- About section -->
|
<!-- About section -->
|
||||||
<string name="version">Version</string>
|
<string name="version">Version</string>
|
||||||
<string name="build_time">Build time</string>
|
<string name="build_time">Build time</string>
|
||||||
<string name="pref_enable_automatic_updates">Check for updates</string>
|
<string name="pref_enable_automatic_updates">Check for updates</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user