Compare commits
221
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77a8fec790 | ||
|
|
34440edfaa | ||
|
|
3c3d8784ad | ||
|
|
1591abc92c | ||
|
|
0ffa0c34f0 | ||
|
|
c7dc94b61b | ||
|
|
a8b83871a4 | ||
|
|
6f547984ff | ||
|
|
3979c11317 | ||
|
|
2a1ec985f4 | ||
|
|
2a1d49e945 | ||
|
|
7b7e6140d2 | ||
|
|
907cfd9694 | ||
|
|
b51b1d1ec6 | ||
|
|
6a026300e4 | ||
|
|
8511907390 | ||
|
|
05a5be336e | ||
|
|
5434b1ce19 | ||
|
|
c2d4a4367c | ||
|
|
de2f277513 | ||
|
|
283e522037 | ||
|
|
caebe4c23b | ||
|
|
b195277c9a | ||
|
|
6b99cb6253 | ||
|
|
a822bb670a | ||
|
|
af7cc11647 | ||
|
|
0afe331d3d | ||
|
|
7af40f0cd7 | ||
|
|
52dc699ee2 | ||
|
|
ec28e21897 | ||
|
|
3283851dc4 | ||
|
|
ec5e0c7b25 | ||
|
|
13660cb70a | ||
|
|
ce008f5576 | ||
|
|
25f7e8b35c | ||
|
|
109398d955 | ||
|
|
4a8551087b | ||
|
|
34febe3545 | ||
|
|
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 | ||
|
|
aea75d44e3 | ||
|
|
80481f1778 | ||
|
|
3ea7ff8202 | ||
|
|
b5979c0528 | ||
|
|
f0f79a52b8 | ||
|
|
b549acc1de | ||
|
|
2505cc5d00 | ||
|
|
d5af66b3fc | ||
|
|
f680dc7e46 | ||
|
|
ffd8bbb1ce | ||
|
|
216a043094 | ||
|
|
021eb5f828 | ||
|
|
f3bf8849e9 | ||
|
|
128f7100d7 | ||
|
|
2cf53dd00f | ||
|
|
4a674e46e6 | ||
|
|
f6b0134fdb | ||
|
|
675a6b863e | ||
|
|
b570eeef93 | ||
|
|
71a8b4e607 | ||
|
|
89b866b0fc | ||
|
|
bcce20d9ac | ||
|
|
420e760fb3 | ||
|
|
a168c95d79 | ||
|
|
d8ccec45f9 | ||
|
|
1316875602 | ||
|
|
a85387c7c8 | ||
|
|
d357e83d06 | ||
|
|
51546f6fea | ||
|
|
b4aa5ec593 | ||
|
|
909380f592 | ||
|
|
d5f26643bf | ||
|
|
a15dc4afdf | ||
|
|
b317bc334e | ||
|
|
d0a8d08b26 | ||
|
|
f73a922a8e | ||
|
|
c6682ce718 | ||
|
|
764d1137ae | ||
|
|
02fc972a79 | ||
|
|
7fc727cf2e | ||
|
|
d77e1e6820 | ||
|
|
241d9daae9 | ||
|
|
462e0257a9 | ||
|
|
66fbc7e821 | ||
|
|
3c37f22027 | ||
|
|
0d24bc6602 | ||
|
|
5a50df8179 | ||
|
|
f1251fd150 | ||
|
|
16202efc7b | ||
|
|
26c6052286 | ||
|
|
7ce386a7b8 | ||
|
|
e43cd0a039 | ||
|
|
70be405032 | ||
|
|
9f3ad8142a | ||
|
|
51d9ece30c | ||
|
|
d8e79f879f | ||
|
|
76d50b56ee | ||
|
|
c8d1e957a1 | ||
|
|
b287af4824 | ||
|
|
416ef8d6d7 | ||
|
|
7c71abb985 | ||
|
|
900f2462a7 | ||
|
|
dd982c6cb9 | ||
|
|
927a011c9d | ||
|
|
ad0ad47a40 | ||
|
|
71a424c15d | ||
|
|
145b7049a8 | ||
|
|
323d258bc2 | ||
|
|
56ba52d7b9 | ||
|
|
54bd6f6ed8 | ||
|
|
f06167ba4b | ||
|
|
60438ae1ed | ||
|
|
1b87750b87 | ||
|
|
40cdc566c8 | ||
|
|
428ae07e7f | ||
|
|
481ad22b53 | ||
|
|
65f58b93ed | ||
|
|
45411fa14d | ||
|
|
8ba1ba4fb1 | ||
|
|
8427e1b3a5 | ||
|
|
32f0f2a0cf | ||
|
|
8b94997cde | ||
|
|
bd2d54f774 | ||
|
|
34be285510 | ||
|
|
7b906f3c3e | ||
|
|
82ba22cda2 | ||
|
|
b1a9601ae9 | ||
|
|
7c1a297a99 | ||
|
|
a8195c0e7c | ||
|
|
08713e3922 | ||
|
|
0485d52e3e | ||
|
|
8b1723e19b | ||
|
|
9cb683dc55 | ||
|
|
dce1589c19 | ||
|
|
107cf16d36 | ||
|
|
2bab97c829 | ||
|
|
5242d825c2 | ||
|
|
11d3799b03 | ||
|
|
55c7f6b896 | ||
|
|
a09d607177 | ||
|
|
626a101208 | ||
|
|
f4ca3acbf6 | ||
|
|
86835a3bd7 | ||
|
|
0ef46e2e11 | ||
|
|
04878447b7 | ||
|
|
3669d5d90e | ||
|
|
ee5e222a13 | ||
|
|
9ea44ff59a | ||
|
|
0474e2c0f5 | ||
|
|
4a909d4b93 |
No files matched your search
@@ -17,12 +17,14 @@ body:
|
||||
attributes:
|
||||
label: 复现步骤 / Step to reproduce
|
||||
description: |
|
||||
在此处写下复现的方式
|
||||
Describe how to reproduce here
|
||||
请从全新安装应用开始,在此处写下复现的方式。请尽量附带录屏
|
||||
Describe how to reproduce here with fresh installation, with screen recording if possible.
|
||||
placeholder: |
|
||||
0. 重新安装应用 / Fresh install
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
[录屏] / [Screen recording]
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -111,15 +113,6 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: log
|
||||
attributes:
|
||||
label: 应用日志 / App logs
|
||||
description: 您可以通过设置-高级-导出日志来获得日志文件 / You can get logs file in Settings - Advanced - Dump logcat
|
||||
placeholder: 06-15 17:44:53.704 23382 23382 E ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
id: check
|
||||
attributes:
|
||||
|
||||
@@ -56,3 +56,10 @@ jobs:
|
||||
with:
|
||||
name: x86-${{ github.sha }}
|
||||
path: app/build/outputs/apk/release/app-x86-release.apk
|
||||
|
||||
- name: Update mapping
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mapping-${{ github.sha }}
|
||||
path: app/build/outputs/mapping/release/mapping.txt
|
||||
retention-days: 5
|
||||
@@ -49,6 +49,7 @@ jobs:
|
||||
app/build/outputs/apk/release/EhViewer-x86_64.apk
|
||||
app/build/outputs/apk/release/EhViewer-x86.apk
|
||||
app/build/outputs/apk/release/EhViewer-armeabi-v7a.apk
|
||||
app/build/outputs/mapping/release/mapping.txt
|
||||
|
||||
- name: Collect Apks
|
||||
run: |
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</p>
|
||||
|
||||
<h1 align="center">
|
||||
<img src="art/launcher_icon-web.svg" width="200">
|
||||
<img src="https://github.com/Ehviewer-Overhauled/Art/blob/master/launcher_icon-web.svg" width="200">
|
||||
<br>EhViewer<br>
|
||||
</h1>
|
||||
|
||||
@@ -66,12 +66,12 @@ with Material Design 3 and Dynamic Color Support
|
||||
|
||||
# Download
|
||||
|
||||
<a href="https://github.com/Ehviewer-Overhauled/Ehviewer/releases"><img alt="Get it on GitHub" src="art/get-it-on-github.svg" width="200px"/></a> <a href="https://github.com/Ehviewer-Overhauled/fdroid-repo"><img alt="Git it on F-Droid" src="art/get-it-on-fdroid.svg" width="200px"/></a>
|
||||
<a href="https://github.com/Ehviewer-Overhauled/Ehviewer/releases"><img alt="Get it on GitHub" src="https://github.com/Ehviewer-Overhauled/Art/blob/master/get-it-on-github.svg" width="200px"/></a> <a href="https://github.com/Ehviewer-Overhauled/fdroid-repo"><img alt="Git it on F-Droid" src="https://github.com/Ehviewer-Overhauled/Art/blob/master/get-it-on-fdroid.svg" width="200px"/></a>
|
||||
|
||||
# Screenshot
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
# Thanks
|
||||
|
||||
@@ -94,7 +94,7 @@ Here is the libraries
|
||||
|
||||
Copyright 2014-2019 Hippo Seven
|
||||
Copyright 2020-2022 NekoInverter
|
||||
Copyright 2022 Tarsin Norbin
|
||||
Copyright 2022-2023 Tarsin Norbin
|
||||
|
||||
EhViewer is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
|
||||
+14
-19
@@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
id 'kotlin-android'
|
||||
id 'kotlin-parcelize'
|
||||
id 'com.google.devtools.ksp'
|
||||
}
|
||||
|
||||
@@ -31,8 +32,8 @@ android {
|
||||
applicationId "moe.tarsin.ehviewer"
|
||||
minSdkVersion 28
|
||||
targetSdkVersion 33
|
||||
versionCode 180027
|
||||
versionName "1.8.5.0-preview"
|
||||
versionCode 180030
|
||||
versionName "1.8.5.3-alpha03"
|
||||
resConfigs 'zh', 'zh-rCN', 'zh-rHK', 'zh-rTW', 'es', 'ja', 'ko', 'fr', 'de', 'th'
|
||||
}
|
||||
|
||||
@@ -52,10 +53,6 @@ android {
|
||||
freeCompilerArgs += [
|
||||
// https://kotlinlang.org/docs/compiler-reference.html#progressive
|
||||
"-progressive",
|
||||
// Generate smaller bytecode by not generating runtime not-null assertions.
|
||||
"-Xno-call-assertions",
|
||||
"-Xno-param-assertions",
|
||||
"-Xno-receiver-assertions",
|
||||
"-P",
|
||||
"plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=true"
|
||||
]
|
||||
@@ -94,7 +91,6 @@ android {
|
||||
buildFeatures {
|
||||
buildConfig true
|
||||
compose true
|
||||
dataBinding true
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
@@ -107,12 +103,11 @@ android {
|
||||
|
||||
dependencies {
|
||||
def activity_version = "1.6.1"
|
||||
implementation "androidx.activity:activity:$activity_version"
|
||||
implementation "androidx.activity:activity-ktx:$activity_version"
|
||||
|
||||
implementation "androidx.annotation:annotation:1.5.0"
|
||||
implementation "androidx.annotation:annotation-experimental:1.3.0"
|
||||
implementation "androidx.appcompat:appcompat:1.6.0-rc01"
|
||||
implementation "androidx.appcompat:appcompat:1.7.0-alpha01"
|
||||
|
||||
def arch_core_version = "2.1.0"
|
||||
implementation "androidx.arch.core:core-common:$arch_core_version"
|
||||
@@ -138,14 +133,12 @@ dependencies {
|
||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
|
||||
|
||||
def core_version = "1.9.0"
|
||||
implementation "androidx.core:core:$core_version"
|
||||
implementation "androidx.core:core-ktx:$core_version"
|
||||
|
||||
implementation "androidx.customview:customview:1.2.0-alpha02"
|
||||
implementation "androidx.dynamicanimation:dynamicanimation:1.1.0-alpha03"
|
||||
|
||||
def fragment_version = "1.6.0-alpha04"
|
||||
implementation "androidx.fragment:fragment:$fragment_version"
|
||||
implementation "androidx.fragment:fragment-ktx:$fragment_version"
|
||||
|
||||
def lifecycle_version = "2.6.0-alpha03"
|
||||
@@ -159,19 +152,17 @@ dependencies {
|
||||
implementation "androidx.loader:loader:1.1.0"
|
||||
|
||||
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-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'
|
||||
|
||||
def room_version = "2.5.0-rc01"
|
||||
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.startup:startup-runtime:1.2.0-alpha01'
|
||||
@@ -183,10 +174,11 @@ dependencies {
|
||||
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
|
||||
|
||||
implementation 'com.drakeet.drawer:drawer:1.0.3'
|
||||
implementation 'com.google.android.material:material:1.8.0-beta01'
|
||||
implementation 'com.google.android.material:material:1.8.0-rc01'
|
||||
|
||||
implementation 'com.squareup.okhttp3:okhttp-bom:5.0.0-alpha.10'
|
||||
implementation 'com.squareup.okhttp3:okhttp-bom:5.0.0-alpha.11'
|
||||
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.insets:insets:1.3.0'
|
||||
@@ -206,4 +198,7 @@ configurations.all {
|
||||
exclude group: 'dev.rikka.rikkax.appcompat', module: 'appcompat'
|
||||
exclude group: 'dev.rikka.rikkax.material', module: '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'
|
||||
}
|
||||
Vendored
+3
-10
@@ -2,22 +2,15 @@
|
||||
public static final ** CREATOR;
|
||||
}
|
||||
|
||||
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
|
||||
public static void check*(...);
|
||||
public static void throw*(...);
|
||||
}
|
||||
|
||||
-keepclasseswithmembernames,includedescriptorclasses class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-keep,allowoptimization class com.hippo.ehviewer.ui.fragment.* extends com.hippo.ehviewer.ui.fragment.BaseFragment { }
|
||||
-keep,allowoptimization class com.hippo.ehviewer.ui.fragment.* extends com.hippo.ehviewer.ui.fragment.BasePreferenceFragment { }
|
||||
|
||||
-keep class androidx.viewpager.widget.ViewPager$LayoutParams { int position; }
|
||||
|
||||
-renamesourcefileattribute
|
||||
-keepattributes LineNumberTable,SourceFile
|
||||
-renamesourcefileattribute SourceFile
|
||||
|
||||
-repackageclasses
|
||||
-allowaccessmodification
|
||||
-mergeinterfacesaggressively
|
||||
-overloadaggressively
|
||||
@@ -14,7 +14,8 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-feature
|
||||
android:name="android.software.leanback"
|
||||
@@ -32,10 +33,6 @@
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="28" />
|
||||
|
||||
<uses-feature
|
||||
android:glEsVersion="0x00020000"
|
||||
android:required="true" />
|
||||
|
||||
<application
|
||||
android:name="com.hippo.ehviewer.EhApplication"
|
||||
android:allowBackup="true"
|
||||
@@ -45,12 +42,13 @@
|
||||
android:fullBackupContent="@xml/backup_scheme"
|
||||
android:hasFragileUserData="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:supportsRtl="true"
|
||||
android:label="@string/app_name"
|
||||
android:largeHeap="true"
|
||||
android:localeConfig="@xml/locales_config"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:theme="@style/AppTheme">
|
||||
android:theme="@style/AppTheme"
|
||||
tools:targetApi="tiramisu">
|
||||
|
||||
<activity
|
||||
android:name="com.hippo.ehviewer.ui.MainActivity"
|
||||
@@ -105,7 +103,6 @@
|
||||
android:name="eu.kanade.tachiyomi.ui.reader.ReaderActivity"
|
||||
android:configChanges="screenSize"
|
||||
android:exported="true"
|
||||
android:colorMode="wideColorGamut"
|
||||
android:launchMode="singleTask">
|
||||
|
||||
<intent-filter>
|
||||
@@ -161,6 +158,15 @@
|
||||
android:taskAffinity=""
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
||||
|
||||
<service
|
||||
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
|
||||
android:enabled="false"
|
||||
android:exported="false">
|
||||
<meta-data
|
||||
android:name="autoStoreLocales"
|
||||
android:value="true" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="com.hippo.ehviewer.download.DownloadService"
|
||||
android:foregroundServiceType="dataSync"
|
||||
|
||||
@@ -47,4 +47,4 @@ add_subdirectory(libarchive)
|
||||
# Build and link our app's native lib
|
||||
add_library(${PROJECT_NAME} SHARED archive.c fdutils.c)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC libarchive/libarchive)
|
||||
target_link_libraries(${PROJECT_NAME} archive_static log jnigraphics GLESv2 -Wl,--gc-sections)
|
||||
target_link_libraries(${PROJECT_NAME} archive_static log -Wl,--gc-sections)
|
||||
@@ -43,6 +43,11 @@ typedef struct {
|
||||
struct archive_entry *entry;
|
||||
} archive_ctx;
|
||||
|
||||
typedef struct {
|
||||
const char *filename;
|
||||
int index;
|
||||
} entry;
|
||||
|
||||
pthread_mutex_t ctx_lock;
|
||||
static archive_ctx **ctx_pool;
|
||||
#define CTX_POOL_SIZE 20
|
||||
@@ -51,6 +56,8 @@ static bool need_encrypt = false;
|
||||
static char *passwd = NULL;
|
||||
static void *archiveAddr = NULL;
|
||||
static size_t archiveSize = 0;
|
||||
static entry *entries = NULL;
|
||||
static size_t entryCount = 0;
|
||||
|
||||
#define POPULATE_THRESHOLD (512 * 1024 * 1024) // 512 MiB
|
||||
|
||||
@@ -77,6 +84,30 @@ static inline int filename_is_playable_file(const char *name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int compare_entries(const void *a, const void *b) {
|
||||
const char *fa = ((entry *) a)->filename;
|
||||
const char *fb = ((entry *) b)->filename;
|
||||
int a_len = (int) strlen(fa);
|
||||
int b_len = (int) strlen(fb);
|
||||
return a_len == b_len ? strcmp(fa, fb) : a_len - b_len;
|
||||
}
|
||||
|
||||
static long archive_map_entries_index(archive_ctx *ctx) {
|
||||
long count = 0;
|
||||
while (archive_read_next_header(ctx->arc, &ctx->entry) == ARCHIVE_OK) {
|
||||
const char *name = archive_entry_pathname(ctx->entry);
|
||||
if (filename_is_playable_file(name)) {
|
||||
entries[count].filename = strdup(name);
|
||||
entries[count].index = count;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (!count)
|
||||
LOGE("%s", archive_error_string(ctx->arc));
|
||||
qsort(entries, entryCount, sizeof(entry), compare_entries);
|
||||
return count;
|
||||
}
|
||||
|
||||
static long archive_list_all_entries(archive_ctx *ctx) {
|
||||
long count = 0;
|
||||
while (archive_read_next_header(ctx->arc, &ctx->entry) == ARCHIVE_OK)
|
||||
@@ -221,10 +252,9 @@ Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *env, jobject thiz, jint fd
|
||||
if (r) {
|
||||
if (r == -ENOMEM)
|
||||
LOGE("%s", "Mem alloc failed");
|
||||
r = 0;
|
||||
LOGE("%s%s", "Archive open failed:", archive_error_string(ctx->arc));
|
||||
} else {
|
||||
r = archive_list_all_entries(ctx);
|
||||
entryCount = archive_list_all_entries(ctx);
|
||||
LOGI("%s%ld%s", "Found ", r, " image entries in archive");
|
||||
|
||||
// We must read through the file|vm then we can know whether it is encrypted
|
||||
@@ -251,6 +281,19 @@ Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *env, jobject thiz, jint fd
|
||||
}
|
||||
}
|
||||
|
||||
archive_release_ctx(ctx);
|
||||
|
||||
r = archive_alloc_ctx(&ctx);
|
||||
if (r) {
|
||||
if (r == -ENOMEM)
|
||||
LOGE("%s", "Mem alloc failed");
|
||||
r = 0;
|
||||
LOGE("%s%s", "Archive open failed:", archive_error_string(ctx->arc));
|
||||
} else {
|
||||
entries = calloc(entryCount, sizeof(entry));
|
||||
r = archive_map_entries_index(ctx);
|
||||
}
|
||||
|
||||
archive_release_ctx(ctx);
|
||||
return r;
|
||||
}
|
||||
@@ -259,6 +302,7 @@ JNIEXPORT jobject JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_extractToByteBuffer(JNIEnv *env, jobject thiz, jint index) {
|
||||
EH_UNUSED(env);
|
||||
EH_UNUSED(thiz);
|
||||
index = entries[index].index;
|
||||
archive_ctx *ctx = NULL;
|
||||
int ret;
|
||||
ret = archive_get_ctx(&ctx, index);
|
||||
@@ -295,6 +339,10 @@ Java_com_hippo_UriArchiveAccessor_closeArchive(JNIEnv *env, jobject thiz) {
|
||||
passwd = NULL;
|
||||
need_encrypt = false;
|
||||
munmap(archiveAddr, archiveSize);
|
||||
for (int i = 0; i < entryCount; ++i) {
|
||||
free((void *) entries[i].filename);
|
||||
}
|
||||
free(entries);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
@@ -338,6 +386,7 @@ JNIEXPORT jstring JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_getFilename(JNIEnv *env, jobject thiz, jint index) {
|
||||
EH_UNUSED(env);
|
||||
EH_UNUSED(thiz);
|
||||
index = entries[index].index;
|
||||
archive_ctx *ctx = NULL;
|
||||
int ret;
|
||||
ret = archive_get_ctx(&ctx, index);
|
||||
@@ -352,6 +401,7 @@ JNIEXPORT void JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_extractToFd(JNIEnv *env, jobject thiz, jint index, jint fd) {
|
||||
EH_UNUSED(env);
|
||||
EH_UNUSED(thiz);
|
||||
index = entries[index].index;
|
||||
archive_ctx *ctx = NULL;
|
||||
int ret;
|
||||
ret = archive_get_ctx(&ctx, index);
|
||||
@@ -363,6 +413,7 @@ Java_com_hippo_UriArchiveAccessor_extractToFd(JNIEnv *env, jobject thiz, jint in
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_releaseByteBuffer(JNIEnv *env, jobject thiz, jobject buffer) {
|
||||
EH_UNUSED(thiz);
|
||||
void *addr = (*env)->GetDirectBufferAddress(env, buffer);
|
||||
free(addr);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package androidx.swiperefreshlayout.widget
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.ShapeDrawable
|
||||
import android.util.AttributeSet
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import rikka.core.res.resolveColor
|
||||
|
||||
|
||||
@SuppressLint("PrivateResource")
|
||||
class ThemedSwipeRefreshLayout @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null
|
||||
) : SwipeRefreshLayout(context, attrs) {
|
||||
|
||||
init {
|
||||
val surfaceColor =
|
||||
context.theme.resolveColor(com.google.android.material.R.attr.colorSurface)
|
||||
val overlayColor =
|
||||
context.getColor(com.google.android.material.R.color.m3_popupmenu_overlay_color)
|
||||
val backgroundColor = ColorUtils.compositeColors(overlayColor, surfaceColor)
|
||||
(mCircleView.background as ShapeDrawable).paint.color = backgroundColor
|
||||
setColorSchemeColors(context.theme.resolveColor(com.google.android.material.R.attr.colorAccent))
|
||||
}
|
||||
}
|
||||
@@ -476,8 +476,10 @@ open class SubsamplingScaleImageView @JvmOverloads constructor(
|
||||
|
||||
private fun setGestureDetector(context: Context) {
|
||||
detector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
|
||||
@Suppress("SENSELESS_COMPARISON")
|
||||
override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
|
||||
if (panEnabled && isReady && vTranslate != null && (abs(e1.x - e2.x) > 50 || abs(e1.y - e2.y) > 50) && (abs(velocityX) > 500 || abs(velocityY) > 500) && !isZooming) {
|
||||
// The e1 can be null, that's weird and cause crash
|
||||
if (panEnabled && isReady && vTranslate != null && e1 != null && e2 != null && (abs(e1.x - e2.x) > 50 || abs(e1.y - e2.y) > 50) && (abs(velocityX) > 500 || abs(velocityY) > 500) && !isZooming) {
|
||||
val vTranslateEnd = PointF(vTranslate!!.x + velocityX * 0.25F, vTranslate!!.y + velocityY * 0.25F)
|
||||
val sCenterXEnd = (width / 2 - vTranslateEnd.x) / scale
|
||||
val sCenterYEnd = (height / 2 - vTranslateEnd.y) / scale
|
||||
|
||||
@@ -29,8 +29,6 @@ class UriArchiveAccessor(ctx: Context, uri: Uri) {
|
||||
|
||||
private external fun openArchive(fd: Int, size: Long): Int
|
||||
external fun extractToByteBuffer(index: Int): ByteBuffer?
|
||||
|
||||
external fun releaseByteBuffer(buffer: ByteBuffer)
|
||||
external fun extractToFd(index: Int, fd: Int)
|
||||
external fun getFilename(index: Int): String
|
||||
external fun needPassword(): Boolean
|
||||
@@ -40,4 +38,9 @@ class UriArchiveAccessor(ctx: Context, uri: Uri) {
|
||||
closeArchive()
|
||||
pfd.close()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
external fun releaseByteBuffer(buffer: ByteBuffer)
|
||||
}
|
||||
}
|
||||
@@ -329,21 +329,7 @@ public final class DiskLruCache implements Closeable {
|
||||
} else {
|
||||
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
|
||||
@@ -366,7 +352,21 @@ public final class DiskLruCache implements Closeable {
|
||||
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
|
||||
|
||||
@@ -23,6 +23,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.hippo.streampipe.InputStreamPipe;
|
||||
import com.hippo.streampipe.OutputStreamPipe;
|
||||
import com.hippo.util.HashCodeUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -85,32 +86,13 @@ public class SimpleDiskCache {
|
||||
try {
|
||||
final MessageDigest digest = MessageDigest.getInstance("MD5");
|
||||
digest.update(key.getBytes());
|
||||
cacheKey = bytesToHexString(digest.digest());
|
||||
cacheKey = HashCodeUtils.bytesToHexString(digest.digest());
|
||||
} catch (final NoSuchAlgorithmException e) {
|
||||
cacheKey = String.valueOf(key.hashCode());
|
||||
}
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* http://stackoverflow.com/questions/332079
|
||||
*
|
||||
* @param bytes The bytes to convert.
|
||||
* @return A {@link String} converted from the bytes of a hashable key used
|
||||
* to store a filename on the disk, to hex digits.
|
||||
*/
|
||||
private static String bytesToHexString(final byte[] bytes) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (final byte b : bytes) {
|
||||
final String hex = Integer.toHexString(0xFF & b);
|
||||
if (hex.length() == 1) {
|
||||
builder.append('0');
|
||||
}
|
||||
builder.append(hex);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public synchronized boolean isValid() {
|
||||
return mDiskLruCache != null;
|
||||
}
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.drawable;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.hippo.yorozuya.MathUtils;
|
||||
|
||||
public class BatteryDrawable extends Drawable {
|
||||
|
||||
public static final int WARN_LIMIT = 15;
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = BatteryDrawable.class.getSimpleName();
|
||||
private final Paint mPaint;
|
||||
private final Rect mTopRect;
|
||||
private final Rect mBottomRect;
|
||||
private final Rect mRightRect;
|
||||
private final Rect mHeadRect;
|
||||
private final Rect mElectRect;
|
||||
private int mColor = Color.WHITE;
|
||||
private int mWarningColor = Color.RED;
|
||||
private int mElect = -1;
|
||||
private int mStart;
|
||||
private int mStop;
|
||||
|
||||
public BatteryDrawable() {
|
||||
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
|
||||
mTopRect = new Rect();
|
||||
mBottomRect = new Rect();
|
||||
mRightRect = new Rect();
|
||||
mHeadRect = new Rect();
|
||||
mElectRect = new Rect();
|
||||
updatePaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("SuspiciousNameCombination")
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
int width = bounds.width();
|
||||
int height = bounds.height();
|
||||
int strokeWidth = (int) (Math.sqrt(width * width + height * height) * 0.06f);
|
||||
int turn1 = width * 6 / 7;
|
||||
int turn2 = height / 3;
|
||||
int secBottom = height - strokeWidth;
|
||||
mStart = strokeWidth;
|
||||
mStop = turn1 - strokeWidth;
|
||||
|
||||
mTopRect.set(0, 0, turn1, strokeWidth);
|
||||
mBottomRect.set(0, secBottom, turn1, height);
|
||||
mRightRect.set(turn1 - strokeWidth, strokeWidth, turn1, secBottom);
|
||||
mHeadRect.set(turn1, turn2, width, height - turn2);
|
||||
mElectRect.set(0, strokeWidth, mStop, secBottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* How to draw:<br>
|
||||
* |------------------------------|<br>
|
||||
* |\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\|<br>
|
||||
* |------------------------------|---|<br>
|
||||
* |/////////////////| |//|\\\|<br>
|
||||
* |/////////////////| |//|\\\|<br>
|
||||
* |------------------------------|---|<br>
|
||||
* |\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\|<br>
|
||||
* |------------------------------|
|
||||
*/
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
if (mElect == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
mElectRect.right = MathUtils.lerp(mStart, mStop, mElect / 100.0f);
|
||||
|
||||
canvas.drawRect(mTopRect, mPaint);
|
||||
canvas.drawRect(mBottomRect, mPaint);
|
||||
canvas.drawRect(mRightRect, mPaint);
|
||||
canvas.drawRect(mHeadRect, mPaint);
|
||||
canvas.drawRect(mElectRect, mPaint);
|
||||
}
|
||||
|
||||
private boolean isWarn() {
|
||||
return mElect <= WARN_LIMIT;
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
if (mColor == color) {
|
||||
return;
|
||||
}
|
||||
|
||||
mColor = color;
|
||||
if (!isWarn()) {
|
||||
mPaint.setColor(mColor);
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
public void setWarningColor(int color) {
|
||||
if (mWarningColor == color) {
|
||||
return;
|
||||
}
|
||||
|
||||
mWarningColor = color;
|
||||
if (isWarn()) {
|
||||
mPaint.setColor(mWarningColor);
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
public void setElect(int elect) {
|
||||
if (mElect == elect) {
|
||||
return;
|
||||
}
|
||||
|
||||
mElect = elect;
|
||||
updatePaint();
|
||||
}
|
||||
|
||||
public void setElect(int elect, boolean warn) {
|
||||
if (mElect == elect) {
|
||||
return;
|
||||
}
|
||||
|
||||
mElect = elect;
|
||||
updatePaint(warn);
|
||||
}
|
||||
|
||||
private void updatePaint() {
|
||||
updatePaint(isWarn());
|
||||
}
|
||||
|
||||
private void updatePaint(boolean warn) {
|
||||
if (warn) {
|
||||
mPaint.setColor(mWarningColor);
|
||||
} else {
|
||||
mPaint.setColor(mColor);
|
||||
}
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
mPaint.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
mPaint.setColorFilter(cf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.ActivityManager
|
||||
import android.content.ComponentCallbacks2
|
||||
import android.os.Build
|
||||
import android.text.Html
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.view.View
|
||||
@@ -28,25 +27,24 @@ import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.collection.LruCache
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import coil.ImageLoader
|
||||
import coil.ImageLoaderFactory
|
||||
import coil.disk.DiskCache
|
||||
import com.hippo.Native
|
||||
import com.hippo.app.BaseDialogBuilder
|
||||
import com.hippo.beerbelly.SimpleDiskCache
|
||||
import com.hippo.ehviewer.client.EhClient
|
||||
import com.hippo.ehviewer.client.EhCookieStore
|
||||
import com.hippo.ehviewer.client.EhDns
|
||||
import com.hippo.ehviewer.client.EhEngine
|
||||
import com.hippo.ehviewer.client.EhRequestBuilder
|
||||
import com.hippo.ehviewer.client.EhSSLSocketFactory
|
||||
import com.hippo.ehviewer.client.EhTagDatabase
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
import com.hippo.ehviewer.client.EhX509TrustManager
|
||||
import com.hippo.ehviewer.client.data.GalleryDetail
|
||||
import com.hippo.ehviewer.client.parser.EventPaneParser
|
||||
import com.hippo.ehviewer.dao.buildMainDB
|
||||
import com.hippo.ehviewer.download.DownloadManager
|
||||
import com.hippo.ehviewer.spider.SpiderDen
|
||||
import com.hippo.ehviewer.ui.CommonOperations
|
||||
@@ -57,12 +55,12 @@ import com.hippo.util.ExceptionUtils
|
||||
import com.hippo.util.ReadableTime
|
||||
import com.hippo.yorozuya.FileUtils
|
||||
import com.hippo.yorozuya.IntIdGenerator
|
||||
import eu.kanade.tachiyomi.core.preference.AndroidPreferenceStore
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.Cache
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
@@ -77,7 +75,6 @@ class EhApplication : SceneApplication(), DefaultLifecycleObserver, ImageLoaderF
|
||||
private val mIdGenerator = IntIdGenerator()
|
||||
private val mGlobalStuffMap = HashMap<Int, Any>()
|
||||
private val mActivityList = ArrayList<Activity>()
|
||||
private var initialized = false
|
||||
val topActivity: EhActivity?
|
||||
get() = if (mActivityList.isNotEmpty()) {
|
||||
mActivityList[mActivityList.size - 1] as EhActivity
|
||||
@@ -107,50 +104,53 @@ class EhApplication : SceneApplication(), DefaultLifecycleObserver, ImageLoaderF
|
||||
super<SceneApplication>.onCreate()
|
||||
Native.initialize()
|
||||
GetText.initialize(this)
|
||||
Settings.initialize(this)
|
||||
Settings.initialize()
|
||||
ReadableTime.initialize(this)
|
||||
AppConfig.initialize(this)
|
||||
SpiderDen.initialize(this)
|
||||
EhDB.initialize(this)
|
||||
EhEngine.initialize()
|
||||
BitmapUtils.initialize(this)
|
||||
|
||||
// Locales can be managed by system automatically above Snow Cone v2
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU)
|
||||
AppCompatDelegate.setApplicationLocales(LocaleListCompat.create(Settings.getLocale()))
|
||||
EhTagDatabase.update()
|
||||
AppCompatDelegate.setDefaultNightMode(Settings.getTheme())
|
||||
|
||||
GlobalScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
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)
|
||||
}
|
||||
launchIO {
|
||||
launchIO {
|
||||
ehDatabase
|
||||
}
|
||||
launchIO {
|
||||
downloadManager
|
||||
}
|
||||
launchIO {
|
||||
cleanupDownload()
|
||||
}
|
||||
launchIO {
|
||||
theDawnOfNewDay()
|
||||
}
|
||||
}
|
||||
GlobalScope.launch {
|
||||
theDawnOfNewDay()
|
||||
}
|
||||
mIdGenerator.setNextId(Settings.getInt(KEY_GLOBAL_STUFF_NEXT_ID, 0))
|
||||
initialized = true
|
||||
}
|
||||
|
||||
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()) {
|
||||
return
|
||||
}
|
||||
@@ -162,22 +162,20 @@ class EhApplication : SceneApplication(), DefaultLifecycleObserver, ImageLoaderF
|
||||
EhCookieStore.KEY_IPD_PASS_HASH
|
||||
)
|
||||
) {
|
||||
withContext(Dispatchers.IO) {
|
||||
val referer = EhUrl.REFERER_E
|
||||
val request = EhRequestBuilder(EhUrl.HOST_E + "news.php", referer).build()
|
||||
val call = okHttpClient.newCall(request)
|
||||
try {
|
||||
call.execute().use { response ->
|
||||
val responseBody = response.body
|
||||
val body = responseBody.string()
|
||||
val html = EventPaneParser.parse(body)
|
||||
if (html != null) {
|
||||
showEventPane(html)
|
||||
}
|
||||
val referer = EhUrl.REFERER_E
|
||||
val request = EhRequestBuilder(EhUrl.HOST_E + "news.php", referer).build()
|
||||
val call = okHttpClient.newCall(request)
|
||||
try {
|
||||
call.execute().use { response ->
|
||||
val responseBody = response.body
|
||||
val body = responseBody.string()
|
||||
val html = EventPaneParser.parse(body)
|
||||
if (html != null) {
|
||||
showEventPane(html)
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -285,9 +283,6 @@ class EhApplication : SceneApplication(), DefaultLifecycleObserver, ImageLoaderF
|
||||
@JvmStatic
|
||||
val ehCookieStore by lazy { EhCookieStore(application) }
|
||||
|
||||
@JvmStatic
|
||||
val ehClient by lazy { EhClient() }
|
||||
|
||||
@JvmStatic
|
||||
val ehProxySelector by lazy { EhProxySelector() }
|
||||
|
||||
@@ -296,7 +291,7 @@ class EhApplication : SceneApplication(), DefaultLifecycleObserver, ImageLoaderF
|
||||
val builder = OkHttpClient.Builder()
|
||||
.cookieJar(ehCookieStore)
|
||||
.cache(Cache(File(application.cacheDir, "http_cache"), 50L * 1024L * 1024L))
|
||||
.dns(EhDns())
|
||||
.dns(EhDns)
|
||||
.proxySelector(ehProxySelector)
|
||||
|
||||
if (Settings.getDF()) {
|
||||
@@ -315,10 +310,10 @@ class EhApplication : SceneApplication(), DefaultLifecycleObserver, ImageLoaderF
|
||||
trustManager = trustManagers[0] as X509TrustManager
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
trustManager = EhX509TrustManager()
|
||||
trustManager = EhX509TrustManager
|
||||
}
|
||||
|
||||
builder.sslSocketFactory(EhSSLSocketFactory(), trustManager)
|
||||
builder.sslSocketFactory(EhSSLSocketFactory, trustManager)
|
||||
builder.proxy(Proxy.NO_PROXY)
|
||||
}
|
||||
builder.build()
|
||||
@@ -335,19 +330,23 @@ class EhApplication : SceneApplication(), DefaultLifecycleObserver, ImageLoaderF
|
||||
|
||||
@JvmStatic
|
||||
val spiderInfoCache by lazy {
|
||||
SimpleDiskCache(
|
||||
File(application.cacheDir, "spider_info"),
|
||||
20 * 1024 * 1024
|
||||
)
|
||||
DiskCache.Builder().directory(File(application.cacheDir, "spider_info"))
|
||||
.maxSizeBytes(20 * 1024 * 1024).build()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val downloadManager by lazy { DownloadManager(application) }
|
||||
val downloadManager by lazy { DownloadManager() }
|
||||
|
||||
@JvmStatic
|
||||
val hosts by lazy { Hosts(application, "hosts.db") }
|
||||
|
||||
@JvmStatic
|
||||
val favouriteStatusRouter by lazy { FavouriteStatusRouter() }
|
||||
|
||||
@JvmStatic
|
||||
val readerPreferences by lazy { ReaderPreferences(AndroidPreferenceStore(application)) }
|
||||
|
||||
@JvmStatic
|
||||
val ehDatabase by lazy { buildMainDB(application) }
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ import java.util.List;
|
||||
public class EhDB {
|
||||
private static final int CUR_DB_VER = 4;
|
||||
|
||||
private static EhDatabase db;
|
||||
private static final EhDatabase db = EhApplication.getEhDatabase();
|
||||
|
||||
private static void upgradeDB(SQLiteDatabase db, int oldVersion) {
|
||||
switch (oldVersion) {
|
||||
@@ -99,10 +99,6 @@ public class EhDB {
|
||||
}
|
||||
}
|
||||
|
||||
public static void initialize(Context context) {
|
||||
db = Room.databaseBuilder(context, EhDatabase.class, "eh.db").allowMainThreadQueries().build();
|
||||
}
|
||||
|
||||
public static synchronized List<DownloadInfo> getAllDownloadInfo() {
|
||||
DownloadsDao dao = db.downloadsDao();
|
||||
List<DownloadInfo> list = dao.list();
|
||||
@@ -118,7 +114,7 @@ public class EhDB {
|
||||
// Insert or update
|
||||
public static synchronized void putDownloadInfo(DownloadInfo downloadInfo) {
|
||||
DownloadsDao dao = db.downloadsDao();
|
||||
if (null != dao.load(downloadInfo.gid)) {
|
||||
if (null != dao.load(downloadInfo.getGid())) {
|
||||
// Update
|
||||
dao.update(downloadInfo);
|
||||
} else {
|
||||
@@ -256,7 +252,7 @@ public class EhDB {
|
||||
|
||||
public static synchronized void putLocalFavorites(GalleryInfo galleryInfo) {
|
||||
LocalFavoritesDao dao = db.localFavoritesDao();
|
||||
if (null == dao.load(galleryInfo.gid)) {
|
||||
if (null == dao.load(galleryInfo.getGid())) {
|
||||
LocalFavoriteInfo info;
|
||||
if (galleryInfo instanceof LocalFavoriteInfo) {
|
||||
info = (LocalFavoriteInfo) galleryInfo;
|
||||
@@ -281,9 +277,9 @@ public class EhDB {
|
||||
|
||||
public static synchronized void insertQuickSearch(QuickSearch quickSearch) {
|
||||
QuickSearchDao dao = db.quickSearchDao();
|
||||
quickSearch.id = null;
|
||||
quickSearch.time = System.currentTimeMillis();
|
||||
quickSearch.id = dao.insert(quickSearch);
|
||||
quickSearch.setId(null);
|
||||
quickSearch.setTime(System.currentTimeMillis());
|
||||
quickSearch.setId(dao.insert(quickSearch));
|
||||
}
|
||||
|
||||
public static synchronized void importQuickSearch(List<QuickSearch> quickSearchList) {
|
||||
@@ -335,7 +331,7 @@ public class EhDB {
|
||||
info = new HistoryInfo(galleryInfo);
|
||||
}
|
||||
info.time = System.currentTimeMillis();
|
||||
if (null != dao.load(info.gid)) {
|
||||
if (null != dao.load(info.getGid())) {
|
||||
dao.update(info);
|
||||
} else {
|
||||
dao.insert(info);
|
||||
@@ -345,7 +341,7 @@ public class EhDB {
|
||||
public static synchronized void putHistoryInfo(List<HistoryInfo> historyInfoList) {
|
||||
HistoryDao dao = db.historyDao();
|
||||
for (HistoryInfo info : historyInfoList) {
|
||||
if (null == dao.load(info.gid)) {
|
||||
if (null == dao.load(info.getGid())) {
|
||||
dao.insert(info);
|
||||
}
|
||||
}
|
||||
@@ -386,7 +382,7 @@ public class EhDB {
|
||||
}
|
||||
|
||||
public static synchronized void triggerFilter(Filter filter) {
|
||||
filter.setEnable(!filter.enable);
|
||||
filter.enable = !filter.enable;
|
||||
db.filterDao().update(filter);
|
||||
}
|
||||
|
||||
@@ -521,9 +517,9 @@ public class EhDB {
|
||||
List<QuickSearch> currentQuickSearchList = db.quickSearchDao().list();
|
||||
List<QuickSearch> importList = new ArrayList<>();
|
||||
for (QuickSearch quickSearch : quickSearchList) {
|
||||
String name = quickSearch.name;
|
||||
String name = quickSearch.getName();
|
||||
for (QuickSearch q : currentQuickSearchList) {
|
||||
if (ObjectUtils.equal(q.name, name)) {
|
||||
if (ObjectUtils.equal(q.getName(), name)) {
|
||||
// The same name
|
||||
name = null;
|
||||
break;
|
||||
|
||||
@@ -51,7 +51,7 @@ public class FavouriteStatusRouter {
|
||||
for (Map<Long, GalleryInfo> map : maps.values()) {
|
||||
GalleryInfo info = map.get(gid);
|
||||
if (info != null) {
|
||||
info.favoriteSlot = slot;
|
||||
info.setFavoriteSlot(slot);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.hippo.ehviewer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
@@ -86,7 +85,6 @@ public class Settings {
|
||||
public static final int DEFAULT_READ_CACHE_SIZE = 320;
|
||||
public static final String KEY_BUILT_IN_HOSTS = "built_in_hosts_2";
|
||||
public static final String KEY_DOMAIN_FRONTING = "domain_fronting";
|
||||
public static final String KEY_APP_LANGUAGE = "app_language";
|
||||
public static final String KEY_LIST_THUMB_SIZE = "list_tile_size";
|
||||
private static final String KEY_HIDE_HV_EVENTS = "hide_hv_events";
|
||||
private static final boolean DEFAULT_HIDE_HV_EVENTS = true;
|
||||
@@ -124,34 +122,6 @@ public class Settings {
|
||||
private static final boolean DEFAULT_METERED_NETWORK_WARNING = false;
|
||||
private static final String KEY_APP_LINK_VERIFY_TIP = "app_link_verify_tip";
|
||||
private static final boolean DEFAULT_APP_LINK_VERIFY_TIP = false;
|
||||
/********************
|
||||
****** Read
|
||||
********************/
|
||||
private static final String KEY_SCREEN_ROTATION = "screen_rotation";
|
||||
private static final int DEFAULT_SCREEN_ROTATION = 0;
|
||||
private static final String KEY_READING_DIRECTION = "reading_direction";
|
||||
private static final String KEY_PAGE_SCALING = "page_scaling";
|
||||
private static final String KEY_START_POSITION = "start_position";
|
||||
private static final String KEY_KEEP_SCREEN_ON = "keep_screen_on";
|
||||
private static final boolean DEFAULT_KEEP_SCREEN_ON = false;
|
||||
private static final String KEY_SHOW_CLOCK = "gallery_show_clock";
|
||||
private static final boolean DEFAULT_SHOW_CLOCK = true;
|
||||
private static final String KEY_SHOW_PROGRESS = "gallery_show_progress";
|
||||
private static final boolean DEFAULT_SHOW_PROGRESS = true;
|
||||
private static final String KEY_SHOW_BATTERY = "gallery_show_battery";
|
||||
private static final boolean DEFAULT_SHOW_BATTERY = true;
|
||||
private static final String KEY_SHOW_PAGE_INTERVAL = "gallery_show_page_interval";
|
||||
private static final boolean DEFAULT_SHOW_PAGE_INTERVAL = true;
|
||||
private static final String KEY_VOLUME_PAGE = "volume_page";
|
||||
private static final boolean DEFAULT_VOLUME_PAGE = false;
|
||||
private static final String KEY_REVERSE_VOLUME_PAGE = "reserve_volume_page";
|
||||
private static final boolean DEFAULT_REVERSE_VOLUME_PAGE = false;
|
||||
private static final String KEY_READING_FULLSCREEN = "reading_fullscreen";
|
||||
private static final boolean VALUE_READING_FULLSCREEN = true;
|
||||
private static final String KEY_CUSTOM_SCREEN_LIGHTNESS = "custom_screen_lightness";
|
||||
private static final boolean DEFAULT_CUSTOM_SCREEN_LIGHTNESS = false;
|
||||
private static final String KEY_SCREEN_LIGHTNESS = "screen_lightness";
|
||||
private static final int DEFAULT_SCREEN_LIGHTNESS = 50;
|
||||
private static final boolean DEFAULT_MEDIA_SCAN = false;
|
||||
private static final String KEY_RECENT_DOWNLOAD_LABEL = "recent_download_label";
|
||||
private static final String DEFAULT_RECENT_DOWNLOAD_LABEL = null;
|
||||
@@ -165,8 +135,6 @@ public class Settings {
|
||||
private static final int DEFAULT_PRELOAD_IMAGE = 5;
|
||||
private static final String KEY_DOWNLOAD_ORIGIN_IMAGE = "download_origin_image";
|
||||
private static final boolean DEFAULT_DOWNLOAD_ORIGIN_IMAGE = false;
|
||||
private static final String KEY_READ_THEME = "read_theme";
|
||||
private static final int DEFAULT_READ_THEME = 1;
|
||||
/********************
|
||||
****** Favorites
|
||||
********************/
|
||||
@@ -213,15 +181,12 @@ public class Settings {
|
||||
private static final boolean DEFAULT_SAVE_CRASH_LOG = true;
|
||||
private static final boolean DEFAULT_BUILT_IN_HOSTS = false;
|
||||
private static final boolean DEFAULT_FRONTING = false;
|
||||
private static final String DEFAULT_APP_LANGUAGE = "system";
|
||||
private static final String KEY_PROXY_TYPE = "proxy_type";
|
||||
private static final int DEFAULT_PROXY_TYPE = EhProxySelector.TYPE_SYSTEM;
|
||||
private static final String KEY_PROXY_IP = "proxy_ip";
|
||||
private static final String DEFAULT_PROXY_IP = null;
|
||||
private static final String KEY_PROXY_PORT = "proxy_port";
|
||||
private static final int DEFAULT_PROXY_PORT = -1;
|
||||
private static final String KEY_GUIDE_GALLERY = "guide_gallery";
|
||||
private static final boolean DEFAULT_GUIDE_GALLERY = true;
|
||||
private static final String KEY_CLIPBOARD_TEXT_HASH_CODE = "clipboard_text_hash_code";
|
||||
private static final int DEFAULT_CLIPBOARD_TEXT_HASH_CODE = 0;
|
||||
private static final String KEY_DOWNLOAD_DELAY = "download_delay";
|
||||
@@ -229,15 +194,15 @@ public class Settings {
|
||||
private static final String KEY_REQUEST_NEWS = "request_news";
|
||||
private static final boolean DEFAULT_REQUEST_NEWS = true;
|
||||
private static final String KEY_ARCHIVE_PASSWDS = "archive_passwds";
|
||||
private static final String KEY_QS_SAVE_PROGRESS = "qs_save_progress";
|
||||
private static final boolean DEFAULT_QS_SAVE_PROGRESS = true;
|
||||
public static boolean LIST_THUMB_SIZE_INITED = false;
|
||||
public static SharedPreferences sSettingsPre;
|
||||
private static int LIST_THUMB_SIZE = 40;
|
||||
private static Context sContext;
|
||||
private static EhConfig sEhConfig;
|
||||
|
||||
public static void initialize(Context context) {
|
||||
sContext = context.getApplicationContext();
|
||||
sSettingsPre = PreferenceManager.getDefaultSharedPreferences(sContext);
|
||||
public static void initialize() {
|
||||
sSettingsPre = PreferenceManager.getDefaultSharedPreferences(EhApplication.getApplication());
|
||||
sEhConfig = loadEhConfig();
|
||||
fixDefaultValue();
|
||||
}
|
||||
@@ -259,15 +224,6 @@ public class Settings {
|
||||
}
|
||||
}
|
||||
|
||||
public static Locale getLocale() {
|
||||
String language = Settings.getAppLanguage();
|
||||
if (language != null && !language.equals("system")) {
|
||||
return Locale.forLanguageTag(language);
|
||||
} else {
|
||||
return Locale.getDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private static EhConfig loadEhConfig() {
|
||||
EhConfig ehConfig = new EhConfig();
|
||||
ehConfig.imageSize = getImageResolution();
|
||||
@@ -431,7 +387,7 @@ public class Settings {
|
||||
}
|
||||
|
||||
public static int dip2px(int dpValue) {
|
||||
final float scale = sContext.getResources().getDisplayMetrics().density;
|
||||
final float scale = EhApplication.getApplication().getResources().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
@@ -495,114 +451,6 @@ public class Settings {
|
||||
putBoolean(KEY_APP_LINK_VERIFY_TIP, value);
|
||||
}
|
||||
|
||||
public static int getScreenRotation() {
|
||||
return getIntFromStr(KEY_SCREEN_ROTATION, DEFAULT_SCREEN_ROTATION);
|
||||
}
|
||||
|
||||
public static void putScreenRotation(int value) {
|
||||
putIntToStr(KEY_SCREEN_ROTATION, value);
|
||||
}
|
||||
|
||||
public static void putReadingDirection(int value) {
|
||||
putIntToStr(KEY_READING_DIRECTION, value);
|
||||
}
|
||||
|
||||
public static void putPageScaling(int value) {
|
||||
putIntToStr(KEY_PAGE_SCALING, value);
|
||||
}
|
||||
|
||||
public static void putStartPosition(int value) {
|
||||
putIntToStr(KEY_START_POSITION, value);
|
||||
}
|
||||
|
||||
public static boolean getKeepScreenOn() {
|
||||
return getBoolean(KEY_KEEP_SCREEN_ON, DEFAULT_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
public static void putKeepScreenOn(boolean value) {
|
||||
putBoolean(KEY_KEEP_SCREEN_ON, value);
|
||||
}
|
||||
|
||||
public static boolean getShowClock() {
|
||||
return getBoolean(KEY_SHOW_CLOCK, DEFAULT_SHOW_CLOCK);
|
||||
}
|
||||
|
||||
public static void putShowClock(boolean value) {
|
||||
putBoolean(KEY_SHOW_CLOCK, value);
|
||||
}
|
||||
|
||||
public static boolean getShowProgress() {
|
||||
return getBoolean(KEY_SHOW_PROGRESS, DEFAULT_SHOW_PROGRESS);
|
||||
}
|
||||
|
||||
public static void putShowProgress(boolean value) {
|
||||
putBoolean(KEY_SHOW_PROGRESS, value);
|
||||
}
|
||||
|
||||
public static boolean getShowBattery() {
|
||||
return getBoolean(KEY_SHOW_BATTERY, DEFAULT_SHOW_BATTERY);
|
||||
}
|
||||
|
||||
public static void putShowBattery(boolean value) {
|
||||
putBoolean(KEY_SHOW_BATTERY, value);
|
||||
}
|
||||
|
||||
public static boolean getShowPageInterval() {
|
||||
return getBoolean(KEY_SHOW_PAGE_INTERVAL, DEFAULT_SHOW_PAGE_INTERVAL);
|
||||
}
|
||||
|
||||
public static void putShowPageInterval(boolean value) {
|
||||
putBoolean(KEY_SHOW_PAGE_INTERVAL, value);
|
||||
}
|
||||
|
||||
public static boolean getVolumePage() {
|
||||
return getBoolean(KEY_VOLUME_PAGE, DEFAULT_VOLUME_PAGE);
|
||||
}
|
||||
|
||||
public static void putVolumePage(boolean value) {
|
||||
putBoolean(KEY_VOLUME_PAGE, value);
|
||||
}
|
||||
|
||||
public static boolean getReverseVolumePage() {
|
||||
return getBoolean(KEY_REVERSE_VOLUME_PAGE, DEFAULT_REVERSE_VOLUME_PAGE);
|
||||
}
|
||||
|
||||
public static void putReverseVolumePage(boolean value) {
|
||||
putBoolean(KEY_REVERSE_VOLUME_PAGE, value);
|
||||
}
|
||||
|
||||
public static boolean getReadingFullscreen() {
|
||||
return getBoolean(KEY_READING_FULLSCREEN, VALUE_READING_FULLSCREEN);
|
||||
}
|
||||
|
||||
public static void putReadingFullscreen(boolean value) {
|
||||
putBoolean(KEY_READING_FULLSCREEN, value);
|
||||
}
|
||||
|
||||
public static boolean getCustomScreenLightness() {
|
||||
return getBoolean(KEY_CUSTOM_SCREEN_LIGHTNESS, DEFAULT_CUSTOM_SCREEN_LIGHTNESS);
|
||||
}
|
||||
|
||||
public static void putCustomScreenLightness(boolean value) {
|
||||
putBoolean(KEY_CUSTOM_SCREEN_LIGHTNESS, value);
|
||||
}
|
||||
|
||||
public static int getScreenLightness() {
|
||||
return getInt(KEY_SCREEN_LIGHTNESS, DEFAULT_SCREEN_LIGHTNESS);
|
||||
}
|
||||
|
||||
public static void putScreenLightness(int value) {
|
||||
putInt(KEY_SCREEN_LIGHTNESS, value);
|
||||
}
|
||||
|
||||
public static int getReadTheme() {
|
||||
return getIntFromStr(KEY_READ_THEME, DEFAULT_READ_THEME);
|
||||
}
|
||||
|
||||
public static void putReadTheme(int value) {
|
||||
putIntToStr(KEY_READ_THEME, value);
|
||||
}
|
||||
|
||||
public static boolean getEnabledSecurity() {
|
||||
return getBoolean(KEY_SEC_SECURITY, VALUE_SEC_SECURITY);
|
||||
}
|
||||
@@ -616,7 +464,7 @@ public class Settings {
|
||||
builder.encodedPath(getString(KEY_DOWNLOAD_SAVE_PATH, null));
|
||||
builder.encodedQuery(getString(KEY_DOWNLOAD_SAVE_QUERY, null));
|
||||
builder.encodedFragment(getString(KEY_DOWNLOAD_SAVE_FRAGMENT, null));
|
||||
dir = UniFile.fromUri(sContext, builder.build());
|
||||
dir = UniFile.fromUri(EhApplication.getApplication(), builder.build());
|
||||
return dir != null ? dir : UniFile.fromFile(AppConfig.getDefaultDownloadDir());
|
||||
}
|
||||
|
||||
@@ -783,6 +631,14 @@ public class Settings {
|
||||
putInt(KEY_DEFAULT_FAV_SLOT, value);
|
||||
}
|
||||
|
||||
public static boolean getQSSaveProgress() {
|
||||
return getBoolean(KEY_QS_SAVE_PROGRESS, DEFAULT_QS_SAVE_PROGRESS);
|
||||
}
|
||||
|
||||
public static void putQSSaveProgress(boolean value) {
|
||||
putBoolean(KEY_QS_SAVE_PROGRESS, value);
|
||||
}
|
||||
|
||||
public static boolean getSaveParseErrorBody() {
|
||||
return getBoolean(KEY_SAVE_PARSE_ERROR_BODY, DEFAULT_SAVE_PARSE_ERROR_BODY);
|
||||
}
|
||||
@@ -823,10 +679,6 @@ public class Settings {
|
||||
putBoolean(KEY_DOMAIN_FRONTING, value);
|
||||
}
|
||||
|
||||
public static String getAppLanguage() {
|
||||
return getString(KEY_APP_LANGUAGE, DEFAULT_APP_LANGUAGE);
|
||||
}
|
||||
|
||||
public static int getProxyType() {
|
||||
return getInt(KEY_PROXY_TYPE, DEFAULT_PROXY_TYPE);
|
||||
}
|
||||
@@ -851,14 +703,6 @@ public class Settings {
|
||||
putInt(KEY_PROXY_PORT, value);
|
||||
}
|
||||
|
||||
public static boolean getGuideGallery() {
|
||||
return getBoolean(KEY_GUIDE_GALLERY, DEFAULT_GUIDE_GALLERY);
|
||||
}
|
||||
|
||||
public static void putGuideGallery(boolean value) {
|
||||
putBoolean(KEY_GUIDE_GALLERY, value);
|
||||
}
|
||||
|
||||
public static int getClipboardTextHashCode() {
|
||||
return getInt(KEY_CLIPBOARD_TEXT_HASH_CODE, DEFAULT_CLIPBOARD_TEXT_HASH_CODE);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public final class UrlOpener {
|
||||
if (galleryDetail != null) {
|
||||
GalleryPageUrlParser.Result result = GalleryPageUrlParser.parse(url);
|
||||
if (result != null) {
|
||||
if (result.gid == galleryDetail.gid) {
|
||||
if (result.gid == galleryDetail.getGid()) {
|
||||
intent = new Intent(context, ReaderActivity.class);
|
||||
intent.setAction(ReaderActivity.ACTION_EH);
|
||||
intent.putExtra(ReaderActivity.KEY_GALLERY_INFO, galleryDetail);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import okhttp3.Dns
|
||||
import java.net.InetAddress
|
||||
import java.net.UnknownHostException
|
||||
|
||||
class EhDns : Dns {
|
||||
object EhDns : Dns {
|
||||
private val hosts = EhApplication.hosts
|
||||
private val builtInHosts: MutableMap<String, List<InetAddress>> = mutableMapOf()
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -18,12 +18,16 @@ package com.hippo.ehviewer.client;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.hippo.ehviewer.EhDB;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.dao.Filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class EhFilter {
|
||||
|
||||
@@ -31,41 +35,43 @@ public final class EhFilter {
|
||||
public static final int MODE_UPLOADER = 1;
|
||||
public static final int MODE_TAG = 2;
|
||||
public static final int MODE_TAG_NAMESPACE = 3;
|
||||
public static final int MODE_COMMENTER = 4;
|
||||
public static final int MODE_COMMENT = 5;
|
||||
private static final String TAG = EhFilter.class.getSimpleName();
|
||||
private static EhFilter sInstance;
|
||||
private final List<Filter> mTitleFilterList = new ArrayList<>();
|
||||
private final List<Filter> mUploaderFilterList = new ArrayList<>();
|
||||
private final List<Filter> mTagFilterList = new ArrayList<>();
|
||||
private final List<Filter> mTagNamespaceFilterList = new ArrayList<>();
|
||||
private final List<Filter> mCommenterFilterList = new ArrayList<>();
|
||||
private final List<Filter> mCommentFilterList = new ArrayList<>();
|
||||
|
||||
private EhFilter() {
|
||||
List<Filter> list = EhDB.getAllFilter();
|
||||
for (int i = 0, n = list.size(); i < n; i++) {
|
||||
Filter filter = list.get(i);
|
||||
switch (filter.mode) {
|
||||
case MODE_TITLE:
|
||||
case MODE_TITLE -> {
|
||||
filter.text = filter.text.toLowerCase();
|
||||
mTitleFilterList.add(filter);
|
||||
break;
|
||||
case MODE_UPLOADER:
|
||||
mUploaderFilterList.add(filter);
|
||||
break;
|
||||
case MODE_TAG:
|
||||
}
|
||||
case MODE_TAG -> {
|
||||
filter.text = filter.text.toLowerCase();
|
||||
mTagFilterList.add(filter);
|
||||
break;
|
||||
case MODE_TAG_NAMESPACE:
|
||||
}
|
||||
case MODE_TAG_NAMESPACE -> {
|
||||
filter.text = filter.text.toLowerCase();
|
||||
mTagNamespaceFilterList.add(filter);
|
||||
break;
|
||||
default:
|
||||
Log.d(TAG, "Unknown mode: " + filter.mode);
|
||||
break;
|
||||
}
|
||||
case MODE_UPLOADER -> mUploaderFilterList.add(filter);
|
||||
case MODE_COMMENTER -> mCommenterFilterList.add(filter);
|
||||
case MODE_COMMENT -> mCommentFilterList.add(filter);
|
||||
default -> Log.d(TAG, "Unknown mode: " + filter.mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static EhFilter getInstance() {
|
||||
public static @NonNull EhFilter getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new EhFilter();
|
||||
}
|
||||
@@ -88,30 +94,36 @@ public final class EhFilter {
|
||||
return mTagNamespaceFilterList;
|
||||
}
|
||||
|
||||
public List<Filter> getCommenterFilterList() {
|
||||
return mCommenterFilterList;
|
||||
}
|
||||
|
||||
public List<Filter> getCommentFilterList() {
|
||||
return mCommentFilterList;
|
||||
}
|
||||
|
||||
public synchronized boolean addFilter(Filter filter) {
|
||||
// enable filter by default before it is added to database
|
||||
filter.enable = true;
|
||||
if (!EhDB.addFilter(filter)) return false;
|
||||
|
||||
switch (filter.mode) {
|
||||
case MODE_TITLE:
|
||||
case MODE_TITLE -> {
|
||||
filter.text = filter.text.toLowerCase();
|
||||
mTitleFilterList.add(filter);
|
||||
break;
|
||||
case MODE_UPLOADER:
|
||||
mUploaderFilterList.add(filter);
|
||||
break;
|
||||
case MODE_TAG:
|
||||
}
|
||||
case MODE_TAG -> {
|
||||
filter.text = filter.text.toLowerCase();
|
||||
mTagFilterList.add(filter);
|
||||
break;
|
||||
case MODE_TAG_NAMESPACE:
|
||||
}
|
||||
case MODE_TAG_NAMESPACE -> {
|
||||
filter.text = filter.text.toLowerCase();
|
||||
mTagNamespaceFilterList.add(filter);
|
||||
break;
|
||||
default:
|
||||
Log.d(TAG, "Unknown mode: " + filter.mode);
|
||||
break;
|
||||
}
|
||||
case MODE_UPLOADER -> mUploaderFilterList.add(filter);
|
||||
case MODE_COMMENTER -> mCommenterFilterList.add(filter);
|
||||
case MODE_COMMENT -> mCommentFilterList.add(filter);
|
||||
default -> Log.d(TAG, "Unknown mode: " + filter.mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -124,21 +136,13 @@ public final class EhFilter {
|
||||
EhDB.deleteFilter(filter);
|
||||
|
||||
switch (filter.mode) {
|
||||
case MODE_TITLE:
|
||||
mTitleFilterList.remove(filter);
|
||||
break;
|
||||
case MODE_UPLOADER:
|
||||
mUploaderFilterList.remove(filter);
|
||||
break;
|
||||
case MODE_TAG:
|
||||
mTagFilterList.remove(filter);
|
||||
break;
|
||||
case MODE_TAG_NAMESPACE:
|
||||
mTagNamespaceFilterList.remove(filter);
|
||||
break;
|
||||
default:
|
||||
Log.d(TAG, "Unknown mode: " + filter.mode);
|
||||
break;
|
||||
case MODE_TITLE -> mTitleFilterList.remove(filter);
|
||||
case MODE_TAG -> mTagFilterList.remove(filter);
|
||||
case MODE_TAG_NAMESPACE -> mTagNamespaceFilterList.remove(filter);
|
||||
case MODE_UPLOADER -> mUploaderFilterList.remove(filter);
|
||||
case MODE_COMMENTER -> mCommenterFilterList.remove(filter);
|
||||
case MODE_COMMENT -> mCommentFilterList.remove(filter);
|
||||
default -> Log.d(TAG, "Unknown mode: " + filter.mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +156,7 @@ public final class EhFilter {
|
||||
}
|
||||
|
||||
// Title
|
||||
String title = info.title;
|
||||
String title = info.getTitle();
|
||||
List<Filter> filters = mTitleFilterList;
|
||||
if (null != title && filters.size() > 0) {
|
||||
for (int i = 0, n = filters.size(); i < n; i++) {
|
||||
@@ -171,7 +175,7 @@ public final class EhFilter {
|
||||
}
|
||||
|
||||
// Uploader
|
||||
String uploader = info.uploader;
|
||||
String uploader = info.getUploader();
|
||||
List<Filter> filters = mUploaderFilterList;
|
||||
if (null != uploader && filters.size() > 0) {
|
||||
for (int i = 0, n = filters.size(); i < n; i++) {
|
||||
@@ -223,7 +227,7 @@ public final class EhFilter {
|
||||
}
|
||||
|
||||
// Tag
|
||||
String[] tags = info.simpleTags;
|
||||
String[] tags = info.getSimpleTags();
|
||||
List<Filter> filters = mTagFilterList;
|
||||
if (null != tags && filters.size() > 0) {
|
||||
for (String tag : tags) {
|
||||
@@ -258,7 +262,7 @@ public final class EhFilter {
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] tags = info.simpleTags;
|
||||
String[] tags = info.getSimpleTags();
|
||||
List<Filter> filters = mTagNamespaceFilterList;
|
||||
if (null != tags && filters.size() > 0) {
|
||||
for (String tag : tags) {
|
||||
@@ -272,4 +276,40 @@ public final class EhFilter {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized boolean filterCommenter(String commenter) {
|
||||
if (null == commenter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Filter> filters = mCommenterFilterList;
|
||||
if (filters.size() > 0) {
|
||||
for (int i = 0, n = filters.size(); i < n; i++) {
|
||||
if (filters.get(i).enable && commenter.equals(filters.get(i).text)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized boolean filterComment(String comment) {
|
||||
if (null == comment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Filter> filters = mCommentFilterList;
|
||||
if (filters.size() > 0) {
|
||||
for (int i = 0, n = filters.size(); i < n; i++) {
|
||||
if (filters.get(i).enable) {
|
||||
Pattern p = Pattern.compile(filters.get(i).text);
|
||||
Matcher m = p.matcher(comment);
|
||||
if (m.find()) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import java.net.Socket
|
||||
import javax.net.ssl.SSLSocket
|
||||
import javax.net.ssl.SSLSocketFactory
|
||||
|
||||
class EhSSLSocketFactory : SSLSocketFactory() {
|
||||
object EhSSLSocketFactory : SSLSocketFactory() {
|
||||
private val sslSocketFactory = getDefault() as SSLSocketFactory
|
||||
override fun getDefaultCipherSuites(): Array<String> {
|
||||
return sslSocketFactory.defaultCipherSuites
|
||||
|
||||
@@ -1,436 +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;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Base64;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.util.Pair;
|
||||
|
||||
import com.hippo.ehviewer.AppConfig;
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.util.IoThreadPoolExecutor;
|
||||
import com.hippo.yorozuya.FileUtils;
|
||||
import com.hippo.yorozuya.IOUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import okio.BufferedSource;
|
||||
import okio.Okio;
|
||||
|
||||
public class EhTagDatabase {
|
||||
|
||||
private static final Map<String, String> NAMESPACE_TO_PREFIX = new HashMap<>();
|
||||
// TODO more lock for different language
|
||||
private static final Lock lock = new ReentrantLock();
|
||||
private static volatile EhTagDatabase instance;
|
||||
|
||||
static {
|
||||
NAMESPACE_TO_PREFIX.put("artist", "a:");
|
||||
NAMESPACE_TO_PREFIX.put("cosplayer", "cos:");
|
||||
NAMESPACE_TO_PREFIX.put("character", "c:");
|
||||
NAMESPACE_TO_PREFIX.put("female", "f:");
|
||||
NAMESPACE_TO_PREFIX.put("group", "g:");
|
||||
NAMESPACE_TO_PREFIX.put("language", "l:");
|
||||
NAMESPACE_TO_PREFIX.put("male", "m:");
|
||||
NAMESPACE_TO_PREFIX.put("mixed", "x:");
|
||||
NAMESPACE_TO_PREFIX.put("other", "o:");
|
||||
NAMESPACE_TO_PREFIX.put("parody", "p:");
|
||||
NAMESPACE_TO_PREFIX.put("reclass", "r:");
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final byte[] tags;
|
||||
|
||||
public EhTagDatabase(String name, BufferedSource source) throws IOException {
|
||||
this.name = name;
|
||||
String[] tmp;
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
source.readInt();
|
||||
for (String i : source.readUtf8().split("\n")) {
|
||||
tmp = i.split("\r", 2);
|
||||
buffer.append(tmp[0]);
|
||||
buffer.append("\r");
|
||||
try {
|
||||
buffer.append(new String(Base64.decode(tmp[1], Base64.DEFAULT), StandardCharsets.UTF_8));
|
||||
} catch (Exception e) {
|
||||
buffer.append(tmp[1]);
|
||||
}
|
||||
buffer.append("\n");
|
||||
}
|
||||
byte[] b = buffer.toString().getBytes(StandardCharsets.UTF_8);
|
||||
int totalBytes = b.length;
|
||||
tags = new byte[totalBytes];
|
||||
System.arraycopy(b, 0, tags, 0, totalBytes);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static EhTagDatabase getInstance(Context context) {
|
||||
if (isPossible(context)) {
|
||||
return instance;
|
||||
} else {
|
||||
instance = null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String namespaceToPrefix(String namespace) {
|
||||
return NAMESPACE_TO_PREFIX.get(namespace);
|
||||
}
|
||||
|
||||
private static String[] getMetadata(Context context) {
|
||||
String[] metadata = context.getResources().getStringArray(R.array.tag_translation_metadata);
|
||||
if (metadata.length == 4) {
|
||||
return metadata;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPossible(Context context) {
|
||||
return getMetadata(context) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static byte[] getFileContent(File file, int length) {
|
||||
try (BufferedSource source = Okio.buffer(Okio.source(file))) {
|
||||
byte[] content = new byte[length];
|
||||
source.readFully(content);
|
||||
return content;
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static byte[] getFileSha1(File file) {
|
||||
try (InputStream is = new FileInputStream(file)) {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
||||
int n;
|
||||
byte[] buffer = new byte[4 * 1024];
|
||||
while ((n = is.read(buffer)) != -1) {
|
||||
digest.update(buffer, 0, n);
|
||||
}
|
||||
return digest.digest();
|
||||
} catch (IOException | NoSuchAlgorithmException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean equals(byte[] b1, byte[] b2) {
|
||||
if (b1 == null && b2 == null) {
|
||||
return true;
|
||||
}
|
||||
if (b1 == null || b2 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (b1.length != b2.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < b1.length; i++) {
|
||||
if (b1[i] != b2[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean checkData(File sha1File, File dataFile) {
|
||||
byte[] s1 = getFileContent(sha1File, 20);
|
||||
if (s1 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] s2 = getFileSha1(dataFile);
|
||||
if (s2 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return equals(s1, s2);
|
||||
}
|
||||
|
||||
private static boolean save(OkHttpClient client, String url, File file) {
|
||||
Request request = new Request.Builder().url(url).build();
|
||||
Call call = client.newCall(request);
|
||||
try (Response response = call.execute()) {
|
||||
if (!response.isSuccessful()) {
|
||||
return false;
|
||||
}
|
||||
ResponseBody body = response.body();
|
||||
if (body == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try (InputStream is = body.byteStream(); OutputStream os = new FileOutputStream(file)) {
|
||||
IOUtils.copy(is, os);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
ExceptionUtils.throwIfFatal(t);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void update(Context context) {
|
||||
String[] urls = getMetadata(context);
|
||||
if (urls == null || urls.length != 4) {
|
||||
// Clear tags if it's not possible
|
||||
instance = null;
|
||||
return;
|
||||
}
|
||||
|
||||
String sha1Name = urls[0];
|
||||
String sha1Url = urls[1];
|
||||
String dataName = urls[2];
|
||||
String dataUrl = urls[3];
|
||||
|
||||
// Clear tags if name if different
|
||||
EhTagDatabase tmp = instance;
|
||||
if (tmp != null && !tmp.name.equals(dataName)) {
|
||||
instance = null;
|
||||
}
|
||||
|
||||
IoThreadPoolExecutor.getInstance().execute(() -> {
|
||||
if (!lock.tryLock()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
File dir = AppConfig.getFilesDir("tag-translations");
|
||||
if (dir == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check current sha1 and current data
|
||||
File sha1File = new File(dir, sha1Name);
|
||||
File dataFile = new File(dir, dataName);
|
||||
if (!checkData(sha1File, dataFile)) {
|
||||
FileUtils.delete(sha1File);
|
||||
FileUtils.delete(dataFile);
|
||||
}
|
||||
|
||||
// Read current EhTagDatabase
|
||||
if (instance == null && dataFile.exists()) {
|
||||
try (BufferedSource source = Okio.buffer(Okio.source(dataFile))) {
|
||||
instance = new EhTagDatabase(dataName, source);
|
||||
} catch (IOException e) {
|
||||
FileUtils.delete(sha1File);
|
||||
FileUtils.delete(dataFile);
|
||||
}
|
||||
}
|
||||
|
||||
OkHttpClient client = EhApplication.getOkHttpClient();
|
||||
|
||||
// Save new sha1
|
||||
File tempSha1File = new File(dir, sha1Name + ".tmp");
|
||||
if (!save(client, sha1Url, tempSha1File)) {
|
||||
FileUtils.delete(tempSha1File);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check new sha1 and current data
|
||||
if (checkData(tempSha1File, dataFile)) {
|
||||
// The data is the same
|
||||
FileUtils.delete(tempSha1File);
|
||||
return;
|
||||
}
|
||||
|
||||
// Save new data
|
||||
File tempDataFile = new File(dir, dataName + ".tmp");
|
||||
if (!save(client, dataUrl, tempDataFile)) {
|
||||
FileUtils.delete(tempDataFile);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check new sha1 and new data
|
||||
if (!checkData(tempSha1File, tempDataFile)) {
|
||||
FileUtils.delete(tempSha1File);
|
||||
FileUtils.delete(tempDataFile);
|
||||
return;
|
||||
}
|
||||
|
||||
// Replace current sha1 and current data with new sha1 and new data
|
||||
FileUtils.delete(sha1File);
|
||||
FileUtils.delete(dataFile);
|
||||
tempSha1File.renameTo(sha1File);
|
||||
tempDataFile.renameTo(dataFile);
|
||||
|
||||
// Read new EhTagDatabase
|
||||
try (BufferedSource source = Okio.buffer(Okio.source(dataFile))) {
|
||||
instance = new EhTagDatabase(dataName, source);
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String getTranslation(String tag) {
|
||||
return search(tags, tag.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String search(byte[] tags, byte[] tag) {
|
||||
int low = 0;
|
||||
int high = tags.length;
|
||||
while (low < high) {
|
||||
int start = (low + high) / 2;
|
||||
// Look for the starting '\n'
|
||||
while (start > -1 && tags[start] != '\n') {
|
||||
start--;
|
||||
}
|
||||
start++;
|
||||
|
||||
// Look for the middle '\r'.
|
||||
int middle = 1;
|
||||
while (tags[start + middle] != '\r') {
|
||||
middle++;
|
||||
}
|
||||
|
||||
// Look for the ending '\n'
|
||||
int end = middle + 1;
|
||||
while (tags[start + end] != '\n') {
|
||||
end++;
|
||||
}
|
||||
|
||||
int compare;
|
||||
int tagIndex = 0;
|
||||
int curIndex = start;
|
||||
|
||||
for (; ; ) {
|
||||
int tagByte = tag[tagIndex] & 0xff;
|
||||
int curByte = tags[curIndex] & 0xff;
|
||||
compare = tagByte - curByte;
|
||||
if (compare != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
tagIndex++;
|
||||
curIndex++;
|
||||
if (tagIndex == tag.length && curIndex == start + middle) {
|
||||
break;
|
||||
}
|
||||
if (tagIndex == tag.length) {
|
||||
compare = -1;
|
||||
break;
|
||||
}
|
||||
if (curIndex == start + middle) {
|
||||
compare = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (compare < 0) {
|
||||
high = start - 1;
|
||||
} else if (compare > 0) {
|
||||
low = start + end + 1;
|
||||
} else {
|
||||
return new String(tags, start + middle + 1, end - middle - 1, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ArrayList<Pair<String, String>> suggest(String keyword) {
|
||||
return searchTag(tags, keyword);
|
||||
}
|
||||
|
||||
private ArrayList<Pair<String, String>> searchTag(byte[] tags, String keyword) {
|
||||
ArrayList<Pair<String, String>> searchHints = new ArrayList<>();
|
||||
int begin = 0;
|
||||
while (begin < tags.length - 1) {
|
||||
int start = begin;
|
||||
// Look for the starting '\n'
|
||||
while (tags[start] != '\n') {
|
||||
start++;
|
||||
}
|
||||
|
||||
// Look for the middle '\r'.
|
||||
int middle = 1;
|
||||
while (tags[start + middle] != '\r') {
|
||||
middle++;
|
||||
}
|
||||
|
||||
// Look for the ending '\n'
|
||||
int end = middle + 1;
|
||||
while (tags[start + end] != '\n') {
|
||||
end++;
|
||||
}
|
||||
|
||||
begin = start + end;
|
||||
|
||||
byte[] hintBytes = new byte[end - middle - 1];
|
||||
System.arraycopy(tags, start + middle + 1, hintBytes, 0, end - middle - 1);
|
||||
String hint = new String(hintBytes, StandardCharsets.UTF_8);
|
||||
byte[] tagBytes = new byte[middle];
|
||||
System.arraycopy(tags, start + 1, tagBytes, 0, middle);
|
||||
String tag = new String(tagBytes, StandardCharsets.UTF_8);
|
||||
int index = tag.indexOf(':');
|
||||
boolean keywordMatches;
|
||||
if (index == -1 || index >= tag.length() - 1 || keyword.length() > 2) {
|
||||
keywordMatches = containsIgnoreSpace(tag, keyword);
|
||||
} else {
|
||||
keywordMatches = containsIgnoreSpace(tag.substring(index + 1), keyword);
|
||||
}
|
||||
|
||||
if (keywordMatches || containsIgnoreSpace(hint, keyword)) {
|
||||
Pair<String, String> pair = new Pair<>(hint, tag);
|
||||
if (!searchHints.contains(pair)) {
|
||||
searchHints.add(pair);
|
||||
}
|
||||
}
|
||||
if (searchHints.size() > 20) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return searchHints;
|
||||
}
|
||||
|
||||
private boolean containsIgnoreSpace(String text, String key) {
|
||||
return text.replace(" ", "").contains(key.replace(" ", ""));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import android.content.Context
|
||||
import com.hippo.ehviewer.AppConfig
|
||||
import com.hippo.ehviewer.EhApplication
|
||||
import com.hippo.ehviewer.EhApplication.Companion.okHttpClient
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.util.ExceptionUtils
|
||||
import com.hippo.util.HashCodeUtils
|
||||
import com.hippo.yorozuya.FileUtils
|
||||
import com.hippo.yorozuya.IOUtils
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okio.BufferedSource
|
||||
import okio.buffer
|
||||
import okio.source
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.security.MessageDigest
|
||||
import java.security.NoSuchAlgorithmException
|
||||
|
||||
object EhTagDatabase {
|
||||
private lateinit var tags: JSONObject
|
||||
private lateinit var tagList: ArrayList<Pair<String, String>>
|
||||
|
||||
fun isInitialized(): Boolean {
|
||||
return this::tags.isInitialized && this::tagList.isInitialized
|
||||
}
|
||||
|
||||
private fun updateData(source: BufferedSource) {
|
||||
try {
|
||||
val tmpTags = JSONObject(source.readString(StandardCharsets.UTF_8))
|
||||
val tmpTagList = arrayListOf<Pair<String, String>>()
|
||||
tmpTags.keys().forEachRemaining { prefix: String ->
|
||||
val values = tmpTags.optJSONObject(prefix)
|
||||
values?.let {
|
||||
it.keys().forEachRemaining { tag: String ->
|
||||
tmpTagList.add(Pair("$prefix:$tag", values.optString(tag)))
|
||||
}
|
||||
}
|
||||
}
|
||||
tags = tmpTags
|
||||
tagList = tmpTagList
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
fun getTranslation(prefix: String?, tag: String?): String? {
|
||||
return tags.optJSONObject(prefix)?.optString(tag)?.trim()?.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
|
||||
/* Construct a cold flow for tag database suggestions */
|
||||
fun suggestFlow(
|
||||
keyword: String,
|
||||
translate: Boolean,
|
||||
exactly: Boolean = false
|
||||
): Flow<Pair<String?, String>> = flow {
|
||||
tagList.forEach {
|
||||
val tag = it.first
|
||||
val hint = if (translate) it.second else null
|
||||
val index = tag.indexOf(':')
|
||||
if (tag.substring(index + 1).trim() == keyword) {
|
||||
if (exactly)
|
||||
emit(Pair(hint, tag))
|
||||
return@forEach
|
||||
}
|
||||
if (exactly)
|
||||
return@forEach
|
||||
val keywordMatches: Boolean =
|
||||
if (index == -1 || index >= tag.length - 1 || keyword.length > 2) {
|
||||
containsIgnoreSpace(tag, keyword)
|
||||
} else {
|
||||
containsIgnoreSpace(tag.substring(index + 1), keyword)
|
||||
}
|
||||
if (keywordMatches || containsIgnoreSpace(hint, keyword)) {
|
||||
emit(Pair(hint, tag))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun containsIgnoreSpace(text: String?, key: String): Boolean {
|
||||
return text != null && text.replace(" ", "").contains(key.replace(" ", ""))
|
||||
}
|
||||
|
||||
private val NAMESPACE_TO_PREFIX = HashMap<String, String>().also {
|
||||
it["artist"] = "a"
|
||||
it["cosplayer"] = "cos"
|
||||
it["character"] = "c"
|
||||
it["female"] = "f"
|
||||
it["group"] = "g"
|
||||
it["language"] = "l"
|
||||
it["male"] = "m"
|
||||
it["mixed"] = "x"
|
||||
it["other"] = "o"
|
||||
it["parody"] = "p"
|
||||
it["reclass"] = "r"
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun namespaceToPrefix(namespace: String): String? {
|
||||
return NAMESPACE_TO_PREFIX[namespace]
|
||||
}
|
||||
|
||||
private fun getMetadata(context: Context): Array<String>? {
|
||||
return context.resources.getStringArray(R.array.tag_translation_metadata)
|
||||
.takeIf { it.size == 4 }
|
||||
}
|
||||
|
||||
fun isTranslatable(context: Context): Boolean {
|
||||
return context.resources.getBoolean(R.bool.tag_translatable)
|
||||
}
|
||||
|
||||
private fun getFileContent(file: File): String? {
|
||||
try {
|
||||
file.source().buffer().use { return it.readString(StandardCharsets.UTF_8) }
|
||||
} catch (e: IOException) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFileSha1(file: File): String? {
|
||||
try {
|
||||
FileInputStream(file).use { stream ->
|
||||
val digest = MessageDigest.getInstance("SHA-1")
|
||||
var n: Int
|
||||
val buffer = ByteArray(4 * 1024)
|
||||
while (stream.read(buffer).also { n = it } != -1) {
|
||||
digest.update(buffer, 0, n)
|
||||
}
|
||||
return HashCodeUtils.bytesToHexString(digest.digest())
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
return null
|
||||
} catch (e: NoSuchAlgorithmException) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkData(sha1File: File, dataFile: File): Boolean {
|
||||
val s1 = getFileContent(sha1File) ?: return false
|
||||
val s2 = getFileSha1(dataFile) ?: return false
|
||||
return s1 == s2
|
||||
}
|
||||
|
||||
private fun save(client: OkHttpClient, url: String, file: File): Boolean {
|
||||
val request: Request = Request.Builder().url(url).build()
|
||||
val call = client.newCall(request)
|
||||
try {
|
||||
call.execute().use { response ->
|
||||
if (!response.isSuccessful) {
|
||||
return false
|
||||
}
|
||||
val body = response.body
|
||||
body.byteStream()
|
||||
.use { ins -> FileOutputStream(file).use { os -> IOUtils.copy(ins, os) } }
|
||||
return true
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
FileUtils.delete(file)
|
||||
t.printStackTrace()
|
||||
ExceptionUtils.throwIfFatal(t)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
@JvmStatic
|
||||
fun update() {
|
||||
launchIO {
|
||||
updateInternal()
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun updateInternal() {
|
||||
val urls = getMetadata(EhApplication.application)
|
||||
urls?.let {
|
||||
val sha1Name = urls[0]
|
||||
val sha1Url = urls[1]
|
||||
val dataName = urls[2]
|
||||
val dataUrl = urls[3]
|
||||
|
||||
try {
|
||||
val dir = AppConfig.getFilesDir("tag-translations")
|
||||
checkNotNull(dir)
|
||||
|
||||
// Check current sha1 and current data
|
||||
val sha1File = File(dir, sha1Name)
|
||||
val dataFile = File(dir, dataName)
|
||||
if (!checkData(sha1File, dataFile)) {
|
||||
FileUtils.delete(sha1File)
|
||||
FileUtils.delete(dataFile)
|
||||
}
|
||||
|
||||
// Read current EhTagDatabase
|
||||
if (!isInitialized() && dataFile.exists()) {
|
||||
try {
|
||||
dataFile.source().buffer().use { updateData(it) }
|
||||
} catch (e: IOException) {
|
||||
FileUtils.delete(sha1File)
|
||||
FileUtils.delete(dataFile)
|
||||
}
|
||||
}
|
||||
val client = okHttpClient
|
||||
|
||||
// Save new sha1
|
||||
val tempSha1File = File(dir, "$sha1Name.tmp")
|
||||
check(save(client, sha1Url, tempSha1File))
|
||||
|
||||
// Check new sha1 and current data
|
||||
if (checkData(tempSha1File, dataFile)) {
|
||||
// The data is the same
|
||||
FileUtils.delete(tempSha1File)
|
||||
return
|
||||
}
|
||||
|
||||
// Save new data
|
||||
val tempDataFile = File(dir, "$dataName.tmp")
|
||||
check(save(client, dataUrl, tempDataFile))
|
||||
|
||||
// Check new sha1 and new data
|
||||
if (!checkData(tempSha1File, tempDataFile)) {
|
||||
FileUtils.delete(tempSha1File)
|
||||
FileUtils.delete(tempDataFile)
|
||||
return
|
||||
}
|
||||
|
||||
// Replace current sha1 and current data with new sha1 and new data
|
||||
FileUtils.delete(sha1File)
|
||||
FileUtils.delete(dataFile)
|
||||
tempSha1File.renameTo(sha1File)
|
||||
tempDataFile.renameTo(dataFile)
|
||||
|
||||
// Read new EhTagDatabase
|
||||
try {
|
||||
dataFile.source().buffer().use { updateData(it) }
|
||||
} catch (_: IOException) {
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,9 +133,9 @@ public class EhUtils {
|
||||
|
||||
public static String getSuitableTitle(GalleryInfo gi) {
|
||||
if (Settings.getShowJpnTitle()) {
|
||||
return TextUtils.isEmpty(gi.titleJpn) ? gi.title : gi.titleJpn;
|
||||
return TextUtils.isEmpty(gi.getTitleJpn()) ? gi.getTitle() : gi.getTitleJpn();
|
||||
} else {
|
||||
return TextUtils.isEmpty(gi.title) ? gi.titleJpn : gi.title;
|
||||
return TextUtils.isEmpty(gi.getTitle()) ? gi.getTitleJpn() : gi.getTitle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.security.cert.X509Certificate
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
@SuppressLint("CustomX509TrustManager")
|
||||
class EhX509TrustManager : X509TrustManager {
|
||||
object EhX509TrustManager : X509TrustManager {
|
||||
@SuppressLint("TrustAllX509TrustManager")
|
||||
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.hippo.ehviewer.client.data
|
||||
|
||||
interface AbstractGalleryInfo {
|
||||
var gid: Long
|
||||
var token: String?
|
||||
var title: String?
|
||||
var titleJpn: String?
|
||||
var thumb: String?
|
||||
var category: Int
|
||||
var posted: String?
|
||||
var uploader: String?
|
||||
var disowned: Boolean
|
||||
var rating: Float
|
||||
var rated: Boolean
|
||||
var simpleTags: Array<String>?
|
||||
var pages: Int
|
||||
var thumbWidth: Int
|
||||
var thumbHeight: Int
|
||||
var spanSize: Int
|
||||
var spanIndex: Int
|
||||
var spanGroupIndex: Int
|
||||
var simpleLanguage: String?
|
||||
var favoriteSlot: Int
|
||||
var favoriteName: String?
|
||||
}
|
||||
@@ -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 androidx.room.ColumnInfo
|
||||
import androidx.room.Ignore
|
||||
import androidx.room.PrimaryKey
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
open class BaseGalleryInfo(
|
||||
@PrimaryKey
|
||||
@ColumnInfo(name = "GID")
|
||||
override var gid: Long = 0,
|
||||
|
||||
@ColumnInfo(name = "TOKEN")
|
||||
override var token: String? = null,
|
||||
|
||||
@ColumnInfo(name = "TITLE")
|
||||
override var title: String? = null,
|
||||
|
||||
@ColumnInfo(name = "TITLE_JPN")
|
||||
override var titleJpn: String? = null,
|
||||
|
||||
@ColumnInfo(name = "THUMB")
|
||||
override var thumb: String? = null,
|
||||
|
||||
@ColumnInfo(name = "CATEGORY")
|
||||
override var category: Int = 0,
|
||||
|
||||
@ColumnInfo(name = "POSTED")
|
||||
override var posted: String? = null,
|
||||
|
||||
@ColumnInfo(name = "UPLOADER")
|
||||
override var uploader: String? = null,
|
||||
|
||||
@Ignore
|
||||
override var disowned: Boolean = false,
|
||||
|
||||
@ColumnInfo(name = "RATING")
|
||||
override var rating: Float = 0f,
|
||||
|
||||
@Ignore
|
||||
override var rated: Boolean = false,
|
||||
|
||||
@Ignore
|
||||
override var simpleTags: Array<String>? = null,
|
||||
|
||||
@Ignore
|
||||
override var pages: Int = 0,
|
||||
|
||||
@Ignore
|
||||
override var thumbWidth: Int = 0,
|
||||
|
||||
@Ignore
|
||||
override var thumbHeight: Int = 0,
|
||||
|
||||
@Ignore
|
||||
override var spanSize: Int = 0,
|
||||
|
||||
@Ignore
|
||||
override var spanIndex: Int = 0,
|
||||
|
||||
@Ignore
|
||||
override var spanGroupIndex: Int = 0,
|
||||
|
||||
@ColumnInfo(name = "SIMPLE_LANGUAGE")
|
||||
override var simpleLanguage: String? = null,
|
||||
|
||||
@Ignore
|
||||
override var favoriteSlot: Int = -2,
|
||||
|
||||
@Ignore
|
||||
override var favoriteName: String? = null
|
||||
|
||||
) : GalleryInfo
|
||||
@@ -1,150 +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<FavListUrlBuilder>() {
|
||||
|
||||
@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 setPrev(String prev) {
|
||||
mPrev = prev;
|
||||
}
|
||||
|
||||
public void setNext(String next) {
|
||||
mNext = next;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
// Name
|
||||
ub.addQuery("sn", "on");
|
||||
// Tags
|
||||
ub.addQuery("st", "on");
|
||||
// Note
|
||||
ub.addQuery("sf", "on");
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
+21
-19
@@ -13,24 +13,26 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.hippo.ehviewer.client.data
|
||||
|
||||
package com.hippo.ehviewer.ui.fragment;
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
public class ReadFragment extends BasePreferenceFragment {
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
addPreferencesFromResource(R.xml.read_settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFragmentTitle() {
|
||||
return R.string.settings_read;
|
||||
}
|
||||
}
|
||||
@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");
|
||||
* 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
|
||||
* 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 {
|
||||
|
||||
public EhException(String detailMessage) {
|
||||
super(detailMessage);
|
||||
}
|
||||
|
||||
public EhException(String detailMessage, Throwable cause) {
|
||||
super(detailMessage, cause);
|
||||
}
|
||||
}
|
||||
@Parcelize
|
||||
class GalleryCommentList(
|
||||
@JvmField
|
||||
var comments: Array<GalleryComment>?,
|
||||
@JvmField
|
||||
var hasMore: Boolean
|
||||
) : Parcelable
|
||||
@@ -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,75 @@
|
||||
/*
|
||||
* 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
|
||||
class GalleryDetail(
|
||||
@JvmField
|
||||
val galleryInfo: GalleryInfo = BaseGalleryInfo(),
|
||||
|
||||
@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,
|
||||
) : AbstractGalleryInfo by galleryInfo, 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,131 @@
|
||||
/*
|
||||
* 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 java.util.regex.Pattern
|
||||
|
||||
interface GalleryInfo : AbstractGalleryInfo, 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"
|
||||
|
||||
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
|
||||
* 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 {
|
||||
|
||||
private final String mBody;
|
||||
|
||||
public ParseException(String detailMessage, String body) {
|
||||
super(detailMessage);
|
||||
mBody = body;
|
||||
@Parcelize
|
||||
class GalleryTagGroup(
|
||||
private val mTagList: ArrayList<String> = arrayListOf(),
|
||||
@JvmField
|
||||
var groupName: String? = null
|
||||
) : Parcelable {
|
||||
fun addTag(tag: String) {
|
||||
mTagList.add(tag)
|
||||
}
|
||||
|
||||
public ParseException(String detailMessage, String body, Throwable cause) {
|
||||
super(detailMessage, cause);
|
||||
mBody = body;
|
||||
fun size(): Int {
|
||||
return mTagList.size
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return mBody;
|
||||
fun getTagAt(position: Int): String {
|
||||
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
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.os.Parcelable.Creator
|
||||
import android.text.TextUtils
|
||||
import androidx.annotation.IntDef
|
||||
import com.hippo.ehviewer.client.EhConfig
|
||||
@@ -26,54 +24,36 @@ import com.hippo.ehviewer.client.EhUtils
|
||||
import com.hippo.ehviewer.dao.QuickSearch
|
||||
import com.hippo.ehviewer.widget.AdvanceSearchTable
|
||||
import com.hippo.network.UrlBuilder
|
||||
import com.hippo.util.encodeUTF8
|
||||
import com.hippo.yorozuya.NumberUtils
|
||||
import com.hippo.yorozuya.StringUtils
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import java.io.UnsupportedEncodingException
|
||||
import java.net.URLDecoder
|
||||
import java.net.URLEncoder
|
||||
|
||||
open class ListUrlBuilder : Cloneable, Parcelable {
|
||||
@get:Mode
|
||||
@Mode
|
||||
var mode = MODE_NORMAL
|
||||
private var mPrevGid = 0
|
||||
private var mNextGid = 0
|
||||
private var mJumpTo: String? = null
|
||||
var category = EhUtils.NONE
|
||||
private var mKeyword: String? = null
|
||||
private var mSHash: String? = null
|
||||
var advanceSearch = -1
|
||||
var minRating = -1
|
||||
var pageFrom = -1
|
||||
var pageTo = -1
|
||||
var imagePath: String? = null
|
||||
var isUseSimilarityScan = false
|
||||
var isOnlySearchCovers = false
|
||||
var isShowExpunged = false
|
||||
|
||||
constructor()
|
||||
protected constructor(parcel: Parcel) {
|
||||
mode = parcel.readInt()
|
||||
mPrevGid = parcel.readInt()
|
||||
mNextGid = parcel.readInt()
|
||||
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()
|
||||
}
|
||||
@Parcelize
|
||||
data class ListUrlBuilder(
|
||||
@get:Mode @Mode var mode: Int = MODE_NORMAL,
|
||||
private var mPrev: String? = null,
|
||||
private var mNext: String? = null,
|
||||
private var mJumpTo: String? = null,
|
||||
var category: Int = EhUtils.NONE,
|
||||
private var mKeyword: String? = null,
|
||||
private var mSHash: String? = null,
|
||||
var advanceSearch: Int = -1,
|
||||
var minRating: Int = -1,
|
||||
var pageFrom: Int = -1,
|
||||
var pageTo: Int = -1,
|
||||
var imagePath: String? = null,
|
||||
var isUseSimilarityScan: Boolean = false,
|
||||
var isOnlySearchCovers: Boolean = false,
|
||||
var isShowExpunged: Boolean = false,
|
||||
) : Parcelable {
|
||||
|
||||
fun reset() {
|
||||
mode = MODE_NORMAL
|
||||
mPrevGid = 0
|
||||
mNextGid = 0
|
||||
mPrev = null
|
||||
mNext = null
|
||||
mJumpTo = null
|
||||
this.category = EhUtils.NONE
|
||||
mKeyword = null
|
||||
@@ -88,20 +68,9 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
||||
mSHash = null
|
||||
}
|
||||
|
||||
public override fun clone(): ListUrlBuilder {
|
||||
return try {
|
||||
super.clone() as ListUrlBuilder
|
||||
} catch (e: CloneNotSupportedException) {
|
||||
throw IllegalStateException(e)
|
||||
}
|
||||
}
|
||||
|
||||
fun setPrevGid(prevGid: Int) {
|
||||
mPrevGid = prevGid
|
||||
}
|
||||
|
||||
fun setNextGid(nextGid: Int) {
|
||||
mNextGid = nextGid
|
||||
fun setIndex(index: String?, isNext: Boolean = true) {
|
||||
mNext = index?.takeIf { isNext }
|
||||
mPrev = index?.takeUnless { isNext }
|
||||
}
|
||||
|
||||
fun setJumpTo(jumpTo: String?) {
|
||||
@@ -114,29 +83,6 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
||||
mKeyword = keyword
|
||||
}
|
||||
|
||||
/**
|
||||
* Make them the same
|
||||
*
|
||||
* @param lub The template
|
||||
*/
|
||||
fun set(lub: ListUrlBuilder) {
|
||||
mode = lub.mode
|
||||
mPrevGid = lub.mPrevGid
|
||||
mNextGid = lub.mNextGid
|
||||
mJumpTo = lub.mJumpTo
|
||||
this.category = lub.category
|
||||
mKeyword = lub.mKeyword
|
||||
advanceSearch = lub.advanceSearch
|
||||
minRating = lub.minRating
|
||||
pageFrom = lub.pageFrom
|
||||
pageTo = lub.pageTo
|
||||
imagePath = lub.imagePath
|
||||
isUseSimilarityScan = lub.isUseSimilarityScan
|
||||
isOnlySearchCovers = lub.isOnlySearchCovers
|
||||
isShowExpunged = lub.isShowExpunged
|
||||
mSHash = lub.mSHash
|
||||
}
|
||||
|
||||
fun set(q: QuickSearch) {
|
||||
mode = q.mode
|
||||
this.category = q.category
|
||||
@@ -196,7 +142,7 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
||||
if (TextUtils.isEmpty(query)) {
|
||||
return
|
||||
}
|
||||
val querys = StringUtils.split(query, '&')
|
||||
val queries = StringUtils.split(query, '&')
|
||||
var category = 0
|
||||
var keyword: String? = null
|
||||
var enableAdvanceSearch = false
|
||||
@@ -206,7 +152,7 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
||||
var enablePage = false
|
||||
var pageFrom = -1
|
||||
var pageTo = -1
|
||||
for (str in querys) {
|
||||
for (str in queries) {
|
||||
val index = str.indexOf('=')
|
||||
if (index < 0) {
|
||||
continue
|
||||
@@ -338,29 +284,23 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
||||
ub.addQuery("f_cats", category.inv() and EhConfig.ALL_CATEGORY)
|
||||
}
|
||||
// Search key
|
||||
if (mKeyword != null) {
|
||||
val keyword = mKeyword!!.trim { it <= ' ' }
|
||||
mKeyword?.run {
|
||||
val keyword = trim { it <= ' ' }
|
||||
if (keyword.isNotEmpty()) {
|
||||
try {
|
||||
ub.addQuery("f_search", URLEncoder.encode(mKeyword, "UTF-8"))
|
||||
} catch (e: UnsupportedEncodingException) {
|
||||
// Empty
|
||||
}
|
||||
ub.addQuery("f_search", encodeUTF8(this))
|
||||
}
|
||||
}
|
||||
if (mSHash != null) {
|
||||
ub.addQuery("f_shash", mSHash!!)
|
||||
mSHash?.let {
|
||||
ub.addQuery("f_shash", it)
|
||||
}
|
||||
mJumpTo?.let {
|
||||
ub.addQuery("seek", mJumpTo!!)
|
||||
mPrevGid = 0
|
||||
mNextGid = 0
|
||||
ub.addQuery("seek", it)
|
||||
}
|
||||
if (mPrevGid != 0) {
|
||||
ub.addQuery("prev", mPrevGid)
|
||||
mPrev?.let {
|
||||
ub.addQuery("prev", it)
|
||||
}
|
||||
if (mNextGid != 0) {
|
||||
ub.addQuery("next", mNextGid)
|
||||
mNext?.let {
|
||||
ub.addQuery("next", it)
|
||||
}
|
||||
// Advance search
|
||||
if (advanceSearch != -1) {
|
||||
@@ -387,40 +327,36 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
||||
|
||||
MODE_UPLOADER -> {
|
||||
val sb = StringBuilder(EhUrl.getHost())
|
||||
sb.append("uploader/")
|
||||
try {
|
||||
sb.append(URLEncoder.encode(mKeyword, "UTF-8"))
|
||||
} catch (e: UnsupportedEncodingException) {
|
||||
// Empty
|
||||
mKeyword?.let {
|
||||
sb.append("uploader/")
|
||||
sb.append(encodeUTF8(it))
|
||||
}
|
||||
if (mPrevGid != 0) {
|
||||
sb.append("?prev=").append(mPrevGid)
|
||||
mPrev?.let {
|
||||
sb.append("?prev=").append(it)
|
||||
}
|
||||
if (mNextGid != 0) {
|
||||
sb.append("?next=").append(mNextGid)
|
||||
mNext?.let {
|
||||
sb.append("?next=").append(it)
|
||||
}
|
||||
if (mJumpTo != null) {
|
||||
sb.append("&seek=").append(mJumpTo)
|
||||
mJumpTo?.let {
|
||||
sb.append("&seek=").append(it)
|
||||
}
|
||||
sb.toString()
|
||||
}
|
||||
|
||||
MODE_TAG -> {
|
||||
val sb = StringBuilder(EhUrl.getHost())
|
||||
sb.append("tag/")
|
||||
try {
|
||||
sb.append(URLEncoder.encode(mKeyword, "UTF-8"))
|
||||
} catch (e: UnsupportedEncodingException) {
|
||||
// Empty
|
||||
mKeyword?.let {
|
||||
sb.append("tag/")
|
||||
sb.append(encodeUTF8(it))
|
||||
}
|
||||
if (mPrevGid != 0) {
|
||||
sb.append("?prev=").append(mPrevGid)
|
||||
mPrev?.let {
|
||||
sb.append("?prev=").append(it)
|
||||
}
|
||||
if (mNextGid != 0) {
|
||||
sb.append("?next=").append(mNextGid)
|
||||
mNext?.let {
|
||||
sb.append("?next=").append(it)
|
||||
}
|
||||
if (mJumpTo != null) {
|
||||
sb.append("&seek=").append(mJumpTo)
|
||||
mJumpTo?.let {
|
||||
sb.append("&seek=").append(it)
|
||||
}
|
||||
sb.toString()
|
||||
}
|
||||
@@ -430,89 +366,19 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
||||
MODE_TOPLIST -> {
|
||||
val sb = StringBuilder(EhUrl.HOST_E)
|
||||
sb.append("toplist.php?tl=")
|
||||
try {
|
||||
sb.append(URLEncoder.encode(mKeyword, "UTF-8"))
|
||||
} catch (e: UnsupportedEncodingException) {
|
||||
// Empty
|
||||
mKeyword.orEmpty().let {
|
||||
sb.append(encodeUTF8(it))
|
||||
}
|
||||
if (mNextGid != 0) {
|
||||
sb.append("&p=").append(mNextGid)
|
||||
mJumpTo?.let {
|
||||
sb.append("&p=").append(it)
|
||||
}
|
||||
sb.toString()
|
||||
}
|
||||
|
||||
else -> {
|
||||
val url: String = if (mode == MODE_NORMAL) {
|
||||
EhUrl.getHost()
|
||||
} else {
|
||||
EhUrl.getWatchedUrl()
|
||||
}
|
||||
val ub = UrlBuilder(url)
|
||||
if (this.category != EhUtils.NONE) {
|
||||
ub.addQuery("f_cats", category.inv() and EhConfig.ALL_CATEGORY)
|
||||
}
|
||||
if (mKeyword != null) {
|
||||
val keyword = mKeyword!!.trim { it <= ' ' }
|
||||
if (keyword.isNotEmpty()) {
|
||||
try {
|
||||
ub.addQuery("f_search", URLEncoder.encode(mKeyword, "UTF-8"))
|
||||
} catch (_: UnsupportedEncodingException) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mSHash != null) {
|
||||
ub.addQuery("f_shash", mSHash!!)
|
||||
}
|
||||
if (mPrevGid != 0) {
|
||||
ub.addQuery("prev", mPrevGid)
|
||||
}
|
||||
if (mNextGid != 0) {
|
||||
ub.addQuery("next", mNextGid)
|
||||
}
|
||||
if (advanceSearch != -1) {
|
||||
ub.addQuery("advsearch", "1")
|
||||
if (advanceSearch and AdvanceSearchTable.SH != 0) ub.addQuery("f_sh", "on")
|
||||
if (advanceSearch and AdvanceSearchTable.STO != 0) ub.addQuery("f_sto", "on")
|
||||
if (advanceSearch and AdvanceSearchTable.SFL != 0) ub.addQuery("f_sfl", "on")
|
||||
if (advanceSearch and AdvanceSearchTable.SFU != 0) ub.addQuery("f_sfu", "on")
|
||||
if (advanceSearch and AdvanceSearchTable.SFT != 0) ub.addQuery("f_sft", "on")
|
||||
if (minRating != -1) {
|
||||
ub.addQuery("f_sr", "on")
|
||||
ub.addQuery("f_srdd", minRating)
|
||||
}
|
||||
if (pageFrom != -1 || pageTo != -1) {
|
||||
ub.addQuery("f_sp", "on")
|
||||
ub.addQuery("f_spf", if (pageFrom != -1) pageFrom.toString() else "")
|
||||
ub.addQuery("f_spt", if (pageTo != -1) pageTo.toString() else "")
|
||||
}
|
||||
}
|
||||
ub.build()
|
||||
}
|
||||
else -> throw IllegalStateException("Unexpected value: $mode")
|
||||
}
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
||||
dest.writeInt(mode)
|
||||
dest.writeInt(mPrevGid)
|
||||
dest.writeInt(mNextGid)
|
||||
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(
|
||||
MODE_NORMAL,
|
||||
MODE_UPLOADER,
|
||||
@@ -532,16 +398,5 @@ open class ListUrlBuilder : Cloneable, Parcelable {
|
||||
const val MODE_IMAGE_SEARCH = 0x4
|
||||
const val MODE_SUBSCRIPTION = 0x5
|
||||
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
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.hippo.ehviewer.client.exception
|
||||
|
||||
package com.hippo.ehviewer.client.exception;
|
||||
|
||||
public class NoHAtHClientException extends EhException {
|
||||
|
||||
public NoHAtHClientException(String detailMessage) {
|
||||
super(detailMessage);
|
||||
}
|
||||
|
||||
}
|
||||
open class EhException : Exception {
|
||||
constructor(detailMessage: String?) : super(detailMessage)
|
||||
constructor(detailMessage: String?, cause: Throwable?) : super(detailMessage, cause)
|
||||
}
|
||||
+2
-8
@@ -13,12 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.hippo.ehviewer.client.exception
|
||||
|
||||
package com.hippo.ehviewer.client.exception;
|
||||
|
||||
public class Image509Exception extends EhException {
|
||||
|
||||
public Image509Exception() {
|
||||
super("509");
|
||||
}
|
||||
}
|
||||
class Image509Exception : EhException("509")
|
||||
+2
-8
@@ -13,12 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.hippo.ehviewer.client.exception
|
||||
|
||||
package com.hippo.ehviewer.client.exception;
|
||||
|
||||
public class CancelledException extends Exception {
|
||||
|
||||
public CancelledException() {
|
||||
super("CANCELED");
|
||||
}
|
||||
}
|
||||
class NoHAtHClientException(detailMessage: String?) : EhException(detailMessage)
|
||||
+2
-8
@@ -13,15 +13,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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
|
||||
*/
|
||||
public class OffensiveException extends EhException {
|
||||
|
||||
public OffensiveException() {
|
||||
super("OFFENSIVE");
|
||||
}
|
||||
}
|
||||
class OffensiveException : EhException("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
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.hippo.ehviewer.client.exception
|
||||
|
||||
package com.hippo.ehviewer.client.exception;
|
||||
|
||||
public class PiningException extends EhException {
|
||||
|
||||
public PiningException() {
|
||||
super("pining for the fjords");
|
||||
}
|
||||
}
|
||||
class PiningException : EhException("pining for the fjords")
|
||||
@@ -16,33 +16,193 @@
|
||||
|
||||
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.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
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 = Pattern.compile("<a href=\"[^\"]*\" onclick=\"return do_hathdl\\('([0-9]+|org)'\\)\">([^<]+)</a>");
|
||||
private static final Pattern PATTERN_ARCHIVE_URL = Pattern.compile("<strong>(.*)</strong>.*<a href=\"([^\"]*)\">Click Here To Start Downloading</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 Pair<String, Pair<String, String>[]> parse(String body) {
|
||||
Matcher m = PATTERN_FORM.matcher(body);
|
||||
public static Result parse(String body) {
|
||||
Matcher m = PATTERN_HATH_FORM.matcher(body);
|
||||
if (!m.find()) {
|
||||
return new Pair<String, Pair<String, String>[]>("", new Pair[0]);
|
||||
return new Result(null, null);
|
||||
}
|
||||
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()) {
|
||||
String res = ParserUtils.trim(m.group(1));
|
||||
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);
|
||||
}
|
||||
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 + ']';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -31,22 +31,17 @@ import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class FavoritesParser {
|
||||
private static final Pattern PATTERN_PREV_PAGE = Pattern.compile("prev=(\\d+(-\\d+)?)");
|
||||
private static final Pattern PATTERN_NEXT_PAGE = Pattern.compile("next=(\\d+(-\\d+)?)");
|
||||
|
||||
public static Result parse(String body) throws Exception {
|
||||
if (body.contains("This page requires you to log on.</p>")) {
|
||||
throw new EhException(GetText.getString(R.string.need_sign_in));
|
||||
}
|
||||
Document d = Jsoup.parse(body);
|
||||
|
||||
String[] catArray = new String[10];
|
||||
int[] countArray = new int[10];
|
||||
try {
|
||||
Document d = Jsoup.parse(body);
|
||||
Element ido = JsoupUtils.getElementByClass(d, "ido");
|
||||
//noinspection ConstantConditions
|
||||
Elements fps = ido.getElementsByClass("fp");
|
||||
@@ -64,24 +59,13 @@ public class FavoritesParser {
|
||||
throw new ParseException("Parse favorites error", body);
|
||||
}
|
||||
|
||||
Result re = new Result();
|
||||
try {
|
||||
Element prev = d.getElementById("uprev");
|
||||
Element next = d.getElementById("unext");
|
||||
assert prev != null;
|
||||
assert next != null;
|
||||
Matcher matcherPrev = PATTERN_PREV_PAGE.matcher(prev.attr("href"));
|
||||
Matcher matcherNext = PATTERN_NEXT_PAGE.matcher(next.attr("href"));
|
||||
if (matcherPrev.find()) re.prevPage = matcherPrev.group(1);
|
||||
if (matcherNext.find()) re.nextPage = matcherNext.group(1);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
GalleryListParser.Result result = GalleryListParser.parse(body);
|
||||
|
||||
Result re = new Result();
|
||||
re.catArray = catArray;
|
||||
re.countArray = countArray;
|
||||
re.prev = result.prev;
|
||||
re.next = result.next;
|
||||
re.galleryInfoList = result.galleryInfoList;
|
||||
|
||||
return re;
|
||||
@@ -90,8 +74,8 @@ public class FavoritesParser {
|
||||
public static class Result {
|
||||
public String[] catArray; // Size 10
|
||||
public int[] countArray; // Size 10
|
||||
public String prevPage;
|
||||
public String nextPage;
|
||||
public String prev;
|
||||
public String next;
|
||||
public List<GalleryInfo> galleryInfoList;
|
||||
}
|
||||
}
|
||||
@@ -39,13 +39,13 @@ public class GalleryApiParser {
|
||||
if (gi == null) {
|
||||
continue;
|
||||
}
|
||||
gi.title = ParserUtils.trim(g.getString("title"));
|
||||
gi.titleJpn = ParserUtils.trim(g.getString("title_jpn"));
|
||||
gi.category = EhUtils.getCategory(g.getString("category"));
|
||||
gi.thumb = EhUtils.handleThumbUrlResolution(g.getString("thumb"));
|
||||
gi.uploader = g.getString("uploader");
|
||||
gi.posted = ParserUtils.formatDate(ParserUtils.parseLong(g.getString("posted"), 0) * 1000);
|
||||
gi.rating = NumberUtils.parseFloatSafely(g.getString("rating"), 0.0f);
|
||||
gi.setTitle(ParserUtils.trim(g.getString("title")));
|
||||
gi.setTitleJpn(ParserUtils.trim(g.getString("title_jpn")));
|
||||
gi.setCategory(EhUtils.getCategory(g.getString("category")));
|
||||
gi.setThumb(EhUtils.handleThumbUrlResolution(g.getString("thumb")));
|
||||
gi.setUploader(g.getString("uploader"));
|
||||
gi.setPosted(ParserUtils.formatDate(ParserUtils.parseLong(g.getString("posted"), 0) * 1000));
|
||||
gi.setRating(NumberUtils.parseFloatSafely(g.getString("rating"), 0.0f));
|
||||
// tags
|
||||
JSONArray tagJa = g.getJSONArray("tags");
|
||||
int tagLength = tagJa.length();
|
||||
@@ -53,8 +53,8 @@ public class GalleryApiParser {
|
||||
for (int j = 0; j < tagLength; j++) {
|
||||
tags[j] = tagJa.getString(j);
|
||||
}
|
||||
gi.simpleTags = tags;
|
||||
gi.pages = NumberUtils.parseIntSafely(g.getString("filecount"), 0);
|
||||
gi.setSimpleTags(tags);
|
||||
gi.setPages(NumberUtils.parseIntSafely(g.getString("filecount"), 0));
|
||||
gi.generateSLang();
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ public class GalleryApiParser {
|
||||
private static GalleryInfo getGalleryInfoByGid(List<GalleryInfo> galleryInfoList, long gid) {
|
||||
for (int i = 0, size = galleryInfoList.size(); i < size; i++) {
|
||||
GalleryInfo gi = galleryInfoList.get(i);
|
||||
if (gi.gid == gid) {
|
||||
if (gi.getGid() == gid) {
|
||||
return gi;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,13 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.hippo.ehviewer.EhDB;
|
||||
import com.hippo.ehviewer.client.EhFilter;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.ehviewer.client.data.GalleryComment;
|
||||
import com.hippo.ehviewer.client.data.GalleryCommentList;
|
||||
import com.hippo.ehviewer.client.data.GalleryDetail;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo;
|
||||
import com.hippo.ehviewer.client.data.GalleryTagGroup;
|
||||
import com.hippo.ehviewer.client.data.LargePreviewSet;
|
||||
import com.hippo.ehviewer.client.data.NormalPreviewSet;
|
||||
@@ -123,7 +125,7 @@ public class GalleryDetailParser {
|
||||
// Generate simpleLanguage for local favorites
|
||||
for (int i = 0; i < LANGUAGES.length; i++) {
|
||||
if (galleryDetail.language.equals(LANGUAGES[i])) {
|
||||
galleryDetail.simpleLanguage = GalleryInfo.S_LANGS[i];
|
||||
galleryDetail.setSimpleLanguage(GalleryInfo.Companion.getS_LANGS()[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -135,14 +137,14 @@ public class GalleryDetailParser {
|
||||
private static void parseDetail(GalleryDetail gd, Document d, String body) throws ParseException {
|
||||
Matcher matcher = PATTERN_DETAIL.matcher(body);
|
||||
if (matcher.find()) {
|
||||
gd.gid = NumberUtils.parseLongSafely(matcher.group(1), -1L);
|
||||
gd.token = matcher.group(2);
|
||||
gd.setGid(NumberUtils.parseLongSafely(matcher.group(1), -1L));
|
||||
gd.setToken(matcher.group(2));
|
||||
gd.apiUid = NumberUtils.parseLongSafely(matcher.group(3), -1L);
|
||||
gd.apiKey = matcher.group(4);
|
||||
} else {
|
||||
throw new ParseException("Can't parse gallery detail", body);
|
||||
}
|
||||
if (gd.gid == -1L) {
|
||||
if (gd.getGid() == -1L) {
|
||||
throw new ParseException("Can't parse gallery detail", body);
|
||||
}
|
||||
|
||||
@@ -168,26 +170,26 @@ public class GalleryDetailParser {
|
||||
// Thumb url
|
||||
Element gd1 = gm.getElementById("gd1");
|
||||
try {
|
||||
gd.thumb = parseCoverStyle(StringUtils.trim(gd1.child(0).attr("style")));
|
||||
gd.setThumb(parseCoverStyle(StringUtils.trim(gd1.child(0).attr("style"))));
|
||||
} catch (Throwable e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
gd.thumb = "";
|
||||
gd.setThumb("");
|
||||
}
|
||||
|
||||
// Title
|
||||
Element gn = gm.getElementById("gn");
|
||||
if (null != gn) {
|
||||
gd.title = StringUtils.trim(gn.text());
|
||||
gd.setTitle(StringUtils.trim(gn.text()));
|
||||
} else {
|
||||
gd.title = "";
|
||||
gd.setTitle("");
|
||||
}
|
||||
|
||||
// Jpn title
|
||||
Element gj = gm.getElementById("gj");
|
||||
if (null != gj) {
|
||||
gd.titleJpn = StringUtils.trim(gj.text());
|
||||
gd.setTitleJpn(StringUtils.trim(gj.text()));
|
||||
} else {
|
||||
gd.titleJpn = "";
|
||||
gd.setTitleJpn("");
|
||||
}
|
||||
|
||||
// Category
|
||||
@@ -197,27 +199,27 @@ public class GalleryDetailParser {
|
||||
if (ce == null) {
|
||||
ce = JsoupUtils.getElementByClass(gdc, "cs");
|
||||
}
|
||||
gd.category = EhUtils.getCategory(ce.text());
|
||||
gd.setCategory(EhUtils.getCategory(ce.text()));
|
||||
} catch (Throwable e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
gd.category = EhUtils.UNKNOWN;
|
||||
gd.setCategory(EhUtils.UNKNOWN);
|
||||
}
|
||||
|
||||
// Uploader
|
||||
Element gdn = gm.getElementById("gdn");
|
||||
if (null != gdn) {
|
||||
gd.disowned = gdn.attr("style").contains("opacity:0.5");
|
||||
gd.uploader = StringUtils.trim(gdn.text());
|
||||
gd.setDisowned(gdn.attr("style").contains("opacity:0.5"));
|
||||
gd.setUploader(StringUtils.trim(gdn.text()));
|
||||
} else {
|
||||
gd.uploader = "";
|
||||
gd.setUploader("");
|
||||
}
|
||||
|
||||
Element gdd = gm.getElementById("gdd");
|
||||
gd.posted = "";
|
||||
gd.setPosted("");
|
||||
gd.parent = "";
|
||||
gd.visible = "";
|
||||
gd.size = "";
|
||||
gd.pages = 0;
|
||||
gd.setPages(0);
|
||||
gd.favoriteCount = 0;
|
||||
Elements es = gdd.child(0).child(0).children();
|
||||
for (int i = 0, n = es.size(); i < n; i++) {
|
||||
@@ -238,17 +240,17 @@ public class GalleryDetailParser {
|
||||
if (null != rating_label) {
|
||||
String ratingStr = StringUtils.trim(rating_label.text());
|
||||
if ("Not Yet Rated".equals(ratingStr)) {
|
||||
gd.rating = -1.0f;
|
||||
gd.setRating(-1.0f);
|
||||
} else {
|
||||
int index = ratingStr.indexOf(' ');
|
||||
if (index == -1 || index >= ratingStr.length()) {
|
||||
gd.rating = 0f;
|
||||
gd.setRating(0f);
|
||||
} else {
|
||||
gd.rating = NumberUtils.parseFloatSafely(ratingStr.substring(index + 1), 0f);
|
||||
gd.setRating(NumberUtils.parseFloatSafely(ratingStr.substring(index + 1), 0f));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gd.rating = -1.0f;
|
||||
gd.setRating(-1.0f);
|
||||
}
|
||||
|
||||
// isFavorited
|
||||
@@ -257,19 +259,19 @@ public class GalleryDetailParser {
|
||||
if (gdf != null) {
|
||||
final String favoriteName = StringUtils.trim(gdf.text());
|
||||
if (favoriteName.equals("Add to Favorites")) {
|
||||
gd.favoriteName = null;
|
||||
gd.setFavoriteName(null);
|
||||
} else {
|
||||
gd.isFavorited = true;
|
||||
gd.favoriteName = StringUtils.trim(gdf.text());
|
||||
gd.setFavoriteName(StringUtils.trim(gdf.text()));
|
||||
|
||||
matcher = PATTERN_FAVORITE_SLOT.matcher(body);
|
||||
if (matcher.find()) {
|
||||
gd.favoriteSlot = (NumberUtils.parseIntSafely(matcher.group(1), 2) - 2) / 19;
|
||||
gd.setFavoriteSlot((NumberUtils.parseIntSafely(matcher.group(1), 2) - 2) / 19);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gd.favoriteSlot == -2 && EhDB.containLocalFavorites(gd.gid)) {
|
||||
gd.favoriteSlot = -1;
|
||||
if (gd.getFavoriteSlot() == -2 && EhDB.containLocalFavorites(gd.getGid())) {
|
||||
gd.setFavoriteSlot(-1);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
@@ -288,13 +290,13 @@ public class GalleryDetailParser {
|
||||
Elements elements = gnd.select("a");
|
||||
for (int i = 0; i < elements.size(); i++) {
|
||||
Element element = elements.get(i);
|
||||
GalleryInfo gi = new GalleryInfo();
|
||||
GalleryInfo gi = new BaseGalleryInfo();
|
||||
GalleryDetailUrlParser.Result result = GalleryDetailUrlParser.parse(element.attr("href"));
|
||||
if (result != null) {
|
||||
gi.gid = result.gid;
|
||||
gi.token = result.token;
|
||||
gi.title = StringUtils.trim(element.text());
|
||||
gi.posted = dates.get(i);
|
||||
gi.setGid(result.gid);
|
||||
gi.setToken(result.token);
|
||||
gi.setTitle(StringUtils.trim(element.text()));
|
||||
gi.setPosted(dates.get(i));
|
||||
gd.newerVersions.add(gi);
|
||||
}
|
||||
}
|
||||
@@ -323,7 +325,7 @@ public class GalleryDetailParser {
|
||||
String key = StringUtils.trim(es.get(0).text());
|
||||
String value = StringUtils.trim(es.get(1).ownText());
|
||||
if (key.startsWith("Posted")) {
|
||||
gd.posted = value;
|
||||
gd.setPosted(value);
|
||||
} else if (key.startsWith("Parent")) {
|
||||
Element a = es.get(1).children().first();
|
||||
if (a != null) {
|
||||
@@ -338,9 +340,9 @@ public class GalleryDetailParser {
|
||||
} else if (key.startsWith("Length")) {
|
||||
int index = value.indexOf(' ');
|
||||
if (index >= 0) {
|
||||
gd.pages = NumberUtils.parseIntSafely(value.substring(0, index), 1);
|
||||
gd.setPages(NumberUtils.parseIntSafely(value.substring(0, index), 1));
|
||||
} else {
|
||||
gd.pages = 1;
|
||||
gd.setPages(1);
|
||||
}
|
||||
} else if (key.startsWith("Favorited")) {
|
||||
switch (value) {
|
||||
@@ -473,6 +475,13 @@ public class GalleryDetailParser {
|
||||
comment.user = c3.child(0).text();
|
||||
// comment
|
||||
comment.comment = JsoupUtils.getElementByClass(element, "c6").html();
|
||||
// filter comment
|
||||
if (!comment.uploader) {
|
||||
EhFilter sEhFilter = EhFilter.getInstance();
|
||||
if (!sEhFilter.filterCommenter(comment.user) || !sEhFilter.filterComment(comment.comment)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// last edited
|
||||
Element c8 = JsoupUtils.getElementByClass(element, "c8");
|
||||
if (c8 != null) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import androidx.annotation.NonNull;
|
||||
import com.hippo.ehviewer.EhDB;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo;
|
||||
import com.hippo.ehviewer.client.exception.ParseException;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.util.JsoupUtils;
|
||||
@@ -50,8 +51,9 @@ public class GalleryListParser {
|
||||
private static final Pattern PATTERN_THUMB_SIZE = Pattern.compile("height:(\\d+)px;width:(\\d+)px");
|
||||
private static final Pattern PATTERN_FAVORITE_SLOT = Pattern.compile("background-color:rgba\\((\\d+),(\\d+),(\\d+),");
|
||||
private static final Pattern PATTERN_PAGES = Pattern.compile("(\\d+) page");
|
||||
private static final Pattern PATTERN_PREV_PAGE = Pattern.compile("prev=(\\d+)");
|
||||
private static final Pattern PATTERN_NEXT_PAGE = Pattern.compile("next=(\\d+)");
|
||||
private static final Pattern PATTERN_NEXT_PAGE = Pattern.compile("p=(\\d+)");
|
||||
private static final Pattern PATTERN_PREV = Pattern.compile("prev=(\\d+(-\\d+)?)");
|
||||
private static final Pattern PATTERN_NEXT = Pattern.compile("next=(\\d+(-\\d+)?)");
|
||||
|
||||
private static final String[][] FAVORITE_SLOT_RGB = new String[][]{
|
||||
new String[]{"0", "0", "0"},
|
||||
@@ -109,7 +111,7 @@ public class GalleryListParser {
|
||||
}
|
||||
|
||||
private static GalleryInfo parseGalleryInfo(Element e) {
|
||||
GalleryInfo gi = new GalleryInfo();
|
||||
GalleryInfo gi = new BaseGalleryInfo();
|
||||
|
||||
// Title, gid, token (required), tags
|
||||
Element glname = JsoupUtils.getElementByClass(e, "glname");
|
||||
@@ -124,8 +126,8 @@ public class GalleryListParser {
|
||||
if (a != null) {
|
||||
GalleryDetailUrlParser.Result result = GalleryDetailUrlParser.parse(a.attr("href"));
|
||||
if (result != null) {
|
||||
gi.gid = result.gid;
|
||||
gi.token = result.token;
|
||||
gi.setGid(result.gid);
|
||||
gi.setToken(result.token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,9 +137,9 @@ public class GalleryListParser {
|
||||
child = children.get(0);
|
||||
children = child.children();
|
||||
}
|
||||
gi.title = child.text().trim();
|
||||
gi.setTitle(child.text().trim());
|
||||
}
|
||||
if (gi.title == null) {
|
||||
if (gi.getTitle() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -148,17 +150,17 @@ public class GalleryListParser {
|
||||
for (Element gt : gts) {
|
||||
tags.add(gt.attr("title"));
|
||||
}
|
||||
gi.simpleTags = tags.toArray(new String[0]);
|
||||
gi.setSimpleTags(tags.toArray(new String[0]));
|
||||
}
|
||||
|
||||
// Category
|
||||
gi.category = EhUtils.UNKNOWN;
|
||||
gi.setCategory(EhUtils.UNKNOWN);
|
||||
Element ce = JsoupUtils.getElementByClass(e, "cn");
|
||||
if (ce == null) {
|
||||
ce = JsoupUtils.getElementByClass(e, "cs");
|
||||
}
|
||||
if (ce != null) {
|
||||
gi.category = EhUtils.getCategory(ce.text());
|
||||
gi.setCategory(EhUtils.getCategory(ce.text()));
|
||||
}
|
||||
|
||||
// Thumb
|
||||
@@ -169,12 +171,12 @@ public class GalleryListParser {
|
||||
// Thumb size
|
||||
Matcher m = PATTERN_THUMB_SIZE.matcher(img.attr("style"));
|
||||
if (m.find()) {
|
||||
gi.thumbWidth = NumberUtils.parseIntSafely(m.group(2), 0);
|
||||
gi.thumbHeight = NumberUtils.parseIntSafely(m.group(1), 0);
|
||||
gi.setThumbWidth(NumberUtils.parseIntSafely(m.group(2), 0));
|
||||
gi.setThumbHeight(NumberUtils.parseIntSafely(m.group(1), 0));
|
||||
} else {
|
||||
Log.w(TAG, "Can't parse gallery info thumb size");
|
||||
gi.thumbWidth = 0;
|
||||
gi.thumbHeight = 0;
|
||||
gi.setThumbWidth(0);
|
||||
gi.setThumbHeight(0);
|
||||
}
|
||||
// Thumb url
|
||||
String url = img.attr("data-src");
|
||||
@@ -184,7 +186,7 @@ public class GalleryListParser {
|
||||
if (TextUtils.isEmpty(url)) {
|
||||
url = null;
|
||||
}
|
||||
gi.thumb = EhUtils.handleThumbUrlResolution(url);
|
||||
gi.setThumb(EhUtils.handleThumbUrlResolution(url));
|
||||
}
|
||||
|
||||
// Pages
|
||||
@@ -192,12 +194,12 @@ public class GalleryListParser {
|
||||
if (div != null) {
|
||||
Matcher matcher = PATTERN_PAGES.matcher(div.text());
|
||||
if (matcher.find()) {
|
||||
gi.pages = NumberUtils.parseIntSafely(matcher.group(1), 0);
|
||||
gi.setPages(NumberUtils.parseIntSafely(matcher.group(1), 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Try extended and thumbnail version
|
||||
if (gi.thumb == null) {
|
||||
if (gi.getThumb() == null) {
|
||||
Element gl = JsoupUtils.getElementByClass(e, "gl1e");
|
||||
if (gl == null) {
|
||||
gl = JsoupUtils.getElementByClass(e, "gl3t");
|
||||
@@ -208,35 +210,35 @@ public class GalleryListParser {
|
||||
// Thumb size
|
||||
Matcher m = PATTERN_THUMB_SIZE.matcher(img.attr("style"));
|
||||
if (m.find()) {
|
||||
gi.thumbWidth = NumberUtils.parseIntSafely(m.group(2), 0);
|
||||
gi.thumbHeight = NumberUtils.parseIntSafely(m.group(1), 0);
|
||||
gi.setThumbWidth(NumberUtils.parseIntSafely(m.group(2), 0));
|
||||
gi.setThumbHeight(NumberUtils.parseIntSafely(m.group(1), 0));
|
||||
} else {
|
||||
Log.w(TAG, "Can't parse gallery info thumb size");
|
||||
gi.thumbWidth = 0;
|
||||
gi.thumbHeight = 0;
|
||||
gi.setThumbWidth(0);
|
||||
gi.setThumbHeight(0);
|
||||
}
|
||||
gi.thumb = EhUtils.handleThumbUrlResolution(img.attr("src"));
|
||||
gi.setThumb(EhUtils.handleThumbUrlResolution(img.attr("src")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Posted
|
||||
gi.favoriteSlot = -2;
|
||||
Element posted = e.getElementById("posted_" + gi.gid);
|
||||
gi.setFavoriteSlot(-2);
|
||||
Element posted = e.getElementById("posted_" + gi.getGid());
|
||||
if (posted != null) {
|
||||
gi.posted = posted.text().trim();
|
||||
gi.favoriteSlot = parseFavoriteSlot(posted.attr("style"));
|
||||
gi.setPosted(posted.text().trim());
|
||||
gi.setFavoriteSlot(parseFavoriteSlot(posted.attr("style")));
|
||||
}
|
||||
if (gi.favoriteSlot == -2) {
|
||||
gi.favoriteSlot = EhDB.containLocalFavorites(gi.gid) ? -1 : -2;
|
||||
if (gi.getFavoriteSlot() == -2) {
|
||||
gi.setFavoriteSlot(EhDB.containLocalFavorites(gi.getGid()) ? -1 : -2);
|
||||
}
|
||||
|
||||
// Rating
|
||||
Element ir = JsoupUtils.getElementByClass(e, "ir");
|
||||
if (ir != null) {
|
||||
gi.rating = NumberUtils.parseFloatSafely(parseRating(ir.attr("style")), -1.0f);
|
||||
gi.setRating(NumberUtils.parseFloatSafely(parseRating(ir.attr("style")), -1.0f));
|
||||
// TODO The gallery may be rated even if it doesn't has one of these classes
|
||||
gi.rated = ir.hasClass("irr") || ir.hasClass("irg") || ir.hasClass("irb");
|
||||
gi.setRated(ir.hasClass("irr") || ir.hasClass("irg") || ir.hasClass("irb"));
|
||||
}
|
||||
|
||||
// Uploader and pages
|
||||
@@ -254,19 +256,15 @@ public class GalleryListParser {
|
||||
if (children.size() > uploaderIndex) {
|
||||
Element div = children.get(uploaderIndex);
|
||||
if (div != null) {
|
||||
gi.disowned = div.attr("style").contains("opacity:0.5");
|
||||
gi.setDisowned(div.attr("style").contains("opacity:0.5"));
|
||||
Element a = div.children().first();
|
||||
if (a != null) {
|
||||
gi.uploader = a.text().trim();
|
||||
} else {
|
||||
gi.uploader = div.text().trim();
|
||||
}
|
||||
gi.setUploader(a == null ? div.text().trim() : a.text().trim());
|
||||
}
|
||||
}
|
||||
if (children.size() > pagesIndex) {
|
||||
Matcher matcher = PATTERN_PAGES.matcher(children.get(pagesIndex).text());
|
||||
if (matcher.find()) {
|
||||
gi.pages = NumberUtils.parseIntSafely(matcher.group(1), 0);
|
||||
gi.setPages(NumberUtils.parseIntSafely(matcher.group(1), 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -277,7 +275,7 @@ public class GalleryListParser {
|
||||
if (div != null) {
|
||||
Matcher matcher = PATTERN_PAGES.matcher(div.text());
|
||||
if (matcher.find()) {
|
||||
gi.pages = NumberUtils.parseIntSafely(matcher.group(1), 0);
|
||||
gi.setPages(NumberUtils.parseIntSafely(matcher.group(1), 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,28 +294,44 @@ public class GalleryListParser {
|
||||
Element next = d.getElementById("unext");
|
||||
assert prev != null;
|
||||
assert next != null;
|
||||
Matcher matcherPrev = PATTERN_PREV_PAGE.matcher(prev.attr("href"));
|
||||
Matcher matcherNext = PATTERN_NEXT_PAGE.matcher(next.attr("href"));
|
||||
Matcher matcherPrev = PATTERN_PREV.matcher(prev.attr("href"));
|
||||
Matcher matcherNext = PATTERN_NEXT.matcher(next.attr("href"));
|
||||
if (matcherPrev.find())
|
||||
result.prevGid = NumberUtils.parseIntSafely(matcherPrev.group(1), 0);
|
||||
result.prev = matcherPrev.group(1);
|
||||
if (matcherNext.find())
|
||||
result.nextGid = NumberUtils.parseIntSafely(matcherNext.group(1), 0);
|
||||
result.founds = Integer.MAX_VALUE;
|
||||
result.next = matcherNext.group(1);
|
||||
} catch (Throwable e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
result.noWatchedTags = body.contains("<p>You do not have any watched tags");
|
||||
if (body.contains("No hits found</p>")) {
|
||||
result.founds = 0;
|
||||
//noinspection unchecked
|
||||
result.galleryInfoList = Collections.EMPTY_LIST;
|
||||
return result;
|
||||
} else if (d.getElementsByClass("ptt").isEmpty()) {
|
||||
result.founds = 1;
|
||||
} else {
|
||||
result.founds = Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
try { // For toplists
|
||||
Element ptt = d.getElementsByClass("ptt").first();
|
||||
if (ptt != null) {
|
||||
Elements es = ptt.child(0).child(0).children();
|
||||
result.pages = Integer.parseInt(es.get(es.size() - 2).text().trim());
|
||||
|
||||
Element e = es.get(es.size() - 1);
|
||||
if (e != null) {
|
||||
e = e.children().first();
|
||||
if (e != null) {
|
||||
String href = e.attr("href");
|
||||
Matcher matcher = PATTERN_NEXT_PAGE.matcher(href);
|
||||
if (matcher.find()) {
|
||||
result.nextPage = NumberUtils.parseIntSafely(matcher.group(1), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
Element itg = d.getElementsByClass("itg").first();
|
||||
Elements es;
|
||||
@@ -350,9 +364,10 @@ public class GalleryListParser {
|
||||
}
|
||||
|
||||
public static class Result {
|
||||
public int founds;
|
||||
public int prevGid;
|
||||
public int nextGid;
|
||||
public int pages;
|
||||
public int nextPage;
|
||||
public String prev;
|
||||
public String next;
|
||||
public boolean noWatchedTags;
|
||||
public List<GalleryInfo> galleryInfoList;
|
||||
}
|
||||
|
||||
@@ -16,27 +16,132 @@
|
||||
|
||||
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.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
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 Pair<String, String>[] parse(String body) {
|
||||
List<Pair<String, String>> torrentList = new ArrayList<>();
|
||||
Matcher m = PATTERN_TORRENT.matcher(body);
|
||||
while (m.find()) {
|
||||
String url = ParserUtils.trim(m.group(1));
|
||||
String name = ParserUtils.trim(m.group(2));
|
||||
Pair<String, String> item = new Pair<>(url, name);
|
||||
torrentList.add(item);
|
||||
public static List<Result> parse(String body) {
|
||||
var torrentList = new ArrayList<Result>();
|
||||
var d = Jsoup.parse(body);
|
||||
var es = d.select("form>div>table");
|
||||
for (var e : es) {
|
||||
Matcher m = PATTERN_TORRENT.matcher(e.html());
|
||||
if (m.find()) {
|
||||
String posted = m.group(1);
|
||||
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.BaseGalleryInfo
|
||||
|
||||
@Entity(tableName = "BOOKMARKS")
|
||||
class BookmarkInfo : BaseGalleryInfo() {
|
||||
@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,69 @@
|
||||
package com.hippo.ehviewer.dao
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Ignore
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
|
||||
@Entity(tableName = "DOWNLOADS")
|
||||
class DownloadInfo() : BaseGalleryInfo() {
|
||||
@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,28 @@
|
||||
package com.hippo.ehviewer.dao
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
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
|
||||
}
|
||||
|
||||
fun buildMainDB(context: Context): EhDatabase {
|
||||
// TODO: Remove allowMainThreadQueries
|
||||
return Room.databaseBuilder(context, EhDatabase::class.java, "eh.db").allowMainThreadQueries()
|
||||
.build()
|
||||
}
|
||||
@@ -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,42 @@
|
||||
package com.hippo.ehviewer.dao
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
|
||||
@Entity(tableName = "HISTORY")
|
||||
class HistoryInfo() : BaseGalleryInfo() {
|
||||
@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,31 @@
|
||||
package com.hippo.ehviewer.dao
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
|
||||
@Entity(tableName = "LOCAL_FAVORITES")
|
||||
class LocalFavoriteInfo() : BaseGalleryInfo() {
|
||||
@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
|
||||
}
|
||||
}
|
||||
Loaded 100 of 262 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user