Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f699973b9 | ||
|
|
3f27c9139c | ||
|
|
9eee6fc4af | ||
|
|
a343dbe8f8 | ||
|
|
bc08a09621 | ||
|
|
586ad66bff | ||
|
|
1a426e1f5f | ||
|
|
e9a9f1070c | ||
|
|
7d3dd61bc4 | ||
|
|
f37894af88 | ||
|
|
14129545b8 | ||
|
|
f06346b6c7 | ||
|
|
13e3e8c534 | ||
|
|
4be282813c | ||
|
|
74e66a407d | ||
|
|
b19da4c82e | ||
|
|
2f49764e1b | ||
|
|
08dfb0f72d | ||
|
|
9251ed238c | ||
|
|
3b96328765 | ||
|
|
108928e524 | ||
|
|
b1191bbf9b | ||
|
|
3424260cfd | ||
|
|
e1fe56160e | ||
|
|
5838ea3e3f | ||
|
|
0906b17ed1 | ||
|
|
49b9cb72d3 | ||
|
|
01508cc3c1 | ||
|
|
79eba83812 | ||
|
|
a455dee24c | ||
|
|
f58b4959e4 | ||
|
|
a6b4182ecd | ||
|
|
9010591ffc | ||
|
|
e0dde2c982 | ||
|
|
6109d97bf7 | ||
|
|
95936e01ce | ||
|
|
beadc7b185 | ||
|
|
0bc2e45137 | ||
|
|
b8e649e995 | ||
|
|
bdcd21a535 | ||
|
|
1b779a8b77 | ||
|
|
6c59a341ee | ||
|
|
1a6e03c8f8 | ||
|
|
653c0a2ac6 | ||
|
|
e4189f367a | ||
|
|
48b7355ba4 | ||
|
|
d7d3a903ff | ||
|
|
bab3067273 | ||
|
|
fdd70a6908 | ||
|
|
3699a8fe30 | ||
|
|
32f98f8a15 | ||
|
|
c5366760a2 | ||
|
|
c98ec2a7a4 | ||
|
|
e4c729e51b | ||
|
|
f36726d8fb | ||
|
|
d2fc2ee136 | ||
|
|
6edc2164af | ||
|
|
e34dc30f1f | ||
|
|
c03081d3fa | ||
|
|
97287e4538 | ||
|
|
fc44507a34 | ||
|
|
2597004750 | ||
|
|
d1bd9c5fae | ||
|
|
54542f9246 | ||
|
|
377b23458f | ||
|
|
b7973cdb76 | ||
|
|
5f1a70886c | ||
|
|
5fbc8b0b66 | ||
|
|
780b2b6e1d | ||
|
|
039ad2032c | ||
|
|
a24222b693 | ||
|
|
6047d91d7e | ||
|
|
f0158f6946 | ||
|
|
00ecdc58e6 | ||
|
|
0a075a97af | ||
|
|
34ee70ca7d | ||
|
|
338751ef2b | ||
|
|
d4465ba864 | ||
|
|
9a8fdd4edb |
No files matched your search
@@ -1,8 +1,17 @@
|
||||
name: Bug 反馈 / Bug report
|
||||
description: 提交一个问题报告 / Create a bug report to help us improve
|
||||
description: 提交一个问题报告 / Create a bug report
|
||||
labels:
|
||||
- "bug"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
感谢您愿意为 Ehviewer-Overhauled 做出贡献!
|
||||
提交问题报告前,还请首先完成文末的自查步骤
|
||||
|
||||
Thanks for your contribution on Ehviewer-Overhauled Project!
|
||||
Please finish verify steps which list in the end first before create bug report
|
||||
|
||||
- type: textarea
|
||||
id: reproduce
|
||||
attributes:
|
||||
@@ -44,12 +53,25 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: more
|
||||
attributes:
|
||||
label: 备注 / Addition details
|
||||
description: |
|
||||
在此处写下其他您想说的内容
|
||||
Describe addition details here
|
||||
placeholder: |
|
||||
其他有用的信息与附件
|
||||
Additional details and attachments
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: EhViewer 版本号 / EhViewer version code
|
||||
description: 您可以在设置 - 关于处找到版本号 / You can get version code in Settings - About
|
||||
placeholder: 四位版本号 / 4 digits version code
|
||||
placeholder: 1.6.9.13
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -119,4 +141,4 @@ body:
|
||||
required: true
|
||||
|
||||
- label: 您确保已使用最新 CI 版本测试,并且该问题在最新 CI 版本中并未解决 / This bug have not solved in latest CI version
|
||||
required: true
|
||||
required: true
|
||||
@@ -1,8 +1,17 @@
|
||||
name: 功能请求 / Feature request
|
||||
description: 提出一个功能建议 / Suggest an idea for this project
|
||||
description: 提出一个功能建议 / Suggest an idea
|
||||
labels:
|
||||
- "enhancement"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
感谢您愿意为 Ehviewer-Overhauled 做出贡献!
|
||||
提交功能建议前,还请首先完成文末的自查步骤
|
||||
|
||||
Thanks for your contribution on Ehviewer-Overhauled Project!
|
||||
Please finish verify steps which list in the end first before suggest an idea
|
||||
|
||||
- type: textarea
|
||||
id: request
|
||||
attributes:
|
||||
@@ -33,7 +42,7 @@ body:
|
||||
- type: textarea
|
||||
id: more
|
||||
attributes:
|
||||
label: 其他细节 / Addition details
|
||||
label: 备注 / Addition details
|
||||
description: |
|
||||
在此处写下其他您想说的内容
|
||||
Describe addition details here
|
||||
@@ -48,7 +57,7 @@ body:
|
||||
attributes:
|
||||
label: EhViewer 版本号 / EhViewer version code
|
||||
description: 您可以在设置 - 关于处找到版本号 / You can get version code in Settings - About
|
||||
placeholder: 四位版本号 / 4 digits version code
|
||||
placeholder: 1.6.9.13
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -82,4 +91,4 @@ body:
|
||||
required: true
|
||||
|
||||
- label: 您确保已使用最新 CI 版本测试,并且该功能在最新 CI 版本中并未按照预期实现 / This feature don't implement correctly in latest CI version
|
||||
required: true
|
||||
required: true
|
||||
@@ -25,11 +25,12 @@ jobs:
|
||||
|
||||
- name: Install NDK
|
||||
run: |
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;25.0.8775105" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;25.1.8937393" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
|
||||
- name: Gradle Build
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
gradle-home-cache-cleanup: true
|
||||
arguments: assembleRelease
|
||||
|
||||
- name: Update ARM64
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
|
||||
- name: Install NDK
|
||||
run: |
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;25.0.8775105" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;25.1.8937393" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
|
||||
- name: Gradle Build
|
||||
uses: gradle/gradle-build-action@v2
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
|
||||
- name: Install NDK
|
||||
run: |
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;25.0.8775105" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;25.1.8937393" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
|
||||
- name: Gradle Build
|
||||
uses: gradle/gradle-build-action@v2
|
||||
|
||||
@@ -79,7 +79,7 @@ App is divided into two versions: 1.7 and 1.8 . Version 1.8 support Android 12 a
|
||||
|
||||
Here is the libraries
|
||||
|
||||
- [AOSP&AndroidX](http://source.android.com/)
|
||||
- [AOSP & AndroidX](http://source.android.com/)
|
||||
- [FullDraggableDrawer](https://github.com/PureWriter/FullDraggableDrawer)
|
||||
- [GnuTLS](https://gnutls.org/)
|
||||
- [material-components-android](https://github.com/material-components/material-components-android)
|
||||
|
||||
+21
-26
@@ -7,12 +7,7 @@ plugins {
|
||||
android {
|
||||
compileSdkVersion 33
|
||||
buildToolsVersion "33.0.0"
|
||||
ndkVersion "25.0.8775105"
|
||||
|
||||
Properties localProperties = new Properties()
|
||||
if (project.rootProject.file('local.properties').exists()) {
|
||||
localProperties.load(project.rootProject.file('local.properties').newDataInputStream())
|
||||
}
|
||||
ndkVersion "25.1.8937393"
|
||||
|
||||
splits {
|
||||
abi {
|
||||
@@ -36,8 +31,8 @@ android {
|
||||
applicationId "moe.tarsin.ehviewer"
|
||||
minSdkVersion 31
|
||||
targetSdkVersion 33
|
||||
versionCode 180010
|
||||
versionName "1.8.2.1"
|
||||
versionCode 180013
|
||||
versionName "1.8.2.4"
|
||||
resConfigs 'zh', 'zh-rCN', 'zh-rHK', 'zh-rTW', 'es', 'ja', 'ko', 'fr', 'de', 'th'
|
||||
}
|
||||
|
||||
@@ -98,26 +93,26 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
def activity_version = "1.6.0-beta01"
|
||||
def activity_version = "1.6.0"
|
||||
implementation "androidx.activity:activity:$activity_version"
|
||||
implementation "androidx.activity:activity-ktx:$activity_version"
|
||||
|
||||
implementation "androidx.annotation:annotation:1.5.0-alpha02"
|
||||
implementation "androidx.annotation:annotation-experimental:1.3.0-beta01"
|
||||
implementation "androidx.appcompat:appcompat:1.6.0-beta01"
|
||||
implementation "androidx.annotation:annotation:1.5.0"
|
||||
implementation "androidx.annotation:annotation-experimental:1.3.0"
|
||||
implementation "androidx.appcompat:appcompat:1.6.0-rc01"
|
||||
|
||||
def arch_core_version = "2.1.0"
|
||||
implementation "androidx.arch.core:core-common:$arch_core_version"
|
||||
implementation "androidx.arch.core:core-runtime:$arch_core_version"
|
||||
|
||||
implementation "androidx.biometric:biometric-ktx:1.2.0-alpha04"
|
||||
implementation "androidx.biometric:biometric-ktx:1.2.0-alpha05"
|
||||
implementation "androidx.browser:browser:1.4.0"
|
||||
|
||||
def collection_version = "1.3.0-alpha02"
|
||||
implementation "androidx.collection:collection:$collection_version"
|
||||
implementation "androidx.collection:collection-ktx:$collection_version"
|
||||
|
||||
def compose_version = "1.3.0-alpha03"
|
||||
def compose_version = "1.3.0-beta03"
|
||||
implementation "androidx.compose.animation:animation:$compose_version"
|
||||
implementation "androidx.compose.foundation:foundation:$compose_version"
|
||||
implementation "androidx.compose.foundation:foundation-layout:$compose_version"
|
||||
@@ -125,23 +120,23 @@ dependencies {
|
||||
implementation "androidx.compose.runtime:runtime-saveable:$compose_version"
|
||||
implementation "androidx.compose.ui:ui:$compose_version"
|
||||
|
||||
implementation "androidx.compose.material3:material3:1.0.0-alpha16"
|
||||
implementation "androidx.compose.material3:material3:1.0.0-beta03"
|
||||
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.2.0-alpha03"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.2.0-alpha04"
|
||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
|
||||
|
||||
def core_version = "1.9.0-beta01"
|
||||
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-alpha01"
|
||||
implementation "androidx.customview:customview:1.2.0-alpha02"
|
||||
implementation "androidx.dynamicanimation:dynamicanimation:1.1.0-alpha03"
|
||||
|
||||
def fragment_version = "1.6.0-alpha01"
|
||||
def fragment_version = "1.6.0-alpha02"
|
||||
implementation "androidx.fragment:fragment:$fragment_version"
|
||||
implementation "androidx.fragment:fragment-ktx:$fragment_version"
|
||||
|
||||
def lifecycle_version = "2.6.0-alpha01"
|
||||
def lifecycle_version = "2.6.0-alpha02"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-core-ktx:$lifecycle_version"
|
||||
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
|
||||
@@ -151,7 +146,7 @@ dependencies {
|
||||
|
||||
implementation "androidx.loader:loader:1.1.0"
|
||||
|
||||
def nav_version = "2.5.1"
|
||||
def nav_version = "2.5.2"
|
||||
implementation "androidx.navigation:navigation-fragment:$nav_version"
|
||||
implementation "androidx.navigation:navigation-ui:$nav_version"
|
||||
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
|
||||
@@ -160,9 +155,9 @@ dependencies {
|
||||
implementation "androidx.paging:paging-runtime:3.2.0-alpha02"
|
||||
|
||||
implementation 'androidx.preference:preference:1.2.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.0-beta02'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.0-rc01'
|
||||
|
||||
def room_version = "2.5.0-alpha02"
|
||||
def room_version = "2.5.0-alpha03"
|
||||
implementation "androidx.room:room-runtime:$room_version"
|
||||
annotationProcessor "androidx.room:room-compiler:$room_version"
|
||||
implementation "androidx.room:room-paging:$room_version"
|
||||
@@ -174,10 +169,10 @@ dependencies {
|
||||
implementation "androidx.vectordrawable:vectordrawable-animated:1.1.0"
|
||||
implementation 'androidx.viewpager:viewpager:1.1.0-alpha01'
|
||||
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
|
||||
implementation 'androidx.webkit:webkit:1.5.0-rc01'
|
||||
implementation 'androidx.webkit:webkit:1.5.0'
|
||||
|
||||
implementation 'com.drakeet.drawer:drawer:1.0.3'
|
||||
implementation 'com.google.android.material:material:1.7.0-beta01'
|
||||
implementation 'com.google.android.material:material:1.8.0-alpha01'
|
||||
|
||||
implementation 'com.squareup.okhttp3:okhttp-bom:5.0.0-alpha.10'
|
||||
implementation 'com.squareup.okhttp3:okhttp'
|
||||
@@ -189,7 +184,7 @@ dependencies {
|
||||
implementation 'dev.rikka.rikkax.preference:simplemenu-preference:1.0.3'
|
||||
implementation 'dev.rikka.rikkax.material:material-preference:2.0.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
|
||||
implementation 'org.jsoup:jsoup:1.15.2'
|
||||
implementation 'org.jsoup:jsoup:1.15.3'
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
|
||||
@@ -23,16 +23,11 @@
|
||||
android:name="android.hardware.touchscreen"
|
||||
android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
<!-- Required to maintain app compatibility. -->
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" />
|
||||
|
||||
<uses-feature
|
||||
android:glEsVersion="0x00020000"
|
||||
android:required="true" />
|
||||
|
||||
@@ -45,6 +45,6 @@ SET(LIBARCHIVE_CUSTOM_LIBS "liblzma" "nettle")
|
||||
add_subdirectory(libarchive)
|
||||
|
||||
# Build and link our app's native lib
|
||||
add_library(${PROJECT_NAME} SHARED main.c archive.c image.c)
|
||||
add_library(${PROJECT_NAME} SHARED main.c archive.c image.c fdutils.c)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC libarchive/libarchive)
|
||||
target_link_libraries(${PROJECT_NAME} archive_static log jnigraphics GLESv2 -Wl,--gc-sections)
|
||||
+46
-31
@@ -195,8 +195,8 @@ static int archive_get_ctx(archive_ctx **ctxptr, int idx) {
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *env, jobject thiz, jint fd, jlong size) {
|
||||
(void)env; /* UNUSED */
|
||||
(void)thiz; /* UNUSED */
|
||||
(void) env; /* UNUSED */
|
||||
(void) thiz; /* UNUSED */
|
||||
archive_ctx *ctx = NULL;
|
||||
archiveAddr = mmap64(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (archiveAddr == MAP_FAILED) {
|
||||
@@ -246,51 +246,39 @@ Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *env, jobject thiz, jint fd
|
||||
return r;
|
||||
}
|
||||
|
||||
typedef struct Memarea {
|
||||
void *buffer;
|
||||
long size;
|
||||
} Memarea;
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *env, jobject thiz, jint index) {
|
||||
(void)env; /* UNUSED */
|
||||
(void)thiz; /* UNUSED */
|
||||
Java_com_hippo_UriArchiveAccessor_extractToAddr(JNIEnv *env, jobject thiz, jint index) {
|
||||
(void) env; /* UNUSED */
|
||||
(void) thiz; /* UNUSED */
|
||||
archive_ctx *ctx = NULL;
|
||||
int ret;
|
||||
ret = archive_get_ctx(&ctx, index);
|
||||
if (ret)
|
||||
return 0;
|
||||
Memarea *memarea = malloc(sizeof(Memarea));
|
||||
if (!memarea) {
|
||||
long long size = archive_entry_size(ctx->entry);
|
||||
void *buffer = malloc(size + sizeof(long long));
|
||||
if (!buffer) {
|
||||
ctx->using = 0;
|
||||
LOGE("Allocate buffer for decompression failed:ENOMEM");
|
||||
return 0;
|
||||
}
|
||||
memarea->size = (long) archive_entry_size(ctx->entry);
|
||||
memarea->buffer = malloc(memarea->size);
|
||||
if (!memarea->buffer) {
|
||||
ctx->using = 0;
|
||||
LOGE("Allocate buffer for decompression failed:ENOMEM");
|
||||
free(memarea);
|
||||
return 0;
|
||||
}
|
||||
ret = archive_read_data(ctx->arc, memarea->buffer, memarea->size);
|
||||
*(long long *) buffer = size;
|
||||
ret = archive_read_data(ctx->arc, buffer + sizeof(long long), size);
|
||||
ctx->using = 0;
|
||||
if (ret == memarea->size)
|
||||
return (jlong) memarea;
|
||||
if (ret != memarea->size)
|
||||
if (ret == size)
|
||||
return (jlong) buffer;
|
||||
if (ret != size)
|
||||
LOGE("%s", "No enough data read, WTF?");
|
||||
if (ret < 0)
|
||||
LOGE("%s%s", "Archive read failed:", archive_error_string(ctx->arc));
|
||||
free(memarea->buffer);
|
||||
free(memarea);
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_closeArchive(JNIEnv *env, jobject thiz) {
|
||||
(void)env; /* UNUSED */
|
||||
(void)thiz; /* UNUSED */
|
||||
(void) env; /* UNUSED */
|
||||
(void) thiz; /* UNUSED */
|
||||
for (int i = 0; i < CTX_POOL_SIZE; i++)
|
||||
archive_release_ctx(ctx_pool[i]);
|
||||
free(passwd);
|
||||
@@ -303,14 +291,14 @@ Java_com_hippo_UriArchiveAccessor_closeArchive(JNIEnv *env, jobject thiz) {
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_needPassword(JNIEnv *env, jobject thiz) {
|
||||
(void)env; /* UNUSED */
|
||||
(void)thiz; /* UNUSED */
|
||||
(void) env; /* UNUSED */
|
||||
(void) thiz; /* UNUSED */
|
||||
return need_encrypt;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_providePassword(JNIEnv *env, jobject thiz, jstring str) {
|
||||
(void)thiz; /* UNUSED */
|
||||
(void) thiz; /* UNUSED */
|
||||
struct archive_entry *entry;
|
||||
archive_ctx *ctx;
|
||||
jboolean ret = true;
|
||||
@@ -337,3 +325,30 @@ Java_com_hippo_UriArchiveAccessor_providePassword(JNIEnv *env, jobject thiz, jst
|
||||
archive_release_ctx(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_getFilename(JNIEnv *env, jobject thiz, jint index) {
|
||||
(void) env; /* UNUSED */
|
||||
(void) thiz; /* UNUSED */
|
||||
archive_ctx *ctx = NULL;
|
||||
int ret;
|
||||
ret = archive_get_ctx(&ctx, index);
|
||||
if (ret)
|
||||
return NULL;
|
||||
jstring str = (*env)->NewStringUTF(env, archive_entry_pathname(ctx->entry));
|
||||
ctx->using = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_extractToFd(JNIEnv *env, jobject thiz, jint index, jint fd) {
|
||||
(void) env; /* UNUSED */
|
||||
(void) thiz; /* UNUSED */
|
||||
archive_ctx *ctx = NULL;
|
||||
int ret;
|
||||
ret = archive_get_ctx(&ctx, index);
|
||||
if (!ret) {
|
||||
archive_read_data_into_fd(ctx->arc, fd);
|
||||
ctx->using = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <jni.h>
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_hippo_Native_getFd(JNIEnv *env, jclass clazz, jobject fileDescriptor) {
|
||||
jint fd = -1;
|
||||
jclass fdClass = (*env)->FindClass(env, "java/io/FileDescriptor");
|
||||
|
||||
if (fdClass != NULL) {
|
||||
jfieldID fdClassDescriptorFieldID = (*env)->GetFieldID(env, fdClass, "descriptor", "I");
|
||||
if (fdClassDescriptorFieldID != NULL && fileDescriptor != NULL) {
|
||||
fd = (*env)->GetIntField(env, fileDescriptor, fdClassDescriptorFieldID);
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
+11
-37
@@ -84,11 +84,6 @@ static void recycle(IMAGE *image) {
|
||||
free(image);
|
||||
}
|
||||
|
||||
typedef struct Memarea {
|
||||
void *buffer;
|
||||
long size;
|
||||
} Memarea;
|
||||
|
||||
bool copy_pixels(const void *src, int src_w, int src_h, int src_x, int src_y,
|
||||
void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height) {
|
||||
@@ -159,17 +154,17 @@ bool copy_pixels(const void *src, int src_w, int src_h, int src_x, int src_y,
|
||||
dst_blank_length = (size_t) (dst_y * dst_w + dst_x) * 4;
|
||||
|
||||
// First line
|
||||
dst_pos += (int)dst_blank_length;
|
||||
dst_pos += (int) dst_blank_length;
|
||||
memcpy(dst + dst_pos, src + src_pos, line_stride);
|
||||
dst_pos += (int)line_stride;
|
||||
dst_pos += (int) line_stride;
|
||||
src_pos += src_stride;
|
||||
|
||||
// Other lines
|
||||
dst_blank_length = (size_t) ((dst_w - width) * 4);
|
||||
for (line = 1; line < height; line++) {
|
||||
dst_pos += (int)dst_blank_length;
|
||||
dst_pos += (int) dst_blank_length;
|
||||
memcpy(dst + dst_pos, src + src_pos, line_stride);
|
||||
dst_pos += (int)line_stride;
|
||||
dst_pos += (int) line_stride;
|
||||
src_pos += src_stride;
|
||||
}
|
||||
|
||||
@@ -216,9 +211,9 @@ IMAGE *createFromFd(int fd) {
|
||||
return image;
|
||||
}
|
||||
|
||||
IMAGE *createFromAddr(void *addr, long size) {
|
||||
IMAGE *createFromAddr(void *addr, long long size) {
|
||||
AImageDecoder *decoder;
|
||||
AImageDecoder_createFromBuffer((const void *) addr, size, &decoder);
|
||||
AImageDecoder_createFromBuffer((const void *) addr + sizeof(long long), size, &decoder);
|
||||
IMAGE *image = calloc(1, sizeof(IMAGE));
|
||||
SOURCE *src = calloc(1, sizeof(SOURCE));
|
||||
src->decoder = decoder;
|
||||
@@ -263,32 +258,12 @@ void advance(IMAGE *image) {
|
||||
}
|
||||
}
|
||||
|
||||
static int jniGetFDFromFileDescriptor(JNIEnv *env, jobject fileDescriptor) {
|
||||
jint fd = -1;
|
||||
jclass fdClass = (*env)->FindClass(env, "java/io/FileDescriptor");
|
||||
|
||||
if (fdClass != NULL) {
|
||||
jfieldID fdClassDescriptorFieldID = (*env)->GetFieldID(env, fdClass, "descriptor", "I");
|
||||
if (fdClassDescriptorFieldID != NULL && fileDescriptor != NULL) {
|
||||
fd = (*env)->GetIntField(env, fileDescriptor, fdClassDescriptorFieldID);
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_hippo_image_Image_nativeDecodeFdInt(JNIEnv *env, jclass clazz, jint fd) {
|
||||
Java_com_hippo_image_Image_nativeDecode(JNIEnv *env, jclass clazz, jint fd) {
|
||||
IMAGE *image = createFromFd(fd);
|
||||
return (jlong) image;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_hippo_image_Image_nativeDecode(JNIEnv *env, jclass clazz, jobject fd) {
|
||||
return Java_com_hippo_image_Image_nativeDecodeFdInt(env, clazz,
|
||||
jniGetFDFromFileDescriptor(env, fd));
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_hippo_image_Image_nativeCreate(JNIEnv *env, jclass clazz, jobject bitmap) {
|
||||
AndroidBitmapInfo info;
|
||||
@@ -298,7 +273,7 @@ Java_com_hippo_image_Image_nativeCreate(JNIEnv *env, jclass clazz, jobject bitma
|
||||
AndroidBitmap_getInfo(env, bitmap, &info);
|
||||
AndroidBitmap_lockPixels(env, bitmap, &pixels);
|
||||
|
||||
image = create((int)info.width, (int)info.height, pixels);
|
||||
image = create((int) info.width, (int) info.height, pixels);
|
||||
AndroidBitmap_unlockPixels(env, bitmap);
|
||||
return (jlong) image;
|
||||
}
|
||||
@@ -313,7 +288,8 @@ Java_com_hippo_image_Image_nativeRender(JNIEnv *env, jclass clazz, jlong ptr, ji
|
||||
AndroidBitmap_getInfo(env, dst, &info);
|
||||
AndroidBitmap_lockPixels(env, dst, &pixels);
|
||||
|
||||
render((IMAGE *) ptr, src_x, src_y, pixels, (int)info.width, (int)info.height, dst_x, dst_y, width,
|
||||
render((IMAGE *) ptr, src_x, src_y, pixels, (int) info.width, (int) info.height, dst_x, dst_y,
|
||||
width,
|
||||
height);
|
||||
|
||||
AndroidBitmap_unlockPixels(env, dst);
|
||||
@@ -358,9 +334,7 @@ Java_com_hippo_image_Image_nativeRecycle(JNIEnv *env, jclass clazz, jlong ptr) {
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_hippo_image_Image_nativeDecodeAddr(JNIEnv *env, jclass clazz, jlong addr) {
|
||||
Memarea *memarea = (Memarea *) addr;
|
||||
IMAGE *image = createFromAddr(memarea->buffer, memarea->size);
|
||||
free(memarea);
|
||||
IMAGE *image = createFromAddr((void *) addr, *(long long *) addr);
|
||||
return (jlong) image;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,23 +43,3 @@ JNIEXPORT void JNICALL
|
||||
JNI_OnUnload(JavaVM *vm, void *reserved) {
|
||||
image_onUnload();
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_hippo_Native_getlibarchiveVersion(JNIEnv *env, jclass clazz) {
|
||||
return (*env)->NewStringUTF(env, ARCHIVE_VERSION_STRING);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_hippo_Native_getliblzmaVersion(JNIEnv *env, jclass clazz) {
|
||||
return (*env)->NewStringUTF(env, lzma_version_string());
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_hippo_Native_getzlibVersion(JNIEnv *env, jclass clazz) {
|
||||
return (*env)->NewStringUTF(env, ZLIB_VERSION);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_hippo_Native_getnettleVersion(JNIEnv *env, jclass clazz) {
|
||||
return (*env)->NewStringUTF(env, PACKAGE_STRING);
|
||||
}
|
||||
@@ -18,17 +18,12 @@
|
||||
|
||||
package com.hippo;
|
||||
|
||||
public class Native {
|
||||
import java.io.FileDescriptor;
|
||||
|
||||
public class Native {
|
||||
public static void initialize() {
|
||||
System.loadLibrary("ehviewer");
|
||||
}
|
||||
|
||||
public static native String getlibarchiveVersion();
|
||||
|
||||
public static native String getliblzmaVersion();
|
||||
|
||||
public static native String getzlibVersion();
|
||||
|
||||
public static native String getnettleVersion();
|
||||
public static native int getFd(FileDescriptor fd);
|
||||
}
|
||||
@@ -21,10 +21,6 @@ package com.hippo;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.system.Os;
|
||||
import android.system.OsConstants;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
|
||||
public class UriArchiveAccessor {
|
||||
ParcelFileDescriptor pfd;
|
||||
@@ -43,7 +39,11 @@ public class UriArchiveAccessor {
|
||||
|
||||
private native int openArchive(int fd, long size);
|
||||
|
||||
public native long extracttoOutputStream(int index);
|
||||
public native long extractToAddr(int index);
|
||||
|
||||
public native void extractToFd(int index, int fd);
|
||||
|
||||
public native String getFilename(int index);
|
||||
|
||||
public native boolean needPassword();
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.hippo.app
|
||||
|
||||
import android.content.Context
|
||||
import android.view.WindowManager
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
||||
open class BaseDialogBuilder constructor(
|
||||
context: Context
|
||||
) : MaterialAlertDialogBuilder(context) {
|
||||
override fun create(): AlertDialog {
|
||||
return super.create().apply {
|
||||
window?.run {
|
||||
addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND)
|
||||
addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
|
||||
attributes.blurBehindRadius = 32
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ package com.hippo.app
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.CheckBox
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.hippo.ehviewer.R
|
||||
|
||||
class CheckBoxDialogBuilder constructor(
|
||||
@@ -26,7 +25,7 @@ class CheckBoxDialogBuilder constructor(
|
||||
message: String?,
|
||||
checkText: String?,
|
||||
checked: Boolean
|
||||
) : MaterialAlertDialogBuilder(
|
||||
) : BaseDialogBuilder(
|
||||
context
|
||||
) {
|
||||
private val mCheckBox: CheckBox
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import android.widget.TextView.OnEditorActionListener
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.hippo.ehviewer.R
|
||||
|
||||
@@ -31,7 +30,7 @@ class EditTextDialogBuilder constructor(
|
||||
context: Context,
|
||||
text: String?,
|
||||
hint: String?
|
||||
) : MaterialAlertDialogBuilder(
|
||||
) : BaseDialogBuilder(
|
||||
context
|
||||
), OnEditorActionListener {
|
||||
private val mTextInputLayout: TextInputLayout
|
||||
|
||||
@@ -23,14 +23,13 @@ import android.widget.ArrayAdapter
|
||||
import android.widget.CheckBox
|
||||
import android.widget.ListView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.yorozuya.ViewUtils
|
||||
|
||||
class ListCheckBoxDialogBuilder constructor(
|
||||
context: Context, items: Array<CharSequence>,
|
||||
listener: OnItemClickListener?, checkText: String?, checked: Boolean
|
||||
) : MaterialAlertDialogBuilder(
|
||||
) : BaseDialogBuilder(
|
||||
context
|
||||
) {
|
||||
private val mCheckBox: CheckBox
|
||||
|
||||
@@ -51,7 +51,6 @@ public final class ConacoTask<V> {
|
||||
private final WeakReference<Unikery<V>> mUnikeryWeakReference;
|
||||
private final String mKey;
|
||||
private final String mUrl;
|
||||
private final DataContainer mDataContainer;
|
||||
private final boolean mUseMemoryCache;
|
||||
private final boolean mUseDiskCache;
|
||||
private final boolean mUseNetwork;
|
||||
@@ -73,7 +72,6 @@ public final class ConacoTask<V> {
|
||||
mUnikeryWeakReference = new WeakReference<>(builder.mUnikery);
|
||||
mKey = builder.mKey;
|
||||
mUrl = builder.mUrl;
|
||||
mDataContainer = builder.mDataContainer;
|
||||
mUseMemoryCache = builder.mUseMemoryCache;
|
||||
mUseDiskCache = builder.mUseDiskCache;
|
||||
mUseNetwork = builder.mUseNetwork;
|
||||
@@ -85,42 +83,6 @@ public final class ConacoTask<V> {
|
||||
mConaco = builder.mConaco;
|
||||
}
|
||||
|
||||
private static void putFromDiskCacheToDataContainer(String key, ValueCache cache, DataContainer container) {
|
||||
SimpleDiskCache diskCache = cache.getDiskCache();
|
||||
if (diskCache != null) {
|
||||
InputStreamPipe pipe = diskCache.getInputStreamPipe(key);
|
||||
if (pipe != null) {
|
||||
try {
|
||||
pipe.obtain();
|
||||
container.save(pipe.open(), -1L, null, null);
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, "Can't save value from disk cache to data container");
|
||||
e.printStackTrace();
|
||||
container.remove();
|
||||
} finally {
|
||||
pipe.close();
|
||||
pipe.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void putFromDataContainerToDiskCache(String key, ValueCache cache, DataContainer container) {
|
||||
InputStreamPipe pipe = container.get();
|
||||
if (pipe != null) {
|
||||
try {
|
||||
pipe.obtain();
|
||||
cache.putRawToDisk(key, pipe.open());
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Can't save value from data container to disk cache", e);
|
||||
cache.removeFromDisk(key);
|
||||
} finally {
|
||||
pipe.close();
|
||||
pipe.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int getId() {
|
||||
return mId;
|
||||
}
|
||||
@@ -219,7 +181,6 @@ public final class ConacoTask<V> {
|
||||
private Unikery<T> mUnikery;
|
||||
private String mKey;
|
||||
private String mUrl;
|
||||
private DataContainer mDataContainer;
|
||||
private boolean mUseMemoryCache = true;
|
||||
private boolean mUseDiskCache = true;
|
||||
private boolean mUseNetwork = true;
|
||||
@@ -262,11 +223,6 @@ public final class ConacoTask<V> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> setDataContainer(DataContainer dataContainer) {
|
||||
mDataContainer = dataContainer;
|
||||
return this;
|
||||
}
|
||||
|
||||
boolean isUseMemoryCache() {
|
||||
return mUseMemoryCache;
|
||||
}
|
||||
@@ -332,7 +288,7 @@ public final class ConacoTask<V> {
|
||||
if (mUnikery == null) {
|
||||
throw new IllegalStateException("Must set unikery");
|
||||
}
|
||||
if (mKey == null && mUrl == null && mDataContainer == null) {
|
||||
if (mKey == null && mUrl == null) {
|
||||
throw new IllegalStateException("At least one of mKey and mUrl and mDataContainer have to not be null");
|
||||
}
|
||||
}
|
||||
@@ -352,26 +308,13 @@ public final class ConacoTask<V> {
|
||||
} else {
|
||||
V value = null;
|
||||
|
||||
// First check data container
|
||||
if (mDataContainer != null && mDataContainer.isEnabled()) {
|
||||
InputStreamPipe isp = mDataContainer.get();
|
||||
if (isp != null) {
|
||||
value = mHelper.decode(isp);
|
||||
}
|
||||
}
|
||||
|
||||
// Then check disk cache
|
||||
if (mKey != null) {
|
||||
if (value == null && mUseDiskCache) {
|
||||
value = mCache.getFromDisk(mKey);
|
||||
// Put back to data container
|
||||
if (value != null && mDataContainer != null && mDataContainer.isEnabled()) {
|
||||
putFromDiskCacheToDataContainer(mKey, mCache, mDataContainer);
|
||||
}
|
||||
}
|
||||
|
||||
if (value != null && mUseMemoryCache && mHelper.useMemoryCache(mKey, value)) {
|
||||
// Put it to memory
|
||||
mCache.putToMemory(mKey, value);
|
||||
}
|
||||
}
|
||||
@@ -451,18 +394,6 @@ public final class ConacoTask<V> {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean putToDataContainer(InputStream is, ResponseBody body) {
|
||||
// Get media type
|
||||
String mediaType;
|
||||
MediaType mt = body.contentType();
|
||||
if (mt != null) {
|
||||
mediaType = mt.type() + '/' + mt.subtype();
|
||||
} else {
|
||||
mediaType = null;
|
||||
}
|
||||
return mDataContainer.save(is, body.contentLength(), mediaType, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected V doInBackground(Void... params) {
|
||||
if (isNotNecessary(this)) {
|
||||
@@ -489,7 +420,7 @@ public final class ConacoTask<V> {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((mDataContainer == null || !mDataContainer.isEnabled()) && mKey != null) {
|
||||
if (mKey != null) {
|
||||
if (putToDiskCache(is, body.contentLength())) {
|
||||
// Get object from disk cache
|
||||
value = mCache.getFromDisk(mKey);
|
||||
@@ -506,37 +437,6 @@ public final class ConacoTask<V> {
|
||||
mCache.removeFromDisk(mKey);
|
||||
return null;
|
||||
}
|
||||
} else if (mDataContainer != null && mDataContainer.isEnabled()) {
|
||||
// Check url Moved
|
||||
HttpUrl requestHttpUrl = request.url();
|
||||
HttpUrl responseHttpUrl = response.request().url();
|
||||
if (!responseHttpUrl.equals(requestHttpUrl)) {
|
||||
mDataContainer.onUrlMoved(mUrl, responseHttpUrl.url().toString());
|
||||
}
|
||||
|
||||
// Put to data container
|
||||
if (!putToDataContainer(is, body)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get value from data container
|
||||
InputStreamPipe isp = mDataContainer.get();
|
||||
if (isp == null) {
|
||||
return null;
|
||||
}
|
||||
value = mHelper.decode(isp);
|
||||
if (value == null) {
|
||||
mDataContainer.remove();
|
||||
} else if (mKey != null) {
|
||||
// Put to disk cache
|
||||
putFromDataContainerToDiskCache(mKey, mCache, mDataContainer);
|
||||
|
||||
if (mUseMemoryCache && mHelper.useMemoryCache(mKey, value)) {
|
||||
// Put it to memory
|
||||
mCache.putToMemory(mKey, value);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015-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.conaco;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.hippo.streampipe.InputStreamPipe;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public interface DataContainer {
|
||||
|
||||
/**
|
||||
* Returns the enabled status for this DataContainer.
|
||||
*/
|
||||
boolean isEnabled();
|
||||
|
||||
/**
|
||||
* Get 304 or something like that
|
||||
*/
|
||||
void onUrlMoved(String requestUrl, String responseUrl);
|
||||
|
||||
/**
|
||||
* Save the {@code InputStream}
|
||||
*/
|
||||
boolean save(InputStream is, long length, @Nullable String mediaType, @Nullable ProgressNotifier notify);
|
||||
|
||||
/**
|
||||
* Get {@code InputStreamPipe} for saved before
|
||||
*/
|
||||
@Nullable
|
||||
InputStreamPipe get();
|
||||
|
||||
/**
|
||||
* Remove saved stuff
|
||||
*/
|
||||
void remove();
|
||||
}
|
||||
@@ -44,8 +44,8 @@ import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.ProcessLifecycleOwner;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.hippo.Native;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.beerbelly.SimpleDiskCache;
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.ehviewer.client.EhClient;
|
||||
@@ -68,7 +68,6 @@ import com.hippo.network.StatusCodeException;
|
||||
import com.hippo.scene.SceneApplication;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.util.BitmapUtils;
|
||||
import com.hippo.util.ClipboardUtil;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.util.IoThreadPoolExecutor;
|
||||
import com.hippo.util.ReadableTime;
|
||||
@@ -110,6 +109,7 @@ public class EhApplication extends SceneApplication {
|
||||
private static final long DEBUG_PRINT_INTERVAL = 3000L;
|
||||
|
||||
public static boolean locked = true;
|
||||
public static long locked_last_leave_time = 0;
|
||||
|
||||
private static EhApplication instance;
|
||||
|
||||
@@ -328,7 +328,6 @@ public class EhApplication extends SceneApplication {
|
||||
super.onCreate();
|
||||
|
||||
Native.initialize();
|
||||
ClipboardUtil.initialize(this);
|
||||
GetText.initialize(this);
|
||||
StatusCodeException.initialize(this);
|
||||
Settings.initialize(this);
|
||||
@@ -430,7 +429,7 @@ public class EhApplication extends SceneApplication {
|
||||
Activity activity = getTopActivity();
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(() -> {
|
||||
AlertDialog dialog = new MaterialAlertDialogBuilder(activity)
|
||||
AlertDialog dialog = new BaseDialogBuilder(activity)
|
||||
.setMessage(Html.fromHtml(html))
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.create();
|
||||
@@ -591,6 +590,8 @@ public class EhApplication extends SceneApplication {
|
||||
static class EhlifecycleObserver implements DefaultLifecycleObserver {
|
||||
@Override
|
||||
public void onPause(@NonNull LifecycleOwner owner) {
|
||||
if (!locked)
|
||||
locked_last_leave_time = System.currentTimeMillis() / 1000;
|
||||
locked = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,60 +490,73 @@ public class EhDB {
|
||||
EhDatabase oldRoomDatabase = Room.databaseBuilder(context, EhDatabase.class, tmpDBName)
|
||||
.createFromFile(file).allowMainThreadQueries().build();
|
||||
|
||||
// Download label
|
||||
DownloadManager manager = EhApplication.getDownloadManager(context);
|
||||
try {
|
||||
List<DownloadLabel> downloadLabelList = oldRoomDatabase.downloadLabelDao().list();
|
||||
manager.addDownloadLabel(downloadLabelList);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
// Downloads
|
||||
DownloadManager manager = EhApplication.getDownloadManager(context);
|
||||
List<DownloadInfo> downloadInfoList = oldRoomDatabase.downloadsDao().list();
|
||||
manager.addDownload(downloadInfoList, false);
|
||||
|
||||
// Download label
|
||||
List<DownloadLabel> downloadLabelList = oldRoomDatabase.downloadLabelDao().list();
|
||||
manager.addDownloadLabel(downloadLabelList);
|
||||
try {
|
||||
List<DownloadInfo> downloadInfoList = oldRoomDatabase.downloadsDao().list();
|
||||
manager.addDownload(downloadInfoList, false);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
// Download dirname
|
||||
List<DownloadDirname> downloadDirnameList = oldRoomDatabase.downloadDirnameDao().list();
|
||||
for (DownloadDirname dirname : downloadDirnameList) {
|
||||
putDownloadDirname(dirname.getGid(), dirname.getDirname());
|
||||
}
|
||||
try {
|
||||
List<DownloadDirname> downloadDirnameList = oldRoomDatabase.downloadDirnameDao().list();
|
||||
for (DownloadDirname dirname : downloadDirnameList) {
|
||||
putDownloadDirname(dirname.getGid(), dirname.getDirname());
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
// History
|
||||
List<HistoryInfo> historyInfoList = oldRoomDatabase.historyDao().list();
|
||||
putHistoryInfo(historyInfoList);
|
||||
try {
|
||||
List<HistoryInfo> historyInfoList = oldRoomDatabase.historyDao().list();
|
||||
putHistoryInfo(historyInfoList);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
// QuickSearch
|
||||
List<QuickSearch> quickSearchList = oldRoomDatabase.quickSearchDao().list();
|
||||
List<QuickSearch> currentQuickSearchList = db.quickSearchDao().list();
|
||||
List<QuickSearch> importList = new ArrayList<>();
|
||||
for (QuickSearch quickSearch : quickSearchList) {
|
||||
String name = quickSearch.name;
|
||||
for (QuickSearch q : currentQuickSearchList) {
|
||||
if (ObjectUtils.equal(q.name, name)) {
|
||||
// The same name
|
||||
name = null;
|
||||
break;
|
||||
try {
|
||||
List<QuickSearch> quickSearchList = oldRoomDatabase.quickSearchDao().list();
|
||||
List<QuickSearch> currentQuickSearchList = db.quickSearchDao().list();
|
||||
List<QuickSearch> importList = new ArrayList<>();
|
||||
for (QuickSearch quickSearch : quickSearchList) {
|
||||
String name = quickSearch.name;
|
||||
for (QuickSearch q : currentQuickSearchList) {
|
||||
if (ObjectUtils.equal(q.name, name)) {
|
||||
// The same name
|
||||
name = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (null == name) {
|
||||
continue;
|
||||
}
|
||||
importList.add(quickSearch);
|
||||
}
|
||||
if (null == name) {
|
||||
continue;
|
||||
}
|
||||
importList.add(quickSearch);
|
||||
}
|
||||
importQuickSearch(importList);
|
||||
importQuickSearch(importList);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
// LocalFavorites
|
||||
List<LocalFavoriteInfo> localFavoriteInfoList = oldRoomDatabase.localFavoritesDao().list();
|
||||
for (LocalFavoriteInfo info : localFavoriteInfoList) {
|
||||
putLocalFavorites(info);
|
||||
}
|
||||
try {
|
||||
List<LocalFavoriteInfo> localFavoriteInfoList = oldRoomDatabase.localFavoritesDao().list();
|
||||
for (LocalFavoriteInfo info : localFavoriteInfoList) {
|
||||
putLocalFavorites(info);
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
// Filter
|
||||
List<Filter> filterList = oldRoomDatabase.filterDao().list();
|
||||
List<Filter> currentFilterList = db.filterDao().list();
|
||||
for (Filter filter : filterList) {
|
||||
if (!currentFilterList.contains(filter)) {
|
||||
addFilter(filter);
|
||||
try {
|
||||
List<Filter> filterList = oldRoomDatabase.filterDao().list();
|
||||
List<Filter> currentFilterList = db.filterDao().list();
|
||||
for (Filter filter : filterList) {
|
||||
if (!currentFilterList.contains(filter)) {
|
||||
addFilter(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
return null;
|
||||
} catch (Throwable e) {
|
||||
|
||||
@@ -50,6 +50,8 @@ public class Settings {
|
||||
********************/
|
||||
|
||||
public static final String KEY_THEME = "theme";
|
||||
|
||||
public static final String KEY_ACCOUNT = "account";
|
||||
public static final String KEY_BLACK_DARK_THEME = "black_dark_theme";
|
||||
public static final int THEME_LIGHT = 1;
|
||||
public static final int THEME_SYSTEM = -1;
|
||||
@@ -90,6 +92,7 @@ public class Settings {
|
||||
********************/
|
||||
public static final String KEY_SAVE_PARSE_ERROR_BODY = "save_parse_error_body";
|
||||
public static final String KEY_SECURITY = "require_unlock";
|
||||
public static final String KEY_SECURITY_DELAY = "require_unlock_delay";
|
||||
public static final String DEFAULT_SECURITY = "";
|
||||
public static final String KEY_ENABLE_FINGERPRINT = "enable_fingerprint";
|
||||
public static final String KEY_READ_CACHE_SIZE = "read_cache_size";
|
||||
@@ -433,6 +436,7 @@ public class Settings {
|
||||
putInt(KEY_VERSION_CODE, value);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getDisplayName() {
|
||||
return getString(KEY_DISPLAY_NAME, DEFAULT_DISPLAY_NAME);
|
||||
}
|
||||
@@ -1063,6 +1067,9 @@ public class Settings {
|
||||
public static void putSecurity(boolean value) {
|
||||
putBoolean(KEY_SECURITY, value);
|
||||
}
|
||||
public static int getSecurityDelay() {
|
||||
return getInt(KEY_SECURITY_DELAY, 0);
|
||||
}
|
||||
|
||||
public static boolean getEnableFingerprint() {
|
||||
return getBoolean(KEY_ENABLE_FINGERPRINT, true);
|
||||
|
||||
@@ -24,15 +24,19 @@ import android.os.Process;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.hippo.Native;
|
||||
import com.hippo.UriArchiveAccessor;
|
||||
import com.hippo.ehviewer.GetText;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.yorozuya.FileUtils;
|
||||
import com.hippo.yorozuya.thread.PVLock;
|
||||
import com.hippo.yorozuya.thread.PriorityThread;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
@@ -143,28 +147,43 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
@NonNull
|
||||
@Override
|
||||
public String getImageFilename(int index) {
|
||||
// TODO
|
||||
return Integer.toString(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean save(int index, @NonNull UniFile file) {
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public UniFile save(int index, @NonNull UniFile dir, @NonNull String filename) {
|
||||
// TODO
|
||||
return null;
|
||||
return FileUtils.getNameFromFilename(getImageFilenameWithExtension(index));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getImageFilenameWithExtension(int index) {
|
||||
// TODO
|
||||
return Integer.toString(index);
|
||||
return FileUtils.sanitizeFilename(archiveAccessor.getFilename(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean save(int index, @NonNull UniFile file) {
|
||||
int fd;
|
||||
FileOutputStream stream;
|
||||
try {
|
||||
stream = (FileOutputStream)file.openOutputStream();
|
||||
fd = Native.getFd(stream.getFD());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
archiveAccessor.extractToFd(index, fd);
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public UniFile save(int index, @NonNull UniFile dir, @NonNull String filename) {
|
||||
String extension = FileUtils.getExtensionFromFilename(getImageFilenameWithExtension(index));
|
||||
UniFile dst = dir.subFile(null != extension ? filename + "." + extension : filename);
|
||||
save(index, dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
private class ArchiveHostTask implements Runnable {
|
||||
@@ -279,7 +298,7 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
}
|
||||
}
|
||||
|
||||
long addr = archiveAccessor.extracttoOutputStream(index);
|
||||
long addr = archiveAccessor.extractToAddr(index);
|
||||
|
||||
synchronized (streams) {
|
||||
streams.put(index, addr);
|
||||
|
||||
+12
-21
@@ -16,8 +16,6 @@
|
||||
package com.hippo.ehviewer.preference
|
||||
|
||||
import android.content.*
|
||||
import android.os.Build
|
||||
import android.os.PersistableBundle
|
||||
import android.text.Html
|
||||
import android.util.AttributeSet
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
@@ -25,14 +23,17 @@ import com.hippo.ehviewer.EhApplication
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.client.EhCookieStore
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
import com.hippo.ehviewer.client.EhUtils
|
||||
import com.hippo.ehviewer.ui.SettingsActivity
|
||||
import com.hippo.ehviewer.ui.scene.BaseScene
|
||||
import com.hippo.preference.MessagePreference
|
||||
import com.hippo.util.addTextToClipboard
|
||||
import com.hippo.util.getClipboardManager
|
||||
import okhttp3.Cookie
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import java.util.*
|
||||
|
||||
class IdentityCookiePreference @JvmOverloads constructor(
|
||||
class AccountPreference @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null
|
||||
) : MessagePreference(context, attrs) {
|
||||
private val mActivity = context as SettingsActivity
|
||||
@@ -79,26 +80,16 @@ class IdentityCookiePreference @JvmOverloads constructor(
|
||||
override fun onPrepareDialogBuilder(builder: AlertDialog.Builder) {
|
||||
super.onPrepareDialogBuilder(builder)
|
||||
if (message != null) {
|
||||
builder.setPositiveButton(R.string.settings_eh_identity_cookies_copy) { dialog: DialogInterface?, which: Int ->
|
||||
val clipboardManager =
|
||||
context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?
|
||||
val clipData = ClipData.newPlainText(null, message)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
||||
clipData.apply {
|
||||
description.extras = PersistableBundle().apply {
|
||||
putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true)
|
||||
}
|
||||
}
|
||||
clipboardManager?.setPrimaryClip(clipData)
|
||||
|
||||
// There is no need to notify user by toast since Tiramisu have its clipboard own logic
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU)
|
||||
builder.setNeutralButton(R.string.settings_eh_identity_cookies_copy) { dialog: DialogInterface?, which: Int ->
|
||||
context.getClipboardManager().addTextToClipboard(message, true) {
|
||||
mActivity.showTip(R.string.copied_to_clipboard, BaseScene.LENGTH_SHORT)
|
||||
this@IdentityCookiePreference.onClick(dialog, which)
|
||||
}
|
||||
this@AccountPreference.onClick(dialog, which)
|
||||
}
|
||||
builder.setNegativeButton(android.R.string.cancel, null)
|
||||
} else {
|
||||
builder.setPositiveButton(android.R.string.ok, null)
|
||||
}
|
||||
builder.setPositiveButton(R.string.settings_eh_sign_out) { _: DialogInterface?, _: Int ->
|
||||
EhUtils.signOut(context)
|
||||
mActivity.showTip(R.string.settings_eh_sign_out_tip, BaseScene.LENGTH_SHORT)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.preference;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.ehviewer.ui.SettingsActivity;
|
||||
import com.hippo.ehviewer.ui.scene.BaseScene;
|
||||
import com.hippo.preference.MessagePreference;
|
||||
|
||||
public class SignOutPreference extends MessagePreference {
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private final SettingsActivity mActivity;
|
||||
|
||||
public SignOutPreference(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
mActivity = (SettingsActivity) context;
|
||||
}
|
||||
|
||||
public SignOutPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
mActivity = (SettingsActivity) context;
|
||||
}
|
||||
|
||||
public SignOutPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
mActivity = (SettingsActivity) context;
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setDialogMessage(getContext().getString(R.string.settings_eh_sign_out_warning));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
|
||||
super.onPrepareDialogBuilder(builder);
|
||||
builder.setPositiveButton(R.string.settings_eh_sign_out_yes, this);
|
||||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDialogClosed(boolean positiveResult) {
|
||||
super.onDialogClosed(positiveResult);
|
||||
if (positiveResult) {
|
||||
EhUtils.signOut(getContext());
|
||||
mActivity.showTip(R.string.settings_eh_sign_out_tip, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,14 +18,12 @@ package com.hippo.ehviewer.preference
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.util.AttributeSet
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.hippo.Native
|
||||
import androidx.preference.Preference
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.preference.MessagePreference
|
||||
|
||||
class VersionPreference @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null
|
||||
) : MessagePreference(context, attrs) {
|
||||
) : Preference(context, attrs) {
|
||||
init {
|
||||
setTitle(R.string.settings_about_version)
|
||||
@Suppress("DEPRECATION") val version: String = try {
|
||||
@@ -37,31 +35,4 @@ class VersionPreference @JvmOverloads constructor(
|
||||
}
|
||||
summary = version
|
||||
}
|
||||
|
||||
override fun onPrepareDialogBuilder(builder: AlertDialog.Builder) {
|
||||
super.onPrepareDialogBuilder(builder)
|
||||
builder.setTitle(R.string.show_library_version)
|
||||
val info = NativeLibInfo().addLib(Native.getlibarchiveVersion())
|
||||
.addLib("lzma(xz-utils)", Native.getliblzmaVersion())
|
||||
.addLib("zlib", Native.getzlibVersion())
|
||||
.addLib(Native.getnettleVersion())
|
||||
builder.setMessage(info.getMessage())
|
||||
}
|
||||
|
||||
inner class NativeLibInfo {
|
||||
private var message: String = ""
|
||||
fun addLib(libname: String, libversion: String): NativeLibInfo {
|
||||
message = "$message$libname $libversion\n"
|
||||
return this
|
||||
}
|
||||
|
||||
fun getMessage(): String {
|
||||
return message;
|
||||
}
|
||||
|
||||
fun addLib(msg: String): NativeLibInfo {
|
||||
message = "$message$msg\n"
|
||||
return this
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import androidx.annotation.StyleRes
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.hippo.ehviewer.EhApplication
|
||||
import com.hippo.ehviewer.EhApplication.locked_last_leave_time
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.ui.SecurityActivity.Companion.isAuthenticationSupported
|
||||
@@ -100,7 +101,11 @@ abstract class EhActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
if (Settings.getSecurity() && isAuthenticationSupported(this) && EhApplication.locked) {
|
||||
val locked_resume_time = System.currentTimeMillis() / 1000
|
||||
val locked_delay_time = locked_resume_time - locked_last_leave_time
|
||||
if (Settings.getSecurity() && locked_delay_time >= Settings.getSecurityDelay() * 60
|
||||
&& isAuthenticationSupported(this) && EhApplication.locked
|
||||
) {
|
||||
startActivity(Intent(this, SecurityActivity::class.java))
|
||||
}
|
||||
super.onResume()
|
||||
@@ -121,7 +126,7 @@ abstract class EhActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
|
||||
fun checkAndRequestNotificationPermission(){
|
||||
fun checkAndRequestNotificationPermission() {
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
this,
|
||||
Manifest.permission.POST_NOTIFICATIONS
|
||||
|
||||
@@ -67,8 +67,8 @@ import androidx.core.view.WindowCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.core.view.WindowInsetsControllerCompat;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.materialswitch.MaterialSwitch;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.app.EditTextDialogBuilder;
|
||||
import com.hippo.ehviewer.AppConfig;
|
||||
import com.hippo.ehviewer.BuildConfig;
|
||||
@@ -290,16 +290,7 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
}
|
||||
outState.putInt(KEY_PAGE, mPage);
|
||||
outState.putInt(KEY_CURRENT_INDEX, mCurrentIndex);
|
||||
} ActivityResultLauncher<String> requestStoragePermissionLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.RequestPermission(),
|
||||
result -> {
|
||||
if (result && mSavingPage != -1) {
|
||||
saveImage(mSavingPage);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
mSavingPage = -1;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(@NonNull Context newBase) {
|
||||
@@ -312,7 +303,16 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
break;
|
||||
}
|
||||
super.attachBaseContext(newBase);
|
||||
}
|
||||
} ActivityResultLauncher<String> requestStoragePermissionLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.RequestPermission(),
|
||||
result -> {
|
||||
if (result && mSavingPage != -1) {
|
||||
saveImage(mSavingPage);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
mSavingPage = -1;
|
||||
});
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"WrongConstant"})
|
||||
@@ -410,7 +410,7 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
if (scroll < 0.0f) {
|
||||
if (mLayoutMode == GalleryView.LAYOUT_RIGHT_TO_LEFT) {
|
||||
mGalleryView.pageLeft();
|
||||
} else if (mLayoutMode == GalleryView.LAYOUT_LEFT_TO_RIGHT){
|
||||
} else if (mLayoutMode == GalleryView.LAYOUT_LEFT_TO_RIGHT) {
|
||||
mGalleryView.pageRight();
|
||||
} else if (mLayoutMode == GalleryView.LAYOUT_TOP_TO_BOTTOM) {
|
||||
mGalleryView.onScroll(0, -scroll, 0, -scroll, 0, -scroll);
|
||||
@@ -858,7 +858,8 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
intent.setAction(Intent.ACTION_SEND);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
intent.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, EhUrl.getGalleryDetailUrl(mGalleryInfo.gid, mGalleryInfo.token));
|
||||
if (mGalleryInfo != null)
|
||||
intent.putExtra(Intent.EXTRA_TEXT, EhUrl.getGalleryDetailUrl(mGalleryInfo.gid, mGalleryInfo.token));
|
||||
intent.setDataAndType(uri, mimeType);
|
||||
|
||||
try {
|
||||
@@ -990,7 +991,7 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
|
||||
private void showPageDialog(final int page) {
|
||||
Resources resources = GalleryActivity.this.getResources();
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(GalleryActivity.this);
|
||||
BaseDialogBuilder builder = new BaseDialogBuilder(GalleryActivity.this);
|
||||
builder.setTitle(resources.getString(R.string.page_menu_title, page + 1));
|
||||
|
||||
final CharSequence[] items;
|
||||
@@ -1286,7 +1287,7 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
}
|
||||
|
||||
private void onTapMenuArea() {
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(GalleryActivity.this);
|
||||
BaseDialogBuilder builder = new BaseDialogBuilder(GalleryActivity.this);
|
||||
GalleryMenuHelper helper = new GalleryMenuHelper(builder.getContext());
|
||||
builder.setTitle(R.string.gallery_menu_title)
|
||||
.setView(helper.getView())
|
||||
@@ -1375,4 +1376,6 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -42,9 +42,9 @@ import androidx.annotation.RequiresApi;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.navigation.NavigationView;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.app.EditTextDialogBuilder;
|
||||
import com.hippo.ehviewer.AppConfig;
|
||||
import com.hippo.ehviewer.R;
|
||||
@@ -77,7 +77,7 @@ import com.hippo.scene.SceneFragment;
|
||||
import com.hippo.scene.StageActivity;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.util.BitmapUtils;
|
||||
import com.hippo.util.ClipboardUtil;
|
||||
import com.hippo.util.ClipboardUtilKt;
|
||||
import com.hippo.widget.DrawerView;
|
||||
import com.hippo.yorozuya.IOUtils;
|
||||
import com.hippo.yorozuya.SimpleHandler;
|
||||
@@ -259,7 +259,7 @@ public final class MainActivity extends StageActivity
|
||||
String url = intent.getData().toString();
|
||||
new EditTextDialogBuilder(this, url, "")
|
||||
.setTitle(R.string.error_cannot_parse_the_url)
|
||||
.setPositiveButton(android.R.string.copy, (dialog, which) -> ClipboardUtil.addTextToClipboard(url))
|
||||
.setPositiveButton(android.R.string.copy, (dialog, which) -> ClipboardUtilKt.addTextToClipboard(ClipboardUtilKt.getClipboardManager(this), url, false, () -> null))
|
||||
.show();
|
||||
}
|
||||
}
|
||||
@@ -337,7 +337,7 @@ public final class MainActivity extends StageActivity
|
||||
break;
|
||||
}
|
||||
if (hasUnverified) {
|
||||
new MaterialAlertDialogBuilder(this)
|
||||
new BaseDialogBuilder(this)
|
||||
.setTitle(R.string.app_link_not_verified_title)
|
||||
.setMessage(R.string.app_link_not_verified_message)
|
||||
.setPositiveButton(R.string.open_settings, (dialogInterface, i) -> {
|
||||
@@ -363,7 +363,7 @@ public final class MainActivity extends StageActivity
|
||||
if (null == uniFile || uniFile.ensureDir()) {
|
||||
return;
|
||||
}
|
||||
new MaterialAlertDialogBuilder(this)
|
||||
new BaseDialogBuilder(this)
|
||||
.setTitle(R.string.waring)
|
||||
.setMessage(R.string.invalid_download_location)
|
||||
.setPositiveButton(R.string.get_it, null)
|
||||
@@ -456,7 +456,7 @@ public final class MainActivity extends StageActivity
|
||||
}
|
||||
|
||||
private void checkClipboardUrlInternal() {
|
||||
String text = ClipboardUtil.getUrlFromClipboard();
|
||||
String text = ClipboardUtilKt.getUrlFromClipboard(ClipboardUtilKt.getClipboardManager(this), this);
|
||||
int hashCode = text != null ? text.hashCode() : 0;
|
||||
|
||||
if (text != null && hashCode != 0 && Settings.getClipboardTextHashCode() != hashCode) {
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
package com.hippo.ehviewer.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.biometric.BiometricManager
|
||||
import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
||||
@@ -32,8 +31,8 @@ import com.hippo.ehviewer.EhApplication
|
||||
import com.hippo.ehviewer.R
|
||||
|
||||
class SecurityActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (isAuthenticationSupported(this))
|
||||
startAuthentication(getString(R.string.settings_privacy_require_unlock))
|
||||
else
|
||||
|
||||
@@ -33,7 +33,8 @@ class SettingsActivity : EhActivity() {
|
||||
setSupportActionBar(findViewById(R.id.toolbar))
|
||||
val bar = supportActionBar
|
||||
bar?.setDisplayHomeAsUpEnabled(true)
|
||||
WindowCompat.getInsetsController(window, window.decorView).isAppearanceLightStatusBars = (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_YES) <= 0
|
||||
WindowCompat.getInsetsController(window, window.decorView).isAppearanceLightStatusBars =
|
||||
(resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_YES) <= 0
|
||||
if (savedInstanceState == null) {
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
package com.hippo.ehviewer.ui.fragment;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
@@ -31,13 +33,18 @@ import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.core.os.LocaleListCompat;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.ehviewer.AppConfig;
|
||||
import com.hippo.ehviewer.BuildConfig;
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.EhDB;
|
||||
import com.hippo.ehviewer.GetText;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.ehviewer.client.EhClient;
|
||||
import com.hippo.ehviewer.client.EhRequest;
|
||||
import com.hippo.ehviewer.client.data.FavListUrlBuilder;
|
||||
import com.hippo.ehviewer.client.parser.FavoritesParser;
|
||||
import com.hippo.ehviewer.ui.scene.BaseScene;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.util.IoThreadPoolExecutor;
|
||||
@@ -52,6 +59,7 @@ import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@@ -63,6 +71,7 @@ public class AdvancedFragment extends BasePreferenceFragment {
|
||||
private static final String KEY_IMPORT_DATA = "import_data";
|
||||
private static final String KEY_EXPORT_DATA = "export_data";
|
||||
private static final String KEY_OPEN_BY_DEFAULT = "open_by_default";
|
||||
private static final String KEY_BACKUP_FAVORITE = "backup_favorite";
|
||||
|
||||
ActivityResultLauncher<String> exportLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.CreateDocument(),
|
||||
@@ -76,7 +85,7 @@ public class AdvancedFragment extends BasePreferenceFragment {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
AlertDialog alertDialog = new MaterialAlertDialogBuilder(requireActivity())
|
||||
AlertDialog alertDialog = new BaseDialogBuilder(requireActivity())
|
||||
.setCancelable(false)
|
||||
.setView(R.layout.preference_dialog_task)
|
||||
.show();
|
||||
@@ -193,7 +202,7 @@ public class AdvancedFragment extends BasePreferenceFragment {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
AlertDialog alertDialog = new MaterialAlertDialogBuilder(requireActivity())
|
||||
AlertDialog alertDialog = new BaseDialogBuilder(requireActivity())
|
||||
.setCancelable(false)
|
||||
.setView(R.layout.preference_dialog_task)
|
||||
.show();
|
||||
@@ -232,6 +241,7 @@ public class AdvancedFragment extends BasePreferenceFragment {
|
||||
Preference importData = findPreference(KEY_IMPORT_DATA);
|
||||
Preference exportData = findPreference(KEY_EXPORT_DATA);
|
||||
Preference openByDefault = findPreference(KEY_OPEN_BY_DEFAULT);
|
||||
Preference backupFavorite = findPreference(KEY_BACKUP_FAVORITE);
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
||||
openByDefault.setVisible(false);
|
||||
@@ -243,6 +253,7 @@ public class AdvancedFragment extends BasePreferenceFragment {
|
||||
clearMemoryCache.setOnPreferenceClickListener(this);
|
||||
importData.setOnPreferenceClickListener(this);
|
||||
exportData.setOnPreferenceClickListener(this);
|
||||
backupFavorite.setOnPreferenceClickListener(this);
|
||||
|
||||
appLanguage.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
@@ -289,10 +300,62 @@ public class AdvancedFragment extends BasePreferenceFragment {
|
||||
startActivity(intent);
|
||||
}
|
||||
return true;
|
||||
} else if (KEY_BACKUP_FAVORITE.equals(key)) {
|
||||
try {
|
||||
showTip(R.string.backup_favorite_start, BaseScene.LENGTH_SHORT);
|
||||
backupFavorite();
|
||||
} catch (Exception e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
showTip(R.string.backup_favorite_failed, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void backupFavorite() {
|
||||
AtomicInteger page = new AtomicInteger(0);
|
||||
Context context = requireContext();
|
||||
Activity activity = requireActivity();
|
||||
EhClient mClient = EhApplication.getEhClient(context);
|
||||
FavListUrlBuilder favListUrlBuilder = new FavListUrlBuilder();
|
||||
favListUrlBuilder.setIndex(page.get());
|
||||
|
||||
EhRequest request = new EhRequest();
|
||||
request.setMethod(EhClient.METHOD_GET_FAVORITES);
|
||||
request.setCallback(new EhClient.Callback() {
|
||||
@Override
|
||||
public void onSuccess(Object result) {
|
||||
try {
|
||||
FavoritesParser.Result result1 = (FavoritesParser.Result) result;
|
||||
EhDB.putLocalFavorites(result1.galleryInfoList);
|
||||
Log.d("LocalFavorites", "now backup page " + page.get());
|
||||
if (!result1.galleryInfoList.isEmpty()) {
|
||||
favListUrlBuilder.setIndex(page.incrementAndGet());
|
||||
request.setArgs(favListUrlBuilder.build(), Settings.getShowJpnTitle());
|
||||
mClient.execute(request);
|
||||
} else {
|
||||
showTip(R.string.backup_favorite_success, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
showTip(R.string.backup_favorite_failed, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
showTip(R.string.backup_favorite_failed, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
showTip(R.string.backup_favorite_failed, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
});
|
||||
request.setArgs(favListUrlBuilder.build(), Settings.getShowJpnTitle());
|
||||
mClient.execute(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
String key = preference.getKey();
|
||||
|
||||
@@ -70,7 +70,8 @@ public class BasePreferenceFragment extends PreferenceFragmentCompat
|
||||
.replace(R.id.fragment, classObj)
|
||||
.addToBackStack(null)
|
||||
.commitAllowingStateLoss();
|
||||
} catch (ClassNotFoundException | IllegalAccessException | java.lang.InstantiationException ignored) {
|
||||
} catch (ClassNotFoundException | IllegalAccessException |
|
||||
java.lang.InstantiationException ignored) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.ehviewer.AppConfig;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
@@ -99,7 +99,7 @@ public class DownloadFragment extends BasePreferenceFragment {
|
||||
if (KEY_DOWNLOAD_LOCATION.equals(key)) {
|
||||
UniFile file = Settings.getDownloadLocation();
|
||||
if (file != null && !UniFile.isFileUri(Settings.getDownloadLocation().getUri())) {
|
||||
new MaterialAlertDialogBuilder(requireContext())
|
||||
new BaseDialogBuilder(requireContext())
|
||||
.setTitle(R.string.settings_download_download_location)
|
||||
.setMessage(file.getUri().toString())
|
||||
.setPositiveButton(R.string.pick_new_download_location, (dialogInterface, i) -> openDirPickerL())
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.ui.fragment;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.ehviewer.client.EhTagDatabase;
|
||||
|
||||
public class EhFragment extends BasePreferenceFragment {
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
addPreferencesFromResource(R.xml.eh_settings);
|
||||
|
||||
Preference theme = findPreference(Settings.KEY_THEME);
|
||||
Preference blackDarkTheme = findPreference(Settings.KEY_BLACK_DARK_THEME);
|
||||
Preference gallerySite = findPreference(Settings.KEY_GALLERY_SITE);
|
||||
Preference listMode = findPreference(Settings.KEY_LIST_MODE);
|
||||
Preference listThumbSize = findPreference(Settings.KEY_LIST_THUMB_SIZE);
|
||||
Preference detailSize = findPreference(Settings.KEY_DETAIL_SIZE);
|
||||
Preference thumbSize = findPreference(Settings.KEY_THUMB_SIZE);
|
||||
Preference showTagTranslations = findPreference(Settings.KEY_SHOW_TAG_TRANSLATIONS);
|
||||
Preference tagTranslationsSource = findPreference("tag_translations_source");
|
||||
|
||||
theme.setOnPreferenceChangeListener(this);
|
||||
gallerySite.setOnPreferenceChangeListener(this);
|
||||
listMode.setOnPreferenceChangeListener(this);
|
||||
listThumbSize.setOnPreferenceChangeListener(this);
|
||||
detailSize.setOnPreferenceChangeListener(this);
|
||||
thumbSize.setOnPreferenceChangeListener(this);
|
||||
showTagTranslations.setOnPreferenceChangeListener(this);
|
||||
blackDarkTheme.setOnPreferenceChangeListener(this);
|
||||
|
||||
if (!EhTagDatabase.isPossible(requireActivity())) {
|
||||
getPreferenceScreen().removePreference(showTagTranslations);
|
||||
getPreferenceScreen().removePreference(tagTranslationsSource);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
String key = preference.getKey();
|
||||
if (Settings.KEY_THEME.equals(key)) {
|
||||
AppCompatDelegate.setDefaultNightMode(Integer.parseInt((String) newValue));
|
||||
requireActivity().recreate();
|
||||
return true;
|
||||
} else if (Settings.KEY_GALLERY_SITE.equals(key)) {
|
||||
requireActivity().setResult(Activity.RESULT_OK);
|
||||
return true;
|
||||
} else if (Settings.KEY_LIST_MODE.equals(key)) {
|
||||
requireActivity().setResult(Activity.RESULT_OK);
|
||||
return true;
|
||||
} else if (Settings.KEY_LIST_THUMB_SIZE.equals(key)) {
|
||||
Settings.LIST_THUMB_SIZE_INITED = false;
|
||||
requireActivity().setResult(Activity.RESULT_OK);
|
||||
return true;
|
||||
} else if (Settings.KEY_DETAIL_SIZE.equals(key)) {
|
||||
requireActivity().setResult(Activity.RESULT_OK);
|
||||
} else if (Settings.KEY_THUMB_SIZE.equals(key)) {
|
||||
requireActivity().setResult(Activity.RESULT_OK);
|
||||
} else if (Settings.KEY_SHOW_TAG_TRANSLATIONS.equals(key)) {
|
||||
if (Boolean.TRUE.equals(newValue)) {
|
||||
EhTagDatabase.update(requireActivity());
|
||||
}
|
||||
} else if (Settings.KEY_BLACK_DARK_THEME.equals(key)) {
|
||||
if ((requireActivity().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_YES) > 0) {
|
||||
requireActivity().recreate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFragmentTitle() {
|
||||
return R.string.settings_eh;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.hippo.ehviewer.ui.fragment
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.preference.Preference
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhTagDatabase
|
||||
|
||||
class EhFragment : BasePreferenceFragment() {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.eh_settings)
|
||||
val account = findPreference<Preference>(Settings.KEY_ACCOUNT)
|
||||
val theme = findPreference<Preference>(Settings.KEY_THEME)
|
||||
val blackDarkTheme = findPreference<Preference>(Settings.KEY_BLACK_DARK_THEME)
|
||||
val gallerySite = findPreference<Preference>(Settings.KEY_GALLERY_SITE)
|
||||
val listMode = findPreference<Preference>(Settings.KEY_LIST_MODE)
|
||||
val listThumbSize = findPreference<Preference>(Settings.KEY_LIST_THUMB_SIZE)
|
||||
val detailSize = findPreference<Preference>(Settings.KEY_DETAIL_SIZE)
|
||||
val thumbSize = findPreference<Preference>(Settings.KEY_THUMB_SIZE)
|
||||
val showTagTranslations = findPreference<Preference>(Settings.KEY_SHOW_TAG_TRANSLATIONS)
|
||||
val tagTranslationsSource = findPreference<Preference>("tag_translations_source")
|
||||
Settings.getDisplayName()?.let { account?.summary = it }
|
||||
theme!!.onPreferenceChangeListener = this
|
||||
gallerySite!!.onPreferenceChangeListener = this
|
||||
listMode!!.onPreferenceChangeListener = this
|
||||
listThumbSize!!.onPreferenceChangeListener = this
|
||||
detailSize!!.onPreferenceChangeListener = this
|
||||
thumbSize!!.onPreferenceChangeListener = this
|
||||
showTagTranslations!!.onPreferenceChangeListener = this
|
||||
blackDarkTheme!!.onPreferenceChangeListener = this
|
||||
if (!EhTagDatabase.isPossible(requireActivity())) {
|
||||
preferenceScreen.removePreference(showTagTranslations)
|
||||
preferenceScreen.removePreference(tagTranslationsSource!!)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
|
||||
val key = preference.key
|
||||
if (Settings.KEY_THEME == key) {
|
||||
AppCompatDelegate.setDefaultNightMode((newValue as String).toInt())
|
||||
requireActivity().recreate()
|
||||
return true
|
||||
} else if (Settings.KEY_GALLERY_SITE == key) {
|
||||
requireActivity().setResult(Activity.RESULT_OK)
|
||||
return true
|
||||
} else if (Settings.KEY_LIST_MODE == key) {
|
||||
requireActivity().setResult(Activity.RESULT_OK)
|
||||
return true
|
||||
} else if (Settings.KEY_LIST_THUMB_SIZE == key) {
|
||||
Settings.LIST_THUMB_SIZE_INITED = false
|
||||
requireActivity().setResult(Activity.RESULT_OK)
|
||||
return true
|
||||
} else if (Settings.KEY_DETAIL_SIZE == key) {
|
||||
requireActivity().setResult(Activity.RESULT_OK)
|
||||
} else if (Settings.KEY_THUMB_SIZE == key) {
|
||||
requireActivity().setResult(Activity.RESULT_OK)
|
||||
} else if (Settings.KEY_SHOW_TAG_TRANSLATIONS == key) {
|
||||
if (java.lang.Boolean.TRUE == newValue) {
|
||||
EhTagDatabase.update(requireActivity())
|
||||
}
|
||||
} else if (Settings.KEY_BLACK_DARK_THEME == key) {
|
||||
if (requireActivity().resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_YES > 0) {
|
||||
requireActivity().recreate()
|
||||
}
|
||||
return true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getFragmentTitle(): Int {
|
||||
return R.string.settings_eh
|
||||
}
|
||||
}
|
||||
@@ -31,9 +31,9 @@ import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.checkbox.MaterialCheckBox
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.hippo.app.BaseDialogBuilder
|
||||
import com.hippo.easyrecyclerview.EasyRecyclerView
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.client.EhFilter
|
||||
@@ -112,7 +112,7 @@ class FilterFragment : BaseFragment() {
|
||||
}
|
||||
|
||||
private fun showTipDialog() {
|
||||
MaterialAlertDialogBuilder(requireActivity())
|
||||
BaseDialogBuilder(requireActivity())
|
||||
.setTitle(R.string.filter)
|
||||
.setMessage(R.string.filter_tip)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
@@ -120,7 +120,7 @@ class FilterFragment : BaseFragment() {
|
||||
}
|
||||
|
||||
private fun showAddFilterDialog() {
|
||||
val dialog = MaterialAlertDialogBuilder(requireActivity())
|
||||
val dialog = BaseDialogBuilder(requireActivity())
|
||||
.setTitle(R.string.add_filter)
|
||||
.setView(R.layout.dialog_add_filter)
|
||||
.setPositiveButton(R.string.add, null)
|
||||
@@ -131,7 +131,7 @@ class FilterFragment : BaseFragment() {
|
||||
|
||||
private fun showDeleteFilterDialog(filter: Filter) {
|
||||
val message = getString(R.string.delete_filter, filter.text)
|
||||
MaterialAlertDialogBuilder(requireActivity())
|
||||
BaseDialogBuilder(requireActivity())
|
||||
.setMessage(message)
|
||||
.setPositiveButton(R.string.delete) { _: DialogInterface?, which: Int ->
|
||||
if (DialogInterface.BUTTON_POSITIVE != which) {
|
||||
|
||||
@@ -34,9 +34,9 @@ import androidx.fragment.app.DialogFragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.Hosts;
|
||||
import com.hippo.ehviewer.R;
|
||||
@@ -149,7 +149,8 @@ public class HostsFragment extends BaseFragment
|
||||
ip.setText(arguments.getString(KEY_IP));
|
||||
}
|
||||
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireContext()).setView(view);
|
||||
BaseDialogBuilder builder = new BaseDialogBuilder(requireContext());
|
||||
builder.setView(view);
|
||||
onCreateDialogBuilder(builder);
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.setOnShowListener(d -> onCreateDialog((AlertDialog) d));
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
package com.hippo.ehviewer.ui.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.preference.SeekBarPreference
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
@@ -28,20 +29,45 @@ import com.hippo.ehviewer.ui.SecurityActivity.Companion.isAuthenticationSupporte
|
||||
* Created by Mo10 on 2018/2/10.
|
||||
*/
|
||||
class PrivacyFragment : BasePreferenceFragment() {
|
||||
private lateinit var requireUnlock: SwitchPreferenceCompat
|
||||
private lateinit var unlockDelay: SeekBarPreference
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.privacy_settings)
|
||||
requireUnlock = findPreference("require_unlock")!!
|
||||
unlockDelay = findPreference("require_unlock_delay")!!
|
||||
requireUnlock.setOnPreferenceChangeListener { _, newValue ->
|
||||
unlockDelay.isEnabled = newValue as Boolean
|
||||
setUnlockDelaySummary(unlockDelay.value)
|
||||
true
|
||||
}
|
||||
unlockDelay.setOnPreferenceChangeListener { _, newValue ->
|
||||
setUnlockDelaySummary(newValue as Int)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
if (!isAuthenticationSupported(requireContext())) {
|
||||
Settings.putSecurity(false)
|
||||
findPreference<SwitchPreferenceCompat>("require_unlock")?.isEnabled = false
|
||||
findPreference<SwitchPreferenceCompat>("require_unlock")?.isChecked = false
|
||||
requireUnlock.isEnabled = false
|
||||
requireUnlock.isChecked = false
|
||||
unlockDelay.isEnabled = false
|
||||
} else {
|
||||
unlockDelay.isEnabled = requireUnlock.isChecked == true
|
||||
setUnlockDelaySummary(unlockDelay.value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFragmentTitle(): Int {
|
||||
return R.string.settings_privacy
|
||||
}
|
||||
|
||||
private fun setUnlockDelaySummary(value: Int) {
|
||||
unlockDelay.summary = if (value == 0) {
|
||||
getString(R.string.settings_privacy_require_unlock_delay_summary_immediately)
|
||||
} else {
|
||||
getString(R.string.settings_privacy_require_unlock_delay_summary, value.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,8 @@ import androidx.fragment.app.FragmentActivity;
|
||||
import com.hippo.ehviewer.ui.MainActivity;
|
||||
import com.hippo.scene.SceneFragment;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
public abstract class BaseScene extends SceneFragment {
|
||||
|
||||
public static final int LENGTH_SHORT = 0;
|
||||
@@ -106,11 +108,12 @@ public abstract class BaseScene extends SceneFragment {
|
||||
}
|
||||
}
|
||||
|
||||
public void showTip(@StringRes int id, int length) {
|
||||
public Unit showTip(@StringRes int id, int length) {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity instanceof MainActivity) {
|
||||
((MainActivity) activity).showTip(id, length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean needShowLeftDrawer() {
|
||||
|
||||
@@ -31,14 +31,14 @@ import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.EhCookieStore;
|
||||
import com.hippo.ehviewer.client.EhUrl;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.util.ClipboardUtil;
|
||||
import com.hippo.util.ClipboardUtilKt;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.yorozuya.AssertUtils;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
@@ -217,7 +217,7 @@ public class CookieSignInScene extends SolidScene implements EditText.OnEditorAc
|
||||
hideSoftInput();
|
||||
|
||||
if (!checkIpbMemberId(ipbMemberId) || !(checkIpbPassHash(ipbPassHash))) {
|
||||
new MaterialAlertDialogBuilder(context).setTitle(R.string.waring)
|
||||
new BaseDialogBuilder(context).setTitle(R.string.waring)
|
||||
.setMessage(R.string.wrong_cookie_warning)
|
||||
.setPositiveButton(R.string.i_will_check_it, null)
|
||||
.setNegativeButton(R.string.i_dont_think_so, (dialog, which) -> {
|
||||
@@ -253,7 +253,7 @@ public class CookieSignInScene extends SolidScene implements EditText.OnEditorAc
|
||||
|
||||
private void fillCookiesFromClipboard() {
|
||||
hideSoftInput();
|
||||
String text = ClipboardUtil.getTextFromClipboard();
|
||||
String text = ClipboardUtilKt.getTextFromClipboard(ClipboardUtilKt.getClipboardManager(getContext()), getContext());
|
||||
if (text == null) {
|
||||
showTip(R.string.from_clipboard_error, LENGTH_SHORT);
|
||||
return;
|
||||
|
||||
@@ -51,12 +51,10 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator;
|
||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.app.CheckBoxDialogBuilder;
|
||||
import com.hippo.app.EditTextDialogBuilder;
|
||||
import com.hippo.conaco.DataContainer;
|
||||
import com.hippo.conaco.ProgressNotifier;
|
||||
import com.hippo.easyrecyclerview.EasyRecyclerView;
|
||||
import com.hippo.easyrecyclerview.FastScroller;
|
||||
import com.hippo.easyrecyclerview.HandlerDrawable;
|
||||
@@ -74,9 +72,7 @@ import com.hippo.ehviewer.download.DownloadService;
|
||||
import com.hippo.ehviewer.spider.SpiderDen;
|
||||
import com.hippo.ehviewer.ui.GalleryActivity;
|
||||
import com.hippo.ehviewer.widget.SimpleRatingView;
|
||||
import com.hippo.io.UniFileInputStreamPipe;
|
||||
import com.hippo.scene.Announcer;
|
||||
import com.hippo.streampipe.InputStreamPipe;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.util.IoThreadPoolExecutor;
|
||||
import com.hippo.view.ViewTransition;
|
||||
@@ -85,14 +81,10 @@ import com.hippo.widget.LoadImageView;
|
||||
import com.hippo.widget.recyclerview.AutoStaggeredGridLayoutManager;
|
||||
import com.hippo.yorozuya.AssertUtils;
|
||||
import com.hippo.yorozuya.FileUtils;
|
||||
import com.hippo.yorozuya.IOUtils;
|
||||
import com.hippo.yorozuya.ObjectUtils;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
import com.hippo.yorozuya.collect.LongList;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -425,7 +417,7 @@ public class DownloadsScene extends ToolbarScene
|
||||
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.action_filter) {
|
||||
new MaterialAlertDialogBuilder(requireActivity())
|
||||
new BaseDialogBuilder(requireActivity())
|
||||
.setSingleChoiceItems(R.array.download_state, mType + 1, (dialog, which) -> {
|
||||
mType = which - 1;
|
||||
updateForLabel();
|
||||
@@ -448,7 +440,7 @@ public class DownloadsScene extends ToolbarScene
|
||||
openDrawer(Gravity.RIGHT);
|
||||
return true;
|
||||
} else if (id == R.id.action_reset_reading_progress) {
|
||||
new MaterialAlertDialogBuilder(getContext())
|
||||
new BaseDialogBuilder(getContext())
|
||||
.setMessage(R.string.reset_reading_progress_message)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
@@ -521,7 +513,7 @@ public class DownloadsScene extends ToolbarScene
|
||||
for (int i = 0, n = list.size(); i < n; i++) {
|
||||
items[i + 2] = list.get(i).getLabel();
|
||||
}
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setTitle(R.string.default_download_label)
|
||||
.setItems(items, (dialog1, which) -> {
|
||||
if (which == 0) {
|
||||
@@ -708,7 +700,7 @@ public class DownloadsScene extends ToolbarScene
|
||||
|
||||
MoveDialogHelper helper = new MoveDialogHelper(labels, downloadInfoList);
|
||||
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setTitle(R.string.download_move_dialog_title)
|
||||
.setItems(labels, helper)
|
||||
.show();
|
||||
@@ -885,73 +877,6 @@ public class DownloadsScene extends ToolbarScene
|
||||
}
|
||||
}
|
||||
|
||||
private static class ThumbDataContainer implements DataContainer {
|
||||
|
||||
private final DownloadInfo mInfo;
|
||||
@Nullable
|
||||
private UniFile mFile;
|
||||
|
||||
public ThumbDataContainer(@NonNull DownloadInfo info) {
|
||||
mInfo = info;
|
||||
}
|
||||
|
||||
private void ensureFile() {
|
||||
if (mFile == null) {
|
||||
UniFile dir = SpiderDen.getGalleryDownloadDir(mInfo);
|
||||
if (dir != null && dir.isDirectory()) {
|
||||
mFile = dir.createFile(".thumb");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
ensureFile();
|
||||
return mFile != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUrlMoved(String requestUrl, String responseUrl) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean save(InputStream is, long length, String mediaType, ProgressNotifier notify) {
|
||||
ensureFile();
|
||||
if (mFile == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OutputStream os = null;
|
||||
try {
|
||||
os = mFile.openOutputStream();
|
||||
IOUtils.copy(is, os);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} finally {
|
||||
IOUtils.closeQuietly(os);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStreamPipe get() {
|
||||
ensureFile();
|
||||
if (mFile != null) {
|
||||
return new UniFileInputStreamPipe(mFile);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (mFile != null) {
|
||||
mFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DownloadLabelAdapter extends RecyclerView.Adapter<DownloadLabelHolder> {
|
||||
|
||||
private final LayoutInflater mInflater;
|
||||
@@ -1230,8 +1155,7 @@ public class DownloadsScene extends ToolbarScene
|
||||
return;
|
||||
}
|
||||
DownloadInfo info = mList.get(position);
|
||||
holder.thumb.load(EhCacheKeyFactory.getThumbKey(info.gid), info.thumb,
|
||||
new ThumbDataContainer(info), true);
|
||||
holder.thumb.load(EhCacheKeyFactory.getThumbKey(info.gid), info.thumb, true);
|
||||
holder.title.setText(EhUtils.getSuitableTitle(info));
|
||||
holder.uploader.setText(info.uploader);
|
||||
holder.rating.setRating(info.rating);
|
||||
|
||||
@@ -21,13 +21,10 @@ import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.Display;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -45,9 +42,9 @@ import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.hippo.annotation.Implemented;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.app.EditTextDialogBuilder;
|
||||
import com.hippo.drawable.AddDeleteDrawable;
|
||||
import com.hippo.drawable.DrawerArrowDrawable;
|
||||
@@ -77,7 +74,6 @@ import com.hippo.widget.ContentLayout;
|
||||
import com.hippo.widget.FabLayout;
|
||||
import com.hippo.widget.SearchBarMover;
|
||||
import com.hippo.yorozuya.AssertUtils;
|
||||
import com.hippo.yorozuya.LayoutUtils;
|
||||
import com.hippo.yorozuya.ObjectUtils;
|
||||
import com.hippo.yorozuya.SimpleHandler;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
@@ -402,7 +398,7 @@ public class FavoritesScene extends BaseScene implements
|
||||
items[1] = getString(R.string.local_favorites);
|
||||
String[] favCat = Settings.getFavCat();
|
||||
System.arraycopy(favCat, 0, items, 2, 10);
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setTitle(R.string.default_favorites_collection)
|
||||
.setItems(items, (dialog, which) -> Settings.putDefaultFavSlot(which - 2)).show();
|
||||
return true;
|
||||
@@ -731,7 +727,7 @@ public class FavoritesScene extends BaseScene implements
|
||||
}
|
||||
case 4: { // Delete
|
||||
DeleteDialogHelper helper = new DeleteDialogHelper();
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setTitle(R.string.delete_favorites_dialog_title)
|
||||
.setMessage(getString(R.string.delete_favorites_dialog_message, mModifyGiList.size()))
|
||||
.setPositiveButton(android.R.string.ok, helper)
|
||||
@@ -745,7 +741,7 @@ public class FavoritesScene extends BaseScene implements
|
||||
String[] array = new String[11];
|
||||
array[0] = getString(R.string.local_favorites);
|
||||
System.arraycopy(Settings.getFavCat(), 0, array, 1, 10);
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setTitle(R.string.move_favorites_dialog_title)
|
||||
.setItems(array, helper)
|
||||
.setOnCancelListener(helper)
|
||||
|
||||
@@ -54,8 +54,8 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.easyrecyclerview.EasyRecyclerView;
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.R;
|
||||
@@ -72,7 +72,7 @@ import com.hippo.ehviewer.client.parser.VoteCommentParser;
|
||||
import com.hippo.ehviewer.ui.MainActivity;
|
||||
import com.hippo.scene.SceneFragment;
|
||||
import com.hippo.text.URLImageGetter;
|
||||
import com.hippo.util.ClipboardUtil;
|
||||
import com.hippo.util.ClipboardUtilKt;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.util.ReadableTime;
|
||||
import com.hippo.util.TextUrl;
|
||||
@@ -184,14 +184,7 @@ public final class GalleryCommentsScene extends ToolbarScene
|
||||
mEditPanel,
|
||||
mFabLayout
|
||||
));
|
||||
|
||||
mRefreshLayout.setColorSchemeResources(
|
||||
R.color.loading_indicator_red,
|
||||
R.color.loading_indicator_purple,
|
||||
R.color.loading_indicator_blue,
|
||||
R.color.loading_indicator_cyan,
|
||||
R.color.loading_indicator_green,
|
||||
R.color.loading_indicator_yellow);
|
||||
mRefreshLayout.setColorSchemeColors(ResourcesKt.resolveColor(getTheme(), androidx.appcompat.R.attr.colorPrimary));
|
||||
mRefreshLayout.setOnRefreshListener(this);
|
||||
|
||||
Context context = requireContext();
|
||||
@@ -297,7 +290,7 @@ public final class GalleryCommentsScene extends ToolbarScene
|
||||
}
|
||||
}
|
||||
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context);
|
||||
BaseDialogBuilder builder = new BaseDialogBuilder(context);
|
||||
context = builder.getContext();
|
||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
||||
EasyRecyclerView rv = (EasyRecyclerView) inflater.inflate(R.layout.dialog_recycler_view, null);
|
||||
@@ -354,15 +347,14 @@ public final class GalleryCommentsScene extends ToolbarScene
|
||||
menuId.add(R.id.check_vote_status);
|
||||
}
|
||||
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setItems(menu.toArray(new String[0]), (dialog, which) -> {
|
||||
if (which < 0 || which >= menuId.size()) {
|
||||
return;
|
||||
}
|
||||
int id = menuId.get(which);
|
||||
if (id == R.id.copy) {
|
||||
ClipboardUtil.addTextToClipboard(comment.comment);
|
||||
showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
|
||||
ClipboardUtilKt.addTextToClipboard(ClipboardUtilKt.getClipboardManager(getContext()), comment.comment, false, () -> showTip(R.string.copied_to_clipboard, LENGTH_SHORT));
|
||||
} else if (id == R.id.vote_up) {
|
||||
voteComment(comment.id, 1);
|
||||
} else if (id == R.id.vote_down) {
|
||||
|
||||
@@ -62,9 +62,9 @@ import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.progressindicator.CircularProgressIndicator;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.app.EditTextDialogBuilder;
|
||||
import com.hippo.beerbelly.BeerBelly;
|
||||
import com.hippo.ehviewer.AppConfig;
|
||||
@@ -103,7 +103,7 @@ import com.hippo.scene.Announcer;
|
||||
import com.hippo.scene.SceneFragment;
|
||||
import com.hippo.text.URLImageGetter;
|
||||
import com.hippo.util.AppHelper;
|
||||
import com.hippo.util.ClipboardUtil;
|
||||
import com.hippo.util.ClipboardUtilKt;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.util.ReadableTime;
|
||||
import com.hippo.view.ViewTransition;
|
||||
@@ -260,7 +260,7 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
|
||||
result -> {
|
||||
if (result && mGalleryDetail != null) {
|
||||
TorrentListDialogHelper helper = new TorrentListDialogHelper();
|
||||
Dialog dialog = new MaterialAlertDialogBuilder(requireActivity())
|
||||
Dialog dialog = new BaseDialogBuilder(requireActivity())
|
||||
.setTitle(R.string.torrents)
|
||||
.setView(R.layout.dialog_torrent_list)
|
||||
.setOnDismissListener(helper)
|
||||
@@ -1203,7 +1203,7 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
|
||||
if (EhApplication.getDownloadManager(context).getDownloadState(galleryInfo.gid) == DownloadInfo.STATE_INVALID) {
|
||||
CommonOperations.startDownload(activity, galleryInfo, false);
|
||||
} else {
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setTitle(R.string.download_remove_dialog_title)
|
||||
.setMessage(getString(R.string.download_remove_dialog_message, galleryInfo.title))
|
||||
.setPositiveButton(android.R.string.ok, (dialog1, which1) -> EhApplication.getDownloadManager(context).deleteDownload(galleryInfo.gid))
|
||||
@@ -1229,7 +1229,7 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
|
||||
for (GalleryInfo newerVersion : mGalleryDetail.newerVersions) {
|
||||
titles.add(getString(R.string.newer_version_title, newerVersion.title, newerVersion.posted));
|
||||
}
|
||||
new MaterialAlertDialogBuilder(requireContext())
|
||||
new BaseDialogBuilder(requireContext())
|
||||
.setItems(titles.toArray(new CharSequence[0]), (dialog, which) -> {
|
||||
GalleryInfo newerVersion = mGalleryDetail.newerVersions.get(which);
|
||||
Bundle args = new Bundle();
|
||||
@@ -1275,7 +1275,7 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
|
||||
requestStoragePermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||
} else {
|
||||
TorrentListDialogHelper helper = new TorrentListDialogHelper();
|
||||
Dialog dialog = new MaterialAlertDialogBuilder(context)
|
||||
Dialog dialog = new BaseDialogBuilder(context)
|
||||
.setTitle(R.string.torrents)
|
||||
.setView(R.layout.dialog_torrent_list)
|
||||
.setOnDismissListener(helper)
|
||||
@@ -1292,7 +1292,7 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
|
||||
return;
|
||||
}
|
||||
ArchiveListDialogHelper helper = new ArchiveListDialogHelper();
|
||||
Dialog dialog = new MaterialAlertDialogBuilder(context)
|
||||
Dialog dialog = new BaseDialogBuilder(context)
|
||||
.setTitle(R.string.dialog_archive_title)
|
||||
.setView(R.layout.dialog_archive_list)
|
||||
.setOnDismissListener(helper)
|
||||
@@ -1307,7 +1307,7 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
|
||||
return;
|
||||
}
|
||||
RateDialogHelper helper = new RateDialogHelper();
|
||||
Dialog dialog = new MaterialAlertDialogBuilder(context)
|
||||
Dialog dialog = new BaseDialogBuilder(context)
|
||||
.setTitle(R.string.rate)
|
||||
.setView(R.layout.dialog_rate)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
@@ -1369,7 +1369,7 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
|
||||
return;
|
||||
}
|
||||
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setMessage(getString(R.string.filter_the_uploader, uploader))
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
Filter filter = new Filter();
|
||||
@@ -1389,7 +1389,7 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
|
||||
return;
|
||||
}
|
||||
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setMessage(getString(R.string.filter_the_tag, tag))
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
Filter filter = new Filter();
|
||||
@@ -1438,7 +1438,7 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
|
||||
menuId.add(R.id.vote_down);
|
||||
}
|
||||
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setTitle(tag)
|
||||
.setItems(menu.toArray(new String[0]), (dialog, which) -> {
|
||||
if (which < 0 || which >= menuId.size()) {
|
||||
@@ -1454,11 +1454,9 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
|
||||
} else if (id == R.id.add_filter) {
|
||||
showFilterTagDialog(tag);
|
||||
} else if (id == R.id.copy) {
|
||||
ClipboardUtil.addTextToClipboard(tag);
|
||||
showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
|
||||
ClipboardUtilKt.addTextToClipboard(ClipboardUtilKt.getClipboardManager(getContext()), tag, false, () -> showTip(R.string.copied_to_clipboard, LENGTH_SHORT));
|
||||
} else if (id == R.id.copy_trans) {
|
||||
ClipboardUtil.addTextToClipboard(tv.getText().toString());
|
||||
showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
|
||||
ClipboardUtilKt.addTextToClipboard(ClipboardUtilKt.getClipboardManager(getContext()), tv.getText().toString(), false, () -> showTip(R.string.copied_to_clipboard, LENGTH_SHORT));
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import com.hippo.ehviewer.UrlOpener;
|
||||
import com.hippo.ehviewer.client.EhUrl;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.ehviewer.client.data.GalleryDetail;
|
||||
import com.hippo.util.ClipboardUtil;
|
||||
import com.hippo.util.ClipboardUtilKt;
|
||||
import com.hippo.yorozuya.AssertUtils;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
@@ -188,14 +188,11 @@ public final class GalleryInfoScene extends ToolbarScene {
|
||||
if (position == INDEX_PARENT) {
|
||||
UrlOpener.openUrl(context, mValues.get(position), true);
|
||||
} else {
|
||||
ClipboardUtil.addTextToClipboard(mValues.get(position));
|
||||
|
||||
ClipboardUtilKt.addTextToClipboard(ClipboardUtilKt.getClipboardManager(getContext()), mValues.get(position), false, () -> showTip(R.string.copied_to_clipboard, LENGTH_SHORT));
|
||||
if (position == INDEX_URL) {
|
||||
// Save it to avoid detect the gallery
|
||||
Settings.putClipboardTextHashCode(mValues.get(position).hashCode());
|
||||
}
|
||||
|
||||
showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -55,8 +55,8 @@ import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.app.EditTextDialogBuilder;
|
||||
import com.hippo.drawable.AddDeleteDrawable;
|
||||
import com.hippo.drawable.DrawerArrowDrawable;
|
||||
@@ -215,7 +215,7 @@ public final class GalleryListScene extends BaseScene
|
||||
}
|
||||
};
|
||||
// Double click back exit
|
||||
private long mPressBackTime = 0;
|
||||
private final long mPressBackTime = 0;
|
||||
private boolean mHasFirstRefresh = false;
|
||||
private int mNavCheckedId = 0;
|
||||
private DownloadManager mDownloadManager;
|
||||
@@ -663,7 +663,7 @@ public final class GalleryListScene extends BaseScene
|
||||
if (null == context) {
|
||||
return;
|
||||
}
|
||||
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context);
|
||||
final BaseDialogBuilder builder = new BaseDialogBuilder(context);
|
||||
builder.setMessage(R.string.add_quick_search_tip);
|
||||
builder.setTitle(R.string.readme);
|
||||
builder.show();
|
||||
@@ -950,7 +950,7 @@ public final class GalleryListScene extends BaseScene
|
||||
favourited ? R.drawable.v_heart_broken_x24 : R.drawable.v_heart_x24,
|
||||
};
|
||||
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setTitle(EhUtils.getSuitableTitle(gi))
|
||||
.setAdapter(new SelectItemWithIconAdapter(context, items, icons), (dialog, which) -> {
|
||||
switch (which) {
|
||||
@@ -962,7 +962,7 @@ public final class GalleryListScene extends BaseScene
|
||||
break;
|
||||
case 1: // Download
|
||||
if (downloaded) {
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setTitle(R.string.download_remove_dialog_title)
|
||||
.setMessage(getString(R.string.download_remove_dialog_message, gi.title))
|
||||
.setPositiveButton(android.R.string.ok, (dialog1, which1) -> mDownloadManager.deleteDownload(gi.gid))
|
||||
@@ -989,7 +989,7 @@ public final class GalleryListScene extends BaseScene
|
||||
|
||||
MoveDialogHelper helper = new MoveDialogHelper(labels, gi);
|
||||
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setTitle(R.string.download_move_dialog_title)
|
||||
.setItems(labels, helper)
|
||||
.show();
|
||||
|
||||
@@ -35,8 +35,8 @@ import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.slider.Slider;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.easyrecyclerview.EasyRecyclerView;
|
||||
import com.hippo.easyrecyclerview.MarginItemDecoration;
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
@@ -211,7 +211,7 @@ public class GalleryPreviewsScene extends ToolbarScene {
|
||||
int pages = mHelper.getPages();
|
||||
if (pages > 1 && mHelper.canGoTo()) {
|
||||
GoToDialogHelper helper = new GoToDialogHelper(pages, mHelper.getPageForTop());
|
||||
AlertDialog dialog = new MaterialAlertDialogBuilder(context).setTitle(R.string.go_to)
|
||||
AlertDialog dialog = new BaseDialogBuilder(context).setTitle(R.string.go_to)
|
||||
.setView(R.layout.dialog_go_to)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.create();
|
||||
|
||||
@@ -35,7 +35,7 @@ import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.hippo.app.BaseDialogBuilder
|
||||
import com.hippo.easyrecyclerview.EasyRecyclerView
|
||||
import com.hippo.easyrecyclerview.FastScroller
|
||||
import com.hippo.easyrecyclerview.HandlerDrawable
|
||||
@@ -200,7 +200,7 @@ class HistoryScene : ToolbarScene() {
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun showClearAllDialog() {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
BaseDialogBuilder(requireContext())
|
||||
.setMessage(R.string.clear_all_history)
|
||||
.setPositiveButton(R.string.clear_all) { _: DialogInterface?, which: Int ->
|
||||
if (DialogInterface.BUTTON_POSITIVE != which || null == mAdapter) {
|
||||
@@ -260,7 +260,7 @@ class HistoryScene : ToolbarScene() {
|
||||
R.drawable.v_download_x24,
|
||||
if (favourited) R.drawable.v_heart_broken_x24 else R.drawable.v_heart_x24,
|
||||
)
|
||||
MaterialAlertDialogBuilder(context)
|
||||
BaseDialogBuilder(context)
|
||||
.setTitle(EhUtils.getSuitableTitle(gi))
|
||||
.setAdapter(
|
||||
SelectItemWithIconAdapter(
|
||||
@@ -277,7 +277,7 @@ class HistoryScene : ToolbarScene() {
|
||||
startActivity(intent)
|
||||
}
|
||||
1 -> if (downloaded) {
|
||||
MaterialAlertDialogBuilder(context)
|
||||
BaseDialogBuilder(context)
|
||||
.setTitle(R.string.download_remove_dialog_title)
|
||||
.setMessage(
|
||||
getString(
|
||||
@@ -319,7 +319,7 @@ class HistoryScene : ToolbarScene() {
|
||||
}
|
||||
val labels = labelList.toTypedArray()
|
||||
val helper = MoveDialogHelper(labels, gi)
|
||||
MaterialAlertDialogBuilder(context)
|
||||
BaseDialogBuilder(context)
|
||||
.setTitle(R.string.download_move_dialog_title)
|
||||
.setItems(labels, helper)
|
||||
.show()
|
||||
|
||||
@@ -30,8 +30,8 @@ import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
@@ -333,7 +333,7 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
|
||||
return;
|
||||
}
|
||||
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setTitle(R.string.sign_in_failed)
|
||||
.setMessage(ExceptionUtils.getReadableString(e) + "\n\n" + getString(R.string.sign_in_failed_tip))
|
||||
.setPositiveButton(R.string.get_it, null)
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.scene.Announcer;
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,7 +26,7 @@ import android.webkit.WebView;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
public class DialogWebChromeClient extends WebChromeClient {
|
||||
@@ -39,7 +39,7 @@ public class DialogWebChromeClient extends WebChromeClient {
|
||||
|
||||
@Override
|
||||
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
|
||||
new MaterialAlertDialogBuilder(view.getContext())
|
||||
new BaseDialogBuilder(view.getContext())
|
||||
.setMessage(message)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> result.confirm())
|
||||
.setOnCancelListener(dialog -> result.cancel())
|
||||
@@ -49,7 +49,7 @@ public class DialogWebChromeClient extends WebChromeClient {
|
||||
|
||||
@Override
|
||||
public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
|
||||
new MaterialAlertDialogBuilder(view.getContext())
|
||||
new BaseDialogBuilder(view.getContext())
|
||||
.setMessage(message)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> result.confirm())
|
||||
.setNegativeButton(android.R.string.cancel, (dialog, which) -> result.cancel())
|
||||
@@ -67,7 +67,7 @@ public class DialogWebChromeClient extends WebChromeClient {
|
||||
final EditText valueView = promptView.findViewById(R.id.value);
|
||||
valueView.setText(defaultValue);
|
||||
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
new BaseDialogBuilder(context)
|
||||
.setView(promptView)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> result.confirm(valueView.getText().toString()))
|
||||
.setOnCancelListener(dialog -> result.cancel())
|
||||
|
||||
@@ -46,7 +46,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.card.MaterialCardView;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.easyrecyclerview.EasyRecyclerView;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.EhTagDatabase;
|
||||
@@ -668,7 +668,7 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener,
|
||||
|
||||
@Override
|
||||
public boolean onLongClick() {
|
||||
new MaterialAlertDialogBuilder(getContext())
|
||||
new BaseDialogBuilder(getContext())
|
||||
.setMessage(getContext().getString(R.string.delete_search_history, mKeyword))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.delete, (dialog, which) -> {
|
||||
|
||||
@@ -34,9 +34,9 @@ import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.chip.ChipGroup
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
|
||||
import com.hippo.app.BaseDialogBuilder
|
||||
import com.hippo.easyrecyclerview.EasyRecyclerView
|
||||
import com.hippo.easyrecyclerview.MarginItemDecoration
|
||||
import com.hippo.easyrecyclerview.SimpleHolder
|
||||
@@ -217,7 +217,7 @@ class SearchLayout @JvmOverloads constructor(
|
||||
|
||||
override fun onClick(v: View) {
|
||||
if (mNormalSearchModeHelp === v) {
|
||||
MaterialAlertDialogBuilder(context)
|
||||
BaseDialogBuilder(context)
|
||||
.setMessage(R.string.search_tip)
|
||||
.show()
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.graphics.Bitmap;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.hippo.Native;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -64,7 +66,7 @@ public final class Image {
|
||||
*/
|
||||
@Nullable
|
||||
public static Image decode(FileDescriptor fd, boolean partially) {
|
||||
return newFromAddr(nativeDecode(fd));
|
||||
return newFromAddr(nativeDecode(Native.getFd(fd)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,7 +74,7 @@ public final class Image {
|
||||
*/
|
||||
@Nullable
|
||||
public static Image decode(Integer fd, boolean partially) {
|
||||
return newFromAddr(nativeDecodeFdInt(fd));
|
||||
return newFromAddr(nativeDecode(fd));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,9 +101,7 @@ public final class Image {
|
||||
return imageList.size();
|
||||
}
|
||||
|
||||
private static native long nativeDecode(FileDescriptor fd);
|
||||
|
||||
private static native long nativeDecodeFdInt(int fd);
|
||||
private static native long nativeDecode(int fd);
|
||||
|
||||
private static native long nativeDecodeAddr(long addr);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.hippo.app.BaseDialogBuilder;
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
/**
|
||||
@@ -255,7 +255,7 @@ public abstract class DialogPreference extends Preference implements
|
||||
|
||||
mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
|
||||
|
||||
mBuilder = new MaterialAlertDialogBuilder(context)
|
||||
mBuilder = new BaseDialogBuilder(context)
|
||||
.setTitle(mDialogTitle)
|
||||
.setIcon(mDialogIcon)
|
||||
.setPositiveButton(mPositiveButtonText, this)
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.text;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Html;
|
||||
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.drawable.UnikeryDrawable;
|
||||
import com.hippo.image.ImageBitmap;
|
||||
import com.hippo.widget.ObservedTextView;
|
||||
|
||||
public class URLImageGetter implements Html.ImageGetter {
|
||||
|
||||
private final ObservedTextView mTextView;
|
||||
private final Conaco<ImageBitmap> mConaco;
|
||||
|
||||
public URLImageGetter(ObservedTextView textView, Conaco<ImageBitmap> conaco) {
|
||||
mTextView = textView;
|
||||
mConaco = conaco;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable getDrawable(String source) {
|
||||
UnikeryDrawable drawable = new UnikeryDrawable(mTextView, mConaco);
|
||||
drawable.load(source);
|
||||
return drawable;
|
||||
}
|
||||
}
|
||||
+16
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
* Copyright 2015 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,15 +13,20 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.hippo.text
|
||||
|
||||
package com.hippo.scene;
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.text.Html.ImageGetter
|
||||
import com.hippo.conaco.Conaco
|
||||
import com.hippo.drawable.UnikeryDrawable
|
||||
import com.hippo.image.ImageBitmap
|
||||
import com.hippo.widget.ObservedTextView
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
public interface TransitionHelper {
|
||||
|
||||
boolean onTransition(Context context, FragmentTransaction transaction, Fragment exit, Fragment enter);
|
||||
}
|
||||
class URLImageGetter(
|
||||
private val mTextView: ObservedTextView,
|
||||
private val mConaco: Conaco<ImageBitmap>
|
||||
) : ImageGetter {
|
||||
override fun getDrawable(source: String): Drawable {
|
||||
return UnikeryDrawable(mTextView, mConaco).apply { load(source) }
|
||||
}
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 Tarsin Norbin
|
||||
*
|
||||
* This file is part of EhViewer
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* EhViewer is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with EhViewer.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.hippo.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipDescription;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.textclassifier.TextClassifier;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class ClipboardUtil {
|
||||
private static final String TAG = "ClipboardUtil";
|
||||
@Nullable
|
||||
private static ClipboardManager clipboardManager;
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private static Context sContext;
|
||||
|
||||
public static void initialize(Context context) {
|
||||
sContext = context;
|
||||
clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if (clipboardManager == null) {
|
||||
Log.e(TAG, "This device has no clipboard!");
|
||||
}
|
||||
}
|
||||
|
||||
public static void addTextToClipboard(String text) {
|
||||
if (clipboardManager != null) {
|
||||
try {
|
||||
clipboardManager.setPrimaryClip(ClipData.newPlainText(null, text));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTextFromClipboard() {
|
||||
if (clipboardManager != null) {
|
||||
try {
|
||||
if (!clipboardManager.hasPrimaryClip()) {
|
||||
return null;
|
||||
}
|
||||
ClipData primaryClip = clipboardManager.getPrimaryClip();
|
||||
if (primaryClip == null) {
|
||||
return null;
|
||||
}
|
||||
ClipData.Item item = primaryClip.getItemAt(0);
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
String string = String.valueOf(item.coerceToText(sContext));
|
||||
if (!TextUtils.isEmpty(string)) {
|
||||
return string;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getUrlFromClipboard() {
|
||||
if (clipboardManager != null) {
|
||||
try {
|
||||
if (!clipboardManager.hasPrimaryClip()) {
|
||||
return null;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
ClipDescription primaryClipDescription = clipboardManager.getPrimaryClipDescription();
|
||||
if (primaryClipDescription != null) {
|
||||
if (primaryClipDescription.getClassificationStatus() == ClipDescription.CLASSIFICATION_COMPLETE) {
|
||||
if (primaryClipDescription.getConfidenceScore(TextClassifier.TYPE_URL) <= 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ClipData primaryClip = clipboardManager.getPrimaryClip();
|
||||
if (primaryClip == null) {
|
||||
return null;
|
||||
}
|
||||
ClipData.Item item = primaryClip.getItemAt(0);
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
String string = String.valueOf(item.coerceToText(sContext));
|
||||
if (!TextUtils.isEmpty(string)) {
|
||||
return string;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2022 Tarsin Norbin
|
||||
*
|
||||
* This file is part of EhViewer
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* EhViewer is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with EhViewer.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.hippo.util
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipDescription
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.PersistableBundle
|
||||
import android.text.TextUtils
|
||||
import android.view.textclassifier.TextClassifier
|
||||
|
||||
fun Context.getClipboardManager(): ClipboardManager {
|
||||
return getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
}
|
||||
|
||||
fun ClipboardManager.addTextToClipboard(text: String?, isSensitive: Boolean, showTip: () -> Unit) {
|
||||
setPrimaryClip(ClipData.newPlainText(null, text).apply {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && isSensitive)
|
||||
description.extras = PersistableBundle().apply {
|
||||
putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true)
|
||||
}
|
||||
})
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU)
|
||||
showTip()
|
||||
}
|
||||
|
||||
fun ClipboardManager.getTextFromClipboard(context: Context): String? {
|
||||
val item = primaryClip?.getItemAt(0)
|
||||
val string = item?.coerceToText(context).toString()
|
||||
return if (!TextUtils.isEmpty(string)) string else null
|
||||
}
|
||||
|
||||
fun ClipboardManager.getUrlFromClipboard(context: Context): String? {
|
||||
if (primaryClipDescription?.classificationStatus == ClipDescription.CLASSIFICATION_COMPLETE) {
|
||||
if ((primaryClipDescription?.getConfidenceScore(TextClassifier.TYPE_URL)
|
||||
?.let { it <= 0 }) == true
|
||||
) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
val item = primaryClip?.getItemAt(0)
|
||||
val string = item?.coerceToText(context).toString()
|
||||
return if (!TextUtils.isEmpty(string)) string else null
|
||||
}
|
||||
@@ -102,27 +102,11 @@ public class ContentLayout extends FrameLayout {
|
||||
mFastScroller = mContentView.findViewById(R.id.fast_scroller);
|
||||
mRecyclerView = mRefreshLayout.findViewById(R.id.recycler_view);
|
||||
|
||||
mRefreshLayout.setColorSchemeColors(ResourcesKt.resolveColor(context.getTheme(), androidx.appcompat.R.attr.colorPrimary));
|
||||
mFastScroller.attachToRecyclerView(mRecyclerView);
|
||||
HandlerDrawable drawable = new HandlerDrawable();
|
||||
drawable.setColor(ResourcesKt.resolveColor(context.getTheme(), androidx.appcompat.R.attr.colorPrimary));
|
||||
mFastScroller.setHandlerDrawable(drawable);
|
||||
|
||||
mRefreshLayout.setColorSchemeResources(
|
||||
R.color.loading_indicator_red,
|
||||
R.color.loading_indicator_purple,
|
||||
R.color.loading_indicator_blue,
|
||||
R.color.loading_indicator_cyan,
|
||||
R.color.loading_indicator_green,
|
||||
R.color.loading_indicator_yellow);
|
||||
|
||||
Resources resources = getResources();
|
||||
mBottomProgress.setIndicatorColor(
|
||||
resources.getColor(R.color.loading_indicator_red),
|
||||
resources.getColor(R.color.loading_indicator_blue),
|
||||
resources.getColor(R.color.loading_indicator_green),
|
||||
resources.getColor(R.color.loading_indicator_orange));
|
||||
mBottomProgress.setIndeterminateAnimationType(LinearProgressIndicator.INDETERMINATE_ANIMATION_TYPE_CONTIGUOUS);
|
||||
|
||||
mRecyclerViewOriginBottom = mRecyclerView.getPaddingBottom();
|
||||
mFastScrollerOriginBottom = mFastScroller.getPaddingBottom();
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.conaco.ConacoTask;
|
||||
import com.hippo.conaco.DataContainer;
|
||||
import com.hippo.conaco.Unikery;
|
||||
import com.hippo.drawable.PreciselyClipDrawable;
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
@@ -56,7 +55,6 @@ public class LoadImageView extends FixedAspectImageView implements Unikery<Image
|
||||
private Conaco<ImageBitmap> mConaco;
|
||||
private String mKey;
|
||||
private String mUrl;
|
||||
private DataContainer mContainer;
|
||||
private boolean mUseNetwork;
|
||||
private int mOffsetX = Integer.MIN_VALUE;
|
||||
private int mOffsetY = Integer.MIN_VALUE;
|
||||
@@ -109,7 +107,7 @@ public class LoadImageView extends FixedAspectImageView implements Unikery<Image
|
||||
if (mFailed) {
|
||||
onFailure();
|
||||
} else if (mConaco.isLoading(this)) {
|
||||
load(mKey, mUrl, mContainer, mUseNetwork);
|
||||
load(mKey, mUrl, mUseNetwork);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,15 +207,11 @@ public class LoadImageView extends FixedAspectImageView implements Unikery<Image
|
||||
}
|
||||
|
||||
public void load(String key, String url) {
|
||||
load(key, url, null, true);
|
||||
load(key, url, true);
|
||||
}
|
||||
|
||||
public void load(String key, String url, boolean useNetwork) {
|
||||
load(key, url, null, useNetwork);
|
||||
}
|
||||
|
||||
public void load(String key, String url, DataContainer container, boolean useNetwork) {
|
||||
if (url == null || (key == null && container == null)) {
|
||||
if (url == null || (key == null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -226,14 +220,12 @@ public class LoadImageView extends FixedAspectImageView implements Unikery<Image
|
||||
|
||||
mKey = key;
|
||||
mUrl = url;
|
||||
mContainer = container;
|
||||
mUseNetwork = useNetwork;
|
||||
|
||||
ConacoTask.Builder<ImageBitmap> builder = new ConacoTask.Builder<ImageBitmap>()
|
||||
.setUnikery(this)
|
||||
.setKey(key)
|
||||
.setUrl(url)
|
||||
.setDataContainer(container)
|
||||
.setUseNetwork(useNetwork);
|
||||
mConaco.load(builder);
|
||||
}
|
||||
@@ -255,7 +247,6 @@ public class LoadImageView extends FixedAspectImageView implements Unikery<Image
|
||||
mConaco.cancel(this);
|
||||
mKey = null;
|
||||
mUrl = null;
|
||||
mContainer = null;
|
||||
clearDrawable();
|
||||
}
|
||||
|
||||
@@ -326,7 +317,6 @@ public class LoadImageView extends FixedAspectImageView implements Unikery<Image
|
||||
// Can't retry, so release
|
||||
mKey = null;
|
||||
mUrl = null;
|
||||
mContainer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,12 +353,12 @@ public class LoadImageView extends FixedAspectImageView implements Unikery<Image
|
||||
|
||||
@Override
|
||||
public void onClick(@NonNull View v) {
|
||||
load(mKey, mUrl, mContainer, true);
|
||||
load(mKey, mUrl, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(@NonNull View v) {
|
||||
load(mKey, mUrl, mContainer, true);
|
||||
load(mKey, mUrl, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/language"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
style="@style/TextAppearance.Material3.LabelMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
@@ -115,7 +115,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/size"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
style="@style/TextAppearance.Material3.LabelMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
@@ -129,7 +129,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/favoredTimes"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
style="@style/TextAppearance.Material3.LabelMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
@@ -140,7 +140,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pages"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
style="@style/TextAppearance.Material3.LabelMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
@@ -154,7 +154,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/posted"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
style="@style/TextAppearance.Material3.LabelMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
|
||||
@@ -29,12 +29,20 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.hippo.ehviewer.widget.ResizeableFixedThumb
|
||||
android:id="@+id/thumb"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:alwaysCutAndScale="true"
|
||||
app:retryType="longClick" />
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/thumb_card"
|
||||
style="@style/Widget.Material3.CardView.Filled"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.hippo.ehviewer.widget.ResizeableFixedThumb
|
||||
android:id="@+id/thumb"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:alwaysCutAndScale="true"
|
||||
app:retryType="longClick"/>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
@@ -45,7 +53,7 @@
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_toEndOf="@id/thumb" />
|
||||
android:layout_toEndOf="@id/thumb_card" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/uploader"
|
||||
@@ -70,7 +78,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignStart="@id/title"
|
||||
android:layout_alignBottom="@id/thumb"
|
||||
android:layout_alignBottom="@id/thumb_card"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingTop="2dp"
|
||||
@@ -83,7 +91,7 @@
|
||||
android:id="@+id/actions"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@+id/thumb"
|
||||
android:layout_alignBottom="@+id/thumb_card"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
|
||||
@@ -35,12 +35,14 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/user"
|
||||
style="@style/TextAppearance.Material3.TitleSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
style="@style/TextAppearance.Material3.TitleSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true" />
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
android:layout_gravity="bottom"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"
|
||||
app:fitsSystemWindowsInsets="end"
|
||||
app:hideAnimationBehavior="inward"
|
||||
app:showAnimationBehavior="outward" />
|
||||
|
||||
|
||||
@@ -15,10 +15,6 @@
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<!-- divider -->
|
||||
<color name="divider">#20ffffff</color>
|
||||
|
||||
<color name="navigation_bar_divider">#1fffffff</color>
|
||||
|
||||
<!-- Lock pattern view -->
|
||||
</resources>
|
||||
@@ -391,7 +391,7 @@
|
||||
<string name="hosts">自定义 hosts.txt</string>
|
||||
<string name="hosts_tip">hosts.txt</string>
|
||||
<string name="hosts_host">Host</string>
|
||||
<string name="hosts_ip">IP1(+IP2+IP3...)</string>
|
||||
<string name="hosts_ip">IP1(+IP2+IP3…)</string>
|
||||
<string name="add_host">添加 host</string>
|
||||
<string name="add_host_add">添加</string>
|
||||
<string name="edit_host">编辑 host</string>
|
||||
@@ -421,8 +421,8 @@
|
||||
<string name="settings_eh_identity_cookies">身份 Cookie</string>
|
||||
<string name="settings_eh_identity_cookies_summary">可用于登录</string>
|
||||
<string name="settings_eh_identity_cookies_signed">身份 Cookie 可用于登录该账号。<br><b>注意数据安全</b><br><br>%s</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">未登录</string>
|
||||
<string name="settings_eh_identity_cookies_copy">复制</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">游客模式</string>
|
||||
<string name="settings_eh_identity_cookies_copy">复制 Cookies</string>
|
||||
<string name="settings_u_config">EHentai 设置</string>
|
||||
<string name="settings_u_config_summary">EHentai 网站上的设置</string>
|
||||
<string name="settings_my_tags">我的标签</string>
|
||||
@@ -761,6 +761,9 @@
|
||||
|
||||
<string name="show_library_version">依赖库之版本</string>
|
||||
<string name="settings_privacy_require_unlock">需要解锁</string>
|
||||
<string name="settings_privacy_require_unlock_delay">锁定延迟</string>
|
||||
<string name="settings_privacy_require_unlock_delay_summary">离开应用并在 %s 分钟内返回时不需要解锁</string>
|
||||
<string name="settings_privacy_require_unlock_delay_summary_immediately">无论何时回到应用均要求解锁</string>
|
||||
<string name="proxy_type_name">代理类型</string>
|
||||
<string name="filter_label">屏蔽项类型</string>
|
||||
|
||||
@@ -769,4 +772,10 @@
|
||||
<string name="passwd_wrong">密码错误</string>
|
||||
<string name="passwd_cannot_be_empty">密码不能为空</string>
|
||||
<string name="list_tile_thumb_size">详情模式下缩略图大小</string>
|
||||
<string name="backup_favorite">备份收藏列表</string>
|
||||
<string name="backup_favorite_summary">备份云端收藏列表到本地</string>
|
||||
<string name="backup_favorite_failed">备份收藏列表失败</string>
|
||||
<string name="backup_favorite_success">备份收藏列表成功</string>
|
||||
<string name="backup_favorite_start">正在备份收藏列表</string>
|
||||
<string name="account_name">账户</string>
|
||||
</resources>
|
||||
@@ -391,7 +391,7 @@
|
||||
<string name="hosts">自訂hosts.txt</string>
|
||||
<string name="hosts_tip">hosts.txt</string>
|
||||
<string name="hosts_host">Host</string>
|
||||
<string name="hosts_ip">IP1(+IP2+IP3...)</string>
|
||||
<string name="hosts_ip">IP1(+IP2+IP3…)</string>
|
||||
<string name="add_host">加入 host</string>
|
||||
<string name="add_host_add">加入</string>
|
||||
<string name="edit_host">編輯 host</string>
|
||||
@@ -421,8 +421,8 @@
|
||||
<string name="settings_eh_identity_cookies">身份識別 Cookie</string>
|
||||
<string name="settings_eh_identity_cookies_summary">可用於登入</string>
|
||||
<string name="settings_eh_identity_cookies_signed">身份 Cookie 可用於登入該帳號。<br><b>請注意資料安全</b><br><br>%s</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">未登入</string>
|
||||
<string name="settings_eh_identity_cookies_copy">複製</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">訪客模式</string>
|
||||
<string name="settings_eh_identity_cookies_copy">複製 Cookies</string>
|
||||
<string name="settings_u_config">EHentai 設定</string>
|
||||
<string name="settings_u_config_summary">EHentai 網站上的設定</string>
|
||||
<string name="settings_my_tags">我的標籤</string>
|
||||
@@ -735,7 +735,7 @@
|
||||
<string name="delete_search_history">從搜索記錄中刪除“%s”?</string>
|
||||
<string name="settings_advanced_dns_over_http_title">安全 DNS(DoH)</string>
|
||||
<string name="settings_advanced_dns_over_http_summary">解決某些地區的 DNS 汙染問題</string>
|
||||
<string name="settings_advanced_domain_fronting_title">域名前置</string>
|
||||
<string name="settings_advanced_domain_fronting_title">域名前綴</string>
|
||||
<string name="settings_advanced_domain_fronting_summary">繞過 SNI 封鎖</string>
|
||||
<string name="read_theme">色彩主題</string>
|
||||
<string name="follow_app">跟隨應用</string>
|
||||
@@ -754,19 +754,27 @@
|
||||
<string name="reset_download_location">恢復預設路徑</string>
|
||||
<string name="pick_new_download_location">選擇新路徑</string>
|
||||
<string name="dont_show_again">不再顯示</string>
|
||||
<string name="open_settings">打開設置</string>
|
||||
<string name="open_settings">打開設定</string>
|
||||
<string name="app_link_not_verified_message">對於 Android 12 及更新的版本,您需要手動增加連結到已驗證連結才能在 EhViewer 中打開 E-Hentai 連結。</string>
|
||||
<string name="app_link_not_verified_title">應用連結未驗證</string>
|
||||
<string name="open_by_default">預設打開</string>
|
||||
|
||||
<string name="show_library_version">依賴庫之版本</string>
|
||||
<string name="settings_privacy_require_unlock">需要解鎖</string>
|
||||
<string name="settings_privacy_require_unlock_delay">鎖定延遲</string>
|
||||
<string name="settings_privacy_require_unlock_delay_summary">離開程式並在 %s 分鐘內返回時不需要解鎖</string>
|
||||
<string name="settings_privacy_require_unlock_delay_summary_immediately">無論何時回到程式均要求解鎖</string>
|
||||
<string name="proxy_type_name">代理類型</string>
|
||||
<string name="filter_label">屏蔽項類型</string>
|
||||
<string name="filter_label">隱藏項類型</string>
|
||||
|
||||
<string name="archive_passwd">歸檔文件密碼</string>
|
||||
<string name="archive_need_passwd">歸檔文件需要密碼</string>
|
||||
<string name="archive_passwd">封存文件密碼</string>
|
||||
<string name="archive_need_passwd">封存文件需要密碼</string>
|
||||
<string name="passwd_wrong">密碼錯誤</string>
|
||||
<string name="passwd_cannot_be_empty">密碼不能為空</string>
|
||||
|
||||
<string name="list_tile_thumb_size">詳情模式下縮圖大小</string>
|
||||
<string name="backup_favorite">備份收藏列表</string>
|
||||
<string name="backup_favorite_summary">備份雲端收藏列表到本機</string>
|
||||
<string name="backup_favorite_failed">備份收藏列表失敗</string>
|
||||
<string name="backup_favorite_success">備份收藏列表成功</string>
|
||||
<string name="backup_favorite_start">正在備份收藏列表</string>
|
||||
</resources>
|
||||
@@ -18,43 +18,10 @@
|
||||
<color name="primary_drawable_black">#ccffffff</color>
|
||||
<color name="secondary_drawable_black">#3dffffff</color>
|
||||
<color name="red_500">#fff44336</color>
|
||||
<color name="purple_a700">#ffaa00ff</color>
|
||||
<color name="cyan_600">#ff00acc1</color>
|
||||
<color name="light_green_600">#ff7cb342</color>
|
||||
<color name="yellow_800">#fff9a825</color>
|
||||
<color name="deep_orange_400">#ffff7043</color>
|
||||
<color name="brown_500">#ff795548</color>
|
||||
<color name="loading_indicator_red">#ffe53935</color>
|
||||
<color name="loading_indicator_purple">@color/purple_a700</color>
|
||||
<color name="loading_indicator_blue">#ff1d87e4</color>
|
||||
<color name="loading_indicator_cyan">@color/cyan_600</color>
|
||||
<color name="loading_indicator_green">@color/light_green_600</color>
|
||||
<color name="loading_indicator_yellow">@color/yellow_800</color>
|
||||
<color name="loading_indicator_orange">@color/deep_orange_400</color>
|
||||
|
||||
<color name="navigation_bar_divider">#1f000000</color>
|
||||
|
||||
<!-- Red -->
|
||||
<!-- Orange -->
|
||||
<!-- Yellow 700 -->
|
||||
<!-- Green -->
|
||||
<!-- Light Green -->
|
||||
<!-- Blue -->
|
||||
<!-- Indigo -->
|
||||
<!-- Purple -->
|
||||
<!-- Deep Purple 300 -->
|
||||
<!-- Pink 300 -->
|
||||
|
||||
<!-- divider -->
|
||||
<color name="divider">#20000000</color>
|
||||
|
||||
<color name="divider_black">#20ffffff</color>
|
||||
<!-- shadow -->
|
||||
|
||||
<!-- Gallery Activity -->
|
||||
|
||||
<!-- Lock pattern view -->
|
||||
|
||||
<!--Shortcut background-->
|
||||
<color name="shortcut_bg">#F5F5F5</color>
|
||||
</resources>
|
||||
@@ -60,13 +60,10 @@
|
||||
<string name="pd_file_image" translatable="false">M13,9H18.5L13,3.5V9M6,2H14L20,8V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V4C4,2.89 4.89,2 6,2M6,20H15L18,20V12L14,16L12,14L6,20M8,9A2,2 0 0,0 6,11A2,2 0 0,0 8,13A2,2 0 0,0 10,11A2,2 0 0,0 8,9Z</string>
|
||||
<string name="pd_eh_subscription" translatable="false">M20,8H4V6h16V8 M18,2H6v2h12V2 M20,10H4c-1.1,0-2,0.9-2,2v8c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2v-8C22,10.9,21.1,10,20,10zM11,14H7v1h4v2H7v1h4v2H5v-8h6V14z M19,20h-2v-3h-2v3h-2v-8h2v3h2v-3h2V20z</string>
|
||||
<string name="pd_pencil" translatable="false">M20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L15.12,5.12L18.87,8.87M3,17.25V21H6.75L17.81,9.93L14.06,6.18L3,17.25Z</string>
|
||||
|
||||
<string name="pd_big_history" translatable="false">M5.5,2H22V0H5C3.3,0,2,1.3,2,3V21C2,22.7,3.3,24,5,24H22V4H5.5C4.1,4,4.1,2,5.5,2ZM20,6V22H6V6H20M12.5,11.8V14.4L14.9,15.8L15.3,15.2L13.3,14V11.9M13.3,9.3C11.5,9.3,10,10.3,9.2,11.7L8,10.5V13.8H11.3L9.9,12.4C10.5,11.1,11.8,10.3,13.3,10.3C15.4,10.3,17.1,12,17.1,14.1S15.4,17.9,13.3,17.9C11.7,17.9,10.3,16.9,9.8,15.4H8.7C9.3,17.4,11.1,18.9,13.3,18.9C15.9,18.9,18.1,16.8,18.1,14.1C18,11.4,15.9,9.3,13.3,9.3Z</string>
|
||||
<string name="pd_big_download" translatable="false">M0,19V24H24V19H0ZM16,22H15V21H16V22ZM19,22H18V21H19V22ZM22,22H21V21H22V22M15,11L15,0L9,0L9,11L5,11L12,18L19,11Z</string>
|
||||
<string name="pd_big_filter" translatable="false">M22.9,2.84C24,0.44,15.08,0,12,0C9.06,0,0,0.43,1.1,2.84C1.6,3.94,10,15.76,10,15.76V21L14,24V15.76S22.4,3.96,22.9,2.84ZM12,1.94C16.25,1.94,20.15,2.51,20.15,3.17S16.25,4.34,12,4.34S3.97,3.8,3.97,3.17S7.76,1.94,12,1.94Z</string>
|
||||
|
||||
<string name="pd_slider_bubble" translatable="false">M13,0C20.2,0,26,5.9,26,13.2,26,16.9,24,20.8,18.7,26.1L13,32,7.2,26.2C2,20.8,0,16.9,0,13.3,0,5.9,5.8,0,13,0Z</string>
|
||||
|
||||
<string name="pd_sad_panda" translatable="false">M21.1,7.8C22.2,7.4,23,6.3,23,5C23,3.3,21.7,2,20,2C18.9,2,17.9,2.6,17.4,3.6L21.1,7.8M6.6,3.6C6.1,2.6,5.1,2,4,2C2.3,2,1,3.3,1,5C1,6.3,1.8,7.4,2.9,7.8L6.6,3.6M10.1,13L8,15.1C7.4,15.7,6.5,15.7,5.9,15.1L5.9,15.1C5.3,14.5,5.3,13.6,5.9,13L8,10.9C8.6,10.3,9.5,10.3,10.1,10.9L10.1,10.9C10.7,11.5,10.7,12.4,10.1,13M16,15.1L13.9,13C13.3,12.4,13.3,11.5,13.9,10.9L13.9,10.9C14.5,10.3,15.4,10.3,16,10.9L18.1,13C18.7,13.6,18.7,14.5,18.1,15.1L18.1,15.1C17.5,15.7,16.6,15.7,16,15.1M12,17C12.8,17,13.5,17.4,13.5,18S12.8,19,12,19S10.5,18.6,10.5,18S11.2,17,12,17Z</string>
|
||||
<string name="pd_archive" translatable="false">M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM10,17l-3.5,-3.5 1.41,-1.41L10,14.17 15.18,9l1.41,1.41L10,17z</string>
|
||||
|
||||
|
||||
@@ -466,8 +466,8 @@
|
||||
<string name="settings_eh_identity_cookies">Identity cookies</string>
|
||||
<string name="settings_eh_identity_cookies_summary">Cookies can be used to sign in</string>
|
||||
<string name="settings_eh_identity_cookies_signed">Identity cookies can be used to sign in to this account.<br><b>KEEP IT SAFE</b><br><br>%s</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">Not signed in.</string>
|
||||
<string name="settings_eh_identity_cookies_copy">Copy</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">Tourist mode</string>
|
||||
<string name="settings_eh_identity_cookies_copy">Copy Cookies</string>
|
||||
<string name="settings_u_config">EHentai settings</string>
|
||||
<string name="settings_u_config_summary">Settings on EHentai website</string>
|
||||
<string name="settings_my_tags">My tags</string>
|
||||
@@ -825,6 +825,9 @@
|
||||
|
||||
<string name="show_library_version">Library Version</string>
|
||||
<string name="settings_privacy_require_unlock">Require Unlock</string>
|
||||
<string name="settings_privacy_require_unlock_delay">Lock Delay</string>
|
||||
<string name="settings_privacy_require_unlock_delay_summary">No unlock is required when leaving App and returning within %s minute(s)</string>
|
||||
<string name="settings_privacy_require_unlock_delay_summary_immediately">Unlock is required whenever you return to this App</string>
|
||||
<string name="proxy_type_name">Proxy Type</string>
|
||||
<string name="filter_label">Blocker Type</string>
|
||||
|
||||
@@ -833,4 +836,10 @@
|
||||
<string name="passwd_wrong">Password Wrong</string>
|
||||
<string name="passwd_cannot_be_empty">Password can\'t be empty</string>
|
||||
<string name="list_tile_thumb_size">Thumb size in thumb mode</string>
|
||||
<string name="backup_favorite">Backup favorite list</string>
|
||||
<string name="backup_favorite_summary">Backup remote favorite list to local</string>
|
||||
<string name="backup_favorite_failed">Backup favorite list failed</string>
|
||||
<string name="backup_favorite_success">backup favorite list success</string>
|
||||
<string name="backup_favorite_start">Now starting backup favorite list</string>
|
||||
<string name="account_name">Account</string>
|
||||
</resources>
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
<style name="AppTheme" parent="Base.AppTheme" />
|
||||
|
||||
<!-- TextAppearance -->
|
||||
|
||||
<!-- Progress View -->
|
||||
<style name="ProgressView">
|
||||
<item name="android:indeterminate">true</item>
|
||||
@@ -34,7 +32,7 @@
|
||||
</style>
|
||||
|
||||
<style name="CardMessage">
|
||||
<item name="android:textAppearance">@style/TextAppearance.Material3.BodyMedium</item>
|
||||
<item name="android:textAppearance">@style/TextAppearance.Material3.LabelLarge</item>
|
||||
<item name="android:ellipsize">end</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:maxLines">1</item>
|
||||
|
||||
@@ -109,4 +109,10 @@
|
||||
android:title="@string/open_by_default"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<Preference
|
||||
android:key="backup_favorite"
|
||||
android:summary="@string/backup_favorite_summary"
|
||||
android:title="@string/backup_favorite"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -17,16 +17,10 @@
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<com.hippo.ehviewer.preference.SignOutPreference
|
||||
android:key="sign_out"
|
||||
android:summary="@string/settings_eh_sign_out_summary"
|
||||
android:title="@string/settings_eh_sign_out"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<com.hippo.ehviewer.preference.IdentityCookiePreference
|
||||
android:key="identity_cookie"
|
||||
android:summary="@string/settings_eh_identity_cookies_summary"
|
||||
android:title="@string/settings_eh_identity_cookies"
|
||||
<com.hippo.ehviewer.preference.AccountPreference
|
||||
android:key="account"
|
||||
android:summary="@string/settings_eh_identity_cookies_tourist"
|
||||
android:title="@string/account_name"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<rikka.preference.SimpleMenuPreference
|
||||
@@ -88,7 +82,7 @@
|
||||
android:title="@string/list_tile_thumb_size"
|
||||
android:max="60"
|
||||
app:iconSpaceReserved="false"
|
||||
app:min="30"
|
||||
app:min="20"
|
||||
app:showSeekBarValue="true" />
|
||||
|
||||
<rikka.preference.SimpleMenuPreference
|
||||
|
||||
@@ -24,6 +24,16 @@
|
||||
android:title="@string/settings_privacy_require_unlock"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SeekBarPreference
|
||||
android:defaultValue="0"
|
||||
android:key="require_unlock_delay"
|
||||
android:max="30"
|
||||
android:progress="0"
|
||||
android:summary=""
|
||||
android:title="@string/settings_privacy_require_unlock_delay"
|
||||
app:iconSpaceReserved="false"
|
||||
app:showSeekBarValue="true" />
|
||||
|
||||
<rikka.material.preference.MaterialSwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="enable_secure"
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id 'com.android.application' version '7.2.2' apply false
|
||||
id 'com.android.application' version '8.0.0-alpha02' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
|
||||
id 'com.google.devtools.ksp' version '1.7.10-1.0.6' apply false
|
||||
}
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ App is divided into two versions: 1.7 and 1.8 . Version 1.8 support Android 12 a
|
||||
|
||||
Here is the libraries
|
||||
|
||||
- [AOSP&AndroidX](http://source.android.com/)
|
||||
- [AOSP & AndroidX](http://source.android.com/)
|
||||
- [FullDraggableDrawer](https://github.com/PureWriter/FullDraggableDrawer)
|
||||
- [GnuTLS](https://gnutls.org/)
|
||||
- [material-components-android](https://github.com/material-components/material-components-android)
|
||||
|
||||
@@ -79,7 +79,7 @@ App 分为 1.8 与 1.7 两个版本。1.8 版本适配 Android 12 及以上系
|
||||
|
||||
本项目受到了诸多开源项目的帮助
|
||||
|
||||
- [AOSP&AndroidX](http://source.android.com/)
|
||||
- [AOSP & AndroidX](http://source.android.com/)
|
||||
- [FullDraggableDrawer](https://github.com/PureWriter/FullDraggableDrawer)
|
||||
- [GnuTLS](https://gnutls.org/)
|
||||
- [material-components-android](https://github.com/material-components/material-components-android)
|
||||
|
||||
@@ -79,7 +79,7 @@ App 分為 1.8 與 1.7 兩個版本。1.8 版本適配 Android 12 及以上系
|
||||
|
||||
本項目受到了諸多開源項目的幫助
|
||||
|
||||
- [AOSP&AndroidX](http://source.android.com/)
|
||||
- [AOSP & AndroidX](http://source.android.com/)
|
||||
- [FullDraggableDrawer](https://github.com/PureWriter/FullDraggableDrawer)
|
||||
- [GnuTLS](https://gnutls.org/)
|
||||
- [material-components-android](https://github.com/material-components/material-components-android)
|
||||
|
||||
Reference in new issue
Block a user