Compare commits

..
61 Commits
Author SHA1 Message Date
tarsin ae941a4955 Bump Version
EhViewer / Build (push) Has been cancelled
2022-05-20 00:39:47 +08:00
tarsin 72da7ebfe4 Fix search crash 2022-05-20 00:39:07 +08:00
tarsin 8e1bacbfac Refactor Search 2022-05-19 23:59:18 +08:00
tarsin 747c19c028 Rename .java to .kt 2022-05-19 23:59:18 +08:00
txyyh aca83fc1ee Cut photo edges 2022-05-19 21:25:36 +08:00
tarsin 35babd089d Image search layout tweaks 2022-05-19 21:06:23 +08:00
tarsin 457ea56aab Reformat code 2022-05-19 20:18:59 +08:00
txyyh ed22de2360 Cut photo background 2022-05-19 20:17:13 +08:00
tarsin 8d386b44bc Kill redundant things in navmain 2022-05-19 20:16:35 +08:00
tarsin c4c88c40c5 Surround Image with round corner cardview 2022-05-19 20:07:37 +08:00
tarsin e637ad6acb Honor uploader with Chip 2022-05-19 19:48:27 +08:00
tarsin 3b9e08e1c7 Don't disturb nekochan 2022-05-19 18:30:34 +08:00
tarsin 4a2aa8a975 Update README.md 2022-05-19 14:14:42 +08:00
txyyh 9c08eda38a Rewrite README commit
Rewrite commit 713d972d16 to make it look normal
2022-05-19 13:18:01 +08:00
tarsin 713d972d16 Update README.md 2022-05-19 00:46:49 +08:00
tarsin d4b3705a9e Bump version
EhViewer / Build (push) Has been cancelled
2022-05-19 00:30:50 +08:00
tarsin c543d1540c Drop unused res
* Use dyn color as much as possible, try avoid hardcode color schemes
2022-05-19 00:28:35 +08:00
tarsin 2956ff08bd Fix black theme 2022-05-19 00:16:01 +08:00
tarsin ff09dec4e4 Refine color schemes 2022-05-19 00:00:10 +08:00
tarsin 5e02479aa5 inline a blank class 2022-05-18 22:33:06 +08:00
tarsin 6157b9cf82 Drop e-ink mode 2022-05-18 22:26:21 +08:00
tarsin 9260633e26 Merge pull request #27 from txyyh/master
Change download section in README
2022-05-18 21:23:41 +08:00
txyyh 1a2ae6b1a8 Redirect download link 2022-05-18 17:42:49 +08:00
txyyh 282b4adaff Move download link below introduce 2022-05-18 17:40:47 +08:00
tarsin 8519b5a096 New screenshot 2022-05-18 16:10:52 +08:00
tarsin 4a00be922e Merge pull request #25 from asuka-mio/renovate/actions-checkout-3.x
Update actions/checkout action to v3
2022-05-18 15:54:45 +08:00
tarsin 31f30cf1b1 Merge pull request #26 from asuka-mio/renovate/dev.rikka.rikkax.material-material-2.x
Update dependency dev.rikka.rikkax.material:material to v2
2022-05-18 15:54:34 +08:00
Renovate Bot 62737cc32f Update dependency dev.rikka.rikkax.material:material to v2 2022-05-18 07:08:08 +00:00
Renovate Bot c7306b2358 Update actions/checkout action to v3 2022-05-18 07:08:05 +00:00
tarsin 779958dfeb Merge pull request #20 from asuka-mio/renovate/com.squareup.okhttp3-okhttp-dnsoverhttps-4.x
Update dependency com.squareup.okhttp3:okhttp-dnsoverhttps to v4.9.3
2022-05-18 14:56:35 +08:00
tarsin d0ca6872b0 Merge pull request #23 from asuka-mio/renovate/actions-setup-java-3.x
Update actions/setup-java action to v3
2022-05-18 14:56:11 +08:00
tarsin 161f191f3d Merge pull request #21 from asuka-mio/renovate/org.jboss.forge.roaster-roaster-api-2.x
Update dependency org.jboss.forge.roaster:roaster-api to v2.24.0.Final
2022-05-18 14:55:59 +08:00
tarsin 2cfa46ed05 Revert "Update dependency com.github.seven332:yorozuya-thread to v0.1.2"
This reverts commit e19759a7e4.
2022-05-18 14:52:42 +08:00
tarsin 005e2b3fa1 Revert "Update dependency com.github.seven332:glview to v0.1.4"
This reverts commit 2fd688ff9e.
2022-05-18 14:49:02 +08:00
tarsin 3826dfb1d4 Revert "Update dependency com.github.seven332:beerbelly to v0.2.1"
This reverts commit b0274946bf.
2022-05-18 14:43:58 +08:00
Renovate Bot 81bb9a852f Update actions/setup-java action to v3 2022-05-18 06:22:35 +00:00
Renovate Bot 37e60673d7 Update dependency org.jboss.forge.roaster:roaster-api to v2.24.0.Final 2022-05-18 06:22:29 +00:00
Renovate Bot 9b618f7ecc Update dependency com.squareup.okhttp3:okhttp-dnsoverhttps to v4.9.3 2022-05-18 06:22:26 +00:00
tarsin 0ce3ceb900 Merge pull request #14 from asuka-mio/renovate/org.jboss.forge.roaster-roaster-jdt-2.x
Update dependency org.jboss.forge.roaster:roaster-jdt to v2.24.0.Final
2022-05-18 14:20:56 +08:00
tarsin 4833226241 Merge pull request #12 from asuka-mio/renovate/dev.rikka.rikkax.core-core-1.x
Update dependency dev.rikka.rikkax.core:core to v1.4.0
2022-05-18 14:20:45 +08:00
tarsin 5cae964a1e Merge pull request #10 from asuka-mio/renovate/com.github.seven332-beerbelly-0.x
Update dependency com.github.seven332:beerbelly to v0.2.1
2022-05-18 14:20:34 +08:00
tarsin 70eaa35bc9 Merge pull request #11 from asuka-mio/renovate/com.github.seven332-glview-0.x
Update dependency com.github.seven332:glview to v0.1.4
2022-05-18 14:20:21 +08:00
tarsin 38bd3fede1 Merge pull request #15 from asuka-mio/renovate/org.jsoup-jsoup-1.x
Update dependency org.jsoup:jsoup to v1.15.1
2022-05-18 14:20:09 +08:00
tarsin e1e32a7f5e Merge pull request #9 from asuka-mio/renovate/gradle-7.x
Update dependency gradle to v7.4.2
2022-05-18 14:19:57 +08:00
tarsin b77d0fb47a Update android.yml 2022-05-18 14:02:02 +08:00
Renovate Bot 4076b2f900 Update dependency org.jsoup:jsoup to v1.15.1 2022-05-18 05:53:38 +00:00
Renovate Bot 1bc409b54a Update dependency org.jboss.forge.roaster:roaster-jdt to v2.24.0.Final 2022-05-18 05:53:35 +00:00
Renovate Bot 1247a0ade9 Update dependency dev.rikka.rikkax.core:core to v1.4.0 2022-05-18 05:53:29 +00:00
Renovate Bot 2fd688ff9e Update dependency com.github.seven332:glview to v0.1.4 2022-05-18 05:53:26 +00:00
Renovate Bot b0274946bf Update dependency com.github.seven332:beerbelly to v0.2.1 2022-05-18 05:53:24 +00:00
Renovate Bot b78c132742 Update dependency gradle to v7.4.2 2022-05-18 05:53:20 +00:00
tarsin b33c46de82 Merge pull request #7 from asuka-mio/renovate/com.squareup.okhttp3-okhttp-4.x
Update dependency com.squareup.okhttp3:okhttp to v4.9.3
2022-05-18 13:48:56 +08:00
Renovate Bot 25c8bba1b0 Update dependency com.squareup.okhttp3:okhttp to v4.9.3 2022-05-18 05:48:23 +00:00
tarsin 089f5cb7ec Merge pull request #4 from asuka-mio/renovate/com.github.seven332-glview-image-0.x
Update dependency com.github.seven332:glview-image to v0.1.3
2022-05-18 13:45:16 +08:00
tarsin 95a6a9dca6 Merge pull request #5 from asuka-mio/renovate/com.github.seven332-yorozuya-thread-0.x
Update dependency com.github.seven332:yorozuya-thread to v0.1.2
2022-05-18 13:45:02 +08:00
Renovate Bot e19759a7e4 Update dependency com.github.seven332:yorozuya-thread to v0.1.2 2022-05-18 05:44:21 +00:00
Renovate Bot 8f95ffeebf Update dependency com.github.seven332:glview-image to v0.1.3 2022-05-18 05:44:19 +00:00
tarsin 98f08feb16 Merge pull request #3 from asuka-mio/renovate/configure
Configure Renovate
2022-05-18 13:43:53 +08:00
Renovate Bot 50baaffc36 Add renovate.json 2022-05-18 05:39:46 +00:00
tarsin 66e9f43bba Revert "Revert minsdk to sdk29"
* No dynamic color support, crashed
* Won't fix
This reverts commit 0cb13bb6a3.
2022-05-18 12:02:21 +08:00
tarsin 0cb13bb6a3 Revert minsdk to sdk29
* Sadly my HW-SCM09 is still Android Q and seems it will never upgrade, damn

* Huawei sucks
2022-05-18 11:59:03 +08:00
59 changed files with 640 additions and 1965 deletions

No files matched your search

+17 -46
View File
@@ -1,57 +1,28 @@
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
- uses: actions/checkout@v3
- 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
- uses: gradle/gradle-build-action@v2
- run: |
git submodule update --init --recursive
gradle assembleRelease
- 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 }}
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
with:
name: EhViewer
path: app/build/outputs/
name: github-${{ github.sha }}
path: app/build/outputs/apk/release/app-arm64-v8a-release-unsigned.apk
+13 -5
View File
@@ -1,15 +1,23 @@
### [下载](https://install.appcenter.ms/users/nekoinverter/apps/ehviewer/distribution_groups/public)
[Download](https://install.appcenter.ms/users/nekoinverter/apps/ehviewer/distribution_groups/public)
# EhViewer
![Icon](art/launcher_icon-web.png)
这是一个 E-Hentai Android 平台的浏览器。
这是一个 E-Hentai Android 平台的浏览器
已针对性适配 Material Design 3 及其动态取色系统
仅供 Android 12 及以上平台使用!
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
+8 -8
View File
@@ -36,8 +36,8 @@ android {
applicationId "io.github.nekoinverter.ehviewer"
minSdkVersion 31
targetSdkVersion 32
versionCode 114516
versionName "1.7.26.7"
versionCode 114518
versionName "1.7.26.9"
resConfigs 'zh', 'zh-rCN', 'zh-rHK', 'zh-rTW', 'es', 'ja', 'ko', 'fr', 'de', 'th'
}
@@ -115,28 +115,28 @@ 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
}
+1 -2
View File
@@ -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() {
@@ -594,14 +594,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);
}
@@ -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);
}
});
}
@@ -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) {
@@ -259,7 +250,16 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
mGalleryProvider = new ArchiveGalleryProvider(this, mUri);
}
}
}
} 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 void onInit() {
Intent intent = getIntent();
@@ -1304,4 +1304,6 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
}
}
@@ -22,7 +22,6 @@ 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;
@@ -33,7 +32,6 @@ 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 +41,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 +82,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 +92,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 +133,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
@@ -320,19 +310,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 +417,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 +518,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
@@ -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) {
@@ -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,412 @@
/*
* 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 com.hippo.easyrecyclerview.EasyRecyclerView
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
import android.view.LayoutInflater
import com.google.android.material.chip.ChipGroup
import com.hippo.widget.RadioGridGroup
import com.google.android.material.tabs.TabLayout
import androidx.recyclerview.widget.LinearLayoutManager
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.net.Uri
import android.os.Bundle
import androidx.recyclerview.widget.DefaultItemAnimator
import com.hippo.ehviewer.R
import com.hippo.easyrecyclerview.MarginItemDecoration
import android.view.ViewGroup
import android.util.SparseArray
import android.os.Parcelable
import android.util.AttributeSet
import android.view.View
import android.widget.*
import kotlin.Throws
import com.hippo.ehviewer.client.exception.EhException
import com.hippo.ehviewer.client.data.ListUrlBuilder
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import androidx.annotation.IntDef
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import com.google.android.material.chip.Chip
import com.hippo.easyrecyclerview.SimpleHolder
import com.hippo.ehviewer.client.EhConfig
import com.hippo.yorozuya.NumberUtils
import com.hippo.yorozuya.ViewUtils
import java.lang.IndexOutOfBoundsException
class SearchLayout : EasyRecyclerView, CompoundButton.OnCheckedChangeListener, View.OnClickListener,
ImageSearchLayout.Helper, OnTabSelectedListener {
private val mInflater : LayoutInflater
private val mSharePref : SharedPreferences
@SearchMode
private var mSearchMode = SEARCH_MODE_NORMAL
private var mEnableAdvance = false
private var mNormalView: View? = null
private var mNormalSearchMode: RadioGridGroup? = null
private var mNormalSearchModeHelp: ImageView? = null
private var mEnableAdvanceSwitch: Switch? = null
private var mAdvanceView: View? = null
private var mTableAdvanceSearch: AdvanceSearchTable? = null
private var mImageView: ImageSearchLayout? = null
private var mActionView: View? = null
private var mAction: TabLayout? = null
private var mLayoutManager: LinearLayoutManager? = null
private var mAdapter: SearchAdapter? = null
private var mHelper: Helper? = null
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)
)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
mSharePref = PreferenceManager.getDefaultSharedPreferences(context)
mInflater = LayoutInflater.from(context)
init(context)
}
constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(
context,
attrs,
defStyle
) {
mSharePref = PreferenceManager.getDefaultSharedPreferences(context)
mInflater = LayoutInflater.from(context)
init(context)
}
@SuppressLint("InflateParams")
private fun init(context: Context) {
val resources = context.resources
mLayoutManager = SearchLayoutManager(context)
mAdapter = SearchAdapter()
mAdapter!!.setHasStableIds(true)
layoutManager = mLayoutManager
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
val normalView = mInflater.inflate(R.layout.search_normal, null)
mNormalView = normalView
val mCategoryStored = mSharePref.getInt(SEARCH_CATEGORY_PREF, EhConfig.ALL_CATEGORY)
val mCategoryGroup = normalView.findViewById(R.id.search_category_chipgroup) as 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)
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 = 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!!.switchPadding = 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 = 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() {
mLayoutManager!!.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 dispatchSaveInstanceState(container: SparseArray<Parcelable>) {
super.dispatchSaveInstanceState(container)
mNormalView!!.saveHierarchyState(container)
mAdvanceView!!.saveHierarchyState(container)
mImageView!!.saveHierarchyState(container)
mActionView!!.saveHierarchyState(container)
}
override fun dispatchRestoreInstanceState(container: SparseArray<Parcelable>) {
super.dispatchRestoreInstanceState(container)
mNormalView!!.restoreHierarchyState(container)
mAdvanceView!!.restoreHierarchyState(container)
mImageView!!.restoreHierarchyState(container)
mActionView!!.restoreHierarchyState(container)
}
override fun onSaveInstanceState(): Parcelable {
val state = 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 fun onRestoreInstanceState(state: Parcelable) {
if (state is Bundle) {
super.onRestoreInstanceState(state.getParcelable(STATE_KEY_SUPER))
mSearchMode = state.getInt(STATE_KEY_SEARCH_MODE)
mEnableAdvance = state.getBoolean(STATE_KEY_ENABLE_ADVANCE)
}
}
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
private const val STATE_KEY_SUPER = "super"
private const val STATE_KEY_SEARCH_MODE = "search_mode"
private const val STATE_KEY_ENABLE_ADVANCE = "enable_advance"
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 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,8 @@ 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; private final Runnable mCharger = new Runnable() {
private int level = 0;
@@ -55,13 +56,35 @@ 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);
}
public BatteryView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
TypedArray typedArray = context.obtainStyledAttributes(
attrs, R.styleable.BatteryView, defStyleAttr, 0);
mColor = typedArray.getColor(R.styleable.BatteryView_color, Color.WHITE);
mWarningColor = typedArray.getColor(R.styleable.BatteryView_warningColor, Color.RED);
typedArray.recycle();
mDrawable.setColor(mColor);
mDrawable.setWarningColor(mWarningColor);
}
private void init() {
mDrawable = new BatteryDrawable();
int height = (int) getTextSize();
mDrawable.setBounds(0, 0, (int) (height / 0.618f), height);
setCompoundDrawables(mDrawable, null, null, null);
} private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
@@ -93,28 +116,6 @@ public class BatteryView extends AppCompatTextView {
}
};
public BatteryView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
TypedArray typedArray = context.obtainStyledAttributes(
attrs, R.styleable.BatteryView, defStyleAttr, 0);
mColor = typedArray.getColor(R.styleable.BatteryView_color, Color.WHITE);
mWarningColor = typedArray.getColor(R.styleable.BatteryView_warningColor, Color.RED);
typedArray.recycle();
mDrawable.setColor(mColor);
mDrawable.setWarningColor(mWarningColor);
}
private void init() {
mDrawable = new BatteryDrawable();
int height = (int) getTextSize();
mDrawable.setBounds(0, 0, (int) (height / 0.618f), height);
setCompoundDrawables(mDrawable, null, null, null);
}
@Override
public void setTextColor(int color) {
if (mCurrentColor == color) {
@@ -173,4 +174,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,17 @@ 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();
}
}; private final Runnable mTicker = new Runnable() {
@Override
public void run() {
onTimeChanged();
@@ -66,16 +76,12 @@ 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()) {
public TextClock(Context context) {
this(context, null);
}
public TextClock(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
chooseFormat();
@@ -88,12 +94,6 @@ public class TextClock extends AppCompatTextView {
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);
@@ -261,4 +261,6 @@ public class TextClock extends AppCompatTextView {
}
@@ -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>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

@@ -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
@@ -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,38 +65,30 @@
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
<com.google.android.material.chip.Chip
android:id="@+id/uploader"
style="@style/Widget.Material3.Chip.Assist"
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
<com.google.android.material.chip.Chip
android:id="@+id/category"
style="@style/Widget.Material3.Chip.Assist"
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_alignStart="@id/title"
android:ellipsize="end"
android:paddingLeft="8dp"
android:paddingTop="2dp"
android:paddingRight="8dp"
android:paddingBottom="2dp"
android:singleLine="true"
android:textAllCaps="true"
android:textStyle="bold" />
@@ -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>
+13 -14
View File
@@ -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>
+24 -16
View File
@@ -29,13 +29,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,7 +54,7 @@
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"
@@ -54,7 +62,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" />
<TextView
@@ -62,8 +70,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,7 +85,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/category"
android:layout_alignLeft="@id/title"
android:layout_alignStart="@id/title"
android:layout_marginBottom="4dp" />
<TextView
@@ -85,17 +93,17 @@
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>
+3 -6
View File
@@ -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>
+3 -3
View File
@@ -20,11 +20,11 @@
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" />
android:layout_marginBottom="@dimen/search_item_interval"/>
<com.hippo.widget.RadioGridGroup
android:id="@+id/normal_search_mode"
@@ -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>
+18 -11
View File
@@ -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" />
-6
View File
@@ -17,12 +17,6 @@
<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>
-18
View File
@@ -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">
-33
View File
@@ -15,52 +15,20 @@
-->
<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>
@@ -68,7 +36,6 @@
<color name="loading_indicator_green">@color/light_green_600</color>
<color name="loading_indicator_yellow">@color/yellow_800</color>
<color name="loading_indicator_orange">@color/deep_orange_400</color>
<color name="check_text_view_mask">#4a000000</color>
<!-- Red -->
+6 -21
View File
@@ -19,7 +19,7 @@
<style name="AppTheme" parent="Base.AppTheme" />
<!-- TextAppearance -->
<style name="TextAppearance" parent="TextAppearance.AppCompat" />
<style name="TextAppearance" parent="TextAppearance.Material3.TitleMedium" />
<!-- Progress View -->
<style name="ProgressView">
@@ -30,7 +30,6 @@
<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">
@@ -42,7 +41,6 @@
<style name="TextAppearance.CardMessage">
<item name="android:textSize">@dimen/text_small</item>
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
<style name="CardMessage">
@@ -54,16 +52,15 @@
<!-- CategoryText -->
<style name="CategoryText">
<item name="android:textAppearance">@style/TextAppearance.AppCompat.Subhead</item>
<item name="android:textAppearance">@style/TextAppearance.Material3.ActionBar.Subtitle
</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>
@@ -75,13 +72,12 @@
</style>
<style name="ButtonInCard">
<item name="android:textAppearance">@style/TextAppearance.AppCompat.Button</item>
<item name="android:textAppearance">@style/TextAppearance.Material3.LabelLarge</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">
@@ -95,18 +91,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>
+10 -21
View File
@@ -24,44 +24,33 @@
<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 -->
<!-- ============ -->
-31
View File
@@ -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>
@@ -93,13 +93,6 @@
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"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 735 KiB

+2 -2
View File
@@ -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.24.0.Final'
implementation 'org.jboss.forge.roaster:roaster-jdt:2.24.0.Final'
}
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-1
View File
@@ -1 +0,0 @@
<manifest />
@@ -31,9 +31,9 @@ public class ImageDrawable extends Drawable implements Animatable, ImageBitmap.C
private final ImageBitmap mImageBitmap;
private final Paint mPaint;
public ImageDrawable(ImageBitmap imageBitmap) throws RecycledException {
public ImageDrawable(ImageBitmap imageBitmap) throws Exception {
if (!imageBitmap.obtain()) {
throw new RecycledException();
throw new Exception();
}
mImageBitmap = imageBitmap;
@@ -1,23 +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.image;
/**
* Image is recycled.
*/
public class RecycledException extends Exception {
}
+5
View File
@@ -0,0 +1,5 @@
{
"extends": [
"config:base"
]
}