Compare commits

...
52 Commits
Author SHA1 Message Date
tarsin ac55e2f8fc Version bump
EhViewer / Build (push) Has been cancelled
Releases / Build (push) Has been cancelled
2022-05-25 16:31:27 +08:00
tarsin 24718e7d25 Add my name to author 2022-05-25 16:30:50 +08:00
tarsin 72e1fe9621 Rename packagename 2022-05-25 16:19:59 +08:00
tarsin 0c7bf96bf5 No "require unlock" available when keyguard is not enabled 2022-05-25 15:55:54 +08:00
tarsin f1dde6c8bc Rename .java to .kt 2022-05-25 15:55:54 +08:00
tarsin 3177a8352f Drop unused res 2022-05-25 15:30:01 +08:00
tarsin 3cb024b7f5 Do code reformat 2022-05-25 15:25:57 +08:00
tarsin 0a09d16500 Drop LockPatternView, migrate to system's provider 2022-05-25 15:24:35 +08:00
tarsin a79b1ad785 Rename .java to .kt 2022-05-25 15:24:35 +08:00
tarsin 4388c53929 Clean primary color
* No hardcode primary color anymore
2022-05-25 14:08:57 +08:00
tarsin 02f000d37b Merge pull request #41 from txyyh/feature/checkbox
Use checkbox instead
2022-05-24 23:44:32 +08:00
txyyh 7259e5e315 Use checkbox instead
It's clear that button will be too big when switch to m3 button, and radio button is not suitable, so that's it.
2022-05-24 23:01:43 +08:00
tarsin 7ce744b5af Fix #39 2022-05-24 21:34:37 +08:00
tarsin 57f21c8d39 Version bump
EhViewer / Build (push) Has been cancelled
Releases / Build (push) Has been cancelled
2022-05-24 18:19:11 +08:00
tarsin 07f27a8438 screenshot update 2022-05-24 18:16:56 +08:00
tarsin 4f4dc55b4e itemcard layout tweaks 2022-05-24 18:15:33 +08:00
tarsin 8e9cda8e93 update screenshot 2022-05-24 17:37:46 +08:00
tarsin d5cfabd73e Only check this when longpressed on chip 2022-05-24 17:12:05 +08:00
tarsin 4f1b371e75 Drop fuse-archive
* This glue can't work with latest libfuse and require c++ STL for no reason, drop it and try find better impl
2022-05-24 16:59:07 +08:00
tarsin 4d8b50912d Version bump
EhViewer / Build (push) Has been cancelled
Releases / Build (push) Has been cancelled
2022-05-24 16:52:50 +08:00
tarsin 660c717cfb Make elf32 release 2022-05-24 16:51:37 +08:00
tarsin 70d3d9a5b2 Update jconfigint.h 2022-05-24 16:35:37 +08:00
tarsin 464da25ca1 Update android.yml 2022-05-24 16:08:58 +08:00
tarsin c2795120e1 Update CMakeLists.txt 2022-05-24 16:00:51 +08:00
tarsin b10fb46f1f Update build.gradle 2022-05-24 15:48:38 +08:00
tarsin e39897176a Update build.gradle 2022-05-24 15:47:45 +08:00
tarsin 6e7e6fab74 Import fuse-archive 0.1.11
* From https://github.com/google/fuse-archive
2022-05-24 11:33:41 +08:00
tarsin 94009b6829 Build libfuse 2022-05-24 11:09:19 +08:00
tarsin 289217fefc Add libfuse 3.11.0 2022-05-24 10:02:26 +08:00
tarsin 97feab1203 Rename native libs, drop a rikka util 2022-05-24 09:23:05 +08:00
tarsin a9a3b20eb3 Make all lib shared 2022-05-23 21:22:39 +08:00
tarsin 7af1e168a4 Bump Version
EhViewer / Build (push) Has been cancelled
Releases / Build (push) Has been cancelled
2022-05-23 20:46:46 +08:00
tarsin c8bf34e0d7 Switch to md3 switch 2022-05-23 20:46:09 +08:00
tarsin 86d2282cd6 native: Reformat code 2022-05-23 20:04:04 +08:00
tarsin cfdb23d6dc app: Reformat code 2022-05-23 19:59:40 +08:00
tarsin 1874ddd15b Add nativelib version check 2022-05-23 19:58:16 +08:00
tarsin a004c308cc Rename .java to .kt 2022-05-23 19:58:16 +08:00
tarsin 863337c789 Support fskip for better decompress perf
* Actually the whole impl can't be more sucks, will import algorithm to manage buffer and read strategy further
2022-05-23 17:34:59 +08:00
tarsin 64d91eed33 Upgrade libjpeg-turbo to 2.1.3 2022-05-23 14:55:15 +08:00
tarsin d0c3a3e14d Refactor cmake 2022-05-23 11:36:51 +08:00
tarsin 464636d87d Add zstd support 2022-05-23 11:28:28 +08:00
tarsin 0b0a1f456f Reduce supported ext
* hippo's legacy glgallery only support these four extensions, further support need we migrate to coil and drop glgallery, in progress
2022-05-23 08:40:15 +08:00
tarsin 302030ca65 Update README.md 2022-05-23 08:28:38 +08:00
tarsin 3e63738542 Make a release
EhViewer / Build (push) Has been cancelled
Releases / Build (push) Has been cancelled
2022-05-23 08:21:14 +08:00
tarsin d6823c9c8e Checkout to our newly patched libarchive 2022-05-23 08:04:59 +08:00
tarsin 6bc3866660 Build lzma
FIXME: Don't hack!!
https://github.com/asuka-mio/libarchive/commit/588598490ad0a80e44554ed5e608a9f9878220c0
2022-05-23 08:02:20 +08:00
tarsin f41f4dd8ba Support 7z read 2022-05-23 07:31:58 +08:00
tarsin cde39812ce Update proguard-rules.pro 2022-05-23 01:12:58 +08:00
tarsin 03c2abc901 Merge pull request #34 from txyyh/feature/Button
Use Material3 Button instead
2022-05-23 00:59:14 +08:00
tarsin 7646334525 Don't obfuscate native code 2022-05-23 00:59:00 +08:00
txyyh f8d1cd3fab Use Material3 Button instead 2022-05-23 00:47:28 +08:00
tarsin 4ea94be64a Update releases.yml 2022-05-23 00:44:56 +08:00
81 changed files with 761 additions and 2349 deletions

No files matched your search

+17 -5
View File
@@ -13,8 +13,8 @@ jobs:
- name: Setup Java 11
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
distribution: temurin
java-version: 11
- name: Setup Android SDK Tools
uses: android-actions/setup-android@v2
@@ -32,11 +32,23 @@ jobs:
- name: Update ARM64
uses: actions/upload-artifact@v3
with:
name: arm64-${{ github.sha }}
path: app/build/outputs/apk/release/app-arm64-v8a-release.apk
name: arm64-${{ github.sha }}
path: app/build/outputs/apk/release/app-arm64-v8a-release.apk
- name: Update x86_64
uses: actions/upload-artifact@v3
with:
name: x86_64-${{ github.sha }}
path: app/build/outputs/apk/release/app-x86_64-release.apk
path: app/build/outputs/apk/release/app-x86_64-release.apk
- name: Update ARM32
uses: actions/upload-artifact@v3
with:
name: armeabi-v7a-${{ github.sha }}
path: app/build/outputs/apk/release/app-armeabi-v7a-release.apk
- name: Update x86
uses: actions/upload-artifact@v3
with:
name: x86-${{ github.sha }}
path: app/build/outputs/apk/release/app-x86-release.apk
+4 -3
View File
@@ -16,8 +16,8 @@ jobs:
- name: Setup Java 11
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
distribution: temurin
java-version: 11
- name: Setup Android SDK Tools
uses: android-actions/setup-android@v2
@@ -36,7 +36,8 @@ jobs:
uses: softprops/action-gh-release@v0.1.14
with:
body: Bump Version
prerelease: true
files: |
app/build/outputs/apk/release/app-arm64-v8a-release.apk
app/build/outputs/apk/release/app-x86_64-release.apk
app/build/outputs/apk/release/app-x86-release.apk
app/build/outputs/apk/release/app-armeabi-v7a-release.apk
+7 -1
View File
@@ -1,6 +1,6 @@
[submodule "native/src/main/jni/image/libjpeg-turbo/libjpeg-turbo"]
path = native/src/main/jni/image/libjpeg-turbo/libjpeg-turbo
url = https://gitlab.com/NekoInverter/libjpeg-turbo.git
url = https://github.com/asuka-mio/libjpeg-turbo
[submodule "native/src/main/jni/image/giflib/giflib"]
path = native/src/main/jni/image/giflib/giflib
url = https://gitlab.com/NekoInverter/giflib.git
@@ -13,3 +13,9 @@
[submodule "native/src/main/jni/liblzma"]
path = native/src/main/jni/liblzma
url = https://git.tukaani.org/xz.git
[submodule "native/src/main/jni/libzstd"]
path = native/src/main/jni/libzstd
url = https://github.com/facebook/zstd
[submodule "native/src/main/jni/libfuse/libfuse"]
path = native/src/main/jni/libfuse/libfuse
url = https://github.com/libfuse/libfuse/
+2
View File
@@ -74,6 +74,8 @@ Here is the libraries
- [ShowcaseView](https://github.com/amlcurran/ShowcaseView)
- [Slabo](https://github.com/TiroTypeworks/Slabo)
- [TagSoup](http://home.ccil.org/~cowan/tagsoup/)
- [libarchive](http://www.libarchive.org/)
- [XZ Utils](https://tukaani.org/xz/)
# License
+12 -13
View File
@@ -17,17 +17,17 @@ android {
abi {
enable = true
reset()
include 'arm64-v8a', 'x86_64'
include 'arm64-v8a', 'x86_64', 'armeabi-v7a', 'x86'
}
}
signingConfigs {
sign {
storeFile file(signStoreFile)
storePassword signStorePassword
keyAlias signkeyAlias
keyPassword signkeyPassword
}
sign {
storeFile file(signStoreFile)
storePassword signStorePassword
keyAlias signkeyAlias
keyPassword signkeyPassword
}
}
buildFeatures {
@@ -35,11 +35,11 @@ android {
}
defaultConfig {
applicationId "io.github.nekoinverter.ehviewer"
applicationId "moe.tarsin.ehviewer"
minSdkVersion 31
targetSdkVersion 32
versionCode 114520
versionName "1.7.27.0"
versionCode 114525
versionName "1.7.27.5"
resConfigs 'zh', 'zh-rCN', 'zh-rHK', 'zh-rTW', 'es', 'ja', 'ko', 'fr', 'de', 'th'
}
@@ -100,8 +100,8 @@ tasks.withType(JavaCompile) {
dependencies {
implementation 'androidx.activity:activity:1.4.0'
implementation "androidx.activity:activity-compose:1.4.0"
implementation 'androidx.biometric:biometric:1.1.0'
implementation 'androidx.activity:activity-compose:1.4.0'
implementation 'androidx.biometric:biometric-ktx:1.2.0-alpha04'
implementation 'androidx.browser:browser:1.4.0'
implementation 'androidx.core:core:1.7.0'
implementation 'androidx.dynamicanimation:dynamicanimation:1.1.0-alpha03'
@@ -133,7 +133,6 @@ dependencies {
implementation 'dev.rikka.rikkax.layoutinflater:layoutinflater:1.2.0'
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'
@@ -86,7 +86,7 @@ public class Settings {
****** Advanced
********************/
public static final String KEY_SAVE_PARSE_ERROR_BODY = "save_parse_error_body";
public static final String KEY_SECURITY = "security";
public static final String KEY_SECURITY = "require_unlock";
public static final String DEFAULT_SECURITY = "";
public static final String KEY_ENABLE_FINGERPRINT = "enable_fingerprint";
public static final String KEY_READ_CACHE_SIZE = "read_cache_size";
@@ -1028,22 +1028,18 @@ public class Settings {
return getBoolean(KEY_SAVE_CRASH_LOG, DEFAULT_SAVE_CRASH_LOG);
}
public static String getSecurity() {
return getString(KEY_SECURITY, DEFAULT_SECURITY);
public static boolean getSecurity() {
return getBoolean(KEY_SECURITY, false);
}
public static void putSecurity(String value) {
putString(KEY_SECURITY, value);
public static void putSecurity(boolean value) {
putBoolean(KEY_SECURITY, value);
}
public static boolean getEnableFingerprint() {
return getBoolean(KEY_ENABLE_FINGERPRINT, true);
}
public static void putEnableFingerprint(boolean value) {
putBoolean(KEY_ENABLE_FINGERPRINT, value);
}
public static int getReadCacheSize() {
return getIntFromStr(KEY_READ_CACHE_SIZE, DEFAULT_READ_CACHE_SIZE);
}
@@ -29,7 +29,6 @@ import androidx.annotation.Nullable;
import androidx.core.app.NotificationChannelCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import com.hippo.ehviewer.EhApplication;
import com.hippo.ehviewer.R;
@@ -224,8 +223,6 @@ public class DownloadService extends Service implements DownloadManager.Download
.setOngoing(true)
.setAutoCancel(false)
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
.setColorized(true)
.addAction(R.drawable.v_pause_x24, getString(R.string.stat_download_action_stop_all), piStopAll)
.setShowWhen(false)
.setChannelId(CHANNEL_ID);
@@ -254,7 +251,6 @@ public class DownloadService extends Service implements DownloadManager.Download
mDownloadedBuilder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID)
.setSmallIcon(android.R.drawable.stat_sys_download_done)
.setContentTitle(getString(R.string.stat_download_done_title))
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
.setDeleteIntent(piClear)
.setOngoing(false)
.setAutoCancel(true)
@@ -273,7 +269,6 @@ public class DownloadService extends Service implements DownloadManager.Download
.setContentText(getString(R.string.stat_509_alert_title))
.setContentText(getString(R.string.stat_509_alert_text))
.setStyle(new NotificationCompat.BigTextStyle().bigText(getString(R.string.stat_509_alert_text)))
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
.setAutoCancel(true)
.setOngoing(false)
.setCategory(NotificationCompat.CATEGORY_ERROR);
@@ -52,7 +52,7 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
private volatile int size = STATE_WAIT;
private String error;
public ArchiveGalleryProvider(Context context, Uri uri){
public ArchiveGalleryProvider(Context context, Uri uri) {
UriArchiveAccessor archiveAccessor1;
try {
archiveAccessor1 = new UriArchiveAccessor(context, uri);
@@ -194,7 +194,7 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
continue;
}
Pipe pipe = new Pipe(32 * 2048);
Pipe pipe = new Pipe(4096);
synchronized (streams) {
if (streams.get(index) != null) {
@@ -1,58 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.preference;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.util.AttributeSet;
import androidx.preference.Preference;
import com.hippo.ehviewer.R;
public class VersionPreference extends Preference {
public VersionPreference(Context context) {
super(context);
init(context);
}
public VersionPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public VersionPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
setTitle(R.string.settings_about_version);
String version;
try {
PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
version = pInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
version = context.getString(R.string.error_unknown);
}
setSummary(version);
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.preference
import android.content.Context
import android.content.pm.PackageManager
import android.util.AttributeSet
import androidx.appcompat.app.AlertDialog
import com.hippo.Native
import com.hippo.ehviewer.R
import com.hippo.preference.MessagePreference
class VersionPreference @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : MessagePreference(context, attrs) {
init {
setTitle(R.string.settings_about_version)
val version: String = try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
pInfo.versionName
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
context.getString(R.string.error_unknown)
}
summary = version
}
override fun onPrepareDialogBuilder(builder: AlertDialog.Builder) {
super.onPrepareDialogBuilder(builder)
builder.setTitle(R.string.show_library_version)
builder.setMessage(Native.getlibarchiveVersion() + "\nlzma(xz-utils) " + Native.getliblzmaVersion() + "\nlibzstd " + Native.getlibzstdVersion() + "\nzlib " + Native.getzlibVersion() + "\nlibjpeg-turbo " + Native.getlibjpeg_turboVersion())
}
}
@@ -49,7 +49,6 @@ import android.webkit.MimeTypeMap;
import android.widget.FrameLayout;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
@@ -66,6 +65,7 @@ import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.WindowInsetsControllerCompat;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.switchmaterial.SwitchMaterial;
import com.hippo.ehviewer.AppConfig;
import com.hippo.ehviewer.BuildConfig;
import com.hippo.ehviewer.R;
@@ -246,16 +246,7 @@ 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();
@@ -279,7 +270,16 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
mPage = savedInstanceState.getInt(KEY_PAGE, -1);
mCurrentIndex = savedInstanceState.getInt(KEY_CURRENT_INDEX);
buildProvider();
}
} ActivityResultLauncher<String> requestStoragePermissionLauncher = registerForActivityResult(
new ActivityResultContracts.RequestPermission(),
result -> {
if (result && mSavingPage != -1) {
saveImage(mSavingPage);
} else {
Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show();
}
mSavingPage = -1;
});
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
@@ -1047,15 +1047,15 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
private final Spinner mScaleMode;
private final Spinner mStartPosition;
private final Spinner mReadTheme;
private final Switch mKeepScreenOn;
private final Switch mShowClock;
private final Switch mShowProgress;
private final Switch mShowBattery;
private final Switch mShowPageInterval;
private final Switch mVolumePage;
private final Switch mReverseVolumePage;
private final Switch mReadingFullscreen;
private final Switch mCustomScreenLightness;
private final SwitchMaterial mKeepScreenOn;
private final SwitchMaterial mShowClock;
private final SwitchMaterial mShowProgress;
private final SwitchMaterial mShowBattery;
private final SwitchMaterial mShowPageInterval;
private final SwitchMaterial mVolumePage;
private final SwitchMaterial mReverseVolumePage;
private final SwitchMaterial mReadingFullscreen;
private final SwitchMaterial mCustomScreenLightness;
private final SeekBar mScreenLightness;
@SuppressLint("InflateParams")
@@ -28,7 +28,6 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.MenuItem;
import android.view.View;
@@ -143,7 +142,7 @@ public final class MainActivity extends StageActivity
@NonNull
@Override
protected Announcer getLaunchAnnouncer() {
if (!TextUtils.isEmpty(Settings.getSecurity())) {
if (Settings.getSecurity() && SecurityScene.Companion.isAuthenticationSupported(this)) {
return new Announcer(SecurityScene.class);
} else if (Settings.getShowWarning()) {
return new Announcer(WarningScene.class);
@@ -161,7 +160,7 @@ public final class MainActivity extends StageActivity
// Sometimes scene can't show directly
private Announcer processAnnouncer(Announcer announcer) {
if (0 == getSceneCount()) {
if (!TextUtils.isEmpty(Settings.getSecurity())) {
if (Settings.getSecurity() && SecurityScene.Companion.isAuthenticationSupported(this)) {
Bundle newArgs = new Bundle();
newArgs.putString(SecurityScene.KEY_TARGET_SCENE, announcer.getClazz().getName());
newArgs.putBundle(SecurityScene.KEY_TARGET_ARGS, announcer.getArgs());
@@ -1,37 +0,0 @@
package com.hippo.ehviewer.ui.fragment;
import android.os.Bundle;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.Settings;
/**
* Created by Mo10 on 2018/2/10.
*/
public class PrivacyFragment extends BasePreferenceFragment {
private static final String KEY_PATTERN_PROTECTION = "pattern_protection";
@Override
public void onCreatePreferencesFix(@Nullable Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.privacy_settings);
}
@Override
public void onStart() {
super.onStart();
Preference patternProtection = findPreference(KEY_PATTERN_PROTECTION);
patternProtection.setSummary(TextUtils.isEmpty(Settings.getSecurity()) ?
R.string.settings_privacy_pattern_protection_not_set :
R.string.settings_privacy_pattern_protection_set);
}
@Override
public int getFragmentTitle() {
return R.string.settings_privacy;
}
}
@@ -0,0 +1,29 @@
package com.hippo.ehviewer.ui.fragment
import android.os.Bundle
import androidx.preference.SwitchPreferenceCompat
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.ui.scene.SecurityScene.Companion.isAuthenticationSupported
/**
* Created by Mo10 on 2018/2/10.
*/
class PrivacyFragment : BasePreferenceFragment() {
override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.privacy_settings)
}
override fun onStart() {
super.onStart()
if (!isAuthenticationSupported(requireContext())) {
Settings.putSecurity(false)
findPreference<SwitchPreferenceCompat>("require_unlock")?.isEnabled = false
findPreference<SwitchPreferenceCompat>("require_unlock")?.isChecked = false
}
}
override fun getFragmentTitle(): Int {
return R.string.settings_privacy
}
}
@@ -1,87 +0,0 @@
package com.hippo.ehviewer.ui.fragment;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.biometric.BiometricManager;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.Settings;
import com.hippo.widget.lockpattern.LockPatternUtils;
import com.hippo.widget.lockpattern.LockPatternView;
import com.hippo.yorozuya.ViewUtils;
public class SetSecurityFragment extends BaseFragment implements View.OnClickListener {
@Nullable
private LockPatternView mPatternView;
@Nullable
private View mCancel;
@Nullable
private View mSet;
@Nullable
private CheckBox mFingerprint;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_set_security, container, false);
mPatternView = (LockPatternView) ViewUtils.$$(view, R.id.pattern_view);
mCancel = ViewUtils.$$(view, R.id.cancel);
mSet = ViewUtils.$$(view, R.id.set);
mFingerprint = (CheckBox) ViewUtils.$$(view, R.id.fingerprint_checkbox);
String pattern = Settings.getSecurity();
if (!TextUtils.isEmpty(pattern)) {
mPatternView.setPattern(LockPatternView.DisplayMode.Correct,
LockPatternUtils.stringToPattern(pattern));
}
if (BiometricManager.from(requireContext()).canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS) {
mFingerprint.setVisibility(View.VISIBLE);
mFingerprint.setChecked(Settings.getEnableFingerprint());
}
mCancel.setOnClickListener(this);
mSet.setOnClickListener(this);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
mPatternView = null;
}
@Override
public void onClick(View v) {
if (v == mCancel) {
requireActivity().onBackPressed();
} else if (v == mSet) {
if (null != mPatternView && null != mFingerprint) {
String security;
if (mPatternView.getCellSize() <= 1) {
security = "";
} else {
security = mPatternView.getPatternString();
}
Settings.putSecurity(security);
Settings.putEnableFingerprint(mFingerprint.getVisibility() == View.VISIBLE &&
mFingerprint.isChecked() && !security.isEmpty());
}
requireActivity().onBackPressed();
}
}
@Override
public int getFragmentTitle() {
return R.string.set_pattern_protection;
}
}
@@ -468,7 +468,6 @@ public class DownloadsScene extends ToolbarScene
TapTarget.forBounds(bounds,
getString(R.string.guide_download_labels_title),
getString(R.string.guide_download_labels_text))
.outerCircleColor(R.color.colorPrimary)
.transparentTarget(true),
new TapTargetView.Listener() {
@Override
@@ -68,6 +68,7 @@ import com.hippo.ehviewer.client.data.FavListUrlBuilder;
import com.hippo.ehviewer.client.data.GalleryInfo;
import com.hippo.ehviewer.client.parser.FavoritesParser;
import com.hippo.ehviewer.ui.CommonOperations;
import com.hippo.ehviewer.ui.EhActivity;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.ehviewer.ui.annotation.DrawerLifeCircle;
import com.hippo.ehviewer.ui.annotation.ViewLifeCircle;
@@ -290,7 +291,13 @@ public class FavoritesScene extends BaseScene implements
updateSearchBar();
mSearchBarMover = new SearchBarMover(this, mSearchBar, mRecyclerView);
mActionFabDrawable = new AddDeleteDrawable(context, resources.getColor(R.color.primary_drawable_dark));
int colorID;
if (EhActivity.isNightMode(context.getResources().getConfiguration())) {
colorID = resources.getColor(android.R.color.white, getTheme());
} else {
colorID = resources.getColor(android.R.color.black, getTheme());
}
mActionFabDrawable = new AddDeleteDrawable(context, colorID);
mFabLayout.getPrimaryFab().setImageDrawable(mActionFabDrawable);
mFabLayout.setExpanded(false, false);
mFabLayout.setAutoCancel(true);
@@ -334,7 +341,6 @@ public class FavoritesScene extends BaseScene implements
TapTarget.forBounds(bounds,
getString(R.string.guide_collections_title),
getString(R.string.guide_collections_text))
.outerCircleColor(R.color.colorPrimary)
.transparentTarget(true),
new TapTargetView.Listener() {
@Override
@@ -69,7 +69,6 @@ import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter;
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange;
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager;
import com.h6ah4i.android.widget.advrecyclerview.utils.AbstractDraggableItemViewHolder;
import com.hippo.app.CheckBoxDialogBuilder;
import com.hippo.app.EditTextDialogBuilder;
import com.hippo.drawable.AddDeleteDrawable;
import com.hippo.drawable.DrawerArrowDrawable;
@@ -97,6 +96,7 @@ import com.hippo.ehviewer.dao.DownloadLabel;
import com.hippo.ehviewer.dao.QuickSearch;
import com.hippo.ehviewer.download.DownloadManager;
import com.hippo.ehviewer.ui.CommonOperations;
import com.hippo.ehviewer.ui.EhActivity;
import com.hippo.ehviewer.ui.GalleryActivity;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.ehviewer.ui.dialog.SelectItemWithIconAdapter;
@@ -614,7 +614,13 @@ public final class GalleryListScene extends BaseScene
mFabLayout.setOnExpandListener(this);
addAboveSnackView(mFabLayout);
mActionFabDrawable = new AddDeleteDrawable(context, resources.getColor(R.color.primary_drawable_dark));
int colorID;
if (EhActivity.isNightMode(context.getResources().getConfiguration())) {
colorID = resources.getColor(android.R.color.white, getTheme());
} else {
colorID = resources.getColor(android.R.color.black, getTheme());
}
mActionFabDrawable = new AddDeleteDrawable(context, colorID);
mFabLayout.getPrimaryFab().setImageDrawable(mActionFabDrawable);
mSearchFab.setOnClickListener(this);
@@ -658,7 +664,6 @@ public final class GalleryListScene extends BaseScene
TapTarget.forBounds(bounds,
getString(R.string.guide_quick_search_title),
getString(R.string.guide_quick_search_text))
.outerCircleColor(R.color.colorPrimary)
.transparentTarget(true),
new TapTargetView.Listener() {
@Override
@@ -1,193 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.ui.scene;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.biometric.BiometricManager;
import androidx.biometric.BiometricPrompt;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.Settings;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.widget.lockpattern.LockPatternUtils;
import com.hippo.widget.lockpattern.LockPatternView;
import com.hippo.yorozuya.ObjectUtils;
import com.hippo.yorozuya.ViewUtils;
import java.util.List;
import java.util.concurrent.Executors;
public class SecurityScene extends SolidScene implements
LockPatternView.OnPatternListener {
private static final int MAX_RETRY_TIMES = 5;
private static final String KEY_RETRY_TIMES = "retry_times";
@Nullable
private LockPatternView mPatternView;
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private BiometricPrompt.PromptInfo promptInfo;
private BiometricPrompt biometricPrompt;
private boolean canAuthenticate = false;
private int mRetryTimes;
@Override
public boolean needShowLeftDrawer() {
return false;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Context context = requireContext();
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
if (null != mSensorManager) {
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
if (null == savedInstanceState) {
mRetryTimes = MAX_RETRY_TIMES;
} else {
mRetryTimes = savedInstanceState.getInt(KEY_RETRY_TIMES);
}
canAuthenticate = Settings.getEnableFingerprint() &&
BiometricManager.from(requireContext()).canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS;
biometricPrompt = new BiometricPrompt(this, Executors.newSingleThreadExecutor(), new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
}
@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
startSceneForCheckStep(CHECK_STEP_SECURITY, getArguments());
finish();
}
@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
}
});
promptInfo = new BiometricPrompt.PromptInfo.Builder()
.setTitle(getString(R.string.app_name))
.setNegativeButtonText(getString(android.R.string.cancel))
.setConfirmationRequired(false)
.build();
}
@Override
public void onDestroy() {
super.onDestroy();
mSensorManager = null;
mAccelerometer = null;
}
@Override
public void onResume() {
super.onResume();
if (canAuthenticate) {
startBiometricPrompt();
}
}
private void startBiometricPrompt() {
biometricPrompt.authenticate(promptInfo);
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(KEY_RETRY_TIMES, mRetryTimes);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.scene_security, container, false);
if (canAuthenticate) {
view.setOnClickListener(v -> startBiometricPrompt());
}
mPatternView = (LockPatternView) ViewUtils.$$(view, R.id.pattern_view);
mPatternView.setOnPatternListener(this);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
mPatternView = null;
}
@Override
public void onPatternStart() {
}
@Override
public void onPatternCleared() {
}
@Override
public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {
}
@Override
public void onPatternDetected(List<LockPatternView.Cell> pattern) {
MainActivity activity = getMainActivity();
if (null == activity || null == mPatternView) {
return;
}
String enteredPatter = LockPatternUtils.patternToString(pattern);
String targetPatter = Settings.getSecurity();
if (ObjectUtils.equal(enteredPatter, targetPatter)) {
startSceneForCheckStep(CHECK_STEP_SECURITY, getArguments());
finish();
} else {
mPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
mRetryTimes--;
if (mRetryTimes <= 0) {
finish();
}
}
}
}
@@ -0,0 +1,73 @@
/*
* Copyright 2022 tarsin norbin
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.ui.scene
import android.content.Context
import android.os.Bundle
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL
import androidx.biometric.BiometricPrompt
import androidx.biometric.auth.AuthPromptCallback
import androidx.biometric.auth.startClass2BiometricOrCredentialAuthentication
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import com.hippo.ehviewer.R
class SecurityScene : SolidScene() {
override fun needShowLeftDrawer(): Boolean {
return false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (isAuthenticationSupported(requireContext()))
startAuthentication(getString(R.string.settings_privacy_require_unlock))
else
startSceneForCheckStep(CHECK_STEP_SECURITY, arguments)
}
private fun startAuthentication(
title: String,
subtitle: String? = null,
confirmationRequired: Boolean = true,
) {
startClass2BiometricOrCredentialAuthentication(
title = title,
subtitle = subtitle,
confirmationRequired = confirmationRequired,
executor = ContextCompat.getMainExecutor(requireContext()),
callback = AuthenticationCallback()
)
}
inner class AuthenticationCallback : AuthPromptCallback() {
override fun onAuthenticationSucceeded(
activity: FragmentActivity?,
result: BiometricPrompt.AuthenticationResult
) {
super.onAuthenticationSucceeded(activity, result)
startSceneForCheckStep(CHECK_STEP_SECURITY, arguments)
}
}
companion object {
fun isAuthenticationSupported(context: Context): Boolean {
val authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK or DEVICE_CREDENTIAL
return BiometricManager.from(context)
.canAuthenticate(authenticators) == BiometricManager.BIOMETRIC_SUCCESS
}
}
}
@@ -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);
((View)mPreview.getParent()).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);
((View)mPreview.getParent()).setVisibility(VISIBLE);
((View) mPreview.getParent()).setVisibility(VISIBLE);
} catch (FileNotFoundException e) {
// Ignore
} finally {
@@ -32,7 +32,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.switchmaterial.SwitchMaterial
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
import com.hippo.easyrecyclerview.EasyRecyclerView
@@ -59,7 +58,7 @@ class SearchLayout @JvmOverloads constructor(
private var mNormalView: View
private var mNormalSearchMode: RadioGridGroup
private var mNormalSearchModeHelp: ImageView
private var mEnableAdvanceSwitch: SwitchMaterial
private var mEnableAdvanceSwitch: CheckBox
private var mAdvanceView: View
private var mTableAdvanceSearch: AdvanceSearchTable
private var mImageView: ImageSearchLayout
@@ -99,6 +98,11 @@ class SearchLayout @JvmOverloads constructor(
mChip.setText(mPair.second)
mChip.idt = mPair.first
mChip.isChecked = NumberUtils.int2boolean(mPair.first and mCategoryStored)
mChip.setOnLongClickListener {
mCategoryGroup.clearCheck()
mChip.isChecked = true
true
}
mCategoryGroup.addView(mChip)
}
mCategoryGroup.setOnCheckedStateChangeListener { _, checkedIds ->
@@ -113,8 +117,6 @@ class SearchLayout @JvmOverloads constructor(
mEnableAdvanceSwitch = mNormalView.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)
@@ -42,7 +42,16 @@ public class BatteryView extends AppCompatTextView {
private BatteryDrawable mDrawable;
private boolean mAttached = false;
private boolean mIsChargerWorking = false; private final Runnable mCharger = new Runnable() {
private boolean mIsChargerWorking = false;
public BatteryView(Context context) {
super(context);
init();
}
public BatteryView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} private final Runnable mCharger = new Runnable() {
private int level = 0;
@@ -56,14 +65,6 @@ public class BatteryView extends AppCompatTextView {
getHandler().postDelayed(mCharger, 200);
}
};
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);
@@ -85,36 +86,7 @@ public class BatteryView extends AppCompatTextView {
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
@SuppressLint("SetTextI18n")
public void onReceive(Context context, Intent intent) {
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
* 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
boolean charging = (intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
== BatteryManager.BATTERY_STATUS_CHARGING);
if (mLevel != level || mCharging != charging) {
mLevel = level;
mCharging = charging;
if (mCharging && mLevel != 100) {
startCharger();
} else {
stopCharger();
mDrawable.setElect(mLevel);
}
if (level <= BatteryDrawable.WARN_LIMIT && !charging) {
setTextColor(mWarningColor);
} else {
setTextColor(mColor);
}
setText(mLevel + "%");
}
}
};
}
@Override
public void setTextColor(int color) {
@@ -148,7 +120,36 @@ public class BatteryView extends AppCompatTextView {
registerReceiver();
}
}
} private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
@SuppressLint("SetTextI18n")
public void onReceive(Context context, Intent intent) {
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
* 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
boolean charging = (intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
== BatteryManager.BATTERY_STATUS_CHARGING);
if (mLevel != level || mCharging != charging) {
mLevel = level;
mCharging = charging;
if (mCharging && mLevel != 100) {
startCharger();
} else {
stopCharger();
mDrawable.setElect(mLevel);
}
if (level <= BatteryDrawable.WARN_LIMIT && !charging) {
setTextColor(mWarningColor);
} else {
setTextColor(mColor);
}
setText(mLevel + "%");
}
}
};
@Override
protected void onDetachedFromWindow() {
@@ -65,7 +65,15 @@ public class TextClock extends AppCompatTextView {
}
onTimeChanged();
}
}; private final Runnable mTicker = new Runnable() {
};
public TextClock(Context context) {
this(context, null);
}
public TextClock(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} private final Runnable mTicker = new Runnable() {
@Override
public void run() {
onTimeChanged();
@@ -76,24 +84,6 @@ public class TextClock extends AppCompatTextView {
getHandler().postAtTime(mTicker, next);
}
};
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();
onTimeChanged();
}
@Override
public void onChange(boolean selfChange, Uri uri) {
chooseFormat();
onTimeChanged();
}
};
public TextClock(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
@@ -121,7 +111,19 @@ public class TextClock extends AppCompatTextView {
public CharSequence getFormat12Hour() {
return mFormat12;
}
} private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
chooseFormat();
onTimeChanged();
}
@Override
public void onChange(boolean selfChange, Uri uri) {
chooseFormat();
onTimeChanged();
}
};
public void setFormat12Hour(CharSequence format) {
mFormat12 = format;
@@ -1,63 +0,0 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.widget.lockpattern;
import java.util.ArrayList;
import java.util.List;
/**
* Utilities for the lock pattern and its settings.
*/
public class LockPatternUtils {
/**
* Deserialize a pattern.
*
* @param string The pattern serialized with {@link #patternToString}
* @return The pattern.
*/
public static List<LockPatternView.Cell> stringToPattern(String string) {
List<LockPatternView.Cell> result = new ArrayList<>();
final byte[] bytes = string.getBytes();
for (byte b : bytes) {
result.add(LockPatternView.Cell.of(b / 3, b % 3));
}
return result;
}
/**
* Serialize a pattern.
*
* @param pattern The pattern.
* @return The pattern in string form.
*/
public static String patternToString(List<LockPatternView.Cell> pattern) {
if (pattern == null) {
return "";
}
final int patternSize = pattern.size();
byte[] res = new byte[patternSize];
for (int i = 0; i < patternSize; i++) {
LockPatternView.Cell cell = pattern.get(i);
res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
}
return new String(res);
}
}
File diff suppressed because it is too large. Load diff
@@ -6,10 +6,10 @@
android:viewportHeight="48">
<path
android:fillAlpha="1"
android:fillColor="@color/shortcut_bg"
android:fillColor="@android:color/white"
android:pathData="M46,24A22,22 0,0 1,24 46,22 22,0 0,1 2,24 22,22 0,0 1,24 2,22 22,0 0,1 46,24Z" />
<path
android:fillAlpha="1"
android:fillColor="@color/colorPrimary"
android:fillColor="@android:color/black"
android:pathData="M20,17V31L31,24Z" />
</vector>
@@ -6,10 +6,10 @@
android:viewportHeight="48">
<path
android:fillAlpha="1"
android:fillColor="@color/shortcut_bg"
android:fillColor="@android:color/white"
android:pathData="M46,24A22,22 0,0 1,24 46,22 22,0 0,1 2,24 22,22 0,0 1,24 2,22 22,0 0,1 46,24Z" />
<path
android:fillAlpha="1"
android:fillColor="@color/colorPrimary"
android:fillColor="@android:color/black"
android:pathData="m18,31h4L22,17h-4zM26,17v14h4L30,17Z" />
</vector>
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<color android:color="@android:color/system_neutral1_50" />
</item>
<item android:drawable="?android:attr/selectableItemBackground" />
</layer-list>
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<selector
android:enterFadeDuration="@android:integer/config_shortAnimTime"
android:exitFadeDuration="@android:integer/config_shortAnimTime">
<item android:state_checked="true">
<color android:color="@color/check_text_view_mask" />
</item>
</selector>
</item>
<item android:drawable="?android:attr/selectableItemBackground" />
</layer-list>
@@ -1,47 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2016 Hippo Seven
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/teal_500"
android:pathData="M0,12a12,12 0 1,0 24,0a12,12 0 1,0 -24,0" />
<path
android:fillColor="@android:color/black"
android:pathData="M16.5,9.9L16.1,9.6L19.1,5.9C19.2,5.8,19.4,5.8,19.5,5.9L19.5,5.9C19.6,6,19.6,6.2,19.5,6.3L16.5,9.9Z" />
<path
android:fillColor="@android:color/black"
android:pathData="M9.1,8.8L8.6,9.1L6.2,5C6.1,4.9,6.2,4.7,6.3,4.6L6.3,4.6C6.4,4.5,6.6,4.6,6.7,4.7L9.1,8.8Z" />
<path
android:fillColor="@android:color/white"
android:pathData="M1.8,14.6L22.1,16.4C21.4,11.3,17.6,7.9,12.6,7.5C7.8,7,3.4,9.7,1.8,14.6Z" />
<path
android:fillColor="@android:color/black"
android:pathData="M15.4,11.9a1.1,1.1 0 1,0 2.2,0a1.1,1.1 0 1,0 -2.2,0" />
<path
android:fillColor="@android:color/black"
android:pathData="M7.1,11.2a1.1,1.1 0 1,0 2.2,0a1.1,1.1 0 1,0 -2.2,0" />
</vector>
@@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M12,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9s9,-4.03 9,-9c0,-0.46 -0.04,-0.92 -0.1,-1.36c-0.98,1.37 -2.58,2.26 -4.4,2.26c-2.98,0 -5.4,-2.42 -5.4,-5.4c0,-1.81 0.89,-3.42 2.26,-4.4C12.92,3.04 12.46,3 12,3L12,3z" />
</vector>
+1 -1
View File
@@ -5,6 +5,6 @@
android:viewportHeight="108">
<path
android:fillAlpha="1"
android:fillColor="@color/colorPrimary"
android:fillColor="@android:color/white"
android:pathData="m42,68h8V40H42ZM58,40v28h8V40Z" />
</vector>
@@ -5,6 +5,6 @@
android:viewportHeight="108">
<path
android:fillAlpha="1"
android:fillColor="@color/colorPrimary"
android:fillColor="@android:color/white"
android:pathData="M46,40V68L68,54Z" />
</vector>
@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2016 Hippo Seven
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="true"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/keyline_margin"
app:fitsSystemWindowsInsets="bottom">
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
android:gravity="center"
android:padding="@dimen/keyline_margin"
android:text="@string/set_pattern_protection_tip"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<androidx.appcompat.widget.AppCompatCheckBox
android:id="@+id/fingerprint_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="20dp"
android:text="@string/enable_biometric"
android:visibility="gone" />
<LinearLayout
android:id="@+id/buttonPanel"
style="?attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingLeft="12dp"
android:paddingTop="4dp"
android:paddingRight="12dp"
android:paddingBottom="4dp">
<Button
android:id="@+id/set"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/set" />
<Button
android:id="@+id/cancel"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@android:string/cancel" />
</LinearLayout>
</FrameLayout>
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<com.hippo.widget.lockpattern.LockPatternView
android:id="@+id/pattern_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
</LinearLayout>
@@ -11,13 +11,12 @@
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="4dp"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
android:layout_height="wrap_content" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
@@ -1,95 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2016 Hippo Seven
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingHorizontal="@dimen/keyline_margin"
app:fitsSystemWindowsInsets="bottom">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="@dimen/keyline_margin"
android:text="@string/set_pattern_protection_tip"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<com.hippo.widget.MaxSizeContainer xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="32dp"
app:maxHeight="320dp"
app:maxWidth="320dp">
<com.hippo.widget.lockpattern.LockPatternView
android:id="@+id/pattern_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</com.hippo.widget.MaxSizeContainer>
</FrameLayout>
<androidx.appcompat.widget.AppCompatCheckBox
android:id="@+id/fingerprint_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="20dp"
android:text="@string/enable_biometric"
android:visibility="gone" />
<LinearLayout
android:id="@+id/buttonPanel"
style="?attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:gravity="bottom"
android:orientation="horizontal"
android:paddingLeft="12dp"
android:paddingTop="4dp"
android:paddingRight="12dp"
android:paddingBottom="20dp">
<Button
android:id="@+id/cancel"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="4dp"
android:layout_weight="1"
android:text="@android:string/cancel" />
<Button
android:id="@+id/set"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="4dp"
android:layout_weight="1"
android:text="@string/set" />
</LinearLayout>
</LinearLayout>
+24 -37
View File
@@ -14,7 +14,7 @@
~ limitations under the License.
-->
<rikka.widget.borderview.BorderNestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -37,8 +37,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:text="@string/settings_read_screen_rotation"
android:textColor="?android:attr/textColorPrimary" />
android:text="@string/settings_read_screen_rotation" />
<com.hippo.widget.CuteSpinner
android:id="@+id/screen_rotation"
@@ -60,8 +59,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:text="@string/settings_read_reading_direction"
android:textColor="?android:attr/textColorPrimary" />
android:text="@string/settings_read_reading_direction" />
<com.hippo.widget.CuteSpinner
android:id="@+id/reading_direction"
@@ -83,8 +81,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:text="@string/settings_read_page_scaling"
android:textColor="?android:attr/textColorPrimary" />
android:text="@string/settings_read_page_scaling" />
<com.hippo.widget.CuteSpinner
android:id="@+id/page_scaling"
@@ -106,8 +103,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:text="@string/settings_read_start_position"
android:textColor="?android:attr/textColorPrimary" />
android:text="@string/settings_read_start_position" />
<com.hippo.widget.CuteSpinner
android:id="@+id/start_position"
@@ -129,8 +125,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:text="@string/read_theme"
android:textColor="?android:attr/textColorPrimary" />
android:text="@string/read_theme" />
<com.hippo.widget.CuteSpinner
android:id="@+id/read_theme"
@@ -142,68 +137,60 @@
</LinearLayout>
<Switch
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/keep_screen_on"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_read_keep_screen_on"
android:textColor="?android:attr/textColorPrimary" />
android:text="@string/settings_read_keep_screen_on" />
<Switch
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/show_clock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_read_show_clock"
android:textColor="?android:attr/textColorPrimary" />
android:text="@string/settings_read_show_clock" />
<Switch
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/show_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_read_show_progress"
android:textColor="?android:attr/textColorPrimary" />
android:text="@string/settings_read_show_progress" />
<Switch
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/show_battery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_read_show_battery"
android:textColor="?android:attr/textColorPrimary" />
android:text="@string/settings_read_show_battery" />
<Switch
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/show_page_interval"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_read_show_page_interval"
android:textColor="?android:attr/textColorPrimary" />
android:text="@string/settings_read_show_page_interval" />
<Switch
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/volume_page"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_read_volume_page"
android:textColor="?android:attr/textColorPrimary" />
<Switch
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/reverse_volume_page"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_read_reverse_volume"
android:textColor="?android:attr/textColorPrimary" />
android:text="@string/settings_read_reverse_volume" />
<Switch
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/reading_fullscreen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_read_reading_fullscreen"
android:textColor="?android:attr/textColorPrimary" />
android:text="@string/settings_read_reading_fullscreen" />
<Switch
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/custom_screen_lightness"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_read_custom_screen_lightness"
android:textColor="?android:attr/textColorPrimary" />
android:text="@string/settings_read_custom_screen_lightness" />
<SeekBar
android:id="@+id/screen_lightness"
@@ -212,4 +199,4 @@
android:max="200" />
</LinearLayout>
</rikka.widget.borderview.BorderNestedScrollView>
</androidx.core.widget.NestedScrollView>
@@ -105,52 +105,41 @@
android:paddingTop="16dp"
android:paddingRight="12dp"
android:paddingBottom="16dp"
app:srcCompat="@drawable/v_dots_vertical_secondary_dark_x24"
app:tint="@color/primary_drawable_black" />
app:srcCompat="@drawable/v_dots_vertical_secondary_dark_x24" />
</RelativeLayout>
<com.google.android.material.card.MaterialCardView
<LinearLayout
android:id="@+id/action_card"
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/keyline_margin"
android:layout_marginRight="@dimen/keyline_margin"
app:cardUseCompatPadding="true">
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
<Button
android:id="@+id/download"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:layout_weight="1"
android:clickable="true"
android:focusable="true" />
<TextView
android:id="@+id/download"
style="@style/ButtonInCard"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
android:focusable="true" />
<android.widget.Space
android:layout_width="8dp"
android:layout_height="wrap_content" />
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="?attr/dividerColor" />
<Button
android:id="@+id/read"
style="@style/Widget.Material3.Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:text="@string/read" />
<TextView
android:id="@+id/read"
style="@style/ButtonInCard"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:text="@string/read" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</LinearLayout>
</FrameLayout>
@@ -19,8 +19,7 @@
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:background="?selectableItemBackground"
android:layout_margin="4dp"
android:checkable="true"
android:clickable="true"
android:focusable="true">
@@ -61,7 +60,7 @@
style="@style/CardMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:layout_above="@id/rating"
android:layout_alignStart="@id/title"
android:layout_marginTop="2dp" />
@@ -86,7 +85,7 @@
android:layout_height="wrap_content"
android:layout_above="@id/category"
android:layout_alignStart="@id/title"
android:layout_marginBottom="4dp" />
android:layout_marginBottom="2dp" />
<TextView
android:id="@+id/posted"
@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2016 Hippo Seven
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:fitsSystemWindowsInsets="top|bottom">
<com.hippo.widget.MaxSizeContainer xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="32dp"
app:maxHeight="360dp"
app:maxWidth="320dp">
<com.hippo.widget.lockpattern.LockPatternView
android:id="@+id/pattern_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</com.hippo.widget.MaxSizeContainer>
</FrameLayout>
+2 -2
View File
@@ -24,7 +24,7 @@
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"
@@ -89,7 +89,7 @@
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.google.android.material.switchmaterial.SwitchMaterial
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/search_enable_advance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -20,7 +20,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:visibility="gone" >
android:visibility="gone">
<com.hippo.widget.FixedAspectImageView
+4 -4
View File
@@ -20,13 +20,13 @@
android:id="@+id/action_add"
android:icon="@drawable/v_plus_dark_x24"
android:title="@string/settings"
android:showAsAction="always" />
android:showAsAction="always"
android:title="@string/settings" />
<item
android:id="@+id/action_default_download_label"
android:icon="@drawable/v_download_box_dark_x24"
android:title="@string/default_download_label"
android:showAsAction="ifRoom" />
android:showAsAction="ifRoom"
android:title="@string/default_download_label" />
</menu>
@@ -19,13 +19,13 @@
<item
android:id="@+id/action_help"
android:icon="@drawable/v_help_circle_x24"
android:title="@string/add"
android:showAsAction="ifRoom" />
android:showAsAction="ifRoom"
android:title="@string/add" />
<item
android:id="@+id/action_add"
android:icon="@drawable/v_plus_dark_x24"
android:title="@string/add"
android:showAsAction="always" />
android:showAsAction="always"
android:title="@string/add" />
</menu>
-10
View File
@@ -15,18 +15,8 @@
-->
<resources>
<color name="primary_drawable">#ffffffff</color>
<!-- divider -->
<color name="divider">#20ffffff</color>
<!-- shadow -->
<!-- Gallery Activity -->
<!-- Lock pattern view -->
<color name="lock_pattern_view_regular_color">#8affffff</color>
<!--Shortcut background-->
</resources>
-1
View File
@@ -519,7 +519,6 @@
<string name="settings_about_declaration" translatable="false">EhViewer</string>
<string name="settings_about_declaration_summary">EhViewer ไม่มีความแตกต่างจากตัวเว็บ E-Hentai.org แต่อย่างใด</string>
<string name="settings_about_author">นักพัฒนา</string>
<string name="settings_about_author_summary" translatable="false">Hippo &lt;ehviewersu$gmail.com&gt;</string>
<string name="settings_about_telegram">Telegram</string>
<string name="settings_about_website">เว็บไซต์</string>
<string name="settings_about_source">ซอร์สโค้ด</string>
@@ -759,4 +759,7 @@
<string name="app_link_not_verified_message">对于 Android 12 及更新的版本,您需要手动添加链接到已验证链接才能在 EhViewer 中打开 E-Hentai 链接。</string>
<string name="app_link_not_verified_title">应用链接未验证</string>
<string name="open_by_default">默认打开</string>
<string name="show_library_version">依赖库之版本</string>
<string name="settings_privacy_require_unlock">需要解锁</string>
</resources>
-18
View File
@@ -15,12 +15,9 @@
-->
<resources>
<color name="primary_drawable">#8a000000</color>
<color name="primary_drawable_dark">#ffffffff</color>
<color name="primary_drawable_black">#ccffffff</color>
<color name="secondary_drawable_black">#3dffffff</color>
<color name="red_500">#fff44336</color>
<color name="teal_500">#ff009688</color>
<color name="purple_a700">#ffaa00ff</color>
<color name="cyan_600">#ff00acc1</color>
<color name="light_green_600">#ff7cb342</color>
@@ -28,7 +25,6 @@
<color name="deep_orange_400">#ffff7043</color>
<color name="grey_500">#ff9e9e9e</color>
<color name="brown_500">#ff795548</color>
<color name="colorPrimary">@color/teal_500</color>
<color name="loading_indicator_red">#ffe53935</color>
<color name="loading_indicator_purple">@color/purple_a700</color>
<color name="loading_indicator_blue">#ff1d87e4</color>
@@ -36,28 +32,17 @@
<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 -->
<color name="doujinshi">#fff44336</color>
<!-- Orange -->
<color name="manga">#ffff9800</color>
<!-- Yellow 700 -->
<color name="artist_cg">#ffFbc02d</color>
<!-- Green -->
<color name="game_cg">#ff4caf50</color>
<!-- Light Green -->
<color name="western">#ff8bc34a</color>
<!-- Blue -->
<color name="non_h">#ff2196f3</color>
<!-- Indigo -->
<color name="image_set">#ff3f51b5</color>
<!-- Purple -->
<color name="cosplay">#ff9c27b0</color>
<!-- Deep Purple 300 -->
<color name="asian_porn">#ff9575cd</color>
<!-- Pink 300 -->
<color name="misc">#fff06292</color>
<!-- divider -->
<color name="divider">#20000000</color>
@@ -68,9 +53,6 @@
<!-- Gallery Activity -->
<!-- Lock pattern view -->
<color name="lock_pattern_view_regular_color">#8a000000</color>
<color name="lock_pattern_view_success_color">@color/colorPrimary</color>
<color name="lock_pattern_view_error_color">@color/red_500</color>
<!--Shortcut background-->
<color name="shortcut_bg">#F5F5F5</color>
-6
View File
@@ -82,8 +82,6 @@
<dimen name="add_thickness">2dp</dimen>
<!-- CategoryTable -->
<dimen name="category_table_item_height">40dp</dimen>
<dimen name="category_table_item_margin">4dp</dimen>
<!-- AdvanceSearchTable -->
<dimen name="advance_search_table_item_margin">4dp</dimen>
@@ -97,7 +95,6 @@
<dimen name="image_search_max_size">240dp</dimen>
<!-- Switch padding -->
<dimen name="switch_padding">8dp</dimen>
<!-- FabLayout -->
<dimen name="fab_layout_primary_margin">24dp</dimen>
@@ -120,9 +117,6 @@
<dimen name="gallery_guide_divider_width">3dp</dimen>
<!-- Lock pattern view -->
<dimen name="lock_pattern_dot_line_width">3dp</dimen>
<dimen name="lock_pattern_dot_size">12dp</dimen>
<dimen name="lock_pattern_dot_size_activated">28dp</dimen>
<!-- Custom preference -->
-1
View File
@@ -17,6 +17,5 @@
<drawable name="transparent">@android:color/transparent</drawable>
<drawable name="tile_background_activated">#7f9c27b0</drawable>
<drawable name="sadpanda_low_poly">@color/colorPrimary</drawable>
</resources>
+4 -1
View File
@@ -620,7 +620,7 @@
<string name="settings_about_declaration" translatable="false">EhViewer</string>
<string name="settings_about_declaration_summary">EhViewer is not affiliated with E-Hentai.org in any way</string>
<string name="settings_about_author">Author</string>
<string name="settings_about_author_summary" translatable="false">&lt;del&gt;Hippo &amp;lt;ehviewersu$gmail.com&amp;gt;&lt;/del&gt;&lt;br&gt;NekoInverter &amp;lt;nekoworkshop$protonmail.com&amp;gt;</string>
<string name="settings_about_author_summary" translatable="false">&lt;del&gt;Hippo &amp;lt;ehviewersu$gmail.com&amp;gt;&lt;/del&gt;&lt;br&gt;NekoInverter &amp;lt;nekoworkshop$protonmail.com&amp;gt; &lt;br&gt;飛鳥澪</string>
<string name="settings_about_telegram">Telegram</string>
<string name="settings_about_latest_release">Latest release</string>
<string name="settings_about_website">Website</string>
@@ -823,4 +823,7 @@
<string name="app_link_not_verified_message">For Android 12 and newer, you need to manually add link to verified links in order to open E-Hentai links in EhViewer.</string>
<string name="app_link_not_verified_title">App links not verified</string>
<string name="open_by_default">Open by default</string>
<string name="show_library_version">Library Version</string>
<string name="settings_privacy_require_unlock">Require Unlock</string>
</resources>
+2 -31
View File
@@ -19,7 +19,6 @@
<style name="AppTheme" parent="Base.AppTheme" />
<!-- TextAppearance -->
<style name="TextAppearance" parent="TextAppearance.Material3.TitleMedium" />
<!-- Progress View -->
<style name="ProgressView">
@@ -28,38 +27,19 @@
<item name="android:minHeight">48dp</item>
</style>
<style name="TextAppearance.CardTitle">
<item name="android:textSize">@dimen/text_little_small</item>
</style>
<style name="CardTitle">
<item name="android:textAppearance">@style/TextAppearance.CardTitle</item>
<item name="android:textAppearance">@style/TextAppearance.Material3.TitleSmall</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">2</item>
<item name="android:lineSpacingExtra">0sp</item>
</style>
<style name="TextAppearance.CardMessage">
<item name="android:textSize">@dimen/text_small</item>
</style>
<style name="CardMessage">
<item name="android:textAppearance">@style/TextAppearance.CardMessage</item>
<item name="android:textAppearance">@style/TextAppearance.Material3.BodyMedium</item>
<item name="android:ellipsize">end</item>
<item name="android:singleLine">true</item>
<item name="android:maxLines">1</item>
</style>
<!-- CategoryText -->
<style name="CategoryText">
<item name="android:textAppearance">@style/TextAppearance.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>
</style>
<style name="TextAppearance.CategoryTitle" parent="TextAppearance.Material3.TitleMedium">
<item name="android:textStyle">bold</item>
</style>
@@ -71,15 +51,6 @@
<item name="android:gravity">center_vertical</item>
</style>
<style name="ButtonInCard">
<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>
</style>
<style name="Slider">
<item name="thickness">2dp</item>
<item name="radius">6dp</item>
-3
View File
@@ -21,10 +21,8 @@
<!-- ========== -->
<style name="Base.AppTheme" parent="Theme.Material3.DynamicColors.DayNight">
<item name="colorControlActivated">@color/colorPrimary</item>
<item name="colorEdgeEffect">@color/grey_500</item>
<item name="dividerColor">@color/divider</item>
<item name="colorControlNormal">@color/primary_drawable</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>
@@ -45,7 +43,6 @@
<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="guideBackgroundColor">#e5000000</item>
+2 -2
View File
@@ -11,7 +11,7 @@
<intent
android:action="start_all"
android:targetClass="com.hippo.ehviewer.shortcuts.ShortcutsActivity"
android:targetPackage="io.github.nekoinverter.ehviewer" />
android:targetPackage="moe.tarsin.ehviewer" />
<categories android:name="android.shortcut.conversation" />
</shortcut>
@@ -25,7 +25,7 @@
<intent
android:action="stop_all"
android:targetClass="com.hippo.ehviewer.shortcuts.ShortcutsActivity"
android:targetPackage="io.github.nekoinverter.ehviewer" />
android:targetPackage="moe.tarsin.ehviewer" />
<categories android:name="android.shortcut.conversation" />
</shortcut>
+4 -4
View File
@@ -2,10 +2,10 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Preference
android:fragment="com.hippo.ehviewer.ui.fragment.SetSecurityFragment"
android:key="pattern_protection"
android:title="@string/settings_privacy_pattern_protection_title"
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="require_unlock"
android:title="@string/settings_privacy_require_unlock"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
Binary file not shown.

Before

Width:  |  Height:  |  Size: 735 KiB

After

Width:  |  Height:  |  Size: 1003 KiB

+7 -1
View File
@@ -12,8 +12,14 @@ android {
targetSdkVersion 32
consumerProguardFiles 'proguard-rules.pro'
externalNativeBuild {
cmake {
arguments '-DANDROID_STL=none'
}
}
ndk {
abiFilters 'arm64-v8a', 'x86_64'
abiFilters 'arm64-v8a', 'x86_64', 'armeabi-v7a', 'x86'
}
}
+1 -1
View File
@@ -1,2 +1,2 @@
-keep class com.hippo.a7zip.* { *; }
-keep class com.hippo.* { *; }
-keep class com.hippo.image.* { *; }
@@ -5,4 +5,14 @@ public class Native {
public static void initialize() {
System.loadLibrary("ehviewer");
}
public static native String getlibarchiveVersion();
public static native String getliblzmaVersion();
public static native String getlibzstdVersion();
public static native String getlibjpeg_turboVersion();
public static native String getzlibVersion();
}
@@ -31,6 +31,7 @@ public class UriArchiveAccessor implements Closeable {
}
private native int openArchive(OsReadableFile osf);
private native int extracttoOutputStream(OsReadableFile osf, int index, OutputStream os);
@Override
@@ -59,14 +60,39 @@ public class UriArchiveAccessor implements Closeable {
return Os.fstat(fd).st_size;
}
public void seek(long pos) throws IOException, ErrnoException {
Os.lseek(fd, pos, OsConstants.SEEK_SET);
public long seek(long pos, int whence) throws IOException, ErrnoException {
try {
return Os.lseek(fd, pos, whence);
} catch (Exception e) {
e.printStackTrace();
return -30;
}
}
public void rewind() throws IOException, ErrnoException {
Os.lseek(fd, 0, OsConstants.SEEK_SET);
}
public long skip(long n) throws IOException, ErrnoException {
long pos;
long len;
long newpos;
if (n <= 0) {
return 0;
}
pos = Os.lseek(fd, 0L, OsConstants.SEEK_CUR);
len = length();
newpos = pos + n;
if (newpos > len) {
newpos = len;
}
seek(newpos, OsConstants.SEEK_SET);
/* return the actual number of bytes skipped */
return newpos - pos;
}
public void close() throws IOException {
pfd.close();
try {
+78 -80
View File
@@ -55,12 +55,10 @@ public final class Image {
public static final int FORMAT_GIF = 3;
private static final AtomicInteger sImageCount = new AtomicInteger();
private long mNativePtr;
private final int mFormat;
private final int mWidth;
private final int mHeight;
private long mNativePtr;
private Throwable mRecycleTracker;
private Image(long nativePtr, int format, int width, int height) {
@@ -72,6 +70,83 @@ public final class Image {
sImageCount.getAndIncrement();
}
/**
* Decode image from {@code InputStream}
*/
@Nullable
public static Image decode(InputStream is, boolean partially) {
if (!(is instanceof BufferedInputStream)) {
is = new BufferedInputStream(is);
}
return nativeDecode(is, partially);
}
/**
* Create a plain image from Bitmap
*/
@Nullable
public static Image create(Bitmap bitmap) {
return nativeCreate(bitmap);
}
/**
* Return all un-recycled {@code Image} instance count.
* It is useful for debug.
*/
public static int getImageCount() {
return sImageCount.get();
}
/**
* Return all supported image formats, exclude {@link #FORMAT_PLAIN}
*/
public static int[] getSupportedImageFormats() {
return nativeGetSupportedImageFormats();
}
/**
* Return decoder description of the image format,
* {@code null} for invalid image format.
*/
public static String getDecoderDescription(int format) {
return nativeGetDecoderDescription(format);
}
private static native Image nativeDecode(InputStream is, boolean partially);
private static native Image nativeCreate(Bitmap bitmap);
private static native int nativeGetByteCount(long nativePtr, int format);
private static native boolean nativeComplete(long nativePtr, int format);
private static native boolean nativeIsCompleted(long nativePtr, int format);
private static native void nativeRender(long nativePtr, int format,
int srcX, int srcY, Bitmap dst, int dstX, int dstY,
int width, int height, boolean fillBlank, int defaultColor);
private static native void nativeTexImage(long nativePtr, int format,
boolean init, int offsetX, int offsetY, int width, int height);
private static native void nativeAdvance(long nativePtr, int format);
private static native int nativeGetDelay(long nativePtr, int format);
private static native int nativeFrameCount(long nativePtr, int format);
private static native boolean nativeIsOpaque(long nativePtr, int format);
private static native boolean nativeIsGray(long nativePtr, int format, int error);
private static native void nativeClahe(long nativePtr, int format, boolean toGray);
private static native void nativeRecycle(long nativePtr, int format);
private static native int[] nativeGetSupportedImageFormats();
private static native String nativeGetDecoderDescription(int format);
/**
* Return the format of the image
*/
@@ -218,81 +293,4 @@ public final class Image {
public boolean isRecycled() {
return mNativePtr == 0;
}
/**
* Decode image from {@code InputStream}
*/
@Nullable
public static Image decode(InputStream is, boolean partially) {
if (!(is instanceof BufferedInputStream)) {
is = new BufferedInputStream(is);
}
return nativeDecode(is, partially);
}
/**
* Create a plain image from Bitmap
*/
@Nullable
public static Image create(Bitmap bitmap) {
return nativeCreate(bitmap);
}
/**
* Return all un-recycled {@code Image} instance count.
* It is useful for debug.
*/
public static int getImageCount() {
return sImageCount.get();
}
/**
* Return all supported image formats, exclude {@link #FORMAT_PLAIN}
*/
public static int[] getSupportedImageFormats() {
return nativeGetSupportedImageFormats();
}
/**
* Return decoder description of the image format,
* {@code null} for invalid image format.
*/
public static String getDecoderDescription(int format) {
return nativeGetDecoderDescription(format);
}
private static native Image nativeDecode(InputStream is, boolean partially);
private static native Image nativeCreate(Bitmap bitmap);
private static native int nativeGetByteCount(long nativePtr, int format);
private static native boolean nativeComplete(long nativePtr, int format);
private static native boolean nativeIsCompleted(long nativePtr, int format);
private static native void nativeRender(long nativePtr, int format,
int srcX, int srcY, Bitmap dst, int dstX, int dstY,
int width, int height, boolean fillBlank, int defaultColor);
private static native void nativeTexImage(long nativePtr, int format,
boolean init, int offsetX, int offsetY, int width, int height);
private static native void nativeAdvance(long nativePtr, int format);
private static native int nativeGetDelay(long nativePtr, int format);
private static native int nativeFrameCount(long nativePtr, int format);
private static native boolean nativeIsOpaque(long nativePtr, int format);
private static native boolean nativeIsGray(long nativePtr, int format, int error);
private static native void nativeClahe(long nativePtr, int format, boolean toGray);
private static native void nativeRecycle(long nativePtr, int format);
private static native int[] nativeGetSupportedImageFormats();
private static native String nativeGetDecoderDescription(int format);
}
@@ -40,19 +40,18 @@ import java.util.Set;
public final class ImageBitmap implements Animatable, Runnable {
private static final Handler HANDLER = new Handler(Looper.getMainLooper());
@Nullable
private Image mImage;
@NonNull
private final Bitmap mBitmap;
private final int mFormat;
private final boolean mIsOpaque;
private final int mByteCount;
private final int mFrameCount;
private final Set<WeakReference<Callback>> mCallbackSet = new LinkedHashSet<>();
@Nullable
private Image mImage;
private int mReferences;
private int mAnimationReferences;
private boolean mRunning;
private final Set<WeakReference<Callback>> mCallbackSet = new LinkedHashSet<>();
private ImageBitmap(@NonNull Image image) throws OutOfMemoryError {
int width = image.getWidth();
+34 -3
View File
@@ -1,10 +1,41 @@
project(ehviewer)
cmake_minimum_required(VERSION 3.4.1)
# Build liblzma as shared lib
set(BUILD_SHARED_LIBS ON)
add_subdirectory(liblzma)
include_directories(liblzma/src/liblzma/api)
add_subdirectory(image)
# Build libzstd
add_subdirectory(libzstd/build/cmake)
# Configure libarchive for android platform
include_directories(libarchive/contrib/android/include)
# Configure lzma support for libarchive
include_directories(liblzma/src/liblzma/api)
SET(HAVE_LIBLZMA 1)
SET(HAVE_LZMA_H 1)
SET(HAVE_LZMA_STREAM_ENCODER_MT 1)
SET(HAVE_LZMADEC_H 1)
SET(HAVE_LIBLZMADEC 1)
# Configure zstd support for libarchive
include_directories(libzstd/lib)
SET(HAVE_LIBZSTD 1)
SET(HAVE_LIBZSTD_COMPRESSOR 1)
SET(HAVE_ZSTD_H 1)
# Build libarchive
add_subdirectory(libarchive)
# Build hippo's image lib
add_subdirectory(image)
# Build libfuse
add_subdirectory(libfuse)
include_directories(libfuse/libfuse/include)
# Build and link our app's native lib
add_library(${PROJECT_NAME} SHARED main.c archive.c)
target_include_directories(${PROJECT_NAME} PUBLIC image/image libarchive/libarchive)
target_link_libraries(${PROJECT_NAME} image archive)
target_link_libraries(${PROJECT_NAME} image archive fuse)
+35 -25
View File
@@ -30,26 +30,21 @@ typedef struct archive_inst_sc {
jmethodID readID;
jmethodID seekID;
jmethodID skipID;
void* read_buffer;
void* output_buffer;
void *read_buffer;
void *output_buffer;
jbyteArray jbr;
} archive_inst;
static int filename_is_playable_file(const char* name)
{
const char* dotptr = strrchr(name, '.');
static int filename_is_playable_file(const char *name) {
const char *dotptr = strrchr(name, '.');
if (dotptr++) {
switch (*dotptr) {
case 'b':
return strcmp(dotptr, "bmp") == 0;
case 'j':
return (strcmp(dotptr, "jpg") == 0) || (strcmp(dotptr, "jpeg") == 0);
case 'p':
return strcmp(dotptr, "png") == 0;
case 'g':
return strcmp(dotptr, "gif") == 0;
case 'w':
return strcmp(dotptr, "webp") == 0;
default:
return 0;
}
@@ -57,20 +52,19 @@ static int filename_is_playable_file(const char* name)
return 0;
}
static void archive_list_all_entries(struct archive_inst_sc *inst)
{
static void archive_list_all_entries(struct archive_inst_sc *inst) {
struct archive *a = inst->archive;
struct archive_entry *entry;
int count = 0;
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
if(filename_is_playable_file(archive_entry_pathname(entry)))
if (filename_is_playable_file(archive_entry_pathname(entry)))
count++;
archive_read_data_skip(a);
}
inst->entry_num = count;
}
ssize_t ins_read(struct archive *a, void* client_data_ptr, const void **buff)
{
ssize_t ins_read(struct archive *a, void *client_data_ptr, const void **buff) {
archive_inst *arc = client_data_ptr;
int32_t r = (*arc->env)->CallIntMethod(arc->env, arc->file, arc->readID, arc->jbr);
(*arc->env)->GetByteArrayRegion(arc->env, arc->jbr, 0, r, arc->read_buffer);
@@ -78,31 +72,46 @@ ssize_t ins_read(struct archive *a, void* client_data_ptr, const void **buff)
return r;
}
int ins_close(struct archive *a, void* client_data)
{
int ins_close(struct archive *a, void *client_data) {
archive_inst *arc = client_data;
JNIEnv *env = arc->env;
jmethodID rewind = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, arc->file), "rewind", "()V");
jmethodID rewind = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, arc->file), "rewind",
"()V");
(*arc->env)->CallVoidMethod(arc->env, arc->file, rewind);
return ARCHIVE_OK;
}
static archive_inst *archive_create_inst(JNIEnv *env, jobject file)
{
la_int64_t ins_seek(struct archive *a, void *client_data, la_int64_t offset, int whence) {
archive_inst *arc = client_data;
jlong ret = (*arc->env)->CallLongMethod(arc->env, arc->file, arc->seekID, offset, whence);
return ret;
}
la_int64_t ins_skip(struct archive *a, void *client_data, la_int64_t request) {
archive_inst *arc = client_data;
jlong ret = (*arc->env)->CallLongMethod(arc->env, arc->file, arc->skipID, request);
return ret;
}
static archive_inst *archive_create_inst(JNIEnv *env, jobject file) {
archive_inst *inst = malloc(sizeof(archive_inst));
inst->archive = archive_read_new();
archive_read_set_seek_callback(inst->archive, ins_seek);
archive_read_set_skip_callback(inst->archive, ins_skip);
archive_read_support_format_all(inst->archive);
archive_read_support_filter_all(inst->archive);
inst->env = env;
inst->file = file;
inst->readID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, file), "read", "([B)I");
inst->seekID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, file), "seek", "(JI)J");
inst->skipID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, file), "skip", "(J)J");
inst->jbr = (*env)->NewByteArray(env, BLOCK_SIZE);
inst->read_buffer = malloc(BLOCK_SIZE);
inst->output_buffer = malloc(BLOCK_SIZE);
return inst;
}
static void archive_destroy_inst(archive_inst* inst)
{
static void archive_destroy_inst(archive_inst *inst) {
JNIEnv *env = inst->env;
archive_read_close(inst->archive);
(*env)->DeleteLocalRef(env, inst->jbr);
@@ -117,7 +126,6 @@ Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *env, jobject thiz, jobject
archive_inst *arc = archive_create_inst(env, osf);
r = archive_read_open(arc->archive, arc, NULL, ins_read, ins_close);
if (r) {
LOGI("%s%d", "Error open inputstream as archive, id is ", r);
r = 0;
} else {
archive_list_all_entries(arc);
@@ -132,17 +140,17 @@ Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *env, jobject thi
jint index, jobject os) {
int count = 0;
struct archive_entry *entry;
archive_inst *arc = archive_create_inst(env, osf);
archive_inst *arc = archive_create_inst(env, osf);
int32_t size;
jmethodID writeID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, os), "write", "([B)V");
jmethodID flushID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, os), "flush", "()V");
archive_read_open(arc->archive, arc, NULL, ins_read, ins_close);
while (archive_read_next_header(arc->archive, &entry) == ARCHIVE_OK) {
if(!filename_is_playable_file(archive_entry_pathname(entry)))
if (!filename_is_playable_file(archive_entry_pathname(entry)))
continue;
if (count == index) {
for (;;) {
size = (int32_t)archive_read_data(arc->archive, arc->output_buffer, BLOCK_SIZE);
size = (int32_t) archive_read_data(arc->archive, arc->output_buffer, BLOCK_SIZE);
if (size < 0) {
return READ_DATA_ERR;
}
@@ -153,6 +161,8 @@ Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *env, jobject thi
(*arc->env)->CallVoidMethod(env, os, flushID);
}
break;
} else {
archive_read_data_skip(arc->archive);
}
count++;
}
@@ -13,7 +13,7 @@
# limitations under the License.
cmake_minimum_required(VERSION 3.4.1)
project(giflib C)
project(gif C)
set(GIFLIB_SOURCES
giflib/dgif_lib.c
@@ -23,5 +23,5 @@ set(GIFLIB_SOURCES
)
set(GIFLIB_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/giflib)
add_library(giflib STATIC ${GIFLIB_SOURCES})
target_include_directories(giflib PUBLIC ${GIFLIB_INCLUDES})
add_library(gif SHARED ${GIFLIB_SOURCES})
target_include_directories(gif PUBLIC ${GIFLIB_INCLUDES})
@@ -34,11 +34,11 @@ set(IMAGE_LIBRARIES
jnigraphics
GLESv2
stream
libjpeg-turbo
libpng
giflib
jpeg
png
gif
)
add_library(image STATIC ${IMAGE_SOURCES})
add_library(image SHARED ${IMAGE_SOURCES})
target_include_directories(image PRIVATE ${IMAGE_INCLUDES})
target_link_libraries(image PRIVATE ${IMAGE_LIBRARIES})
@@ -13,7 +13,7 @@
# limitations under the License.
cmake_minimum_required(VERSION 3.4.1)
project(libjpeg-turbo C)
project(jpeg C)
set(LIBJPEG_TURBO_SOURCES
libjpeg-turbo/jaricom.c
@@ -207,5 +207,5 @@ else ()
endif ()
add_library(libjpeg-turbo STATIC ${LIBJPEG_TURBO_SOURCES})
target_include_directories(libjpeg-turbo PUBLIC ${LIBJPEG_TURBO_INCLUDES})
add_library(jpeg SHARED ${LIBJPEG_TURBO_SOURCES})
target_include_directories(jpeg PUBLIC ${LIBJPEG_TURBO_INCLUDES})
@@ -4,22 +4,22 @@
#define JPEG_LIB_VERSION 62
/* libjpeg-turbo version */
#define LIBJPEG_TURBO_VERSION 2.0.0
#define LIBJPEG_TURBO_VERSION 2.1.3
/* libjpeg-turbo version in integer form */
#define LIBJPEG_TURBO_VERSION_NUMBER 2000000
#define LIBJPEG_TURBO_VERSION_NUMBER 2001003
/* Support arithmetic encoding */
#define C_ARITH_CODING_SUPPORTED
#define C_ARITH_CODING_SUPPORTED 1
/* Support arithmetic decoding */
#define D_ARITH_CODING_SUPPORTED
#define D_ARITH_CODING_SUPPORTED 1
/* Support in-memory source/destination managers */
#define MEM_SRCDST_SUPPORTED
#define MEM_SRCDST_SUPPORTED 1
/* Use accelerated SIMD routines. */
#define WITH_SIMD
#define WITH_SIMD 1
/*
* Define BITS_IN_JSAMPLE as either
@@ -32,42 +32,6 @@
#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
/* Define to 1 if you have the <locale.h> header file. */
#define HAVE_LOCALE_H
/* Define to 1 if you have the <stddef.h> header file. */
#define HAVE_STDDEF_H
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H
/* Define if you need to include <sys/types.h> to get size_t. */
#define NEED_SYS_TYPES_H
/* Define if you have BSD-like bzero and bcopy in <strings.h> rather than
memset/memcpy in <string.h>. */
/* #undef NEED_BSD_STRINGS */
/* Define to 1 if the system has the type `unsigned char'. */
#define HAVE_UNSIGNED_CHAR
/* Define to 1 if the system has the type `unsigned short'. */
#define HAVE_UNSIGNED_SHORT
/* Compiler does not support pointers to undefined structures. */
/* #undef INCOMPLETE_TYPES_BROKEN */
/* Define if your (broken) compiler shifts signed values as if they were
unsigned. */
/* #undef RIGHT_SHIFT_IS_UNSIGNED */
/* Define to 1 if type `char' is unsigned and you are not using gcc. */
#ifndef __CHAR_UNSIGNED__
/* #undef __CHAR_UNSIGNED__ */
#endif
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
@@ -1,5 +1,5 @@
/* libjpeg-turbo build number */
#define BUILD "20180730"
#define BUILD "20220523"
/* Compiler's inline keyword */
#undef inline
@@ -7,11 +7,14 @@
/* How to obtain function inlining. */
#define INLINE __inline__ __attribute__((always_inline))
/* How to obtain thread-local storage */
#define THREAD_LOCAL __thread
/* Define to the full name of this package. */
#define PACKAGE_NAME "libjpeg-turbo"
/* Version number of package */
#define VERSION "2.0.0"
#define VERSION "2.1.3"
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T __SIZEOF_SIZE_T__
@@ -0,0 +1,54 @@
/*
* jversion.h
*
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2010, 2012-2022, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
* This file contains software version identification.
*/
#if JPEG_LIB_VERSION >= 80
#define JVERSION "8d 15-Jan-2012"
#elif JPEG_LIB_VERSION >= 70
#define JVERSION "7 27-Jun-2009"
#else
#define JVERSION "6b 27-Mar-1998"
#endif
/*
* NOTE: It is our convention to place the authors in the following order:
* - libjpeg-turbo authors (2009-) in descending order of the date of their
* most recent contribution to the project, then in ascending order of the
* date of their first contribution to the project, then in alphabetical
* order
* - Upstream authors in descending order of the date of the first inclusion of
* their code
*/
#define JCOPYRIGHT \
"Copyright (C) 2009-2022 D. R. Commander\n" \
"Copyright (C) 2015, 2020 Google, Inc.\n" \
"Copyright (C) 2019-2020 Arm Limited\n" \
"Copyright (C) 2015-2016, 2018 Matthieu Darbois\n" \
"Copyright (C) 2011-2016 Siarhei Siamashka\n" \
"Copyright (C) 2015 Intel Corporation\n" \
"Copyright (C) 2013-2014 Linaro Limited\n" \
"Copyright (C) 2013-2014 MIPS Technologies, Inc.\n" \
"Copyright (C) 2009, 2012 Pierre Ossman for Cendio AB\n" \
"Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \
"Copyright (C) 1999-2006 MIYASAKA Masaru\n" \
"Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding"
#define JCOPYRIGHT_SHORT \
"Copyright (C) 1991-2022 The libjpeg-turbo Project and many others"
@@ -13,7 +13,7 @@
# limitations under the License.
cmake_minimum_required(VERSION 3.4.1)
project(libpng C)
project(png C)
set(LIBPNG_SOURCES
libpng/png.c
@@ -91,7 +91,7 @@ elseif (${ANDROID_ABI} STREQUAL "arm64-v8a")
endif ()
add_library(libpng STATIC ${LIBPNG_SOURCES})
target_include_directories(libpng PUBLIC ${LIBPNG_INCLUDES})
target_compile_definitions(libpng PRIVATE ${LIBPNG_DEFINITIONS})
target_link_libraries(libpng PRIVATE ${LIBPNG_LIBRARIES})
add_library(png SHARED ${LIBPNG_SOURCES})
target_include_directories(png PUBLIC ${LIBPNG_INCLUDES})
target_compile_definitions(png PRIVATE ${LIBPNG_DEFINITIONS})
target_link_libraries(png PRIVATE ${LIBPNG_LIBRARIES})
@@ -24,5 +24,6 @@ set(STREAM_SOURCES
)
set(STREAM_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
add_library(stream STATIC ${STREAM_SOURCES})
add_library(stream SHARED ${STREAM_SOURCES})
target_include_directories(stream PUBLIC ${STREAM_INCLUDES})
target_link_libraries(stream PRIVATE log)
@@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 3.4.1)
project(fuse C)
add_definitions(-D_FILE_OFFSET_BITS=64)
add_definitions(-DFUSERMOUNT_DIR=\"/system/bin\")
add_definitions(-DFUSE_USE_VERSION=35)
SET(FUSE_SOURCES
libfuse/lib/fuse.c
libfuse/lib/fuse_loop.c
libfuse/lib/fuse_loop_mt.c
libfuse/lib/fuse_lowlevel.c
libfuse/lib/fuse_opt.c
libfuse/lib/fuse_signals.c
libfuse/lib/buffer.c
libfuse/lib/cuse_lowlevel.c
libfuse/lib/helper.c
libfuse/lib/modules/subdir.c
libfuse/lib/modules/iconv.c
libfuse/lib/mount_util.c
libfuse/lib/mount.c
libfuse/lib/fuse_log.c)
set(FUSE_INCLUDES
${CMAKE_CURRENT_SOURCE_DIR}
libfuse/lib
libfuse/include)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version-script=${CMAKE_SOURCE_DIR}/libfuse/libfuse/lib/fuse_versionscript")
add_library(${PROJECT_NAME} SHARED ${FUSE_SOURCES})
target_include_directories(${PROJECT_NAME} PRIVATE ${FUSE_INCLUDES})
@@ -0,0 +1,2 @@
#define pthread_setcancelstate(x, y)
#define pthread_cancel(c)
+24
View File
@@ -0,0 +1,24 @@
/*
* Autogenerated by the Meson build system.
* Do not edit, your changes will be lost.
*/
#pragma once
#define HAVE_COPY_FILE_RANGE
#define HAVE_FALLOCATE
#define HAVE_FDATASYNC
#define HAVE_FORK
#define HAVE_FSTATAT
#define HAVE_ICONV
#define HAVE_OPENAT
#define HAVE_PIPE2
#define HAVE_POSIX_FALLOCATE
#define HAVE_READLINKAT
#define HAVE_SETXATTR
#define HAVE_SPLICE
#define HAVE_STRUCT_STAT_ST_ATIM
#undef HAVE_STRUCT_STAT_ST_ATIMESPEC
#define HAVE_UTIMENSAT
#define HAVE_VMSPLICE
#define PACKAGE_VERSION "3.6.1"
#include "android_config.h"
+33 -4
View File
@@ -1,12 +1,16 @@
#include <jni.h>
#include <archive.h>
#include <lzma.h>
#include <zstd.h>
#include <zlib.h>
#include "image/libjpeg-turbo/jconfigint.h"
#include "java_wrapper.h"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
{
JNIEnv* env;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env;
if ((*vm)->GetEnv(vm, (void**) (&env), JNI_VERSION_1_6) != JNI_OK) {
if ((*vm)->GetEnv(vm, (void **) (&env), JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
}
@@ -16,3 +20,28 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
return JNI_VERSION_1_6;
}
JNIEXPORT jstring JNICALL
Java_com_hippo_Native_getlibarchiveVersion(JNIEnv *env, jclass clazz) {
return (*env)->NewStringUTF(env, ARCHIVE_VERSION_STRING);
}
JNIEXPORT jstring JNICALL
Java_com_hippo_Native_getliblzmaVersion(JNIEnv *env, jclass clazz) {
return (*env)->NewStringUTF(env, lzma_version_string());
}
JNIEXPORT jstring JNICALL
Java_com_hippo_Native_getlibjpeg_1turboVersion(JNIEnv *env, jclass clazz) {
return (*env)->NewStringUTF(env, VERSION);
}
JNIEXPORT jstring JNICALL
Java_com_hippo_Native_getlibzstdVersion(JNIEnv *env, jclass clazz) {
return (*env)->NewStringUTF(env, ZSTD_VERSION_STRING);
}
JNIEXPORT jstring JNICALL
Java_com_hippo_Native_getzlibVersion(JNIEnv *env, jclass clazz) {
return (*env)->NewStringUTF(env, ZLIB_VERSION);
}