Compare commits
52
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f3476895e | ||
|
|
98af874e83 | ||
|
|
02bd5badb9 | ||
|
|
605f86483b | ||
|
|
f0d6ad9848 | ||
|
|
7677498e0c | ||
|
|
d115af60b3 | ||
|
|
b07ab230e9 | ||
|
|
760ca8d6fb | ||
|
|
4f0acb465a | ||
|
|
f1ddc6c3aa | ||
|
|
3b955cc9a9 | ||
|
|
652f503635 | ||
|
|
5f6d2e8dbd | ||
|
|
4925312c4a | ||
|
|
c58bad59e2 | ||
|
|
7aa318890d | ||
|
|
066500f2f8 | ||
|
|
d37752a6db | ||
|
|
cd81a10d28 | ||
|
|
812018af06 | ||
|
|
ee1ddeec12 | ||
|
|
8a3ce0e5ef | ||
|
|
8b9a3a0274 | ||
|
|
08f8f6cc75 | ||
|
|
1052ac5fc5 | ||
|
|
b62b6f95a8 | ||
|
|
ffd719a104 | ||
|
|
2f787ca94b | ||
|
|
990c8ed9c9 | ||
|
|
3492593a06 | ||
|
|
2bea46b15b | ||
|
|
f0903fa8b2 | ||
|
|
60caa099e2 | ||
|
|
586fba4221 | ||
|
|
80faa9a2db | ||
|
|
54fea2929f | ||
|
|
4599ed88ee | ||
|
|
60d75fd780 | ||
|
|
896d71b867 | ||
|
|
6d440730fd | ||
|
|
77a6960e90 | ||
|
|
215eb267fe | ||
|
|
2c86e8b898 | ||
|
|
d7daa47c73 | ||
|
|
3c488916bf | ||
|
|
ba09fcdc3c | ||
|
|
385101a729 | ||
|
|
002c3cf1d5 | ||
|
|
84064549ac | ||
|
|
8c52ad212e | ||
|
|
23e6f78067 |
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
|
||||
@@ -30,6 +30,7 @@ jobs:
|
||||
- name: Gradle Build
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
gradle-home-cache-cleanup: true
|
||||
arguments: assembleRelease
|
||||
|
||||
- name: Update ARM64
|
||||
|
||||
@@ -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)
|
||||
|
||||
+16
-16
@@ -35,8 +35,8 @@ android {
|
||||
applicationId "moe.tarsin.ehviewer"
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 33
|
||||
versionCode 114536
|
||||
versionName "1.7.30.0"
|
||||
versionCode 114537
|
||||
versionName "1.7.31.0-alpha02"
|
||||
resConfigs 'zh', 'zh-rCN', 'zh-rHK', 'zh-rTW', 'es', 'ja', 'ko', 'fr', 'de', 'th'
|
||||
}
|
||||
|
||||
@@ -93,41 +93,41 @@ tasks.withType(JavaCompile) {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
def activity_version = "1.6.0-beta01"
|
||||
def activity_version = "1.6.1"
|
||||
implementation "androidx.activity:activity:$activity_version"
|
||||
implementation "androidx.activity:activity-ktx:$activity_version"
|
||||
|
||||
implementation "androidx.annotation:annotation:1.4.0"
|
||||
implementation "androidx.annotation:annotation-experimental:1.2.0"
|
||||
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"
|
||||
|
||||
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.documentfile:documentfile:1.1.0-alpha01"
|
||||
implementation "androidx.dynamicanimation:dynamicanimation:1.1.0-alpha03"
|
||||
|
||||
def fragment_version = "1.5.2"
|
||||
def fragment_version = "1.5.4"
|
||||
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-alpha03"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-core-ktx:$lifecycle_version"
|
||||
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
|
||||
@@ -137,7 +137,7 @@ dependencies {
|
||||
|
||||
implementation "androidx.loader:loader:1.1.0"
|
||||
implementation 'androidx.preference:preference:1.2.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.0-beta02'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.0-rc01'
|
||||
implementation 'androidx.startup:startup-runtime:1.2.0-alpha01'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01'
|
||||
implementation "androidx.transition:transition-ktx:1.4.1"
|
||||
@@ -145,10 +145,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-alpha02'
|
||||
|
||||
implementation 'com.squareup.okhttp3:okhttp-bom:5.0.0-alpha.10'
|
||||
implementation 'com.squareup.okhttp3:okhttp'
|
||||
@@ -161,7 +161,7 @@ dependencies {
|
||||
implementation 'dev.rikka.rikkax.material:material-preference:2.0.0'
|
||||
implementation 'org.greenrobot:greendao:3.3.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'
|
||||
implementation projects.native
|
||||
}
|
||||
|
||||
|
||||
@@ -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,7 +44,7 @@ public class FavListUrlBuilder implements Parcelable {
|
||||
}
|
||||
};
|
||||
private static final String TAG = FavListUrlBuilder.class.getSimpleName();
|
||||
private int mIndex;
|
||||
private String mNext;
|
||||
private String mKeyword;
|
||||
private int mFavCat = FAV_CAT_ALL;
|
||||
|
||||
@@ -52,7 +52,7 @@ public class FavListUrlBuilder implements Parcelable {
|
||||
}
|
||||
|
||||
protected FavListUrlBuilder(Parcel in) {
|
||||
this.mIndex = in.readInt();
|
||||
this.mNext = in.readString();
|
||||
this.mKeyword = in.readString();
|
||||
this.mFavCat = in.readInt();
|
||||
}
|
||||
@@ -61,8 +61,8 @@ public class FavListUrlBuilder implements Parcelable {
|
||||
return favCat >= 0 && favCat <= 9;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
mIndex = index;
|
||||
public void setNext(String next) {
|
||||
mNext = next;
|
||||
}
|
||||
|
||||
public String getKeyword() {
|
||||
@@ -105,8 +105,8 @@ public class FavListUrlBuilder implements Parcelable {
|
||||
Log.e(TAG, "Can't URLEncoder.encode " + mKeyword);
|
||||
}
|
||||
}
|
||||
if (mIndex > 0) {
|
||||
ub.addQuery("page", Integer.toString(mIndex));
|
||||
if (mNext != null && !mNext.isEmpty()) {
|
||||
ub.addQuery("next", mNext);
|
||||
}
|
||||
return ub.build();
|
||||
}
|
||||
@@ -118,7 +118,7 @@ public class FavListUrlBuilder implements Parcelable {
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(this.mIndex);
|
||||
dest.writeString(this.mNext);
|
||||
dest.writeString(this.mKeyword);
|
||||
dest.writeInt(this.mFavCat);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,8 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
@Mode
|
||||
private int mMode = MODE_NORMAL;
|
||||
|
||||
private int mPageIndex = 0;
|
||||
private int mNextGid = 0;
|
||||
private int mPrevGid = 0;
|
||||
|
||||
private int mCategory = EhUtils.NONE;
|
||||
private String mKeyword = null;
|
||||
@@ -86,7 +87,8 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
@SuppressWarnings("WrongConstant")
|
||||
protected ListUrlBuilder(Parcel in) {
|
||||
this.mMode = in.readInt();
|
||||
this.mPageIndex = in.readInt();
|
||||
this.mNextGid = in.readInt();
|
||||
this.mPrevGid = in.readInt();
|
||||
this.mCategory = in.readInt();
|
||||
this.mKeyword = in.readString();
|
||||
this.mAdvanceSearch = in.readInt();
|
||||
@@ -105,7 +107,8 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
*/
|
||||
public void reset() {
|
||||
mMode = MODE_NORMAL;
|
||||
mPageIndex = 0;
|
||||
mNextGid = 0;
|
||||
mPrevGid = 0;
|
||||
mCategory = EhUtils.NONE;
|
||||
mKeyword = null;
|
||||
mAdvanceSearch = -1;
|
||||
@@ -137,12 +140,12 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
mMode = mode;
|
||||
}
|
||||
|
||||
public int getPageIndex() {
|
||||
return mPageIndex;
|
||||
public void setNextGid(int nextGid) {
|
||||
mNextGid = nextGid;
|
||||
}
|
||||
|
||||
public void setPageIndex(int pageIndex) {
|
||||
mPageIndex = pageIndex;
|
||||
public void setPrevGid(int prevGid) {
|
||||
mPrevGid = prevGid;
|
||||
}
|
||||
|
||||
public int getCategory() {
|
||||
@@ -233,7 +236,8 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
*/
|
||||
public void set(ListUrlBuilder lub) {
|
||||
mMode = lub.mMode;
|
||||
mPageIndex = lub.mPageIndex;
|
||||
mNextGid = lub.mNextGid;
|
||||
mPrevGid = lub.mPrevGid;
|
||||
mCategory = lub.mCategory;
|
||||
mKeyword = lub.mKeyword;
|
||||
mAdvanceSearch = lub.mAdvanceSearch;
|
||||
@@ -524,9 +528,11 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
if (mSHash != null) {
|
||||
ub.addQuery("f_shash", mSHash);
|
||||
}
|
||||
// Page index
|
||||
if (mPageIndex != 0) {
|
||||
ub.addQuery("page", mPageIndex);
|
||||
if (mNextGid != 0) {
|
||||
ub.addQuery("next", mNextGid);
|
||||
}
|
||||
if (mPrevGid != 0) {
|
||||
ub.addQuery("prev", mPrevGid);
|
||||
}
|
||||
// Advance search
|
||||
if (mAdvanceSearch != -1) {
|
||||
@@ -570,8 +576,8 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// Empty
|
||||
}
|
||||
if (mPageIndex != 0) {
|
||||
sb.append('/').append(mPageIndex);
|
||||
if (mNextGid != 0) {
|
||||
sb.append("?next=").append(mNextGid);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -583,8 +589,8 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// Empty
|
||||
}
|
||||
if (mPageIndex != 0) {
|
||||
sb.append('/').append(mPageIndex);
|
||||
if (mNextGid != 0) {
|
||||
sb.append("?next=").append(mNextGid);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -600,8 +606,8 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// Empty
|
||||
}
|
||||
if (mPageIndex != 0) {
|
||||
sb.append("&p=").append(mPageIndex);
|
||||
if (mNextGid != 0) {
|
||||
sb.append("&p=").append(mNextGid);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -615,7 +621,8 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(this.mMode);
|
||||
dest.writeInt(this.mPageIndex);
|
||||
dest.writeInt(this.mNextGid);
|
||||
dest.writeInt(this.mPrevGid);
|
||||
dest.writeInt(this.mCategory);
|
||||
dest.writeString(this.mKeyword);
|
||||
dest.writeInt(this.mAdvanceSearch);
|
||||
|
||||
@@ -31,8 +31,10 @@ import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class FavoritesParser {
|
||||
private static final Pattern PATTERN_NEXT_PAGE = Pattern.compile("next=(\\d+-\\d+)");
|
||||
|
||||
public static Result parse(String body) throws Exception {
|
||||
if (body.contains("This page requires you to log on.</p>")) {
|
||||
@@ -59,14 +61,25 @@ public class FavoritesParser {
|
||||
e.printStackTrace();
|
||||
throw new ParseException("Parse favorites error", body);
|
||||
}
|
||||
Result re = new Result();
|
||||
|
||||
try {
|
||||
var d = Jsoup.parse(body);
|
||||
var snv = d.getElementsByClass("searchnav").first();
|
||||
assert snv != null;
|
||||
var href = snv.child(3).child(0).attr("href");
|
||||
var matcher = PATTERN_NEXT_PAGE.matcher(href);
|
||||
if (matcher.find()) {
|
||||
re.nextPage = matcher.group(1);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
GalleryListParser.Result result = GalleryListParser.parse(body);
|
||||
|
||||
Result re = new Result();
|
||||
re.catArray = catArray;
|
||||
re.countArray = countArray;
|
||||
re.pages = result.pages;
|
||||
re.nextPage = result.nextPage;
|
||||
re.galleryInfoList = result.galleryInfoList;
|
||||
|
||||
return re;
|
||||
@@ -75,8 +88,7 @@ public class FavoritesParser {
|
||||
public static class Result {
|
||||
public String[] catArray; // Size 10
|
||||
public int[] countArray; // Size 10
|
||||
public int pages;
|
||||
public int nextPage;
|
||||
public String nextPage;
|
||||
public List<GalleryInfo> galleryInfoList;
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,8 @@ public class GalleryListParser {
|
||||
private static final Pattern PATTERN_THUMB_SIZE = Pattern.compile("height:(\\d+)px;width:(\\d+)px");
|
||||
private static final Pattern PATTERN_FAVORITE_SLOT = Pattern.compile("background-color:rgba\\((\\d+),(\\d+),(\\d+),");
|
||||
private static final Pattern PATTERN_PAGES = Pattern.compile("(\\d+) page");
|
||||
private static final Pattern PATTERN_NEXT_PAGE = Pattern.compile("page=(\\d+)");
|
||||
|
||||
private static final Pattern PATTERN_GETINT = Pattern.compile("[^0-9]");
|
||||
|
||||
private static final String[][] FAVORITE_SLOT_RGB = new String[][]{
|
||||
new String[]{"0", "0", "0"},
|
||||
@@ -297,39 +298,21 @@ public class GalleryListParser {
|
||||
return gi;
|
||||
}
|
||||
|
||||
private static int getInt(String str) {
|
||||
var m = PATTERN_GETINT.matcher(str);
|
||||
return Integer.parseInt(m.replaceAll("").trim());
|
||||
}
|
||||
|
||||
public static Result parse(@NonNull String body) throws Exception {
|
||||
Result result = new Result();
|
||||
Document d = Jsoup.parse(body);
|
||||
|
||||
try {
|
||||
Element ptt = d.getElementsByClass("ptt").first();
|
||||
Elements es = ptt.child(0).child(0).children();
|
||||
result.pages = Integer.parseInt(es.get(es.size() - 2).text().trim());
|
||||
|
||||
Element e = es.get(es.size() - 1);
|
||||
if (e != null) {
|
||||
e = e.children().first();
|
||||
if (e != null) {
|
||||
String href = e.attr("href");
|
||||
Matcher matcher = PATTERN_NEXT_PAGE.matcher(href);
|
||||
if (matcher.find()) {
|
||||
result.nextPage = NumberUtils.parseIntSafely(matcher.group(1), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
result.noWatchedTags = body.contains("<p>You do not have any watched tags");
|
||||
if (body.contains("No hits found</p>")) {
|
||||
result.pages = 0;
|
||||
//noinspection unchecked
|
||||
result.galleryInfoList = Collections.EMPTY_LIST;
|
||||
return result;
|
||||
} else if (d.getElementsByClass("ptt").isEmpty()) {
|
||||
result.pages = 1;
|
||||
} else {
|
||||
result.pages = Integer.MAX_VALUE;
|
||||
}
|
||||
result.founds = Integer.MAX_VALUE;
|
||||
result.noWatchedTags = body.contains("<p>You do not have any watched tags");
|
||||
if (body.contains("No hits found</p>")) {
|
||||
result.founds = 0;
|
||||
result.galleryInfoList = Collections.EMPTY_LIST;
|
||||
return result;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -364,8 +347,7 @@ public class GalleryListParser {
|
||||
}
|
||||
|
||||
public static class Result {
|
||||
public int pages;
|
||||
public int nextPage;
|
||||
public int founds;
|
||||
public boolean noWatchedTags;
|
||||
public List<GalleryInfo> galleryInfoList;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,10 @@ import java.util.List;
|
||||
|
||||
public final class CommonOperations {
|
||||
|
||||
public static int getPagesForFounds(int founds, int per) {
|
||||
return (int)Math.ceil((double) founds/per);
|
||||
}
|
||||
|
||||
private static void doAddToFavorites(Activity activity, GalleryInfo galleryInfo,
|
||||
int slot, EhClient.Callback<Void> listener) {
|
||||
if (slot == -1) {
|
||||
|
||||
@@ -17,12 +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.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
@@ -39,6 +40,11 @@ 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;
|
||||
@@ -53,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;
|
||||
|
||||
@@ -64,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(),
|
||||
@@ -231,6 +239,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);
|
||||
@@ -242,6 +251,7 @@ public class AdvancedFragment extends BasePreferenceFragment {
|
||||
clearMemoryCache.setOnPreferenceClickListener(this);
|
||||
importData.setOnPreferenceClickListener(this);
|
||||
exportData.setOnPreferenceClickListener(this);
|
||||
backupFavorite.setOnPreferenceClickListener(this);
|
||||
|
||||
appLanguage.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
@@ -288,10 +298,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.setNext(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.setNext(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();
|
||||
|
||||
@@ -55,8 +55,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
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;
|
||||
@@ -885,73 +883,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 +1161,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);
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.content.res.Resources;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.util.SparseBooleanArray;
|
||||
@@ -854,7 +855,14 @@ public class FavoritesScene extends BaseScene implements
|
||||
}
|
||||
|
||||
updateSearchBar();
|
||||
mHelper.onGetPageData(taskId, result.pages, result.nextPage, result.galleryInfoList);
|
||||
int pages = 0;
|
||||
assert mUrlBuilder != null;
|
||||
if (FavListUrlBuilder.isValidFavCat(mUrlBuilder.getFavCat()))
|
||||
pages = CommonOperations.getPagesForFounds(mFavCountArray[mUrlBuilder.getFavCat()], 50);
|
||||
else if (mUrlBuilder.getFavCat() == FavListUrlBuilder.FAV_CAT_ALL)
|
||||
pages = CommonOperations.getPagesForFounds(mFavCountSum, 50);
|
||||
mHelper.nextPg = result.nextPage;
|
||||
mHelper.onGetPageData(taskId, pages, mHelper.pgCounter + 1, result.galleryInfoList);
|
||||
|
||||
if (mDrawerAdapter != null) {
|
||||
mDrawerAdapter.notifyDataSetChanged();
|
||||
@@ -1173,6 +1181,8 @@ public class FavoritesScene extends BaseScene implements
|
||||
}
|
||||
|
||||
private class FavoritesHelper extends GalleryInfoContentHelper {
|
||||
public int pgCounter = 0;
|
||||
public String nextPg = null;
|
||||
|
||||
@Override
|
||||
protected void getPageData(final int taskId, int type, int page) {
|
||||
@@ -1180,6 +1190,7 @@ public class FavoritesScene extends BaseScene implements
|
||||
if (null == activity || null == mUrlBuilder || null == mClient) {
|
||||
return;
|
||||
}
|
||||
pgCounter = page;
|
||||
|
||||
if (mEnableModify) {
|
||||
mEnableModify = false;
|
||||
@@ -1219,7 +1230,7 @@ public class FavoritesScene extends BaseScene implements
|
||||
url = mUrlBuilder.build();
|
||||
}
|
||||
|
||||
mUrlBuilder.setIndex(page);
|
||||
mUrlBuilder.setNext(nextPg);
|
||||
EhRequest request = new EhRequest();
|
||||
request.setMethod(EhClient.METHOD_MODIFY_FAVORITES);
|
||||
request.setCallback(new GetFavoritesListener(getContext(),
|
||||
@@ -1232,7 +1243,7 @@ public class FavoritesScene extends BaseScene implements
|
||||
final String keyword = mUrlBuilder.getKeyword();
|
||||
SimpleHandler.getInstance().post(() -> onGetFavoritesLocal(keyword, taskId));
|
||||
} else {
|
||||
mUrlBuilder.setIndex(page);
|
||||
mUrlBuilder.setNext(nextPg);
|
||||
String url = mUrlBuilder.build();
|
||||
EhRequest request = new EhRequest();
|
||||
request.setMethod(EhClient.METHOD_GET_FAVORITES);
|
||||
@@ -1295,5 +1306,25 @@ public class FavoritesScene extends BaseScene implements
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClearData() {
|
||||
super.onClearData();
|
||||
nextPg = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parcelable saveInstanceState(Parcelable superState) {
|
||||
Bundle bundle = (Bundle) super.saveInstanceState(superState);
|
||||
bundle.putString(KEY_NEXT_PAGE, nextPg);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parcelable restoreInstanceState(Parcelable state) {
|
||||
Bundle bundle = (Bundle) state;
|
||||
nextPg = bundle.getString(KEY_NEXT_PAGE);
|
||||
return super.restoreInstanceState(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -1371,7 +1371,7 @@ public final class GalleryListScene extends BaseScene
|
||||
? R.string.gallery_list_empty_hit_subscription
|
||||
: R.string.gallery_list_empty_hit);
|
||||
mHelper.setEmptyString(emptyString);
|
||||
mHelper.onGetPageData(taskId, result.pages, result.nextPage, result.galleryInfoList);
|
||||
mHelper.onGetPageData(taskId, CommonOperations.getPagesForFounds(result.founds, 25), mHelper.pgCounter + 1, result.galleryInfoList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1544,7 +1544,7 @@ public final class GalleryListScene extends BaseScene
|
||||
}
|
||||
|
||||
mUrlBuilder.set(mQuickSearchList.get(position));
|
||||
mUrlBuilder.setPageIndex(0);
|
||||
mUrlBuilder.setNextGid(0);
|
||||
onUpdateUrlBuilder();
|
||||
mHelper.refresh();
|
||||
setState(STATE_NORMAL);
|
||||
@@ -1561,7 +1561,7 @@ public final class GalleryListScene extends BaseScene
|
||||
}
|
||||
|
||||
mUrlBuilder.setKeyword(String.valueOf(keywords[position]));
|
||||
mUrlBuilder.setPageIndex(0);
|
||||
mUrlBuilder.setNextGid(0);
|
||||
onUpdateUrlBuilder();
|
||||
mHelper.refresh();
|
||||
setState(STATE_NORMAL);
|
||||
@@ -1691,15 +1691,20 @@ public final class GalleryListScene extends BaseScene
|
||||
}
|
||||
|
||||
private class GalleryListHelper extends GalleryInfoContentHelper {
|
||||
public int pgCounter = 0;
|
||||
|
||||
@Override
|
||||
protected void getPageData(int taskId, int type, int page) {
|
||||
pgCounter = page;
|
||||
MainActivity activity = getMainActivity();
|
||||
if (null == activity || null == mClient || null == mUrlBuilder) {
|
||||
return;
|
||||
}
|
||||
|
||||
mUrlBuilder.setPageIndex(page);
|
||||
if (page != 0)
|
||||
mUrlBuilder.setNextGid(minGid);
|
||||
else
|
||||
mUrlBuilder.setNextGid(0);
|
||||
if (ListUrlBuilder.MODE_IMAGE_SEARCH == mUrlBuilder.getMode()) {
|
||||
EhRequest request = new EhRequest();
|
||||
request.setMethod(EhClient.METHOD_IMAGE_SEARCH);
|
||||
|
||||
@@ -31,8 +31,14 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class GalleryInfoContentHelper extends ContentLayout.ContentHelper<GalleryInfo> {
|
||||
public int maxGid = -1;
|
||||
public int minGid = -1;
|
||||
|
||||
private static final String KEY_DATA_MAP = "data_map";
|
||||
private static final String KEY_MAX_GID = "max_gid";
|
||||
private static final String KEY_MIN_GID = "min_gid";
|
||||
|
||||
public static final String KEY_NEXT_PAGE = "next_page";
|
||||
private final FavouriteStatusRouter.Listener listener;
|
||||
@SuppressLint("UseSparseArrays")
|
||||
private Map<Long, GalleryInfo> map = new HashMap<>();
|
||||
@@ -59,6 +65,12 @@ public abstract class GalleryInfoContentHelper extends ContentLayout.ContentHelp
|
||||
@Override
|
||||
protected void onAddData(List<GalleryInfo> data) {
|
||||
for (GalleryInfo info : data) {
|
||||
if (maxGid == -1)
|
||||
maxGid = (int) info.gid;
|
||||
if (minGid == -1)
|
||||
minGid = (int) info.gid;
|
||||
maxGid = (int) Math.max(maxGid, info.gid);
|
||||
minGid = (int) Math.min(minGid, info.gid);
|
||||
map.put(info.gid, info);
|
||||
}
|
||||
}
|
||||
@@ -78,6 +90,8 @@ public abstract class GalleryInfoContentHelper extends ContentLayout.ContentHelp
|
||||
@Override
|
||||
protected void onClearData() {
|
||||
map.clear();
|
||||
maxGid = -1;
|
||||
minGid = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,6 +102,8 @@ public abstract class GalleryInfoContentHelper extends ContentLayout.ContentHelp
|
||||
FavouriteStatusRouter router = EhApplication.getFavouriteStatusRouter();
|
||||
int id = router.saveDataMap(map);
|
||||
bundle.putInt(KEY_DATA_MAP, id);
|
||||
bundle.putInt(KEY_MIN_GID, minGid);
|
||||
bundle.putInt(KEY_MAX_GID, maxGid);
|
||||
|
||||
return bundle;
|
||||
}
|
||||
@@ -104,6 +120,8 @@ public abstract class GalleryInfoContentHelper extends ContentLayout.ContentHelp
|
||||
this.map = map;
|
||||
}
|
||||
}
|
||||
minGid = bundle.getInt(KEY_MIN_GID);
|
||||
maxGid = bundle.getInt(KEY_MAX_GID);
|
||||
|
||||
return super.restoreInstanceState(state);
|
||||
}
|
||||
|
||||
@@ -1,27 +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.scene;
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -467,48 +451,22 @@ public class ContentLayout extends FrameLayout {
|
||||
|
||||
switch (mCurrentTaskType) {
|
||||
case TYPE_REFRESH:
|
||||
mStartPage = 0;
|
||||
mEndPage = 1;
|
||||
mPages = pages;
|
||||
mNextPage = nextPage;
|
||||
mPageDivider.clear();
|
||||
mPageDivider.add(data.size());
|
||||
|
||||
if (data.isEmpty()) {
|
||||
mData.clear();
|
||||
onClearData();
|
||||
notifyDataSetChanged();
|
||||
|
||||
if (true || mEndPage >= mPages) { // Not found
|
||||
// Ui change, show empty string
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showEmptyString();
|
||||
} else {
|
||||
// Ui change, show progress bar
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showProgressBar();
|
||||
|
||||
// Get next page
|
||||
mCurrentTaskId = mIdGenerator.nextId();
|
||||
mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
|
||||
mCurrentTaskPage = mEndPage;
|
||||
getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
|
||||
}
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showEmptyString();
|
||||
} else {
|
||||
mData.clear();
|
||||
onClearData();
|
||||
mData.addAll(data);
|
||||
onAddData(data);
|
||||
notifyDataSetChanged();
|
||||
|
||||
// Ui change, show content
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showContent();
|
||||
|
||||
// RecyclerView scroll
|
||||
if (mRecyclerView.isAttachedToWindow()) {
|
||||
mRecyclerView.stopScroll();
|
||||
LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
|
||||
@@ -529,33 +487,24 @@ public class ContentLayout extends FrameLayout {
|
||||
// assert mStartPage >= 0
|
||||
|
||||
if (data.isEmpty()) {
|
||||
if (true || mStartPage <= 0) { // OK, that's all
|
||||
if (mData.isEmpty()) {
|
||||
// Ui change, show empty string
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showEmptyString();
|
||||
} else {
|
||||
// Ui change, show content
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showContent();
|
||||
|
||||
if (mCurrentTaskType == TYPE_PRE_PAGE && mRecyclerView.isAttachedToWindow()) {
|
||||
// RecyclerView scroll, to top
|
||||
mRecyclerView.stopScroll();
|
||||
LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
|
||||
onScrollToPosition(0);
|
||||
}
|
||||
}
|
||||
// OK, that's all
|
||||
if (mData.isEmpty()) {
|
||||
// Ui change, show empty string
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showEmptyString();
|
||||
} else {
|
||||
// Keep UI
|
||||
// Ui change, show content
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showContent();
|
||||
|
||||
// Get previous
|
||||
mCurrentTaskId = mIdGenerator.nextId();
|
||||
// Keep mCurrentTaskType
|
||||
mCurrentTaskPage = mStartPage - 1;
|
||||
getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
|
||||
if (mCurrentTaskType == TYPE_PRE_PAGE && mRecyclerView.isAttachedToWindow()) {
|
||||
// RecyclerView scroll, to top
|
||||
mRecyclerView.stopScroll();
|
||||
LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
|
||||
onScrollToPosition(0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mData.addAll(0, data);
|
||||
@@ -592,33 +541,24 @@ public class ContentLayout extends FrameLayout {
|
||||
mPages = Math.max(mEndPage, pages);
|
||||
|
||||
if (data.isEmpty()) {
|
||||
if (true || mEndPage >= mPages) { // OK, that's all
|
||||
if (mData.isEmpty()) {
|
||||
// Ui change, show empty string
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showEmptyString();
|
||||
} else {
|
||||
// Ui change, show content
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showContent();
|
||||
|
||||
if (mCurrentTaskType == TYPE_NEXT_PAGE && mRecyclerView.isAttachedToWindow()) {
|
||||
// RecyclerView scroll
|
||||
mRecyclerView.stopScroll();
|
||||
LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), oldDataSize, 0);
|
||||
onScrollToPosition(oldDataSize);
|
||||
}
|
||||
}
|
||||
// OK, that's all
|
||||
if (mData.isEmpty()) {
|
||||
// Ui change, show empty string
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showEmptyString();
|
||||
} else {
|
||||
// Keep UI
|
||||
// Ui change, show content
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showContent();
|
||||
|
||||
// Get next page
|
||||
mCurrentTaskId = mIdGenerator.nextId();
|
||||
// Keep mCurrentTaskType
|
||||
mCurrentTaskPage = mEndPage;
|
||||
getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
|
||||
if (mCurrentTaskType == TYPE_NEXT_PAGE && mRecyclerView.isAttachedToWindow()) {
|
||||
// RecyclerView scroll
|
||||
mRecyclerView.stopScroll();
|
||||
LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), oldDataSize, 0);
|
||||
onScrollToPosition(oldDataSize);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mData.addAll(data);
|
||||
@@ -655,23 +595,11 @@ public class ContentLayout extends FrameLayout {
|
||||
onClearData();
|
||||
notifyDataSetChanged();
|
||||
|
||||
if (true || mEndPage >= mPages) { // Not found
|
||||
// Ui change, show empty string
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showEmptyString();
|
||||
} else {
|
||||
// Ui change, show progress bar
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showProgressBar();
|
||||
|
||||
// Get next page
|
||||
mCurrentTaskId = mIdGenerator.nextId();
|
||||
mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
|
||||
mCurrentTaskPage = mEndPage;
|
||||
getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
|
||||
}
|
||||
// Not found
|
||||
// Ui change, show empty string
|
||||
mRefreshLayout.setRefreshing(false);
|
||||
mBottomProgress.hide();
|
||||
showEmptyString();
|
||||
} else {
|
||||
mData.clear();
|
||||
onClearData();
|
||||
@@ -820,6 +748,12 @@ public class ContentLayout extends FrameLayout {
|
||||
}
|
||||
|
||||
private void doRefresh() {
|
||||
mStartPage = 0;
|
||||
mEndPage = 1;
|
||||
mPages = 0;
|
||||
mPageDivider.clear();
|
||||
mData.clear();
|
||||
onClearData();
|
||||
mCurrentTaskId = mIdGenerator.nextId();
|
||||
mCurrentTaskType = TYPE_REFRESH;
|
||||
mCurrentTaskPage = 0;
|
||||
|
||||
@@ -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="click"/>
|
||||
|
||||
</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>
|
||||
@@ -769,4 +769,9 @@
|
||||
<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>
|
||||
@@ -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,7 +754,7 @@
|
||||
<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>
|
||||
@@ -762,11 +762,16 @@
|
||||
<string name="show_library_version">依賴庫之版本</string>
|
||||
<string name="settings_privacy_require_unlock">需要解鎖</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>
|
||||
|
||||
|
||||
@@ -833,4 +833,9 @@
|
||||
<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>
|
||||
</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>
|
||||
@@ -88,7 +88,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
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
plugins {
|
||||
id 'com.android.application' version '7.2.2' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
|
||||
id 'com.android.application' version '7.3.1' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
|
||||
+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)
|
||||
|
||||
+1
-1
@@ -37,5 +37,5 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'androidx.annotation:annotation:1.4.0'
|
||||
compileOnly 'androidx.annotation:annotation:1.5.0'
|
||||
}
|
||||
Reference in new issue
Block a user