Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac55e2f8fc | ||
|
|
24718e7d25 | ||
|
|
72e1fe9621 | ||
|
|
0c7bf96bf5 | ||
|
|
f1dde6c8bc | ||
|
|
3177a8352f | ||
|
|
3cb024b7f5 | ||
|
|
0a09d16500 | ||
|
|
a79b1ad785 | ||
|
|
4388c53929 | ||
|
|
02f000d37b | ||
|
|
7259e5e315 | ||
|
|
7ce744b5af | ||
|
|
57f21c8d39 | ||
|
|
07f27a8438 | ||
|
|
4f4dc55b4e | ||
|
|
8e9cda8e93 | ||
|
|
d5cfabd73e | ||
|
|
4f1b371e75 | ||
|
|
4d8b50912d | ||
|
|
660c717cfb | ||
|
|
70d3d9a5b2 | ||
|
|
464da25ca1 | ||
|
|
c2795120e1 | ||
|
|
b10fb46f1f | ||
|
|
e39897176a | ||
|
|
6e7e6fab74 | ||
|
|
94009b6829 | ||
|
|
289217fefc | ||
|
|
97feab1203 | ||
|
|
a9a3b20eb3 | ||
|
|
7af1e168a4 | ||
|
|
c8bf34e0d7 | ||
|
|
86d2282cd6 | ||
|
|
cfdb23d6dc | ||
|
|
1874ddd15b | ||
|
|
a004c308cc | ||
|
|
863337c789 | ||
|
|
64d91eed33 | ||
|
|
d0c3a3e14d | ||
|
|
464636d87d | ||
|
|
0b0a1f456f | ||
|
|
302030ca65 | ||
|
|
3e63738542 | ||
|
|
d6823c9c8e | ||
|
|
6bc3866660 | ||
|
|
f41f4dd8ba | ||
|
|
cde39812ce | ||
|
|
03c2abc901 | ||
|
|
7646334525 | ||
|
|
f8d1cd3fab | ||
|
|
4ea94be64a |
No files matched your search
@@ -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
|
||||
@@ -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
@@ -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/
|
||||
@@ -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
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -519,7 +519,6 @@
|
||||
<string name="settings_about_declaration" translatable="false">EhViewer</string>
|
||||
<string name="settings_about_declaration_summary">EhViewer ไม่มีความแตกต่างจากตัวเว็บ E-Hentai.org แต่อย่างใด</string>
|
||||
<string name="settings_about_author">นักพัฒนา</string>
|
||||
<string name="settings_about_author_summary" translatable="false">Hippo <ehviewersu$gmail.com></string>
|
||||
<string name="settings_about_telegram">Telegram</string>
|
||||
<string name="settings_about_website">เว็บไซต์</string>
|
||||
<string name="settings_about_source">ซอร์สโค้ด</string>
|
||||
|
||||
@@ -759,4 +759,7 @@
|
||||
<string name="app_link_not_verified_message">对于 Android 12 及更新的版本,您需要手动添加链接到已验证链接才能在 EhViewer 中打开 E-Hentai 链接。</string>
|
||||
<string name="app_link_not_verified_title">应用链接未验证</string>
|
||||
<string name="open_by_default">默认打开</string>
|
||||
|
||||
<string name="show_library_version">依赖库之版本</string>
|
||||
<string name="settings_privacy_require_unlock">需要解锁</string>
|
||||
</resources>
|
||||
@@ -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>
|
||||
|
||||
@@ -82,8 +82,6 @@
|
||||
<dimen name="add_thickness">2dp</dimen>
|
||||
|
||||
<!-- CategoryTable -->
|
||||
<dimen name="category_table_item_height">40dp</dimen>
|
||||
<dimen name="category_table_item_margin">4dp</dimen>
|
||||
|
||||
<!-- AdvanceSearchTable -->
|
||||
<dimen name="advance_search_table_item_margin">4dp</dimen>
|
||||
@@ -97,7 +95,6 @@
|
||||
<dimen name="image_search_max_size">240dp</dimen>
|
||||
|
||||
<!-- Switch padding -->
|
||||
<dimen name="switch_padding">8dp</dimen>
|
||||
|
||||
<!-- FabLayout -->
|
||||
<dimen name="fab_layout_primary_margin">24dp</dimen>
|
||||
@@ -120,9 +117,6 @@
|
||||
<dimen name="gallery_guide_divider_width">3dp</dimen>
|
||||
|
||||
<!-- Lock pattern view -->
|
||||
<dimen name="lock_pattern_dot_line_width">3dp</dimen>
|
||||
<dimen name="lock_pattern_dot_size">12dp</dimen>
|
||||
<dimen name="lock_pattern_dot_size_activated">28dp</dimen>
|
||||
|
||||
<!-- Custom preference -->
|
||||
|
||||
|
||||
@@ -17,6 +17,5 @@
|
||||
|
||||
<drawable name="transparent">@android:color/transparent</drawable>
|
||||
<drawable name="tile_background_activated">#7f9c27b0</drawable>
|
||||
<drawable name="sadpanda_low_poly">@color/colorPrimary</drawable>
|
||||
|
||||
</resources>
|
||||
@@ -620,7 +620,7 @@
|
||||
<string name="settings_about_declaration" translatable="false">EhViewer</string>
|
||||
<string name="settings_about_declaration_summary">EhViewer is not affiliated with E-Hentai.org in any way</string>
|
||||
<string name="settings_about_author">Author</string>
|
||||
<string name="settings_about_author_summary" translatable="false"><del>Hippo &lt;ehviewersu$gmail.com&gt;</del><br>NekoInverter &lt;nekoworkshop$protonmail.com&gt;</string>
|
||||
<string name="settings_about_author_summary" translatable="false"><del>Hippo &lt;ehviewersu$gmail.com&gt;</del><br>NekoInverter &lt;nekoworkshop$protonmail.com&gt; <br>飛鳥澪</string>
|
||||
<string name="settings_about_telegram">Telegram</string>
|
||||
<string name="settings_about_latest_release">Latest release</string>
|
||||
<string name="settings_about_website">Website</string>
|
||||
@@ -823,4 +823,7 @@
|
||||
<string name="app_link_not_verified_message">For Android 12 and newer, you need to manually add link to verified links in order to open E-Hentai links in EhViewer.</string>
|
||||
<string name="app_link_not_verified_title">App links not verified</string>
|
||||
<string name="open_by_default">Open by default</string>
|
||||
|
||||
<string name="show_library_version">Library Version</string>
|
||||
<string name="settings_privacy_require_unlock">Require Unlock</string>
|
||||
</resources>
|
||||
@@ -19,7 +19,6 @@
|
||||
<style name="AppTheme" parent="Base.AppTheme" />
|
||||
|
||||
<!-- TextAppearance -->
|
||||
<style name="TextAppearance" parent="TextAppearance.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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
@@ -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'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
@@ -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"
|
||||
Submodule native/src/main/jni/image/libjpeg-turbo/libjpeg-turbo updated: 7e3cd1ac22...3331f85edc.
@@ -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)
|
||||
Submodule native/src/main/jni/libarchive updated: cffd8ecd55...f06bdccdfb.
@@ -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)
|
||||
@@ -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"
|
||||
Submodule
+1
Submodule native/src/main/jni/libfuse/libfuse added at a56147d3cb.
Submodule
+1
Submodule native/src/main/jni/libzstd added at e47e674cd0.
@@ -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);
|
||||
}
|
||||
Reference in new issue
Block a user