Compare commits
73
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53a0307a8e | ||
|
|
1c6f624fd1 | ||
|
|
780e5f08f9 | ||
|
|
1bb73b1147 | ||
|
|
09b0d4d6c4 | ||
|
|
7e3856fa05 | ||
|
|
fbcb3f5436 | ||
|
|
324b4ced06 | ||
|
|
79c2abe790 | ||
|
|
cdab9168fc | ||
|
|
ce272724de | ||
|
|
2fa0a19d3b | ||
|
|
38b9a6e04a | ||
|
|
22d3c2b6bf | ||
|
|
218a8397c4 | ||
|
|
fd990da71e | ||
|
|
4a70c89a4d | ||
|
|
7e3143678f | ||
|
|
d80e09dfba | ||
|
|
3b3b251c21 | ||
|
|
1e848bd70f | ||
|
|
fab2295445 | ||
|
|
a913bccc9e | ||
|
|
57e7f89814 | ||
|
|
f98fd5e5f1 | ||
|
|
e6af2e5c6b | ||
|
|
d219989ec7 | ||
|
|
b9daf608ff | ||
|
|
869da61fd0 | ||
|
|
9f79e2505c | ||
|
|
3000b36dbd | ||
|
|
1d21b0e5c4 | ||
|
|
8d6b0926d6 | ||
|
|
4c39d13c80 | ||
|
|
327dd1c73f | ||
|
|
b36b8f3234 | ||
|
|
5f6da284fb | ||
|
|
83d27e18cb | ||
|
|
e291bd58a8 | ||
|
|
23acdb6492 | ||
|
|
3b5e56b049 | ||
|
|
57d4967f2a | ||
|
|
80fcda149b | ||
|
|
1a86eef52c | ||
|
|
98d401f9c3 | ||
|
|
0f2fae886e | ||
|
|
f30a9093af | ||
|
|
b4334da202 | ||
|
|
416fb3bda9 | ||
|
|
7e0fc2e364 | ||
|
|
540d290be2 | ||
|
|
53974ad88d | ||
|
|
cd9b5e5a44 | ||
|
|
d9959bbcb2 | ||
|
|
d7dfd53244 | ||
|
|
84489bf61b | ||
|
|
3fdb56390e | ||
|
|
a34e766f70 | ||
|
|
d74023d4fa | ||
|
|
41572e98ba | ||
|
|
063087c87e | ||
|
|
4a5d53d713 | ||
|
|
9a262525ec | ||
|
|
e327b4e84b | ||
|
|
c128a2b518 | ||
|
|
a3263ab4af | ||
|
|
4a4efe4725 | ||
|
|
89d2433369 | ||
|
|
023175ce6d | ||
|
|
21c8d24d57 | ||
|
|
e49f5c95f4 | ||
|
|
6912e578ca | ||
|
|
8680cff2b2 |
No files matched your search
+10
-11
@@ -1,6 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application'
|
id 'com.android.application'
|
||||||
id 'org.jetbrains.kotlin.android'
|
id 'kotlin-android'
|
||||||
|
id 'kotlin-parcelize'
|
||||||
id 'com.google.devtools.ksp'
|
id 'com.google.devtools.ksp'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ android {
|
|||||||
minSdkVersion 28
|
minSdkVersion 28
|
||||||
targetSdkVersion 33
|
targetSdkVersion 33
|
||||||
versionCode 180030
|
versionCode 180030
|
||||||
versionName "1.8.5.2"
|
versionName "1.8.5.3-alpha01"
|
||||||
resConfigs 'zh', 'zh-rCN', 'zh-rHK', 'zh-rTW', 'es', 'ja', 'ko', 'fr', 'de', 'th'
|
resConfigs 'zh', 'zh-rCN', 'zh-rHK', 'zh-rTW', 'es', 'ja', 'ko', 'fr', 'de', 'th'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +91,6 @@ android {
|
|||||||
buildFeatures {
|
buildFeatures {
|
||||||
buildConfig true
|
buildConfig true
|
||||||
compose true
|
compose true
|
||||||
dataBinding true
|
|
||||||
viewBinding true
|
viewBinding true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +103,6 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
def activity_version = "1.6.1"
|
def activity_version = "1.6.1"
|
||||||
implementation "androidx.activity:activity:$activity_version"
|
|
||||||
implementation "androidx.activity:activity-ktx:$activity_version"
|
implementation "androidx.activity:activity-ktx:$activity_version"
|
||||||
|
|
||||||
implementation "androidx.annotation:annotation:1.5.0"
|
implementation "androidx.annotation:annotation:1.5.0"
|
||||||
@@ -134,14 +133,12 @@ dependencies {
|
|||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
|
||||||
|
|
||||||
def core_version = "1.9.0"
|
def core_version = "1.9.0"
|
||||||
implementation "androidx.core:core:$core_version"
|
|
||||||
implementation "androidx.core:core-ktx:$core_version"
|
implementation "androidx.core:core-ktx:$core_version"
|
||||||
|
|
||||||
implementation "androidx.customview:customview:1.2.0-alpha02"
|
implementation "androidx.customview:customview:1.2.0-alpha02"
|
||||||
implementation "androidx.dynamicanimation:dynamicanimation:1.1.0-alpha03"
|
implementation "androidx.dynamicanimation:dynamicanimation:1.1.0-alpha03"
|
||||||
|
|
||||||
def fragment_version = "1.6.0-alpha04"
|
def fragment_version = "1.6.0-alpha04"
|
||||||
implementation "androidx.fragment:fragment:$fragment_version"
|
|
||||||
implementation "androidx.fragment:fragment-ktx:$fragment_version"
|
implementation "androidx.fragment:fragment-ktx:$fragment_version"
|
||||||
|
|
||||||
def lifecycle_version = "2.6.0-alpha03"
|
def lifecycle_version = "2.6.0-alpha03"
|
||||||
@@ -155,19 +152,17 @@ dependencies {
|
|||||||
implementation "androidx.loader:loader:1.1.0"
|
implementation "androidx.loader:loader:1.1.0"
|
||||||
|
|
||||||
def nav_version = "2.5.3"
|
def nav_version = "2.5.3"
|
||||||
implementation "androidx.navigation:navigation-fragment:$nav_version"
|
|
||||||
implementation "androidx.navigation:navigation-ui:$nav_version"
|
|
||||||
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
|
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
|
||||||
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
|
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
|
||||||
|
|
||||||
implementation "androidx.paging:paging-runtime:3.2.0-alpha03"
|
implementation "androidx.paging:paging-runtime-ktx:3.2.0-alpha03"
|
||||||
|
|
||||||
implementation 'androidx.preference:preference:1.2.0'
|
implementation 'androidx.preference:preference-ktx:1.2.0'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.3.0-rc01'
|
implementation 'androidx.recyclerview:recyclerview:1.3.0-rc01'
|
||||||
|
|
||||||
def room_version = "2.5.0-rc01"
|
def room_version = "2.5.0-rc01"
|
||||||
implementation "androidx.room:room-runtime:$room_version"
|
implementation "androidx.room:room-runtime:$room_version"
|
||||||
annotationProcessor "androidx.room:room-compiler:$room_version"
|
ksp "androidx.room:room-compiler:$room_version"
|
||||||
implementation "androidx.room:room-paging:$room_version"
|
implementation "androidx.room:room-paging:$room_version"
|
||||||
|
|
||||||
implementation 'androidx.startup:startup-runtime:1.2.0-alpha01'
|
implementation 'androidx.startup:startup-runtime:1.2.0-alpha01'
|
||||||
@@ -183,6 +178,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation 'com.squareup.okhttp3:okhttp-bom:5.0.0-alpha.11'
|
implementation 'com.squareup.okhttp3:okhttp-bom:5.0.0-alpha.11'
|
||||||
implementation 'com.squareup.okhttp3:okhttp'
|
implementation 'com.squareup.okhttp3:okhttp'
|
||||||
|
implementation 'com.squareup.okhttp3:okhttp-coroutines'
|
||||||
|
|
||||||
implementation 'dev.rikka.rikkax.core:core-ktx:1.4.1'
|
implementation 'dev.rikka.rikkax.core:core-ktx:1.4.1'
|
||||||
implementation 'dev.rikka.rikkax.insets:insets:1.3.0'
|
implementation 'dev.rikka.rikkax.insets:insets:1.3.0'
|
||||||
@@ -202,4 +198,7 @@ configurations.all {
|
|||||||
exclude group: 'dev.rikka.rikkax.appcompat', module: 'appcompat'
|
exclude group: 'dev.rikka.rikkax.appcompat', module: 'appcompat'
|
||||||
exclude group: 'dev.rikka.rikkax.material', module: 'material'
|
exclude group: 'dev.rikka.rikkax.material', module: 'material'
|
||||||
exclude group: 'androidx.compose.material'
|
exclude group: 'androidx.compose.material'
|
||||||
|
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-android-extensions-runtime'
|
||||||
|
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk7'
|
||||||
|
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
|
||||||
}
|
}
|
||||||
@@ -329,21 +329,7 @@ public final class DiskLruCache implements Closeable {
|
|||||||
} else {
|
} else {
|
||||||
throw new IOException("unexpected journal line: " + line);
|
throw new IOException("unexpected journal line: " + line);
|
||||||
}
|
}
|
||||||
} private final Callable<Void> cleanupCallable = new Callable<>() {
|
}
|
||||||
public Void call() throws Exception {
|
|
||||||
synchronized (DiskLruCache.this) {
|
|
||||||
if (journalWriter == null) {
|
|
||||||
return null; // Closed.
|
|
||||||
}
|
|
||||||
trimToSize();
|
|
||||||
if (journalRebuildRequired()) {
|
|
||||||
rebuildJournal();
|
|
||||||
redundantOpCount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the initial size and collects garbage as a part of opening the
|
* Computes the initial size and collects garbage as a part of opening the
|
||||||
@@ -366,7 +352,21 @@ public final class DiskLruCache implements Closeable {
|
|||||||
i.remove();
|
i.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} private final Callable<Void> cleanupCallable = new Callable<>() {
|
||||||
|
public Void call() throws Exception {
|
||||||
|
synchronized (DiskLruCache.this) {
|
||||||
|
if (journalWriter == null) {
|
||||||
|
return null; // Closed.
|
||||||
|
}
|
||||||
|
trimToSize();
|
||||||
|
if (journalRebuildRequired()) {
|
||||||
|
rebuildJournal();
|
||||||
|
redundantOpCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new journal that omits redundant information. This replaces the
|
* Creates a new journal that omits redundant information. This replaces the
|
||||||
|
|||||||
@@ -35,10 +35,8 @@ import coil.ImageLoaderFactory
|
|||||||
import coil.disk.DiskCache
|
import coil.disk.DiskCache
|
||||||
import com.hippo.Native
|
import com.hippo.Native
|
||||||
import com.hippo.app.BaseDialogBuilder
|
import com.hippo.app.BaseDialogBuilder
|
||||||
import com.hippo.ehviewer.client.EhClient
|
|
||||||
import com.hippo.ehviewer.client.EhCookieStore
|
import com.hippo.ehviewer.client.EhCookieStore
|
||||||
import com.hippo.ehviewer.client.EhDns
|
import com.hippo.ehviewer.client.EhDns
|
||||||
import com.hippo.ehviewer.client.EhEngine
|
|
||||||
import com.hippo.ehviewer.client.EhRequestBuilder
|
import com.hippo.ehviewer.client.EhRequestBuilder
|
||||||
import com.hippo.ehviewer.client.EhSSLSocketFactory
|
import com.hippo.ehviewer.client.EhSSLSocketFactory
|
||||||
import com.hippo.ehviewer.client.EhTagDatabase
|
import com.hippo.ehviewer.client.EhTagDatabase
|
||||||
@@ -58,12 +56,10 @@ import com.hippo.yorozuya.FileUtils
|
|||||||
import com.hippo.yorozuya.IntIdGenerator
|
import com.hippo.yorozuya.IntIdGenerator
|
||||||
import eu.kanade.tachiyomi.core.preference.AndroidPreferenceStore
|
import eu.kanade.tachiyomi.core.preference.AndroidPreferenceStore
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||||
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import okhttp3.Cache
|
import okhttp3.Cache
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
@@ -112,42 +108,46 @@ class EhApplication : SceneApplication(), DefaultLifecycleObserver, ImageLoaderF
|
|||||||
AppConfig.initialize(this)
|
AppConfig.initialize(this)
|
||||||
SpiderDen.initialize(this)
|
SpiderDen.initialize(this)
|
||||||
EhDB.initialize(this)
|
EhDB.initialize(this)
|
||||||
EhEngine.initialize()
|
|
||||||
BitmapUtils.initialize(this)
|
BitmapUtils.initialize(this)
|
||||||
EhTagDatabase.update()
|
EhTagDatabase.update()
|
||||||
|
|
||||||
AppCompatDelegate.setDefaultNightMode(Settings.getTheme())
|
AppCompatDelegate.setDefaultNightMode(Settings.getTheme())
|
||||||
|
launchIO {
|
||||||
GlobalScope.launch {
|
launchIO {
|
||||||
withContext(Dispatchers.IO) {
|
downloadManager
|
||||||
try {
|
}
|
||||||
val downloadLocation = Settings.getDownloadLocation()
|
launchIO {
|
||||||
if (Settings.getMediaScan()) {
|
cleanupDownload()
|
||||||
CommonOperations.removeNoMediaFile(downloadLocation)
|
}
|
||||||
} else {
|
launchIO {
|
||||||
CommonOperations.ensureNoMediaFile(downloadLocation)
|
theDawnOfNewDay()
|
||||||
}
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
t.printStackTrace()
|
|
||||||
ExceptionUtils.throwIfFatal(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear temp files
|
|
||||||
try {
|
|
||||||
clearTempDir()
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
t.printStackTrace()
|
|
||||||
ExceptionUtils.throwIfFatal(t)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
GlobalScope.launch {
|
|
||||||
theDawnOfNewDay()
|
|
||||||
}
|
}
|
||||||
mIdGenerator.setNextId(Settings.getInt(KEY_GLOBAL_STUFF_NEXT_ID, 0))
|
mIdGenerator.setNextId(Settings.getInt(KEY_GLOBAL_STUFF_NEXT_ID, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun theDawnOfNewDay() {
|
private fun cleanupDownload() {
|
||||||
|
try {
|
||||||
|
val downloadLocation = Settings.getDownloadLocation()
|
||||||
|
if (Settings.getMediaScan()) {
|
||||||
|
CommonOperations.removeNoMediaFile(downloadLocation)
|
||||||
|
} else {
|
||||||
|
CommonOperations.ensureNoMediaFile(downloadLocation)
|
||||||
|
}
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
t.printStackTrace()
|
||||||
|
ExceptionUtils.throwIfFatal(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear temp files
|
||||||
|
try {
|
||||||
|
clearTempDir()
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
t.printStackTrace()
|
||||||
|
ExceptionUtils.throwIfFatal(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun theDawnOfNewDay() {
|
||||||
if (!Settings.getRequestNews()) {
|
if (!Settings.getRequestNews()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -159,22 +159,20 @@ class EhApplication : SceneApplication(), DefaultLifecycleObserver, ImageLoaderF
|
|||||||
EhCookieStore.KEY_IPD_PASS_HASH
|
EhCookieStore.KEY_IPD_PASS_HASH
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
withContext(Dispatchers.IO) {
|
val referer = EhUrl.REFERER_E
|
||||||
val referer = EhUrl.REFERER_E
|
val request = EhRequestBuilder(EhUrl.HOST_E + "news.php", referer).build()
|
||||||
val request = EhRequestBuilder(EhUrl.HOST_E + "news.php", referer).build()
|
val call = okHttpClient.newCall(request)
|
||||||
val call = okHttpClient.newCall(request)
|
try {
|
||||||
try {
|
call.execute().use { response ->
|
||||||
call.execute().use { response ->
|
val responseBody = response.body
|
||||||
val responseBody = response.body
|
val body = responseBody.string()
|
||||||
val body = responseBody.string()
|
val html = EventPaneParser.parse(body)
|
||||||
val html = EventPaneParser.parse(body)
|
if (html != null) {
|
||||||
if (html != null) {
|
showEventPane(html)
|
||||||
showEventPane(html)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,9 +280,6 @@ class EhApplication : SceneApplication(), DefaultLifecycleObserver, ImageLoaderF
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
val ehCookieStore by lazy { EhCookieStore(application) }
|
val ehCookieStore by lazy { EhCookieStore(application) }
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
val ehClient by lazy { EhClient() }
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val ehProxySelector by lazy { EhProxySelector() }
|
val ehProxySelector by lazy { EhProxySelector() }
|
||||||
|
|
||||||
|
|||||||
@@ -281,9 +281,9 @@ public class EhDB {
|
|||||||
|
|
||||||
public static synchronized void insertQuickSearch(QuickSearch quickSearch) {
|
public static synchronized void insertQuickSearch(QuickSearch quickSearch) {
|
||||||
QuickSearchDao dao = db.quickSearchDao();
|
QuickSearchDao dao = db.quickSearchDao();
|
||||||
quickSearch.id = null;
|
quickSearch.setId(null);
|
||||||
quickSearch.time = System.currentTimeMillis();
|
quickSearch.setTime(System.currentTimeMillis());
|
||||||
quickSearch.id = dao.insert(quickSearch);
|
quickSearch.setId(dao.insert(quickSearch));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void importQuickSearch(List<QuickSearch> quickSearchList) {
|
public static synchronized void importQuickSearch(List<QuickSearch> quickSearchList) {
|
||||||
@@ -386,7 +386,7 @@ public class EhDB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void triggerFilter(Filter filter) {
|
public static synchronized void triggerFilter(Filter filter) {
|
||||||
filter.setEnable(!filter.enable);
|
filter.enable = !filter.enable;
|
||||||
db.filterDao().update(filter);
|
db.filterDao().update(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,9 +521,9 @@ public class EhDB {
|
|||||||
List<QuickSearch> currentQuickSearchList = db.quickSearchDao().list();
|
List<QuickSearch> currentQuickSearchList = db.quickSearchDao().list();
|
||||||
List<QuickSearch> importList = new ArrayList<>();
|
List<QuickSearch> importList = new ArrayList<>();
|
||||||
for (QuickSearch quickSearch : quickSearchList) {
|
for (QuickSearch quickSearch : quickSearchList) {
|
||||||
String name = quickSearch.name;
|
String name = quickSearch.getName();
|
||||||
for (QuickSearch q : currentQuickSearchList) {
|
for (QuickSearch q : currentQuickSearchList) {
|
||||||
if (ObjectUtils.equal(q.name, name)) {
|
if (ObjectUtils.equal(q.getName(), name)) {
|
||||||
// The same name
|
// The same name
|
||||||
name = null;
|
name = null;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,202 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.client;
|
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
|
|
||||||
import com.hippo.ehviewer.EhApplication;
|
|
||||||
import com.hippo.ehviewer.client.exception.CancelledException;
|
|
||||||
import com.hippo.util.ExceptionUtils;
|
|
||||||
import com.hippo.util.IoThreadPoolExecutor;
|
|
||||||
import com.hippo.yorozuya.SimpleHandler;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
import okhttp3.Call;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
|
|
||||||
public class EhClient {
|
|
||||||
|
|
||||||
public static final String TAG = EhClient.class.getSimpleName();
|
|
||||||
|
|
||||||
public static final int METHOD_SIGN_IN = 0;
|
|
||||||
public static final int METHOD_GET_GALLERY_LIST = 1;
|
|
||||||
public static final int METHOD_GET_GALLERY_DETAIL = 3;
|
|
||||||
public static final int METHOD_GET_PREVIEW_SET = 4;
|
|
||||||
public static final int METHOD_GET_RATE_GALLERY = 5;
|
|
||||||
public static final int METHOD_GET_COMMENT_GALLERY = 6;
|
|
||||||
public static final int METHOD_GET_GALLERY_TOKEN = 7;
|
|
||||||
public static final int METHOD_GET_FAVORITES = 8;
|
|
||||||
public static final int METHOD_ADD_FAVORITES = 9;
|
|
||||||
public static final int METHOD_ADD_FAVORITES_RANGE = 10;
|
|
||||||
public static final int METHOD_MODIFY_FAVORITES = 11;
|
|
||||||
public static final int METHOD_GET_TORRENT_LIST = 12;
|
|
||||||
public static final int METHOD_GET_PROFILE = 14;
|
|
||||||
public static final int METHOD_VOTE_COMMENT = 15;
|
|
||||||
public static final int METHOD_IMAGE_SEARCH = 16;
|
|
||||||
public static final int METHOD_ARCHIVE_LIST = 17;
|
|
||||||
public static final int METHOD_DOWNLOAD_ARCHIVE = 18;
|
|
||||||
public static final int METHOD_VOTE_TAG = 19;
|
|
||||||
public static final int METHOD_GET_UCONFIG = 20;
|
|
||||||
private static final OkHttpClient mOkHttpClient = EhApplication.getOkHttpClient();
|
|
||||||
private final ThreadPoolExecutor mRequestThreadPool;
|
|
||||||
|
|
||||||
public EhClient() {
|
|
||||||
mRequestThreadPool = IoThreadPoolExecutor.getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void execute(EhRequest request) {
|
|
||||||
if (!request.isCancelled()) {
|
|
||||||
Task task = new Task(request.getMethod(), request.getCallback());
|
|
||||||
task.executeOnExecutor(mRequestThreadPool, request.getArgs());
|
|
||||||
request.task = task;
|
|
||||||
} else {
|
|
||||||
request.getCallback().onCancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Callback<E> {
|
|
||||||
|
|
||||||
void onSuccess(E result);
|
|
||||||
|
|
||||||
void onFailure(Exception e);
|
|
||||||
|
|
||||||
void onCancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public static class Task extends AsyncTask<Object, Void, Object> {
|
|
||||||
|
|
||||||
private final int mMethod;
|
|
||||||
private final AtomicReference<Call> mCall = new AtomicReference<>();
|
|
||||||
private final AtomicBoolean mStop = new AtomicBoolean();
|
|
||||||
private Callback<Object> mCallback;
|
|
||||||
|
|
||||||
public Task(int method, Callback<Object> callback) {
|
|
||||||
mMethod = method;
|
|
||||||
mCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called in Job thread
|
|
||||||
public void setCall(Call call) throws CancelledException {
|
|
||||||
if (mStop.get()) {
|
|
||||||
// Stopped Job thread
|
|
||||||
throw new CancelledException();
|
|
||||||
} else {
|
|
||||||
mCall.lazySet(call);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
if (!mStop.get()) {
|
|
||||||
mStop.lazySet(true);
|
|
||||||
|
|
||||||
if (mCallback != null) {
|
|
||||||
// TODO Avoid new runnable
|
|
||||||
SimpleHandler.getInstance().post(mCallback::onCancel);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status status = getStatus();
|
|
||||||
if (status == Status.PENDING) {
|
|
||||||
cancel(false);
|
|
||||||
} else if (status == Status.RUNNING) {
|
|
||||||
// It is running, cancel call if it is created
|
|
||||||
Call call = mCall.get();
|
|
||||||
if (call != null) {
|
|
||||||
call.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear
|
|
||||||
mCallback = null;
|
|
||||||
mCall.lazySet(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object doInBackground(Object... params) {
|
|
||||||
try {
|
|
||||||
return switch (mMethod) {
|
|
||||||
case METHOD_SIGN_IN ->
|
|
||||||
EhEngine.signIn(this, mOkHttpClient, (String) params[0], (String) params[1]);
|
|
||||||
case METHOD_GET_GALLERY_LIST ->
|
|
||||||
EhEngine.getGalleryList(this, mOkHttpClient, (String) params[0]);
|
|
||||||
case METHOD_GET_GALLERY_DETAIL ->
|
|
||||||
EhEngine.getGalleryDetail(this, mOkHttpClient, (String) params[0]);
|
|
||||||
case METHOD_GET_PREVIEW_SET ->
|
|
||||||
EhEngine.getPreviewSet(this, mOkHttpClient, (String) params[0]);
|
|
||||||
case METHOD_GET_RATE_GALLERY ->
|
|
||||||
EhEngine.rateGallery(this, mOkHttpClient, (Long) params[0], (String) params[1], (Long) params[2], (String) params[3], (Float) params[4]);
|
|
||||||
case METHOD_GET_COMMENT_GALLERY ->
|
|
||||||
EhEngine.commentGallery(this, mOkHttpClient, (String) params[0], (String) params[1], (String) params[2]);
|
|
||||||
case METHOD_GET_GALLERY_TOKEN ->
|
|
||||||
EhEngine.getGalleryToken(this, mOkHttpClient, (Long) params[0], (String) params[1], (Integer) params[2]);
|
|
||||||
case METHOD_GET_FAVORITES ->
|
|
||||||
EhEngine.getFavorites(this, mOkHttpClient, (String) params[0]);
|
|
||||||
case METHOD_ADD_FAVORITES ->
|
|
||||||
EhEngine.addFavorites(this, mOkHttpClient, (Long) params[0], (String) params[1], (Integer) params[2], (String) params[3]);
|
|
||||||
case METHOD_ADD_FAVORITES_RANGE ->
|
|
||||||
EhEngine.addFavoritesRange(this, mOkHttpClient, (long[]) params[0], (String[]) params[1], (Integer) params[2]);
|
|
||||||
case METHOD_MODIFY_FAVORITES ->
|
|
||||||
EhEngine.modifyFavorites(this, mOkHttpClient, (String) params[0], (long[]) params[1], (Integer) params[2]);
|
|
||||||
case METHOD_GET_TORRENT_LIST ->
|
|
||||||
EhEngine.getTorrentList(this, mOkHttpClient, (String) params[0], (Long) params[1], (String) params[2]);
|
|
||||||
case METHOD_GET_PROFILE -> EhEngine.getProfile(this, mOkHttpClient);
|
|
||||||
case METHOD_VOTE_COMMENT ->
|
|
||||||
EhEngine.voteComment(this, mOkHttpClient, (Long) params[0], (String) params[1], (Long) params[2], (String) params[3], (Long) params[4], (Integer) params[5]);
|
|
||||||
case METHOD_IMAGE_SEARCH ->
|
|
||||||
EhEngine.imageSearch(this, mOkHttpClient, (File) params[0], (Boolean) params[1], (Boolean) params[2], (Boolean) params[3]);
|
|
||||||
case METHOD_ARCHIVE_LIST ->
|
|
||||||
EhEngine.getArchiveList(this, mOkHttpClient, (String) params[0], (Long) params[1], (String) params[2]);
|
|
||||||
case METHOD_DOWNLOAD_ARCHIVE ->
|
|
||||||
EhEngine.downloadArchive(this, mOkHttpClient, (Long) params[0], (String) params[1], (String) params[2], (String) params[3]);
|
|
||||||
case METHOD_VOTE_TAG ->
|
|
||||||
EhEngine.voteTag(this, mOkHttpClient, (Long) params[0], (String) params[1], (Long) params[2], (String) params[3], (String) params[4], (Integer) params[5]);
|
|
||||||
case METHOD_GET_UCONFIG -> EhEngine.getUConfig(this, mOkHttpClient);
|
|
||||||
default -> new IllegalStateException("Can't detect method " + mMethod);
|
|
||||||
};
|
|
||||||
} catch (Throwable e) {
|
|
||||||
ExceptionUtils.throwIfFatal(e);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Object result) {
|
|
||||||
if (mCallback != null) {
|
|
||||||
//noinspection StatementWithEmptyBody
|
|
||||||
if (!(result instanceof CancelledException)) {
|
|
||||||
if (result instanceof Exception) {
|
|
||||||
mCallback.onFailure((Exception) result);
|
|
||||||
} else {
|
|
||||||
mCallback.onSuccess(result);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// onCancel is called in stop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear
|
|
||||||
mCallback = null;
|
|
||||||
mCall.lazySet(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.client
|
||||||
|
|
||||||
|
import com.hippo.ehviewer.EhApplication.Companion.okHttpClient
|
||||||
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
|
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||||
|
import kotlinx.coroutines.CancellationException
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
object EhClient {
|
||||||
|
internal fun enqueue(request: EhRequest, scope: CoroutineScope) {
|
||||||
|
check(!request.isActive) // Abort if attempt to execute an active request
|
||||||
|
request.job = scope.launchIO {
|
||||||
|
val method = request.method
|
||||||
|
val params = request.args
|
||||||
|
val callback: Callback<Any?>? = request.callback
|
||||||
|
try {
|
||||||
|
val result: Any? = when (method) {
|
||||||
|
METHOD_SIGN_IN -> EhEngine.signIn(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as String,
|
||||||
|
params[1] as String
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_GET_GALLERY_LIST -> EhEngine.getGalleryList(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as String
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_GET_GALLERY_DETAIL -> EhEngine.getGalleryDetail(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as String?
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_GET_PREVIEW_SET -> EhEngine.getPreviewSet(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as String?
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_GET_RATE_GALLERY -> EhEngine.rateGallery(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as Long,
|
||||||
|
params[1] as String?,
|
||||||
|
params[2] as Long,
|
||||||
|
params[3] as String?,
|
||||||
|
params[4] as Float
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_GET_COMMENT_GALLERY -> EhEngine.commentGallery(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as String?,
|
||||||
|
params[1] as String,
|
||||||
|
params[2] as String?
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_GET_GALLERY_TOKEN -> EhEngine.getGalleryToken(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as Long,
|
||||||
|
params[1] as String?,
|
||||||
|
params[2] as Int
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_GET_FAVORITES -> EhEngine.getFavorites(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as String
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_ADD_FAVORITES -> EhEngine.addFavorites(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as Long,
|
||||||
|
params[1] as String?,
|
||||||
|
params[2] as Int,
|
||||||
|
params[3] as String?
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_ADD_FAVORITES_RANGE -> @Suppress("UNCHECKED_CAST") EhEngine.addFavoritesRange(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as LongArray,
|
||||||
|
params[1] as Array<String?>,
|
||||||
|
params[2] as Int
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_MODIFY_FAVORITES -> EhEngine.modifyFavorites(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as String,
|
||||||
|
params[1] as LongArray,
|
||||||
|
params[2] as Int
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_GET_TORRENT_LIST -> EhEngine.getTorrentList(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as String?,
|
||||||
|
params[1] as Long,
|
||||||
|
params[2] as String?
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_GET_PROFILE -> EhEngine.getProfile(mOkHttpClient)
|
||||||
|
METHOD_VOTE_COMMENT -> EhEngine.voteComment(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as Long,
|
||||||
|
params[1] as String?,
|
||||||
|
params[2] as Long,
|
||||||
|
params[3] as String?,
|
||||||
|
params[4] as Long,
|
||||||
|
params[5] as Int
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_IMAGE_SEARCH -> EhEngine.imageSearch(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as File,
|
||||||
|
params[1] as Boolean,
|
||||||
|
params[2] as Boolean,
|
||||||
|
params[3] as Boolean
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_ARCHIVE_LIST -> EhEngine.getArchiveList(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as String?,
|
||||||
|
params[1] as Long,
|
||||||
|
params[2] as String?
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_DOWNLOAD_ARCHIVE -> EhEngine.downloadArchive(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as Long,
|
||||||
|
params[1] as String?,
|
||||||
|
params[2] as String?,
|
||||||
|
params[3] as String?,
|
||||||
|
params[4] as Boolean
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_VOTE_TAG -> EhEngine.voteTag(
|
||||||
|
mOkHttpClient,
|
||||||
|
params!![0] as Long,
|
||||||
|
params[1] as String?,
|
||||||
|
params[2] as Long,
|
||||||
|
params[3] as String?,
|
||||||
|
params[4] as String?,
|
||||||
|
params[5] as Int
|
||||||
|
)
|
||||||
|
|
||||||
|
METHOD_GET_UCONFIG -> EhEngine.getUConfig(mOkHttpClient)
|
||||||
|
else -> throw IllegalStateException("Can't detect method $method")
|
||||||
|
}
|
||||||
|
withUIContext { callback?.onSuccess(result) }
|
||||||
|
} catch (e: Exception) {
|
||||||
|
if (e is CancellationException)
|
||||||
|
throw e // Don't catch coroutine CancellationException
|
||||||
|
e.printStackTrace()
|
||||||
|
withUIContext { callback?.onFailure(e) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Callback<E> {
|
||||||
|
fun onSuccess(result: E)
|
||||||
|
fun onFailure(e: Exception)
|
||||||
|
fun onCancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
const val METHOD_SIGN_IN = 0
|
||||||
|
const val METHOD_GET_GALLERY_LIST = 1
|
||||||
|
const val METHOD_GET_GALLERY_DETAIL = 3
|
||||||
|
const val METHOD_GET_PREVIEW_SET = 4
|
||||||
|
const val METHOD_GET_RATE_GALLERY = 5
|
||||||
|
const val METHOD_GET_COMMENT_GALLERY = 6
|
||||||
|
const val METHOD_GET_GALLERY_TOKEN = 7
|
||||||
|
const val METHOD_GET_FAVORITES = 8
|
||||||
|
const val METHOD_ADD_FAVORITES = 9
|
||||||
|
const val METHOD_ADD_FAVORITES_RANGE = 10
|
||||||
|
const val METHOD_MODIFY_FAVORITES = 11
|
||||||
|
const val METHOD_GET_TORRENT_LIST = 12
|
||||||
|
const val METHOD_GET_PROFILE = 14
|
||||||
|
const val METHOD_VOTE_COMMENT = 15
|
||||||
|
const val METHOD_IMAGE_SEARCH = 16
|
||||||
|
const val METHOD_ARCHIVE_LIST = 17
|
||||||
|
const val METHOD_DOWNLOAD_ARCHIVE = 18
|
||||||
|
const val METHOD_VOTE_TAG = 19
|
||||||
|
const val METHOD_GET_UCONFIG = 20
|
||||||
|
private val mOkHttpClient = okHttpClient
|
||||||
|
}
|
||||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -18,6 +18,8 @@ package com.hippo.ehviewer.client;
|
|||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.hippo.ehviewer.EhDB;
|
import com.hippo.ehviewer.EhDB;
|
||||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||||
import com.hippo.ehviewer.dao.Filter;
|
import com.hippo.ehviewer.dao.Filter;
|
||||||
@@ -69,7 +71,7 @@ public final class EhFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EhFilter getInstance() {
|
public static @NonNull EhFilter getInstance() {
|
||||||
if (sInstance == null) {
|
if (sInstance == null) {
|
||||||
sInstance = new EhFilter();
|
sInstance = new EhFilter();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.client;
|
|
||||||
|
|
||||||
import com.hippo.ehviewer.Settings;
|
|
||||||
|
|
||||||
public class EhRequest {
|
|
||||||
|
|
||||||
EhClient.Task task;
|
|
||||||
private int mMethod;
|
|
||||||
private Object[] mArgs;
|
|
||||||
private EhClient.Callback mCallback;
|
|
||||||
private EhConfig mEhConfig;
|
|
||||||
private boolean mCancel = false;
|
|
||||||
|
|
||||||
public int getMethod() {
|
|
||||||
return mMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EhRequest setMethod(int method) {
|
|
||||||
mMethod = method;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object[] getArgs() {
|
|
||||||
return mArgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EhRequest setArgs(Object... args) {
|
|
||||||
mArgs = args;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EhClient.Callback getCallback() {
|
|
||||||
return mCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EhRequest setCallback(EhClient.Callback callback) {
|
|
||||||
mCallback = callback;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EhConfig getEhConfig() {
|
|
||||||
return mEhConfig != null ? mEhConfig : Settings.getEhConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
public EhRequest setEhConfig(EhConfig ehConfig) {
|
|
||||||
mEhConfig = ehConfig;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cancel() {
|
|
||||||
if (!mCancel) {
|
|
||||||
mCancel = true;
|
|
||||||
if (task != null) {
|
|
||||||
task.stop();
|
|
||||||
task = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return mCancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.client
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import androidx.annotation.MainThread
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
|
||||||
|
class EhRequest {
|
||||||
|
internal var job: Job? = null
|
||||||
|
val isActive
|
||||||
|
get() = job?.isActive ?: false
|
||||||
|
var method = 0
|
||||||
|
private set
|
||||||
|
var args: Array<out Any>? = null
|
||||||
|
private set
|
||||||
|
var callback: EhClient.Callback<Any?>? = null
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun setMethod(method: Int): EhRequest {
|
||||||
|
this.method = method
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setArgs(vararg args: Any): EhRequest {
|
||||||
|
this.args = args
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
fun setCallback(callback: EhClient.Callback<*>?): EhRequest {
|
||||||
|
this.callback = callback as EhClient.Callback<Any?>?
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun enqueue(scope: CoroutineScope) {
|
||||||
|
EhClient.enqueue(this, scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
@DelicateCoroutinesApi
|
||||||
|
fun enqueue() {
|
||||||
|
EhClient.enqueue(this, GlobalScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun enqueue(fragment: Fragment) {
|
||||||
|
enqueue(fragment.lifecycleScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun enqueue(activity: Activity) {
|
||||||
|
check(activity is FragmentActivity)
|
||||||
|
enqueue(activity.lifecycleScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainThread
|
||||||
|
fun cancel() {
|
||||||
|
if (isActive) {
|
||||||
|
job?.cancel()
|
||||||
|
callback?.onCancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,12 +24,10 @@ import com.hippo.util.ExceptionUtils
|
|||||||
import com.hippo.util.HashCodeUtils
|
import com.hippo.util.HashCodeUtils
|
||||||
import com.hippo.yorozuya.FileUtils
|
import com.hippo.yorozuya.FileUtils
|
||||||
import com.hippo.yorozuya.IOUtils
|
import com.hippo.yorozuya.IOUtils
|
||||||
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okio.BufferedSource
|
import okio.BufferedSource
|
||||||
@@ -193,7 +191,7 @@ object EhTagDatabase {
|
|||||||
@OptIn(DelicateCoroutinesApi::class)
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun update() {
|
fun update() {
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
launchIO {
|
||||||
updateInternal()
|
updateInternal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,146 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.data;
|
|
||||||
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import com.hippo.ehviewer.client.EhUrl;
|
|
||||||
import com.hippo.network.UrlBuilder;
|
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class FavListUrlBuilder implements Parcelable {
|
|
||||||
|
|
||||||
public static final int FAV_CAT_ALL = -1;
|
|
||||||
public static final int FAV_CAT_LOCAL = -2;
|
|
||||||
public static final Parcelable.Creator<FavListUrlBuilder> CREATOR = new Parcelable.Creator<>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FavListUrlBuilder createFromParcel(Parcel source) {
|
|
||||||
return new FavListUrlBuilder(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FavListUrlBuilder[] newArray(int size) {
|
|
||||||
return new FavListUrlBuilder[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private static final String TAG = FavListUrlBuilder.class.getSimpleName();
|
|
||||||
private String mPrev;
|
|
||||||
private String mNext;
|
|
||||||
private String mJumpTo;
|
|
||||||
private String mKeyword;
|
|
||||||
private int mFavCat = FAV_CAT_ALL;
|
|
||||||
|
|
||||||
public FavListUrlBuilder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected FavListUrlBuilder(Parcel in) {
|
|
||||||
this.mPrev = in.readString();
|
|
||||||
this.mNext = in.readString();
|
|
||||||
this.mJumpTo = in.readString();
|
|
||||||
this.mKeyword = in.readString();
|
|
||||||
this.mFavCat = in.readInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isValidFavCat(int favCat) {
|
|
||||||
return favCat >= 0 && favCat <= 9;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIndex(String index, boolean isNext) {
|
|
||||||
if (isNext) {
|
|
||||||
mNext = index;
|
|
||||||
mPrev = null;
|
|
||||||
} else {
|
|
||||||
mPrev = index;
|
|
||||||
mNext = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJumpTo(String jumpTo) {
|
|
||||||
mJumpTo = jumpTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getKeyword() {
|
|
||||||
return mKeyword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKeyword(String keyword) {
|
|
||||||
mKeyword = keyword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFavCat() {
|
|
||||||
return mFavCat;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFavCat(int favCat) {
|
|
||||||
mFavCat = favCat;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocalFavCat() {
|
|
||||||
return mFavCat == FAV_CAT_LOCAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String build() {
|
|
||||||
UrlBuilder ub = new UrlBuilder(EhUrl.getFavoritesUrl());
|
|
||||||
if (isValidFavCat(mFavCat)) {
|
|
||||||
ub.addQuery("favcat", Integer.toString(mFavCat));
|
|
||||||
} else if (mFavCat == FAV_CAT_ALL) {
|
|
||||||
ub.addQuery("favcat", "all");
|
|
||||||
}
|
|
||||||
if (!TextUtils.isEmpty(mKeyword)) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
||||||
ub.addQuery("f_search", URLEncoder.encode(mKeyword, StandardCharsets.UTF_8));
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
ub.addQuery("f_search", URLEncoder.encode(mKeyword, StandardCharsets.UTF_8.displayName()));
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mPrev != null && !mPrev.isEmpty()) {
|
|
||||||
ub.addQuery("prev", mPrev);
|
|
||||||
}
|
|
||||||
if (mNext != null && !mNext.isEmpty()) {
|
|
||||||
ub.addQuery("next", mNext);
|
|
||||||
}
|
|
||||||
if (mJumpTo != null && !mJumpTo.isEmpty()) {
|
|
||||||
ub.addQuery("seek", mJumpTo);
|
|
||||||
}
|
|
||||||
return ub.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
dest.writeString(this.mPrev);
|
|
||||||
dest.writeString(this.mNext);
|
|
||||||
dest.writeString(this.mJumpTo);
|
|
||||||
dest.writeString(this.mKeyword);
|
|
||||||
dest.writeInt(this.mFavCat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.client.data
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import com.hippo.ehviewer.client.EhUrl
|
||||||
|
import com.hippo.network.UrlBuilder
|
||||||
|
import com.hippo.util.encodeUTF8
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
class FavListUrlBuilder(
|
||||||
|
private var mPrev: String? = null,
|
||||||
|
private var mNext: String? = null,
|
||||||
|
var jumpTo: String? = null,
|
||||||
|
var keyword: String? = null,
|
||||||
|
var favCat: Int = FAV_CAT_ALL,
|
||||||
|
) : Parcelable {
|
||||||
|
fun setIndex(index: String?, isNext: Boolean) {
|
||||||
|
mNext = index.takeIf { isNext }
|
||||||
|
mPrev = index.takeUnless { isNext }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build(): String {
|
||||||
|
val ub = UrlBuilder(EhUrl.getFavoritesUrl())
|
||||||
|
if (isValidFavCat(favCat)) {
|
||||||
|
ub.addQuery("favcat", favCat.toString())
|
||||||
|
} else if (favCat == FAV_CAT_ALL) {
|
||||||
|
ub.addQuery("favcat", "all")
|
||||||
|
}
|
||||||
|
keyword?.takeIf { it.isNotBlank() }?.let { ub.addQuery("f_search", encodeUTF8(it)) }
|
||||||
|
mPrev?.takeIf { it.isNotEmpty() }?.let { ub.addQuery("prev", it) }
|
||||||
|
mNext?.takeIf { it.isNotEmpty() }?.let { ub.addQuery("next", it) }
|
||||||
|
jumpTo?.takeIf { it.isNotEmpty() }?.let { ub.addQuery("seek", it) }
|
||||||
|
return ub.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val FAV_CAT_ALL = -1
|
||||||
|
const val FAV_CAT_LOCAL = -2
|
||||||
|
fun isValidFavCat(favCat: Int): Boolean {
|
||||||
|
return favCat in 0..9
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.data;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
public class GalleryApiInfo implements Parcelable {
|
|
||||||
|
|
||||||
public static final Parcelable.Creator<GalleryApiInfo> CREATOR = new Parcelable.Creator<GalleryApiInfo>() {
|
|
||||||
@Override
|
|
||||||
public GalleryApiInfo createFromParcel(Parcel source) {
|
|
||||||
return new GalleryApiInfo(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GalleryApiInfo[] newArray(int size) {
|
|
||||||
return new GalleryApiInfo[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
public long gid;
|
|
||||||
public String token;
|
|
||||||
public String archiverKey;
|
|
||||||
public String title;
|
|
||||||
public String titleJpn;
|
|
||||||
public int category;
|
|
||||||
public String thumb;
|
|
||||||
public String uploader;
|
|
||||||
public long posted;
|
|
||||||
public int filecount;
|
|
||||||
public long filesize;
|
|
||||||
public boolean expunged;
|
|
||||||
public float rating;
|
|
||||||
public int torrentcount;
|
|
||||||
@Nullable
|
|
||||||
public String[] tags;
|
|
||||||
|
|
||||||
public GalleryApiInfo() {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected GalleryApiInfo(Parcel in) {
|
|
||||||
this.gid = in.readLong();
|
|
||||||
this.token = in.readString();
|
|
||||||
this.archiverKey = in.readString();
|
|
||||||
this.title = in.readString();
|
|
||||||
this.titleJpn = in.readString();
|
|
||||||
this.category = in.readInt();
|
|
||||||
this.thumb = in.readString();
|
|
||||||
this.uploader = in.readString();
|
|
||||||
this.posted = in.readLong();
|
|
||||||
this.filecount = in.readInt();
|
|
||||||
this.filesize = in.readLong();
|
|
||||||
this.expunged = in.readByte() != 0;
|
|
||||||
this.rating = in.readFloat();
|
|
||||||
this.torrentcount = in.readInt();
|
|
||||||
this.tags = in.createStringArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
dest.writeLong(this.gid);
|
|
||||||
dest.writeString(this.token);
|
|
||||||
dest.writeString(this.archiverKey);
|
|
||||||
dest.writeString(this.title);
|
|
||||||
dest.writeString(this.titleJpn);
|
|
||||||
dest.writeInt(this.category);
|
|
||||||
dest.writeString(this.thumb);
|
|
||||||
dest.writeString(this.uploader);
|
|
||||||
dest.writeLong(this.posted);
|
|
||||||
dest.writeInt(this.filecount);
|
|
||||||
dest.writeLong(this.filesize);
|
|
||||||
dest.writeByte(expunged ? (byte) 1 : (byte) 0);
|
|
||||||
dest.writeFloat(this.rating);
|
|
||||||
dest.writeInt(this.torrentcount);
|
|
||||||
dest.writeStringArray(this.tags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.client.data
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
class GalleryApiInfo(
|
||||||
|
var gid: Long = 0,
|
||||||
|
var token: String? = null,
|
||||||
|
var archiverKey: String? = null,
|
||||||
|
var title: String? = null,
|
||||||
|
var titleJpn: String? = null,
|
||||||
|
var category: Int = 0,
|
||||||
|
var thumb: String? = null,
|
||||||
|
var uploader: String? = null,
|
||||||
|
var posted: Long = 0,
|
||||||
|
var filecount: Int = 0,
|
||||||
|
var filesize: Long = 0,
|
||||||
|
var expunged: Boolean = false,
|
||||||
|
var rating: Float = 0f,
|
||||||
|
var torrentcount: Int = 0,
|
||||||
|
var tags: Array<String>?
|
||||||
|
) : Parcelable
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.data;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
|
|
||||||
public class GalleryComment implements Parcelable {
|
|
||||||
|
|
||||||
public static final Creator<GalleryComment> CREATOR = new Creator<GalleryComment>() {
|
|
||||||
@Override
|
|
||||||
public GalleryComment createFromParcel(Parcel source) {
|
|
||||||
return new GalleryComment(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GalleryComment[] newArray(int size) {
|
|
||||||
return new GalleryComment[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// 0 for uploader comment. can't vote
|
|
||||||
public long id;
|
|
||||||
public int score;
|
|
||||||
public boolean editable;
|
|
||||||
public boolean voteUpAble;
|
|
||||||
public boolean voteUpEd;
|
|
||||||
public boolean voteDownAble;
|
|
||||||
public boolean voteDownEd;
|
|
||||||
public boolean uploader;
|
|
||||||
public String voteState;
|
|
||||||
public long time;
|
|
||||||
public String user;
|
|
||||||
public String comment;
|
|
||||||
public long lastEdited;
|
|
||||||
|
|
||||||
public GalleryComment() {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected GalleryComment(Parcel in) {
|
|
||||||
this.id = in.readLong();
|
|
||||||
this.score = in.readInt();
|
|
||||||
this.editable = in.readByte() != 0;
|
|
||||||
this.voteUpAble = in.readByte() != 0;
|
|
||||||
this.voteUpEd = in.readByte() != 0;
|
|
||||||
this.voteDownAble = in.readByte() != 0;
|
|
||||||
this.voteDownEd = in.readByte() != 0;
|
|
||||||
this.uploader = in.readByte() != 0;
|
|
||||||
this.voteState = in.readString();
|
|
||||||
this.time = in.readLong();
|
|
||||||
this.user = in.readString();
|
|
||||||
this.comment = in.readString();
|
|
||||||
this.lastEdited = in.readLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
dest.writeLong(this.id);
|
|
||||||
dest.writeInt(this.score);
|
|
||||||
dest.writeByte(editable ? (byte) 1 : (byte) 0);
|
|
||||||
dest.writeByte(voteUpAble ? (byte) 1 : (byte) 0);
|
|
||||||
dest.writeByte(voteUpEd ? (byte) 1 : (byte) 0);
|
|
||||||
dest.writeByte(voteDownAble ? (byte) 1 : (byte) 0);
|
|
||||||
dest.writeByte(voteDownEd ? (byte) 1 : (byte) 0);
|
|
||||||
dest.writeByte(uploader ? (byte) 1 : (byte) 0);
|
|
||||||
dest.writeString(this.voteState);
|
|
||||||
dest.writeLong(this.time);
|
|
||||||
dest.writeString(this.user);
|
|
||||||
dest.writeString(this.comment);
|
|
||||||
dest.writeLong(this.lastEdited);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.client.data
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
class GalleryComment(
|
||||||
|
// 0 for uploader comment. can't vote
|
||||||
|
@JvmField
|
||||||
|
var id: Long = 0,
|
||||||
|
@JvmField
|
||||||
|
var score: Int = 0,
|
||||||
|
@JvmField
|
||||||
|
var editable: Boolean = false,
|
||||||
|
@JvmField
|
||||||
|
var voteUpAble: Boolean = false,
|
||||||
|
@JvmField
|
||||||
|
var voteUpEd: Boolean = false,
|
||||||
|
@JvmField
|
||||||
|
var voteDownAble: Boolean = false,
|
||||||
|
@JvmField
|
||||||
|
var voteDownEd: Boolean = false,
|
||||||
|
@JvmField
|
||||||
|
var uploader: Boolean = false,
|
||||||
|
@JvmField
|
||||||
|
var voteState: String? = null,
|
||||||
|
@JvmField
|
||||||
|
var time: Long = 0,
|
||||||
|
@JvmField
|
||||||
|
var user: String? = null,
|
||||||
|
@JvmField
|
||||||
|
var comment: String? = null,
|
||||||
|
@JvmField
|
||||||
|
var lastEdited: Long = 0
|
||||||
|
) : Parcelable
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.data;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class GalleryCommentList implements Parcelable {
|
|
||||||
|
|
||||||
public static final Creator<GalleryCommentList> CREATOR = new Creator<GalleryCommentList>() {
|
|
||||||
@Override
|
|
||||||
public GalleryCommentList createFromParcel(Parcel in) {
|
|
||||||
return new GalleryCommentList(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GalleryCommentList[] newArray(int size) {
|
|
||||||
return new GalleryCommentList[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
public GalleryComment[] comments;
|
|
||||||
public boolean hasMore;
|
|
||||||
|
|
||||||
public GalleryCommentList(GalleryComment[] comments, boolean hasMore) {
|
|
||||||
this.comments = comments;
|
|
||||||
this.hasMore = hasMore;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected GalleryCommentList(Parcel in) {
|
|
||||||
Parcelable[] array = in.readParcelableArray(getClass().getClassLoader());
|
|
||||||
if (array != null) {
|
|
||||||
comments = Arrays.copyOf(array, array.length, GalleryComment[].class);
|
|
||||||
} else {
|
|
||||||
comments = null;
|
|
||||||
}
|
|
||||||
hasMore = in.readByte() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
dest.writeParcelableArray(comments, flags);
|
|
||||||
dest.writeByte(hasMore ? (byte) 1 : (byte) 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+11
-12
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 Hippo Seven
|
* Copyright 2019 Hippo Seven
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -13,16 +13,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
package com.hippo.ehviewer.client.data
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.exception;
|
import android.os.Parcelable
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
public class EhException extends Exception {
|
@Parcelize
|
||||||
|
class GalleryCommentList(
|
||||||
public EhException(String detailMessage) {
|
@JvmField
|
||||||
super(detailMessage);
|
var comments: Array<GalleryComment>?,
|
||||||
}
|
@JvmField
|
||||||
|
var hasMore: Boolean
|
||||||
public EhException(String detailMessage, Throwable cause) {
|
) : Parcelable
|
||||||
super(detailMessage, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.data;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class GalleryDetail extends GalleryInfo {
|
|
||||||
|
|
||||||
public static final Creator<GalleryDetail> CREATOR = new Creator<GalleryDetail>() {
|
|
||||||
@Override
|
|
||||||
public GalleryDetail createFromParcel(Parcel source) {
|
|
||||||
return new GalleryDetail(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GalleryDetail[] newArray(int size) {
|
|
||||||
return new GalleryDetail[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
public long apiUid = -1L;
|
|
||||||
public String apiKey;
|
|
||||||
public int torrentCount;
|
|
||||||
public String torrentUrl;
|
|
||||||
public String archiveUrl;
|
|
||||||
public String parent;
|
|
||||||
public ArrayList<GalleryInfo> newerVersions = new ArrayList<>();
|
|
||||||
public String visible;
|
|
||||||
public String language;
|
|
||||||
public String size;
|
|
||||||
public int pages;
|
|
||||||
public int favoriteCount;
|
|
||||||
public boolean isFavorited;
|
|
||||||
public int ratingCount;
|
|
||||||
public GalleryTagGroup[] tags;
|
|
||||||
public GalleryCommentList comments;
|
|
||||||
public int previewPages;
|
|
||||||
public PreviewSet previewSet;
|
|
||||||
|
|
||||||
public GalleryDetail() {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected GalleryDetail(Parcel in) {
|
|
||||||
super(in);
|
|
||||||
this.torrentCount = in.readInt();
|
|
||||||
this.torrentUrl = in.readString();
|
|
||||||
this.archiveUrl = in.readString();
|
|
||||||
this.parent = in.readString();
|
|
||||||
//noinspection unchecked
|
|
||||||
this.newerVersions = in.readArrayList(GalleryInfo.class.getClassLoader());
|
|
||||||
this.visible = in.readString();
|
|
||||||
this.language = in.readString();
|
|
||||||
this.size = in.readString();
|
|
||||||
this.pages = in.readInt();
|
|
||||||
this.favoriteCount = in.readInt();
|
|
||||||
this.isFavorited = in.readByte() != 0;
|
|
||||||
this.ratingCount = in.readInt();
|
|
||||||
Parcelable[] array = in.readParcelableArray(GalleryTagGroup.class.getClassLoader());
|
|
||||||
if (array != null) {
|
|
||||||
this.tags = Arrays.copyOf(array, array.length, GalleryTagGroup[].class);
|
|
||||||
} else {
|
|
||||||
this.tags = null;
|
|
||||||
}
|
|
||||||
this.comments = in.readParcelable(getClass().getClassLoader());
|
|
||||||
this.previewPages = in.readInt();
|
|
||||||
this.previewSet = in.readParcelable(PreviewSet.class.getClassLoader());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
super.writeToParcel(dest, flags);
|
|
||||||
dest.writeInt(this.torrentCount);
|
|
||||||
dest.writeString(this.torrentUrl);
|
|
||||||
dest.writeString(this.archiveUrl);
|
|
||||||
dest.writeString(this.parent);
|
|
||||||
dest.writeList(this.newerVersions);
|
|
||||||
dest.writeString(this.visible);
|
|
||||||
dest.writeString(this.language);
|
|
||||||
dest.writeString(this.size);
|
|
||||||
dest.writeInt(this.pages);
|
|
||||||
dest.writeInt(this.favoriteCount);
|
|
||||||
dest.writeByte(isFavorited ? (byte) 1 : (byte) 0);
|
|
||||||
dest.writeInt(this.ratingCount);
|
|
||||||
dest.writeParcelableArray(this.tags, flags);
|
|
||||||
dest.writeParcelable(this.comments, flags);
|
|
||||||
dest.writeInt(this.previewPages);
|
|
||||||
dest.writeParcelable(previewSet, flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.client.data
|
||||||
|
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize // This is wrong Parcelize usage, TODO: use delegate and move galleryinfo to primary constructor
|
||||||
|
class GalleryDetail(
|
||||||
|
@JvmField
|
||||||
|
var apiUid: Long = -1L,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var apiKey: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var torrentCount: Int = 0,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var torrentUrl: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var archiveUrl: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var parent: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var newerVersions: ArrayList<GalleryInfo> = ArrayList(),
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var visible: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var language: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var size: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var favoriteCount: Int = 0,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var isFavorited: Boolean = false,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var ratingCount: Int = 0,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var tags: Array<GalleryTagGroup>? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var comments: GalleryCommentList? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var previewPages: Int = 0,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var previewSet: PreviewSet? = null,
|
||||||
|
) : GalleryInfo()
|
||||||
@@ -1,247 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.data;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.room.ColumnInfo;
|
|
||||||
import androidx.room.Ignore;
|
|
||||||
import androidx.room.PrimaryKey;
|
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class GalleryInfo implements Parcelable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ISO 639-1
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public static final String S_LANG_JA = "JA";
|
|
||||||
public static final String S_LANG_EN = "EN";
|
|
||||||
public static final String S_LANG_ZH = "ZH";
|
|
||||||
public static final String S_LANG_NL = "NL";
|
|
||||||
public static final String S_LANG_FR = "FR";
|
|
||||||
public static final String S_LANG_DE = "DE";
|
|
||||||
public static final String S_LANG_HU = "HU";
|
|
||||||
public static final String S_LANG_IT = "IT";
|
|
||||||
public static final String S_LANG_KO = "KO";
|
|
||||||
public static final String S_LANG_PL = "PL";
|
|
||||||
public static final String S_LANG_PT = "PT";
|
|
||||||
public static final String S_LANG_RU = "RU";
|
|
||||||
public static final String S_LANG_ES = "ES";
|
|
||||||
public static final String S_LANG_TH = "TH";
|
|
||||||
public static final String S_LANG_VI = "VI";
|
|
||||||
|
|
||||||
public static final String[] S_LANGS = {
|
|
||||||
S_LANG_EN,
|
|
||||||
S_LANG_ZH,
|
|
||||||
S_LANG_ES,
|
|
||||||
S_LANG_KO,
|
|
||||||
S_LANG_RU,
|
|
||||||
S_LANG_FR,
|
|
||||||
S_LANG_PT,
|
|
||||||
S_LANG_TH,
|
|
||||||
S_LANG_DE,
|
|
||||||
S_LANG_IT,
|
|
||||||
S_LANG_VI,
|
|
||||||
S_LANG_PL,
|
|
||||||
S_LANG_HU,
|
|
||||||
S_LANG_NL,
|
|
||||||
};
|
|
||||||
|
|
||||||
public static final Pattern[] S_LANG_PATTERNS = {
|
|
||||||
Pattern.compile("[(\\[]eng(?:lish)?[)\\]]|英訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
// [((\[]ch(?:inese)?[))\]]|[汉漢]化|中[国國][语語]|中文|中国翻訳
|
|
||||||
Pattern.compile("[(\uFF08\\[]ch(?:inese)?[)\uFF09\\]]|[汉漢]化|中[国國][语語]|中文|中国翻訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
Pattern.compile("[(\\[]spanish[)\\]]|[(\\[]Español[)\\]]|スペイン翻訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
Pattern.compile("[(\\[]korean?[)\\]]|韓国翻訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
Pattern.compile("[(\\[]rus(?:sian)?[)\\]]|ロシア翻訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
Pattern.compile("[(\\[]fr(?:ench)?[)\\]]|フランス翻訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
Pattern.compile("[(\\[]portuguese|ポルトガル翻訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
Pattern.compile("[(\\[]thai(?: ภาษาไทย)?[)\\]]|แปลไทย|タイ翻訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
Pattern.compile("[(\\[]german[)\\]]|ドイツ翻訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
Pattern.compile("[(\\[]italiano?[)\\]]|イタリア翻訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
Pattern.compile("[(\\[]vietnamese(?: Tiếng Việt)?[)\\]]|ベトナム翻訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
Pattern.compile("[(\\[]polish[)\\]]|ポーランド翻訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
Pattern.compile("[(\\[]hun(?:garian)?[)\\]]|ハンガリー翻訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
Pattern.compile("[(\\[]dutch[)\\]]|オランダ翻訳", Pattern.CASE_INSENSITIVE),
|
|
||||||
};
|
|
||||||
|
|
||||||
public static final String[] S_LANG_TAGS = {
|
|
||||||
"language:english",
|
|
||||||
"language:chinese",
|
|
||||||
"language:spanish",
|
|
||||||
"language:korean",
|
|
||||||
"language:russian",
|
|
||||||
"language:french",
|
|
||||||
"language:portuguese",
|
|
||||||
"language:thai",
|
|
||||||
"language:german",
|
|
||||||
"language:italian",
|
|
||||||
"language:vietnamese",
|
|
||||||
"language:polish",
|
|
||||||
"language:hungarian",
|
|
||||||
"language:dutch",
|
|
||||||
};
|
|
||||||
public static final Parcelable.Creator<GalleryInfo> CREATOR = new Parcelable.Creator<GalleryInfo>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GalleryInfo createFromParcel(Parcel source) {
|
|
||||||
return new GalleryInfo(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GalleryInfo[] newArray(int size) {
|
|
||||||
return new GalleryInfo[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@PrimaryKey
|
|
||||||
@ColumnInfo(name = "GID")
|
|
||||||
public long gid;
|
|
||||||
@ColumnInfo(name = "TOKEN")
|
|
||||||
public String token;
|
|
||||||
@ColumnInfo(name = "TITLE")
|
|
||||||
public String title;
|
|
||||||
@ColumnInfo(name = "TITLE_JPN")
|
|
||||||
public String titleJpn;
|
|
||||||
@ColumnInfo(name = "THUMB")
|
|
||||||
public String thumb;
|
|
||||||
@ColumnInfo(name = "CATEGORY")
|
|
||||||
public int category;
|
|
||||||
@ColumnInfo(name = "POSTED")
|
|
||||||
public String posted;
|
|
||||||
@ColumnInfo(name = "UPLOADER")
|
|
||||||
public String uploader;
|
|
||||||
@Ignore
|
|
||||||
public boolean disowned;
|
|
||||||
@ColumnInfo(name = "RATING")
|
|
||||||
public float rating;
|
|
||||||
@Ignore
|
|
||||||
public boolean rated;
|
|
||||||
@Nullable
|
|
||||||
@Ignore
|
|
||||||
public String[] simpleTags;
|
|
||||||
@Ignore
|
|
||||||
public int pages;
|
|
||||||
@Ignore
|
|
||||||
public int thumbWidth;
|
|
||||||
@Ignore
|
|
||||||
public int thumbHeight;
|
|
||||||
@Ignore
|
|
||||||
public int spanSize;
|
|
||||||
@Ignore
|
|
||||||
public int spanIndex;
|
|
||||||
@Ignore
|
|
||||||
public int spanGroupIndex;
|
|
||||||
/**
|
|
||||||
* language from title
|
|
||||||
*/
|
|
||||||
@ColumnInfo(name = "SIMPLE_LANGUAGE")
|
|
||||||
public String simpleLanguage;
|
|
||||||
@Ignore
|
|
||||||
public int favoriteSlot = -2;
|
|
||||||
@Ignore
|
|
||||||
public String favoriteName;
|
|
||||||
|
|
||||||
public GalleryInfo() {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected GalleryInfo(Parcel in) {
|
|
||||||
this.gid = in.readLong();
|
|
||||||
this.token = in.readString();
|
|
||||||
this.title = in.readString();
|
|
||||||
this.titleJpn = in.readString();
|
|
||||||
this.thumb = in.readString();
|
|
||||||
this.category = in.readInt();
|
|
||||||
this.posted = in.readString();
|
|
||||||
this.uploader = in.readString();
|
|
||||||
this.rating = in.readFloat();
|
|
||||||
this.rated = in.readByte() != 0;
|
|
||||||
this.simpleLanguage = in.readString();
|
|
||||||
this.simpleTags = in.createStringArray();
|
|
||||||
this.thumbWidth = in.readInt();
|
|
||||||
this.thumbHeight = in.readInt();
|
|
||||||
this.spanSize = in.readInt();
|
|
||||||
this.spanIndex = in.readInt();
|
|
||||||
this.spanGroupIndex = in.readInt();
|
|
||||||
this.favoriteSlot = in.readInt();
|
|
||||||
this.favoriteName = in.readString();
|
|
||||||
this.disowned = in.readByte() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void generateSLang() {
|
|
||||||
if (simpleTags != null) {
|
|
||||||
generateSLangFromTags();
|
|
||||||
}
|
|
||||||
if (simpleLanguage == null && title != null) {
|
|
||||||
generateSLangFromTitle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateSLangFromTags() {
|
|
||||||
assert simpleTags != null;
|
|
||||||
for (String tag : simpleTags) {
|
|
||||||
for (int i = 0; i < S_LANGS.length; i++) {
|
|
||||||
if (S_LANG_TAGS[i].equals(tag)) {
|
|
||||||
simpleLanguage = S_LANGS[i];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateSLangFromTitle() {
|
|
||||||
for (int i = 0; i < S_LANGS.length; i++) {
|
|
||||||
if (S_LANG_PATTERNS[i].matcher(title).find()) {
|
|
||||||
simpleLanguage = S_LANGS[i];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
simpleLanguage = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
dest.writeLong(this.gid);
|
|
||||||
dest.writeString(this.token);
|
|
||||||
dest.writeString(this.title);
|
|
||||||
dest.writeString(this.titleJpn);
|
|
||||||
dest.writeString(this.thumb);
|
|
||||||
dest.writeInt(this.category);
|
|
||||||
dest.writeString(this.posted);
|
|
||||||
dest.writeString(this.uploader);
|
|
||||||
dest.writeFloat(this.rating);
|
|
||||||
dest.writeByte(this.rated ? (byte) 1 : (byte) 0);
|
|
||||||
dest.writeString(this.simpleLanguage);
|
|
||||||
dest.writeStringArray(this.simpleTags);
|
|
||||||
dest.writeInt(this.thumbWidth);
|
|
||||||
dest.writeInt(this.thumbHeight);
|
|
||||||
dest.writeInt(this.spanSize);
|
|
||||||
dest.writeInt(this.spanIndex);
|
|
||||||
dest.writeInt(this.spanGroupIndex);
|
|
||||||
dest.writeInt(this.favoriteSlot);
|
|
||||||
dest.writeString(this.favoriteName);
|
|
||||||
dest.writeByte(this.disowned ? (byte) 1 : (byte) 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.client.data
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Ignore
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
open class GalleryInfo(
|
||||||
|
@JvmField
|
||||||
|
@PrimaryKey
|
||||||
|
@ColumnInfo(name = "GID")
|
||||||
|
var gid: Long = 0,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "TOKEN")
|
||||||
|
var token: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "TITLE")
|
||||||
|
var title: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "TITLE_JPN")
|
||||||
|
var titleJpn: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "THUMB")
|
||||||
|
var thumb: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "CATEGORY")
|
||||||
|
var category: Int = 0,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "POSTED")
|
||||||
|
var posted: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "UPLOADER")
|
||||||
|
var uploader: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Ignore
|
||||||
|
var disowned: Boolean = false,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "RATING")
|
||||||
|
var rating: Float = 0f,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Ignore
|
||||||
|
var rated: Boolean = false,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Ignore
|
||||||
|
var simpleTags: Array<String>? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Ignore
|
||||||
|
var pages: Int = 0,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Ignore
|
||||||
|
var thumbWidth: Int = 0,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Ignore
|
||||||
|
var thumbHeight: Int = 0,
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
var spanSize: Int = 0,
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
var spanIndex: Int = 0,
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
var spanGroupIndex: Int = 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* language from title
|
||||||
|
*/
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "SIMPLE_LANGUAGE")
|
||||||
|
var simpleLanguage: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Ignore
|
||||||
|
var favoriteSlot: Int = -2,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Ignore
|
||||||
|
var favoriteName: String? = null
|
||||||
|
|
||||||
|
) : Parcelable {
|
||||||
|
fun generateSLang() {
|
||||||
|
simpleLanguage = simpleTags?.let { generateSLangFromTags(it) } ?: title?.let { generateSLangFromTitle(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateSLangFromTags(simpleTags: Array<String>): String? {
|
||||||
|
for (tag in simpleTags) {
|
||||||
|
for (i in S_LANGS.indices) {
|
||||||
|
if (S_LANG_TAGS[i] == tag) {
|
||||||
|
return S_LANGS[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateSLangFromTitle(title: String): String? {
|
||||||
|
for (i in S_LANGS.indices) {
|
||||||
|
if (S_LANG_PATTERNS[i].matcher(title).find()) {
|
||||||
|
return S_LANGS[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* ISO 639-1
|
||||||
|
*/
|
||||||
|
const val S_LANG_JA = "JA"
|
||||||
|
const val S_LANG_EN = "EN"
|
||||||
|
const val S_LANG_ZH = "ZH"
|
||||||
|
const val S_LANG_NL = "NL"
|
||||||
|
const val S_LANG_FR = "FR"
|
||||||
|
const val S_LANG_DE = "DE"
|
||||||
|
const val S_LANG_HU = "HU"
|
||||||
|
const val S_LANG_IT = "IT"
|
||||||
|
const val S_LANG_KO = "KO"
|
||||||
|
const val S_LANG_PL = "PL"
|
||||||
|
const val S_LANG_PT = "PT"
|
||||||
|
const val S_LANG_RU = "RU"
|
||||||
|
const val S_LANG_ES = "ES"
|
||||||
|
const val S_LANG_TH = "TH"
|
||||||
|
const val S_LANG_VI = "VI"
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val S_LANGS = arrayOf(
|
||||||
|
S_LANG_EN,
|
||||||
|
S_LANG_ZH,
|
||||||
|
S_LANG_ES,
|
||||||
|
S_LANG_KO,
|
||||||
|
S_LANG_RU,
|
||||||
|
S_LANG_FR,
|
||||||
|
S_LANG_PT,
|
||||||
|
S_LANG_TH,
|
||||||
|
S_LANG_DE,
|
||||||
|
S_LANG_IT,
|
||||||
|
S_LANG_VI,
|
||||||
|
S_LANG_PL,
|
||||||
|
S_LANG_HU,
|
||||||
|
S_LANG_NL
|
||||||
|
)
|
||||||
|
val S_LANG_PATTERNS = arrayOf(
|
||||||
|
Pattern.compile(
|
||||||
|
"[(\\[]eng(?:lish)?[)\\]]|英訳",
|
||||||
|
Pattern.CASE_INSENSITIVE
|
||||||
|
), // [((\[]ch(?:inese)?[))\]]|[汉漢]化|中[国國][语語]|中文|中国翻訳
|
||||||
|
Pattern.compile(
|
||||||
|
"[(\uFF08\\[]ch(?:inese)?[)\uFF09\\]]|[汉漢]化|中[国國][语語]|中文|中国翻訳",
|
||||||
|
Pattern.CASE_INSENSITIVE
|
||||||
|
),
|
||||||
|
Pattern.compile(
|
||||||
|
"[(\\[]spanish[)\\]]|[(\\[]Español[)\\]]|スペイン翻訳",
|
||||||
|
Pattern.CASE_INSENSITIVE
|
||||||
|
),
|
||||||
|
Pattern.compile("[(\\[]korean?[)\\]]|韓国翻訳", Pattern.CASE_INSENSITIVE),
|
||||||
|
Pattern.compile("[(\\[]rus(?:sian)?[)\\]]|ロシア翻訳", Pattern.CASE_INSENSITIVE),
|
||||||
|
Pattern.compile("[(\\[]fr(?:ench)?[)\\]]|フランス翻訳", Pattern.CASE_INSENSITIVE),
|
||||||
|
Pattern.compile("[(\\[]portuguese|ポルトガル翻訳", Pattern.CASE_INSENSITIVE),
|
||||||
|
Pattern.compile(
|
||||||
|
"[(\\[]thai(?: ภาษาไทย)?[)\\]]|แปลไทย|タイ翻訳",
|
||||||
|
Pattern.CASE_INSENSITIVE
|
||||||
|
),
|
||||||
|
Pattern.compile("[(\\[]german[)\\]]|ドイツ翻訳", Pattern.CASE_INSENSITIVE),
|
||||||
|
Pattern.compile("[(\\[]italiano?[)\\]]|イタリア翻訳", Pattern.CASE_INSENSITIVE),
|
||||||
|
Pattern.compile(
|
||||||
|
"[(\\[]vietnamese(?: Tiếng Việt)?[)\\]]|ベトナム翻訳",
|
||||||
|
Pattern.CASE_INSENSITIVE
|
||||||
|
),
|
||||||
|
Pattern.compile("[(\\[]polish[)\\]]|ポーランド翻訳", Pattern.CASE_INSENSITIVE),
|
||||||
|
Pattern.compile("[(\\[]hun(?:garian)?[)\\]]|ハンガリー翻訳", Pattern.CASE_INSENSITIVE),
|
||||||
|
Pattern.compile("[(\\[]dutch[)\\]]|オランダ翻訳", Pattern.CASE_INSENSITIVE)
|
||||||
|
)
|
||||||
|
val S_LANG_TAGS = arrayOf(
|
||||||
|
"language:english",
|
||||||
|
"language:chinese",
|
||||||
|
"language:spanish",
|
||||||
|
"language:korean",
|
||||||
|
"language:russian",
|
||||||
|
"language:french",
|
||||||
|
"language:portuguese",
|
||||||
|
"language:thai",
|
||||||
|
"language:german",
|
||||||
|
"language:italian",
|
||||||
|
"language:vietnamese",
|
||||||
|
"language:polish",
|
||||||
|
"language:hungarian",
|
||||||
|
"language:dutch"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.data;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
|
|
||||||
import com.hippo.widget.LoadImageView;
|
|
||||||
|
|
||||||
public class GalleryPreview implements Parcelable {
|
|
||||||
|
|
||||||
public static final Parcelable.Creator<GalleryPreview> CREATOR = new Parcelable.Creator<GalleryPreview>() {
|
|
||||||
@Override
|
|
||||||
public GalleryPreview createFromParcel(Parcel source) {
|
|
||||||
return new GalleryPreview(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GalleryPreview[] newArray(int size) {
|
|
||||||
return new GalleryPreview[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
String imageKey;
|
|
||||||
String imageUrl;
|
|
||||||
String pageUrl;
|
|
||||||
int position;
|
|
||||||
int offsetX = Integer.MIN_VALUE;
|
|
||||||
int offsetY = Integer.MIN_VALUE;
|
|
||||||
int clipWidth = Integer.MIN_VALUE;
|
|
||||||
int clipHeight = Integer.MIN_VALUE;
|
|
||||||
|
|
||||||
public GalleryPreview() {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected GalleryPreview(Parcel in) {
|
|
||||||
this.imageUrl = in.readString();
|
|
||||||
this.pageUrl = in.readString();
|
|
||||||
this.position = in.readInt();
|
|
||||||
this.offsetX = in.readInt();
|
|
||||||
this.offsetY = in.readInt();
|
|
||||||
this.clipWidth = in.readInt();
|
|
||||||
this.clipHeight = in.readInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load(LoadImageView view) {
|
|
||||||
view.setClip(offsetX, offsetY, clipWidth, clipHeight);
|
|
||||||
view.load(imageKey, imageUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
dest.writeString(this.imageUrl);
|
|
||||||
dest.writeString(this.pageUrl);
|
|
||||||
dest.writeInt(this.position);
|
|
||||||
dest.writeInt(this.offsetX);
|
|
||||||
dest.writeInt(this.offsetY);
|
|
||||||
dest.writeInt(this.clipWidth);
|
|
||||||
dest.writeInt(this.clipHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.client.data
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import com.hippo.widget.LoadImageView
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
class GalleryPreview(
|
||||||
|
@JvmField
|
||||||
|
var imageKey: String? = null,
|
||||||
|
@JvmField
|
||||||
|
var imageUrl: String? = null,
|
||||||
|
@JvmField
|
||||||
|
var pageUrl: String? = null,
|
||||||
|
@JvmField
|
||||||
|
var position: Int = 0,
|
||||||
|
@JvmField
|
||||||
|
var offsetX: Int = Int.MIN_VALUE,
|
||||||
|
@JvmField
|
||||||
|
var offsetY: Int = Int.MIN_VALUE,
|
||||||
|
@JvmField
|
||||||
|
var clipWidth: Int = Int.MIN_VALUE,
|
||||||
|
@JvmField
|
||||||
|
var clipHeight: Int = Int.MIN_VALUE,
|
||||||
|
) : Parcelable {
|
||||||
|
fun load(view: LoadImageView) {
|
||||||
|
view.setClip(offsetX, offsetY, clipWidth, clipHeight)
|
||||||
|
view.load(imageKey!!, imageUrl!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.data;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
// TODO Add url field?
|
|
||||||
public class GalleryTagGroup implements Parcelable {
|
|
||||||
|
|
||||||
public static final Parcelable.Creator<GalleryTagGroup> CREATOR = new Parcelable.Creator<GalleryTagGroup>() {
|
|
||||||
@Override
|
|
||||||
public GalleryTagGroup createFromParcel(Parcel source) {
|
|
||||||
return new GalleryTagGroup(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GalleryTagGroup[] newArray(int size) {
|
|
||||||
return new GalleryTagGroup[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private final ArrayList<String> mTagList;
|
|
||||||
public String groupName;
|
|
||||||
|
|
||||||
public GalleryTagGroup() {
|
|
||||||
mTagList = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected GalleryTagGroup(Parcel in) {
|
|
||||||
this.groupName = in.readString();
|
|
||||||
this.mTagList = in.createStringArrayList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addTag(String tag) {
|
|
||||||
mTagList.add(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
|
||||||
return mTagList.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTagAt(int position) {
|
|
||||||
return mTagList.get(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
dest.writeString(this.groupName);
|
|
||||||
dest.writeStringList(this.mTagList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+16
-14
@@ -13,24 +13,26 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
package com.hippo.ehviewer.client.data
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.exception;
|
import android.os.Parcelable
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
public class ParseException extends EhException {
|
@Parcelize
|
||||||
|
class GalleryTagGroup(
|
||||||
private final String mBody;
|
private val mTagList: ArrayList<String> = arrayListOf(),
|
||||||
|
@JvmField
|
||||||
public ParseException(String detailMessage, String body) {
|
var groupName: String? = null
|
||||||
super(detailMessage);
|
) : Parcelable {
|
||||||
mBody = body;
|
fun addTag(tag: String) {
|
||||||
|
mTagList.add(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParseException(String detailMessage, String body, Throwable cause) {
|
fun size(): Int {
|
||||||
super(detailMessage, cause);
|
return mTagList.size
|
||||||
mBody = body;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBody() {
|
fun getTagAt(position: Int): String {
|
||||||
return mBody;
|
return mTagList[position]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.data;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
|
|
||||||
import com.hippo.ehviewer.client.EhCacheKeyFactory;
|
|
||||||
import com.hippo.widget.LoadImageView;
|
|
||||||
import com.hippo.yorozuya.collect.IntList;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class LargePreviewSet extends PreviewSet {
|
|
||||||
|
|
||||||
public static final Parcelable.Creator<LargePreviewSet> CREATOR = new Parcelable.Creator<LargePreviewSet>() {
|
|
||||||
@Override
|
|
||||||
public LargePreviewSet createFromParcel(Parcel source) {
|
|
||||||
return new LargePreviewSet(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LargePreviewSet[] newArray(int size) {
|
|
||||||
return new LargePreviewSet[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private final IntList mPositionList;
|
|
||||||
private final ArrayList<String> mImageUrlList;
|
|
||||||
private final ArrayList<String> mPageUrlList;
|
|
||||||
|
|
||||||
public LargePreviewSet() {
|
|
||||||
mPositionList = new IntList();
|
|
||||||
mImageUrlList = new ArrayList<>();
|
|
||||||
mPageUrlList = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected LargePreviewSet(Parcel in) {
|
|
||||||
this.mPositionList = in.readParcelable(IntList.class.getClassLoader());
|
|
||||||
this.mImageUrlList = in.createStringArrayList();
|
|
||||||
this.mPageUrlList = in.createStringArrayList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addItem(int index, String imageUrl, String pageUrl) {
|
|
||||||
mPositionList.add(index);
|
|
||||||
mImageUrlList.add(imageUrl);
|
|
||||||
mPageUrlList.add(pageUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return mImageUrlList.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPosition(int index) {
|
|
||||||
return mPositionList.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPageUrlAt(int index) {
|
|
||||||
return mPageUrlList.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GalleryPreview getGalleryPreview(long gid, int index) {
|
|
||||||
GalleryPreview galleryPreview = new GalleryPreview();
|
|
||||||
galleryPreview.position = mPositionList.get(index);
|
|
||||||
galleryPreview.imageKey = EhCacheKeyFactory.getLargePreviewKey(gid, galleryPreview.position);
|
|
||||||
galleryPreview.imageUrl = mImageUrlList.get(index);
|
|
||||||
galleryPreview.pageUrl = mPageUrlList.get(index);
|
|
||||||
return galleryPreview;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(LoadImageView view, long gid, int index) {
|
|
||||||
view.resetClip();
|
|
||||||
view.load(EhCacheKeyFactory.getLargePreviewKey(gid, mPositionList.get(index)),
|
|
||||||
mImageUrlList.get(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
dest.writeParcelable(this.mPositionList, flags);
|
|
||||||
dest.writeStringList(this.mImageUrlList);
|
|
||||||
dest.writeStringList(this.mPageUrlList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.client.data
|
||||||
|
|
||||||
|
import com.hippo.ehviewer.client.EhCacheKeyFactory
|
||||||
|
import com.hippo.widget.LoadImageView
|
||||||
|
import com.hippo.yorozuya.collect.IntList
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
class LargePreviewSet(
|
||||||
|
private val mPositionList: IntList = IntList(),
|
||||||
|
private val mImageUrlList: ArrayList<String> = ArrayList(),
|
||||||
|
private val mPageUrlList: ArrayList<String> = ArrayList()
|
||||||
|
) : PreviewSet() {
|
||||||
|
|
||||||
|
fun addItem(index: Int, imageUrl: String, pageUrl: String) {
|
||||||
|
mPositionList.add(index)
|
||||||
|
mImageUrlList.add(imageUrl)
|
||||||
|
mPageUrlList.add(pageUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun size(): Int {
|
||||||
|
return mImageUrlList.size
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPosition(index: Int): Int {
|
||||||
|
return mPositionList[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPageUrlAt(index: Int): String {
|
||||||
|
return mPageUrlList[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getGalleryPreview(gid: Long, index: Int): GalleryPreview {
|
||||||
|
val galleryPreview = GalleryPreview()
|
||||||
|
galleryPreview.position = mPositionList[index]
|
||||||
|
galleryPreview.imageKey = EhCacheKeyFactory.getLargePreviewKey(gid, galleryPreview.position)
|
||||||
|
galleryPreview.imageUrl = mImageUrlList[index]
|
||||||
|
galleryPreview.pageUrl = mPageUrlList[index]
|
||||||
|
return galleryPreview
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun load(view: LoadImageView, gid: Long, index: Int) {
|
||||||
|
view.resetClip()
|
||||||
|
view.load(
|
||||||
|
EhCacheKeyFactory.getLargePreviewKey(gid, mPositionList[index]),
|
||||||
|
mImageUrlList[index]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,9 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.hippo.ehviewer.client.data
|
package com.hippo.ehviewer.client.data
|
||||||
|
|
||||||
import android.os.Parcel
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.os.Parcelable.Creator
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import androidx.annotation.IntDef
|
import androidx.annotation.IntDef
|
||||||
import com.hippo.ehviewer.client.EhConfig
|
import com.hippo.ehviewer.client.EhConfig
|
||||||
@@ -26,49 +24,31 @@ import com.hippo.ehviewer.client.EhUtils
|
|||||||
import com.hippo.ehviewer.dao.QuickSearch
|
import com.hippo.ehviewer.dao.QuickSearch
|
||||||
import com.hippo.ehviewer.widget.AdvanceSearchTable
|
import com.hippo.ehviewer.widget.AdvanceSearchTable
|
||||||
import com.hippo.network.UrlBuilder
|
import com.hippo.network.UrlBuilder
|
||||||
|
import com.hippo.util.encodeUTF8
|
||||||
import com.hippo.yorozuya.NumberUtils
|
import com.hippo.yorozuya.NumberUtils
|
||||||
import com.hippo.yorozuya.StringUtils
|
import com.hippo.yorozuya.StringUtils
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
import java.io.UnsupportedEncodingException
|
import java.io.UnsupportedEncodingException
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
import java.net.URLEncoder
|
|
||||||
|
|
||||||
open class ListUrlBuilder : Cloneable, Parcelable {
|
@Parcelize
|
||||||
@get:Mode
|
open class ListUrlBuilder(
|
||||||
@Mode
|
@get:Mode @Mode var mode: Int = MODE_NORMAL,
|
||||||
var mode = MODE_NORMAL
|
private var mPrev: String? = null,
|
||||||
private var mPrev: String? = null
|
private var mNext: String? = null,
|
||||||
private var mNext: String? = null
|
private var mJumpTo: String? = null,
|
||||||
private var mJumpTo: String? = null
|
var category: Int = EhUtils.NONE,
|
||||||
var category = EhUtils.NONE
|
private var mKeyword: String? = null,
|
||||||
private var mKeyword: String? = null
|
private var mSHash: String? = null,
|
||||||
private var mSHash: String? = null
|
var advanceSearch: Int = -1,
|
||||||
var advanceSearch = -1
|
var minRating: Int = -1,
|
||||||
var minRating = -1
|
var pageFrom: Int = -1,
|
||||||
var pageFrom = -1
|
var pageTo: Int = -1,
|
||||||
var pageTo = -1
|
var imagePath: String? = null,
|
||||||
var imagePath: String? = null
|
var isUseSimilarityScan: Boolean = false,
|
||||||
var isUseSimilarityScan = false
|
var isOnlySearchCovers: Boolean = false,
|
||||||
var isOnlySearchCovers = false
|
var isShowExpunged: Boolean = false,
|
||||||
var isShowExpunged = false
|
) : Cloneable, Parcelable {
|
||||||
|
|
||||||
constructor()
|
|
||||||
protected constructor(parcel: Parcel) {
|
|
||||||
mode = parcel.readInt()
|
|
||||||
mPrev = parcel.readString()
|
|
||||||
mNext = parcel.readString()
|
|
||||||
mJumpTo = parcel.readString()
|
|
||||||
this.category = parcel.readInt()
|
|
||||||
mKeyword = parcel.readString()
|
|
||||||
advanceSearch = parcel.readInt()
|
|
||||||
minRating = parcel.readInt()
|
|
||||||
pageFrom = parcel.readInt()
|
|
||||||
pageTo = parcel.readInt()
|
|
||||||
imagePath = parcel.readString()
|
|
||||||
isUseSimilarityScan = parcel.readByte().toInt() != 0
|
|
||||||
isOnlySearchCovers = parcel.readByte().toInt() != 0
|
|
||||||
isShowExpunged = parcel.readByte().toInt() != 0
|
|
||||||
mSHash = parcel.readString()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
mode = MODE_NORMAL
|
mode = MODE_NORMAL
|
||||||
@@ -88,22 +68,9 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
|||||||
mSHash = null
|
mSHash = null
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun clone(): ListUrlBuilder {
|
|
||||||
return try {
|
|
||||||
super.clone() as ListUrlBuilder
|
|
||||||
} catch (e: CloneNotSupportedException) {
|
|
||||||
throw IllegalStateException(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setIndex(index: String?, isNext: Boolean = true) {
|
fun setIndex(index: String?, isNext: Boolean = true) {
|
||||||
if (isNext) {
|
mNext = index?.takeIf { isNext }
|
||||||
mNext = index
|
mPrev = index?.takeUnless { isNext }
|
||||||
mPrev = null
|
|
||||||
} else {
|
|
||||||
mPrev = index
|
|
||||||
mNext = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setJumpTo(jumpTo: String?) {
|
fun setJumpTo(jumpTo: String?) {
|
||||||
@@ -340,14 +307,10 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
|||||||
ub.addQuery("f_cats", category.inv() and EhConfig.ALL_CATEGORY)
|
ub.addQuery("f_cats", category.inv() and EhConfig.ALL_CATEGORY)
|
||||||
}
|
}
|
||||||
// Search key
|
// Search key
|
||||||
if (mKeyword != null) {
|
mKeyword?.run {
|
||||||
val keyword = mKeyword!!.trim { it <= ' ' }
|
val keyword = trim { it <= ' ' }
|
||||||
if (keyword.isNotEmpty()) {
|
if (keyword.isNotEmpty()) {
|
||||||
try {
|
ub.addQuery("f_search", encodeUTF8(this))
|
||||||
ub.addQuery("f_search", URLEncoder.encode(mKeyword, "UTF-8"))
|
|
||||||
} catch (e: UnsupportedEncodingException) {
|
|
||||||
// Empty
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mSHash?.let {
|
mSHash?.let {
|
||||||
@@ -387,11 +350,9 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
|||||||
|
|
||||||
MODE_UPLOADER -> {
|
MODE_UPLOADER -> {
|
||||||
val sb = StringBuilder(EhUrl.getHost())
|
val sb = StringBuilder(EhUrl.getHost())
|
||||||
sb.append("uploader/")
|
mKeyword?.let {
|
||||||
try {
|
sb.append("uploader/")
|
||||||
sb.append(URLEncoder.encode(mKeyword, "UTF-8"))
|
sb.append(encodeUTF8(it))
|
||||||
} catch (e: UnsupportedEncodingException) {
|
|
||||||
// Empty
|
|
||||||
}
|
}
|
||||||
mPrev?.let {
|
mPrev?.let {
|
||||||
sb.append("?prev=").append(it)
|
sb.append("?prev=").append(it)
|
||||||
@@ -407,11 +368,9 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
|||||||
|
|
||||||
MODE_TAG -> {
|
MODE_TAG -> {
|
||||||
val sb = StringBuilder(EhUrl.getHost())
|
val sb = StringBuilder(EhUrl.getHost())
|
||||||
sb.append("tag/")
|
mKeyword?.let {
|
||||||
try {
|
sb.append("tag/")
|
||||||
sb.append(URLEncoder.encode(mKeyword, "UTF-8"))
|
sb.append(encodeUTF8(it))
|
||||||
} catch (e: UnsupportedEncodingException) {
|
|
||||||
// Empty
|
|
||||||
}
|
}
|
||||||
mPrev?.let {
|
mPrev?.let {
|
||||||
sb.append("?prev=").append(it)
|
sb.append("?prev=").append(it)
|
||||||
@@ -430,10 +389,8 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
|||||||
MODE_TOPLIST -> {
|
MODE_TOPLIST -> {
|
||||||
val sb = StringBuilder(EhUrl.HOST_E)
|
val sb = StringBuilder(EhUrl.HOST_E)
|
||||||
sb.append("toplist.php?tl=")
|
sb.append("toplist.php?tl=")
|
||||||
try {
|
mKeyword.orEmpty().let {
|
||||||
sb.append(URLEncoder.encode(mKeyword, "UTF-8"))
|
sb.append(encodeUTF8(it))
|
||||||
} catch (e: UnsupportedEncodingException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
}
|
||||||
mJumpTo?.let {
|
mJumpTo?.let {
|
||||||
sb.append("&p=").append(it)
|
sb.append("&p=").append(it)
|
||||||
@@ -441,32 +398,10 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
|||||||
sb.toString()
|
sb.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw java.lang.IllegalStateException("Unexpected value: $mode")
|
else -> throw IllegalStateException("Unexpected value: $mode")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun describeContents(): Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
|
||||||
dest.writeInt(mode)
|
|
||||||
dest.writeString(mPrev)
|
|
||||||
dest.writeString(mNext)
|
|
||||||
dest.writeString(mJumpTo)
|
|
||||||
dest.writeInt(this.category)
|
|
||||||
dest.writeString(mKeyword)
|
|
||||||
dest.writeInt(advanceSearch)
|
|
||||||
dest.writeInt(minRating)
|
|
||||||
dest.writeInt(pageFrom)
|
|
||||||
dest.writeInt(pageTo)
|
|
||||||
dest.writeString(imagePath)
|
|
||||||
dest.writeByte(if (isUseSimilarityScan) 1.toByte() else 0.toByte())
|
|
||||||
dest.writeByte(if (isOnlySearchCovers) 1.toByte() else 0.toByte())
|
|
||||||
dest.writeByte(if (isShowExpunged) 1.toByte() else 0.toByte())
|
|
||||||
dest.writeString(mSHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
@IntDef(
|
@IntDef(
|
||||||
MODE_NORMAL,
|
MODE_NORMAL,
|
||||||
MODE_UPLOADER,
|
MODE_UPLOADER,
|
||||||
@@ -486,16 +421,5 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
|||||||
const val MODE_IMAGE_SEARCH = 0x4
|
const val MODE_IMAGE_SEARCH = 0x4
|
||||||
const val MODE_SUBSCRIPTION = 0x5
|
const val MODE_SUBSCRIPTION = 0x5
|
||||||
const val MODE_TOPLIST = 0x6
|
const val MODE_TOPLIST = 0x6
|
||||||
|
|
||||||
@JvmField
|
|
||||||
val CREATOR: Creator<ListUrlBuilder> = object : Creator<ListUrlBuilder> {
|
|
||||||
override fun createFromParcel(source: Parcel): ListUrlBuilder {
|
|
||||||
return ListUrlBuilder(source)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun newArray(size: Int): Array<ListUrlBuilder?> {
|
|
||||||
return arrayOfNulls(size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.data;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
|
|
||||||
import com.hippo.widget.LoadImageView;
|
|
||||||
import com.hippo.yorozuya.collect.IntList;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class NormalPreviewSet extends PreviewSet {
|
|
||||||
|
|
||||||
public static final Creator<NormalPreviewSet> CREATOR = new Creator<NormalPreviewSet>() {
|
|
||||||
@Override
|
|
||||||
public NormalPreviewSet createFromParcel(Parcel source) {
|
|
||||||
return new NormalPreviewSet(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NormalPreviewSet[] newArray(int size) {
|
|
||||||
return new NormalPreviewSet[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private IntList mPositionList = new IntList();
|
|
||||||
private ArrayList<String> mImageKeyList = new ArrayList<>();
|
|
||||||
private ArrayList<String> mImageUrlList = new ArrayList<>();
|
|
||||||
private IntList mOffsetXList = new IntList();
|
|
||||||
private IntList mOffsetYList = new IntList();
|
|
||||||
private IntList mClipWidthList = new IntList();
|
|
||||||
private IntList mClipHeightList = new IntList();
|
|
||||||
private ArrayList<String> mPageUrlList = new ArrayList<>();
|
|
||||||
|
|
||||||
public NormalPreviewSet() {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected NormalPreviewSet(Parcel in) {
|
|
||||||
this.mPositionList = in.readParcelable(IntList.class.getClassLoader());
|
|
||||||
this.mImageKeyList = in.createStringArrayList();
|
|
||||||
this.mImageUrlList = in.createStringArrayList();
|
|
||||||
this.mOffsetXList = in.readParcelable(IntList.class.getClassLoader());
|
|
||||||
this.mOffsetYList = in.readParcelable(IntList.class.getClassLoader());
|
|
||||||
this.mClipWidthList = in.readParcelable(IntList.class.getClassLoader());
|
|
||||||
this.mClipHeightList = in.readParcelable(IntList.class.getClassLoader());
|
|
||||||
this.mPageUrlList = in.createStringArrayList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getImageKey(String imageUrl) {
|
|
||||||
int index = imageUrl.indexOf('/');
|
|
||||||
if (index >= 0) {
|
|
||||||
return imageUrl.substring(index + 1);
|
|
||||||
} else {
|
|
||||||
return imageUrl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addItem(int position, String imageUrl, int xOffset, int yOffset, int width,
|
|
||||||
int height, String pageUrl) {
|
|
||||||
mPositionList.add(position);
|
|
||||||
mImageKeyList.add(getImageKey(imageUrl));
|
|
||||||
mImageUrlList.add(imageUrl);
|
|
||||||
mOffsetXList.add(xOffset);
|
|
||||||
mOffsetYList.add(yOffset);
|
|
||||||
mClipWidthList.add(width);
|
|
||||||
mClipHeightList.add(height);
|
|
||||||
mPageUrlList.add(pageUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return mPositionList.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPosition(int index) {
|
|
||||||
return mPositionList.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPageUrlAt(int index) {
|
|
||||||
return mPageUrlList.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GalleryPreview getGalleryPreview(long gid, int index) {
|
|
||||||
GalleryPreview galleryPreview = new GalleryPreview();
|
|
||||||
galleryPreview.position = mPositionList.get(index);
|
|
||||||
galleryPreview.imageKey = mImageKeyList.get(index);
|
|
||||||
galleryPreview.imageUrl = mImageUrlList.get(index);
|
|
||||||
galleryPreview.pageUrl = mPageUrlList.get(index);
|
|
||||||
galleryPreview.offsetX = mOffsetXList.get(index);
|
|
||||||
galleryPreview.offsetY = mOffsetYList.get(index);
|
|
||||||
galleryPreview.clipWidth = mClipWidthList.get(index);
|
|
||||||
galleryPreview.clipHeight = mClipHeightList.get(index);
|
|
||||||
return galleryPreview;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(LoadImageView view, long gid, int index) {
|
|
||||||
view.setClip(mOffsetXList.get(index), mOffsetYList.get(index),
|
|
||||||
mClipWidthList.get(index), mClipHeightList.get(index));
|
|
||||||
view.load(mImageKeyList.get(index), mImageUrlList.get(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
dest.writeParcelable(this.mPositionList, flags);
|
|
||||||
dest.writeStringList(this.mImageKeyList);
|
|
||||||
dest.writeStringList(this.mImageUrlList);
|
|
||||||
dest.writeParcelable(this.mOffsetXList, flags);
|
|
||||||
dest.writeParcelable(this.mOffsetYList, flags);
|
|
||||||
dest.writeParcelable(this.mClipWidthList, flags);
|
|
||||||
dest.writeParcelable(this.mClipHeightList, flags);
|
|
||||||
dest.writeStringList(this.mPageUrlList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.client.data
|
||||||
|
|
||||||
|
import com.hippo.widget.LoadImageView
|
||||||
|
import com.hippo.yorozuya.collect.IntList
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
class NormalPreviewSet(
|
||||||
|
private var mPositionList: IntList = IntList(),
|
||||||
|
private var mImageKeyList: ArrayList<String> = ArrayList(),
|
||||||
|
private var mImageUrlList: ArrayList<String> = ArrayList(),
|
||||||
|
private var mOffsetXList: IntList = IntList(),
|
||||||
|
private var mOffsetYList: IntList = IntList(),
|
||||||
|
private var mClipWidthList: IntList = IntList(),
|
||||||
|
private var mClipHeightList: IntList = IntList(),
|
||||||
|
private var mPageUrlList: ArrayList<String> = ArrayList()
|
||||||
|
) : PreviewSet() {
|
||||||
|
|
||||||
|
private fun getImageKey(imageUrl: String): String {
|
||||||
|
val index = imageUrl.indexOf('/')
|
||||||
|
return if (index >= 0) {
|
||||||
|
imageUrl.substring(index + 1)
|
||||||
|
} else {
|
||||||
|
imageUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addItem(
|
||||||
|
position: Int, imageUrl: String, xOffset: Int, yOffset: Int, width: Int,
|
||||||
|
height: Int, pageUrl: String
|
||||||
|
) {
|
||||||
|
mPositionList.add(position)
|
||||||
|
mImageKeyList.add(getImageKey(imageUrl))
|
||||||
|
mImageUrlList.add(imageUrl)
|
||||||
|
mOffsetXList.add(xOffset)
|
||||||
|
mOffsetYList.add(yOffset)
|
||||||
|
mClipWidthList.add(width)
|
||||||
|
mClipHeightList.add(height)
|
||||||
|
mPageUrlList.add(pageUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun size(): Int {
|
||||||
|
return mPositionList.size()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPosition(index: Int): Int {
|
||||||
|
return mPositionList[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPageUrlAt(index: Int): String {
|
||||||
|
return mPageUrlList[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getGalleryPreview(gid: Long, index: Int): GalleryPreview {
|
||||||
|
val galleryPreview = GalleryPreview()
|
||||||
|
galleryPreview.position = mPositionList[index]
|
||||||
|
galleryPreview.imageKey = mImageKeyList[index]
|
||||||
|
galleryPreview.imageUrl = mImageUrlList[index]
|
||||||
|
galleryPreview.pageUrl = mPageUrlList[index]
|
||||||
|
galleryPreview.offsetX = mOffsetXList[index]
|
||||||
|
galleryPreview.offsetY = mOffsetYList[index]
|
||||||
|
galleryPreview.clipWidth = mClipWidthList[index]
|
||||||
|
galleryPreview.clipHeight = mClipHeightList[index]
|
||||||
|
return galleryPreview
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun load(view: LoadImageView, gid: Long, index: Int) {
|
||||||
|
view.setClip(
|
||||||
|
mOffsetXList[index], mOffsetYList[index],
|
||||||
|
mClipWidthList[index], mClipHeightList[index]
|
||||||
|
)
|
||||||
|
view.load(mImageKeyList[index], mImageUrlList[index])
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.data;
|
|
||||||
|
|
||||||
import android.os.Parcelable;
|
|
||||||
|
|
||||||
import com.hippo.widget.LoadImageView;
|
|
||||||
|
|
||||||
public abstract class PreviewSet implements Parcelable {
|
|
||||||
|
|
||||||
public abstract int size();
|
|
||||||
|
|
||||||
public abstract int getPosition(int index);
|
|
||||||
|
|
||||||
public abstract String getPageUrlAt(int index);
|
|
||||||
|
|
||||||
public abstract GalleryPreview getGalleryPreview(long gid, int index);
|
|
||||||
|
|
||||||
public abstract void load(LoadImageView view, long gid, int index);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.client.data
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import com.hippo.widget.LoadImageView
|
||||||
|
|
||||||
|
abstract class PreviewSet : Parcelable {
|
||||||
|
abstract fun size(): Int
|
||||||
|
abstract fun getPosition(index: Int): Int
|
||||||
|
abstract fun getPageUrlAt(index: Int): String
|
||||||
|
abstract fun getGalleryPreview(gid: Long, index: Int): GalleryPreview
|
||||||
|
abstract fun load(view: LoadImageView, gid: Long, index: Int)
|
||||||
|
}
|
||||||
+5
-9
@@ -13,13 +13,9 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
package com.hippo.ehviewer.client.exception
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.exception;
|
open class EhException : Exception {
|
||||||
|
constructor(detailMessage: String?) : super(detailMessage)
|
||||||
public class NoHAtHClientException extends EhException {
|
constructor(detailMessage: String?, cause: Throwable?) : super(detailMessage, cause)
|
||||||
|
}
|
||||||
public NoHAtHClientException(String detailMessage) {
|
|
||||||
super(detailMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+2
-8
@@ -13,12 +13,6 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
package com.hippo.ehviewer.client.exception
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.exception;
|
class Image509Exception : EhException("509")
|
||||||
|
|
||||||
public class Image509Exception extends EhException {
|
|
||||||
|
|
||||||
public Image509Exception() {
|
|
||||||
super("509");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-8
@@ -13,12 +13,6 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
package com.hippo.ehviewer.client.exception
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.exception;
|
class NoHAtHClientException(detailMessage: String?) : EhException(detailMessage)
|
||||||
|
|
||||||
public class CancelledException extends Exception {
|
|
||||||
|
|
||||||
public CancelledException() {
|
|
||||||
super("CANCELED");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-8
@@ -13,15 +13,9 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
package com.hippo.ehviewer.client.exception
|
||||||
package com.hippo.ehviewer.client.exception;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It is an exception for get offensive tip for g.e-hentai.org
|
* It is an exception for get offensive tip for g.e-hentai.org
|
||||||
*/
|
*/
|
||||||
public class OffensiveException extends EhException {
|
class OffensiveException : EhException("OFFENSIVE")
|
||||||
|
|
||||||
public OffensiveException() {
|
|
||||||
super("OFFENSIVE");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.client.exception
|
||||||
|
|
||||||
|
class ParseException : EhException {
|
||||||
|
val body: String
|
||||||
|
|
||||||
|
constructor(detailMessage: String?, body: String) : super(detailMessage) {
|
||||||
|
this.body = body
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(detailMessage: String?, body: String, cause: Throwable?) : super(
|
||||||
|
detailMessage,
|
||||||
|
cause
|
||||||
|
) {
|
||||||
|
this.body = body
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-8
@@ -13,12 +13,6 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
package com.hippo.ehviewer.client.exception
|
||||||
|
|
||||||
package com.hippo.ehviewer.client.exception;
|
class PiningException : EhException("pining for the fjords")
|
||||||
|
|
||||||
public class PiningException extends EhException {
|
|
||||||
|
|
||||||
public PiningException() {
|
|
||||||
super("pining for the fjords");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,33 +16,193 @@
|
|||||||
|
|
||||||
package com.hippo.ehviewer.client.parser;
|
package com.hippo.ehviewer.client.parser;
|
||||||
|
|
||||||
import android.util.Pair;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.hippo.ehviewer.R;
|
||||||
|
import com.hippo.ehviewer.client.exception.NoHAtHClientException;
|
||||||
|
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class ArchiveParser {
|
public class ArchiveParser {
|
||||||
|
|
||||||
private static final Pattern PATTERN_FORM = Pattern.compile("<form id=\"hathdl_form\" action=\"[^\"]*?or=([^=\"]*?)\" method=\"post\">");
|
private static final Pattern PATTERN_ARCHIVE_URL = Pattern.compile("<strong>(.*)</strong>.*<a href=\"([^\"]*)\">Click Here To Start Downloading</a>");
|
||||||
private static final Pattern PATTERN_ARCHIVE = Pattern.compile("<a href=\"[^\"]*\" onclick=\"return do_hathdl\\('([0-9]+|org)'\\)\">([^<]+)</a>");
|
private static final Pattern PATTERN_HATH_FORM = Pattern.compile("<form id=\"hathdl_form\" action=\"[^\"]*?or=([^=\"]*?)\" method=\"post\">");
|
||||||
|
private static final Pattern PATTERN_HATH_ARCHIVE = Pattern.compile("<p><a href=\"[^\"]*\" onclick=\"return do_hathdl\\('([0-9]+|org)'\\)\">([^<]+)</a></p>\\s*<p>([\\w. ]+)</p>\\s*<p>([\\w. ]+)</p>");
|
||||||
|
private static final Pattern PATTERN_NEED_HATH_CLIENT = Pattern.compile("You must have a H@H client assigned to your account to use this feature\\.");
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
public static Result parse(String body) {
|
||||||
public static Pair<String, Pair<String, String>[]> parse(String body) {
|
Matcher m = PATTERN_HATH_FORM.matcher(body);
|
||||||
Matcher m = PATTERN_FORM.matcher(body);
|
|
||||||
if (!m.find()) {
|
if (!m.find()) {
|
||||||
return new Pair<String, Pair<String, String>[]>("", new Pair[0]);
|
return new Result(null, null);
|
||||||
}
|
}
|
||||||
String paramOr = m.group(1);
|
String paramOr = m.group(1);
|
||||||
List<Pair<String, String>> archiveList = new ArrayList<>();
|
|
||||||
m = PATTERN_ARCHIVE.matcher(body);
|
var archiveList = new ArrayList<Archive>();
|
||||||
|
var d = Jsoup.parse(body);
|
||||||
|
var es = d.select("#db>div>div");
|
||||||
|
for (var e : es) {
|
||||||
|
try {
|
||||||
|
var res = e.selectFirst("form>input").attr("value");
|
||||||
|
var name = e.selectFirst("form>div>input").attr("value");
|
||||||
|
var size = e.selectFirst("p>strong").text();
|
||||||
|
var cost = e.selectFirst("div>strong").text();
|
||||||
|
var item = new Archive(res, name, size, cost, false);
|
||||||
|
archiveList.add(item);
|
||||||
|
} catch (NullPointerException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m = PATTERN_HATH_ARCHIVE.matcher(body);
|
||||||
while (m.find()) {
|
while (m.find()) {
|
||||||
String res = ParserUtils.trim(m.group(1));
|
String res = ParserUtils.trim(m.group(1));
|
||||||
String name = ParserUtils.trim(m.group(2));
|
String name = ParserUtils.trim(m.group(2));
|
||||||
Pair<String, String> item = new Pair<>(res, name);
|
String size = ParserUtils.trim(m.group(3));
|
||||||
|
String cost = ParserUtils.trim(m.group(4));
|
||||||
|
var item = new Archive(res, name, size, cost, true);
|
||||||
archiveList.add(item);
|
archiveList.add(item);
|
||||||
}
|
}
|
||||||
return new Pair<>(paramOr, archiveList.toArray(new Pair[0]));
|
|
||||||
|
return new Result(paramOr, archiveList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String parseArchiveUrl(String body) throws NoHAtHClientException {
|
||||||
|
Matcher m = PATTERN_NEED_HATH_CLIENT.matcher(body);
|
||||||
|
if (m.find()) {
|
||||||
|
throw new NoHAtHClientException("No H@H client");
|
||||||
|
}
|
||||||
|
|
||||||
|
var d = Jsoup.parse(body);
|
||||||
|
var a = d.selectFirst("#continue>a[href]");
|
||||||
|
if (a != null) {
|
||||||
|
return a.attr("href") + "?start=1";
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Check more errors
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Archive {
|
||||||
|
private final String res;
|
||||||
|
private final String name;
|
||||||
|
private final String size;
|
||||||
|
private final String cost;
|
||||||
|
private final boolean isHAtH;
|
||||||
|
|
||||||
|
public Archive(String res, String name, String size, String cost, boolean isHAtH) {
|
||||||
|
this.res = res;
|
||||||
|
this.name = name;
|
||||||
|
this.size = size;
|
||||||
|
this.cost = cost;
|
||||||
|
this.isHAtH = isHAtH;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String format(IntFunction<String> getString) {
|
||||||
|
if (isHAtH) {
|
||||||
|
var costStr = cost.equals("Free") ? getString.apply(R.string.archive_free) : cost;
|
||||||
|
return String.format("[H@H] %s [%s] [%s]", name, size, costStr);
|
||||||
|
} else {
|
||||||
|
var nameStr = getString.apply(res.equals("org") ? R.string.archive_original : R.string.archive_resample);
|
||||||
|
var costStr = cost.equals("Free!") ? getString.apply(R.string.archive_free) : cost;
|
||||||
|
return String.format("%s [%s] [%s]", nameStr, size, costStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String res() {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String size() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String cost() {
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHAtH() {
|
||||||
|
return isHAtH;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == this) return true;
|
||||||
|
if (obj == null || obj.getClass() != this.getClass()) return false;
|
||||||
|
var that = (Archive) obj;
|
||||||
|
return Objects.equals(this.res, that.res) &&
|
||||||
|
Objects.equals(this.name, that.name) &&
|
||||||
|
Objects.equals(this.size, that.size) &&
|
||||||
|
Objects.equals(this.cost, that.cost) &&
|
||||||
|
this.isHAtH == that.isHAtH;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(res, name, size, cost, isHAtH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Archive[" +
|
||||||
|
"res=" + res + ", " +
|
||||||
|
"name=" + name + ", " +
|
||||||
|
"size=" + size + ", " +
|
||||||
|
"cost=" + cost + ", " +
|
||||||
|
"isHAtH=" + isHAtH + ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Result {
|
||||||
|
private final String paramOr;
|
||||||
|
private final List<Archive> archiveList;
|
||||||
|
|
||||||
|
public Result(String paramOr, List<Archive> archiveList) {
|
||||||
|
this.paramOr = paramOr;
|
||||||
|
this.archiveList = archiveList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String paramOr() {
|
||||||
|
return paramOr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Archive> archiveList() {
|
||||||
|
return archiveList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == this) return true;
|
||||||
|
if (obj == null || obj.getClass() != this.getClass()) return false;
|
||||||
|
var that = (Result) obj;
|
||||||
|
return Objects.equals(this.paramOr, that.paramOr) &&
|
||||||
|
Objects.equals(this.archiveList, that.archiveList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(paramOr, archiveList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Result[" +
|
||||||
|
"paramOr=" + paramOr + ", " +
|
||||||
|
"archiveList=" + archiveList + ']';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,27 +16,132 @@
|
|||||||
|
|
||||||
package com.hippo.ehviewer.client.parser;
|
package com.hippo.ehviewer.client.parser;
|
||||||
|
|
||||||
import android.util.Pair;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class TorrentParser {
|
public class TorrentParser {
|
||||||
|
|
||||||
private static final Pattern PATTERN_TORRENT = Pattern.compile("<td colspan=\"5\"> <a href=\".*\" onclick=\"document.location='([^\"]+)'[^<]+>([^<]+)</a></td>");
|
private static final Pattern PATTERN_TORRENT = Pattern.compile("</span> ([0-9-]+) [0-9:]+</td>[\\s\\S]+</span> ([0-9\\.]+ [KMGT]B)</td>[\\s\\S]+</span> ([0-9]+)</td>[\\s\\S]+</span> ([0-9]+)</td>[\\s\\S]+</span> ([0-9]+)</td>[\\s\\S]+</span>([^<]+)</td>[\\s\\S]+onclick=\"document.location='([^\"]+)'[^<]+>([^<]+)</a>");
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
public static List<Result> parse(String body) {
|
||||||
public static Pair<String, String>[] parse(String body) {
|
var torrentList = new ArrayList<Result>();
|
||||||
List<Pair<String, String>> torrentList = new ArrayList<>();
|
var d = Jsoup.parse(body);
|
||||||
Matcher m = PATTERN_TORRENT.matcher(body);
|
var es = d.select("form>div>table");
|
||||||
while (m.find()) {
|
for (var e : es) {
|
||||||
String url = ParserUtils.trim(m.group(1));
|
Matcher m = PATTERN_TORRENT.matcher(e.html());
|
||||||
String name = ParserUtils.trim(m.group(2));
|
if (m.find()) {
|
||||||
Pair<String, String> item = new Pair<>(url, name);
|
String posted = m.group(1);
|
||||||
torrentList.add(item);
|
String size = m.group(2);
|
||||||
|
int seeds = Integer.parseInt(m.group(3));
|
||||||
|
int peers = Integer.parseInt(m.group(4));
|
||||||
|
int downloads = Integer.parseInt(m.group(5));
|
||||||
|
String uploader = ParserUtils.trim(m.group(6));
|
||||||
|
String url = ParserUtils.trim(m.group(7));
|
||||||
|
String name = ParserUtils.trim(m.group(8));
|
||||||
|
var item = new Result(posted, size, seeds, peers, downloads, uploader, url, name);
|
||||||
|
torrentList.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return torrentList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Result {
|
||||||
|
private final String posted;
|
||||||
|
private final String size;
|
||||||
|
private final int seeds;
|
||||||
|
private final int peers;
|
||||||
|
private final int downloads;
|
||||||
|
private final String uploader;
|
||||||
|
private final String url;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public Result(String posted, String size, int seeds, int peers, int downloads, String uploader, String url, String name) {
|
||||||
|
this.posted = posted;
|
||||||
|
this.size = size;
|
||||||
|
this.seeds = seeds;
|
||||||
|
this.peers = peers;
|
||||||
|
this.downloads = downloads;
|
||||||
|
this.uploader = uploader;
|
||||||
|
this.url = url;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String format(IntFunction<String> getString) {
|
||||||
|
return String.format("[%s] %s [%s] [↑%s ↓%s ✓%s]", posted, name, size, seeds, peers, downloads);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String posted() {
|
||||||
|
return posted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String size() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int seeds() {
|
||||||
|
return seeds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int peers() {
|
||||||
|
return peers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int downloads() {
|
||||||
|
return downloads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String uploader() {
|
||||||
|
return uploader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String url() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == this) return true;
|
||||||
|
if (obj == null || obj.getClass() != this.getClass()) return false;
|
||||||
|
var that = (Result) obj;
|
||||||
|
return Objects.equals(this.posted, that.posted) &&
|
||||||
|
Objects.equals(this.size, that.size) &&
|
||||||
|
this.seeds == that.seeds &&
|
||||||
|
this.peers == that.peers &&
|
||||||
|
this.downloads == that.downloads &&
|
||||||
|
Objects.equals(this.uploader, that.uploader) &&
|
||||||
|
Objects.equals(this.url, that.url) &&
|
||||||
|
Objects.equals(this.name, that.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(posted, size, seeds, peers, downloads, uploader, url, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Result[" +
|
||||||
|
"posted=" + posted + ", " +
|
||||||
|
"size=" + size + ", " +
|
||||||
|
"seeds=" + seeds + ", " +
|
||||||
|
"peers=" + peers + ", " +
|
||||||
|
"downloads=" + downloads + ", " +
|
||||||
|
"uploader=" + uploader + ", " +
|
||||||
|
"url=" + url + ", " +
|
||||||
|
"name=" + name + ']';
|
||||||
}
|
}
|
||||||
return torrentList.toArray(new Pair[0]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface BasicDao<T> {
|
|
||||||
List<T> list();
|
|
||||||
|
|
||||||
long insert(T t);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
interface BasicDao<T> {
|
||||||
|
fun list(): List<T>
|
||||||
|
fun insert(t: T): Long
|
||||||
|
}
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
|
||||||
import androidx.room.Entity;
|
|
||||||
|
|
||||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
|
||||||
|
|
||||||
@Entity(tableName = "BOOKMARKS")
|
|
||||||
public class BookmarkInfo extends GalleryInfo {
|
|
||||||
public static final Creator<BookmarkInfo> CREATOR = new Creator<>() {
|
|
||||||
@Override
|
|
||||||
public BookmarkInfo createFromParcel(Parcel source) {
|
|
||||||
return new BookmarkInfo(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BookmarkInfo[] newArray(int size) {
|
|
||||||
return new BookmarkInfo[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ColumnInfo(name = "PAGE")
|
|
||||||
public int page;
|
|
||||||
@ColumnInfo(name = "TIME")
|
|
||||||
public long time;
|
|
||||||
|
|
||||||
protected BookmarkInfo(Parcel in) {
|
|
||||||
super(in);
|
|
||||||
this.page = in.readInt();
|
|
||||||
this.time = in.readLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BookmarkInfo(GalleryInfo galleryInfo) {
|
|
||||||
this.gid = galleryInfo.gid;
|
|
||||||
this.token = galleryInfo.token;
|
|
||||||
this.title = galleryInfo.title;
|
|
||||||
this.titleJpn = galleryInfo.titleJpn;
|
|
||||||
this.thumb = galleryInfo.thumb;
|
|
||||||
this.category = galleryInfo.category;
|
|
||||||
this.posted = galleryInfo.posted;
|
|
||||||
this.uploader = galleryInfo.uploader;
|
|
||||||
this.rating = galleryInfo.rating;
|
|
||||||
this.simpleTags = galleryInfo.simpleTags;
|
|
||||||
this.simpleLanguage = galleryInfo.simpleLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BookmarkInfo(int page, long time) {
|
|
||||||
this.page = page;
|
|
||||||
this.time = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getGid() {
|
|
||||||
return gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGid(long gid) {
|
|
||||||
this.gid = gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getToken() {
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToken(String token) {
|
|
||||||
this.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitleJpn() {
|
|
||||||
return titleJpn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitleJpn(String titleJpn) {
|
|
||||||
this.titleJpn = titleJpn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getThumb() {
|
|
||||||
return thumb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setThumb(String thumb) {
|
|
||||||
this.thumb = thumb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCategory() {
|
|
||||||
return category;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCategory(int category) {
|
|
||||||
this.category = category;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPosted() {
|
|
||||||
return posted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPosted(String posted) {
|
|
||||||
this.posted = posted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUploader() {
|
|
||||||
return uploader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUploader(String uploader) {
|
|
||||||
this.uploader = uploader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getRating() {
|
|
||||||
return rating;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRating(float rating) {
|
|
||||||
this.rating = rating;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSimpleLanguage() {
|
|
||||||
return simpleLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSimpleLanguage(String simpleLanguage) {
|
|
||||||
this.simpleLanguage = simpleLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPage() {
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPage(int page) {
|
|
||||||
this.page = page;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTime() {
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTime(long time) {
|
|
||||||
this.time = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
super.writeToParcel(dest, flags);
|
|
||||||
dest.writeInt(this.page);
|
|
||||||
dest.writeLong(this.time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import com.hippo.ehviewer.client.data.GalleryInfo
|
||||||
|
|
||||||
|
@Entity(tableName = "BOOKMARKS")
|
||||||
|
class BookmarkInfo : GalleryInfo() {
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "PAGE")
|
||||||
|
var page = 0
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "TIME")
|
||||||
|
var time: Long = 0
|
||||||
|
}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import androidx.room.Dao;
|
|
||||||
import androidx.room.Delete;
|
|
||||||
import androidx.room.Insert;
|
|
||||||
import androidx.room.Query;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
public interface BookmarksDao extends BasicDao<BookmarkInfo> {
|
|
||||||
@Insert
|
|
||||||
long insert(BookmarkInfo bookmark);
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
void delete(BookmarkInfo bookmark);
|
|
||||||
|
|
||||||
@Query("SELECT * FROM BOOKMARKS ORDER BY TIME DESC")
|
|
||||||
List<BookmarkInfo> list();
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface BookmarksDao : BasicDao<BookmarkInfo> {
|
||||||
|
@Insert
|
||||||
|
override fun insert(t: BookmarkInfo): Long
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(bookmark: BookmarkInfo)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM BOOKMARKS ORDER BY TIME DESC")
|
||||||
|
override fun list(): List<BookmarkInfo>
|
||||||
|
}
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
|
||||||
import androidx.room.Entity;
|
|
||||||
import androidx.room.PrimaryKey;
|
|
||||||
|
|
||||||
@Entity(tableName = "DOWNLOAD_DIRNAME")
|
|
||||||
public class DownloadDirname {
|
|
||||||
@PrimaryKey
|
|
||||||
@ColumnInfo(name = "GID")
|
|
||||||
private long gid;
|
|
||||||
@ColumnInfo(name = "DIRNAME")
|
|
||||||
private String dirname;
|
|
||||||
|
|
||||||
public long getGid() {
|
|
||||||
return gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGid(long gid) {
|
|
||||||
this.gid = gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDirname() {
|
|
||||||
return dirname;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDirname(String dirname) {
|
|
||||||
this.dirname = dirname;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "DOWNLOAD_DIRNAME")
|
||||||
|
data class DownloadDirname(
|
||||||
|
@PrimaryKey
|
||||||
|
@ColumnInfo(name = "GID")
|
||||||
|
var gid: Long = 0,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "DIRNAME")
|
||||||
|
var dirname: String? = null
|
||||||
|
)
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import androidx.room.Dao;
|
|
||||||
import androidx.room.Insert;
|
|
||||||
import androidx.room.Query;
|
|
||||||
import androidx.room.Update;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
public interface DownloadDirnameDao extends BasicDao<DownloadDirname> {
|
|
||||||
@Query("SELECT * FROM DOWNLOAD_DIRNAME WHERE GID = :gid")
|
|
||||||
DownloadDirname load(long gid);
|
|
||||||
|
|
||||||
@Update
|
|
||||||
void update(DownloadDirname downloadDirname);
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
long insert(DownloadDirname downloadDirname);
|
|
||||||
|
|
||||||
@Query("DELETE FROM DOWNLOAD_DIRNAME WHERE GID = :gid")
|
|
||||||
void deleteByKey(long gid);
|
|
||||||
|
|
||||||
@Query("DELETE FROM DOWNLOAD_DIRNAME")
|
|
||||||
void deleteAll();
|
|
||||||
|
|
||||||
@Query("SELECT * FROM DOWNLOAD_DIRNAME")
|
|
||||||
List<DownloadDirname> list();
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Update
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface DownloadDirnameDao : BasicDao<DownloadDirname> {
|
||||||
|
@Query("SELECT * FROM DOWNLOAD_DIRNAME WHERE GID = :gid")
|
||||||
|
fun load(gid: Long): DownloadDirname?
|
||||||
|
|
||||||
|
@Update
|
||||||
|
fun update(downloadDirname: DownloadDirname)
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
override fun insert(t: DownloadDirname): Long
|
||||||
|
|
||||||
|
@Query("DELETE FROM DOWNLOAD_DIRNAME WHERE GID = :gid")
|
||||||
|
fun deleteByKey(gid: Long)
|
||||||
|
|
||||||
|
@Query("DELETE FROM DOWNLOAD_DIRNAME")
|
||||||
|
fun deleteAll()
|
||||||
|
|
||||||
|
@Query("SELECT * FROM DOWNLOAD_DIRNAME")
|
||||||
|
override fun list(): List<DownloadDirname>
|
||||||
|
}
|
||||||
@@ -1,252 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
|
||||||
import androidx.room.Entity;
|
|
||||||
import androidx.room.Ignore;
|
|
||||||
|
|
||||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
|
||||||
|
|
||||||
@Entity(tableName = "DOWNLOADS")
|
|
||||||
public class DownloadInfo extends GalleryInfo {
|
|
||||||
public static final Creator<DownloadInfo> CREATOR = new Creator<>() {
|
|
||||||
@Override
|
|
||||||
public DownloadInfo createFromParcel(Parcel source) {
|
|
||||||
return new DownloadInfo(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DownloadInfo[] newArray(int size) {
|
|
||||||
return new DownloadInfo[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
public static final int STATE_INVALID = -1;
|
|
||||||
public static final int STATE_NONE = 0;
|
|
||||||
public static final int STATE_WAIT = 1;
|
|
||||||
public static final int STATE_DOWNLOAD = 2;
|
|
||||||
public static final int STATE_FINISH = 3;
|
|
||||||
public static final int STATE_FAILED = 4;
|
|
||||||
@ColumnInfo(name = "STATE")
|
|
||||||
public int state;
|
|
||||||
@ColumnInfo(name = "LEGACY")
|
|
||||||
public int legacy;
|
|
||||||
@ColumnInfo(name = "TIME")
|
|
||||||
public long time;
|
|
||||||
@ColumnInfo(name = "LABEL")
|
|
||||||
public String label;
|
|
||||||
@Ignore
|
|
||||||
public long speed;
|
|
||||||
@Ignore
|
|
||||||
public long remaining;
|
|
||||||
@Ignore
|
|
||||||
public int finished;
|
|
||||||
@Ignore
|
|
||||||
public int downloaded;
|
|
||||||
@Ignore
|
|
||||||
public int total;
|
|
||||||
|
|
||||||
DownloadInfo() {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected DownloadInfo(Parcel in) {
|
|
||||||
super(in);
|
|
||||||
this.state = in.readInt();
|
|
||||||
this.legacy = in.readInt();
|
|
||||||
this.time = in.readLong();
|
|
||||||
this.label = in.readString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public DownloadInfo(GalleryInfo galleryInfo) {
|
|
||||||
this.gid = galleryInfo.gid;
|
|
||||||
this.token = galleryInfo.token;
|
|
||||||
this.title = galleryInfo.title;
|
|
||||||
this.titleJpn = galleryInfo.titleJpn;
|
|
||||||
this.thumb = galleryInfo.thumb;
|
|
||||||
this.category = galleryInfo.category;
|
|
||||||
this.posted = galleryInfo.posted;
|
|
||||||
this.uploader = galleryInfo.uploader;
|
|
||||||
this.rating = galleryInfo.rating;
|
|
||||||
this.simpleTags = galleryInfo.simpleTags;
|
|
||||||
this.simpleLanguage = galleryInfo.simpleLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DownloadInfo(int state, int legacy, long time, String label, long speed, long remaining,
|
|
||||||
int finished, int downloaded, int total) {
|
|
||||||
this.state = state;
|
|
||||||
this.legacy = legacy;
|
|
||||||
this.time = time;
|
|
||||||
this.label = label;
|
|
||||||
this.speed = speed;
|
|
||||||
this.remaining = remaining;
|
|
||||||
this.finished = finished;
|
|
||||||
this.downloaded = downloaded;
|
|
||||||
this.total = total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getGid() {
|
|
||||||
return gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGid(long gid) {
|
|
||||||
this.gid = gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getToken() {
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToken(String token) {
|
|
||||||
this.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitleJpn() {
|
|
||||||
return titleJpn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitleJpn(String titleJpn) {
|
|
||||||
this.titleJpn = titleJpn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getThumb() {
|
|
||||||
return thumb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setThumb(String thumb) {
|
|
||||||
this.thumb = thumb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCategory() {
|
|
||||||
return category;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCategory(int category) {
|
|
||||||
this.category = category;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPosted() {
|
|
||||||
return posted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPosted(String posted) {
|
|
||||||
this.posted = posted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUploader() {
|
|
||||||
return uploader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUploader(String uploader) {
|
|
||||||
this.uploader = uploader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getRating() {
|
|
||||||
return rating;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRating(float rating) {
|
|
||||||
this.rating = rating;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSimpleLanguage() {
|
|
||||||
return simpleLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSimpleLanguage(String simpleLanguage) {
|
|
||||||
this.simpleLanguage = simpleLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getState() {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setState(int state) {
|
|
||||||
this.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLegacy() {
|
|
||||||
return legacy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLegacy(int legacy) {
|
|
||||||
this.legacy = legacy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTime() {
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTime(long time) {
|
|
||||||
this.time = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLabel() {
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLabel(String label) {
|
|
||||||
this.label = label;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
super.writeToParcel(dest, flags);
|
|
||||||
dest.writeInt(this.state);
|
|
||||||
dest.writeInt(this.legacy);
|
|
||||||
dest.writeLong(this.time);
|
|
||||||
dest.writeString(this.label);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getSpeed() {
|
|
||||||
return this.speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSpeed(long speed) {
|
|
||||||
this.speed = speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getRemaining() {
|
|
||||||
return this.remaining;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRemaining(long remaining) {
|
|
||||||
this.remaining = remaining;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFinished() {
|
|
||||||
return this.finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFinished(int finished) {
|
|
||||||
this.finished = finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDownloaded() {
|
|
||||||
return this.downloaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDownloaded(int downloaded) {
|
|
||||||
this.downloaded = downloaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTotal() {
|
|
||||||
return this.total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTotal(int total) {
|
|
||||||
this.total = total;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.Ignore
|
||||||
|
import com.hippo.ehviewer.client.data.GalleryInfo
|
||||||
|
|
||||||
|
@Entity(tableName = "DOWNLOADS")
|
||||||
|
class DownloadInfo() : GalleryInfo() {
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "STATE")
|
||||||
|
var state = 0
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "LEGACY")
|
||||||
|
var legacy = 0
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "TIME")
|
||||||
|
var time: Long = 0
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "LABEL")
|
||||||
|
var label: String? = null
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Ignore
|
||||||
|
var speed: Long = 0
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Ignore
|
||||||
|
var remaining: Long = 0
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Ignore
|
||||||
|
var finished = 0
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Ignore
|
||||||
|
var downloaded = 0
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Ignore
|
||||||
|
var total = 0
|
||||||
|
|
||||||
|
constructor(galleryInfo: GalleryInfo) : this() {
|
||||||
|
gid = galleryInfo.gid
|
||||||
|
token = galleryInfo.token
|
||||||
|
title = galleryInfo.title
|
||||||
|
titleJpn = galleryInfo.titleJpn
|
||||||
|
thumb = galleryInfo.thumb
|
||||||
|
this.category = galleryInfo.category
|
||||||
|
posted = galleryInfo.posted
|
||||||
|
uploader = galleryInfo.uploader
|
||||||
|
rating = galleryInfo.rating
|
||||||
|
simpleTags = galleryInfo.simpleTags
|
||||||
|
simpleLanguage = galleryInfo.simpleLanguage
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val STATE_INVALID = -1
|
||||||
|
const val STATE_NONE = 0
|
||||||
|
const val STATE_WAIT = 1
|
||||||
|
const val STATE_DOWNLOAD = 2
|
||||||
|
const val STATE_FINISH = 3
|
||||||
|
const val STATE_FAILED = 4
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
|
||||||
import androidx.room.Entity;
|
|
||||||
import androidx.room.PrimaryKey;
|
|
||||||
|
|
||||||
@Entity(tableName = "DOWNLOAD_LABELS")
|
|
||||||
public class DownloadLabel {
|
|
||||||
@PrimaryKey
|
|
||||||
@ColumnInfo(name = "_id")
|
|
||||||
private Long id;
|
|
||||||
@ColumnInfo(name = "LABEL")
|
|
||||||
private String label;
|
|
||||||
@ColumnInfo(name = "TIME")
|
|
||||||
private long time;
|
|
||||||
|
|
||||||
public Long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLabel() {
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLabel(String label) {
|
|
||||||
this.label = label;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTime() {
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTime(long time) {
|
|
||||||
this.time = time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "DOWNLOAD_LABELS")
|
||||||
|
data class DownloadLabel(
|
||||||
|
@PrimaryKey
|
||||||
|
@ColumnInfo(name = "_id")
|
||||||
|
var id: Long? = null,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "LABEL")
|
||||||
|
var label: String? = null,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "TIME")
|
||||||
|
var time: Long = 0
|
||||||
|
)
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import androidx.room.Dao;
|
|
||||||
import androidx.room.Delete;
|
|
||||||
import androidx.room.Insert;
|
|
||||||
import androidx.room.Query;
|
|
||||||
import androidx.room.Update;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
public interface DownloadLabelDao extends BasicDao<DownloadLabel> {
|
|
||||||
@Query("SELECT * FROM DOWNLOAD_LABELS ORDER BY TIME ASC")
|
|
||||||
List<DownloadLabel> list();
|
|
||||||
|
|
||||||
@Query("SELECT * FROM DOWNLOAD_LABELS ORDER BY TIME ASC LIMIT :limit OFFSET :offset")
|
|
||||||
List<DownloadLabel> list(int offset, int limit);
|
|
||||||
|
|
||||||
@Update
|
|
||||||
void update(List<DownloadLabel> downloadLabels);
|
|
||||||
|
|
||||||
@Update
|
|
||||||
void update(DownloadLabel downloadLabel);
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
long insert(DownloadLabel downloadLabel);
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
void delete(DownloadLabel downloadLabel);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Update
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface DownloadLabelDao : BasicDao<DownloadLabel> {
|
||||||
|
@Query("SELECT * FROM DOWNLOAD_LABELS ORDER BY TIME ASC")
|
||||||
|
override fun list(): List<DownloadLabel>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM DOWNLOAD_LABELS ORDER BY TIME ASC LIMIT :limit OFFSET :offset")
|
||||||
|
fun list(offset: Int, limit: Int): List<DownloadLabel>
|
||||||
|
|
||||||
|
@Update
|
||||||
|
fun update(downloadLabels: List<DownloadLabel>)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
fun update(downloadLabel: DownloadLabel)
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
override fun insert(t: DownloadLabel): Long
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(downloadLabel: DownloadLabel)
|
||||||
|
}
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import androidx.room.Dao;
|
|
||||||
import androidx.room.Delete;
|
|
||||||
import androidx.room.Insert;
|
|
||||||
import androidx.room.Query;
|
|
||||||
import androidx.room.Update;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
public interface DownloadsDao extends BasicDao<DownloadInfo> {
|
|
||||||
@Query("SELECT * FROM DOWNLOADS ORDER BY TIME DESC")
|
|
||||||
List<DownloadInfo> list();
|
|
||||||
|
|
||||||
@Query("SELECT * FROM DOWNLOADS WHERE GID = :gid")
|
|
||||||
DownloadInfo load(long gid);
|
|
||||||
|
|
||||||
@Update
|
|
||||||
void update(DownloadInfo downloadInfo);
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
long insert(DownloadInfo downloadInfo);
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
void delete(DownloadInfo downloadInfo);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Update
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface DownloadsDao : BasicDao<DownloadInfo> {
|
||||||
|
@Query("SELECT * FROM DOWNLOADS ORDER BY TIME DESC")
|
||||||
|
override fun list(): List<DownloadInfo>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM DOWNLOADS WHERE GID = :gid")
|
||||||
|
fun load(gid: Long): DownloadInfo?
|
||||||
|
|
||||||
|
@Update
|
||||||
|
fun update(downloadInfo: DownloadInfo)
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
override fun insert(downloadInfo: DownloadInfo): Long
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(downloadInfo: DownloadInfo)
|
||||||
|
}
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import androidx.room.Database;
|
|
||||||
import androidx.room.RoomDatabase;
|
|
||||||
|
|
||||||
@Database(entities = {BookmarkInfo.class, DownloadInfo.class, DownloadLabel.class, DownloadDirname.class, Filter.class, HistoryInfo.class, LocalFavoriteInfo.class, QuickSearch.class}, version = 4, exportSchema = false)
|
|
||||||
public abstract class EhDatabase extends RoomDatabase {
|
|
||||||
public abstract BookmarksDao bookmarksBao();
|
|
||||||
|
|
||||||
public abstract DownloadDirnameDao downloadDirnameDao();
|
|
||||||
|
|
||||||
public abstract DownloadLabelDao downloadLabelDao();
|
|
||||||
|
|
||||||
public abstract DownloadsDao downloadsDao();
|
|
||||||
|
|
||||||
public abstract FilterDao filterDao();
|
|
||||||
|
|
||||||
public abstract HistoryDao historyDao();
|
|
||||||
|
|
||||||
public abstract LocalFavoritesDao localFavoritesDao();
|
|
||||||
|
|
||||||
public abstract QuickSearchDao quickSearchDao();
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.Database
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
|
|
||||||
|
@Database(
|
||||||
|
entities = [BookmarkInfo::class, DownloadInfo::class, DownloadLabel::class, DownloadDirname::class, Filter::class, HistoryInfo::class, LocalFavoriteInfo::class, QuickSearch::class],
|
||||||
|
version = 4,
|
||||||
|
exportSchema = false
|
||||||
|
)
|
||||||
|
abstract class EhDatabase : RoomDatabase() {
|
||||||
|
abstract fun bookmarksBao(): BookmarksDao
|
||||||
|
abstract fun downloadDirnameDao(): DownloadDirnameDao
|
||||||
|
abstract fun downloadLabelDao(): DownloadLabelDao
|
||||||
|
abstract fun downloadsDao(): DownloadsDao
|
||||||
|
abstract fun filterDao(): FilterDao
|
||||||
|
abstract fun historyDao(): HistoryDao
|
||||||
|
abstract fun localFavoritesDao(): LocalFavoritesDao
|
||||||
|
abstract fun quickSearchDao(): QuickSearchDao
|
||||||
|
}
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
|
||||||
import androidx.room.Entity;
|
|
||||||
import androidx.room.PrimaryKey;
|
|
||||||
|
|
||||||
import com.hippo.util.HashCodeUtils;
|
|
||||||
import com.hippo.yorozuya.ObjectUtils;
|
|
||||||
|
|
||||||
@Entity(tableName = "FILTER")
|
|
||||||
public class Filter {
|
|
||||||
@ColumnInfo(name = "MODE")
|
|
||||||
public int mode;
|
|
||||||
@ColumnInfo(name = "TEXT")
|
|
||||||
public String text;
|
|
||||||
@ColumnInfo(name = "ENABLE")
|
|
||||||
public Boolean enable;
|
|
||||||
@PrimaryKey
|
|
||||||
@ColumnInfo(name = "_id")
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
public Long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMode() {
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMode(int mode) {
|
|
||||||
this.mode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getText() {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setText(String text) {
|
|
||||||
this.text = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean getEnable() {
|
|
||||||
return enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEnable(Boolean enable) {
|
|
||||||
this.enable = enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return HashCodeUtils.hashCode(mode, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof Filter filter)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return filter.mode == mode && ObjectUtils.equal(filter.text, text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "FILTER")
|
||||||
|
data class Filter(
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "MODE")
|
||||||
|
var mode: Int = 0,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "TEXT")
|
||||||
|
var text: String? = null,
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "ENABLE")
|
||||||
|
var enable: Boolean? = null,
|
||||||
|
|
||||||
|
@PrimaryKey
|
||||||
|
@ColumnInfo(name = "_id")
|
||||||
|
var id: Long? = null
|
||||||
|
)
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import androidx.room.Dao;
|
|
||||||
import androidx.room.Delete;
|
|
||||||
import androidx.room.Insert;
|
|
||||||
import androidx.room.Query;
|
|
||||||
import androidx.room.Update;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
public interface FilterDao extends BasicDao<Filter> {
|
|
||||||
@Query("SELECT * FROM FILTER")
|
|
||||||
List<Filter> list();
|
|
||||||
|
|
||||||
@Update
|
|
||||||
void update(Filter filter);
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
long insert(Filter filter);
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
void delete(Filter filter);
|
|
||||||
|
|
||||||
@Query("SELECT * FROM FILTER WHERE TEXT = :text AND MODE = :mode")
|
|
||||||
Filter load(String text, int mode);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Update
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface FilterDao : BasicDao<Filter> {
|
||||||
|
@Query("SELECT * FROM FILTER")
|
||||||
|
override fun list(): List<Filter>
|
||||||
|
|
||||||
|
@Update
|
||||||
|
fun update(filter: Filter)
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
override fun insert(t: Filter): Long
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(filter: Filter)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM FILTER WHERE TEXT = :text AND MODE = :mode")
|
||||||
|
fun load(text: String, mode: Int): Filter?
|
||||||
|
}
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import androidx.paging.PagingSource;
|
|
||||||
import androidx.room.Dao;
|
|
||||||
import androidx.room.Delete;
|
|
||||||
import androidx.room.Insert;
|
|
||||||
import androidx.room.Query;
|
|
||||||
import androidx.room.Update;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
public interface HistoryDao extends BasicDao<HistoryInfo> {
|
|
||||||
@Query("SELECT * FROM HISTORY WHERE GID = :gid")
|
|
||||||
HistoryInfo load(long gid);
|
|
||||||
|
|
||||||
@Query("SELECT * FROM HISTORY ORDER BY TIME DESC")
|
|
||||||
List<HistoryInfo> list();
|
|
||||||
|
|
||||||
@Query("SELECT * FROM HISTORY ORDER BY TIME DESC LIMIT :limit OFFSET :offset")
|
|
||||||
List<HistoryInfo> list(int offset, int limit);
|
|
||||||
|
|
||||||
@Query("SELECT * FROM HISTORY ORDER BY TIME DESC")
|
|
||||||
PagingSource<Integer, HistoryInfo> listLazy();
|
|
||||||
|
|
||||||
@Update
|
|
||||||
void update(HistoryInfo historyInfo);
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
long insert(HistoryInfo historyInfo);
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
void delete(HistoryInfo historyInfos);
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
void delete(List<HistoryInfo> historyInfos);
|
|
||||||
|
|
||||||
@Query("DELETE FROM HISTORY")
|
|
||||||
void deleteAll();
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.paging.PagingSource
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Update
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface HistoryDao : BasicDao<HistoryInfo> {
|
||||||
|
@Query("SELECT * FROM HISTORY WHERE GID = :gid")
|
||||||
|
fun load(gid: Long): HistoryInfo?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM HISTORY ORDER BY TIME DESC")
|
||||||
|
override fun list(): List<HistoryInfo>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM HISTORY ORDER BY TIME DESC LIMIT :limit OFFSET :offset")
|
||||||
|
fun list(offset: Int, limit: Int): List<HistoryInfo>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM HISTORY ORDER BY TIME DESC")
|
||||||
|
fun listLazy(): PagingSource<Int, HistoryInfo>
|
||||||
|
|
||||||
|
@Update
|
||||||
|
fun update(historyInfo: HistoryInfo)
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
override fun insert(t: HistoryInfo): Long
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(historyInfo: HistoryInfo)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(historyInfo: List<HistoryInfo>)
|
||||||
|
|
||||||
|
@Query("DELETE FROM HISTORY")
|
||||||
|
fun deleteAll()
|
||||||
|
}
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
|
||||||
import androidx.room.Entity;
|
|
||||||
|
|
||||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
|
||||||
|
|
||||||
@Entity(tableName = "HISTORY")
|
|
||||||
public class HistoryInfo extends GalleryInfo {
|
|
||||||
public static final Creator<HistoryInfo> CREATOR = new Creator<>() {
|
|
||||||
@Override
|
|
||||||
public HistoryInfo createFromParcel(Parcel source) {
|
|
||||||
return new HistoryInfo(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HistoryInfo[] newArray(int size) {
|
|
||||||
return new HistoryInfo[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ColumnInfo(name = "TIME")
|
|
||||||
public long time;
|
|
||||||
// Use MODE for favoriteSlot
|
|
||||||
@ColumnInfo(name = "MODE")
|
|
||||||
private int mode;
|
|
||||||
|
|
||||||
protected HistoryInfo(Parcel in) {
|
|
||||||
super(in);
|
|
||||||
this.mode = in.readInt();
|
|
||||||
this.time = in.readLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
public HistoryInfo(GalleryInfo galleryInfo) {
|
|
||||||
this.gid = galleryInfo.gid;
|
|
||||||
this.token = galleryInfo.token;
|
|
||||||
this.title = galleryInfo.title;
|
|
||||||
this.titleJpn = galleryInfo.titleJpn;
|
|
||||||
this.thumb = galleryInfo.thumb;
|
|
||||||
this.category = galleryInfo.category;
|
|
||||||
this.posted = galleryInfo.posted;
|
|
||||||
this.uploader = galleryInfo.uploader;
|
|
||||||
this.rating = galleryInfo.rating;
|
|
||||||
this.simpleTags = galleryInfo.simpleTags;
|
|
||||||
this.simpleLanguage = galleryInfo.simpleLanguage;
|
|
||||||
this.favoriteSlot = galleryInfo.favoriteSlot;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HistoryInfo(int mode, long time) {
|
|
||||||
this.favoriteSlot = mode - 2;
|
|
||||||
this.time = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getGid() {
|
|
||||||
return gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGid(long gid) {
|
|
||||||
this.gid = gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getToken() {
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToken(String token) {
|
|
||||||
this.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitleJpn() {
|
|
||||||
return titleJpn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitleJpn(String titleJpn) {
|
|
||||||
this.titleJpn = titleJpn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getThumb() {
|
|
||||||
return thumb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setThumb(String thumb) {
|
|
||||||
this.thumb = thumb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCategory() {
|
|
||||||
return category;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCategory(int category) {
|
|
||||||
this.category = category;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPosted() {
|
|
||||||
return posted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPosted(String posted) {
|
|
||||||
this.posted = posted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUploader() {
|
|
||||||
return uploader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUploader(String uploader) {
|
|
||||||
this.uploader = uploader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getRating() {
|
|
||||||
return rating;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRating(float rating) {
|
|
||||||
this.rating = rating;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSimpleLanguage() {
|
|
||||||
return simpleLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSimpleLanguage(String simpleLanguage) {
|
|
||||||
this.simpleLanguage = simpleLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMode() {
|
|
||||||
return favoriteSlot + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMode(int mode) {
|
|
||||||
this.favoriteSlot = mode - 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTime() {
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTime(long time) {
|
|
||||||
this.time = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
super.writeToParcel(dest, flags);
|
|
||||||
dest.writeInt(this.mode);
|
|
||||||
dest.writeLong(this.time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import com.hippo.ehviewer.client.data.GalleryInfo
|
||||||
|
|
||||||
|
@Entity(tableName = "HISTORY")
|
||||||
|
class HistoryInfo() : GalleryInfo() {
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "TIME")
|
||||||
|
var time: Long = 0
|
||||||
|
|
||||||
|
// Trick: Use MODE for favoriteSlot
|
||||||
|
// Shadow its accessors
|
||||||
|
@ColumnInfo(name = "MODE")
|
||||||
|
private val mode: Int = 0
|
||||||
|
|
||||||
|
fun getMode(): Int {
|
||||||
|
return favoriteSlot + 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setMode(mode: Int) {
|
||||||
|
favoriteSlot = mode - 2
|
||||||
|
}
|
||||||
|
// Trick end
|
||||||
|
|
||||||
|
constructor(galleryInfo: GalleryInfo) : this() {
|
||||||
|
gid = galleryInfo.gid
|
||||||
|
token = galleryInfo.token
|
||||||
|
title = galleryInfo.title
|
||||||
|
titleJpn = galleryInfo.titleJpn
|
||||||
|
thumb = galleryInfo.thumb
|
||||||
|
this.category = galleryInfo.category
|
||||||
|
posted = galleryInfo.posted
|
||||||
|
uploader = galleryInfo.uploader
|
||||||
|
rating = galleryInfo.rating
|
||||||
|
simpleTags = galleryInfo.simpleTags
|
||||||
|
simpleLanguage = galleryInfo.simpleLanguage
|
||||||
|
favoriteSlot = galleryInfo.favoriteSlot
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
|
||||||
import androidx.room.Entity;
|
|
||||||
|
|
||||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
|
||||||
|
|
||||||
@Entity(tableName = "LOCAL_FAVORITES")
|
|
||||||
public class LocalFavoriteInfo extends GalleryInfo {
|
|
||||||
|
|
||||||
public static final Creator<LocalFavoriteInfo> CREATOR = new Creator<>() {
|
|
||||||
@Override
|
|
||||||
public LocalFavoriteInfo createFromParcel(Parcel source) {
|
|
||||||
return new LocalFavoriteInfo(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LocalFavoriteInfo[] newArray(int size) {
|
|
||||||
return new LocalFavoriteInfo[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ColumnInfo(name = "TIME")
|
|
||||||
public long time;
|
|
||||||
|
|
||||||
protected LocalFavoriteInfo(Parcel in) {
|
|
||||||
super(in);
|
|
||||||
this.time = in.readLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocalFavoriteInfo(GalleryInfo galleryInfo) {
|
|
||||||
this.gid = galleryInfo.gid;
|
|
||||||
this.token = galleryInfo.token;
|
|
||||||
this.title = galleryInfo.title;
|
|
||||||
this.titleJpn = galleryInfo.titleJpn;
|
|
||||||
this.thumb = galleryInfo.thumb;
|
|
||||||
this.category = galleryInfo.category;
|
|
||||||
this.posted = galleryInfo.posted;
|
|
||||||
this.uploader = galleryInfo.uploader;
|
|
||||||
this.rating = galleryInfo.rating;
|
|
||||||
this.simpleTags = galleryInfo.simpleTags;
|
|
||||||
this.simpleLanguage = galleryInfo.simpleLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocalFavoriteInfo() {
|
|
||||||
this.favoriteSlot = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getGid() {
|
|
||||||
return gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGid(long gid) {
|
|
||||||
this.gid = gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getToken() {
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToken(String token) {
|
|
||||||
this.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitleJpn() {
|
|
||||||
return titleJpn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitleJpn(String titleJpn) {
|
|
||||||
this.titleJpn = titleJpn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getThumb() {
|
|
||||||
return thumb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setThumb(String thumb) {
|
|
||||||
this.thumb = thumb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCategory() {
|
|
||||||
return category;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCategory(int category) {
|
|
||||||
this.category = category;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPosted() {
|
|
||||||
return posted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPosted(String posted) {
|
|
||||||
this.posted = posted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUploader() {
|
|
||||||
return uploader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUploader(String uploader) {
|
|
||||||
this.uploader = uploader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getRating() {
|
|
||||||
return rating;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRating(float rating) {
|
|
||||||
this.rating = rating;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSimpleLanguage() {
|
|
||||||
return simpleLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSimpleLanguage(String simpleLanguage) {
|
|
||||||
this.simpleLanguage = simpleLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTime() {
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTime(long time) {
|
|
||||||
this.time = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
super.writeToParcel(dest, flags);
|
|
||||||
dest.writeLong(this.time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import com.hippo.ehviewer.client.data.GalleryInfo
|
||||||
|
|
||||||
|
@Entity(tableName = "LOCAL_FAVORITES")
|
||||||
|
class LocalFavoriteInfo() : GalleryInfo() {
|
||||||
|
@JvmField
|
||||||
|
@ColumnInfo(name = "TIME")
|
||||||
|
var time: Long = 0
|
||||||
|
|
||||||
|
constructor(galleryInfo: GalleryInfo) : this() {
|
||||||
|
gid = galleryInfo.gid
|
||||||
|
token = galleryInfo.token
|
||||||
|
title = galleryInfo.title
|
||||||
|
titleJpn = galleryInfo.titleJpn
|
||||||
|
thumb = galleryInfo.thumb
|
||||||
|
this.category = galleryInfo.category
|
||||||
|
posted = galleryInfo.posted
|
||||||
|
uploader = galleryInfo.uploader
|
||||||
|
rating = galleryInfo.rating
|
||||||
|
simpleTags = galleryInfo.simpleTags
|
||||||
|
simpleLanguage = galleryInfo.simpleLanguage
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
favoriteSlot = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import androidx.room.Dao;
|
|
||||||
import androidx.room.Delete;
|
|
||||||
import androidx.room.Insert;
|
|
||||||
import androidx.room.Query;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
public interface LocalFavoritesDao extends BasicDao<LocalFavoriteInfo> {
|
|
||||||
@Query("SELECT * FROM LOCAL_FAVORITES ORDER BY TIME DESC")
|
|
||||||
List<LocalFavoriteInfo> list();
|
|
||||||
|
|
||||||
@Query("SELECT * FROM LOCAL_FAVORITES WHERE TITLE LIKE :title ORDER BY TIME DESC")
|
|
||||||
List<LocalFavoriteInfo> list(String title);
|
|
||||||
|
|
||||||
@Query("SELECT * FROM LOCAL_FAVORITES WHERE GID = :gid")
|
|
||||||
LocalFavoriteInfo load(long gid);
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
long insert(LocalFavoriteInfo localFavoriteInfo);
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
void delete(LocalFavoriteInfo localFavoriteInfo);
|
|
||||||
|
|
||||||
@Query("DELETE FROM LOCAL_FAVORITES WHERE GID = :gid")
|
|
||||||
void deleteByKey(long gid);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface LocalFavoritesDao : BasicDao<LocalFavoriteInfo> {
|
||||||
|
@Query("SELECT * FROM LOCAL_FAVORITES ORDER BY TIME DESC")
|
||||||
|
override fun list(): List<LocalFavoriteInfo>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM LOCAL_FAVORITES WHERE TITLE LIKE :title ORDER BY TIME DESC")
|
||||||
|
fun list(title: String): List<LocalFavoriteInfo>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM LOCAL_FAVORITES WHERE GID = :gid")
|
||||||
|
fun load(gid: Long): LocalFavoriteInfo?
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
override fun insert(t: LocalFavoriteInfo): Long
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(localFavoriteInfo: LocalFavoriteInfo)
|
||||||
|
|
||||||
|
@Query("DELETE FROM LOCAL_FAVORITES WHERE GID = :gid")
|
||||||
|
fun deleteByKey(gid: Long)
|
||||||
|
}
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.room.ColumnInfo;
|
|
||||||
import androidx.room.Entity;
|
|
||||||
import androidx.room.PrimaryKey;
|
|
||||||
|
|
||||||
@Entity(tableName = "QUICK_SEARCH")
|
|
||||||
public class QuickSearch {
|
|
||||||
@PrimaryKey
|
|
||||||
@ColumnInfo(name = "_id")
|
|
||||||
public Long id;
|
|
||||||
@ColumnInfo(name = "NAME")
|
|
||||||
public String name;
|
|
||||||
@ColumnInfo(name = "MODE")
|
|
||||||
public int mode;
|
|
||||||
@ColumnInfo(name = "CATEGORY")
|
|
||||||
public int category;
|
|
||||||
@ColumnInfo(name = "KEYWORD")
|
|
||||||
public String keyword;
|
|
||||||
@ColumnInfo(name = "ADVANCE_SEARCH")
|
|
||||||
public int advanceSearch;
|
|
||||||
@ColumnInfo(name = "MIN_RATING")
|
|
||||||
public int minRating;
|
|
||||||
@ColumnInfo(name = "PAGE_FROM")
|
|
||||||
public int pageFrom;
|
|
||||||
@ColumnInfo(name = "PAGE_TO")
|
|
||||||
public int pageTo;
|
|
||||||
@ColumnInfo(name = "TIME")
|
|
||||||
public long time;
|
|
||||||
|
|
||||||
public Long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMode() {
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMode(int mode) {
|
|
||||||
this.mode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCategory() {
|
|
||||||
return category;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCategory(int category) {
|
|
||||||
this.category = category;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getKeyword() {
|
|
||||||
return keyword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKeyword(String keyword) {
|
|
||||||
this.keyword = keyword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAdvanceSearch() {
|
|
||||||
return advanceSearch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAdvanceSearch(int advanceSearch) {
|
|
||||||
this.advanceSearch = advanceSearch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMinRating() {
|
|
||||||
return minRating;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMinRating(int minRating) {
|
|
||||||
this.minRating = minRating;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPageFrom() {
|
|
||||||
return pageFrom;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPageFrom(int pageFrom) {
|
|
||||||
this.pageFrom = pageFrom;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPageTo() {
|
|
||||||
return pageTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPageTo(int pageTo) {
|
|
||||||
this.pageTo = pageTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTime() {
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTime(long time) {
|
|
||||||
this.time = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "QUICK_SEARCH")
|
||||||
|
data class QuickSearch(
|
||||||
|
@PrimaryKey
|
||||||
|
@ColumnInfo(name = "_id")
|
||||||
|
var id: Long? = null,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "NAME")
|
||||||
|
var name: String? = null,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "MODE")
|
||||||
|
var mode: Int = 0,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "CATEGORY")
|
||||||
|
var category: Int = 0,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "KEYWORD")
|
||||||
|
var keyword: String? = null,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "ADVANCE_SEARCH")
|
||||||
|
var advanceSearch: Int = 0,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "MIN_RATING")
|
||||||
|
var minRating: Int = 0,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "PAGE_FROM")
|
||||||
|
var pageFrom: Int = 0,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "PAGE_TO")
|
||||||
|
var pageTo: Int = 0,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "TIME")
|
||||||
|
var time: Long = 0
|
||||||
|
)
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package com.hippo.ehviewer.dao;
|
|
||||||
|
|
||||||
import androidx.room.Dao;
|
|
||||||
import androidx.room.Delete;
|
|
||||||
import androidx.room.Insert;
|
|
||||||
import androidx.room.Query;
|
|
||||||
import androidx.room.Update;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
public interface QuickSearchDao extends BasicDao<QuickSearch> {
|
|
||||||
@Query("SELECT * FROM QUICK_SEARCH ORDER BY TIME ASC")
|
|
||||||
List<QuickSearch> list();
|
|
||||||
|
|
||||||
@Query("SELECT * FROM QUICK_SEARCH ORDER BY TIME ASC LIMIT :limit OFFSET :offset")
|
|
||||||
List<QuickSearch> list(int offset, int limit);
|
|
||||||
|
|
||||||
@Update
|
|
||||||
void update(List<QuickSearch> downloadLabels);
|
|
||||||
|
|
||||||
@Update
|
|
||||||
void update(QuickSearch quickSearch);
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
long insert(QuickSearch quickSearch);
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
void delete(QuickSearch quickSearch);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.hippo.ehviewer.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Update
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface QuickSearchDao : BasicDao<QuickSearch> {
|
||||||
|
@Query("SELECT * FROM QUICK_SEARCH ORDER BY TIME ASC")
|
||||||
|
override fun list(): List<QuickSearch>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM QUICK_SEARCH ORDER BY TIME ASC LIMIT :limit OFFSET :offset")
|
||||||
|
fun list(offset: Int, limit: Int): List<QuickSearch>
|
||||||
|
|
||||||
|
@Update
|
||||||
|
fun update(downloadLabels: List<QuickSearch>)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
fun update(quickSearch: QuickSearch)
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
override fun insert(t: QuickSearch): Long
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(quickSearch: QuickSearch?)
|
||||||
|
}
|
||||||
@@ -588,11 +588,11 @@ public class DownloadManager implements SpiderQueen.OnSpiderListener {
|
|||||||
galleryInfo.uploader = downloadInfo.uploader;
|
galleryInfo.uploader = downloadInfo.uploader;
|
||||||
galleryInfo.rating = downloadInfo.rating;
|
galleryInfo.rating = downloadInfo.rating;
|
||||||
|
|
||||||
UniFile downloadDir = SpiderDen.getGalleryDownloadDir(galleryInfo);
|
UniFile downloadDir = SpiderDen.getGalleryDownloadDir(galleryInfo.gid);
|
||||||
if (downloadDir == null) {
|
if (downloadDir == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
UniFile file = downloadDir.findFile(".ehviewer");
|
UniFile file = downloadDir.findFile(SpiderQueen.SPIDER_INFO_FILENAME);
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import java.io.IOException;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
@@ -187,6 +188,11 @@ public class ArchivePageLoader extends PageLoader2 {
|
|||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void preloadPages(@NonNull List<Integer> pages) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private class ArchiveHostTask implements Runnable {
|
private class ArchiveHostTask implements Runnable {
|
||||||
public final Thread[] archiveThreads = new Thread[]{
|
public final Thread[] archiveThreads = new Thread[]{
|
||||||
new Thread(new ArchiveTask()),
|
new Thread(new ArchiveTask()),
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import com.hippo.image.Image;
|
|||||||
import com.hippo.unifile.UniFile;
|
import com.hippo.unifile.UniFile;
|
||||||
import com.hippo.yorozuya.SimpleHandler;
|
import com.hippo.yorozuya.SimpleHandler;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.ui.reader.loader.PageLoader;
|
import eu.kanade.tachiyomi.ui.reader.loader.PageLoader;
|
||||||
@@ -207,6 +208,13 @@ public class EhPageLoader extends PageLoader2 implements SpiderQueen.OnSpiderLis
|
|||||||
notifyPageFailed(index);
|
notifyPageFailed(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void preloadPages(@NonNull List<Integer> pages) {
|
||||||
|
if (mSpiderQueen != null) {
|
||||||
|
mSpiderQueen.preloadPages(pages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class ReleaseTask implements Runnable {
|
private static class ReleaseTask implements Runnable {
|
||||||
|
|
||||||
private SpiderQueen mSpiderQueen;
|
private SpiderQueen mSpiderQueen;
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.preference;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
|
|
||||||
import com.hippo.ehviewer.EhDB;
|
|
||||||
import com.hippo.ehviewer.R;
|
|
||||||
import com.hippo.preference.MessagePreference;
|
|
||||||
|
|
||||||
public class ClearDownloadPathCachePreference extends MessagePreference {
|
|
||||||
|
|
||||||
public ClearDownloadPathCachePreference(Context context) {
|
|
||||||
super(context);
|
|
||||||
init(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClearDownloadPathCachePreference(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
init(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClearDownloadPathCachePreference(Context context,
|
|
||||||
AttributeSet attrs, int defStyleAttr) {
|
|
||||||
super(context, attrs, defStyleAttr);
|
|
||||||
init(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init(Context context) {
|
|
||||||
setDialogMessage(context.getString(R.string.settings_advanced_clear_download_path_cache_message));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
|
|
||||||
super.onPrepareDialogBuilder(builder);
|
|
||||||
builder.setTitle(null);
|
|
||||||
builder.setNegativeButton(android.R.string.cancel, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDialogClosed(boolean positiveResult) {
|
|
||||||
super.onDialogClosed(positiveResult);
|
|
||||||
|
|
||||||
if (positiveResult) {
|
|
||||||
EhDB.clearDownloadDirname();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,221 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.preference;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
|
|
||||||
import com.hippo.ehviewer.EhApplication;
|
|
||||||
import com.hippo.ehviewer.EhDB;
|
|
||||||
import com.hippo.ehviewer.R;
|
|
||||||
import com.hippo.ehviewer.Settings;
|
|
||||||
import com.hippo.ehviewer.client.EhEngine;
|
|
||||||
import com.hippo.ehviewer.client.EhUrl;
|
|
||||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
|
||||||
import com.hippo.ehviewer.download.DownloadManager;
|
|
||||||
import com.hippo.ehviewer.spider.SpiderInfo;
|
|
||||||
import com.hippo.ehviewer.spider.SpiderQueen;
|
|
||||||
import com.hippo.ehviewer.ui.scene.BaseScene;
|
|
||||||
import com.hippo.unifile.UniFile;
|
|
||||||
import com.hippo.util.ExceptionUtils;
|
|
||||||
import com.hippo.yorozuya.IOUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
|
|
||||||
public class RestoreDownloadPreference extends TaskPreference {
|
|
||||||
|
|
||||||
public RestoreDownloadPreference(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RestoreDownloadPreference(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RestoreDownloadPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
||||||
super(context, attrs, defStyleAttr);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
protected Task onCreateTask() {
|
|
||||||
return new RestoreTask(getContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class RestoreTask extends Task {
|
|
||||||
|
|
||||||
private final DownloadManager mManager;
|
|
||||||
private final OkHttpClient mHttpClient;
|
|
||||||
|
|
||||||
public RestoreTask(@NonNull Context context) {
|
|
||||||
super(context);
|
|
||||||
mManager = EhApplication.getDownloadManager();
|
|
||||||
mHttpClient = EhApplication.getOkHttpClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
private RestoreItem getRestoreItem(UniFile file) {
|
|
||||||
if (null == file || !file.isDirectory()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
UniFile siFile = file.findFile(SpiderQueen.SPIDER_INFO_FILENAME);
|
|
||||||
if (null == siFile) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
InputStream is = null;
|
|
||||||
try {
|
|
||||||
is = siFile.openInputStream();
|
|
||||||
SpiderInfo spiderInfo = SpiderInfo.read(is);
|
|
||||||
if (spiderInfo == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
long gid = spiderInfo.gid;
|
|
||||||
if (mManager.containDownloadInfo(gid)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String token = spiderInfo.token;
|
|
||||||
RestoreItem restoreItem = new RestoreItem();
|
|
||||||
restoreItem.gid = gid;
|
|
||||||
restoreItem.token = token;
|
|
||||||
restoreItem.dirname = file.getName();
|
|
||||||
return restoreItem;
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
} finally {
|
|
||||||
IOUtils.closeQuietly(is);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object doInBackground(Void... params) {
|
|
||||||
UniFile dir = Settings.getDownloadLocation();
|
|
||||||
if (null == dir) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<RestoreItem> restoreItemList = new ArrayList<>();
|
|
||||||
|
|
||||||
UniFile[] files = dir.listFiles();
|
|
||||||
if (files == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (UniFile file : files) {
|
|
||||||
RestoreItem restoreItem = getRestoreItem(file);
|
|
||||||
if (null != restoreItem) {
|
|
||||||
restoreItemList.add(restoreItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == restoreItemList.size()) {
|
|
||||||
return Collections.EMPTY_LIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return EhEngine.fillGalleryListByApi(null, mHttpClient, new ArrayList<>(restoreItemList), EhUrl.getReferer());
|
|
||||||
} catch (Throwable e) {
|
|
||||||
ExceptionUtils.throwIfFatal(e);
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected void onPostExecute(Object o) {
|
|
||||||
if (!(o instanceof List)) {
|
|
||||||
mActivity.showTip(R.string.settings_download_restore_failed, BaseScene.LENGTH_SHORT);
|
|
||||||
} else {
|
|
||||||
List<RestoreItem> list = (List<RestoreItem>) o;
|
|
||||||
if (list.isEmpty()) {
|
|
||||||
mActivity.showTip(R.string.settings_download_restore_not_found, BaseScene.LENGTH_SHORT);
|
|
||||||
} else {
|
|
||||||
int count = 0;
|
|
||||||
for (int i = 0, n = list.size(); i < n; i++) {
|
|
||||||
RestoreItem item = list.get(i);
|
|
||||||
// Avoid failed gallery info
|
|
||||||
if (null != item.title) {
|
|
||||||
// Put to download
|
|
||||||
mManager.addDownload(item, null);
|
|
||||||
// Put download dir to DB
|
|
||||||
EhDB.putDownloadDirname(item.gid, item.dirname);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
showTip(
|
|
||||||
mActivity.getString(R.string.settings_download_restore_successfully, count),
|
|
||||||
BaseScene.LENGTH_SHORT);
|
|
||||||
|
|
||||||
Preference preference = getPreference();
|
|
||||||
if (null != preference) {
|
|
||||||
Context context = preference.getContext();
|
|
||||||
if (context instanceof Activity) {
|
|
||||||
((Activity) context).setResult(Activity.RESULT_OK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.onPostExecute(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class RestoreItem extends GalleryInfo {
|
|
||||||
|
|
||||||
public static final Creator<RestoreItem> CREATOR = new Creator<RestoreItem>() {
|
|
||||||
@Override
|
|
||||||
public RestoreItem createFromParcel(Parcel source) {
|
|
||||||
return new RestoreItem(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RestoreItem[] newArray(int size) {
|
|
||||||
return new RestoreItem[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
public String dirname;
|
|
||||||
|
|
||||||
public RestoreItem() {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected RestoreItem(Parcel in) {
|
|
||||||
super(in);
|
|
||||||
this.dirname = in.readString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
super.writeToParcel(dest, flags);
|
|
||||||
dest.writeString(this.dirname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.preference
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import com.hippo.ehviewer.EhApplication.Companion.downloadManager
|
||||||
|
import com.hippo.ehviewer.EhApplication.Companion.okHttpClient
|
||||||
|
import com.hippo.ehviewer.EhDB
|
||||||
|
import com.hippo.ehviewer.R
|
||||||
|
import com.hippo.ehviewer.Settings
|
||||||
|
import com.hippo.ehviewer.client.EhEngine.fillGalleryListByApi
|
||||||
|
import com.hippo.ehviewer.client.EhUrl
|
||||||
|
import com.hippo.ehviewer.client.data.GalleryInfo
|
||||||
|
import com.hippo.ehviewer.download.DownloadManager
|
||||||
|
import com.hippo.ehviewer.spider.SpiderInfo
|
||||||
|
import com.hippo.ehviewer.spider.SpiderQueen
|
||||||
|
import com.hippo.ehviewer.ui.scene.BaseScene
|
||||||
|
import com.hippo.unifile.UniFile
|
||||||
|
import com.hippo.util.ExceptionUtils
|
||||||
|
import com.hippo.yorozuya.IOUtils
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.util.Collections
|
||||||
|
|
||||||
|
class RestoreDownloadPreference constructor(
|
||||||
|
context: Context, attrs: AttributeSet?
|
||||||
|
) : TaskPreference(context, attrs) {
|
||||||
|
override fun onCreateTask(): Task {
|
||||||
|
return RestoreTask(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RestoreTask(context: Context) : Task(context) {
|
||||||
|
private val mManager: DownloadManager = downloadManager
|
||||||
|
private val mHttpClient: OkHttpClient = okHttpClient
|
||||||
|
private var restoreDirCount = 0
|
||||||
|
private fun getRestoreItem(file: UniFile?): RestoreItem? {
|
||||||
|
if (null == file || !file.isDirectory) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val siFile = file.findFile(SpiderQueen.SPIDER_INFO_FILENAME) ?: return null
|
||||||
|
var `is`: InputStream? = null
|
||||||
|
return try {
|
||||||
|
`is` = siFile.openInputStream()
|
||||||
|
val spiderInfo = SpiderInfo.read(`is`) ?: return null
|
||||||
|
val gid = spiderInfo.gid
|
||||||
|
val dirname = file.name
|
||||||
|
if (mManager.containDownloadInfo(gid)) {
|
||||||
|
// Restore download dir to avoid redownload
|
||||||
|
val dbdirname = EhDB.getDownloadDirname(gid)
|
||||||
|
if (null == dbdirname || dirname != dbdirname) {
|
||||||
|
EhDB.putDownloadDirname(gid, dirname)
|
||||||
|
restoreDirCount++
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val token = spiderInfo.token
|
||||||
|
val restoreItem = RestoreItem()
|
||||||
|
restoreItem.gid = gid
|
||||||
|
restoreItem.token = token
|
||||||
|
restoreItem.dirname = dirname
|
||||||
|
restoreItem
|
||||||
|
} catch (e: IOException) {
|
||||||
|
null
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(`is`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doInBackground(vararg params: Void): Any? {
|
||||||
|
val dir = Settings.getDownloadLocation() ?: return null
|
||||||
|
val restoreItemList: MutableList<RestoreItem> = ArrayList()
|
||||||
|
val files = dir.listFiles() ?: return null
|
||||||
|
for (file in files) {
|
||||||
|
val restoreItem = getRestoreItem(file)
|
||||||
|
if (null != restoreItem) {
|
||||||
|
restoreItemList.add(restoreItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return if (0 == restoreItemList.size) {
|
||||||
|
Collections.EMPTY_LIST
|
||||||
|
} else try {
|
||||||
|
runBlocking {
|
||||||
|
fillGalleryListByApi(
|
||||||
|
mHttpClient,
|
||||||
|
ArrayList(restoreItemList),
|
||||||
|
EhUrl.getReferer()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
ExceptionUtils.throwIfFatal(e)
|
||||||
|
e.printStackTrace()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPostExecute(o: Any) {
|
||||||
|
if (o !is List<*>) {
|
||||||
|
mActivity.showTip(R.string.settings_download_restore_failed, BaseScene.LENGTH_SHORT)
|
||||||
|
} else {
|
||||||
|
val list = o as List<RestoreItem>
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
mActivity.showTip(
|
||||||
|
if (restoreDirCount == 0)
|
||||||
|
mActivity.getString(R.string.settings_download_restore_not_found)
|
||||||
|
else
|
||||||
|
mActivity.getString(
|
||||||
|
R.string.settings_download_restore_successfully,
|
||||||
|
restoreDirCount
|
||||||
|
),
|
||||||
|
BaseScene.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
var count = 0
|
||||||
|
var i = 0
|
||||||
|
val n = list.size
|
||||||
|
while (i < n) {
|
||||||
|
val item = list[i]
|
||||||
|
// Avoid failed gallery info
|
||||||
|
if (null != item.title) {
|
||||||
|
// Put to download
|
||||||
|
mManager.addDownload(item, null)
|
||||||
|
// Put download dir to DB
|
||||||
|
EhDB.putDownloadDirname(item.gid, item.dirname)
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
showTip(
|
||||||
|
mActivity.getString(
|
||||||
|
R.string.settings_download_restore_successfully,
|
||||||
|
count + restoreDirCount
|
||||||
|
),
|
||||||
|
BaseScene.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
val preference: Preference? = preference
|
||||||
|
if (null != preference) {
|
||||||
|
val context = preference.context
|
||||||
|
if (context is Activity) {
|
||||||
|
context.setResult(Activity.RESULT_OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onPostExecute(o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RestoreItem : GalleryInfo() {
|
||||||
|
var dirname: String? = null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,6 @@ import com.hippo.io.UniFileInputStreamPipe;
|
|||||||
import com.hippo.io.UniFileOutputStreamPipe;
|
import com.hippo.io.UniFileOutputStreamPipe;
|
||||||
import com.hippo.streampipe.InputStreamPipe;
|
import com.hippo.streampipe.InputStreamPipe;
|
||||||
import com.hippo.streampipe.OutputStreamPipe;
|
import com.hippo.streampipe.OutputStreamPipe;
|
||||||
import com.hippo.unifile.FilenameFilter;
|
|
||||||
import com.hippo.unifile.UniFile;
|
import com.hippo.unifile.UniFile;
|
||||||
import com.hippo.yorozuya.FileUtils;
|
import com.hippo.yorozuya.FileUtils;
|
||||||
import com.hippo.yorozuya.IOUtils;
|
import com.hippo.yorozuya.IOUtils;
|
||||||
@@ -49,14 +48,16 @@ public final class SpiderDen {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static SimpleDiskCache sCache;
|
private static SimpleDiskCache sCache;
|
||||||
@Nullable
|
private final GalleryInfo mGalleryInfo;
|
||||||
private final UniFile mDownloadDir;
|
|
||||||
private final long mGid;
|
private final long mGid;
|
||||||
|
@Nullable
|
||||||
|
private UniFile mDownloadDir;
|
||||||
private volatile int mMode = SpiderQueen.MODE_READ;
|
private volatile int mMode = SpiderQueen.MODE_READ;
|
||||||
|
|
||||||
public SpiderDen(GalleryInfo galleryInfo) {
|
public SpiderDen(GalleryInfo galleryInfo) {
|
||||||
|
mGalleryInfo = galleryInfo;
|
||||||
mGid = galleryInfo.gid;
|
mGid = galleryInfo.gid;
|
||||||
mDownloadDir = getGalleryDownloadDir(galleryInfo);
|
mDownloadDir = getGalleryDownloadDir(galleryInfo.gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initialize(Context context) {
|
public static void initialize(Context context) {
|
||||||
@@ -64,45 +65,14 @@ public final class SpiderDen {
|
|||||||
MathUtils.clamp(Settings.getReadCacheSize(), 40, 1280) * 1024 * 1024);
|
MathUtils.clamp(Settings.getReadCacheSize(), 40, 1280) * 1024 * 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniFile getGalleryDownloadDir(GalleryInfo galleryInfo) {
|
public static UniFile getGalleryDownloadDir(long gid) {
|
||||||
UniFile dir = Settings.getDownloadLocation();
|
UniFile dir = Settings.getDownloadLocation();
|
||||||
if (dir != null) {
|
// Read from DB
|
||||||
// Read from DB
|
String dirname = EhDB.getDownloadDirname(gid);
|
||||||
String dirname = EhDB.getDownloadDirname(galleryInfo.gid);
|
if (dir != null && dirname != null) {
|
||||||
if (null != dirname) {
|
// Some dirname may be invalid in some version
|
||||||
// Some dirname may be invalid in some version
|
dirname = FileUtils.sanitizeFilename(dirname);
|
||||||
dirname = FileUtils.sanitizeFilename(dirname);
|
EhDB.putDownloadDirname(gid, dirname);
|
||||||
EhDB.putDownloadDirname(galleryInfo.gid, dirname);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find it
|
|
||||||
if (null == dirname) {
|
|
||||||
UniFile[] files = dir.listFiles(new StartWithFilenameFilter(galleryInfo.gid + "-"));
|
|
||||||
if (null != files) {
|
|
||||||
// Get max-length-name dir
|
|
||||||
int maxLength = -1;
|
|
||||||
for (UniFile file : files) {
|
|
||||||
if (file.isDirectory()) {
|
|
||||||
String name = file.getName();
|
|
||||||
int length = name.length();
|
|
||||||
if (length > maxLength) {
|
|
||||||
maxLength = length;
|
|
||||||
dirname = name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (null != dirname) {
|
|
||||||
EhDB.putDownloadDirname(galleryInfo.gid, dirname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create it
|
|
||||||
if (null == dirname) {
|
|
||||||
dirname = FileUtils.sanitizeFilename(galleryInfo.gid + "-" + EhUtils.getSuitableTitle(galleryInfo));
|
|
||||||
EhDB.putDownloadDirname(galleryInfo.gid, dirname);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dir.subFile(dirname);
|
return dir.subFile(dirname);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@@ -137,6 +107,11 @@ public final class SpiderDen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean ensureDownloadDir() {
|
private boolean ensureDownloadDir() {
|
||||||
|
if (mDownloadDir == null) {
|
||||||
|
var dirname = FileUtils.sanitizeFilename(mGid + "-" + EhUtils.getSuitableTitle(mGalleryInfo));
|
||||||
|
EhDB.putDownloadDirname(mGid, dirname);
|
||||||
|
mDownloadDir = getGalleryDownloadDir(mGid);
|
||||||
|
}
|
||||||
return mDownloadDir != null && mDownloadDir.ensureDir();
|
return mDownloadDir != null && mDownloadDir.ensureDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +125,9 @@ public final class SpiderDen {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public UniFile getDownloadDir() {
|
public UniFile getDownloadDir() {
|
||||||
|
if (mDownloadDir == null) {
|
||||||
|
mDownloadDir = getGalleryDownloadDir(mGid);
|
||||||
|
}
|
||||||
return mDownloadDir != null && mDownloadDir.isDirectory() ? mDownloadDir : null;
|
return mDownloadDir != null && mDownloadDir.isDirectory() ? mDownloadDir : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,17 +341,4 @@ public final class SpiderDen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class StartWithFilenameFilter implements FilenameFilter {
|
|
||||||
|
|
||||||
private final String mPrefix;
|
|
||||||
|
|
||||||
public StartWithFilenameFilter(String prefix) {
|
|
||||||
mPrefix = prefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean accept(UniFile dir, String filename) {
|
|
||||||
return filename.startsWith(mPrefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -364,6 +364,7 @@ public final class SpiderQueen implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateMode();
|
updateMode();
|
||||||
|
writeSpiderInfoToLocal();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearMode(@Mode int mode) {
|
private void clearMode(@Mode int mode) {
|
||||||
@@ -460,6 +461,19 @@ public final class SpiderQueen implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void preloadPages(@NonNull List<Integer> pages) {
|
||||||
|
if (mQueenThread == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (mRequestPageQueue) {
|
||||||
|
pages.removeAll(mRequestPageQueue);
|
||||||
|
pages.removeAll(mRequestPageQueue2);
|
||||||
|
pages.removeAll(mDecodeRequestQueue);
|
||||||
|
mRequestPageQueue2.addAll(pages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String for error<br>
|
* @return String for error<br>
|
||||||
* Float for download percent<br>
|
* Float for download percent<br>
|
||||||
@@ -826,6 +840,13 @@ public final class SpiderQueen implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writeSpiderInfoToLocal() {
|
||||||
|
var spiderInfo = mSpiderInfo.get();
|
||||||
|
if (spiderInfo != null) {
|
||||||
|
writeSpiderInfoToLocal(spiderInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized void writeSpiderInfoToLocal(@NonNull SpiderInfo spiderInfo) {
|
private synchronized void writeSpiderInfoToLocal(@NonNull SpiderInfo spiderInfo) {
|
||||||
// Write to download dir
|
// Write to download dir
|
||||||
UniFile downloadDir = mSpiderDen.getDownloadDir();
|
UniFile downloadDir = mSpiderDen.getDownloadDir();
|
||||||
@@ -1094,7 +1115,7 @@ public final class SpiderQueen implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private GalleryPageParser.Result fetchPageResultFromHtml(int index, String pageUrl) throws Throwable {
|
private GalleryPageParser.Result fetchPageResultFromHtml(int index, String pageUrl) throws Throwable {
|
||||||
GalleryPageParser.Result result = EhEngine.getGalleryPage(null, mHttpClient, pageUrl, mGalleryInfo.gid, mGalleryInfo.token);
|
GalleryPageParser.Result result = EhEngine.getGalleryPage(mHttpClient, pageUrl, mGalleryInfo.gid, mGalleryInfo.token);
|
||||||
if (StringUtils.endsWith(result.imageUrl, URL_509_SUFFIX_ARRAY)) {
|
if (StringUtils.endsWith(result.imageUrl, URL_509_SUFFIX_ARRAY)) {
|
||||||
// Get 509
|
// Get 509
|
||||||
// Notify listeners
|
// Notify listeners
|
||||||
@@ -1106,7 +1127,7 @@ public final class SpiderQueen implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private GalleryPageApiParser.Result fetchPageResultFromApi(long gid, int index, String pToken, String showKey, String previousPToken) throws Throwable {
|
private GalleryPageApiParser.Result fetchPageResultFromApi(long gid, int index, String pToken, String showKey, String previousPToken) throws Throwable {
|
||||||
GalleryPageApiParser.Result result = EhEngine.getGalleryPageApi(null, mHttpClient, gid, index, pToken, showKey, previousPToken);
|
GalleryPageApiParser.Result result = EhEngine.getGalleryPageApi(mHttpClient, gid, index, pToken, showKey, previousPToken);
|
||||||
if (StringUtils.endsWith(result.imageUrl, URL_509_SUFFIX_ARRAY)) {
|
if (StringUtils.endsWith(result.imageUrl, URL_509_SUFFIX_ARRAY)) {
|
||||||
// Get 509
|
// Get 509
|
||||||
// Notify listeners
|
// Notify listeners
|
||||||
|
|||||||
@@ -53,12 +53,12 @@ public final class CommonOperations {
|
|||||||
EhDB.putLocalFavorites(galleryInfo);
|
EhDB.putLocalFavorites(galleryInfo);
|
||||||
listener.onSuccess(null);
|
listener.onSuccess(null);
|
||||||
} else if (slot >= 0 && slot <= 9) {
|
} else if (slot >= 0 && slot <= 9) {
|
||||||
EhClient client = EhApplication.getEhClient();
|
EhClient client = EhClient.INSTANCE;
|
||||||
EhRequest request = new EhRequest();
|
EhRequest request = new EhRequest();
|
||||||
request.setMethod(EhClient.METHOD_ADD_FAVORITES);
|
request.setMethod(EhClient.METHOD_ADD_FAVORITES);
|
||||||
request.setArgs(galleryInfo.gid, galleryInfo.token, slot, "");
|
request.setArgs(galleryInfo.gid, galleryInfo.token, slot, "");
|
||||||
request.setCallback(listener);
|
request.setCallback(listener);
|
||||||
client.execute(request);
|
request.enqueue(activity);
|
||||||
} else {
|
} else {
|
||||||
listener.onFailure(new Exception()); // TODO Add text
|
listener.onFailure(new Exception()); // TODO Add text
|
||||||
}
|
}
|
||||||
@@ -100,12 +100,12 @@ public final class CommonOperations {
|
|||||||
public static void removeFromFavorites(Activity activity, GalleryInfo galleryInfo,
|
public static void removeFromFavorites(Activity activity, GalleryInfo galleryInfo,
|
||||||
final EhClient.Callback<Void> listener) {
|
final EhClient.Callback<Void> listener) {
|
||||||
EhDB.removeLocalFavorites(galleryInfo.gid);
|
EhDB.removeLocalFavorites(galleryInfo.gid);
|
||||||
EhClient client = EhApplication.getEhClient();
|
EhClient client = EhClient.INSTANCE;
|
||||||
EhRequest request = new EhRequest();
|
EhRequest request = new EhRequest();
|
||||||
request.setMethod(EhClient.METHOD_ADD_FAVORITES);
|
request.setMethod(EhClient.METHOD_ADD_FAVORITES);
|
||||||
request.setArgs(galleryInfo.gid, galleryInfo.token, -1, "");
|
request.setArgs(galleryInfo.gid, galleryInfo.token, -1, "");
|
||||||
request.setCallback(new DelegateFavoriteCallback(listener, galleryInfo, null, -2));
|
request.setCallback(new DelegateFavoriteCallback(listener, galleryInfo, null, -2));
|
||||||
client.execute(request);
|
request.enqueue(activity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startDownload(final MainActivity activity, final GalleryInfo galleryInfo, boolean forceDefault) {
|
public static void startDownload(final MainActivity activity, final GalleryInfo galleryInfo, boolean forceDefault) {
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ abstract class EhActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
layoutInflater.factory2 = LayoutInflaterFactory(delegate).addOnViewCreatedListener(WindowInsetsHelper.LISTENER)
|
layoutInflater.factory2 =
|
||||||
|
LayoutInflaterFactory(delegate).addOnViewCreatedListener(WindowInsetsHelper.LISTENER)
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
(application as EhApplication).registerActivity(this)
|
(application as EhApplication).registerActivity(this)
|
||||||
}
|
}
|
||||||
@@ -78,7 +79,11 @@ abstract class EhActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||||
fun checkAndRequestNotificationPermission() {
|
fun checkAndRequestNotificationPermission() {
|
||||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) return
|
if (ContextCompat.checkSelfPermission(
|
||||||
|
this,
|
||||||
|
Manifest.permission.POST_NOTIFICATIONS
|
||||||
|
) == PackageManager.PERMISSION_GRANTED
|
||||||
|
) return
|
||||||
if (Settings.getNotificationRequired()) return
|
if (Settings.getNotificationRequired()) return
|
||||||
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,12 +29,11 @@ import com.hippo.ehviewer.UrlOpener
|
|||||||
import com.hippo.ehviewer.client.EhUrl
|
import com.hippo.ehviewer.client.EhUrl
|
||||||
import com.hippo.ehviewer.client.EhUtils
|
import com.hippo.ehviewer.client.EhUtils
|
||||||
import com.hippo.ehviewer.client.data.GalleryDetail
|
import com.hippo.ehviewer.client.data.GalleryDetail
|
||||||
import com.hippo.util.addTextToClipboard
|
|
||||||
import com.hippo.util.tellClipboard
|
import com.hippo.util.tellClipboard
|
||||||
|
|
||||||
class GalleryInfoBottomSheet(detail: GalleryDetail) : BottomSheetDialogFragment() {
|
class GalleryInfoBottomSheet(detail: GalleryDetail) : BottomSheetDialogFragment() {
|
||||||
private var mKeys: ArrayList<String> = arrayListOf()
|
private var mKeys: ArrayList<String> = arrayListOf()
|
||||||
private var mValues: ArrayList<String> = arrayListOf()
|
private var mValues: ArrayList<String?> = arrayListOf()
|
||||||
private var mRecyclerView: RecyclerView? = null
|
private var mRecyclerView: RecyclerView? = null
|
||||||
private val mDetail: GalleryDetail = detail
|
private val mDetail: GalleryDetail = detail
|
||||||
|
|
||||||
|
|||||||
@@ -1,661 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.ui;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.pm.verify.domain.DomainVerificationManager;
|
|
||||||
import android.content.pm.verify.domain.DomainVerificationUserState;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.net.ConnectivityManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.PersistableBundle;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.activity.OnBackPressedCallback;
|
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts;
|
|
||||||
import androidx.annotation.IdRes;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
import androidx.core.view.GravityCompat;
|
|
||||||
import androidx.drawerlayout.widget.DrawerLayout;
|
|
||||||
|
|
||||||
import com.google.android.material.navigation.NavigationView;
|
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
|
||||||
import com.hippo.app.BaseDialogBuilder;
|
|
||||||
import com.hippo.app.EditTextDialogBuilder;
|
|
||||||
import com.hippo.ehviewer.AppConfig;
|
|
||||||
import com.hippo.ehviewer.R;
|
|
||||||
import com.hippo.ehviewer.Settings;
|
|
||||||
import com.hippo.ehviewer.client.EhUrlOpener;
|
|
||||||
import com.hippo.ehviewer.client.EhUtils;
|
|
||||||
import com.hippo.ehviewer.client.data.ListUrlBuilder;
|
|
||||||
import com.hippo.ehviewer.client.parser.GalleryDetailUrlParser;
|
|
||||||
import com.hippo.ehviewer.client.parser.GalleryPageUrlParser;
|
|
||||||
import com.hippo.ehviewer.ui.scene.BaseScene;
|
|
||||||
import com.hippo.ehviewer.ui.scene.CookieSignInScene;
|
|
||||||
import com.hippo.ehviewer.ui.scene.DownloadsScene;
|
|
||||||
import com.hippo.ehviewer.ui.scene.FavoritesScene;
|
|
||||||
import com.hippo.ehviewer.ui.scene.GalleryCommentsScene;
|
|
||||||
import com.hippo.ehviewer.ui.scene.GalleryDetailScene;
|
|
||||||
import com.hippo.ehviewer.ui.scene.GalleryListScene;
|
|
||||||
import com.hippo.ehviewer.ui.scene.GalleryPreviewsScene;
|
|
||||||
import com.hippo.ehviewer.ui.scene.HistoryScene;
|
|
||||||
import com.hippo.ehviewer.ui.scene.ProgressScene;
|
|
||||||
import com.hippo.ehviewer.ui.scene.SelectSiteScene;
|
|
||||||
import com.hippo.ehviewer.ui.scene.SignInScene;
|
|
||||||
import com.hippo.ehviewer.ui.scene.SolidScene;
|
|
||||||
import com.hippo.ehviewer.ui.scene.WebViewSignInScene;
|
|
||||||
import com.hippo.ehviewer.widget.EhStageLayout;
|
|
||||||
import com.hippo.io.UniFileInputStreamPipe;
|
|
||||||
import com.hippo.scene.Announcer;
|
|
||||||
import com.hippo.scene.SceneFragment;
|
|
||||||
import com.hippo.scene.StageActivity;
|
|
||||||
import com.hippo.unifile.UniFile;
|
|
||||||
import com.hippo.util.BitmapUtils;
|
|
||||||
import com.hippo.util.ClipboardUtilKt;
|
|
||||||
import com.hippo.widget.DrawerView;
|
|
||||||
import com.hippo.yorozuya.IOUtils;
|
|
||||||
import com.hippo.yorozuya.SimpleHandler;
|
|
||||||
import com.hippo.yorozuya.ViewUtils;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public final class MainActivity extends StageActivity
|
|
||||||
implements NavigationView.OnNavigationItemSelectedListener {
|
|
||||||
|
|
||||||
private static final String KEY_NAV_CHECKED_ITEM = "nav_checked_item";
|
|
||||||
|
|
||||||
static {
|
|
||||||
registerLaunchMode(SignInScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TASK);
|
|
||||||
registerLaunchMode(WebViewSignInScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TASK);
|
|
||||||
registerLaunchMode(CookieSignInScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TASK);
|
|
||||||
registerLaunchMode(SelectSiteScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TASK);
|
|
||||||
registerLaunchMode(GalleryListScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TOP);
|
|
||||||
registerLaunchMode(GalleryDetailScene.class, SceneFragment.LAUNCH_MODE_STANDARD);
|
|
||||||
registerLaunchMode(GalleryCommentsScene.class, SceneFragment.LAUNCH_MODE_STANDARD);
|
|
||||||
registerLaunchMode(GalleryPreviewsScene.class, SceneFragment.LAUNCH_MODE_STANDARD);
|
|
||||||
registerLaunchMode(DownloadsScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TASK);
|
|
||||||
registerLaunchMode(FavoritesScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TASK);
|
|
||||||
registerLaunchMode(HistoryScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TOP);
|
|
||||||
registerLaunchMode(ProgressScene.class, SceneFragment.LAUNCH_MODE_STANDARD);
|
|
||||||
}
|
|
||||||
|
|
||||||
ActivityResultLauncher<Intent> settingsLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
|
|
||||||
result -> {
|
|
||||||
if (result.getResultCode() == RESULT_OK) {
|
|
||||||
refreshTopScene();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/*---------------
|
|
||||||
Whole life cycle
|
|
||||||
---------------*/
|
|
||||||
@Nullable
|
|
||||||
private DrawerLayout mDrawerLayout;
|
|
||||||
@Nullable
|
|
||||||
private EhStageLayout mStageLayout;
|
|
||||||
@Nullable
|
|
||||||
private NavigationView mNavView;
|
|
||||||
@Nullable
|
|
||||||
private DrawerView mRightDrawer;
|
|
||||||
private int mNavCheckedItem = 0;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getContainerViewId() {
|
|
||||||
return R.id.fragment_container;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
protected Announcer getLaunchAnnouncer() {
|
|
||||||
if (EhUtils.needSignedIn()) {
|
|
||||||
return new Announcer(SignInScene.class);
|
|
||||||
} else if (Settings.getSelectSite()) {
|
|
||||||
return new Announcer(SelectSiteScene.class);
|
|
||||||
} else {
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putString(GalleryListScene.KEY_ACTION, Settings.getLaunchPageGalleryListSceneAction());
|
|
||||||
return new Announcer(GalleryListScene.class).setArgs(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sometimes scene can't show directly
|
|
||||||
private Announcer processAnnouncer(Announcer announcer) {
|
|
||||||
if (0 == getSceneCount()) {
|
|
||||||
if (EhUtils.needSignedIn()) {
|
|
||||||
Bundle newArgs = new Bundle();
|
|
||||||
newArgs.putString(SignInScene.KEY_TARGET_SCENE, announcer.getClazz().getName());
|
|
||||||
newArgs.putBundle(SignInScene.KEY_TARGET_ARGS, announcer.getArgs());
|
|
||||||
return new Announcer(SignInScene.class).setArgs(newArgs);
|
|
||||||
} else if (Settings.getSelectSite()) {
|
|
||||||
Bundle newArgs = new Bundle();
|
|
||||||
newArgs.putString(SelectSiteScene.KEY_TARGET_SCENE, announcer.getClazz().getName());
|
|
||||||
newArgs.putBundle(SelectSiteScene.KEY_TARGET_ARGS, announcer.getArgs());
|
|
||||||
return new Announcer(SelectSiteScene.class).setArgs(newArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return announcer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private File saveImageToTempFile(UniFile file) {
|
|
||||||
if (null == file) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bitmap bitmap = null;
|
|
||||||
try {
|
|
||||||
bitmap = BitmapUtils.decodeStream(new UniFileInputStreamPipe(file), -1, -1, 500 * 500, false, false, null);
|
|
||||||
} catch (OutOfMemoryError e) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
if (null == bitmap) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
File temp = AppConfig.createTempFile();
|
|
||||||
if (null == temp) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputStream os = null;
|
|
||||||
try {
|
|
||||||
os = new FileOutputStream(temp);
|
|
||||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, os);
|
|
||||||
return temp;
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
} finally {
|
|
||||||
IOUtils.closeQuietly(os);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean handleIntent(Intent intent) {
|
|
||||||
if (intent == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String action = intent.getAction();
|
|
||||||
if (Intent.ACTION_VIEW.equals(action)) {
|
|
||||||
Uri uri = intent.getData();
|
|
||||||
if (uri == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Announcer announcer = EhUrlOpener.parseUrl(uri.toString());
|
|
||||||
if (announcer != null) {
|
|
||||||
startScene(processAnnouncer(announcer));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (Intent.ACTION_SEND.equals(action)) {
|
|
||||||
String type = intent.getType();
|
|
||||||
if ("text/plain".equals(type)) {
|
|
||||||
ListUrlBuilder builder = new ListUrlBuilder();
|
|
||||||
builder.setKeyword(intent.getStringExtra(Intent.EXTRA_TEXT));
|
|
||||||
startScene(processAnnouncer(GalleryListScene.getStartAnnouncer(builder)));
|
|
||||||
return true;
|
|
||||||
} else if (type != null && type.startsWith("image/")) {
|
|
||||||
Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
|
|
||||||
if (null != uri) {
|
|
||||||
UniFile file = UniFile.fromUri(this, uri);
|
|
||||||
File temp = saveImageToTempFile(file);
|
|
||||||
if (null != temp) {
|
|
||||||
ListUrlBuilder builder = new ListUrlBuilder();
|
|
||||||
builder.setMode(ListUrlBuilder.MODE_IMAGE_SEARCH);
|
|
||||||
builder.setImagePath(temp.getPath());
|
|
||||||
builder.setUseSimilarityScan(true);
|
|
||||||
startScene(processAnnouncer(GalleryListScene.getStartAnnouncer(builder)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onUnrecognizedIntent(@Nullable Intent intent) {
|
|
||||||
Class<?> clazz = getTopSceneClass();
|
|
||||||
if (clazz != null && SolidScene.class.isAssignableFrom(clazz)) {
|
|
||||||
// TODO the intent lost
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!handleIntent(intent)) {
|
|
||||||
boolean handleUrl = false;
|
|
||||||
if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) {
|
|
||||||
handleUrl = true;
|
|
||||||
if (intent.getData() != null) {
|
|
||||||
String url = intent.getData().toString();
|
|
||||||
new EditTextDialogBuilder(this, url, "")
|
|
||||||
.setTitle(R.string.error_cannot_parse_the_url)
|
|
||||||
.setPositiveButton(android.R.string.copy, (dialog, which) -> ClipboardUtilKt.addTextToClipboard(this, url, false))
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == getSceneCount()) {
|
|
||||||
if (handleUrl) {
|
|
||||||
finish();
|
|
||||||
} else {
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putString(GalleryListScene.KEY_ACTION, Settings.getLaunchPageGalleryListSceneAction());
|
|
||||||
startScene(processAnnouncer(new Announcer(GalleryListScene.class).setArgs(args)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
protected Announcer onStartSceneFromIntent(@NonNull Class<?> clazz, @Nullable Bundle args) {
|
|
||||||
return processAnnouncer(new Announcer(clazz).setArgs(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate2(@Nullable Bundle savedInstanceState) {
|
|
||||||
setContentView(R.layout.activity_main);
|
|
||||||
|
|
||||||
mStageLayout = (EhStageLayout) ViewUtils.$$(this, R.id.fragment_container);
|
|
||||||
mDrawerLayout = (DrawerLayout) ViewUtils.$$(this, R.id.draw_view);
|
|
||||||
mNavView = (NavigationView) ViewUtils.$$(this, R.id.nav_view);
|
|
||||||
mRightDrawer = (DrawerView) ViewUtils.$$(this, R.id.right_drawer);
|
|
||||||
var callback = new DrawerOnBackPressedCallback(false, mDrawerLayout);
|
|
||||||
mDrawerLayout.addDrawerListener(callback);
|
|
||||||
getOnBackPressedDispatcher().addCallback(callback);
|
|
||||||
|
|
||||||
if (mNavView != null) {
|
|
||||||
mNavView.setNavigationItemSelectedListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
|
||||||
checkDownloadLocation();
|
|
||||||
if (Settings.getMeteredNetworkWarning()) {
|
|
||||||
checkMeteredNetwork();
|
|
||||||
}
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
||||||
if (!Settings.getAppLinkVerifyTip()) {
|
|
||||||
try {
|
|
||||||
checkAppLinkVerify();
|
|
||||||
} catch (PackageManager.NameNotFoundException ignored) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
onRestore(savedInstanceState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.S)
|
|
||||||
private void checkAppLinkVerify() throws PackageManager.NameNotFoundException {
|
|
||||||
DomainVerificationManager manager = getSystemService(DomainVerificationManager.class);
|
|
||||||
DomainVerificationUserState userState = manager.getDomainVerificationUserState(getPackageName());
|
|
||||||
|
|
||||||
if (userState == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean hasUnverified = false;
|
|
||||||
Map<String, Integer> hostToStateMap = userState.getHostToStateMap();
|
|
||||||
for (String key : hostToStateMap.keySet()) {
|
|
||||||
Integer stateValue = hostToStateMap.get(key);
|
|
||||||
if (stateValue == null || stateValue == DomainVerificationUserState.DOMAIN_STATE_VERIFIED || stateValue == DomainVerificationUserState.DOMAIN_STATE_SELECTED) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
hasUnverified = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (hasUnverified) {
|
|
||||||
new BaseDialogBuilder(this)
|
|
||||||
.setTitle(R.string.app_link_not_verified_title)
|
|
||||||
.setMessage(R.string.app_link_not_verified_message)
|
|
||||||
.setPositiveButton(R.string.open_settings, (dialogInterface, i) -> {
|
|
||||||
try {
|
|
||||||
Intent intent = new Intent(android.provider.Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
|
|
||||||
Uri.parse("package:" + getPackageName()));
|
|
||||||
startActivity(intent);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
|
|
||||||
Uri.parse("package:" + getPackageName()));
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
|
||||||
.setNeutralButton(R.string.dont_show_again, (dialogInterface, i) -> Settings.putAppLinkVerifyTip(true))
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkDownloadLocation() {
|
|
||||||
UniFile uniFile = Settings.getDownloadLocation();
|
|
||||||
// null == uniFile for first start
|
|
||||||
if (null == uniFile || uniFile.ensureDir()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
new BaseDialogBuilder(this)
|
|
||||||
.setTitle(R.string.waring)
|
|
||||||
.setMessage(R.string.invalid_download_location)
|
|
||||||
.setPositiveButton(R.string.get_it, null)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkMeteredNetwork() {
|
|
||||||
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
|
||||||
if (cm.isActiveNetworkMetered()) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && mDrawerLayout != null) {
|
|
||||||
Snackbar.make(mDrawerLayout, R.string.metered_network_warning, Snackbar.LENGTH_LONG)
|
|
||||||
.setAction(R.string.settings, v -> {
|
|
||||||
Intent panelIntent = new Intent(android.provider.Settings.Panel.ACTION_INTERNET_CONNECTIVITY);
|
|
||||||
startActivity(panelIntent);
|
|
||||||
})
|
|
||||||
.show();
|
|
||||||
} else {
|
|
||||||
showTip(R.string.metered_network_warning, BaseScene.LENGTH_LONG);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onRestore(Bundle savedInstanceState) {
|
|
||||||
mNavCheckedItem = savedInstanceState.getInt(KEY_NAV_CHECKED_ITEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
|
|
||||||
super.onSaveInstanceState(outState, outPersistentState);
|
|
||||||
outState.putInt(KEY_NAV_CHECKED_ITEM, mNavCheckedItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
|
|
||||||
mDrawerLayout = null;
|
|
||||||
mNavView = null;
|
|
||||||
mRightDrawer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
setNavCheckedItem(mNavCheckedItem);
|
|
||||||
checkClipboardUrl();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onTransactScene() {
|
|
||||||
super.onTransactScene();
|
|
||||||
checkClipboardUrl();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkClipboardUrl() {
|
|
||||||
SimpleHandler.getInstance().postDelayed(() -> {
|
|
||||||
if (!isSolid()) {
|
|
||||||
checkClipboardUrlInternal();
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isSolid() {
|
|
||||||
Class<?> topClass = getTopSceneClass();
|
|
||||||
return topClass == null || SolidScene.class.isAssignableFrom(topClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private Announcer createAnnouncerFromClipboardUrl(String url) {
|
|
||||||
GalleryDetailUrlParser.Result result1 = GalleryDetailUrlParser.parse(url, false);
|
|
||||||
if (result1 != null) {
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GID_TOKEN);
|
|
||||||
args.putLong(GalleryDetailScene.KEY_GID, result1.gid);
|
|
||||||
args.putString(GalleryDetailScene.KEY_TOKEN, result1.token);
|
|
||||||
return new Announcer(GalleryDetailScene.class).setArgs(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
GalleryPageUrlParser.Result result2 = GalleryPageUrlParser.parse(url, false);
|
|
||||||
if (result2 != null) {
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putString(ProgressScene.KEY_ACTION, ProgressScene.ACTION_GALLERY_TOKEN);
|
|
||||||
args.putLong(ProgressScene.KEY_GID, result2.gid);
|
|
||||||
args.putString(ProgressScene.KEY_PTOKEN, result2.pToken);
|
|
||||||
args.putInt(ProgressScene.KEY_PAGE, result2.page);
|
|
||||||
return new Announcer(ProgressScene.class).setArgs(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkClipboardUrlInternal() {
|
|
||||||
String text = ClipboardUtilKt.getUrlFromClipboard(ClipboardUtilKt.getClipboardManager(this), this);
|
|
||||||
int hashCode = text != null ? text.hashCode() : 0;
|
|
||||||
|
|
||||||
if (text != null && hashCode != 0 && Settings.getClipboardTextHashCode() != hashCode) {
|
|
||||||
Announcer announcer = createAnnouncerFromClipboardUrl(text);
|
|
||||||
if (announcer != null && mDrawerLayout != null) {
|
|
||||||
Snackbar snackbar = Snackbar.make(mDrawerLayout, R.string.clipboard_gallery_url_snack_message, Snackbar.LENGTH_SHORT);
|
|
||||||
snackbar.setAction(R.string.clipboard_gallery_url_snack_action, v -> startScene(announcer));
|
|
||||||
snackbar.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Settings.putClipboardTextHashCode(hashCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSceneViewCreated(SceneFragment scene, Bundle savedInstanceState) {
|
|
||||||
super.onSceneViewCreated(scene, savedInstanceState);
|
|
||||||
|
|
||||||
createDrawerView(scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("RtlHardcoded")
|
|
||||||
public void createDrawerView(SceneFragment scene) {
|
|
||||||
if (scene instanceof BaseScene baseScene && mRightDrawer != null && mDrawerLayout != null) {
|
|
||||||
mRightDrawer.removeAllViews();
|
|
||||||
View drawerView = baseScene.createDrawerView(
|
|
||||||
baseScene.getLayoutInflater(), mRightDrawer, null);
|
|
||||||
if (drawerView != null) {
|
|
||||||
mRightDrawer.addView(drawerView);
|
|
||||||
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, GravityCompat.END);
|
|
||||||
} else {
|
|
||||||
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, GravityCompat.END);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSceneViewDestroyed(SceneFragment scene) {
|
|
||||||
super.onSceneViewDestroyed(scene);
|
|
||||||
|
|
||||||
if (scene instanceof BaseScene baseScene) {
|
|
||||||
baseScene.destroyDrawerView();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAboveSnackView(View view) {
|
|
||||||
if (mStageLayout != null) {
|
|
||||||
mStageLayout.addAboveSnackView(view);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeAboveSnackView(View view) {
|
|
||||||
if (mStageLayout != null) {
|
|
||||||
mStageLayout.removeAboveSnackView(view);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDrawerLockMode(int lockMode, int edgeGravity) {
|
|
||||||
if (mDrawerLayout != null) {
|
|
||||||
mDrawerLayout.setDrawerLockMode(lockMode, edgeGravity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getDrawerLockMode(int edgeGravity) {
|
|
||||||
if (mDrawerLayout != null) {
|
|
||||||
return mDrawerLayout.getDrawerLockMode(edgeGravity);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void openDrawer(int drawerGravity) {
|
|
||||||
if (mDrawerLayout != null) {
|
|
||||||
mDrawerLayout.openDrawer(drawerGravity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void closeDrawer(int drawerGravity) {
|
|
||||||
if (mDrawerLayout != null) {
|
|
||||||
mDrawerLayout.closeDrawer(drawerGravity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toggleDrawer(int drawerGravity) {
|
|
||||||
if (mDrawerLayout != null) {
|
|
||||||
if (mDrawerLayout.isDrawerOpen(drawerGravity)) {
|
|
||||||
mDrawerLayout.closeDrawer(drawerGravity);
|
|
||||||
} else {
|
|
||||||
mDrawerLayout.openDrawer(drawerGravity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNavCheckedItem(@IdRes int resId) {
|
|
||||||
mNavCheckedItem = resId;
|
|
||||||
if (mNavView != null) {
|
|
||||||
if (resId == 0) {
|
|
||||||
mNavView.setCheckedItem(R.id.nav_stub);
|
|
||||||
} else {
|
|
||||||
mNavView.setCheckedItem(resId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showTip(@StringRes int id, int length) {
|
|
||||||
showTip(getString(id), length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If activity is running, show snack bar, otherwise show toast
|
|
||||||
*/
|
|
||||||
public void showTip(CharSequence message, int length) {
|
|
||||||
View view = findViewById(R.id.snackbar);
|
|
||||||
if (null != view) {
|
|
||||||
Snackbar.make(view, message,
|
|
||||||
length == BaseScene.LENGTH_LONG ? Snackbar.LENGTH_LONG : Snackbar.LENGTH_SHORT).show();
|
|
||||||
} else {
|
|
||||||
Toast.makeText(this, message,
|
|
||||||
length == BaseScene.LENGTH_LONG ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onNavigationItemSelected(MenuItem item) {
|
|
||||||
// Don't select twice
|
|
||||||
if (item.isChecked()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int id = item.getItemId();
|
|
||||||
|
|
||||||
if (id == R.id.nav_homepage) {
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_HOMEPAGE);
|
|
||||||
startSceneFirstly(new Announcer(GalleryListScene.class)
|
|
||||||
.setArgs(args));
|
|
||||||
} else if (id == R.id.nav_subscription) {
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_SUBSCRIPTION);
|
|
||||||
startSceneFirstly(new Announcer(GalleryListScene.class)
|
|
||||||
.setArgs(args));
|
|
||||||
} else if (id == R.id.nav_whats_hot) {
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_WHATS_HOT);
|
|
||||||
startSceneFirstly(new Announcer(GalleryListScene.class)
|
|
||||||
.setArgs(args));
|
|
||||||
} else if (id == R.id.nav_toplist) {
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_TOP_LIST);
|
|
||||||
startSceneFirstly(new Announcer(GalleryListScene.class)
|
|
||||||
.setArgs(args));
|
|
||||||
} else if (id == R.id.nav_favourite) {
|
|
||||||
startScene(new Announcer(FavoritesScene.class));
|
|
||||||
} else if (id == R.id.nav_history) {
|
|
||||||
startScene(new Announcer(HistoryScene.class));
|
|
||||||
} else if (id == R.id.nav_downloads) {
|
|
||||||
startScene(new Announcer(DownloadsScene.class));
|
|
||||||
} else if (id == R.id.nav_settings) {
|
|
||||||
Intent intent = new Intent(this, SettingsActivity.class);
|
|
||||||
settingsLauncher.launch(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id != R.id.nav_stub && mDrawerLayout != null) {
|
|
||||||
mDrawerLayout.closeDrawers();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DrawerOnBackPressedCallback extends OnBackPressedCallback implements DrawerLayout.DrawerListener {
|
|
||||||
private final DrawerLayout mLayout;
|
|
||||||
|
|
||||||
public DrawerOnBackPressedCallback(boolean enabled, DrawerLayout drawerLayout) {
|
|
||||||
super(enabled);
|
|
||||||
mLayout = drawerLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handleOnBackPressed() {
|
|
||||||
mLayout.closeDrawers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDrawerOpened(@NonNull View drawerView) {
|
|
||||||
setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDrawerClosed(@NonNull View drawerView) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDrawerStateChanged(int newState) {
|
|
||||||
switch (newState) {
|
|
||||||
case DrawerLayout.STATE_DRAGGING, DrawerLayout.STATE_SETTLING -> setEnabled(true);
|
|
||||||
case DrawerLayout.STATE_IDLE -> {
|
|
||||||
if (!mLayout.isDrawerVisible(GravityCompat.START) && !mLayout.isDrawerVisible(GravityCompat.END))
|
|
||||||
setEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,641 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.ui
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.verify.domain.DomainVerificationManager
|
||||||
|
import android.content.pm.verify.domain.DomainVerificationUserState
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.PersistableBundle
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.OnBackPressedCallback
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.annotation.IdRes
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.core.view.GravityCompat
|
||||||
|
import androidx.drawerlayout.widget.DrawerLayout
|
||||||
|
import androidx.drawerlayout.widget.DrawerLayout.DrawerListener
|
||||||
|
import com.google.android.material.navigation.NavigationView
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
import com.hippo.app.BaseDialogBuilder
|
||||||
|
import com.hippo.app.EditTextDialogBuilder
|
||||||
|
import com.hippo.ehviewer.AppConfig
|
||||||
|
import com.hippo.ehviewer.R
|
||||||
|
import com.hippo.ehviewer.Settings
|
||||||
|
import com.hippo.ehviewer.client.EhUrlOpener
|
||||||
|
import com.hippo.ehviewer.client.EhUtils
|
||||||
|
import com.hippo.ehviewer.client.data.ListUrlBuilder
|
||||||
|
import com.hippo.ehviewer.client.parser.GalleryDetailUrlParser
|
||||||
|
import com.hippo.ehviewer.client.parser.GalleryPageUrlParser
|
||||||
|
import com.hippo.ehviewer.ui.scene.BaseScene
|
||||||
|
import com.hippo.ehviewer.ui.scene.CookieSignInScene
|
||||||
|
import com.hippo.ehviewer.ui.scene.DownloadsScene
|
||||||
|
import com.hippo.ehviewer.ui.scene.FavoritesScene
|
||||||
|
import com.hippo.ehviewer.ui.scene.GalleryCommentsScene
|
||||||
|
import com.hippo.ehviewer.ui.scene.GalleryDetailScene
|
||||||
|
import com.hippo.ehviewer.ui.scene.GalleryListScene
|
||||||
|
import com.hippo.ehviewer.ui.scene.GalleryPreviewsScene
|
||||||
|
import com.hippo.ehviewer.ui.scene.HistoryScene
|
||||||
|
import com.hippo.ehviewer.ui.scene.ProgressScene
|
||||||
|
import com.hippo.ehviewer.ui.scene.SelectSiteScene
|
||||||
|
import com.hippo.ehviewer.ui.scene.SignInScene
|
||||||
|
import com.hippo.ehviewer.ui.scene.SolidScene
|
||||||
|
import com.hippo.ehviewer.ui.scene.WebViewSignInScene
|
||||||
|
import com.hippo.ehviewer.widget.EhStageLayout
|
||||||
|
import com.hippo.io.UniFileInputStreamPipe
|
||||||
|
import com.hippo.scene.Announcer
|
||||||
|
import com.hippo.scene.SceneFragment
|
||||||
|
import com.hippo.scene.StageActivity
|
||||||
|
import com.hippo.unifile.UniFile
|
||||||
|
import com.hippo.util.BitmapUtils
|
||||||
|
import com.hippo.util.addTextToClipboard
|
||||||
|
import com.hippo.util.getClipboardManager
|
||||||
|
import com.hippo.util.getUrlFromClipboard
|
||||||
|
import com.hippo.widget.DrawerView
|
||||||
|
import com.hippo.yorozuya.IOUtils
|
||||||
|
import com.hippo.yorozuya.SimpleHandler
|
||||||
|
import com.hippo.yorozuya.ViewUtils
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.OutputStream
|
||||||
|
|
||||||
|
class MainActivity : StageActivity(), NavigationView.OnNavigationItemSelectedListener {
|
||||||
|
private var settingsLauncher =
|
||||||
|
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||||
|
if (it.resultCode == RESULT_OK) refreshTopScene()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------
|
||||||
|
Whole life cycle
|
||||||
|
---------------*/
|
||||||
|
private var mDrawerLayout: DrawerLayout? = null
|
||||||
|
private var mStageLayout: EhStageLayout? = null
|
||||||
|
private var mNavView: NavigationView? = null
|
||||||
|
private var mRightDrawer: DrawerView? = null
|
||||||
|
private var mNavCheckedItem = 0
|
||||||
|
override fun getContainerViewId(): Int {
|
||||||
|
return R.id.fragment_container
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLaunchAnnouncer(): Announcer {
|
||||||
|
return if (EhUtils.needSignedIn()) {
|
||||||
|
Announcer(SignInScene::class.java)
|
||||||
|
} else if (Settings.getSelectSite()) {
|
||||||
|
Announcer(SelectSiteScene::class.java)
|
||||||
|
} else {
|
||||||
|
val args = Bundle()
|
||||||
|
args.putString(
|
||||||
|
GalleryListScene.KEY_ACTION,
|
||||||
|
Settings.getLaunchPageGalleryListSceneAction()
|
||||||
|
)
|
||||||
|
Announcer(GalleryListScene::class.java).setArgs(args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sometimes scene can't show directly
|
||||||
|
private fun processAnnouncer(announcer: Announcer): Announcer {
|
||||||
|
if (0 == sceneCount) {
|
||||||
|
if (EhUtils.needSignedIn()) {
|
||||||
|
val newArgs = Bundle()
|
||||||
|
newArgs.putString(SignInScene.KEY_TARGET_SCENE, announcer.clazz.name)
|
||||||
|
newArgs.putBundle(SignInScene.KEY_TARGET_ARGS, announcer.args)
|
||||||
|
return Announcer(SignInScene::class.java).setArgs(newArgs)
|
||||||
|
} else if (Settings.getSelectSite()) {
|
||||||
|
val newArgs = Bundle()
|
||||||
|
newArgs.putString(SelectSiteScene.KEY_TARGET_SCENE, announcer.clazz.name)
|
||||||
|
newArgs.putBundle(SelectSiteScene.KEY_TARGET_ARGS, announcer.args)
|
||||||
|
return Announcer(SelectSiteScene::class.java).setArgs(newArgs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return announcer
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveImageToTempFile(file: UniFile?): File? {
|
||||||
|
file ?: return null
|
||||||
|
var bitmap: Bitmap? = null
|
||||||
|
try {
|
||||||
|
bitmap = BitmapUtils.decodeStream(
|
||||||
|
UniFileInputStreamPipe(file),
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
500 * 500,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
} catch (e: OutOfMemoryError) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
if (null == bitmap) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val temp = AppConfig.createTempFile() ?: return null
|
||||||
|
var os: OutputStream? = null
|
||||||
|
return try {
|
||||||
|
os = FileOutputStream(temp)
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, os)
|
||||||
|
temp
|
||||||
|
} catch (e: IOException) {
|
||||||
|
null
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(os)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleIntent(intent: Intent?): Boolean {
|
||||||
|
if (intent == null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
val action = intent.action
|
||||||
|
if (Intent.ACTION_VIEW == action) {
|
||||||
|
val uri = intent.data ?: return false
|
||||||
|
val announcer = EhUrlOpener.parseUrl(uri.toString())
|
||||||
|
if (announcer != null) {
|
||||||
|
startScene(processAnnouncer(announcer))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else if (Intent.ACTION_SEND == action) {
|
||||||
|
val type = intent.type
|
||||||
|
if ("text/plain" == type) {
|
||||||
|
val builder = ListUrlBuilder()
|
||||||
|
builder.keyword = intent.getStringExtra(Intent.EXTRA_TEXT)
|
||||||
|
startScene(processAnnouncer(GalleryListScene.getStartAnnouncer(builder)))
|
||||||
|
return true
|
||||||
|
} else if (type != null && type.startsWith("image/")) {
|
||||||
|
val uri = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)
|
||||||
|
if (null != uri) {
|
||||||
|
val file = UniFile.fromUri(this, uri)
|
||||||
|
val temp = saveImageToTempFile(file)
|
||||||
|
if (null != temp) {
|
||||||
|
val builder = ListUrlBuilder()
|
||||||
|
builder.mode = ListUrlBuilder.MODE_IMAGE_SEARCH
|
||||||
|
builder.imagePath = temp.path
|
||||||
|
builder.isUseSimilarityScan = true
|
||||||
|
startScene(processAnnouncer(GalleryListScene.getStartAnnouncer(builder)))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUnrecognizedIntent(intent: Intent?) {
|
||||||
|
val clazz = topSceneClass
|
||||||
|
if (clazz != null && SolidScene::class.java.isAssignableFrom(clazz)) {
|
||||||
|
// TODO the intent lost
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!handleIntent(intent)) {
|
||||||
|
var handleUrl = false
|
||||||
|
if (intent != null && Intent.ACTION_VIEW == intent.action) {
|
||||||
|
handleUrl = true
|
||||||
|
if (intent.data != null) {
|
||||||
|
val url = intent.data.toString()
|
||||||
|
EditTextDialogBuilder(this, url, "")
|
||||||
|
.setTitle(R.string.error_cannot_parse_the_url)
|
||||||
|
.setPositiveButton(android.R.string.copy) { _: DialogInterface?, _: Int ->
|
||||||
|
this.addTextToClipboard(
|
||||||
|
url,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 == sceneCount) {
|
||||||
|
if (handleUrl) {
|
||||||
|
finish()
|
||||||
|
} else {
|
||||||
|
val args = Bundle()
|
||||||
|
args.putString(
|
||||||
|
GalleryListScene.KEY_ACTION,
|
||||||
|
Settings.getLaunchPageGalleryListSceneAction()
|
||||||
|
)
|
||||||
|
startScene(processAnnouncer(Announcer(GalleryListScene::class.java).setArgs(args)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartSceneFromIntent(clazz: Class<*>, args: Bundle?): Announcer {
|
||||||
|
return processAnnouncer(Announcer(clazz).setArgs(args))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate2(savedInstanceState: Bundle?) {
|
||||||
|
setContentView(R.layout.activity_main)
|
||||||
|
mStageLayout = ViewUtils.`$$`(this, R.id.fragment_container) as EhStageLayout
|
||||||
|
mDrawerLayout = ViewUtils.`$$`(this, R.id.draw_view) as DrawerLayout
|
||||||
|
mNavView = ViewUtils.`$$`(this, R.id.nav_view) as NavigationView
|
||||||
|
mRightDrawer = ViewUtils.`$$`(this, R.id.right_drawer) as DrawerView
|
||||||
|
mDrawerLayout?.addDrawerListener(mDrawerOnBackPressedCallback)
|
||||||
|
onBackPressedDispatcher.addCallback(mDrawerOnBackPressedCallback)
|
||||||
|
if (mNavView != null) {
|
||||||
|
mNavView!!.setNavigationItemSelectedListener(this)
|
||||||
|
}
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
checkDownloadLocation()
|
||||||
|
if (Settings.getMeteredNetworkWarning()) {
|
||||||
|
checkMeteredNetwork()
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
|
if (!Settings.getAppLinkVerifyTip()) {
|
||||||
|
try {
|
||||||
|
checkAppLinkVerify()
|
||||||
|
} catch (ignored: PackageManager.NameNotFoundException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
onRestore(savedInstanceState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.S)
|
||||||
|
@Throws(PackageManager.NameNotFoundException::class)
|
||||||
|
private fun checkAppLinkVerify() {
|
||||||
|
val manager = getSystemService(DomainVerificationManager::class.java)
|
||||||
|
val userState = manager.getDomainVerificationUserState(packageName) ?: return
|
||||||
|
var hasUnverified = false
|
||||||
|
val hostToStateMap = userState.hostToStateMap
|
||||||
|
for (key in hostToStateMap.keys) {
|
||||||
|
val stateValue = hostToStateMap[key]
|
||||||
|
if (stateValue == null || stateValue == DomainVerificationUserState.DOMAIN_STATE_VERIFIED || stateValue == DomainVerificationUserState.DOMAIN_STATE_SELECTED) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hasUnverified = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (hasUnverified) {
|
||||||
|
BaseDialogBuilder(this)
|
||||||
|
.setTitle(R.string.app_link_not_verified_title)
|
||||||
|
.setMessage(R.string.app_link_not_verified_message)
|
||||||
|
.setPositiveButton(R.string.open_settings) { _: DialogInterface?, _: Int ->
|
||||||
|
try {
|
||||||
|
val intent = Intent(
|
||||||
|
android.provider.Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
|
||||||
|
Uri.parse("package:$packageName")
|
||||||
|
)
|
||||||
|
startActivity(intent)
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
val intent = Intent(
|
||||||
|
android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
|
||||||
|
Uri.parse("package:$packageName")
|
||||||
|
)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.setNeutralButton(R.string.dont_show_again) { _: DialogInterface?, _: Int ->
|
||||||
|
Settings.putAppLinkVerifyTip(
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkDownloadLocation() {
|
||||||
|
val uniFile = Settings.getDownloadLocation()
|
||||||
|
// null == uniFile for first start
|
||||||
|
if (null == uniFile || uniFile.ensureDir()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
BaseDialogBuilder(this)
|
||||||
|
.setTitle(R.string.waring)
|
||||||
|
.setMessage(R.string.invalid_download_location)
|
||||||
|
.setPositiveButton(R.string.get_it, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkMeteredNetwork() {
|
||||||
|
val cm = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||||
|
if (cm.isActiveNetworkMetered) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && mDrawerLayout != null) {
|
||||||
|
Snackbar.make(
|
||||||
|
mDrawerLayout!!,
|
||||||
|
R.string.metered_network_warning,
|
||||||
|
Snackbar.LENGTH_LONG
|
||||||
|
)
|
||||||
|
.setAction(R.string.settings) {
|
||||||
|
val panelIntent =
|
||||||
|
Intent(android.provider.Settings.Panel.ACTION_INTERNET_CONNECTIVITY)
|
||||||
|
startActivity(panelIntent)
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
} else {
|
||||||
|
showTip(R.string.metered_network_warning, BaseScene.LENGTH_LONG)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onRestore(savedInstanceState: Bundle) {
|
||||||
|
mNavCheckedItem = savedInstanceState.getInt(KEY_NAV_CHECKED_ITEM)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) {
|
||||||
|
super.onSaveInstanceState(outState, outPersistentState)
|
||||||
|
outState.putInt(KEY_NAV_CHECKED_ITEM, mNavCheckedItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
mDrawerLayout = null
|
||||||
|
mNavView = null
|
||||||
|
mRightDrawer = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
setNavCheckedItem(mNavCheckedItem)
|
||||||
|
checkClipboardUrl()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTransactScene() {
|
||||||
|
super.onTransactScene()
|
||||||
|
checkClipboardUrl()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkClipboardUrl() {
|
||||||
|
SimpleHandler.getInstance().postDelayed({
|
||||||
|
if (!isSolid) {
|
||||||
|
checkClipboardUrlInternal()
|
||||||
|
}
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val isSolid: Boolean
|
||||||
|
get() {
|
||||||
|
val topClass = topSceneClass
|
||||||
|
return topClass == null || SolidScene::class.java.isAssignableFrom(topClass)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createAnnouncerFromClipboardUrl(url: String): Announcer? {
|
||||||
|
val result1 = GalleryDetailUrlParser.parse(url, false)
|
||||||
|
if (result1 != null) {
|
||||||
|
val args = Bundle()
|
||||||
|
args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GID_TOKEN)
|
||||||
|
args.putLong(GalleryDetailScene.KEY_GID, result1.gid)
|
||||||
|
args.putString(GalleryDetailScene.KEY_TOKEN, result1.token)
|
||||||
|
return Announcer(GalleryDetailScene::class.java).setArgs(args)
|
||||||
|
}
|
||||||
|
val result2 = GalleryPageUrlParser.parse(url, false)
|
||||||
|
if (result2 != null) {
|
||||||
|
val args = Bundle()
|
||||||
|
args.putString(ProgressScene.KEY_ACTION, ProgressScene.ACTION_GALLERY_TOKEN)
|
||||||
|
args.putLong(ProgressScene.KEY_GID, result2.gid)
|
||||||
|
args.putString(ProgressScene.KEY_PTOKEN, result2.pToken)
|
||||||
|
args.putInt(ProgressScene.KEY_PAGE, result2.page)
|
||||||
|
return Announcer(ProgressScene::class.java).setArgs(args)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkClipboardUrlInternal() {
|
||||||
|
val text = this.getClipboardManager().getUrlFromClipboard(this)
|
||||||
|
val hashCode = text?.hashCode() ?: 0
|
||||||
|
if (text != null && hashCode != 0 && Settings.getClipboardTextHashCode() != hashCode) {
|
||||||
|
val announcer = createAnnouncerFromClipboardUrl(text)
|
||||||
|
if (announcer != null && mDrawerLayout != null) {
|
||||||
|
val snackbar = Snackbar.make(
|
||||||
|
mDrawerLayout!!,
|
||||||
|
R.string.clipboard_gallery_url_snack_message,
|
||||||
|
Snackbar.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
snackbar.setAction(R.string.clipboard_gallery_url_snack_action) {
|
||||||
|
startScene(
|
||||||
|
announcer
|
||||||
|
)
|
||||||
|
}
|
||||||
|
snackbar.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Settings.putClipboardTextHashCode(hashCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSceneViewCreated(scene: SceneFragment, savedInstanceState: Bundle?) {
|
||||||
|
super.onSceneViewCreated(scene, savedInstanceState)
|
||||||
|
createDrawerView(scene)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("RtlHardcoded")
|
||||||
|
fun createDrawerView(scene: SceneFragment?) {
|
||||||
|
if (scene is BaseScene && mRightDrawer != null && mDrawerLayout != null) {
|
||||||
|
mRightDrawer!!.removeAllViews()
|
||||||
|
val drawerView = scene.createDrawerView(
|
||||||
|
scene.layoutInflater, mRightDrawer, null
|
||||||
|
)
|
||||||
|
if (drawerView != null) {
|
||||||
|
mRightDrawer!!.addView(drawerView)
|
||||||
|
mDrawerLayout!!.setDrawerLockMode(
|
||||||
|
DrawerLayout.LOCK_MODE_UNLOCKED,
|
||||||
|
GravityCompat.END
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
mDrawerLayout!!.setDrawerLockMode(
|
||||||
|
DrawerLayout.LOCK_MODE_LOCKED_CLOSED,
|
||||||
|
GravityCompat.END
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSceneViewDestroyed(scene: SceneFragment) {
|
||||||
|
super.onSceneViewDestroyed(scene)
|
||||||
|
if (scene is BaseScene) {
|
||||||
|
scene.destroyDrawerView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addAboveSnackView(view: View?) {
|
||||||
|
mStageLayout?.addAboveSnackView(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeAboveSnackView(view: View?) {
|
||||||
|
mStageLayout?.removeAboveSnackView(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setDrawerLockMode(lockMode: Int, edgeGravity: Int) {
|
||||||
|
mDrawerLayout?.setDrawerLockMode(lockMode, edgeGravity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDrawerLockMode(edgeGravity: Int): Int? {
|
||||||
|
return mDrawerLayout?.getDrawerLockMode(edgeGravity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openDrawer(drawerGravity: Int) {
|
||||||
|
mDrawerLayout?.openDrawer(drawerGravity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun closeDrawer(drawerGravity: Int) {
|
||||||
|
mDrawerLayout?.closeDrawer(drawerGravity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toggleDrawer(drawerGravity: Int) {
|
||||||
|
mDrawerLayout?.run {
|
||||||
|
if (isDrawerOpen(drawerGravity)) {
|
||||||
|
closeDrawer(drawerGravity)
|
||||||
|
} else {
|
||||||
|
openDrawer(drawerGravity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setNavCheckedItem(@IdRes resId: Int) {
|
||||||
|
mNavCheckedItem = resId
|
||||||
|
mNavView?.run {
|
||||||
|
if (resId == 0) {
|
||||||
|
setCheckedItem(R.id.nav_stub)
|
||||||
|
} else {
|
||||||
|
setCheckedItem(resId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showTip(@StringRes id: Int, length: Int) {
|
||||||
|
showTip(getString(id), length)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If activity is running, show snack bar, otherwise show toast
|
||||||
|
*/
|
||||||
|
fun showTip(message: CharSequence, length: Int) {
|
||||||
|
findViewById<View>(R.id.snackbar)?.apply {
|
||||||
|
Snackbar.make(
|
||||||
|
this, message,
|
||||||
|
if (length == BaseScene.LENGTH_LONG) Snackbar.LENGTH_LONG else Snackbar.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
} ?: Toast.makeText(
|
||||||
|
this, message,
|
||||||
|
if (length == BaseScene.LENGTH_LONG) Toast.LENGTH_LONG else Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNavigationItemSelected(item: MenuItem): Boolean {
|
||||||
|
// Don't select twice
|
||||||
|
if (item.isChecked) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
val id = item.itemId
|
||||||
|
when (id) {
|
||||||
|
R.id.nav_homepage -> {
|
||||||
|
val args = Bundle()
|
||||||
|
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_HOMEPAGE)
|
||||||
|
startSceneFirstly(
|
||||||
|
Announcer(GalleryListScene::class.java)
|
||||||
|
.setArgs(args)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_subscription -> {
|
||||||
|
val args = Bundle()
|
||||||
|
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_SUBSCRIPTION)
|
||||||
|
startSceneFirstly(
|
||||||
|
Announcer(GalleryListScene::class.java)
|
||||||
|
.setArgs(args)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_whats_hot -> {
|
||||||
|
val args = Bundle()
|
||||||
|
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_WHATS_HOT)
|
||||||
|
startSceneFirstly(
|
||||||
|
Announcer(GalleryListScene::class.java)
|
||||||
|
.setArgs(args)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_toplist -> {
|
||||||
|
val args = Bundle()
|
||||||
|
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_TOP_LIST)
|
||||||
|
startSceneFirstly(
|
||||||
|
Announcer(GalleryListScene::class.java)
|
||||||
|
.setArgs(args)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_favourite -> {
|
||||||
|
startScene(Announcer(FavoritesScene::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_history -> {
|
||||||
|
startScene(Announcer(HistoryScene::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_downloads -> {
|
||||||
|
startScene(Announcer(DownloadsScene::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_settings -> {
|
||||||
|
val intent = Intent(this, SettingsActivity::class.java)
|
||||||
|
settingsLauncher.launch(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (id != R.id.nav_stub) {
|
||||||
|
mDrawerLayout?.closeDrawers()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mDrawerOnBackPressedCallback =
|
||||||
|
object : OnBackPressedCallback(false), DrawerListener {
|
||||||
|
val slideThreshold = 0.05
|
||||||
|
override fun handleOnBackPressed() {
|
||||||
|
mDrawerLayout?.closeDrawers()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
|
||||||
|
isEnabled = slideOffset > slideThreshold
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDrawerOpened(drawerView: View) {}
|
||||||
|
override fun onDrawerClosed(drawerView: View) {}
|
||||||
|
override fun onDrawerStateChanged(newState: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val KEY_NAV_CHECKED_ITEM = "nav_checked_item"
|
||||||
|
|
||||||
|
init {
|
||||||
|
registerLaunchMode(SignInScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TASK)
|
||||||
|
registerLaunchMode(
|
||||||
|
WebViewSignInScene::class.java,
|
||||||
|
SceneFragment.LAUNCH_MODE_SINGLE_TASK
|
||||||
|
)
|
||||||
|
registerLaunchMode(CookieSignInScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TASK)
|
||||||
|
registerLaunchMode(SelectSiteScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TASK)
|
||||||
|
registerLaunchMode(GalleryListScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TOP)
|
||||||
|
registerLaunchMode(GalleryDetailScene::class.java, SceneFragment.LAUNCH_MODE_STANDARD)
|
||||||
|
registerLaunchMode(GalleryCommentsScene::class.java, SceneFragment.LAUNCH_MODE_STANDARD)
|
||||||
|
registerLaunchMode(GalleryPreviewsScene::class.java, SceneFragment.LAUNCH_MODE_STANDARD)
|
||||||
|
registerLaunchMode(DownloadsScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TASK)
|
||||||
|
registerLaunchMode(FavoritesScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TASK)
|
||||||
|
registerLaunchMode(HistoryScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TOP)
|
||||||
|
registerLaunchMode(ProgressScene::class.java, SceneFragment.LAUNCH_MODE_STANDARD)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,12 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.hippo.ehviewer.ui
|
package com.hippo.ehviewer.ui
|
||||||
|
|
||||||
import android.content.res.Configuration
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.core.view.WindowCompat
|
|
||||||
import androidx.fragment.app.FragmentTransaction
|
import androidx.fragment.app.FragmentTransaction
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
|||||||
@@ -1,388 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Hippo Seven
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.hippo.ehviewer.ui.fragment;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate;
|
|
||||||
import androidx.core.os.LocaleListCompat;
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
|
|
||||||
import com.hippo.app.BaseDialogBuilder;
|
|
||||||
import com.hippo.ehviewer.AppConfig;
|
|
||||||
import com.hippo.ehviewer.BuildConfig;
|
|
||||||
import com.hippo.ehviewer.EhApplication;
|
|
||||||
import com.hippo.ehviewer.EhDB;
|
|
||||||
import com.hippo.ehviewer.GetText;
|
|
||||||
import com.hippo.ehviewer.R;
|
|
||||||
import com.hippo.ehviewer.Settings;
|
|
||||||
import com.hippo.ehviewer.client.EhClient;
|
|
||||||
import com.hippo.ehviewer.client.EhRequest;
|
|
||||||
import com.hippo.ehviewer.client.data.FavListUrlBuilder;
|
|
||||||
import com.hippo.ehviewer.client.parser.FavoritesParser;
|
|
||||||
import com.hippo.ehviewer.ui.scene.BaseScene;
|
|
||||||
import com.hippo.util.ExceptionUtils;
|
|
||||||
import com.hippo.util.IoThreadPoolExecutor;
|
|
||||||
import com.hippo.util.LogCat;
|
|
||||||
import com.hippo.util.ReadableTime;
|
|
||||||
import com.hippo.yorozuya.IOUtils;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipOutputStream;
|
|
||||||
|
|
||||||
public class AdvancedFragment extends BasePreferenceFragment {
|
|
||||||
|
|
||||||
private static final String KEY_DUMP_LOGCAT = "dump_logcat";
|
|
||||||
private static final String KEY_APP_LANGUAGE = "app_language";
|
|
||||||
private static final String KEY_IMPORT_DATA = "import_data";
|
|
||||||
private static final String KEY_EXPORT_DATA = "export_data";
|
|
||||||
private static final String KEY_OPEN_BY_DEFAULT = "open_by_default";
|
|
||||||
private static final String KEY_BACKUP_FAVORITE = "backup_favorite";
|
|
||||||
ActivityResultLauncher<String> exportLauncher = registerForActivityResult(
|
|
||||||
new ActivityResultContracts.CreateDocument("application/vnd.sqlite3"),
|
|
||||||
uri -> {
|
|
||||||
if (uri != null) {
|
|
||||||
try {
|
|
||||||
// grantUriPermission might throw RemoteException on MIUI
|
|
||||||
requireActivity().grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
||||||
} catch (Exception e) {
|
|
||||||
ExceptionUtils.throwIfFatal(e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
AlertDialog alertDialog = new BaseDialogBuilder(requireActivity())
|
|
||||||
.setCancelable(false)
|
|
||||||
.setView(R.layout.preference_dialog_task)
|
|
||||||
.show();
|
|
||||||
IoThreadPoolExecutor.getInstance().execute(() -> {
|
|
||||||
boolean success = EhDB.exportDB(requireActivity(), uri);
|
|
||||||
Activity activity = getActivity();
|
|
||||||
if (activity != null) {
|
|
||||||
activity.runOnUiThread(() -> {
|
|
||||||
if (alertDialog.isShowing()) {
|
|
||||||
alertDialog.dismiss();
|
|
||||||
}
|
|
||||||
showTip(
|
|
||||||
(success)
|
|
||||||
? GetText.getString(R.string.settings_advanced_export_data_to, uri.toString())
|
|
||||||
: GetText.getString(R.string.settings_advanced_export_data_failed),
|
|
||||||
BaseScene.LENGTH_SHORT);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Exception e) {
|
|
||||||
showTip(R.string.settings_advanced_export_data_failed, BaseScene.LENGTH_SHORT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ActivityResultLauncher<String> dumpLogcatLauncher = registerForActivityResult(
|
|
||||||
new ActivityResultContracts.CreateDocument("application/zip"),
|
|
||||||
uri -> {
|
|
||||||
if (uri != null) {
|
|
||||||
try {
|
|
||||||
// grantUriPermission might throw RemoteException on MIUI
|
|
||||||
requireActivity().grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
||||||
} catch (Exception e) {
|
|
||||||
ExceptionUtils.throwIfFatal(e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
File zipFile = new File(AppConfig.getExternalTempDir(), "logs.zip");
|
|
||||||
if (zipFile.exists()) {
|
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
zipFile.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<File> files = new ArrayList<>();
|
|
||||||
files.addAll(Arrays.asList(AppConfig.getExternalParseErrorDir().listFiles()));
|
|
||||||
files.addAll(Arrays.asList(AppConfig.getExternalCrashDir().listFiles()));
|
|
||||||
|
|
||||||
boolean finished = false;
|
|
||||||
|
|
||||||
BufferedInputStream origin = null;
|
|
||||||
ZipOutputStream out = null;
|
|
||||||
try {
|
|
||||||
FileOutputStream dest = new FileOutputStream(zipFile);
|
|
||||||
out = new ZipOutputStream(new BufferedOutputStream(dest));
|
|
||||||
byte[] bytes = new byte[1024 * 64];
|
|
||||||
|
|
||||||
for (File file : files) {
|
|
||||||
if (!file.isFile()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
FileInputStream fi = new FileInputStream(file);
|
|
||||||
origin = new BufferedInputStream(fi, bytes.length);
|
|
||||||
|
|
||||||
ZipEntry entry = new ZipEntry(file.getName());
|
|
||||||
out.putNextEntry(entry);
|
|
||||||
int count;
|
|
||||||
while ((count = origin.read(bytes, 0, bytes.length)) != -1) {
|
|
||||||
out.write(bytes, 0, count);
|
|
||||||
}
|
|
||||||
origin.close();
|
|
||||||
origin = null;
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ZipEntry entry = new ZipEntry("logcat-" + ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".txt");
|
|
||||||
out.putNextEntry(entry);
|
|
||||||
LogCat.save(out);
|
|
||||||
out.closeEntry();
|
|
||||||
out.close();
|
|
||||||
IOUtils.copy(new FileInputStream(zipFile), requireActivity().getContentResolver().openOutputStream(uri));
|
|
||||||
finished = true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if (origin != null) {
|
|
||||||
origin.close();
|
|
||||||
}
|
|
||||||
if (out != null) {
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!finished) {
|
|
||||||
finished = LogCat.save(requireActivity().getContentResolver().openOutputStream(uri));
|
|
||||||
}
|
|
||||||
showTip(
|
|
||||||
finished ? getString(R.string.settings_advanced_dump_logcat_to, uri.toString()) :
|
|
||||||
getString(R.string.settings_advanced_dump_logcat_failed), BaseScene.LENGTH_SHORT);
|
|
||||||
} catch (Exception e) {
|
|
||||||
showTip(getString(R.string.settings_advanced_dump_logcat_failed), BaseScene.LENGTH_SHORT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ActivityResultLauncher<String[]> importDataLauncher = registerForActivityResult(
|
|
||||||
new ActivityResultContracts.OpenDocument(),
|
|
||||||
uri -> {
|
|
||||||
if (uri != null) {
|
|
||||||
try {
|
|
||||||
// grantUriPermission might throw RemoteException on MIUI
|
|
||||||
requireActivity().grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
||||||
} catch (Exception e) {
|
|
||||||
ExceptionUtils.throwIfFatal(e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
AlertDialog alertDialog = new BaseDialogBuilder(requireActivity())
|
|
||||||
.setCancelable(false)
|
|
||||||
.setView(R.layout.preference_dialog_task)
|
|
||||||
.show();
|
|
||||||
IoThreadPoolExecutor.getInstance().execute(() -> {
|
|
||||||
final String error = EhDB.importDB(requireActivity(), uri);
|
|
||||||
Activity activity = getActivity();
|
|
||||||
if (activity != null) {
|
|
||||||
activity.runOnUiThread(() -> {
|
|
||||||
if (alertDialog.isShowing()) {
|
|
||||||
alertDialog.dismiss();
|
|
||||||
}
|
|
||||||
if (null == error) {
|
|
||||||
showTip(getString(R.string.settings_advanced_import_data_successfully), BaseScene.LENGTH_SHORT);
|
|
||||||
} else {
|
|
||||||
showTip(error, BaseScene.LENGTH_SHORT);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
} catch (Exception e) {
|
|
||||||
showTip(e.getLocalizedMessage(), BaseScene.LENGTH_SHORT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
private int favTotal;
|
|
||||||
private int favIndex;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
|
|
||||||
addPreferencesFromResource(R.xml.advanced_settings);
|
|
||||||
|
|
||||||
Preference dumpLogcat = findPreference(KEY_DUMP_LOGCAT);
|
|
||||||
Preference appLanguage = findPreference(KEY_APP_LANGUAGE);
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
|
||||||
appLanguage.setVisible(false);
|
|
||||||
Preference importData = findPreference(KEY_IMPORT_DATA);
|
|
||||||
Preference exportData = findPreference(KEY_EXPORT_DATA);
|
|
||||||
Preference backupFavorite = findPreference(KEY_BACKUP_FAVORITE);
|
|
||||||
Preference openByDefault = findPreference(KEY_OPEN_BY_DEFAULT);
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
|
||||||
openByDefault.setVisible(false);
|
|
||||||
} else {
|
|
||||||
openByDefault.setOnPreferenceClickListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
dumpLogcat.setOnPreferenceClickListener(this);
|
|
||||||
importData.setOnPreferenceClickListener(this);
|
|
||||||
exportData.setOnPreferenceClickListener(this);
|
|
||||||
backupFavorite.setOnPreferenceClickListener(this);
|
|
||||||
|
|
||||||
appLanguage.setOnPreferenceChangeListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
|
||||||
String key = preference.getKey();
|
|
||||||
if (KEY_DUMP_LOGCAT.equals(key)) {
|
|
||||||
try {
|
|
||||||
dumpLogcatLauncher.launch("log-" + ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".zip");
|
|
||||||
} catch (Throwable e) {
|
|
||||||
ExceptionUtils.throwIfFatal(e);
|
|
||||||
showTip(R.string.error_cant_find_activity, BaseScene.LENGTH_SHORT);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else if (KEY_IMPORT_DATA.equals(key)) {
|
|
||||||
try {
|
|
||||||
importDataLauncher.launch(new String[]{"*/*"});
|
|
||||||
} catch (Throwable e) {
|
|
||||||
ExceptionUtils.throwIfFatal(e);
|
|
||||||
showTip(R.string.error_cant_find_activity, BaseScene.LENGTH_SHORT);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else if (KEY_EXPORT_DATA.equals(key)) {
|
|
||||||
try {
|
|
||||||
exportLauncher.launch(ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".db");
|
|
||||||
} catch (Throwable e) {
|
|
||||||
ExceptionUtils.throwIfFatal(e);
|
|
||||||
showTip(R.string.error_cant_find_activity, BaseScene.LENGTH_SHORT);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else if (KEY_BACKUP_FAVORITE.equals(key)) {
|
|
||||||
try {
|
|
||||||
backupFavorite();
|
|
||||||
} catch (Exception e) {
|
|
||||||
ExceptionUtils.throwIfFatal(e);
|
|
||||||
showTip(R.string.settings_advanced_backup_favorite_failed, BaseScene.LENGTH_SHORT);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else if (KEY_OPEN_BY_DEFAULT.equals(key)) {
|
|
||||||
try {
|
|
||||||
@SuppressLint("InlinedApi") Intent intent = new Intent(android.provider.Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
|
|
||||||
Uri.parse("package:" + requireContext().getPackageName()));
|
|
||||||
startActivity(intent);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
|
|
||||||
Uri.parse("package:" + requireContext().getPackageName()));
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void backupFavorite() {
|
|
||||||
EhClient mClient = EhApplication.getEhClient();
|
|
||||||
FavListUrlBuilder favListUrlBuilder = new FavListUrlBuilder();
|
|
||||||
favTotal = 0;
|
|
||||||
favIndex = 1;
|
|
||||||
|
|
||||||
EhRequest request = new EhRequest();
|
|
||||||
request.setMethod(EhClient.METHOD_GET_FAVORITES);
|
|
||||||
request.setCallback(new EhClient.Callback<FavoritesParser.Result>() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(FavoritesParser.Result result) {
|
|
||||||
try {
|
|
||||||
if (result.galleryInfoList.isEmpty()) {
|
|
||||||
showTip(R.string.settings_advanced_backup_favorite_nothing, BaseScene.LENGTH_SHORT);
|
|
||||||
} else {
|
|
||||||
if (favTotal == 0 && result.countArray != null) {
|
|
||||||
int totalFav = 0;
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
totalFav = totalFav + result.countArray[i];
|
|
||||||
}
|
|
||||||
favTotal = (int) Math.ceil((double) totalFav / result.galleryInfoList.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
String status = "(" + favIndex + "/" + favTotal + ")";
|
|
||||||
showTip(GetText.getString(R.string.settings_advanced_backup_favorite_start, status), BaseScene.LENGTH_SHORT);
|
|
||||||
Log.d("LocalFavorites", "now backup page " + status);
|
|
||||||
EhDB.putLocalFavorites(result.galleryInfoList);
|
|
||||||
|
|
||||||
if (result.next != null) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(Settings.getDownloadDelay());
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
favIndex++;
|
|
||||||
favListUrlBuilder.setIndex(result.next, true);
|
|
||||||
request.setArgs(favListUrlBuilder.build());
|
|
||||||
mClient.execute(request);
|
|
||||||
} else {
|
|
||||||
showTip(R.string.settings_advanced_backup_favorite_success, BaseScene.LENGTH_SHORT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
showTip(R.string.settings_advanced_backup_favorite_failed, BaseScene.LENGTH_SHORT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Exception e) {
|
|
||||||
showTip(R.string.settings_advanced_backup_favorite_failed, BaseScene.LENGTH_SHORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCancel() {
|
|
||||||
showTip(R.string.settings_advanced_backup_favorite_failed, BaseScene.LENGTH_SHORT);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
request.setArgs(favListUrlBuilder.build());
|
|
||||||
mClient.execute(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
String key = preference.getKey();
|
|
||||||
if (KEY_APP_LANGUAGE.equals(key) && Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
|
||||||
if ("system".equals(newValue)) {
|
|
||||||
AppCompatDelegate.setApplicationLocales(LocaleListCompat.getEmptyLocaleList());
|
|
||||||
} else {
|
|
||||||
AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags((String) newValue));
|
|
||||||
}
|
|
||||||
requireActivity().recreate();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getFragmentTitle() {
|
|
||||||
return R.string.settings_advanced;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,404 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.hippo.ehviewer.ui.fragment
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
import androidx.core.os.LocaleListCompat
|
||||||
|
import androidx.lifecycle.coroutineScope
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import com.hippo.app.BaseDialogBuilder
|
||||||
|
import com.hippo.ehviewer.AppConfig
|
||||||
|
import com.hippo.ehviewer.BuildConfig
|
||||||
|
import com.hippo.ehviewer.EhDB
|
||||||
|
import com.hippo.ehviewer.GetText
|
||||||
|
import com.hippo.ehviewer.R
|
||||||
|
import com.hippo.ehviewer.client.EhClient
|
||||||
|
import com.hippo.ehviewer.client.EhRequest
|
||||||
|
import com.hippo.ehviewer.client.data.FavListUrlBuilder
|
||||||
|
import com.hippo.ehviewer.client.parser.FavoritesParser
|
||||||
|
import com.hippo.ehviewer.ui.scene.BaseScene
|
||||||
|
import com.hippo.util.ExceptionUtils
|
||||||
|
import com.hippo.util.IoThreadPoolExecutor
|
||||||
|
import com.hippo.util.LogCat
|
||||||
|
import com.hippo.util.ReadableTime
|
||||||
|
import com.hippo.yorozuya.IOUtils
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import java.io.BufferedInputStream
|
||||||
|
import java.io.BufferedOutputStream
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.util.zip.ZipEntry
|
||||||
|
import java.util.zip.ZipOutputStream
|
||||||
|
import kotlin.math.ceil
|
||||||
|
|
||||||
|
class AdvancedFragment : BasePreferenceFragment() {
|
||||||
|
private var exportLauncher = registerForActivityResult<String, Uri>(
|
||||||
|
ActivityResultContracts.CreateDocument("application/vnd.sqlite3")
|
||||||
|
) { uri: Uri? ->
|
||||||
|
if (uri != null) {
|
||||||
|
try {
|
||||||
|
// grantUriPermission might throw RemoteException on MIUI
|
||||||
|
requireActivity().grantUriPermission(
|
||||||
|
BuildConfig.APPLICATION_ID,
|
||||||
|
uri,
|
||||||
|
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ExceptionUtils.throwIfFatal(e)
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
val alertDialog = BaseDialogBuilder(requireActivity())
|
||||||
|
.setCancelable(false)
|
||||||
|
.setView(R.layout.preference_dialog_task)
|
||||||
|
.show()
|
||||||
|
IoThreadPoolExecutor.getInstance().execute {
|
||||||
|
val success = EhDB.exportDB(requireActivity(), uri)
|
||||||
|
val activity: Activity? = activity
|
||||||
|
activity?.runOnUiThread {
|
||||||
|
if (alertDialog.isShowing) {
|
||||||
|
alertDialog.dismiss()
|
||||||
|
}
|
||||||
|
showTip(
|
||||||
|
if (success) GetText.getString(
|
||||||
|
R.string.settings_advanced_export_data_to,
|
||||||
|
uri.toString()
|
||||||
|
) else GetText.getString(R.string.settings_advanced_export_data_failed),
|
||||||
|
BaseScene.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
showTip(R.string.settings_advanced_export_data_failed, BaseScene.LENGTH_SHORT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private var dumpLogcatLauncher = registerForActivityResult<String, Uri>(
|
||||||
|
ActivityResultContracts.CreateDocument("application/zip")
|
||||||
|
) { uri: Uri? ->
|
||||||
|
if (uri != null) {
|
||||||
|
try {
|
||||||
|
// grantUriPermission might throw RemoteException on MIUI
|
||||||
|
requireActivity().grantUriPermission(
|
||||||
|
BuildConfig.APPLICATION_ID,
|
||||||
|
uri,
|
||||||
|
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ExceptionUtils.throwIfFatal(e)
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
val zipFile = File(AppConfig.getExternalTempDir(), "logs.zip")
|
||||||
|
if (zipFile.exists()) {
|
||||||
|
zipFile.delete()
|
||||||
|
}
|
||||||
|
val files = ArrayList<File>()
|
||||||
|
AppConfig.getExternalParseErrorDir()?.listFiles()?.let { files.addAll(it) }
|
||||||
|
AppConfig.getExternalCrashDir()?.listFiles()?.let { files.addAll(it) }
|
||||||
|
var finished = false
|
||||||
|
var origin: BufferedInputStream? = null
|
||||||
|
var out: ZipOutputStream? = null
|
||||||
|
try {
|
||||||
|
val dest = FileOutputStream(zipFile)
|
||||||
|
out = ZipOutputStream(BufferedOutputStream(dest))
|
||||||
|
val bytes = ByteArray(1024 * 64)
|
||||||
|
for (file in files) {
|
||||||
|
if (!file.isFile) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
val fi = FileInputStream(file)
|
||||||
|
origin = BufferedInputStream(fi, bytes.size)
|
||||||
|
val entry = ZipEntry(file.name)
|
||||||
|
out.putNextEntry(entry)
|
||||||
|
var count: Int
|
||||||
|
while (origin.read(bytes, 0, bytes.size).also { count = it } != -1) {
|
||||||
|
out.write(bytes, 0, count)
|
||||||
|
}
|
||||||
|
origin.close()
|
||||||
|
origin = null
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val entry =
|
||||||
|
ZipEntry("logcat-" + ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".txt")
|
||||||
|
out.putNextEntry(entry)
|
||||||
|
LogCat.save(out)
|
||||||
|
out.closeEntry()
|
||||||
|
out.close()
|
||||||
|
IOUtils.copy(
|
||||||
|
FileInputStream(zipFile),
|
||||||
|
requireActivity().contentResolver.openOutputStream(uri)
|
||||||
|
)
|
||||||
|
finished = true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} finally {
|
||||||
|
origin?.close()
|
||||||
|
out?.close()
|
||||||
|
}
|
||||||
|
if (!finished) {
|
||||||
|
finished = LogCat.save(requireActivity().contentResolver.openOutputStream(uri))
|
||||||
|
}
|
||||||
|
showTip(
|
||||||
|
if (finished) getString(
|
||||||
|
R.string.settings_advanced_dump_logcat_to,
|
||||||
|
uri.toString()
|
||||||
|
) else getString(R.string.settings_advanced_dump_logcat_failed),
|
||||||
|
BaseScene.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
showTip(
|
||||||
|
getString(R.string.settings_advanced_dump_logcat_failed),
|
||||||
|
BaseScene.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private var importDataLauncher = registerForActivityResult<Array<String>, Uri>(
|
||||||
|
ActivityResultContracts.OpenDocument()
|
||||||
|
) { uri: Uri? ->
|
||||||
|
if (uri != null) {
|
||||||
|
try {
|
||||||
|
// grantUriPermission might throw RemoteException on MIUI
|
||||||
|
requireActivity().grantUriPermission(
|
||||||
|
BuildConfig.APPLICATION_ID,
|
||||||
|
uri,
|
||||||
|
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ExceptionUtils.throwIfFatal(e)
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
val alertDialog = BaseDialogBuilder(requireActivity())
|
||||||
|
.setCancelable(false)
|
||||||
|
.setView(R.layout.preference_dialog_task)
|
||||||
|
.show()
|
||||||
|
IoThreadPoolExecutor.getInstance().execute {
|
||||||
|
val error = EhDB.importDB(requireActivity(), uri)
|
||||||
|
val activity: Activity? = activity
|
||||||
|
activity?.runOnUiThread {
|
||||||
|
if (alertDialog.isShowing) {
|
||||||
|
alertDialog.dismiss()
|
||||||
|
}
|
||||||
|
if (null == error) {
|
||||||
|
showTip(
|
||||||
|
getString(R.string.settings_advanced_import_data_successfully),
|
||||||
|
BaseScene.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
showTip(error, BaseScene.LENGTH_SHORT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
showTip(e.localizedMessage, BaseScene.LENGTH_SHORT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private var favTotal = 0
|
||||||
|
private var favIndex = 0
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
addPreferencesFromResource(R.xml.advanced_settings)
|
||||||
|
val dumpLogcat = findPreference<Preference>(KEY_DUMP_LOGCAT)
|
||||||
|
val appLanguage = findPreference<Preference>(KEY_APP_LANGUAGE)
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) appLanguage!!.isVisible = false
|
||||||
|
val importData = findPreference<Preference>(KEY_IMPORT_DATA)
|
||||||
|
val exportData = findPreference<Preference>(KEY_EXPORT_DATA)
|
||||||
|
val backupFavorite = findPreference<Preference>(KEY_BACKUP_FAVORITE)
|
||||||
|
val openByDefault = findPreference<Preference>(KEY_OPEN_BY_DEFAULT)
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
||||||
|
openByDefault!!.isVisible = false
|
||||||
|
} else {
|
||||||
|
openByDefault!!.onPreferenceClickListener = this
|
||||||
|
}
|
||||||
|
dumpLogcat!!.onPreferenceClickListener = this
|
||||||
|
importData!!.onPreferenceClickListener = this
|
||||||
|
exportData!!.onPreferenceClickListener = this
|
||||||
|
backupFavorite!!.onPreferenceClickListener = this
|
||||||
|
appLanguage!!.onPreferenceChangeListener = this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPreferenceClick(preference: Preference): Boolean {
|
||||||
|
val key = preference.key
|
||||||
|
if (KEY_DUMP_LOGCAT == key) {
|
||||||
|
try {
|
||||||
|
dumpLogcatLauncher.launch("log-" + ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".zip")
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
ExceptionUtils.throwIfFatal(e)
|
||||||
|
showTip(R.string.error_cant_find_activity, BaseScene.LENGTH_SHORT)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else if (KEY_IMPORT_DATA == key) {
|
||||||
|
try {
|
||||||
|
importDataLauncher.launch(arrayOf("*/*"))
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
ExceptionUtils.throwIfFatal(e)
|
||||||
|
showTip(R.string.error_cant_find_activity, BaseScene.LENGTH_SHORT)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else if (KEY_EXPORT_DATA == key) {
|
||||||
|
try {
|
||||||
|
exportLauncher.launch(ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".db")
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
ExceptionUtils.throwIfFatal(e)
|
||||||
|
showTip(R.string.error_cant_find_activity, BaseScene.LENGTH_SHORT)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else if (KEY_BACKUP_FAVORITE == key) {
|
||||||
|
try {
|
||||||
|
backupFavorite()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ExceptionUtils.throwIfFatal(e)
|
||||||
|
showTip(R.string.settings_advanced_backup_favorite_failed, BaseScene.LENGTH_SHORT)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else if (KEY_OPEN_BY_DEFAULT == key) {
|
||||||
|
try {
|
||||||
|
@SuppressLint("InlinedApi") val intent = Intent(
|
||||||
|
Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
|
||||||
|
Uri.parse("package:" + requireContext().packageName)
|
||||||
|
)
|
||||||
|
startActivity(intent)
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
val intent = Intent(
|
||||||
|
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
|
||||||
|
Uri.parse("package:" + requireContext().packageName)
|
||||||
|
)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun backupFavorite() {
|
||||||
|
val mClient = EhClient
|
||||||
|
val favListUrlBuilder = FavListUrlBuilder()
|
||||||
|
favTotal = 0
|
||||||
|
favIndex = 1
|
||||||
|
val request = EhRequest()
|
||||||
|
request.setMethod(EhClient.METHOD_GET_FAVORITES)
|
||||||
|
request.setCallback(object : EhClient.Callback<FavoritesParser.Result> {
|
||||||
|
override fun onSuccess(result: FavoritesParser.Result) {
|
||||||
|
try {
|
||||||
|
if (result.galleryInfoList.isEmpty()) {
|
||||||
|
showTip(
|
||||||
|
R.string.settings_advanced_backup_favorite_nothing,
|
||||||
|
BaseScene.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
if (favTotal == 0 && result.countArray != null) {
|
||||||
|
var totalFav = 0
|
||||||
|
for (i in 0..9) {
|
||||||
|
totalFav += result.countArray[i]
|
||||||
|
}
|
||||||
|
favTotal =
|
||||||
|
ceil(totalFav.toDouble() / result.galleryInfoList.size).toInt()
|
||||||
|
}
|
||||||
|
val status = "($favIndex/$favTotal)"
|
||||||
|
showTip(
|
||||||
|
GetText.getString(
|
||||||
|
R.string.settings_advanced_backup_favorite_start,
|
||||||
|
status
|
||||||
|
), BaseScene.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
Log.d("LocalFavorites", "now backup page $status")
|
||||||
|
EhDB.putLocalFavorites(result.galleryInfoList)
|
||||||
|
if (result.next != null) {
|
||||||
|
try {
|
||||||
|
runBlocking {
|
||||||
|
delay(com.hippo.ehviewer.Settings.getDownloadDelay().toLong())
|
||||||
|
}
|
||||||
|
} catch (e: InterruptedException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
favIndex++
|
||||||
|
favListUrlBuilder.setIndex(result.next, true)
|
||||||
|
request.setArgs(favListUrlBuilder.build())
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
delay(100)
|
||||||
|
request.enqueue(this@AdvancedFragment)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showTip(
|
||||||
|
R.string.settings_advanced_backup_favorite_success,
|
||||||
|
BaseScene.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
showTip(
|
||||||
|
R.string.settings_advanced_backup_favorite_failed,
|
||||||
|
BaseScene.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(e: Exception) {
|
||||||
|
showTip(R.string.settings_advanced_backup_favorite_failed, BaseScene.LENGTH_SHORT)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCancel() {
|
||||||
|
showTip(R.string.settings_advanced_backup_favorite_failed, BaseScene.LENGTH_SHORT)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
request.setArgs(favListUrlBuilder.build())
|
||||||
|
mClient.enqueue(request, viewLifecycleOwner.lifecycle.coroutineScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
|
||||||
|
val key = preference.key
|
||||||
|
if (KEY_APP_LANGUAGE == key && Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
if ("system" == newValue) {
|
||||||
|
AppCompatDelegate.setApplicationLocales(LocaleListCompat.getEmptyLocaleList())
|
||||||
|
} else {
|
||||||
|
AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(newValue as String))
|
||||||
|
}
|
||||||
|
requireActivity().recreate()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override val fragmentTitle: Int
|
||||||
|
get() = R.string.settings_advanced
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val KEY_DUMP_LOGCAT = "dump_logcat"
|
||||||
|
private const val KEY_APP_LANGUAGE = "app_language"
|
||||||
|
private const val KEY_IMPORT_DATA = "import_data"
|
||||||
|
private const val KEY_EXPORT_DATA = "export_data"
|
||||||
|
private const val KEY_OPEN_BY_DEFAULT = "open_by_default"
|
||||||
|
private const val KEY_BACKUP_FAVORITE = "backup_favorite"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -233,7 +233,7 @@ class FilterFragment : BaseFragment() {
|
|||||||
holder.text?.text = filter.text
|
holder.text?.text = filter.text
|
||||||
} else {
|
} else {
|
||||||
holder.checkbox?.text = filter.text
|
holder.checkbox?.text = filter.text
|
||||||
holder.checkbox?.isChecked = filter.enable
|
holder.checkbox?.isChecked = filter.enable!!
|
||||||
holder.itemView.setOnClickListener {
|
holder.itemView.setOnClickListener {
|
||||||
mFilterList.trigger(filter)
|
mFilterList.trigger(filter)
|
||||||
|
|
||||||
@@ -252,7 +252,7 @@ class FilterFragment : BaseFragment() {
|
|||||||
return run {
|
return run {
|
||||||
val filter = mFilterList[position]
|
val filter = mFilterList[position]
|
||||||
if (filter.id != null) {
|
if (filter.id != null) {
|
||||||
(filter.text.hashCode() shr filter.mode) + filter.id
|
(filter.text.hashCode() shr filter.mode) + filter.id!!
|
||||||
} else (filter.text.hashCode() shr filter.mode).toLong()
|
} else (filter.text.hashCode() shr filter.mode).toLong()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,9 +282,9 @@ class FilterFragment : BaseFragment() {
|
|||||||
count += if (0 == size) 0 else size + 1
|
count += if (0 == size) 0 else size + 1
|
||||||
size = mTagNamespaceFilterList.size
|
size = mTagNamespaceFilterList.size
|
||||||
count += if (0 == size) 0 else size + 1
|
count += if (0 == size) 0 else size + 1
|
||||||
size = mCommenterFilterList.size;
|
size = mCommenterFilterList.size
|
||||||
count += if (0 == size) 0 else size + 1
|
count += if (0 == size) 0 else size + 1
|
||||||
size = mCommentFilterList.size;
|
size = mCommentFilterList.size
|
||||||
count += if (0 == size) 0 else size + 1
|
count += if (0 == size) 0 else size + 1
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,10 @@ package com.hippo.ehviewer.ui.scene;
|
|||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|||||||
+23
-36
@@ -22,41 +22,30 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.view.size
|
import androidx.core.view.size
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
import com.hippo.ehviewer.databinding.SceneToolbarBinding
|
||||||
import com.hippo.ehviewer.R
|
|
||||||
|
|
||||||
abstract class ToolbarScene : BaseScene() {
|
abstract class BaseToolbarScene : BaseScene(), ToolBarScene {
|
||||||
protected var mToolbar: Toolbar? = null
|
private var _binding: SceneToolbarBinding? = null
|
||||||
protected var mAppBarLayout: AppBarLayout? = null
|
private val binding get() = _binding!!
|
||||||
private var mTempTitle: CharSequence? = null
|
|
||||||
|
|
||||||
abstract fun onCreateViewWithToolbar(
|
|
||||||
inflater: LayoutInflater,
|
|
||||||
container: ViewGroup?, savedInstanceState: Bundle?
|
|
||||||
): View
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?, savedInstanceState: Bundle?
|
container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
val view = inflater.inflate(R.layout.scene_toolbar, container, false) as ViewGroup
|
_binding = SceneToolbarBinding.inflate(inflater, container, false)
|
||||||
mToolbar = view.findViewById(R.id.toolbar)
|
val contentView = onCreateViewWithToolbar(inflater, binding.root, savedInstanceState)
|
||||||
mAppBarLayout = view.findViewById(R.id.appbar)
|
return binding.root.apply { addView(contentView, 0) }
|
||||||
val contentView = onCreateViewWithToolbar(inflater, view, savedInstanceState)
|
|
||||||
return view.apply { addView(contentView, 0) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
mToolbar = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
mToolbar?.apply {
|
binding.toolbar.apply {
|
||||||
mTempTitle?.let { title = it }
|
|
||||||
val menuResId = getMenuResId()
|
val menuResId = getMenuResId()
|
||||||
if (menuResId != 0) {
|
if (menuResId != 0) {
|
||||||
inflateMenu(menuResId)
|
inflateMenu(menuResId)
|
||||||
@@ -66,30 +55,28 @@ abstract class ToolbarScene : BaseScene() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideMenu() {
|
|
||||||
mToolbar?.menu?.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun showMenu(menuResId: Int) {
|
fun showMenu(menuResId: Int) {
|
||||||
if (mToolbar?.menu?.size != 0) return
|
if (binding.toolbar.menu?.size != 0) return
|
||||||
mToolbar?.apply {
|
binding.toolbar.apply {
|
||||||
inflateMenu(menuResId)
|
inflateMenu(menuResId)
|
||||||
setOnMenuItemClickListener { item: MenuItem -> onMenuItemClick(item) }
|
setOnMenuItemClickListener { item: MenuItem -> onMenuItemClick(item) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun getMenuResId(): Int {
|
override fun getMenuResId(): Int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun onMenuItemClick(item: MenuItem): Boolean {
|
override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun onNavigationClick() {}
|
override fun onNavigationClick() {
|
||||||
|
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
fun setNavigationIcon(@DrawableRes resId: Int) {
|
fun setNavigationIcon(@DrawableRes resId: Int) {
|
||||||
mToolbar?.setNavigationIcon(resId)
|
binding.toolbar.setNavigationIcon(resId)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setTitle(@StringRes resId: Int) {
|
fun setTitle(@StringRes resId: Int) {
|
||||||
@@ -97,11 +84,11 @@ abstract class ToolbarScene : BaseScene() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setTitle(title: CharSequence?) {
|
fun setTitle(title: CharSequence?) {
|
||||||
mToolbar?.title = title
|
_binding ?: return
|
||||||
mTempTitle = title
|
binding.toolbar.title = title
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setLiftOnScrollTargetView(view: View?) {
|
override fun setLiftOnScrollTargetView(view: View?) {
|
||||||
mAppBarLayout?.setLiftOnScrollTargetView(view)
|
binding.appbar.setLiftOnScrollTargetView(view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,25 +2,55 @@ package com.hippo.ehviewer.ui.scene
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import com.hippo.ehviewer.R
|
import androidx.annotation.DrawableRes
|
||||||
|
import com.hippo.ehviewer.databinding.SceneCollapsingToolbarBinding
|
||||||
|
|
||||||
abstract class CollapsingToolbarScene : ToolbarScene() {
|
abstract class CollapsingToolbarScene : BaseScene(), ToolBarScene {
|
||||||
|
private var _binding: SceneCollapsingToolbarBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?, savedInstanceState: Bundle?
|
container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
val view =
|
_binding = SceneCollapsingToolbarBinding.inflate(inflater, container, false)
|
||||||
inflater.inflate(R.layout.scene_collapsing_toolbar, container, false) as ViewGroup
|
val contentView = onCreateViewWithToolbar(inflater, binding.root, savedInstanceState)
|
||||||
mToolbar = view.findViewById(R.id.toolbar)
|
return binding.root.apply { addView(contentView, 0) }
|
||||||
mAppBarLayout = view.findViewById(R.id.appbar)
|
}
|
||||||
val contentView = onCreateViewWithToolbar(inflater, view, savedInstanceState)
|
|
||||||
return view.apply { addView(contentView, 0) }
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
mAppBarLayout?.setExpanded(false, true)
|
binding.toolbar.apply {
|
||||||
|
val menuResId = getMenuResId()
|
||||||
|
if (menuResId != 0) {
|
||||||
|
inflateMenu(menuResId)
|
||||||
|
setOnMenuItemClickListener { item: MenuItem -> onMenuItemClick(item) }
|
||||||
|
}
|
||||||
|
setNavigationOnClickListener { onNavigationClick() }
|
||||||
|
}
|
||||||
|
binding.appbar.setExpanded(false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNavigationClick() {
|
||||||
|
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setNavigationIcon(@DrawableRes resId: Int) {
|
||||||
|
binding.toolbar.setNavigationIcon(resId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setLiftOnScrollTargetView(view: View?) {
|
||||||
|
binding.appbar.setLiftOnScrollTargetView(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTitle(title: CharSequence?) {
|
||||||
|
binding.toolbar.title = title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,7 +198,7 @@ public class CookieSignInScene extends SolidScene implements EditText.OnEditorAc
|
|||||||
EhRequest request = new EhRequest()
|
EhRequest request = new EhRequest()
|
||||||
.setMethod(EhClient.METHOD_GET_PROFILE)
|
.setMethod(EhClient.METHOD_GET_PROFILE)
|
||||||
.setCallback(new CookieSignInListener());
|
.setCallback(new CookieSignInListener());
|
||||||
EhApplication.getEhClient().execute(request);
|
request.enqueue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeCookie(String id, String hash, String igneous) {
|
private void storeCookie(String id, String hash, String igneous) {
|
||||||
|
|||||||
Loaded 100 of 141 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user