Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac55e2f8fc | ||
|
|
24718e7d25 | ||
|
|
72e1fe9621 | ||
|
|
0c7bf96bf5 | ||
|
|
f1dde6c8bc | ||
|
|
3177a8352f | ||
|
|
3cb024b7f5 | ||
|
|
0a09d16500 | ||
|
|
a79b1ad785 | ||
|
|
4388c53929 | ||
|
|
02f000d37b | ||
|
|
7259e5e315 | ||
|
|
7ce744b5af | ||
|
|
57f21c8d39 | ||
|
|
07f27a8438 | ||
|
|
4f4dc55b4e | ||
|
|
8e9cda8e93 | ||
|
|
d5cfabd73e | ||
|
|
4f1b371e75 | ||
|
|
4d8b50912d | ||
|
|
660c717cfb | ||
|
|
70d3d9a5b2 | ||
|
|
464da25ca1 | ||
|
|
c2795120e1 | ||
|
|
b10fb46f1f | ||
|
|
e39897176a | ||
|
|
6e7e6fab74 | ||
|
|
94009b6829 | ||
|
|
289217fefc | ||
|
|
97feab1203 | ||
|
|
a9a3b20eb3 | ||
|
|
7af1e168a4 | ||
|
|
c8bf34e0d7 | ||
|
|
86d2282cd6 | ||
|
|
cfdb23d6dc | ||
|
|
1874ddd15b | ||
|
|
a004c308cc | ||
|
|
863337c789 | ||
|
|
64d91eed33 | ||
|
|
d0c3a3e14d | ||
|
|
464636d87d | ||
|
|
0b0a1f456f | ||
|
|
302030ca65 | ||
|
|
3e63738542 | ||
|
|
d6823c9c8e | ||
|
|
6bc3866660 | ||
|
|
f41f4dd8ba | ||
|
|
cde39812ce | ||
|
|
03c2abc901 | ||
|
|
7646334525 | ||
|
|
f8d1cd3fab | ||
|
|
4ea94be64a | ||
|
|
dc0470e75a | ||
|
|
5d49ecdd7d | ||
|
|
ef2441116d | ||
|
|
207909c7be | ||
|
|
ddb3dd2d95 | ||
|
|
8bb980fe97 | ||
|
|
3c3a201ed8 | ||
|
|
81bb37e929 | ||
|
|
ae34690eb2 | ||
|
|
285b0f5a69 | ||
|
|
a5327fce07 | ||
|
|
a4b750f9cd | ||
|
|
943344d4bb | ||
|
|
79f1b92960 | ||
|
|
575ae38a28 | ||
|
|
f90e2a5c80 | ||
|
|
4d9b2877fe | ||
|
|
4a955947a2 | ||
|
|
7307c136ee | ||
|
|
657e1b1d0f | ||
|
|
43edf11275 | ||
|
|
32ec4c6715 | ||
|
|
84ac57d69e | ||
|
|
328e7745b7 | ||
|
|
ccf22eaef4 | ||
|
|
c89d42f368 | ||
|
|
41192ea7f5 | ||
|
|
7840987a7c | ||
|
|
fcbe0a7f55 | ||
|
|
f12894c95d | ||
|
|
40f139fda2 | ||
|
|
b8507a371e | ||
|
|
e5a71ce906 | ||
|
|
f9e708fe1e | ||
|
|
50ba6f2bd2 | ||
|
|
2484371f8c | ||
|
|
ba675c4212 | ||
|
|
6f9bc3135a | ||
|
|
4475d4d018 | ||
|
|
08e45db49d | ||
|
|
85c76065a5 | ||
|
|
13582c3f1b | ||
|
|
ae941a4955 | ||
|
|
72da7ebfe4 | ||
|
|
8e1bacbfac | ||
|
|
747c19c028 | ||
|
|
aca83fc1ee | ||
|
|
35babd089d | ||
|
|
457ea56aab | ||
|
|
ed22de2360 | ||
|
|
8d386b44bc | ||
|
|
c4c88c40c5 | ||
|
|
e637ad6acb | ||
|
|
3b9e08e1c7 | ||
|
|
4a2aa8a975 | ||
|
|
9c08eda38a | ||
|
|
713d972d16 | ||
|
|
d4b3705a9e | ||
|
|
c543d1540c | ||
|
|
2956ff08bd | ||
|
|
ff09dec4e4 | ||
|
|
5e02479aa5 | ||
|
|
6157b9cf82 | ||
|
|
9260633e26 | ||
|
|
1a2ae6b1a8 | ||
|
|
282b4adaff | ||
|
|
8519b5a096 | ||
|
|
4a00be922e | ||
|
|
31f30cf1b1 | ||
|
|
62737cc32f | ||
|
|
c7306b2358 | ||
|
|
779958dfeb | ||
|
|
d0ca6872b0 | ||
|
|
161f191f3d | ||
|
|
2cfa46ed05 | ||
|
|
005e2b3fa1 | ||
|
|
3826dfb1d4 | ||
|
|
81bb9a852f | ||
|
|
37e60673d7 | ||
|
|
9b618f7ecc | ||
|
|
0ce3ceb900 | ||
|
|
4833226241 | ||
|
|
5cae964a1e | ||
|
|
70eaa35bc9 | ||
|
|
38bd3fede1 | ||
|
|
e1e32a7f5e | ||
|
|
b77d0fb47a | ||
|
|
4076b2f900 | ||
|
|
1bc409b54a | ||
|
|
1247a0ade9 | ||
|
|
2fd688ff9e | ||
|
|
b0274946bf | ||
|
|
b78c132742 | ||
|
|
b33c46de82 | ||
|
|
25c8bba1b0 | ||
|
|
089f5cb7ec | ||
|
|
95a6a9dca6 | ||
|
|
e19759a7e4 | ||
|
|
8f95ffeebf | ||
|
|
98f08feb16 | ||
|
|
50baaffc36 | ||
|
|
66e9f43bba | ||
|
|
0cb13bb6a3 |
No files matched your search
@@ -1,57 +1,54 @@
|
||||
name: EhViewer
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 1.8
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle/caches
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Build
|
||||
env:
|
||||
KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASS }}
|
||||
ALIAS_NAME: ${{ secrets.ALIAS_NAME }}
|
||||
ALIAS_PASS: ${{ secrets.ALIAS_PASS }}
|
||||
distribution: temurin
|
||||
java-version: 11
|
||||
|
||||
- name: Setup Android SDK Tools
|
||||
uses: android-actions/setup-android@v2
|
||||
|
||||
- name: Install NDK
|
||||
run: |
|
||||
./gradlew assembleRelease
|
||||
echo ::set-env name=APK_FILE::$(find app/build/outputs/apk -name "*.apk")
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@latest
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;24.0.8215888" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
|
||||
- name: Gradle Build
|
||||
uses: gradle/gradle-build-action@v2
|
||||
- run: |
|
||||
git submodule update --init --recursive
|
||||
gradle assembleRelease
|
||||
|
||||
- name: Update ARM64
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
tag_name: 1.7.4_${{ github.run_id }}
|
||||
release_name: 1.7.4_${{ github.run_id }}
|
||||
body: ""
|
||||
draft: false
|
||||
prerelease: true
|
||||
- name: Upload Release Asset
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: arm64-${{ github.sha }}
|
||||
path: app/build/outputs/apk/release/app-arm64-v8a-release.apk
|
||||
|
||||
- name: Update x86_64
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: ${{ env.APK_FILE }}
|
||||
asset_name: app-release.apk
|
||||
asset_content_type: application/vnd.android.package-archive
|
||||
- uses: actions/upload-artifact@master
|
||||
name: Upload artifact
|
||||
name: x86_64-${{ github.sha }}
|
||||
path: app/build/outputs/apk/release/app-x86_64-release.apk
|
||||
|
||||
- name: Update ARM32
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: EhViewer
|
||||
path: app/build/outputs/
|
||||
name: armeabi-v7a-${{ github.sha }}
|
||||
path: app/build/outputs/apk/release/app-armeabi-v7a-release.apk
|
||||
|
||||
- name: Update x86
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: x86-${{ github.sha }}
|
||||
path: app/build/outputs/apk/release/app-x86-release.apk
|
||||
@@ -0,0 +1,43 @@
|
||||
name: Releases
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 11
|
||||
|
||||
- name: Setup Android SDK Tools
|
||||
uses: android-actions/setup-android@v2
|
||||
|
||||
- name: Install NDK
|
||||
run: |
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;24.0.8215888" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
|
||||
- name: Gradle Build
|
||||
uses: gradle/gradle-build-action@v2
|
||||
- run: |
|
||||
git submodule update --init --recursive
|
||||
gradle assembleRelease
|
||||
|
||||
- name: Releases
|
||||
uses: softprops/action-gh-release@v0.1.14
|
||||
with:
|
||||
body: Bump Version
|
||||
files: |
|
||||
app/build/outputs/apk/release/app-arm64-v8a-release.apk
|
||||
app/build/outputs/apk/release/app-x86_64-release.apk
|
||||
app/build/outputs/apk/release/app-x86-release.apk
|
||||
app/build/outputs/apk/release/app-armeabi-v7a-release.apk
|
||||
@@ -1,12 +1,21 @@
|
||||
[submodule "native/src/main/jni/a7zip/p7zip/p7zip"]
|
||||
path = native/src/main/jni/a7zip/p7zip/p7zip
|
||||
url = https://github.com/seven332/p7zip.git
|
||||
[submodule "native/src/main/jni/image/libjpeg-turbo/libjpeg-turbo"]
|
||||
path = native/src/main/jni/image/libjpeg-turbo/libjpeg-turbo
|
||||
url = https://gitlab.com/NekoInverter/libjpeg-turbo.git
|
||||
url = https://github.com/asuka-mio/libjpeg-turbo
|
||||
[submodule "native/src/main/jni/image/giflib/giflib"]
|
||||
path = native/src/main/jni/image/giflib/giflib
|
||||
url = https://gitlab.com/NekoInverter/giflib.git
|
||||
[submodule "native/src/main/jni/image/libpng/libpng"]
|
||||
path = native/src/main/jni/image/libpng/libpng
|
||||
url = https://gitlab.com/NekoInverter/libpng.git
|
||||
[submodule "native/src/main/jni/libarchive"]
|
||||
path = native/src/main/jni/libarchive
|
||||
url = https://github.com/asuka-mio/libarchive
|
||||
[submodule "native/src/main/jni/liblzma"]
|
||||
path = native/src/main/jni/liblzma
|
||||
url = https://git.tukaani.org/xz.git
|
||||
[submodule "native/src/main/jni/libzstd"]
|
||||
path = native/src/main/jni/libzstd
|
||||
url = https://github.com/facebook/zstd
|
||||
[submodule "native/src/main/jni/libfuse/libfuse"]
|
||||
path = native/src/main/jni/libfuse/libfuse
|
||||
url = https://github.com/libfuse/libfuse/
|
||||
@@ -1,21 +1,59 @@
|
||||
### [下载](https://install.appcenter.ms/users/nekoinverter/apps/ehviewer/distribution_groups/public)
|
||||
<h1 align="center">
|
||||
<img src="art/launcher_icon-web.png" width="200">
|
||||
<br>EhViewer<br>
|
||||
</h1>
|
||||
|
||||
[Download](https://install.appcenter.ms/users/nekoinverter/apps/ehviewer/distribution_groups/public)
|
||||
<p align="center">
|
||||
<a href="https://github.com/asuka-mio/Ehviewer/actions">
|
||||
<img src="https://img.shields.io/github/workflow/status/asuka-mio/Ehviewer/EhViewer" alt="Github Actions">
|
||||
</a>
|
||||
<a href="https://github.com/asuka-mio/Ehviewer/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/asuka-mio/Ehviewer" alt="LICENSE">
|
||||
</a>
|
||||
<a href="https://www.codefactor.io/repository/github/asuka-mio/ehviewer">
|
||||
<img src="https://www.codefactor.io/repository/github/asuka-mio/ehviewer/badge" alt="CodeFactor">
|
||||
</a>
|
||||
<a href="https://github.com/asuka-mio/Ehviewer/releases">
|
||||
<img src="https://img.shields.io/github/v/release/asuka-mio/ehviewer?include_prereleases" alt="Release">
|
||||
</a>
|
||||
<a href="https://github.com/asuka-mio/Ehviewer/issues">
|
||||
<img src="https://img.shields.io/github/issues/asuka-mio/ehviewer" alt="Issues">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
# EhViewer
|
||||
# Description
|
||||
这是一个 E-Hentai Android 平台的浏览器
|
||||
|
||||

|
||||
已针对性适配 Material Design 3 及其动态取色系统
|
||||
|
||||
仅供 Android 12 及以上平台使用!
|
||||
|
||||
这是一个 E-Hentai Android 平台的浏览器。
|
||||
|
||||
An E-Hentai Application for Android.
|
||||
|
||||
with Material Design 3 and Dynamic Color Support.
|
||||
|
||||
Only Support Android S and above!
|
||||
|
||||
# Download
|
||||
|
||||
[Github 下载](https://github.com/asuka-mio/Ehviewer/releases)
|
||||
|
||||
# Screenshot
|
||||
|
||||

|
||||
|
||||
|
||||
# Build
|
||||
|
||||
本项目使用了 CMake 3.23.1 作为构建工具链之一,而当前版本的 Android Studio SDK Tool 无法满足本项目需求。
|
||||
|
||||
因此,在构建本项目前需要提前配置好 CMake >=3.23.1。
|
||||
|
||||
This Project use CMake 3.23.1, with is highter than Android Studio bundle CMake.
|
||||
|
||||
So you need to pre-install CMake>=3.23.1 before build.
|
||||
|
||||
# Thanks
|
||||
|
||||
本项目受到了诸多开源项目的帮助
|
||||
@@ -36,6 +74,8 @@ Here is the libraries
|
||||
- [ShowcaseView](https://github.com/amlcurran/ShowcaseView)
|
||||
- [Slabo](https://github.com/TiroTypeworks/Slabo)
|
||||
- [TagSoup](http://home.ccil.org/~cowan/tagsoup/)
|
||||
- [libarchive](http://www.libarchive.org/)
|
||||
- [XZ Utils](https://tukaani.org/xz/)
|
||||
|
||||
|
||||
# License
|
||||
|
||||
@@ -17,27 +17,29 @@ android {
|
||||
abi {
|
||||
enable = true
|
||||
reset()
|
||||
include 'arm64-v8a', 'x86_64'
|
||||
include 'arm64-v8a', 'x86_64', 'armeabi-v7a', 'x86'
|
||||
}
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
if (localProperties.getProperty("storeFile") != null) {
|
||||
sign {
|
||||
storeFile file(localProperties.getProperty("storeFile"))
|
||||
storePassword localProperties.getProperty("storePassword")
|
||||
keyAlias localProperties.getProperty("keyAlias")
|
||||
keyPassword localProperties.getProperty("keyPassword")
|
||||
}
|
||||
sign {
|
||||
storeFile file(signStoreFile)
|
||||
storePassword signStorePassword
|
||||
keyAlias signkeyAlias
|
||||
keyPassword signkeyPassword
|
||||
}
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
compose true
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "io.github.nekoinverter.ehviewer"
|
||||
applicationId "moe.tarsin.ehviewer"
|
||||
minSdkVersion 31
|
||||
targetSdkVersion 32
|
||||
versionCode 114516
|
||||
versionName "1.7.26.7"
|
||||
versionCode 114525
|
||||
versionName "1.7.27.5"
|
||||
resConfigs 'zh', 'zh-rCN', 'zh-rHK', 'zh-rTW', 'es', 'ja', 'ko', 'fr', 'de', 'th'
|
||||
}
|
||||
|
||||
@@ -72,17 +74,11 @@ android {
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
proguardFiles 'proguard-rules.pro'
|
||||
if (localProperties.getProperty("storeFile") != null) {
|
||||
signingConfig signingConfigs.sign
|
||||
}
|
||||
signingConfig signingConfigs.sign
|
||||
}
|
||||
debug {
|
||||
applicationIdSuffix ".debug"
|
||||
if (localProperties.getProperty("storeFile") != null) {
|
||||
signingConfig signingConfigs.sign
|
||||
} else {
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +87,10 @@ android {
|
||||
java.srcDirs += 'src/main/java-gen'
|
||||
}
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion compose
|
||||
}
|
||||
namespace 'com.hippo.ehviewer'
|
||||
}
|
||||
|
||||
@@ -100,7 +100,8 @@ tasks.withType(JavaCompile) {
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.activity:activity:1.4.0'
|
||||
implementation 'androidx.biometric:biometric:1.1.0'
|
||||
implementation 'androidx.activity:activity-compose:1.4.0'
|
||||
implementation 'androidx.biometric:biometric-ktx:1.2.0-alpha04'
|
||||
implementation 'androidx.browser:browser:1.4.0'
|
||||
implementation 'androidx.core:core:1.7.0'
|
||||
implementation 'androidx.dynamicanimation:dynamicanimation:1.1.0-alpha03'
|
||||
@@ -115,29 +116,34 @@ dependencies {
|
||||
implementation 'com.github.seven332:beerbelly:0.1.4'
|
||||
implementation 'com.github.seven332:glgallery:0.1.2'
|
||||
implementation 'com.github.seven332:glview:0.1.0'
|
||||
implementation 'com.github.seven332:glview-image:0.1.0'
|
||||
implementation 'com.github.seven332:glview-image:0.1.3'
|
||||
implementation 'com.github.seven332:streampipe:0.1.0'
|
||||
implementation 'com.github.seven332:tuxiang:0.1.6'
|
||||
implementation 'com.github.seven332:unifile:9ec57bcd8f'
|
||||
implementation 'com.github.seven332:yorozuya-thread:0.1.1'
|
||||
implementation 'com.github.seven332:yorozuya-collect:0.1.4'
|
||||
implementation 'com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:1.0.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.9.2'
|
||||
implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.2'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
|
||||
implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.3'
|
||||
implementation 'com.takisoft.preferencex:preferencex:1.1.0'
|
||||
implementation 'com.gitlab.NekoInverter:yorozuya:723dc867a9'
|
||||
implementation 'dev.rikka.rikkax.appcompat:appcompat:1.4.1'
|
||||
implementation 'dev.rikka.rikkax.core:core:1.3.4'
|
||||
implementation 'dev.rikka.rikkax.core:core:1.4.0'
|
||||
implementation 'dev.rikka.rikkax.insets:insets:1.2.0'
|
||||
implementation 'dev.rikka.rikkax.layoutinflater:layoutinflater:1.2.0'
|
||||
implementation 'dev.rikka.rikkax.material:material:1.6.6'
|
||||
implementation 'dev.rikka.rikkax.material:material:2.4.0'
|
||||
implementation 'dev.rikka.rikkax.recyclerview:recyclerview-ktx:1.3.1'
|
||||
implementation 'dev.rikka.rikkax.widget:borderview:1.1.0'
|
||||
implementation 'dev.rikka.rikkax.preference:simplemenu-preference:1.0.3'
|
||||
implementation 'org.ccil.cowan.tagsoup:tagsoup:1.2.1'
|
||||
implementation 'org.greenrobot:greendao:3.3.0'
|
||||
implementation 'org.jsoup:jsoup:1.14.3'
|
||||
implementation 'org.jsoup:jsoup:1.15.1'
|
||||
implementation projects.native
|
||||
|
||||
implementation "androidx.compose.material3:material3:1.0.0-alpha12"
|
||||
|
||||
implementation "androidx.compose.ui:ui:$compose"
|
||||
implementation "androidx.compose.ui:ui-util:$compose"
|
||||
implementation "androidx.compose.animation:animation-graphics:$compose"
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
|
||||
@@ -91,8 +91,7 @@
|
||||
android:name="com.hippo.ehviewer.ui.GalleryActivity"
|
||||
android:configChanges="screenSize"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/AppTheme.Gallery">
|
||||
android:launchMode="singleTask">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
package androidx.recyclerview.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class BridgeRecyclerView extends RecyclerView {
|
||||
public BridgeRecyclerView(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public BridgeRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public BridgeRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
void scrollStep(int dx, int dy, @Nullable int[] consumed) {
|
||||
try {
|
||||
super.scrollStep(dx, dy, consumed);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean scrollByInternal(int x, int y, MotionEvent ev, int type) {
|
||||
return super.scrollByInternal(x, y, ev, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
try {
|
||||
super.onLayout(changed, l, t, r, b);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import com.hippo.conaco.ConacoTask;
|
||||
import com.hippo.conaco.Unikery;
|
||||
import com.hippo.image.ImageBitmap;
|
||||
import com.hippo.image.ImageDrawable;
|
||||
import com.hippo.image.RecycledException;
|
||||
import com.hippo.widget.ObservedTextView;
|
||||
|
||||
public class UnikeryDrawable extends WrapDrawable implements Unikery<ImageBitmap>,
|
||||
@@ -127,7 +126,7 @@ public class UnikeryDrawable extends WrapDrawable implements Unikery<ImageBitmap
|
||||
ImageDrawable drawable;
|
||||
try {
|
||||
drawable = new ImageDrawable(value);
|
||||
} catch (RecycledException e) {
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "The ImageBitmap is recycled", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
|
||||
package com.hippo.easyrecyclerview;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
@@ -26,33 +24,20 @@ import android.util.SparseBooleanArray;
|
||||
import android.view.ActionMode;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.widget.Checkable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.collection.LongSparseArray;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.recyclerview.widget.BridgeRecyclerView;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
||||
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.yorozuya.NumberUtils;
|
||||
|
||||
/**
|
||||
* Add setChoiceMode for RecyclerView
|
||||
*/
|
||||
// Get some code from twoway-view and AbsListView.
|
||||
public class EasyRecyclerView extends BridgeRecyclerView {
|
||||
|
||||
/**
|
||||
* Represents an invalid position. All valid positions are in the range 0 to 1 less than the
|
||||
* number of items in the current adapter.
|
||||
*/
|
||||
public static final int INVALID_POSITION = -1;
|
||||
public class EasyRecyclerView extends RecyclerView {
|
||||
|
||||
/**
|
||||
* Normal list that does not indicate choices
|
||||
@@ -78,14 +63,8 @@ public class EasyRecyclerView extends BridgeRecyclerView {
|
||||
* The list allows multiple choices in custom action
|
||||
*/
|
||||
public static final int CHOICE_MODE_MULTIPLE_CUSTOM = 4;
|
||||
private static final float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9));
|
||||
// Fling friction
|
||||
private final float mFlingFriction = ViewConfiguration.getScrollFriction();
|
||||
public float pageScrollThreshold;
|
||||
double flingMoveDistanceX;
|
||||
double flingMoveDistanceY;
|
||||
boolean canScrollVertical = true;
|
||||
boolean canScrollHorizontally = true;
|
||||
/**
|
||||
* Wrapper for the multiple choice mode callback; AbsListView needs to perform
|
||||
* a few extra actions around what application code does.
|
||||
@@ -131,30 +110,20 @@ public class EasyRecyclerView extends BridgeRecyclerView {
|
||||
private LongSparseArray<Integer> mCheckedIdStates;
|
||||
|
||||
private Adapter<?> mAdapter;
|
||||
private boolean isScrollBefore = false;
|
||||
private int initialTouchX;
|
||||
private int initialTouchY;
|
||||
// A context-specific coefficient adjusted to physical values.
|
||||
private float mPhysicalCoeff;
|
||||
private int defaultOverflowItemScrollKeep;
|
||||
private boolean enableScroll = false;
|
||||
|
||||
public EasyRecyclerView(Context context) {
|
||||
super(context);
|
||||
EasyRecyclerView.this.init(context);
|
||||
setEnableScroll(!Settings.getEInkMode());
|
||||
}
|
||||
|
||||
public EasyRecyclerView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
EasyRecyclerView.this.init(context);
|
||||
setEnableScroll(!Settings.getEInkMode());
|
||||
}
|
||||
|
||||
public EasyRecyclerView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
EasyRecyclerView.this.init(context);
|
||||
setEnableScroll(!Settings.getEInkMode());
|
||||
}
|
||||
|
||||
public static void setViewChecked(View view, boolean checked) {
|
||||
@@ -202,18 +171,7 @@ public class EasyRecyclerView extends BridgeRecyclerView {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of items currently selected. This will only be valid
|
||||
* if the choice mode is not {@link #CHOICE_MODE_NONE} (default).
|
||||
*
|
||||
* <p>To determine the specific items that are currently selected, use one of
|
||||
* the <code>getChecked*</code> methods.
|
||||
*
|
||||
* @return The number of items currently selected
|
||||
* @see #getCheckedItemPosition()
|
||||
* @see #getCheckedItemPositions()
|
||||
* @see #getCheckedItemIds()
|
||||
*/
|
||||
|
||||
public int getCheckedItemCount() {
|
||||
return mCheckedItemCount;
|
||||
}
|
||||
@@ -237,22 +195,6 @@ public class EasyRecyclerView extends BridgeRecyclerView {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently checked item. The result is only valid if the choice
|
||||
* mode has been set to {@link #CHOICE_MODE_SINGLE}.
|
||||
*
|
||||
* @return The position of the currently checked item or
|
||||
* {@link #INVALID_POSITION} if nothing is selected
|
||||
* @see #setChoiceMode(int)
|
||||
*/
|
||||
public int getCheckedItemPosition() {
|
||||
if (mChoiceMode == CHOICE_MODE_SINGLE && mCheckStates != null && mCheckStates.size() == 1) {
|
||||
return mCheckStates.keyAt(0);
|
||||
}
|
||||
|
||||
return INVALID_POSITION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of checked items in the list. The result is only valid if
|
||||
* the choice mode has not been set to {@link #CHOICE_MODE_NONE}.
|
||||
@@ -269,30 +211,6 @@ public class EasyRecyclerView extends BridgeRecyclerView {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of checked items ids. The result is only valid if the
|
||||
* choice mode has not been set to {@link #CHOICE_MODE_NONE} and the adapter
|
||||
* has stable IDs. ({@link android.widget.ListAdapter#hasStableIds()} == {@code true})
|
||||
*
|
||||
* @return A new array which contains the id of each checked item in the
|
||||
* list.
|
||||
*/
|
||||
public long[] getCheckedItemIds() {
|
||||
if (mChoiceMode == CHOICE_MODE_NONE || mCheckedIdStates == null || mAdapter == null) {
|
||||
return new long[0];
|
||||
}
|
||||
|
||||
final LongSparseArray<Integer> idStates = mCheckedIdStates;
|
||||
final int count = idStates.size();
|
||||
final long[] ids = new long[count];
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ids[i] = idStates.keyAt(i);
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
public boolean isInCustomChoice() {
|
||||
return mCustomChoice;
|
||||
}
|
||||
@@ -475,14 +393,6 @@ public class EasyRecyclerView extends BridgeRecyclerView {
|
||||
updateOnScreenCheckedViews();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The current choice mode
|
||||
* @see #setChoiceMode(int)
|
||||
*/
|
||||
public int getChoiceMode() {
|
||||
return mChoiceMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the choice behavior for the List. By default, Lists do not have any choice behavior
|
||||
* ({@link #CHOICE_MODE_NONE}). By setting the choiceMode to {@link #CHOICE_MODE_SINGLE}, the
|
||||
@@ -518,24 +428,6 @@ public class EasyRecyclerView extends BridgeRecyclerView {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a {@link MultiChoiceModeListener} that will manage the lifecycle of the
|
||||
* selection {@link android.view.ActionMode}. Only used when the choice mode is set to
|
||||
* {@link #CHOICE_MODE_MULTIPLE_MODAL}.
|
||||
*
|
||||
* @param listener Listener that will manage the selection mode
|
||||
* @see #setChoiceMode(int)
|
||||
*/
|
||||
public void setMultiChoiceModeListener(MultiChoiceModeListener listener) {
|
||||
if (mMultiChoiceModeCallback == null) {
|
||||
mMultiChoiceModeCallback = new MultiChoiceModeWrapper();
|
||||
}
|
||||
mMultiChoiceModeCallback.setWrapped(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param listener
|
||||
*/
|
||||
public void setCustomCheckedListener(CustomChoiceListener listener) {
|
||||
mCustomChoiceListener = listener;
|
||||
}
|
||||
@@ -556,299 +448,13 @@ public class EasyRecyclerView extends BridgeRecyclerView {
|
||||
|
||||
private void init(Context context) {
|
||||
float scale = context.getResources().getDisplayMetrics().density;
|
||||
final float ppi = scale * 160.0f;
|
||||
mPhysicalCoeff = SensorManager.GRAVITY_EARTH // g (m/s^2)
|
||||
* 39.37f // inch/meter
|
||||
* ppi
|
||||
* 0.84f; // look and feel tuning
|
||||
// g (m/s^2)
|
||||
// inch/meter
|
||||
// A context-specific coefficient adjusted to physical values.
|
||||
// look and feel tuning
|
||||
pageScrollThreshold = scale * 80;
|
||||
}
|
||||
|
||||
public void setPageScrollThreshold(float pageScrollThreshold) {
|
||||
this.pageScrollThreshold = pageScrollThreshold;
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent e) {
|
||||
if (enableScroll) {
|
||||
return super.onTouchEvent(e);
|
||||
}
|
||||
boolean superTouchResult = super.onTouchEvent(e);
|
||||
if (superTouchResult) {
|
||||
switch (e.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
initialTouchX = (int) (e.getX() + 0.5f);
|
||||
initialTouchY = (int) (e.getY() + 0.5f);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (initialTouchX < 0 || initialTouchY < 0) {
|
||||
initialTouchX = (int) (e.getX() + 0.5f);
|
||||
initialTouchY = (int) (e.getY() + 0.5f);
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (isScrollBefore) {
|
||||
int moveDistanceX = (int) (initialTouchX - e.getX() + flingMoveDistanceX);
|
||||
int moveDistanceY = (int) (initialTouchY - e.getY() + flingMoveDistanceY);
|
||||
onTouchScroll(moveDistanceX, moveDistanceY);
|
||||
initialTouchX = initialTouchY = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
isScrollBefore = getScrollState() == SCROLL_STATE_DRAGGING;
|
||||
}
|
||||
return superTouchResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean scrollByInternal(int x, int y, MotionEvent ev, int type) {
|
||||
if (enableScroll) {
|
||||
return super.scrollByInternal(x, y, ev, type);
|
||||
}
|
||||
//disable drag scroll effect,e-ink screen don't need it
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fling(int velocityX, int velocityY) {
|
||||
if (enableScroll) {
|
||||
return super.fling(velocityX, velocityY);
|
||||
}
|
||||
flingMoveDistanceX = getSplineFlingDistance(velocityX) * Math.signum(velocityX);
|
||||
flingMoveDistanceY = getSplineFlingDistance(velocityY) * Math.signum(velocityY);
|
||||
//disable fling scroll effect,e-ink screen don't need it
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void onTouchScroll(int dx, int dy) {
|
||||
canScrollVertical = true;
|
||||
canScrollHorizontally = true;
|
||||
LayoutManager layout = getLayoutManager();
|
||||
if (layout != null) {
|
||||
if (dy > pageScrollThreshold) {
|
||||
if (canScrollVertical && layout.canScrollVertically()) {
|
||||
canScrollVertical = false;
|
||||
onScrollDown();
|
||||
} else if (canScrollHorizontally && layout.canScrollHorizontally()) {
|
||||
canScrollHorizontally = false;
|
||||
onScrollRight();
|
||||
}
|
||||
} else if (dy < -pageScrollThreshold) {
|
||||
if (canScrollVertical && layout.canScrollVertically()) {
|
||||
canScrollVertical = false;
|
||||
onScrollUp();
|
||||
} else if (canScrollHorizontally && layout.canScrollHorizontally()) {
|
||||
canScrollHorizontally = false;
|
||||
onScrollLeft();
|
||||
}
|
||||
}
|
||||
|
||||
if (dx > pageScrollThreshold) {
|
||||
if (canScrollVertical && layout.canScrollVertically()) {
|
||||
onScrollDown();
|
||||
} else if (canScrollHorizontally && layout.canScrollHorizontally()) {
|
||||
onScrollRight();
|
||||
}
|
||||
} else if (dx < -pageScrollThreshold) {
|
||||
if (canScrollVertical && layout.canScrollVertically()) {
|
||||
onScrollUp();
|
||||
} else if (canScrollHorizontally && layout.canScrollHorizontally()) {
|
||||
onScrollLeft();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void onScrollLeft() {
|
||||
LayoutManager layout = getLayoutManager();
|
||||
if (layout instanceof LinearLayoutManager) {
|
||||
LinearLayoutManager realLayout = (LinearLayoutManager) layout;
|
||||
int firstVisiblePosition = realLayout.findFirstVisibleItemPosition();
|
||||
ViewHolder firstVisibleItem = findViewHolderForAdapterPosition(firstVisiblePosition);
|
||||
|
||||
if (firstVisibleItem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//when the item width overscreen, findLastCompletelyVisibleItemPosition always return NO_POSITION
|
||||
if (firstVisibleItem.itemView.getMeasuredWidth() > getMeasuredWidth()) {
|
||||
super.scrollByInternal(-getMeasuredWidth() + defaultOverflowItemScrollKeep, 0, null, ViewCompat.TYPE_TOUCH);
|
||||
} else if (firstVisibleItem.itemView.getMeasuredWidth() == getMeasuredWidth()) {
|
||||
super.scrollByInternal(-getMeasuredWidth(), 0, null, ViewCompat.TYPE_TOUCH);
|
||||
} else {
|
||||
super.scrollByInternal(firstVisibleItem.itemView.getRight() - getMeasuredWidth(), 0, null, ViewCompat.TYPE_TOUCH);
|
||||
}
|
||||
} else if (layout instanceof StaggeredGridLayoutManager) {
|
||||
StaggeredGridLayoutManager realLayout = (StaggeredGridLayoutManager) layout;
|
||||
int[] firstVisiblePosition = realLayout.findFirstVisibleItemPositions(null);
|
||||
ViewHolder[] firstVisibleItems = new ViewHolder[firstVisiblePosition.length];
|
||||
for (int i = 0; i < firstVisiblePosition.length; i++) {
|
||||
firstVisibleItems[i] = findViewHolderForAdapterPosition(firstVisiblePosition[i]);
|
||||
}
|
||||
int scrollDistance = Integer.MAX_VALUE;
|
||||
for (ViewHolder firstVisibleItem : firstVisibleItems) {
|
||||
if (firstVisibleItem != null) {
|
||||
if (firstVisibleItem.itemView.getRight() < scrollDistance) {
|
||||
scrollDistance = firstVisibleItem.itemView.getRight();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scrollDistance == getMeasuredWidth()) {
|
||||
scrollDistance = 0;
|
||||
}
|
||||
super.scrollByInternal(scrollDistance - getMeasuredWidth(), 0, null, ViewCompat.TYPE_TOUCH);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onScrollRight() {
|
||||
LayoutManager layout = getLayoutManager();
|
||||
if (layout instanceof LinearLayoutManager) {
|
||||
LinearLayoutManager realLayout = (LinearLayoutManager) layout;
|
||||
int lastVisiblePosition = realLayout.findLastVisibleItemPosition();
|
||||
ViewHolder lastVisibleItem = findViewHolderForAdapterPosition(lastVisiblePosition);
|
||||
|
||||
if (lastVisibleItem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//when the item width overflow screen, findLastCompletelyVisibleItemPosition always return NO_POSITION
|
||||
if (lastVisibleItem.itemView.getMeasuredWidth() > getMeasuredWidth()) {
|
||||
super.scrollByInternal(getMeasuredWidth() - defaultOverflowItemScrollKeep, 0, null, ViewCompat.TYPE_TOUCH);
|
||||
} else if (lastVisibleItem.itemView.getMeasuredWidth() == getMeasuredWidth()) {
|
||||
super.scrollByInternal(getMeasuredWidth(), 0, null, ViewCompat.TYPE_TOUCH);
|
||||
} else {
|
||||
super.scrollByInternal(lastVisibleItem.itemView.getLeft(), 0, null, ViewCompat.TYPE_TOUCH);
|
||||
}
|
||||
} else if (layout instanceof StaggeredGridLayoutManager) {
|
||||
StaggeredGridLayoutManager realLayout = (StaggeredGridLayoutManager) layout;
|
||||
int[] lastVisiblePosition = realLayout.findLastVisibleItemPositions(null);
|
||||
ViewHolder[] lastVisibleItems = new ViewHolder[lastVisiblePosition.length];
|
||||
for (int i = 0; i < lastVisiblePosition.length; i++) {
|
||||
lastVisibleItems[i] = findViewHolderForAdapterPosition(lastVisiblePosition[i]);
|
||||
}
|
||||
int scrollDistance = 0;
|
||||
for (ViewHolder lastVisibleItem : lastVisibleItems) {
|
||||
if (lastVisibleItem != null) {
|
||||
if (lastVisibleItem.itemView.getLeft() > scrollDistance) {
|
||||
scrollDistance = lastVisibleItem.itemView.getLeft();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (scrollDistance == 0) {
|
||||
scrollDistance = getMeasuredWidth();
|
||||
}
|
||||
super.scrollByInternal(scrollDistance, 0, null, ViewCompat.TYPE_TOUCH);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onScrollUp() {
|
||||
LayoutManager layout = getLayoutManager();
|
||||
if (layout instanceof LinearLayoutManager) {
|
||||
LinearLayoutManager realLayout = (LinearLayoutManager) layout;
|
||||
int firstVisiblePosition = realLayout.findFirstVisibleItemPosition();
|
||||
ViewHolder firstVisibleItem = findViewHolderForAdapterPosition(firstVisiblePosition);
|
||||
|
||||
if (firstVisibleItem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//when the item height overscreen, findLastCompletelyVisibleItemPosition always return NO_POSITION
|
||||
if (firstVisibleItem.itemView.getMeasuredHeight() > getMeasuredHeight()) {
|
||||
super.scrollByInternal(0, -getMeasuredHeight() + defaultOverflowItemScrollKeep, null, ViewCompat.TYPE_TOUCH);
|
||||
} else if (firstVisibleItem.itemView.getMeasuredHeight() == getMeasuredHeight()) {
|
||||
super.scrollByInternal(0, -getMeasuredHeight(), null, ViewCompat.TYPE_TOUCH);
|
||||
} else {
|
||||
super.scrollByInternal(0, firstVisibleItem.itemView.getBottom() - getMeasuredHeight(), null, ViewCompat.TYPE_TOUCH);
|
||||
}
|
||||
} else if (layout instanceof StaggeredGridLayoutManager) {
|
||||
StaggeredGridLayoutManager realLayout = (StaggeredGridLayoutManager) layout;
|
||||
int[] firstVisiblePosition = realLayout.findFirstVisibleItemPositions(null);
|
||||
ViewHolder[] firstVisibleItems = new ViewHolder[firstVisiblePosition.length];
|
||||
for (int i = 0; i < firstVisiblePosition.length; i++) {
|
||||
firstVisibleItems[i] = findViewHolderForAdapterPosition(firstVisiblePosition[i]);
|
||||
}
|
||||
int scrollDistance = Integer.MAX_VALUE;
|
||||
for (ViewHolder firstVisibleItem : firstVisibleItems) {
|
||||
if (firstVisibleItem != null) {
|
||||
if (firstVisibleItem.itemView.getBottom() < scrollDistance) {
|
||||
scrollDistance = firstVisibleItem.itemView.getBaseline();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (scrollDistance == getMeasuredWidth()) {
|
||||
scrollDistance = 0;
|
||||
}
|
||||
super.scrollByInternal(0, scrollDistance - getMeasuredHeight(), null, ViewCompat.TYPE_TOUCH);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onScrollDown() {
|
||||
LayoutManager layout = getLayoutManager();
|
||||
if (layout instanceof LinearLayoutManager) {
|
||||
LinearLayoutManager realLayout = (LinearLayoutManager) layout;
|
||||
int lastVisiblePosition = realLayout.findLastVisibleItemPosition();
|
||||
ViewHolder lastVisibleItem = findViewHolderForAdapterPosition(lastVisiblePosition);
|
||||
|
||||
if (lastVisibleItem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//when the item height overflow screen, findLastCompletelyVisibleItemPosition always return NO_POSITION
|
||||
if (lastVisibleItem.itemView.getMeasuredHeight() > getMeasuredHeight()) {
|
||||
super.scrollByInternal(0, getMeasuredHeight() - defaultOverflowItemScrollKeep, null, ViewCompat.TYPE_TOUCH);
|
||||
} else if (lastVisibleItem.itemView.getMeasuredHeight() == getMeasuredHeight()) {
|
||||
super.scrollByInternal(0, getMeasuredHeight(), null, ViewCompat.TYPE_TOUCH);
|
||||
} else {
|
||||
super.scrollByInternal(0, lastVisibleItem.itemView.getTop(), null, ViewCompat.TYPE_TOUCH);
|
||||
}
|
||||
} else if (layout instanceof StaggeredGridLayoutManager) {
|
||||
StaggeredGridLayoutManager realLayout = (StaggeredGridLayoutManager) layout;
|
||||
int[] lastVisiblePosition = realLayout.findLastVisibleItemPositions(null);
|
||||
ViewHolder[] lastVisibleItems = new ViewHolder[lastVisiblePosition.length];
|
||||
for (int i = 0; i < lastVisiblePosition.length; i++) {
|
||||
lastVisibleItems[i] = findViewHolderForAdapterPosition(lastVisiblePosition[i]);
|
||||
}
|
||||
int scrollDistance = 0;
|
||||
for (ViewHolder lastVisibleItem : lastVisibleItems) {
|
||||
if (lastVisibleItem != null) {
|
||||
if (lastVisibleItem.itemView.getTop() > scrollDistance) {
|
||||
scrollDistance = lastVisibleItem.itemView.getTop();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (scrollDistance == 0) {
|
||||
scrollDistance = getMeasuredHeight();
|
||||
}
|
||||
super.scrollByInternal(0, scrollDistance, null, ViewCompat.TYPE_TOUCH);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
defaultOverflowItemScrollKeep = (int) (h * 0.05f);
|
||||
}
|
||||
|
||||
private double getSplineDeceleration(int velocity) {
|
||||
return Math.log(0.35f * Math.abs(velocity) / (mFlingFriction * mPhysicalCoeff));
|
||||
}
|
||||
|
||||
private double getSplineFlingDistance(int velocity) {
|
||||
final double l = getSplineDeceleration(velocity);
|
||||
final double decelMinusOne = DECELERATION_RATE - 1.0;
|
||||
return mFlingFriction * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l);
|
||||
}
|
||||
|
||||
public boolean isEnableScroll() {
|
||||
return enableScroll;
|
||||
}
|
||||
|
||||
public void setEnableScroll(boolean enableScroll) {
|
||||
this.enableScroll = enableScroll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parcelable onSaveInstanceState() {
|
||||
final SavedState ss = new SavedState(super.onSaveInstanceState());
|
||||
@@ -1016,9 +622,6 @@ public class EasyRecyclerView extends BridgeRecyclerView {
|
||||
class MultiChoiceModeWrapper implements MultiChoiceModeListener {
|
||||
private MultiChoiceModeListener mWrapped;
|
||||
|
||||
public void setWrapped(MultiChoiceModeListener wrapped) {
|
||||
mWrapped = wrapped;
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean hasWrappedCallback() {
|
||||
|
||||
@@ -297,11 +297,6 @@ public class EhApplication extends SceneApplication {
|
||||
return application.mFavouriteStatusRouter;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String getDeveloperEmail() {
|
||||
return "nekoworkshop$protonmail.com".replace('$', '@');
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
@Override
|
||||
public void onCreate() {
|
||||
|
||||
@@ -86,7 +86,7 @@ public class Settings {
|
||||
****** Advanced
|
||||
********************/
|
||||
public static final String KEY_SAVE_PARSE_ERROR_BODY = "save_parse_error_body";
|
||||
public static final String KEY_SECURITY = "security";
|
||||
public static final String KEY_SECURITY = "require_unlock";
|
||||
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";
|
||||
@@ -457,14 +457,6 @@ public class Settings {
|
||||
putBoolean(KEY_SELECT_SITE, value);
|
||||
}
|
||||
|
||||
public static boolean getQuickSearchTip() {
|
||||
return getBoolean(KEY_QUICK_SEARCH_TIP, DEFAULT_QUICK_SEARCH_TIP);
|
||||
}
|
||||
|
||||
public static void putQuickSearchTip(boolean value) {
|
||||
putBoolean(KEY_QUICK_SEARCH_TIP, value);
|
||||
}
|
||||
|
||||
public static int getTheme() {
|
||||
return getIntFromStr(KEY_THEME, DEFAULT_THEME);
|
||||
}
|
||||
@@ -594,14 +586,6 @@ public class Settings {
|
||||
putString(KEY_EXCLUDED_LANGUAGES, value);
|
||||
}
|
||||
|
||||
public static void putEInkMode(boolean value) {
|
||||
putBoolean(KEY_E_INK_MODE, value);
|
||||
}
|
||||
|
||||
public static boolean getEInkMode() {
|
||||
return getBoolean(KEY_E_INK_MODE, DEFAULT_E_INK_MODE);
|
||||
}
|
||||
|
||||
public static boolean getMeteredNetworkWarning() {
|
||||
return getBoolean(KEY_METERED_NETWORK_WARNING, DEFAULT_METERED_NETWORK_WARNING);
|
||||
}
|
||||
@@ -1044,22 +1028,18 @@ public class Settings {
|
||||
return getBoolean(KEY_SAVE_CRASH_LOG, DEFAULT_SAVE_CRASH_LOG);
|
||||
}
|
||||
|
||||
public static String getSecurity() {
|
||||
return getString(KEY_SECURITY, DEFAULT_SECURITY);
|
||||
public static boolean getSecurity() {
|
||||
return getBoolean(KEY_SECURITY, false);
|
||||
}
|
||||
|
||||
public static void putSecurity(String value) {
|
||||
putString(KEY_SECURITY, value);
|
||||
public static void putSecurity(boolean value) {
|
||||
putBoolean(KEY_SECURITY, value);
|
||||
}
|
||||
|
||||
public static boolean getEnableFingerprint() {
|
||||
return getBoolean(KEY_ENABLE_FINGERPRINT, true);
|
||||
}
|
||||
|
||||
public static void putEnableFingerprint(boolean value) {
|
||||
putBoolean(KEY_ENABLE_FINGERPRINT, value);
|
||||
}
|
||||
|
||||
public static int getReadCacheSize() {
|
||||
return getIntFromStr(KEY_READ_CACHE_SIZE, DEFAULT_READ_CACHE_SIZE);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import androidx.annotation.Nullable;
|
||||
import androidx.core.app.NotificationChannelCompat;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.R;
|
||||
@@ -224,8 +223,6 @@ public class DownloadService extends Service implements DownloadManager.Download
|
||||
.setOngoing(true)
|
||||
.setAutoCancel(false)
|
||||
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
|
||||
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
|
||||
.setColorized(true)
|
||||
.addAction(R.drawable.v_pause_x24, getString(R.string.stat_download_action_stop_all), piStopAll)
|
||||
.setShowWhen(false)
|
||||
.setChannelId(CHANNEL_ID);
|
||||
@@ -254,7 +251,6 @@ public class DownloadService extends Service implements DownloadManager.Download
|
||||
mDownloadedBuilder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download_done)
|
||||
.setContentTitle(getString(R.string.stat_download_done_title))
|
||||
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
|
||||
.setDeleteIntent(piClear)
|
||||
.setOngoing(false)
|
||||
.setAutoCancel(true)
|
||||
@@ -273,7 +269,6 @@ public class DownloadService extends Service implements DownloadManager.Download
|
||||
.setContentText(getString(R.string.stat_509_alert_title))
|
||||
.setContentText(getString(R.string.stat_509_alert_text))
|
||||
.setStyle(new NotificationCompat.BigTextStyle().bigText(getString(R.string.stat_509_alert_text)))
|
||||
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
|
||||
.setAutoCancel(true)
|
||||
.setOngoing(false)
|
||||
.setCategory(NotificationCompat.CATEGORY_ERROR);
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.gallery;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.hippo.a7zip.ArchiveException;
|
||||
import com.hippo.a7zip.InArchive;
|
||||
import com.hippo.a7zip.PropID;
|
||||
import com.hippo.a7zip.PropType;
|
||||
import com.hippo.a7zip.SeekableInputStream;
|
||||
import com.hippo.unifile.UniRandomAccessFile;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class A7ZipArchive implements Closeable {
|
||||
|
||||
private final InArchive archive;
|
||||
|
||||
private A7ZipArchive(InArchive archive) {
|
||||
this.archive = archive;
|
||||
}
|
||||
|
||||
private static boolean isSupportedFilename(String name) {
|
||||
for (String extension : GalleryProvider2.SUPPORT_IMAGE_EXTENSIONS) {
|
||||
if (name.endsWith(extension)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static A7ZipArchive create(UniRandomAccessFile file) throws ArchiveException {
|
||||
SeekableInputStream store = new UniRandomAccessFileInStream(file);
|
||||
InArchive archive = InArchive.open(store);
|
||||
if ((archive.getArchivePropertyType(PropID.ENCRYPTED) == PropType.BOOL && archive.getArchiveBooleanProperty(PropID.ENCRYPTED))
|
||||
|| (archive.getArchivePropertyType(PropID.SOLID) == PropType.BOOL && archive.getArchiveBooleanProperty(PropID.SOLID))
|
||||
|| (archive.getArchivePropertyType(PropID.IS_VOLUME) == PropType.BOOL && archive.getArchiveBooleanProperty(PropID.IS_VOLUME))) {
|
||||
throw new ArchiveException("Unsupported archive");
|
||||
}
|
||||
return new A7ZipArchive(archive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
archive.close();
|
||||
}
|
||||
|
||||
List<A7ZipArchiveEntry> getArchiveEntries() {
|
||||
List<A7ZipArchiveEntry> entries = new ArrayList<>();
|
||||
|
||||
for (int i = 0, n = archive.getNumberOfEntries(); i < n; i++) {
|
||||
if (!archive.getEntryBooleanProperty(i, PropID.ENCRYPTED)
|
||||
&& !archive.getEntryBooleanProperty(i, PropID.IS_DIR)
|
||||
&& !archive.getEntryBooleanProperty(i, PropID.IS_VOLUME)
|
||||
&& !archive.getEntryBooleanProperty(i, PropID.SOLID)) {
|
||||
String path = archive.getEntryPath(i);
|
||||
if (isSupportedFilename(path.toLowerCase())) {
|
||||
entries.add(new A7ZipArchiveEntry(archive, i, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
static class A7ZipArchiveEntry {
|
||||
|
||||
private final InArchive archive;
|
||||
private final int index;
|
||||
private final String path;
|
||||
|
||||
private A7ZipArchiveEntry(InArchive archive, int index, String path) {
|
||||
this.archive = archive;
|
||||
this.index = index;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
void extract(OutputStream os) throws ArchiveException {
|
||||
archive.extractEntry(index, new OutputStreamSequentialOutStream(os));
|
||||
}
|
||||
}
|
||||
|
||||
private static class UniRandomAccessFileInStream extends SeekableInputStream {
|
||||
|
||||
private final byte[] scratch = new byte[8];
|
||||
private final UniRandomAccessFile file;
|
||||
|
||||
public UniRandomAccessFileInStream(UniRandomAccessFile file) {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seek(long pos) throws IOException {
|
||||
file.seek(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long tell() throws IOException {
|
||||
return file.getFilePointer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long size() throws IOException {
|
||||
return file.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return (file.read(scratch, 0, 1) != -1) ? scratch[0] & 0xff : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(@NonNull byte[] b) throws IOException {
|
||||
return file.read(b, 0, b.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
return file.read(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static class OutputStreamSequentialOutStream extends OutputStream {
|
||||
|
||||
private final OutputStream stream;
|
||||
|
||||
public OutputStreamSequentialOutStream(OutputStream stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
stream.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
stream.write(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,23 +23,18 @@ import android.os.Process;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.hippo.a7zip.ArchiveException;
|
||||
import com.hippo.UriArchiveAccessor;
|
||||
import com.hippo.ehviewer.GetText;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.glgallery.GalleryPageView;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.unifile.UniRandomAccessFile;
|
||||
import com.hippo.util.NaturalComparator;
|
||||
import com.hippo.yorozuya.thread.PriorityThread;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -47,15 +42,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
|
||||
private static final AtomicInteger sIdGenerator = new AtomicInteger();
|
||||
private static final Comparator<A7ZipArchive.A7ZipArchiveEntry> naturalComparator = new Comparator<A7ZipArchive.A7ZipArchiveEntry>() {
|
||||
private final NaturalComparator comparator = new NaturalComparator();
|
||||
|
||||
@Override
|
||||
public int compare(A7ZipArchive.A7ZipArchiveEntry o1, A7ZipArchive.A7ZipArchiveEntry o2) {
|
||||
return comparator.compare(o1.getPath(), o2.getPath());
|
||||
}
|
||||
};
|
||||
private final UniFile file;
|
||||
private final UriArchiveAccessor archiveAccessor;
|
||||
private final Stack<Integer> requests = new Stack<>();
|
||||
private final AtomicInteger extractingIndex = new AtomicInteger(GalleryPageView.INVALID_INDEX);
|
||||
private final LinkedHashMap<Integer, InputStream> streams = new LinkedHashMap<>();
|
||||
@@ -66,7 +53,14 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
private String error;
|
||||
|
||||
public ArchiveGalleryProvider(Context context, Uri uri) {
|
||||
file = UniFile.fromMediaUri(context, uri);
|
||||
UriArchiveAccessor archiveAccessor1;
|
||||
try {
|
||||
archiveAccessor1 = new UriArchiveAccessor(context, uri);
|
||||
} catch (FileNotFoundException e) {
|
||||
archiveAccessor1 = null;
|
||||
e.printStackTrace();
|
||||
}
|
||||
archiveAccessor = archiveAccessor1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,37 +161,14 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
private class ArchiveTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
UniRandomAccessFile uraf = null;
|
||||
try {
|
||||
uraf = file.createRandomAccessFile("r");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (uraf == null) {
|
||||
size = archiveAccessor.open();
|
||||
if (size <= 0) {
|
||||
size = STATE_ERROR;
|
||||
error = GetText.getString(R.string.error_reading_failed);
|
||||
notifyDataChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
A7ZipArchive archive = null;
|
||||
try {
|
||||
archive = A7ZipArchive.create(uraf);
|
||||
} catch (ArchiveException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (archive == null) {
|
||||
size = STATE_ERROR;
|
||||
error = GetText.getString(R.string.error_invalid_archive);
|
||||
notifyDataChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
List<A7ZipArchive.A7ZipArchiveEntry> entries = archive.getArchiveEntries();
|
||||
Collections.sort(entries, naturalComparator);
|
||||
|
||||
// Update size and notify changed
|
||||
size = entries.size();
|
||||
notifyDataChanged();
|
||||
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
@@ -217,13 +188,13 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
}
|
||||
|
||||
// Check index valid
|
||||
if (index < 0 || index >= entries.size()) {
|
||||
if (index < 0 || index >= size) {
|
||||
extractingIndex.lazySet(GalleryPageView.INVALID_INDEX);
|
||||
notifyPageFailed(index, GetText.getString(R.string.error_out_of_range));
|
||||
continue;
|
||||
}
|
||||
|
||||
Pipe pipe = new Pipe(4 * 1024);
|
||||
Pipe pipe = new Pipe(4096);
|
||||
|
||||
synchronized (streams) {
|
||||
if (streams.get(index) != null) {
|
||||
@@ -233,13 +204,7 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
streams.notify();
|
||||
}
|
||||
|
||||
try {
|
||||
entries.get(index).extract(pipe.getOutputStream());
|
||||
} catch (ArchiveException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
extractingIndex.lazySet(GalleryPageView.INVALID_INDEX);
|
||||
}
|
||||
archiveAccessor.extractTargetIndexToOutputStream(index, pipe.getOutputStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,4 +247,4 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,13 +107,6 @@ class Pipe {
|
||||
public void write(@NonNull byte[] b, int off, int len) throws IOException {
|
||||
synchronized (Pipe.this) {
|
||||
while (len != 0) {
|
||||
if (outClosed) {
|
||||
throw new IOException("The OutputStream is closed");
|
||||
}
|
||||
if (inClosed) {
|
||||
throw new IOException("The InputStream is closed");
|
||||
}
|
||||
|
||||
if (head == tail && full) {
|
||||
// The buffer is full, wait for InputStream read bytes
|
||||
try {
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
public class VersionPreference extends Preference {
|
||||
|
||||
public VersionPreference(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public VersionPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public VersionPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
setTitle(R.string.settings_about_version);
|
||||
|
||||
String version;
|
||||
try {
|
||||
PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
|
||||
version = pInfo.versionName;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
version = context.getString(R.string.error_unknown);
|
||||
}
|
||||
setSummary(version);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.hippo.ehviewer.preference
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.util.AttributeSet
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.hippo.Native
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.preference.MessagePreference
|
||||
|
||||
class VersionPreference @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null
|
||||
) : MessagePreference(context, attrs) {
|
||||
init {
|
||||
setTitle(R.string.settings_about_version)
|
||||
val version: String = try {
|
||||
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
|
||||
pInfo.versionName
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
e.printStackTrace()
|
||||
context.getString(R.string.error_unknown)
|
||||
}
|
||||
summary = version
|
||||
}
|
||||
|
||||
override fun onPrepareDialogBuilder(builder: AlertDialog.Builder) {
|
||||
super.onPrepareDialogBuilder(builder)
|
||||
builder.setTitle(R.string.show_library_version)
|
||||
builder.setMessage(Native.getlibarchiveVersion() + "\nlzma(xz-utils) " + Native.getliblzmaVersion() + "\nlibzstd " + Native.getlibzstdVersion() + "\nzlib " + Native.getzlibVersion() + "\nlibjpeg-turbo " + Native.getlibjpeg_turboVersion())
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.Window;
|
||||
import android.view.WindowInsets;
|
||||
@@ -47,10 +46,8 @@ public abstract class EhActivity extends MaterialActivity {
|
||||
}
|
||||
|
||||
public static String getTheme(Context context) {
|
||||
if (isBlackNightTheme()
|
||||
&& isNightMode(context.getResources().getConfiguration()))
|
||||
if (isBlackNightTheme() && isNightMode(context.getResources().getConfiguration()))
|
||||
return THEME_BLACK;
|
||||
|
||||
return THEME_DEFAULT;
|
||||
}
|
||||
|
||||
@@ -70,26 +67,21 @@ public abstract class EhActivity extends MaterialActivity {
|
||||
|
||||
@StyleRes
|
||||
public int getThemeStyleRes(Context context) {
|
||||
switch (getTheme(context)) {
|
||||
case THEME_BLACK:
|
||||
return R.style.ThemeOverlay_Black;
|
||||
case THEME_DEFAULT:
|
||||
default:
|
||||
return R.style.ThemeOverlay;
|
||||
if (THEME_BLACK.equals(getTheme(context))) {
|
||||
return R.style.ThemeOverlay_Black;
|
||||
}
|
||||
return R.style.ThemeOverlay;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
((EhApplication) getApplication()).registerActivity(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
((EhApplication) getApplication()).unregisterActivity(this);
|
||||
}
|
||||
|
||||
@@ -114,14 +106,10 @@ public abstract class EhActivity extends MaterialActivity {
|
||||
WindowInsets rootWindowInsets = window.getDecorView().getRootWindowInsets();
|
||||
if (rootWindowInsets != null && rootWindowInsets.getSystemWindowInsetBottom() >= Resources.getSystem().getDisplayMetrics().density * 40) {
|
||||
window.setNavigationBarColor(ResourcesKt.resolveColor(getTheme(), android.R.attr.navigationBarColor) & 0x00ffffff | -0x20000000);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
window.setNavigationBarContrastEnforced(false);
|
||||
}
|
||||
window.setNavigationBarContrastEnforced(false);
|
||||
} else {
|
||||
window.setNavigationBarColor(Color.TRANSPARENT);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
window.setNavigationBarContrastEnforced(true);
|
||||
}
|
||||
window.setNavigationBarContrastEnforced(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ import android.webkit.MimeTypeMap;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
@@ -66,6 +65,7 @@ import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.core.view.WindowInsetsControllerCompat;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial;
|
||||
import com.hippo.ehviewer.AppConfig;
|
||||
import com.hippo.ehviewer.BuildConfig;
|
||||
import com.hippo.ehviewer.R;
|
||||
@@ -221,16 +221,7 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
private int mLayoutMode;
|
||||
private int mSize;
|
||||
private int mCurrentIndex;
|
||||
private int mSavingPage = -1; 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;
|
||||
});
|
||||
private int mSavingPage = -1;
|
||||
|
||||
private void buildProvider() {
|
||||
if (mGalleryProvider != null) {
|
||||
@@ -247,13 +238,9 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
}
|
||||
} else if (Intent.ACTION_VIEW.equals(mAction)) {
|
||||
if (mUri != null) {
|
||||
// Only support zip now
|
||||
try {
|
||||
grantUriPermission(BuildConfig.APPLICATION_ID, mUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
} catch (Exception e) {
|
||||
// Some stupid file manager send us a uri and don't allow us to read it
|
||||
// java.lang.SecurityException: UID 10671 does not have permission to
|
||||
// content://com.UCMobile.fileProvider/external_files/BaiduNetdisk/getvoice [user 0]
|
||||
Toast.makeText(this, R.string.error_reading_failed, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
mGalleryProvider = new ArchiveGalleryProvider(this, mUri);
|
||||
@@ -283,7 +270,16 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
mPage = savedInstanceState.getInt(KEY_PAGE, -1);
|
||||
mCurrentIndex = savedInstanceState.getInt(KEY_CURRENT_INDEX);
|
||||
buildProvider();
|
||||
}
|
||||
} 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 onSaveInstanceState(@NonNull Bundle outState) {
|
||||
@@ -1051,15 +1047,15 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
private final Spinner mScaleMode;
|
||||
private final Spinner mStartPosition;
|
||||
private final Spinner mReadTheme;
|
||||
private final Switch mKeepScreenOn;
|
||||
private final Switch mShowClock;
|
||||
private final Switch mShowProgress;
|
||||
private final Switch mShowBattery;
|
||||
private final Switch mShowPageInterval;
|
||||
private final Switch mVolumePage;
|
||||
private final Switch mReverseVolumePage;
|
||||
private final Switch mReadingFullscreen;
|
||||
private final Switch mCustomScreenLightness;
|
||||
private final SwitchMaterial mKeepScreenOn;
|
||||
private final SwitchMaterial mShowClock;
|
||||
private final SwitchMaterial mShowProgress;
|
||||
private final SwitchMaterial mShowBattery;
|
||||
private final SwitchMaterial mShowPageInterval;
|
||||
private final SwitchMaterial mVolumePage;
|
||||
private final SwitchMaterial mReverseVolumePage;
|
||||
private final SwitchMaterial mReadingFullscreen;
|
||||
private final SwitchMaterial mCustomScreenLightness;
|
||||
private final SeekBar mScreenLightness;
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
@@ -1304,4 +1300,6 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -22,18 +22,15 @@ import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.verify.domain.DomainVerificationManager;
|
||||
import android.content.pm.verify.domain.DomainVerificationUserState;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
@@ -43,7 +40,6 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
@@ -85,7 +81,6 @@ import com.hippo.unifile.UniFile;
|
||||
import com.hippo.util.BitmapUtils;
|
||||
import com.hippo.util.ClipboardUtil;
|
||||
import com.hippo.widget.DrawerView;
|
||||
import com.hippo.widget.LoadImageView;
|
||||
import com.hippo.yorozuya.IOUtils;
|
||||
import com.hippo.yorozuya.SimpleHandler;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
@@ -96,8 +91,6 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
|
||||
import rikka.material.app.DayNightDelegate;
|
||||
|
||||
public final class MainActivity extends StageActivity
|
||||
implements NavigationView.OnNavigationItemSelectedListener {
|
||||
|
||||
@@ -139,10 +132,6 @@ public final class MainActivity extends StageActivity
|
||||
private NavigationView mNavView;
|
||||
@Nullable
|
||||
private DrawerView mRightDrawer;
|
||||
@Nullable
|
||||
private LoadImageView mAvatar;
|
||||
@Nullable
|
||||
private TextView mDisplayName;
|
||||
private int mNavCheckedItem = 0;
|
||||
|
||||
@Override
|
||||
@@ -153,7 +142,7 @@ public final class MainActivity extends StageActivity
|
||||
@NonNull
|
||||
@Override
|
||||
protected Announcer getLaunchAnnouncer() {
|
||||
if (!TextUtils.isEmpty(Settings.getSecurity())) {
|
||||
if (Settings.getSecurity() && SecurityScene.Companion.isAuthenticationSupported(this)) {
|
||||
return new Announcer(SecurityScene.class);
|
||||
} else if (Settings.getShowWarning()) {
|
||||
return new Announcer(WarningScene.class);
|
||||
@@ -171,7 +160,7 @@ public final class MainActivity extends StageActivity
|
||||
// Sometimes scene can't show directly
|
||||
private Announcer processAnnouncer(Announcer announcer) {
|
||||
if (0 == getSceneCount()) {
|
||||
if (!TextUtils.isEmpty(Settings.getSecurity())) {
|
||||
if (Settings.getSecurity() && SecurityScene.Companion.isAuthenticationSupported(this)) {
|
||||
Bundle newArgs = new Bundle();
|
||||
newArgs.putString(SecurityScene.KEY_TARGET_SCENE, announcer.getClazz().getName());
|
||||
newArgs.putBundle(SecurityScene.KEY_TARGET_ARGS, announcer.getArgs());
|
||||
@@ -320,19 +309,6 @@ public final class MainActivity extends StageActivity
|
||||
mDrawerLayout.setStatusBarBackgroundColor(0);
|
||||
mNavView = (NavigationView) ViewUtils.$$(this, R.id.nav_view);
|
||||
mRightDrawer = (DrawerView) ViewUtils.$$(this, R.id.right_drawer);
|
||||
View headerLayout = mNavView.getHeaderView(0);
|
||||
mAvatar = (LoadImageView) ViewUtils.$$(headerLayout, R.id.avatar);
|
||||
mDisplayName = (TextView) ViewUtils.$$(headerLayout, R.id.display_name);
|
||||
ViewUtils.$$(headerLayout, R.id.night_mode).setOnClickListener(v -> {
|
||||
int theme = (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_YES) > 0 ? DayNightDelegate.MODE_NIGHT_NO : DayNightDelegate.MODE_NIGHT_YES;
|
||||
DayNightDelegate.setDefaultNightMode(theme);
|
||||
recreate();
|
||||
if (Settings.getTheme() != AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) {
|
||||
Settings.putTheme(theme);
|
||||
}
|
||||
});
|
||||
|
||||
updateProfile();
|
||||
|
||||
if (mNavView != null) {
|
||||
mNavView.setNavigationItemSelectedListener(this);
|
||||
@@ -440,23 +416,18 @@ public final class MainActivity extends StageActivity
|
||||
mDrawerLayout = null;
|
||||
mNavView = null;
|
||||
mRightDrawer = null;
|
||||
mAvatar = null;
|
||||
mDisplayName = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
setNavCheckedItem(mNavCheckedItem);
|
||||
|
||||
checkClipboardUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTransactScene() {
|
||||
super.onTransactScene();
|
||||
|
||||
checkClipboardUrl();
|
||||
}
|
||||
|
||||
@@ -546,25 +517,6 @@ public final class MainActivity extends StageActivity
|
||||
}
|
||||
}
|
||||
|
||||
public void updateProfile() {
|
||||
if (null == mAvatar || null == mDisplayName) {
|
||||
return;
|
||||
}
|
||||
|
||||
String avatarUrl = Settings.getAvatar();
|
||||
if (TextUtils.isEmpty(avatarUrl)) {
|
||||
mAvatar.load(R.drawable.default_avatar);
|
||||
} else {
|
||||
mAvatar.load(avatarUrl, avatarUrl);
|
||||
}
|
||||
|
||||
String displayName = Settings.getDisplayName();
|
||||
if (TextUtils.isEmpty(displayName)) {
|
||||
displayName = getString(R.string.default_display_name);
|
||||
}
|
||||
mDisplayName.setText(displayName);
|
||||
}
|
||||
|
||||
public void addAboveSnackView(View view) {
|
||||
if (mStageLayout != null) {
|
||||
mStageLayout.addAboveSnackView(view);
|
||||
|
||||
@@ -21,40 +21,19 @@ import android.os.Bundle;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.text.Html;
|
||||
import com.hippo.util.AppHelper;
|
||||
|
||||
public class AboutFragment extends BasePreferenceFragment {
|
||||
|
||||
private static final String KEY_AUTHOR = "author";
|
||||
//private static final String KEY_DONATE = "donate";
|
||||
private static final String KEY_CHECK_FOR_UPDATES = "check_for_updates";
|
||||
|
||||
@Override
|
||||
public void onCreatePreferencesFix(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
addPreferencesFromResource(R.xml.about_settings);
|
||||
|
||||
Preference author = findPreference(KEY_AUTHOR);
|
||||
//Preference donate = findPreference(KEY_DONATE);
|
||||
Preference checkForUpdate = findPreference(KEY_CHECK_FOR_UPDATES);
|
||||
|
||||
author.setSummary(Html.fromHtml(getString(R.string.settings_about_author_summary).replace('$', '@')));
|
||||
|
||||
author.setOnPreferenceClickListener(this);
|
||||
//donate.setOnPreferenceClickListener(this);
|
||||
checkForUpdate.setOnPreferenceClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
String key = preference.getKey();
|
||||
if (KEY_AUTHOR.equals(key)) {
|
||||
AppHelper.sendEmail(requireActivity(), EhApplication.getDeveloperEmail(),
|
||||
"About EhViewer", null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.hippo.ehviewer.ui.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
|
||||
/**
|
||||
* Created by Mo10 on 2018/2/10.
|
||||
*/
|
||||
|
||||
public class PrivacyFragment extends BasePreferenceFragment {
|
||||
private static final String KEY_PATTERN_PROTECTION = "pattern_protection";
|
||||
|
||||
@Override
|
||||
public void onCreatePreferencesFix(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
addPreferencesFromResource(R.xml.privacy_settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
Preference patternProtection = findPreference(KEY_PATTERN_PROTECTION);
|
||||
patternProtection.setSummary(TextUtils.isEmpty(Settings.getSecurity()) ?
|
||||
R.string.settings_privacy_pattern_protection_not_set :
|
||||
R.string.settings_privacy_pattern_protection_set);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFragmentTitle() {
|
||||
return R.string.settings_privacy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.hippo.ehviewer.ui.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.ui.scene.SecurityScene.Companion.isAuthenticationSupported
|
||||
|
||||
/**
|
||||
* Created by Mo10 on 2018/2/10.
|
||||
*/
|
||||
class PrivacyFragment : BasePreferenceFragment() {
|
||||
override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.privacy_settings)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
if (!isAuthenticationSupported(requireContext())) {
|
||||
Settings.putSecurity(false)
|
||||
findPreference<SwitchPreferenceCompat>("require_unlock")?.isEnabled = false
|
||||
findPreference<SwitchPreferenceCompat>("require_unlock")?.isChecked = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFragmentTitle(): Int {
|
||||
return R.string.settings_privacy
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package com.hippo.ehviewer.ui.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.biometric.BiometricManager;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.widget.lockpattern.LockPatternUtils;
|
||||
import com.hippo.widget.lockpattern.LockPatternView;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
public class SetSecurityFragment extends BaseFragment implements View.OnClickListener {
|
||||
|
||||
@Nullable
|
||||
private LockPatternView mPatternView;
|
||||
@Nullable
|
||||
private View mCancel;
|
||||
@Nullable
|
||||
private View mSet;
|
||||
@Nullable
|
||||
private CheckBox mFingerprint;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.activity_set_security, container, false);
|
||||
|
||||
mPatternView = (LockPatternView) ViewUtils.$$(view, R.id.pattern_view);
|
||||
mCancel = ViewUtils.$$(view, R.id.cancel);
|
||||
mSet = ViewUtils.$$(view, R.id.set);
|
||||
mFingerprint = (CheckBox) ViewUtils.$$(view, R.id.fingerprint_checkbox);
|
||||
|
||||
String pattern = Settings.getSecurity();
|
||||
if (!TextUtils.isEmpty(pattern)) {
|
||||
mPatternView.setPattern(LockPatternView.DisplayMode.Correct,
|
||||
LockPatternUtils.stringToPattern(pattern));
|
||||
}
|
||||
|
||||
if (BiometricManager.from(requireContext()).canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS) {
|
||||
mFingerprint.setVisibility(View.VISIBLE);
|
||||
mFingerprint.setChecked(Settings.getEnableFingerprint());
|
||||
}
|
||||
|
||||
mCancel.setOnClickListener(this);
|
||||
mSet.setOnClickListener(this);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mPatternView = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == mCancel) {
|
||||
requireActivity().onBackPressed();
|
||||
} else if (v == mSet) {
|
||||
if (null != mPatternView && null != mFingerprint) {
|
||||
String security;
|
||||
if (mPatternView.getCellSize() <= 1) {
|
||||
security = "";
|
||||
} else {
|
||||
security = mPatternView.getPatternString();
|
||||
}
|
||||
Settings.putSecurity(security);
|
||||
Settings.putEnableFingerprint(mFingerprint.getVisibility() == View.VISIBLE &&
|
||||
mFingerprint.isChecked() && !security.isEmpty());
|
||||
}
|
||||
requireActivity().onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFragmentTitle() {
|
||||
return R.string.set_pattern_protection;
|
||||
}
|
||||
}
|
||||
@@ -58,13 +58,6 @@ public abstract class BaseScene extends SceneFragment {
|
||||
private SparseArray<Parcelable> drawerViewState;
|
||||
private boolean needWhiteStatusBar = needWhiteStatusBar();
|
||||
|
||||
public void updateAvatar() {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity instanceof MainActivity) {
|
||||
((MainActivity) activity).updateProfile();
|
||||
}
|
||||
}
|
||||
|
||||
public void addAboveSnackView(View view) {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity instanceof MainActivity) {
|
||||
|
||||
@@ -468,7 +468,6 @@ public class DownloadsScene extends ToolbarScene
|
||||
TapTarget.forBounds(bounds,
|
||||
getString(R.string.guide_download_labels_title),
|
||||
getString(R.string.guide_download_labels_text))
|
||||
.outerCircleColor(R.color.colorPrimary)
|
||||
.transparentTarget(true),
|
||||
new TapTargetView.Listener() {
|
||||
@Override
|
||||
|
||||
@@ -68,6 +68,7 @@ import com.hippo.ehviewer.client.data.FavListUrlBuilder;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.client.parser.FavoritesParser;
|
||||
import com.hippo.ehviewer.ui.CommonOperations;
|
||||
import com.hippo.ehviewer.ui.EhActivity;
|
||||
import com.hippo.ehviewer.ui.MainActivity;
|
||||
import com.hippo.ehviewer.ui.annotation.DrawerLifeCircle;
|
||||
import com.hippo.ehviewer.ui.annotation.ViewLifeCircle;
|
||||
@@ -290,7 +291,13 @@ public class FavoritesScene extends BaseScene implements
|
||||
updateSearchBar();
|
||||
mSearchBarMover = new SearchBarMover(this, mSearchBar, mRecyclerView);
|
||||
|
||||
mActionFabDrawable = new AddDeleteDrawable(context, resources.getColor(R.color.primary_drawable_dark));
|
||||
int colorID;
|
||||
if (EhActivity.isNightMode(context.getResources().getConfiguration())) {
|
||||
colorID = resources.getColor(android.R.color.white, getTheme());
|
||||
} else {
|
||||
colorID = resources.getColor(android.R.color.black, getTheme());
|
||||
}
|
||||
mActionFabDrawable = new AddDeleteDrawable(context, colorID);
|
||||
mFabLayout.getPrimaryFab().setImageDrawable(mActionFabDrawable);
|
||||
mFabLayout.setExpanded(false, false);
|
||||
mFabLayout.setAutoCancel(true);
|
||||
@@ -334,7 +341,6 @@ public class FavoritesScene extends BaseScene implements
|
||||
TapTarget.forBounds(bounds,
|
||||
getString(R.string.guide_collections_title),
|
||||
getString(R.string.guide_collections_text))
|
||||
.outerCircleColor(R.color.colorPrimary)
|
||||
.transparentTarget(true),
|
||||
new TapTargetView.Listener() {
|
||||
@Override
|
||||
|
||||
@@ -69,7 +69,6 @@ import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter;
|
||||
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange;
|
||||
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager;
|
||||
import com.h6ah4i.android.widget.advrecyclerview.utils.AbstractDraggableItemViewHolder;
|
||||
import com.hippo.app.CheckBoxDialogBuilder;
|
||||
import com.hippo.app.EditTextDialogBuilder;
|
||||
import com.hippo.drawable.AddDeleteDrawable;
|
||||
import com.hippo.drawable.DrawerArrowDrawable;
|
||||
@@ -97,6 +96,7 @@ import com.hippo.ehviewer.dao.DownloadLabel;
|
||||
import com.hippo.ehviewer.dao.QuickSearch;
|
||||
import com.hippo.ehviewer.download.DownloadManager;
|
||||
import com.hippo.ehviewer.ui.CommonOperations;
|
||||
import com.hippo.ehviewer.ui.EhActivity;
|
||||
import com.hippo.ehviewer.ui.GalleryActivity;
|
||||
import com.hippo.ehviewer.ui.MainActivity;
|
||||
import com.hippo.ehviewer.ui.dialog.SelectItemWithIconAdapter;
|
||||
@@ -614,7 +614,13 @@ public final class GalleryListScene extends BaseScene
|
||||
mFabLayout.setOnExpandListener(this);
|
||||
addAboveSnackView(mFabLayout);
|
||||
|
||||
mActionFabDrawable = new AddDeleteDrawable(context, resources.getColor(R.color.primary_drawable_dark));
|
||||
int colorID;
|
||||
if (EhActivity.isNightMode(context.getResources().getConfiguration())) {
|
||||
colorID = resources.getColor(android.R.color.white, getTheme());
|
||||
} else {
|
||||
colorID = resources.getColor(android.R.color.black, getTheme());
|
||||
}
|
||||
mActionFabDrawable = new AddDeleteDrawable(context, colorID);
|
||||
mFabLayout.getPrimaryFab().setImageDrawable(mActionFabDrawable);
|
||||
|
||||
mSearchFab.setOnClickListener(this);
|
||||
@@ -658,7 +664,6 @@ public final class GalleryListScene extends BaseScene
|
||||
TapTarget.forBounds(bounds,
|
||||
getString(R.string.guide_quick_search_title),
|
||||
getString(R.string.guide_quick_search_text))
|
||||
.outerCircleColor(R.color.colorPrimary)
|
||||
.transparentTarget(true),
|
||||
new TapTargetView.Listener() {
|
||||
@Override
|
||||
@@ -709,15 +714,10 @@ public final class GalleryListScene extends BaseScene
|
||||
if (null == context) {
|
||||
return;
|
||||
}
|
||||
final CheckBoxDialogBuilder builder = new CheckBoxDialogBuilder(
|
||||
context, getString(R.string.add_quick_search_tip), getString(R.string.get_it), false);
|
||||
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context);
|
||||
builder.setMessage(R.string.add_quick_search_tip);
|
||||
builder.setTitle(R.string.readme);
|
||||
builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
if (builder.isChecked()) {
|
||||
Settings.putQuickSearchTip(false);
|
||||
}
|
||||
showAddQuickSearchDialog(adapter, recyclerView, tip);
|
||||
}).show();
|
||||
builder.show();
|
||||
}
|
||||
|
||||
|
||||
@@ -823,11 +823,9 @@ public final class GalleryListScene extends BaseScene
|
||||
toolbar.setOnMenuItemClickListener(item -> {
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.action_add) {
|
||||
if (Settings.getQuickSearchTip()) {
|
||||
showQuickSearchTipDialog(qsDrawerAdapter, recyclerView, tip);
|
||||
} else {
|
||||
showAddQuickSearchDialog(qsDrawerAdapter, recyclerView, tip);
|
||||
}
|
||||
showAddQuickSearchDialog(qsDrawerAdapter, recyclerView, tip);
|
||||
} else if (id == R.id.action_help) {
|
||||
showQuickSearchTipDialog(qsDrawerAdapter, recyclerView, tip);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -1,193 +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.scene;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.biometric.BiometricManager;
|
||||
import androidx.biometric.BiometricPrompt;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.ehviewer.ui.MainActivity;
|
||||
import com.hippo.widget.lockpattern.LockPatternUtils;
|
||||
import com.hippo.widget.lockpattern.LockPatternView;
|
||||
import com.hippo.yorozuya.ObjectUtils;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class SecurityScene extends SolidScene implements
|
||||
LockPatternView.OnPatternListener {
|
||||
|
||||
private static final int MAX_RETRY_TIMES = 5;
|
||||
private static final String KEY_RETRY_TIMES = "retry_times";
|
||||
|
||||
@Nullable
|
||||
private LockPatternView mPatternView;
|
||||
|
||||
private SensorManager mSensorManager;
|
||||
private Sensor mAccelerometer;
|
||||
private BiometricPrompt.PromptInfo promptInfo;
|
||||
private BiometricPrompt biometricPrompt;
|
||||
private boolean canAuthenticate = false;
|
||||
|
||||
private int mRetryTimes;
|
||||
|
||||
@Override
|
||||
public boolean needShowLeftDrawer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Context context = requireContext();
|
||||
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
||||
if (null != mSensorManager) {
|
||||
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
}
|
||||
|
||||
if (null == savedInstanceState) {
|
||||
mRetryTimes = MAX_RETRY_TIMES;
|
||||
} else {
|
||||
mRetryTimes = savedInstanceState.getInt(KEY_RETRY_TIMES);
|
||||
}
|
||||
|
||||
canAuthenticate = Settings.getEnableFingerprint() &&
|
||||
BiometricManager.from(requireContext()).canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS;
|
||||
biometricPrompt = new BiometricPrompt(this, Executors.newSingleThreadExecutor(), new BiometricPrompt.AuthenticationCallback() {
|
||||
@Override
|
||||
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
|
||||
super.onAuthenticationError(errorCode, errString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
|
||||
startSceneForCheckStep(CHECK_STEP_SECURITY, getArguments());
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailed() {
|
||||
super.onAuthenticationFailed();
|
||||
}
|
||||
});
|
||||
promptInfo = new BiometricPrompt.PromptInfo.Builder()
|
||||
.setTitle(getString(R.string.app_name))
|
||||
.setNegativeButtonText(getString(android.R.string.cancel))
|
||||
.setConfirmationRequired(false)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
mSensorManager = null;
|
||||
mAccelerometer = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (canAuthenticate) {
|
||||
startBiometricPrompt();
|
||||
}
|
||||
}
|
||||
|
||||
private void startBiometricPrompt() {
|
||||
biometricPrompt.authenticate(promptInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt(KEY_RETRY_TIMES, mRetryTimes);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.scene_security, container, false);
|
||||
if (canAuthenticate) {
|
||||
view.setOnClickListener(v -> startBiometricPrompt());
|
||||
}
|
||||
|
||||
mPatternView = (LockPatternView) ViewUtils.$$(view, R.id.pattern_view);
|
||||
mPatternView.setOnPatternListener(this);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
mPatternView = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPatternStart() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPatternCleared() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPatternDetected(List<LockPatternView.Cell> pattern) {
|
||||
MainActivity activity = getMainActivity();
|
||||
if (null == activity || null == mPatternView) {
|
||||
return;
|
||||
}
|
||||
|
||||
String enteredPatter = LockPatternUtils.patternToString(pattern);
|
||||
String targetPatter = Settings.getSecurity();
|
||||
|
||||
if (ObjectUtils.equal(enteredPatter, targetPatter)) {
|
||||
startSceneForCheckStep(CHECK_STEP_SECURITY, getArguments());
|
||||
finish();
|
||||
} else {
|
||||
mPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
|
||||
mRetryTimes--;
|
||||
if (mRetryTimes <= 0) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2022 tarsin norbin
|
||||
*
|
||||
* 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.scene
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import androidx.biometric.BiometricManager
|
||||
import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
||||
import androidx.biometric.BiometricPrompt
|
||||
import androidx.biometric.auth.AuthPromptCallback
|
||||
import androidx.biometric.auth.startClass2BiometricOrCredentialAuthentication
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.hippo.ehviewer.R
|
||||
|
||||
class SecurityScene : SolidScene() {
|
||||
override fun needShowLeftDrawer(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (isAuthenticationSupported(requireContext()))
|
||||
startAuthentication(getString(R.string.settings_privacy_require_unlock))
|
||||
else
|
||||
startSceneForCheckStep(CHECK_STEP_SECURITY, arguments)
|
||||
}
|
||||
|
||||
private fun startAuthentication(
|
||||
title: String,
|
||||
subtitle: String? = null,
|
||||
confirmationRequired: Boolean = true,
|
||||
) {
|
||||
startClass2BiometricOrCredentialAuthentication(
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
confirmationRequired = confirmationRequired,
|
||||
executor = ContextCompat.getMainExecutor(requireContext()),
|
||||
callback = AuthenticationCallback()
|
||||
)
|
||||
}
|
||||
|
||||
inner class AuthenticationCallback : AuthPromptCallback() {
|
||||
override fun onAuthenticationSucceeded(
|
||||
activity: FragmentActivity?,
|
||||
result: BiometricPrompt.AuthenticationResult
|
||||
) {
|
||||
super.onAuthenticationSucceeded(activity, result)
|
||||
startSceneForCheckStep(CHECK_STEP_SECURITY, arguments)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun isAuthenticationSupported(context: Context): Boolean {
|
||||
val authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK or DEVICE_CREDENTIAL
|
||||
return BiometricManager.from(context)
|
||||
.canAuthenticate(authenticators) == BiometricManager.BIOMETRIC_SUCCESS
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -357,7 +357,6 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
|
||||
|
||||
public void onGetProfileEnd() {
|
||||
mSigningIn = false;
|
||||
updateAvatar();
|
||||
redirectTo();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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.ehviewer.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TableLayout;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.EhConfig;
|
||||
import com.hippo.widget.CheckTextView;
|
||||
import com.hippo.yorozuya.NumberUtils;
|
||||
|
||||
public class CategoryTable extends TableLayout implements View.OnLongClickListener {
|
||||
|
||||
private static final String STATE_KEY_SUPER = "super";
|
||||
private static final String STATE_KEY_CATEGORY = "category";
|
||||
|
||||
private CheckTextView mDoujinshi;
|
||||
private CheckTextView mManga;
|
||||
private CheckTextView mArtistCG;
|
||||
private CheckTextView mGameCG;
|
||||
private CheckTextView mWestern;
|
||||
private CheckTextView mNonH;
|
||||
private CheckTextView mImageSets;
|
||||
private CheckTextView mCosplay;
|
||||
private CheckTextView mAsianPorn;
|
||||
private CheckTextView mMisc;
|
||||
|
||||
private CheckTextView[] mOptions;
|
||||
|
||||
public CategoryTable(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public CategoryTable(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
inflater.inflate(R.layout.widget_category_table, this);
|
||||
|
||||
ViewGroup row0 = (ViewGroup) getChildAt(0);
|
||||
mDoujinshi = (CheckTextView) row0.getChildAt(0);
|
||||
mManga = (CheckTextView) row0.getChildAt(1);
|
||||
|
||||
ViewGroup row1 = (ViewGroup) getChildAt(1);
|
||||
mArtistCG = (CheckTextView) row1.getChildAt(0);
|
||||
mGameCG = (CheckTextView) row1.getChildAt(1);
|
||||
|
||||
ViewGroup row2 = (ViewGroup) getChildAt(2);
|
||||
mWestern = (CheckTextView) row2.getChildAt(0);
|
||||
mNonH = (CheckTextView) row2.getChildAt(1);
|
||||
|
||||
ViewGroup row3 = (ViewGroup) getChildAt(3);
|
||||
mImageSets = (CheckTextView) row3.getChildAt(0);
|
||||
mCosplay = (CheckTextView) row3.getChildAt(1);
|
||||
|
||||
ViewGroup row4 = (ViewGroup) getChildAt(4);
|
||||
mAsianPorn = (CheckTextView) row4.getChildAt(0);
|
||||
mMisc = (CheckTextView) row4.getChildAt(1);
|
||||
|
||||
mOptions = new CheckTextView[]{
|
||||
mDoujinshi, mManga, mArtistCG, mGameCG, mWestern,
|
||||
mNonH, mImageSets, mCosplay, mAsianPorn, mMisc
|
||||
};
|
||||
|
||||
for (CheckTextView option : mOptions) {
|
||||
option.setOnLongClickListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (v instanceof CheckTextView) {
|
||||
boolean checked = ((CheckTextView) v).isChecked();
|
||||
for (CheckTextView option : mOptions) {
|
||||
if (option != v) {
|
||||
option.setChecked(!checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get category according to button.
|
||||
*
|
||||
* @return the category of this view
|
||||
*/
|
||||
public int getCategory() {
|
||||
int category = 0;
|
||||
if (!mDoujinshi.isChecked()) category |= EhConfig.DOUJINSHI;
|
||||
if (!mManga.isChecked()) category |= EhConfig.MANGA;
|
||||
if (!mArtistCG.isChecked()) category |= EhConfig.ARTIST_CG;
|
||||
if (!mGameCG.isChecked()) category |= EhConfig.GAME_CG;
|
||||
if (!mWestern.isChecked()) category |= EhConfig.WESTERN;
|
||||
if (!mNonH.isChecked()) category |= EhConfig.NON_H;
|
||||
if (!mImageSets.isChecked()) category |= EhConfig.IMAGE_SET;
|
||||
if (!mCosplay.isChecked()) category |= EhConfig.COSPLAY;
|
||||
if (!mAsianPorn.isChecked()) category |= EhConfig.ASIAN_PORN;
|
||||
if (!mMisc.isChecked()) category |= EhConfig.MISC;
|
||||
return category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set each button checked or not according to category.
|
||||
*
|
||||
* @param category target category
|
||||
*/
|
||||
public void setCategory(int category) {
|
||||
mDoujinshi.setChecked(!NumberUtils.int2boolean(category & EhConfig.DOUJINSHI));
|
||||
mManga.setChecked(!NumberUtils.int2boolean(category & EhConfig.MANGA));
|
||||
mArtistCG.setChecked(!NumberUtils.int2boolean(category & EhConfig.ARTIST_CG));
|
||||
mGameCG.setChecked(!NumberUtils.int2boolean(category & EhConfig.GAME_CG));
|
||||
mWestern.setChecked(!NumberUtils.int2boolean(category & EhConfig.WESTERN));
|
||||
mNonH.setChecked(!NumberUtils.int2boolean(category & EhConfig.NON_H));
|
||||
mImageSets.setChecked(!NumberUtils.int2boolean(category & EhConfig.IMAGE_SET));
|
||||
mCosplay.setChecked(!NumberUtils.int2boolean(category & EhConfig.COSPLAY));
|
||||
mAsianPorn.setChecked(!NumberUtils.int2boolean(category & EhConfig.ASIAN_PORN));
|
||||
mMisc.setChecked(!NumberUtils.int2boolean(category & EhConfig.MISC));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parcelable onSaveInstanceState() {
|
||||
final Bundle state = new Bundle();
|
||||
state.putParcelable(STATE_KEY_SUPER, super.onSaveInstanceState());
|
||||
state.putInt(STATE_KEY_CATEGORY, getCategory());
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(Parcelable state) {
|
||||
if (state instanceof Bundle) {
|
||||
final Bundle savedState = (Bundle) state;
|
||||
super.onRestoreInstanceState(savedState.getParcelable(STATE_KEY_SUPER));
|
||||
setCategory(savedState.getInt(STATE_KEY_CATEGORY));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,7 +141,7 @@ public final class ImageSearchLayout extends LinearLayout implements View.OnClic
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, os);
|
||||
mImagePath = temp.getPath();
|
||||
mPreview.setImageBitmap(bitmap);
|
||||
mPreview.setVisibility(VISIBLE);
|
||||
((View) mPreview.getParent()).setVisibility(VISIBLE);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
@@ -166,7 +166,7 @@ public final class ImageSearchLayout extends LinearLayout implements View.OnClic
|
||||
}
|
||||
mImagePath = imagePath;
|
||||
mPreview.setImageBitmap(bitmap);
|
||||
mPreview.setVisibility(VISIBLE);
|
||||
((View) mPreview.getParent()).setVisibility(VISIBLE);
|
||||
} catch (FileNotFoundException e) {
|
||||
// Ignore
|
||||
} finally {
|
||||
|
||||
@@ -1,403 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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.ehviewer.widget;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.hippo.easyrecyclerview.EasyRecyclerView;
|
||||
import com.hippo.easyrecyclerview.MarginItemDecoration;
|
||||
import com.hippo.easyrecyclerview.SimpleHolder;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder;
|
||||
import com.hippo.ehviewer.client.exception.EhException;
|
||||
import com.hippo.widget.RadioGridGroup;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnCheckedChangeListener,
|
||||
View.OnClickListener, ImageSearchLayout.Helper, TabLayout.OnTabSelectedListener {
|
||||
|
||||
public static final int SEARCH_MODE_NORMAL = 0;
|
||||
public static final int SEARCH_MODE_IMAGE = 1;
|
||||
private static final String STATE_KEY_SUPER = "super";
|
||||
private static final String STATE_KEY_SEARCH_MODE = "search_mode";
|
||||
private static final String STATE_KEY_ENABLE_ADVANCE = "enable_advance";
|
||||
private static final int ITEM_TYPE_NORMAL = 0;
|
||||
private static final int ITEM_TYPE_NORMAL_ADVANCE = 1;
|
||||
private static final int ITEM_TYPE_IMAGE = 2;
|
||||
private static final int ITEM_TYPE_ACTION = 3;
|
||||
private static final int[] SEARCH_ITEM_COUNT_ARRAY = {
|
||||
3, 2
|
||||
};
|
||||
private static final int[][] SEARCH_ITEM_TYPE = {
|
||||
{ITEM_TYPE_NORMAL, ITEM_TYPE_NORMAL_ADVANCE, ITEM_TYPE_ACTION}, // SEARCH_MODE_NORMAL
|
||||
{ITEM_TYPE_IMAGE, ITEM_TYPE_ACTION}, // SEARCH_MODE_IMAGE
|
||||
};
|
||||
private LayoutInflater mInflater;
|
||||
@SearchMode
|
||||
private int mSearchMode = SEARCH_MODE_NORMAL;
|
||||
private boolean mEnableAdvance = false;
|
||||
private View mNormalView;
|
||||
private CategoryTable mCategoryTable;
|
||||
private RadioGridGroup mNormalSearchMode;
|
||||
private ImageView mNormalSearchModeHelp;
|
||||
private Switch mEnableAdvanceSwitch;
|
||||
private View mAdvanceView;
|
||||
private AdvanceSearchTable mTableAdvanceSearch;
|
||||
private ImageSearchLayout mImageView;
|
||||
private View mActionView;
|
||||
private TabLayout mAction;
|
||||
private LinearLayoutManager mLayoutManager;
|
||||
private SearchAdapter mAdapter;
|
||||
private Helper mHelper;
|
||||
|
||||
public SearchLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public SearchLayout(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init(context);
|
||||
}
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
private void init(Context context) {
|
||||
Resources resources = context.getResources();
|
||||
mInflater = LayoutInflater.from(context);
|
||||
|
||||
mLayoutManager = new SearchLayoutManager(context);
|
||||
mAdapter = new SearchAdapter();
|
||||
mAdapter.setHasStableIds(true);
|
||||
setLayoutManager(mLayoutManager);
|
||||
setAdapter(mAdapter);
|
||||
setHasFixedSize(true);
|
||||
setClipToPadding(false);
|
||||
((DefaultItemAnimator) getItemAnimator()).setSupportsChangeAnimations(false);
|
||||
int interval = resources.getDimensionPixelOffset(R.dimen.search_layout_interval);
|
||||
int paddingH = resources.getDimensionPixelOffset(R.dimen.search_layout_margin_h);
|
||||
int paddingV = resources.getDimensionPixelOffset(R.dimen.search_layout_margin_v);
|
||||
MarginItemDecoration decoration = new MarginItemDecoration(
|
||||
interval, paddingH, paddingV, paddingH, paddingV);
|
||||
addItemDecoration(decoration);
|
||||
decoration.applyPaddings(this);
|
||||
|
||||
// Create normal view
|
||||
View normalView = mInflater.inflate(R.layout.search_normal, null);
|
||||
mNormalView = normalView;
|
||||
mCategoryTable = normalView.findViewById(R.id.search_category_table);
|
||||
mNormalSearchMode = normalView.findViewById(R.id.normal_search_mode);
|
||||
mNormalSearchModeHelp = normalView.findViewById(R.id.normal_search_mode_help);
|
||||
mEnableAdvanceSwitch = normalView.findViewById(R.id.search_enable_advance);
|
||||
mNormalSearchModeHelp.setOnClickListener(this);
|
||||
mEnableAdvanceSwitch.setOnCheckedChangeListener(this);
|
||||
mEnableAdvanceSwitch.setSwitchPadding(resources.getDimensionPixelSize(R.dimen.switch_padding));
|
||||
|
||||
// Create advance view
|
||||
mAdvanceView = mInflater.inflate(R.layout.search_advance, null);
|
||||
mTableAdvanceSearch = mAdvanceView.findViewById(R.id.search_advance_search_table);
|
||||
|
||||
// Create image view
|
||||
mImageView = (ImageSearchLayout) mInflater.inflate(R.layout.search_image, null);
|
||||
mImageView.setHelper(this);
|
||||
|
||||
// Create action view
|
||||
mActionView = mInflater.inflate(R.layout.search_action, null);
|
||||
mActionView.setLayoutParams(new RecyclerView.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
mAction = mActionView.findViewById(R.id.action);
|
||||
mAction.addOnTabSelectedListener(this);
|
||||
}
|
||||
|
||||
public void setHelper(Helper helper) {
|
||||
mHelper = helper;
|
||||
}
|
||||
|
||||
public void scrollSearchContainerToTop() {
|
||||
mLayoutManager.scrollToPositionWithOffset(0, 0);
|
||||
}
|
||||
|
||||
public void setImageUri(Uri imageUri) {
|
||||
mImageView.setImageUri(imageUri);
|
||||
}
|
||||
|
||||
public void setNormalSearchMode(int id) {
|
||||
mNormalSearchMode.check(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectImage() {
|
||||
if (mHelper != null) {
|
||||
mHelper.onSelectImage();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchSaveInstanceState(@NonNull SparseArray<Parcelable> container) {
|
||||
super.dispatchSaveInstanceState(container);
|
||||
|
||||
mNormalView.saveHierarchyState(container);
|
||||
mAdvanceView.saveHierarchyState(container);
|
||||
mImageView.saveHierarchyState(container);
|
||||
mActionView.saveHierarchyState(container);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchRestoreInstanceState(@NonNull SparseArray<Parcelable> container) {
|
||||
super.dispatchRestoreInstanceState(container);
|
||||
|
||||
mNormalView.restoreHierarchyState(container);
|
||||
mAdvanceView.restoreHierarchyState(container);
|
||||
mImageView.restoreHierarchyState(container);
|
||||
mActionView.restoreHierarchyState(container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parcelable onSaveInstanceState() {
|
||||
final Bundle state = new Bundle();
|
||||
state.putParcelable(STATE_KEY_SUPER, super.onSaveInstanceState());
|
||||
state.putInt(STATE_KEY_SEARCH_MODE, mSearchMode);
|
||||
state.putBoolean(STATE_KEY_ENABLE_ADVANCE, mEnableAdvance);
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(Parcelable state) {
|
||||
if (state instanceof Bundle) {
|
||||
final Bundle savedState = (Bundle) state;
|
||||
super.onRestoreInstanceState(savedState.getParcelable(STATE_KEY_SUPER));
|
||||
mSearchMode = savedState.getInt(STATE_KEY_SEARCH_MODE);
|
||||
mEnableAdvance = savedState.getBoolean(STATE_KEY_ENABLE_ADVANCE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
if (buttonView == mEnableAdvanceSwitch) {
|
||||
post(() -> {
|
||||
mEnableAdvance = isChecked;
|
||||
if (mSearchMode == SEARCH_MODE_NORMAL) {
|
||||
if (mEnableAdvance) {
|
||||
mAdapter.notifyItemInserted(1);
|
||||
} else {
|
||||
mAdapter.notifyItemRemoved(1);
|
||||
}
|
||||
|
||||
if (mHelper != null) {
|
||||
mHelper.onChangeSearchMode();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NonConstantResourceId")
|
||||
public void formatListUrlBuilder(ListUrlBuilder urlBuilder, String query) throws EhException {
|
||||
urlBuilder.reset();
|
||||
|
||||
switch (mSearchMode) {
|
||||
case SEARCH_MODE_NORMAL:
|
||||
int nsMode = mNormalSearchMode.getCheckedRadioButtonId();
|
||||
if (nsMode == R.id.search_subscription_search) {
|
||||
urlBuilder.setMode(ListUrlBuilder.MODE_SUBSCRIPTION);
|
||||
} else if (nsMode == R.id.search_specify_uploader) {
|
||||
urlBuilder.setMode(ListUrlBuilder.MODE_UPLOADER);
|
||||
} else if (nsMode == R.id.search_specify_tag) {
|
||||
urlBuilder.setMode(ListUrlBuilder.MODE_TAG);
|
||||
} else {
|
||||
urlBuilder.setMode(ListUrlBuilder.MODE_NORMAL);
|
||||
}
|
||||
urlBuilder.setKeyword(query);
|
||||
urlBuilder.setCategory(mCategoryTable.getCategory());
|
||||
if (mEnableAdvance) {
|
||||
urlBuilder.setAdvanceSearch(mTableAdvanceSearch.getAdvanceSearch());
|
||||
urlBuilder.setMinRating(mTableAdvanceSearch.getMinRating());
|
||||
urlBuilder.setPageFrom(mTableAdvanceSearch.getPageFrom());
|
||||
urlBuilder.setPageTo(mTableAdvanceSearch.getPageTo());
|
||||
}
|
||||
break;
|
||||
case SEARCH_MODE_IMAGE:
|
||||
urlBuilder.setMode(ListUrlBuilder.MODE_IMAGE_SEARCH);
|
||||
mImageView.formatListUrlBuilder(urlBuilder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mNormalSearchModeHelp == v) {
|
||||
new MaterialAlertDialogBuilder(getContext())
|
||||
.setMessage(R.string.search_tip)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
post(() -> setSearchMode(tab.getPosition()));
|
||||
}
|
||||
|
||||
public void setSearchMode(@SearchMode int mode) {
|
||||
int oldItemCount = mAdapter.getItemCount();
|
||||
|
||||
mSearchMode = mode;
|
||||
|
||||
int newItemCount = mAdapter.getItemCount();
|
||||
|
||||
mAdapter.notifyItemRangeRemoved(0, oldItemCount - 1);
|
||||
mAdapter.notifyItemRangeInserted(0, newItemCount - 1);
|
||||
|
||||
if (mHelper != null) {
|
||||
mHelper.onChangeSearchMode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
|
||||
@IntDef({SEARCH_MODE_NORMAL, SEARCH_MODE_IMAGE})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
private @interface SearchMode {
|
||||
}
|
||||
|
||||
public interface Helper {
|
||||
void onChangeSearchMode();
|
||||
|
||||
void onSelectImage();
|
||||
}
|
||||
|
||||
static class SearchLayoutManager extends LinearLayoutManager {
|
||||
|
||||
public SearchLayoutManager(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
try {
|
||||
super.onLayoutChildren(recycler, state);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SearchAdapter extends EasyRecyclerView.Adapter<SimpleHolder> {
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
int count = SEARCH_ITEM_COUNT_ARRAY[mSearchMode];
|
||||
if (mSearchMode == SEARCH_MODE_NORMAL && !mEnableAdvance) {
|
||||
count--;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
int type = SEARCH_ITEM_TYPE[mSearchMode][position];
|
||||
if (mSearchMode == SEARCH_MODE_NORMAL && position == 1 && !mEnableAdvance) {
|
||||
type = ITEM_TYPE_ACTION;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SimpleHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view;
|
||||
|
||||
if (viewType == ITEM_TYPE_ACTION) {
|
||||
ViewUtils.removeFromParent(mActionView);
|
||||
view = mActionView;
|
||||
} else {
|
||||
view = mInflater.inflate(R.layout.search_category, parent, false);
|
||||
TextView title = view.findViewById(R.id.category_title);
|
||||
FrameLayout content = view.findViewById(R.id.category_content);
|
||||
switch (viewType) {
|
||||
case ITEM_TYPE_NORMAL:
|
||||
title.setText(R.string.search_normal);
|
||||
ViewUtils.removeFromParent(mNormalView);
|
||||
content.addView(mNormalView);
|
||||
break;
|
||||
case ITEM_TYPE_NORMAL_ADVANCE:
|
||||
title.setText(R.string.search_advance);
|
||||
ViewUtils.removeFromParent(mAdvanceView);
|
||||
content.addView(mAdvanceView);
|
||||
break;
|
||||
case ITEM_TYPE_IMAGE:
|
||||
title.setText(R.string.search_image);
|
||||
ViewUtils.removeFromParent(mImageView);
|
||||
content.addView(mImageView);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new SimpleHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(SimpleHolder holder, int position) {
|
||||
if (holder.getItemViewType() == ITEM_TYPE_ACTION) {
|
||||
mAction.selectTab(mAction.getTabAt(mSearchMode));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
int type = SEARCH_ITEM_TYPE[mSearchMode][position];
|
||||
if (mSearchMode == SEARCH_MODE_NORMAL && position == 1 && !mEnableAdvance) {
|
||||
type = ITEM_TYPE_ACTION;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* Copyright (C) 2022 tarsin norbin
|
||||
*
|
||||
* 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.widget
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import androidx.annotation.IntDef
|
||||
import androidx.core.content.edit
|
||||
import androidx.preference.PreferenceManager
|
||||
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.easyrecyclerview.EasyRecyclerView
|
||||
import com.hippo.easyrecyclerview.MarginItemDecoration
|
||||
import com.hippo.easyrecyclerview.SimpleHolder
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.client.EhConfig
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder
|
||||
import com.hippo.ehviewer.client.exception.EhException
|
||||
import com.hippo.widget.RadioGridGroup
|
||||
import com.hippo.yorozuya.NumberUtils
|
||||
import com.hippo.yorozuya.ViewUtils
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
class SearchLayout @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null
|
||||
) : EasyRecyclerView(context, attrs), CompoundButton.OnCheckedChangeListener, View.OnClickListener,
|
||||
ImageSearchLayout.Helper, OnTabSelectedListener {
|
||||
|
||||
@SearchMode
|
||||
private var mSearchMode = SEARCH_MODE_NORMAL
|
||||
private var mEnableAdvance = false
|
||||
private var mCategoryGroup: ChipGroup
|
||||
private var mNormalView: View
|
||||
private var mNormalSearchMode: RadioGridGroup
|
||||
private var mNormalSearchModeHelp: ImageView
|
||||
private var mEnableAdvanceSwitch: CheckBox
|
||||
private var mAdvanceView: View
|
||||
private var mTableAdvanceSearch: AdvanceSearchTable
|
||||
private var mImageView: ImageSearchLayout
|
||||
private var mActionView: View
|
||||
private var mAction: TabLayout
|
||||
private var mAdapter: SearchAdapter
|
||||
private var mHelper: Helper? = null
|
||||
private val mSharePref: SharedPreferences
|
||||
private val mInflater: LayoutInflater
|
||||
|
||||
init {
|
||||
mSharePref = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
mInflater = LayoutInflater.from(context)
|
||||
val resources = context.resources
|
||||
layoutManager = SearchLayoutManager(context)
|
||||
mAdapter = SearchAdapter()
|
||||
mAdapter.setHasStableIds(true)
|
||||
adapter = mAdapter
|
||||
setHasFixedSize(true)
|
||||
clipToPadding = false
|
||||
(itemAnimator as DefaultItemAnimator?)?.supportsChangeAnimations = false
|
||||
val interval = resources.getDimensionPixelOffset(R.dimen.search_layout_interval)
|
||||
val paddingH = resources.getDimensionPixelOffset(R.dimen.search_layout_margin_h)
|
||||
val paddingV = resources.getDimensionPixelOffset(R.dimen.search_layout_margin_v)
|
||||
val decoration = MarginItemDecoration(
|
||||
interval, paddingH, paddingV, paddingH, paddingV
|
||||
)
|
||||
addItemDecoration(decoration)
|
||||
decoration.applyPaddings(this)
|
||||
// Create normal view
|
||||
mNormalView = mInflater.inflate(R.layout.search_normal, null)
|
||||
val mCategoryStored = mSharePref.getInt(SEARCH_CATEGORY_PREF, EhConfig.ALL_CATEGORY)
|
||||
mCategoryGroup = mNormalView.findViewById(R.id.search_category_chipgroup)
|
||||
for (mPair in mCategoryTable) {
|
||||
val mChip = IdentifiedChip(context)
|
||||
mChip.isCheckable = true
|
||||
mChip.setText(mPair.second)
|
||||
mChip.idt = mPair.first
|
||||
mChip.isChecked = NumberUtils.int2boolean(mPair.first and mCategoryStored)
|
||||
mChip.setOnLongClickListener {
|
||||
mCategoryGroup.clearCheck()
|
||||
mChip.isChecked = true
|
||||
true
|
||||
}
|
||||
mCategoryGroup.addView(mChip)
|
||||
}
|
||||
mCategoryGroup.setOnCheckedStateChangeListener { _, checkedIds ->
|
||||
var mCategory = 0
|
||||
for (index in checkedIds) {
|
||||
mCategory = mCategory or findViewById<IdentifiedChip>(index).idt
|
||||
}
|
||||
mSharePref.edit { putInt(SEARCH_CATEGORY_PREF, mCategory) }
|
||||
}
|
||||
mNormalSearchMode = mNormalView.findViewById(R.id.normal_search_mode)
|
||||
mNormalSearchModeHelp = mNormalView.findViewById(R.id.normal_search_mode_help)
|
||||
mEnableAdvanceSwitch = mNormalView.findViewById(R.id.search_enable_advance)
|
||||
mNormalSearchModeHelp.setOnClickListener(this)
|
||||
mEnableAdvanceSwitch.setOnCheckedChangeListener(this)
|
||||
// Create advance view
|
||||
mAdvanceView = mInflater.inflate(R.layout.search_advance, null)
|
||||
mTableAdvanceSearch = mAdvanceView.findViewById(R.id.search_advance_search_table)
|
||||
// Create image view
|
||||
mImageView = mInflater.inflate(R.layout.search_image, null) as ImageSearchLayout
|
||||
mImageView.setHelper(this)
|
||||
// Create action view
|
||||
mActionView = mInflater.inflate(R.layout.search_action, null)
|
||||
mActionView.layoutParams = LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
mAction = mActionView.findViewById(R.id.action)
|
||||
mAction.addOnTabSelectedListener(this)
|
||||
}
|
||||
|
||||
|
||||
fun setHelper(helper: Helper?) {
|
||||
mHelper = helper
|
||||
}
|
||||
|
||||
fun scrollSearchContainerToTop() {
|
||||
(layoutManager as LinearLayoutManager).scrollToPositionWithOffset(0, 0)
|
||||
}
|
||||
|
||||
fun setImageUri(imageUri: Uri?) {
|
||||
mImageView.setImageUri(imageUri)
|
||||
}
|
||||
|
||||
fun setNormalSearchMode(id: Int) {
|
||||
mNormalSearchMode.check(id)
|
||||
}
|
||||
|
||||
override fun onSelectImage() {
|
||||
if (mHelper != null) {
|
||||
mHelper!!.onSelectImage()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) {
|
||||
if (buttonView === mEnableAdvanceSwitch) {
|
||||
post {
|
||||
mEnableAdvance = isChecked
|
||||
if (mSearchMode == SEARCH_MODE_NORMAL) {
|
||||
if (mEnableAdvance) {
|
||||
mAdapter.notifyItemInserted(1)
|
||||
} else {
|
||||
mAdapter.notifyItemRemoved(1)
|
||||
}
|
||||
if (mHelper != null) {
|
||||
mHelper!!.onChangeSearchMode()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NonConstantResourceId")
|
||||
@Throws(EhException::class)
|
||||
fun formatListUrlBuilder(urlBuilder: ListUrlBuilder, query: String?) {
|
||||
urlBuilder.reset()
|
||||
when (mSearchMode) {
|
||||
SEARCH_MODE_NORMAL -> {
|
||||
when (mNormalSearchMode.checkedRadioButtonId) {
|
||||
R.id.search_subscription_search -> {
|
||||
urlBuilder.mode = ListUrlBuilder.MODE_SUBSCRIPTION
|
||||
}
|
||||
R.id.search_specify_uploader -> {
|
||||
urlBuilder.mode = ListUrlBuilder.MODE_UPLOADER
|
||||
}
|
||||
R.id.search_specify_tag -> {
|
||||
urlBuilder.mode = ListUrlBuilder.MODE_TAG
|
||||
}
|
||||
else -> {
|
||||
urlBuilder.mode = ListUrlBuilder.MODE_NORMAL
|
||||
}
|
||||
}
|
||||
urlBuilder.keyword = query
|
||||
urlBuilder.category = PreferenceManager.getDefaultSharedPreferences(context).getInt(
|
||||
SEARCH_CATEGORY_PREF, 0
|
||||
)
|
||||
if (mEnableAdvance) {
|
||||
urlBuilder.advanceSearch = mTableAdvanceSearch.advanceSearch
|
||||
urlBuilder.minRating = mTableAdvanceSearch.minRating
|
||||
urlBuilder.pageFrom = mTableAdvanceSearch.pageFrom
|
||||
urlBuilder.pageTo = mTableAdvanceSearch.pageTo
|
||||
}
|
||||
}
|
||||
SEARCH_MODE_IMAGE -> {
|
||||
urlBuilder.mode = ListUrlBuilder.MODE_IMAGE_SEARCH
|
||||
mImageView.formatListUrlBuilder(urlBuilder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
if (mNormalSearchModeHelp === v) {
|
||||
MaterialAlertDialogBuilder(context)
|
||||
.setMessage(R.string.search_tip)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||
post { setSearchMode(tab.position) }
|
||||
}
|
||||
|
||||
fun setSearchMode(@SearchMode mode: Int) {
|
||||
val oldItemCount = mAdapter.itemCount
|
||||
mSearchMode = mode
|
||||
val newItemCount = mAdapter.itemCount
|
||||
mAdapter.notifyItemRangeRemoved(0, oldItemCount - 1)
|
||||
mAdapter.notifyItemRangeInserted(0, newItemCount - 1)
|
||||
if (mHelper != null) {
|
||||
mHelper!!.onChangeSearchMode()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab) {}
|
||||
override fun onTabReselected(tab: TabLayout.Tab) {}
|
||||
|
||||
@IntDef(SEARCH_MODE_NORMAL, SEARCH_MODE_IMAGE)
|
||||
@kotlin.annotation.Retention(AnnotationRetention.SOURCE)
|
||||
private annotation class SearchMode
|
||||
interface Helper {
|
||||
fun onChangeSearchMode()
|
||||
fun onSelectImage()
|
||||
}
|
||||
|
||||
internal class SearchLayoutManager(context: Context?) : LinearLayoutManager(context) {
|
||||
override fun onLayoutChildren(recycler: Recycler, state: State) {
|
||||
try {
|
||||
super.onLayoutChildren(recycler, state)
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class SearchAdapter : Adapter<SimpleHolder>() {
|
||||
override fun getItemCount(): Int {
|
||||
var count = SEARCH_ITEM_COUNT_ARRAY[mSearchMode]
|
||||
if (mSearchMode == SEARCH_MODE_NORMAL && !mEnableAdvance) {
|
||||
count--
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
var type = SEARCH_ITEM_TYPE[mSearchMode][position]
|
||||
if (mSearchMode == SEARCH_MODE_NORMAL && position == 1 && !mEnableAdvance) {
|
||||
type = ITEM_TYPE_ACTION
|
||||
}
|
||||
return type
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SimpleHolder {
|
||||
val view: View?
|
||||
if (viewType == ITEM_TYPE_ACTION) {
|
||||
ViewUtils.removeFromParent(mActionView)
|
||||
view = mActionView
|
||||
} else {
|
||||
view = mInflater.inflate(R.layout.search_category, parent, false)
|
||||
val title = view.findViewById<TextView>(R.id.category_title)
|
||||
val content = view.findViewById<FrameLayout>(R.id.category_content)
|
||||
when (viewType) {
|
||||
ITEM_TYPE_NORMAL -> {
|
||||
title.setText(R.string.search_normal)
|
||||
ViewUtils.removeFromParent(mNormalView)
|
||||
content.addView(mNormalView)
|
||||
}
|
||||
ITEM_TYPE_NORMAL_ADVANCE -> {
|
||||
title.setText(R.string.search_advance)
|
||||
ViewUtils.removeFromParent(mAdvanceView)
|
||||
content.addView(mAdvanceView)
|
||||
}
|
||||
ITEM_TYPE_IMAGE -> {
|
||||
title.setText(R.string.search_image)
|
||||
ViewUtils.removeFromParent(mImageView)
|
||||
content.addView(mImageView)
|
||||
}
|
||||
}
|
||||
}
|
||||
return SimpleHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: SimpleHolder, position: Int) {
|
||||
if (holder.itemViewType == ITEM_TYPE_ACTION) {
|
||||
mAction.selectTab(mAction.getTabAt(mSearchMode))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
var type = SEARCH_ITEM_TYPE[mSearchMode][position]
|
||||
if (mSearchMode == SEARCH_MODE_NORMAL && position == 1 && !mEnableAdvance) {
|
||||
type = ITEM_TYPE_ACTION
|
||||
}
|
||||
return type.toLong()
|
||||
}
|
||||
}
|
||||
|
||||
inner class IdentifiedChip @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null
|
||||
) : Chip(context, attrs) {
|
||||
var idt = 0
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SEARCH_MODE_NORMAL = 0
|
||||
const val SEARCH_MODE_IMAGE = 1
|
||||
const val SEARCH_CATEGORY_PREF = "search_pref"
|
||||
private const val ITEM_TYPE_NORMAL = 0
|
||||
private const val ITEM_TYPE_NORMAL_ADVANCE = 1
|
||||
private const val ITEM_TYPE_IMAGE = 2
|
||||
private const val ITEM_TYPE_ACTION = 3
|
||||
private val SEARCH_ITEM_COUNT_ARRAY = intArrayOf(
|
||||
3, 2
|
||||
)
|
||||
private val mCategoryTable: ArrayList<Pair<Int, Int>> = arrayListOf(
|
||||
Pair(EhConfig.DOUJINSHI, R.string.doujinshi),
|
||||
Pair(EhConfig.MANGA, R.string.manga),
|
||||
Pair(EhConfig.ARTIST_CG, R.string.artist_cg),
|
||||
Pair(EhConfig.GAME_CG, R.string.game_cg),
|
||||
Pair(EhConfig.WESTERN, R.string.western),
|
||||
Pair(EhConfig.NON_H, R.string.non_h),
|
||||
Pair(EhConfig.IMAGE_SET, R.string.image_set),
|
||||
Pair(EhConfig.COSPLAY, R.string.cosplay),
|
||||
Pair(EhConfig.ASIAN_PORN, R.string.asian_porn),
|
||||
Pair(EhConfig.MISC, R.string.misc)
|
||||
)
|
||||
private val SEARCH_ITEM_TYPE = arrayOf(
|
||||
intArrayOf(ITEM_TYPE_NORMAL, ITEM_TYPE_NORMAL_ADVANCE, ITEM_TYPE_ACTION), intArrayOf(
|
||||
ITEM_TYPE_IMAGE, ITEM_TYPE_ACTION
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,17 @@ public class BatteryView extends AppCompatTextView {
|
||||
private boolean mCharging = false;
|
||||
|
||||
private BatteryDrawable mDrawable;
|
||||
private boolean mAttached = false; private final Runnable mCharger = new Runnable() {
|
||||
private boolean mAttached = false;
|
||||
private boolean mIsChargerWorking = false;
|
||||
|
||||
public BatteryView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public BatteryView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
} private final Runnable mCharger = new Runnable() {
|
||||
|
||||
private int level = 0;
|
||||
|
||||
@@ -55,43 +65,6 @@ public class BatteryView extends AppCompatTextView {
|
||||
getHandler().postDelayed(mCharger, 200);
|
||||
}
|
||||
};
|
||||
private boolean mIsChargerWorking = false;
|
||||
public BatteryView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
public BatteryView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
} private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
@SuppressLint("SetTextI18n")
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
|
||||
* 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
|
||||
boolean charging = (intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
|
||||
== BatteryManager.BATTERY_STATUS_CHARGING);
|
||||
|
||||
if (mLevel != level || mCharging != charging) {
|
||||
mLevel = level;
|
||||
mCharging = charging;
|
||||
if (mCharging && mLevel != 100) {
|
||||
startCharger();
|
||||
} else {
|
||||
stopCharger();
|
||||
mDrawable.setElect(mLevel);
|
||||
}
|
||||
|
||||
if (level <= BatteryDrawable.WARN_LIMIT && !charging) {
|
||||
setTextColor(mWarningColor);
|
||||
} else {
|
||||
setTextColor(mColor);
|
||||
}
|
||||
setText(mLevel + "%");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public BatteryView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
@@ -147,7 +120,36 @@ public class BatteryView extends AppCompatTextView {
|
||||
|
||||
registerReceiver();
|
||||
}
|
||||
}
|
||||
} private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
@SuppressLint("SetTextI18n")
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
|
||||
* 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
|
||||
boolean charging = (intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
|
||||
== BatteryManager.BATTERY_STATUS_CHARGING);
|
||||
|
||||
if (mLevel != level || mCharging != charging) {
|
||||
mLevel = level;
|
||||
mCharging = charging;
|
||||
if (mCharging && mLevel != 100) {
|
||||
startCharger();
|
||||
} else {
|
||||
stopCharger();
|
||||
mDrawable.setElect(mLevel);
|
||||
}
|
||||
|
||||
if (level <= BatteryDrawable.WARN_LIMIT && !charging) {
|
||||
setTextColor(mWarningColor);
|
||||
} else {
|
||||
setTextColor(mColor);
|
||||
}
|
||||
setText(mLevel + "%");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
@@ -173,4 +175,6 @@ public class BatteryView extends AppCompatTextView {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.AppCompatCheckedTextView;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
public class CheckTextView extends AppCompatCheckedTextView implements View.OnClickListener {
|
||||
|
||||
private final Rect mSelfBounds = new Rect();
|
||||
private final Rect mOverlayBounds = new Rect();
|
||||
protected boolean mForegroundInPadding = true;
|
||||
boolean mForegroundBoundsChanged = false;
|
||||
private Drawable mForeground;
|
||||
private int mForegroundGravity = Gravity.FILL;
|
||||
|
||||
public CheckTextView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public CheckTextView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public CheckTextView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
init(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CheckTextView,
|
||||
defStyleAttr, 0);
|
||||
|
||||
mForegroundGravity = a.getInt(
|
||||
R.styleable.CheckTextView_android_foregroundGravity, mForegroundGravity);
|
||||
|
||||
Drawable d = a.getDrawable(R.styleable.CheckTextView_android_foreground);
|
||||
if (d != null) {
|
||||
setForeground(d);
|
||||
}
|
||||
|
||||
mForegroundInPadding = a.getBoolean(
|
||||
R.styleable.CheckTextView_foregroundInsidePadding, true);
|
||||
|
||||
a.recycle();
|
||||
setOnClickListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes how the foreground is positioned.
|
||||
*
|
||||
* @return foreground gravity.
|
||||
* @see #setForegroundGravity(int)
|
||||
*/
|
||||
public int getForegroundGravity() {
|
||||
return mForegroundGravity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes how the foreground is positioned. Defaults to START and TOP.
|
||||
*
|
||||
* @param foregroundGravity See {@link android.view.Gravity}
|
||||
* @see #getForegroundGravity()
|
||||
*/
|
||||
public void setForegroundGravity(int foregroundGravity) {
|
||||
if (mForegroundGravity != foregroundGravity) {
|
||||
if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
|
||||
foregroundGravity |= Gravity.START;
|
||||
}
|
||||
|
||||
if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
|
||||
foregroundGravity |= Gravity.TOP;
|
||||
}
|
||||
|
||||
mForegroundGravity = foregroundGravity;
|
||||
|
||||
if (mForegroundGravity == Gravity.FILL && mForeground != null) {
|
||||
Rect padding = new Rect();
|
||||
mForeground.getPadding(padding);
|
||||
}
|
||||
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean verifyDrawable(@NonNull Drawable who) {
|
||||
return super.verifyDrawable(who) || (who == mForeground);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jumpDrawablesToCurrentState() {
|
||||
super.jumpDrawablesToCurrentState();
|
||||
if (mForeground != null) {
|
||||
mForeground.jumpToCurrentState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawableStateChanged() {
|
||||
super.drawableStateChanged();
|
||||
if (mForeground != null && mForeground.isStateful()) {
|
||||
mForeground.setState(getDrawableState());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the drawable used as the foreground of this FrameLayout. The
|
||||
* foreground drawable, if non-null, is always drawn on top of the children.
|
||||
*
|
||||
* @return A Drawable or null if no foreground was set.
|
||||
*/
|
||||
public Drawable getForeground() {
|
||||
return mForeground;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supply a Drawable that is to be rendered on top of all of the child
|
||||
* views in the frame layout. Any padding in the Drawable will be taken
|
||||
* into account by ensuring that the children are inset to be placed
|
||||
* inside of the padding area.
|
||||
*
|
||||
* @param drawable The Drawable to be drawn on top of the children.
|
||||
*/
|
||||
public void setForeground(Drawable drawable) {
|
||||
if (mForeground != drawable) {
|
||||
if (mForeground != null) {
|
||||
mForeground.setCallback(null);
|
||||
unscheduleDrawable(mForeground);
|
||||
}
|
||||
|
||||
mForeground = drawable;
|
||||
|
||||
if (drawable != null) {
|
||||
setWillNotDraw(false);
|
||||
drawable.setCallback(this);
|
||||
if (drawable.isStateful()) {
|
||||
drawable.setState(getDrawableState());
|
||||
}
|
||||
if (mForegroundGravity == Gravity.FILL) {
|
||||
Rect padding = new Rect();
|
||||
drawable.getPadding(padding);
|
||||
}
|
||||
} else {
|
||||
setWillNotDraw(true);
|
||||
}
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
mForegroundBoundsChanged |= changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
mForegroundBoundsChanged = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
super.draw(canvas);
|
||||
|
||||
if (mForeground != null) {
|
||||
final Drawable foreground = mForeground;
|
||||
|
||||
if (mForegroundBoundsChanged) {
|
||||
mForegroundBoundsChanged = false;
|
||||
final Rect selfBounds = mSelfBounds;
|
||||
final Rect overlayBounds = mOverlayBounds;
|
||||
|
||||
final int w = getRight() - getLeft();
|
||||
final int h = getBottom() - getTop();
|
||||
|
||||
if (mForegroundInPadding) {
|
||||
selfBounds.set(0, 0, w, h);
|
||||
} else {
|
||||
selfBounds.set(getPaddingLeft(), getPaddingTop(),
|
||||
w - getPaddingRight(), h - getPaddingBottom());
|
||||
}
|
||||
|
||||
Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
|
||||
foreground.getIntrinsicHeight(), selfBounds, overlayBounds);
|
||||
foreground.setBounds(overlayBounds);
|
||||
}
|
||||
|
||||
foreground.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawableHotspotChanged(float x, float y) {
|
||||
super.drawableHotspotChanged(x, y);
|
||||
if (mForeground != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
mForeground.setHotspot(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
setChecked(!isChecked());
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,6 @@ import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.image.ImageBitmap;
|
||||
import com.hippo.image.ImageDrawable;
|
||||
import com.hippo.image.RecycledException;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -285,7 +284,7 @@ public class LoadImageView extends FixedAspectImageView implements Unikery<Image
|
||||
Drawable drawable;
|
||||
try {
|
||||
drawable = new ImageDrawable(value);
|
||||
} catch (RecycledException e) {
|
||||
} catch (Exception e) {
|
||||
// The image might be recycled because it is removed from memory cache.
|
||||
Log.d(TAG, "The image is recycled", e);
|
||||
return false;
|
||||
|
||||
@@ -55,7 +55,25 @@ public class TextClock extends AppCompatTextView {
|
||||
private boolean mAttached;
|
||||
|
||||
private Calendar mTime;
|
||||
private String mTimeZone; private final Runnable mTicker = new Runnable() {
|
||||
private String mTimeZone;
|
||||
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (mTimeZone == null && Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
|
||||
final String timeZone = intent.getStringExtra("time-zone");
|
||||
createTime(timeZone);
|
||||
}
|
||||
onTimeChanged();
|
||||
}
|
||||
};
|
||||
|
||||
public TextClock(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public TextClock(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
} private final Runnable mTicker = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onTimeChanged();
|
||||
@@ -66,34 +84,6 @@ public class TextClock extends AppCompatTextView {
|
||||
getHandler().postAtTime(mTicker, next);
|
||||
}
|
||||
};
|
||||
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (mTimeZone == null && Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
|
||||
final String timeZone = intent.getStringExtra("time-zone");
|
||||
createTime(timeZone);
|
||||
}
|
||||
onTimeChanged();
|
||||
}
|
||||
}; private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
};
|
||||
public TextClock(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
public TextClock(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public TextClock(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
@@ -121,7 +111,19 @@ public class TextClock extends AppCompatTextView {
|
||||
|
||||
public CharSequence getFormat12Hour() {
|
||||
return mFormat12;
|
||||
}
|
||||
} private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
};
|
||||
|
||||
public void setFormat12Hour(CharSequence format) {
|
||||
mFormat12 = format;
|
||||
@@ -261,4 +263,6 @@ public class TextClock extends AppCompatTextView {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.widget.lockpattern;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utilities for the lock pattern and its settings.
|
||||
*/
|
||||
public class LockPatternUtils {
|
||||
|
||||
/**
|
||||
* Deserialize a pattern.
|
||||
*
|
||||
* @param string The pattern serialized with {@link #patternToString}
|
||||
* @return The pattern.
|
||||
*/
|
||||
public static List<LockPatternView.Cell> stringToPattern(String string) {
|
||||
List<LockPatternView.Cell> result = new ArrayList<>();
|
||||
|
||||
final byte[] bytes = string.getBytes();
|
||||
for (byte b : bytes) {
|
||||
result.add(LockPatternView.Cell.of(b / 3, b % 3));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a pattern.
|
||||
*
|
||||
* @param pattern The pattern.
|
||||
* @return The pattern in string form.
|
||||
*/
|
||||
public static String patternToString(List<LockPatternView.Cell> pattern) {
|
||||
if (pattern == null) {
|
||||
return "";
|
||||
}
|
||||
final int patternSize = pattern.size();
|
||||
|
||||
byte[] res = new byte[patternSize];
|
||||
for (int i = 0; i < patternSize; i++) {
|
||||
LockPatternView.Cell cell = pattern.get(i);
|
||||
res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
|
||||
}
|
||||
return new String(res);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2018 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.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:color="@color/content_activated" android:state_activated="true" />
|
||||
<item android:color="@color/content" />
|
||||
|
||||
</selector>
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2018 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.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:color="@color/content_activated_black" android:state_activated="true" />
|
||||
<item android:color="@color/content_black" />
|
||||
|
||||
</selector>
|
||||
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 3.2 KiB |
@@ -6,10 +6,10 @@
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:fillAlpha="1"
|
||||
android:fillColor="@color/shortcut_bg"
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M46,24A22,22 0,0 1,24 46,22 22,0 0,1 2,24 22,22 0,0 1,24 2,22 22,0 0,1 46,24Z" />
|
||||
<path
|
||||
android:fillAlpha="1"
|
||||
android:fillColor="@color/colorPrimary"
|
||||
android:fillColor="@android:color/black"
|
||||
android:pathData="M20,17V31L31,24Z" />
|
||||
</vector>
|
||||
@@ -6,10 +6,10 @@
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:fillAlpha="1"
|
||||
android:fillColor="@color/shortcut_bg"
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M46,24A22,22 0,0 1,24 46,22 22,0 0,1 2,24 22,22 0,0 1,24 2,22 22,0 0,1 46,24Z" />
|
||||
<path
|
||||
android:fillAlpha="1"
|
||||
android:fillColor="@color/colorPrimary"
|
||||
android:fillColor="@android:color/black"
|
||||
android:pathData="m18,31h4L22,17h-4zM26,17v14h4L30,17Z" />
|
||||
</vector>
|
||||
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 9.2 KiB |
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<color android:color="@android:color/system_neutral1_50" />
|
||||
</item>
|
||||
<item android:drawable="?android:attr/selectableItemBackground" />
|
||||
</layer-list>
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<selector
|
||||
android:enterFadeDuration="@android:integer/config_shortAnimTime"
|
||||
android:exitFadeDuration="@android:integer/config_shortAnimTime">
|
||||
<item android:state_checked="true">
|
||||
<color android:color="@color/check_text_view_mask" />
|
||||
</item>
|
||||
</selector>
|
||||
</item>
|
||||
<item android:drawable="?android:attr/selectableItemBackground" />
|
||||
</layer-list>
|
||||
@@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="@color/teal_500"
|
||||
android:pathData="M0,12a12,12 0 1,0 24,0a12,12 0 1,0 -24,0" />
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/black"
|
||||
android:pathData="M16.5,9.9L16.1,9.6L19.1,5.9C19.2,5.8,19.4,5.8,19.5,5.9L19.5,5.9C19.6,6,19.6,6.2,19.5,6.3L16.5,9.9Z" />
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/black"
|
||||
android:pathData="M9.1,8.8L8.6,9.1L6.2,5C6.1,4.9,6.2,4.7,6.3,4.6L6.3,4.6C6.4,4.5,6.6,4.6,6.7,4.7L9.1,8.8Z" />
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M1.8,14.6L22.1,16.4C21.4,11.3,17.6,7.9,12.6,7.5C7.8,7,3.4,9.7,1.8,14.6Z" />
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/black"
|
||||
android:pathData="M15.4,11.9a1.1,1.1 0 1,0 2.2,0a1.1,1.1 0 1,0 -2.2,0" />
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/black"
|
||||
android:pathData="M7.1,11.2a1.1,1.1 0 1,0 2.2,0a1.1,1.1 0 1,0 -2.2,0" />
|
||||
|
||||
</vector>
|
||||
@@ -1,10 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9s9,-4.03 9,-9c0,-0.46 -0.04,-0.92 -0.1,-1.36c-0.98,1.37 -2.58,2.26 -4.4,2.26c-2.98,0 -5.4,-2.42 -5.4,-5.4c0,-1.81 0.89,-3.42 2.26,-4.4C12.92,3.04 12.46,3 12,3L12,3z" />
|
||||
</vector>
|
||||
@@ -5,6 +5,6 @@
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillAlpha="1"
|
||||
android:fillColor="@color/colorPrimary"
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="m42,68h8V40H42ZM58,40v28h8V40Z" />
|
||||
</vector>
|
||||
@@ -5,6 +5,6 @@
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillAlpha="1"
|
||||
android:fillColor="@color/colorPrimary"
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M46,40V68L68,54Z" />
|
||||
</vector>
|
||||
@@ -1,92 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:baselineAligned="true"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="@dimen/keyline_margin"
|
||||
app:fitsSystemWindowsInsets="bottom">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal|top"
|
||||
android:gravity="center"
|
||||
android:padding="@dimen/keyline_margin"
|
||||
android:text="@string/set_pattern_protection_tip"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatCheckBox
|
||||
android:id="@+id/fingerprint_checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:text="@string/enable_biometric"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/buttonPanel"
|
||||
style="?attr/buttonBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingBottom="4dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/set"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/set" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancel"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@android:string/cancel" />
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1">
|
||||
|
||||
<com.hippo.widget.lockpattern.LockPatternView
|
||||
android:id="@+id/pattern_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
@@ -52,13 +52,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:background="?android:attr/colorBackground"
|
||||
app:headerLayout="@layout/nav_header_main"
|
||||
app:insetForeground="@null"
|
||||
app:itemShapeAppearanceOverlay="@style/ShapeAppearanceOverlay.MaterialComponents.NavigationView"
|
||||
app:itemShapeInsetBottom="0dp"
|
||||
app:itemShapeInsetStart="0dp"
|
||||
app:itemShapeInsetTop="0dp"
|
||||
app:menu="@menu/nav_drawer_main" />
|
||||
|
||||
<com.hippo.widget.DrawerView
|
||||
|
||||
@@ -11,13 +11,12 @@
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="4dp"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize" />
|
||||
android:layout_height="wrap_content" />
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="@dimen/keyline_margin"
|
||||
app:fitsSystemWindowsInsets="bottom">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:padding="@dimen/keyline_margin"
|
||||
android:text="@string/set_pattern_protection_tip"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<com.hippo.widget.MaxSizeContainer xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="32dp"
|
||||
app:maxHeight="320dp"
|
||||
app:maxWidth="320dp">
|
||||
|
||||
<com.hippo.widget.lockpattern.LockPatternView
|
||||
android:id="@+id/pattern_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</com.hippo.widget.MaxSizeContainer>
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatCheckBox
|
||||
android:id="@+id/fingerprint_checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:text="@string/enable_biometric"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/buttonPanel"
|
||||
style="?attr/buttonBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:gravity="bottom"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingBottom="20dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancel"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="4dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@android:string/cancel" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/set"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="4dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/set" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -14,7 +14,7 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<rikka.widget.borderview.BorderNestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
@@ -37,8 +37,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/settings_read_screen_rotation"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:text="@string/settings_read_screen_rotation" />
|
||||
|
||||
<com.hippo.widget.CuteSpinner
|
||||
android:id="@+id/screen_rotation"
|
||||
@@ -60,8 +59,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/settings_read_reading_direction"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:text="@string/settings_read_reading_direction" />
|
||||
|
||||
<com.hippo.widget.CuteSpinner
|
||||
android:id="@+id/reading_direction"
|
||||
@@ -83,8 +81,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/settings_read_page_scaling"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:text="@string/settings_read_page_scaling" />
|
||||
|
||||
<com.hippo.widget.CuteSpinner
|
||||
android:id="@+id/page_scaling"
|
||||
@@ -106,8 +103,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/settings_read_start_position"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:text="@string/settings_read_start_position" />
|
||||
|
||||
<com.hippo.widget.CuteSpinner
|
||||
android:id="@+id/start_position"
|
||||
@@ -129,8 +125,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/read_theme"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:text="@string/read_theme" />
|
||||
|
||||
<com.hippo.widget.CuteSpinner
|
||||
android:id="@+id/read_theme"
|
||||
@@ -142,68 +137,60 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Switch
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/keep_screen_on"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings_read_keep_screen_on"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:text="@string/settings_read_keep_screen_on" />
|
||||
|
||||
<Switch
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/show_clock"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings_read_show_clock"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:text="@string/settings_read_show_clock" />
|
||||
|
||||
<Switch
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/show_progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings_read_show_progress"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:text="@string/settings_read_show_progress" />
|
||||
|
||||
<Switch
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/show_battery"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings_read_show_battery"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:text="@string/settings_read_show_battery" />
|
||||
|
||||
<Switch
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/show_page_interval"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings_read_show_page_interval"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:text="@string/settings_read_show_page_interval" />
|
||||
|
||||
<Switch
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/volume_page"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings_read_volume_page"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
|
||||
<Switch
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/reverse_volume_page"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings_read_reverse_volume"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:text="@string/settings_read_reverse_volume" />
|
||||
|
||||
<Switch
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/reading_fullscreen"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings_read_reading_fullscreen"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:text="@string/settings_read_reading_fullscreen" />
|
||||
|
||||
<Switch
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/custom_screen_lightness"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings_read_custom_screen_lightness"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:text="@string/settings_read_custom_screen_lightness" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/screen_lightness"
|
||||
@@ -212,4 +199,4 @@
|
||||
android:max="200" />
|
||||
|
||||
</LinearLayout>
|
||||
</rikka.widget.borderview.BorderNestedScrollView>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
@@ -14,12 +14,10 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
style="@style/Widget.Material3.CardView.Filled"
|
||||
style="@style/Widget.Material3.CardView.Elevated"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
app:cardBackgroundColor="?android:attr/windowBackground">
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -32,7 +30,6 @@
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:elevation="4dp"
|
||||
android:saveEnabled="false" />
|
||||
|
||||
<FrameLayout
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="@string/newer_version_avaliable"
|
||||
android:textColor="?attr/textColorThemeAccent"
|
||||
android:visibility="gone" />
|
||||
|
||||
<HorizontalScrollView
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
android:id="@+id/comments_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:textColor="?attr/textColorThemeAccent" />
|
||||
android:layout_gravity="center_horizontal" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -65,41 +65,32 @@
|
||||
android:layout_alignTop="@id/thumb"
|
||||
android:layout_marginLeft="@dimen/keyline_margin"
|
||||
android:layout_marginRight="@dimen/keyline_margin"
|
||||
android:layout_toRightOf="@id/thumb"
|
||||
android:layout_toEndOf="@id/thumb"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="5"
|
||||
android:textSize="@dimen/text_little_large" />
|
||||
|
||||
<TextView
|
||||
<Button
|
||||
android:id="@+id/uploader"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/title"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginRight="@dimen/keyline_margin"
|
||||
android:background="?selectableItemBackground"
|
||||
android:layout_alignStart="@id/title"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/text_little_small" />
|
||||
android:textAllCaps="true" />
|
||||
|
||||
<TextView
|
||||
<Button
|
||||
android:id="@+id/category"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/uploader"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginRight="@dimen/keyline_margin"
|
||||
android:background="@drawable/category_background"
|
||||
android:layout_below="@id/title"
|
||||
android:layout_toRightOf="@id/uploader"
|
||||
android:ellipsize="end"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingRight="8dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:singleLine="true"
|
||||
android:textAllCaps="true"
|
||||
android:textStyle="bold" />
|
||||
android:textAllCaps="true" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/other_actions"
|
||||
@@ -114,52 +105,41 @@
|
||||
android:paddingTop="16dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingBottom="16dp"
|
||||
app:srcCompat="@drawable/v_dots_vertical_secondary_dark_x24"
|
||||
app:tint="@color/primary_drawable_black" />
|
||||
app:srcCompat="@drawable/v_dots_vertical_secondary_dark_x24" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
<LinearLayout
|
||||
android:id="@+id/action_card"
|
||||
style="@style/Widget.Material3.CardView.Elevated"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/keyline_margin"
|
||||
android:layout_marginRight="@dimen/keyline_margin"
|
||||
app:cardUseCompatPadding="true">
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
<Button
|
||||
android:id="@+id/download"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:layout_weight="1"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/download"
|
||||
style="@style/ButtonInCard"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
<android.widget.Space
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="?attr/dividerColor" />
|
||||
<Button
|
||||
android:id="@+id/read"
|
||||
style="@style/Widget.Material3.Button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:text="@string/read" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/read"
|
||||
style="@style/ButtonInCard"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:text="@string/read" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
@@ -88,7 +88,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/more_information"
|
||||
android:textColor="?attr/textColorThemeAccent" />
|
||||
android:text="@string/more_information" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -39,7 +39,6 @@
|
||||
android:id="@+id/preview_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:textColor="?attr/textColorThemeAccent" />
|
||||
android:layout_gravity="center_horizontal" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -26,7 +26,6 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:text="@string/no_tags"
|
||||
android:textColor="?attr/textColorThemeAccent" />
|
||||
android:text="@string/no_tags" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -46,7 +46,7 @@
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_toRightOf="@id/thumb" />
|
||||
android:layout_toEndOf="@id/thumb" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/uploader"
|
||||
@@ -54,7 +54,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/title"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_alignStart="@id/title"
|
||||
android:layout_marginTop="2dp" />
|
||||
|
||||
<com.hippo.ehviewer.widget.SimpleRatingView
|
||||
@@ -62,7 +62,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/uploader"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_alignStart="@id/title"
|
||||
android:layout_marginTop="2dp" />
|
||||
|
||||
<TextView
|
||||
@@ -70,7 +70,7 @@
|
||||
style="@style/CardMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_alignStart="@id/title"
|
||||
android:layout_alignBottom="@id/thumb"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
@@ -85,8 +85,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@+id/thumb"
|
||||
android:layout_alignParentRight="true"
|
||||
android:paddingRight="8dp">
|
||||
android:layout_alignParentEnd="true"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/start"
|
||||
@@ -115,10 +115,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/actions"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:paddingRight="16dp"
|
||||
android:textColor="?attr/textColorThemeAccent" />
|
||||
android:paddingRight="16dp" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
@@ -126,8 +125,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/actions"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_alignStart="@id/title"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:indeterminate="false" />
|
||||
|
||||
<TextView
|
||||
@@ -135,7 +134,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/progress_bar"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_alignStart="@id/title"
|
||||
android:textSize="@dimen/text_super_small" />
|
||||
|
||||
<TextView
|
||||
@@ -143,8 +142,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/progress_bar"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textSize="@dimen/text_super_small" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
style="@style/Widget.Material3.CardView.Elevated"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="2dp"
|
||||
android:background="?selectableItemBackground"
|
||||
android:layout_margin="4dp"
|
||||
android:checkable="true"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
@@ -29,13 +28,21 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.hippo.ehviewer.widget.FixedThumb
|
||||
android:id="@+id/thumb"
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/thumb_card"
|
||||
style="@style/Widget.Material3.CardView.Filled"
|
||||
android:layout_width="@dimen/gallery_list_thumb_width"
|
||||
android:layout_height="@dimen/gallery_list_thumb_height"
|
||||
app:maxAspect="1.333"
|
||||
app:minAspect="0.333"
|
||||
app:retryType="click" />
|
||||
android:layout_height="@dimen/gallery_list_thumb_height">
|
||||
|
||||
<com.hippo.ehviewer.widget.FixedThumb
|
||||
android:id="@+id/thumb"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:maxAspect="1.333"
|
||||
app:minAspect="0.333"
|
||||
app:retryType="click" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
@@ -46,15 +53,15 @@
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_toRightOf="@id/thumb" />
|
||||
android:layout_toEndOf="@id/thumb_card" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/uploader"
|
||||
style="@style/CardMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/title"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_above="@id/rating"
|
||||
android:layout_alignStart="@id/title"
|
||||
android:layout_marginTop="2dp" />
|
||||
|
||||
<TextView
|
||||
@@ -62,8 +69,8 @@
|
||||
style="@style/CardMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_alignBottom="@id/thumb"
|
||||
android:layout_alignStart="@id/title"
|
||||
android:layout_alignBottom="@id/thumb_card"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingTop="2dp"
|
||||
@@ -77,25 +84,25 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/category"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_marginBottom="4dp" />
|
||||
android:layout_alignStart="@id/title"
|
||||
android:layout_marginBottom="2dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/posted"
|
||||
style="@style/CardMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@id/thumb"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="6dp"
|
||||
android:layout_alignBottom="@id/thumb_card"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:layout_marginBottom="4dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/posted"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="6dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:divider="@drawable/spacer_x6"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
|
||||
@@ -19,15 +19,21 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.hippo.ehviewer.widget.FixedThumb xmlns:auto="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/image"
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:foreground="?selectableItemBackground"
|
||||
auto:aspect="0.667"
|
||||
auto:maxAspect="0.8"
|
||||
auto:minAspect="0.5"
|
||||
auto:retryType="longClick" />
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.hippo.ehviewer.widget.FixedThumb xmlns:auto="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:foreground="?selectableItemBackground"
|
||||
auto:aspect="0.667"
|
||||
auto:maxAspect="0.8"
|
||||
auto:minAspect="0.5"
|
||||
auto:retryType="longClick" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
|
||||
@@ -27,43 +27,4 @@
|
||||
android:scaleType="centerCrop"
|
||||
app:srcCompat="@drawable/sadpanda_low_poly" />
|
||||
|
||||
<com.hippo.widget.LoadImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginBottom="48dp"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/display_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="@dimen/text_small" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:background="@android:color/transparent"
|
||||
android:clipToPadding="false"
|
||||
android:padding="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/night_mode"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="6dp"
|
||||
app:srcCompat="@drawable/ic_baseline_dark_mode_24"
|
||||
app:tint="#fff" />
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
||||
@@ -154,8 +154,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:text="@string/from_clipboard"
|
||||
android:textColor="?attr/textColorThemeAccent" />
|
||||
android:text="@string/from_clipboard" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -135,8 +135,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:text="@string/sign_in_via_webview"
|
||||
android:textColor="?attr/textColorThemeAccent" />
|
||||
android:text="@string/sign_in_via_webview" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sign_in_via_cookies"
|
||||
@@ -144,8 +143,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:text="@string/sign_in_via_cookies"
|
||||
android:textColor="?attr/textColorThemeAccent" />
|
||||
android:text="@string/sign_in_via_cookies" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -156,8 +154,7 @@
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:background="?selectableItemBackground"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:text="@string/skip_signing_in"
|
||||
android:textColor="?attr/textColorThemeAccent" />
|
||||
android:text="@string/skip_signing_in" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:fitsSystemWindowsInsets="top|bottom">
|
||||
|
||||
<com.hippo.widget.MaxSizeContainer xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="32dp"
|
||||
app:maxHeight="360dp"
|
||||
app:maxWidth="320dp">
|
||||
|
||||
<com.hippo.widget.lockpattern.LockPatternView
|
||||
android:id="@+id/pattern_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
|
||||
</com.hippo.widget.MaxSizeContainer>
|
||||
</FrameLayout>
|
||||
@@ -20,8 +20,8 @@
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.hippo.ehviewer.widget.CategoryTable
|
||||
android:id="@+id/search_category_table"
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/search_category_chipgroup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/search_item_interval" />
|
||||
@@ -89,7 +89,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<Switch
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
android:id="@+id/search_enable_advance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright (C) 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
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<TableRow>
|
||||
|
||||
<com.hippo.widget.CheckTextView
|
||||
style="@style/CategoryText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="@dimen/category_table_item_margin"
|
||||
android:layout_marginBottom="@dimen/category_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/doujinshi"
|
||||
android:text="@string/doujinshi"
|
||||
android:textColor="@android:color/white" />
|
||||
|
||||
<com.hippo.widget.CheckTextView
|
||||
style="@style/CategoryText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/category_table_item_margin"
|
||||
android:layout_marginBottom="@dimen/category_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/manga"
|
||||
android:text="@string/manga"
|
||||
android:textColor="@android:color/white" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
|
||||
<com.hippo.widget.CheckTextView
|
||||
style="@style/CategoryText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/category_table_item_margin"
|
||||
android:layout_marginRight="@dimen/category_table_item_margin"
|
||||
android:layout_marginBottom="@dimen/category_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/artist_cg"
|
||||
android:text="@string/artist_cg"
|
||||
android:textColor="@android:color/white" />
|
||||
|
||||
<com.hippo.widget.CheckTextView
|
||||
style="@style/CategoryText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/category_table_item_margin"
|
||||
android:layout_marginTop="@dimen/category_table_item_margin"
|
||||
android:layout_marginBottom="@dimen/category_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/game_cg"
|
||||
android:text="@string/game_cg"
|
||||
android:textColor="@android:color/white" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
|
||||
<com.hippo.widget.CheckTextView
|
||||
style="@style/CategoryText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/category_table_item_margin"
|
||||
android:layout_marginRight="@dimen/category_table_item_margin"
|
||||
android:layout_marginBottom="@dimen/category_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/western"
|
||||
android:text="@string/western"
|
||||
android:textColor="@android:color/white" />
|
||||
|
||||
<com.hippo.widget.CheckTextView
|
||||
style="@style/CategoryText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/category_table_item_margin"
|
||||
android:layout_marginTop="@dimen/category_table_item_margin"
|
||||
android:layout_marginBottom="@dimen/category_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/non_h"
|
||||
android:text="@string/non_h"
|
||||
android:textColor="@android:color/white" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
|
||||
<com.hippo.widget.CheckTextView
|
||||
style="@style/CategoryText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/category_table_item_margin"
|
||||
android:layout_marginRight="@dimen/category_table_item_margin"
|
||||
android:layout_marginBottom="@dimen/category_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/image_set"
|
||||
android:text="@string/image_set"
|
||||
android:textColor="@android:color/white" />
|
||||
|
||||
<com.hippo.widget.CheckTextView
|
||||
style="@style/CategoryText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/category_table_item_margin"
|
||||
android:layout_marginTop="@dimen/category_table_item_margin"
|
||||
android:layout_marginBottom="@dimen/category_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/cosplay"
|
||||
android:text="@string/cosplay"
|
||||
android:textColor="@android:color/white" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
|
||||
<com.hippo.widget.CheckTextView
|
||||
style="@style/CategoryText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/category_table_item_margin"
|
||||
android:layout_marginRight="@dimen/category_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/asian_porn"
|
||||
android:text="@string/asian_porn"
|
||||
android:textColor="@android:color/white" />
|
||||
|
||||
<com.hippo.widget.CheckTextView
|
||||
style="@style/CategoryText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/category_table_item_margin"
|
||||
android:layout_marginTop="@dimen/category_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/misc"
|
||||
android:text="@string/misc"
|
||||
android:textColor="@android:color/white" />
|
||||
</TableRow>
|
||||
|
||||
</merge>
|
||||
@@ -16,19 +16,26 @@
|
||||
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<com.hippo.widget.FixedAspectImageView
|
||||
android:id="@+id/preview"
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:adjustViewBounds="true"
|
||||
android:maxWidth="@dimen/image_search_max_size"
|
||||
android:maxHeight="@dimen/image_search_max_size"
|
||||
android:visibility="gone" />
|
||||
android:visibility="gone">
|
||||
|
||||
|
||||
<com.hippo.widget.FixedAspectImageView
|
||||
android:id="@+id/preview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
android:maxWidth="@dimen/image_search_max_size"
|
||||
android:maxHeight="@dimen/image_search_max_size" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/select_image"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
@@ -44,7 +51,7 @@
|
||||
android:id="@+id/search_uss"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="@dimen/advance_search_table_item_margin"
|
||||
android:layout_marginEnd="@dimen/advance_search_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:checked="true"
|
||||
android:minWidth="0dp"
|
||||
@@ -55,7 +62,7 @@
|
||||
android:id="@+id/search_osc"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/advance_search_table_item_margin"
|
||||
android:layout_marginStart="@dimen/advance_search_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:checked="false"
|
||||
android:minWidth="0dp"
|
||||
@@ -69,7 +76,7 @@
|
||||
android:id="@+id/search_se"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="@dimen/advance_search_table_item_margin"
|
||||
android:layout_marginEnd="@dimen/advance_search_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:checked="false"
|
||||
android:minWidth="0dp"
|
||||
@@ -79,7 +86,7 @@
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/advance_search_table_item_margin"
|
||||
android:layout_marginStart="@dimen/advance_search_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:checked="false" />
|
||||
|
||||
|
||||
@@ -14,20 +14,19 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
|
||||
android:id="@+id/action_add"
|
||||
android:icon="@drawable/v_plus_dark_x24"
|
||||
android:title="@string/settings"
|
||||
app:showAsAction="always" />
|
||||
android:showAsAction="always"
|
||||
android:title="@string/settings" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_default_download_label"
|
||||
android:icon="@drawable/v_download_box_dark_x24"
|
||||
android:title="@string/default_download_label"
|
||||
app:showAsAction="ifRoom" />
|
||||
android:showAsAction="ifRoom"
|
||||
android:title="@string/default_download_label" />
|
||||
|
||||
</menu>
|
||||
@@ -14,13 +14,18 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_help"
|
||||
android:icon="@drawable/v_help_circle_x24"
|
||||
android:showAsAction="ifRoom"
|
||||
android:title="@string/add" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_add"
|
||||
android:icon="@drawable/v_plus_dark_x24"
|
||||
android:title="@string/add"
|
||||
app:showAsAction="always" />
|
||||
android:showAsAction="always"
|
||||
android:title="@string/add" />
|
||||
|
||||
</menu>
|
||||
@@ -15,24 +15,8 @@
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<color name="primary_drawable">#ffffffff</color>
|
||||
<color name="secondary_drawable">#4dffffff</color>
|
||||
|
||||
<color name="content">@color/grey_825</color>
|
||||
<color name="content_activated">@color/grey_600</color>
|
||||
<color name="tag_group_background">@color/grey_775</color>
|
||||
<color name="tag_background">@color/grey_775</color>
|
||||
|
||||
<!-- divider -->
|
||||
<color name="divider">#20ffffff</color>
|
||||
|
||||
<!-- shadow -->
|
||||
|
||||
<!-- Gallery Activity -->
|
||||
|
||||
<!-- Lock pattern view -->
|
||||
<color name="lock_pattern_view_regular_color">#8affffff</color>
|
||||
|
||||
<!--Shortcut background-->
|
||||
</resources>
|
||||
@@ -519,7 +519,6 @@
|
||||
<string name="settings_about_declaration" translatable="false">EhViewer</string>
|
||||
<string name="settings_about_declaration_summary">EhViewer ไม่มีความแตกต่างจากตัวเว็บ E-Hentai.org แต่อย่างใด</string>
|
||||
<string name="settings_about_author">นักพัฒนา</string>
|
||||
<string name="settings_about_author_summary" translatable="false">Hippo <ehviewersu$gmail.com></string>
|
||||
<string name="settings_about_telegram">Telegram</string>
|
||||
<string name="settings_about_website">เว็บไซต์</string>
|
||||
<string name="settings_about_source">ซอร์สโค้ด</string>
|
||||
|
||||
@@ -759,4 +759,7 @@
|
||||
<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>
|
||||
</resources>
|
||||
@@ -18,34 +18,16 @@
|
||||
|
||||
<declare-styleable name="Theme">
|
||||
<attr name="colorEdgeEffect" format="color" />
|
||||
|
||||
<attr name="dividerColor" format="color" />
|
||||
|
||||
<attr name="textColorThemeAccent" format="color" />
|
||||
|
||||
<!-- For light theme, it's secondary dark color -->
|
||||
<!-- For dark theme, it's secondary light color -->
|
||||
<!-- For black theme, it's secondary light color -->
|
||||
<attr name="drawableColorSecondary" format="color" />
|
||||
<!-- For light theme, it's primary color -->
|
||||
<!-- For dark theme, it's primary light color -->
|
||||
<!-- For black theme, it's primary light color -->
|
||||
<attr name="drawableColorThemePrimary" format="color" />
|
||||
|
||||
<!-- Color of card background -->
|
||||
<attr name="contentColorThemePrimary" format="color" />
|
||||
<attr name="contentColorThemeAccent" format="color" />
|
||||
<attr name="contentColorReactive" format="color" />
|
||||
|
||||
<attr name="guideBackgroundColor" format="color" />
|
||||
<attr name="guideTitleColor" format="color" />
|
||||
<attr name="guideTextColor" format="color" />
|
||||
|
||||
<attr name="tagGroupBackgroundColor" format="color" />
|
||||
<attr name="tagBackgroundColor" format="color" />
|
||||
|
||||
<attr name="galleryDetailHeaderTitleColor" format="color" />
|
||||
<attr name="galleryDetailHeaderBackgroundColor" format="color" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="ProgressView">
|
||||
|
||||
@@ -15,52 +15,16 @@
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- primary_drawable 54% -->
|
||||
<!-- secondary_drawable 26% -->
|
||||
<!-- primary_drawable_dark 100% -->
|
||||
<!-- secondary_drawable_dark 30% -->
|
||||
<!-- primary_drawable_black 80% -->
|
||||
<!-- secondary_drawable_black 24% -->
|
||||
<color name="primary_drawable">#8a000000</color>
|
||||
<color name="secondary_drawable">#42000000</color>
|
||||
<color name="primary_drawable_dark">#ffffffff</color>
|
||||
<color name="primary_drawable_black">#ccffffff</color>
|
||||
<color name="secondary_drawable_black">#3dffffff</color>
|
||||
|
||||
<color name="content">#fff</color>
|
||||
<color name="content_black">@color/grey_925</color>
|
||||
|
||||
<color name="content_activated">@color/grey_300</color>
|
||||
<color name="content_activated_black">@color/grey_700</color>
|
||||
|
||||
<color name="tag_group_background">@color/colorAccent</color>
|
||||
<color name="tag_group_background_black">@color/grey_875</color>
|
||||
|
||||
<color name="tag_background">@color/colorPrimary</color>
|
||||
<color name="tag_background_black">@color/grey_875</color>
|
||||
|
||||
<color name="red_500">#fff44336</color>
|
||||
<color name="teal_500">#ff009688</color>
|
||||
<color name="purple_a200">#ffe040fb</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="grey_925">#ff191919</color>
|
||||
<color name="grey_875">#ff292929</color>
|
||||
<color name="grey_825">#ff3a3a3a</color>
|
||||
<color name="grey_775">#ff4a4a4a</color>
|
||||
<color name="grey_700">#ff616161</color>
|
||||
<color name="grey_600">#ff757575</color>
|
||||
<color name="grey_500">#ff9e9e9e</color>
|
||||
<color name="grey_300">#ffe0e0e0</color>
|
||||
<color name="brown_500">#ff795548</color>
|
||||
|
||||
<color name="colorPrimary">@color/teal_500</color>
|
||||
<color name="colorAccent">@color/purple_a200</color>
|
||||
|
||||
<color name="loading_indicator_red">#ffe53935</color>
|
||||
<color name="loading_indicator_purple">@color/purple_a700</color>
|
||||
<color name="loading_indicator_blue">#ff1d87e4</color>
|
||||
@@ -69,28 +33,16 @@
|
||||
<color name="loading_indicator_yellow">@color/yellow_800</color>
|
||||
<color name="loading_indicator_orange">@color/deep_orange_400</color>
|
||||
|
||||
<color name="check_text_view_mask">#4a000000</color>
|
||||
|
||||
<!-- Red -->
|
||||
<color name="doujinshi">#fff44336</color>
|
||||
<!-- Orange -->
|
||||
<color name="manga">#ffff9800</color>
|
||||
<!-- Yellow 700 -->
|
||||
<color name="artist_cg">#ffFbc02d</color>
|
||||
<!-- Green -->
|
||||
<color name="game_cg">#ff4caf50</color>
|
||||
<!-- Light Green -->
|
||||
<color name="western">#ff8bc34a</color>
|
||||
<!-- Blue -->
|
||||
<color name="non_h">#ff2196f3</color>
|
||||
<!-- Indigo -->
|
||||
<color name="image_set">#ff3f51b5</color>
|
||||
<!-- Purple -->
|
||||
<color name="cosplay">#ff9c27b0</color>
|
||||
<!-- Deep Purple 300 -->
|
||||
<color name="asian_porn">#ff9575cd</color>
|
||||
<!-- Pink 300 -->
|
||||
<color name="misc">#fff06292</color>
|
||||
|
||||
<!-- divider -->
|
||||
<color name="divider">#20000000</color>
|
||||
@@ -101,9 +53,6 @@
|
||||
<!-- Gallery Activity -->
|
||||
|
||||
<!-- Lock pattern view -->
|
||||
<color name="lock_pattern_view_regular_color">#8a000000</color>
|
||||
<color name="lock_pattern_view_success_color">@color/colorPrimary</color>
|
||||
<color name="lock_pattern_view_error_color">@color/red_500</color>
|
||||
|
||||
<!--Shortcut background-->
|
||||
<color name="shortcut_bg">#F5F5F5</color>
|
||||
|
||||
@@ -82,8 +82,6 @@
|
||||
<dimen name="add_thickness">2dp</dimen>
|
||||
|
||||
<!-- CategoryTable -->
|
||||
<dimen name="category_table_item_height">40dp</dimen>
|
||||
<dimen name="category_table_item_margin">4dp</dimen>
|
||||
|
||||
<!-- AdvanceSearchTable -->
|
||||
<dimen name="advance_search_table_item_margin">4dp</dimen>
|
||||
@@ -97,7 +95,6 @@
|
||||
<dimen name="image_search_max_size">240dp</dimen>
|
||||
|
||||
<!-- Switch padding -->
|
||||
<dimen name="switch_padding">8dp</dimen>
|
||||
|
||||
<!-- FabLayout -->
|
||||
<dimen name="fab_layout_primary_margin">24dp</dimen>
|
||||
@@ -120,9 +117,6 @@
|
||||
<dimen name="gallery_guide_divider_width">3dp</dimen>
|
||||
|
||||
<!-- Lock pattern view -->
|
||||
<dimen name="lock_pattern_dot_line_width">3dp</dimen>
|
||||
<dimen name="lock_pattern_dot_size">12dp</dimen>
|
||||
<dimen name="lock_pattern_dot_size_activated">28dp</dimen>
|
||||
|
||||
<!-- Custom preference -->
|
||||
|
||||
|
||||
@@ -17,6 +17,5 @@
|
||||
|
||||
<drawable name="transparent">@android:color/transparent</drawable>
|
||||
<drawable name="tile_background_activated">#7f9c27b0</drawable>
|
||||
<drawable name="sadpanda_low_poly">@color/colorPrimary</drawable>
|
||||
|
||||
</resources>
|
||||
@@ -620,7 +620,7 @@
|
||||
<string name="settings_about_declaration" translatable="false">EhViewer</string>
|
||||
<string name="settings_about_declaration_summary">EhViewer is not affiliated with E-Hentai.org in any way</string>
|
||||
<string name="settings_about_author">Author</string>
|
||||
<string name="settings_about_author_summary" translatable="false"><del>Hippo &lt;ehviewersu$gmail.com&gt;</del><br>NekoInverter &lt;nekoworkshop$protonmail.com&gt;</string>
|
||||
<string name="settings_about_author_summary" translatable="false"><del>Hippo &lt;ehviewersu$gmail.com&gt;</del><br>NekoInverter &lt;nekoworkshop$protonmail.com&gt; <br>飛鳥澪</string>
|
||||
<string name="settings_about_telegram">Telegram</string>
|
||||
<string name="settings_about_latest_release">Latest release</string>
|
||||
<string name="settings_about_website">Website</string>
|
||||
@@ -823,4 +823,7 @@
|
||||
<string name="app_link_not_verified_message">For Android 12 and newer, you need to manually add link to verified links in order to open E-Hentai links in EhViewer.</string>
|
||||
<string name="app_link_not_verified_title">App links not verified</string>
|
||||
<string name="open_by_default">Open by default</string>
|
||||
|
||||
<string name="show_library_version">Library Version</string>
|
||||
<string name="settings_privacy_require_unlock">Require Unlock</string>
|
||||
</resources>
|
||||
@@ -19,7 +19,6 @@
|
||||
<style name="AppTheme" parent="Base.AppTheme" />
|
||||
|
||||
<!-- TextAppearance -->
|
||||
<style name="TextAppearance" parent="TextAppearance.AppCompat" />
|
||||
|
||||
<!-- Progress View -->
|
||||
<style name="ProgressView">
|
||||
@@ -28,42 +27,20 @@
|
||||
<item name="android:minHeight">48dp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.CardTitle">
|
||||
<item name="android:textSize">@dimen/text_little_small</item>
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="CardTitle">
|
||||
<item name="android:textAppearance">@style/TextAppearance.CardTitle</item>
|
||||
<item name="android:textAppearance">@style/TextAppearance.Material3.TitleSmall</item>
|
||||
<item name="android:ellipsize">end</item>
|
||||
<item name="android:maxLines">2</item>
|
||||
<item name="android:lineSpacingExtra">0sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.CardMessage">
|
||||
<item name="android:textSize">@dimen/text_small</item>
|
||||
<item name="android:textColor">?android:attr/textColorSecondary</item>
|
||||
</style>
|
||||
|
||||
<style name="CardMessage">
|
||||
<item name="android:textAppearance">@style/TextAppearance.CardMessage</item>
|
||||
<item name="android:textAppearance">@style/TextAppearance.Material3.BodyMedium</item>
|
||||
<item name="android:ellipsize">end</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:maxLines">1</item>
|
||||
</style>
|
||||
|
||||
<!-- CategoryText -->
|
||||
<style name="CategoryText">
|
||||
<item name="android:textAppearance">@style/TextAppearance.AppCompat.Subhead</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:minHeight">@dimen/category_table_item_height</item>
|
||||
<item name="android:foreground">@drawable/check_text_view_foreground</item>
|
||||
<item name="android:theme">@style/Theme.Material3.DynamicColors.DayNight</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.CategoryTitle" parent="TextAppearance.AppCompat.Small">
|
||||
<item name="android:textColor">?attr/textColorThemeAccent</item>
|
||||
<style name="TextAppearance.CategoryTitle" parent="TextAppearance.Material3.TitleMedium">
|
||||
<item name="android:textStyle">bold</item>
|
||||
</style>
|
||||
|
||||
@@ -74,16 +51,6 @@
|
||||
<item name="android:gravity">center_vertical</item>
|
||||
</style>
|
||||
|
||||
<style name="ButtonInCard">
|
||||
<item name="android:textAppearance">@style/TextAppearance.AppCompat.Button</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:minHeight">48dp</item>
|
||||
<item name="android:minWidth">88dp</item>
|
||||
<item name="android:padding">8dp</item>
|
||||
<item name="android:textColor">?attr/colorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="Slider">
|
||||
<item name="thickness">2dp</item>
|
||||
<item name="radius">6dp</item>
|
||||
@@ -95,18 +62,7 @@
|
||||
<item name="indicatorColor">?attr/dividerColor</item>
|
||||
</style>
|
||||
|
||||
<style name="Guide.Title" parent="TextAppearance.AppCompat.Title">
|
||||
<style name="Guide.Title" parent="TextAppearance.Material3.TitleMedium">
|
||||
<item name="android:textColor">?attr/guideTitleColor</item>
|
||||
</style>
|
||||
|
||||
<style name="ShapeAppearanceOverlay.App.CornerSize50Percent" parent="">
|
||||
<item name="cornerSize">50%</item>
|
||||
</style>
|
||||
|
||||
<style name="ShapeAppearanceOverlay.MaterialComponents.NavigationView" parent="">
|
||||
<item name="cornerSizeTopLeft">0dp</item>
|
||||
<item name="cornerSizeBottomLeft">0dp</item>
|
||||
<item name="cornerSize">50%</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -21,47 +21,33 @@
|
||||
<!-- ========== -->
|
||||
|
||||
<style name="Base.AppTheme" parent="Theme.Material3.DynamicColors.DayNight">
|
||||
<item name="colorControlActivated">@color/colorPrimary</item>
|
||||
<item name="colorEdgeEffect">@color/grey_500</item>
|
||||
<item name="dividerColor">@color/divider</item>
|
||||
<item name="textColorThemeAccent">?android:attr/textColorSecondary</item>
|
||||
<item name="colorControlNormal">@color/primary_drawable</item>
|
||||
<item name="drawableColorSecondary">@color/secondary_drawable</item>
|
||||
<item name="drawableColorThemePrimary">@color/primary_drawable</item>
|
||||
<item name="contentColorReactive">@color/content_reactive</item>
|
||||
<item name="guideBackgroundColor">#e5303030</item>
|
||||
<item name="guideTitleColor">?android:attr/textColorPrimary</item>
|
||||
<item name="guideTextColor">?android:attr/textColorSecondary</item>
|
||||
<item name="tagGroupBackgroundColor">@color/tag_group_background</item>
|
||||
<item name="tagBackgroundColor">@color/tag_background</item>
|
||||
<item name="galleryDetailHeaderTitleColor">?android:attr/textColorPrimary</item>
|
||||
<item name="galleryDetailHeaderBackgroundColor">?attr/contentColorThemePrimary</item>
|
||||
<item name="drawableColorSecondary">@color/material_dynamic_secondary50</item>
|
||||
<item name="drawableColorThemePrimary">@color/material_dynamic_primary50</item>
|
||||
<item name="guideBackgroundColor">@color/material_dynamic_neutral80</item>
|
||||
<item name="guideTitleColor">@color/material_dynamic_primary70</item>
|
||||
<item name="guideTextColor">@color/material_dynamic_primary50</item>
|
||||
<item name="tagGroupBackgroundColor">@color/material_dynamic_primary50</item>
|
||||
<item name="tagBackgroundColor">@color/material_dynamic_neutral50</item>
|
||||
<item name="android:windowActionBar">false</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<!-- =============== -->
|
||||
<!-- Base Black Theme -->
|
||||
<!-- =============== -->
|
||||
|
||||
<style name="ThemeOverlay" />
|
||||
|
||||
<style name="ThemeOverlay.Black">
|
||||
<item name="colorPrimaryDark">@android:color/black</item>
|
||||
<item name="android:colorBackground">@android:color/black</item>
|
||||
<item name="toolbarColor">@android:color/black</item>
|
||||
<item name="dividerColor">@color/divider_black</item>
|
||||
<item name="colorControlNormal">@color/primary_drawable_black</item>
|
||||
<item name="drawableColorSecondary">@color/secondary_drawable_black</item>
|
||||
<item name="drawableColorThemePrimary">@color/primary_drawable_black</item>
|
||||
<item name="contentColorReactive">@color/content_reactive_black</item>
|
||||
<item name="guideBackgroundColor">#e5000000</item>
|
||||
<item name="tagGroupBackgroundColor">@color/tag_group_background_black</item>
|
||||
<item name="tagBackgroundColor">@color/tag_background_black</item>
|
||||
<item name="galleryDetailHeaderBackgroundColor">@android:color/black</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Gallery" parent="AppTheme"></style>
|
||||
|
||||
<!-- ============ -->
|
||||
<!-- Widget Theme -->
|
||||
<!-- ============ -->
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<intent
|
||||
android:action="start_all"
|
||||
android:targetClass="com.hippo.ehviewer.shortcuts.ShortcutsActivity"
|
||||
android:targetPackage="io.github.nekoinverter.ehviewer" />
|
||||
android:targetPackage="moe.tarsin.ehviewer" />
|
||||
<categories android:name="android.shortcut.conversation" />
|
||||
</shortcut>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<intent
|
||||
android:action="stop_all"
|
||||
android:targetClass="com.hippo.ehviewer.shortcuts.ShortcutsActivity"
|
||||
android:targetPackage="io.github.nekoinverter.ehviewer" />
|
||||
android:targetPackage="moe.tarsin.ehviewer" />
|
||||
<categories android:name="android.shortcut.conversation" />
|
||||
</shortcut>
|
||||
|
||||
|
||||
@@ -36,12 +36,6 @@
|
||||
app:iconSpaceReserved="false"
|
||||
app:url="https://github.com/asuka-mio/Ehviewer/releases" />
|
||||
|
||||
<!--<com.hippo.preference.UrlPreference
|
||||
android:key="website"
|
||||
android:title="@string/settings_about_website"
|
||||
app:iconSpaceReserved="false"
|
||||
app:url="http://www.ehviewer.com" />-->
|
||||
|
||||
<com.hippo.preference.UrlPreference
|
||||
android:key="source"
|
||||
android:title="@string/settings_about_source"
|
||||
@@ -49,18 +43,6 @@
|
||||
app:iconSpaceReserved="false"
|
||||
app:url="https://github.com/asuka-mio/Ehviewer" />
|
||||
|
||||
<!--<com.hippo.preference.UrlPreference
|
||||
android:key="changelog"
|
||||
android:title="@string/settings_about_changelog"
|
||||
app:iconSpaceReserved="false"
|
||||
app:url="http://www.ehviewer.com/changelog" />
|
||||
|
||||
<com.hippo.preference.UrlPreference
|
||||
android:key="help"
|
||||
android:title="@string/settings_about_help"
|
||||
app:iconSpaceReserved="false"
|
||||
app:url="http://www.ehviewer.com/help" />-->
|
||||
|
||||
<com.hippo.ehviewer.preference.VersionPreference
|
||||
android:key="version"
|
||||
app:iconSpaceReserved="false" />
|
||||
@@ -69,17 +51,4 @@
|
||||
android:key="check_for_updates"
|
||||
android:title="@string/settings_about_check_for_updates"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<!--<SwitchPreferenceCompat
|
||||
android:defaultValue="@bool/beta"
|
||||
android:key="beta_update_channel"
|
||||
android:summary="@string/settings_about_beta_update_channel_summary"
|
||||
android:title="@string/settings_about_beta_update_channel"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<Preference
|
||||
android:key="donate"
|
||||
android:title="@string/settings_about_donate"
|
||||
app:iconSpaceReserved="false" />-->
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -17,14 +17,14 @@
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="save_parse_error_body"
|
||||
android:summary="@string/settings_advanced_save_parse_error_body_summary"
|
||||
android:title="@string/settings_advanced_save_parse_error_body"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="save_crash_log"
|
||||
android:summary="@string/settings_advanced_save_crash_log_summary"
|
||||
@@ -72,7 +72,7 @@
|
||||
android:title="@string/settings_advanced_proxy"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="built_in_hosts_2"
|
||||
android:summary="@string/settings_advanced_built_in_hosts_summary"
|
||||
@@ -86,20 +86,13 @@
|
||||
android:title="@string/settings_advanced_custom_hosts_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="domain_fronting"
|
||||
android:summary="@string/settings_advanced_domain_fronting_summary"
|
||||
android:title="@string/settings_advanced_domain_fronting_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="e_ink_mode_2"
|
||||
android:summary="@string/settings_e_ink_mode_summary"
|
||||
android:title="@string/settings_e_ink_mode_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<Preference
|
||||
android:key="export_data"
|
||||
android:summary="@string/settings_advanced_export_data_summary"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
android:title="@string/settings_download_download_location"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="media_scan"
|
||||
android:title="@string/settings_download_media_scan"
|
||||
@@ -66,7 +66,7 @@
|
||||
app:entryValues="@array/image_resolution_entry_values"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="download_origin_image"
|
||||
android:summary="@string/settings_download_download_origin_image_summary"
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
android:title="@string/dark_theme"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:key="black_dark_theme"
|
||||
android:title="@string/black_dark_theme"
|
||||
app:iconSpaceReserved="false" />
|
||||
@@ -111,27 +111,27 @@
|
||||
app:entryValues="@array/thumb_resolution_entry_values"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="fix_thumb_url"
|
||||
android:title="@string/settings_eh_fix_thumb_url"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="show_jpn_title"
|
||||
android:summary="@string/settings_eh_show_jpn_title_summary"
|
||||
android:title="@string/settings_eh_show_jpn_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="show_gallery_pages"
|
||||
android:summary="@string/settings_eh_show_gallery_pages_summary"
|
||||
android:title="@string/settings_eh_show_gallery_pages"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="show_tag_translations"
|
||||
android:summary="@string/settings_eh_show_tag_translations_summary"
|
||||
@@ -151,13 +151,13 @@
|
||||
android:title="@string/settings_eh_filter"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="cellular_network_warning"
|
||||
android:title="@string/settings_eh_metered_network_warning"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="request_news"
|
||||
android:title="@string/settings_request_news_title"
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<Preference
|
||||
android:fragment="com.hippo.ehviewer.ui.fragment.SetSecurityFragment"
|
||||
android:key="pattern_protection"
|
||||
android:title="@string/settings_privacy_pattern_protection_title"
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="require_unlock"
|
||||
android:title="@string/settings_privacy_require_unlock"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="enable_secure"
|
||||
android:title="@string/settings_privacy_secure"
|
||||
|
||||
@@ -62,56 +62,56 @@
|
||||
app:entryValues="@array/read_theme_entry_values"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="keep_screen_on"
|
||||
android:title="@string/settings_read_keep_screen_on"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="gallery_show_clock"
|
||||
android:title="@string/settings_read_show_clock"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="gallery_show_progress"
|
||||
android:title="@string/settings_read_show_progress"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="gallery_show_battery"
|
||||
android:title="@string/settings_read_show_battery"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="gallery_show_page_interval"
|
||||
android:title="@string/settings_read_show_page_interval"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="volume_page"
|
||||
android:title="@string/settings_read_volume_page"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:dependency="volume_page"
|
||||
android:key="reserve_volume_page"
|
||||
android:title="@string/settings_read_reverse_volume"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="reading_fullscreen"
|
||||
android:title="@string/settings_read_reading_fullscreen"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="custom_screen_lightness"
|
||||
android:title="@string/settings_read_custom_screen_lightness"
|
||||
|
||||
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1003 KiB |
@@ -1,3 +1,9 @@
|
||||
buildscript {
|
||||
ext {
|
||||
compose = '1.2.0-beta02'
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'com.android.application' version '7.2.0' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
|
||||
|
||||
@@ -24,6 +24,6 @@ task executeDaoGenerator(type:JavaExec) {
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'org.greenrobot:greendao-generator:3.3.0'
|
||||
implementation 'org.jboss.forge.roaster:roaster-api:2.20.1.Final'
|
||||
implementation 'org.jboss.forge.roaster:roaster-jdt:2.20.1.Final'
|
||||
implementation 'org.jboss.forge.roaster:roaster-api:2.25.0.Final'
|
||||
implementation 'org.jboss.forge.roaster:roaster-jdt:2.25.0.Final'
|
||||
}
|
||||