Compare commits

..
6 Commits
Author SHA1 Message Date
tarsin 4278bf4631 Version Bump 2022-05-18 11:48:23 +08:00
tarsin 7fa2dd1b74 Update Screenshot 2022-05-18 11:45:41 +08:00
tarsin afcd5b0d6e Drop unused res 2022-05-18 11:42:47 +08:00
tarsin 2f49748a3b Do Code cleanup 2022-05-18 11:40:29 +08:00
tarsin 4dffa25819 Drop unused lib 2022-05-18 11:30:24 +08:00
tarsin fcce3a04a6 Convert to dynamic color
* Drop color hardcode
2022-05-18 11:17:47 +08:00
172 changed files with 1073 additions and 1497 deletions

No files matched your search

+2 -5
View File
@@ -1,5 +1,3 @@
import java.nio.file.Paths
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
@@ -38,8 +36,8 @@ android {
applicationId "io.github.nekoinverter.ehviewer"
minSdkVersion 31
targetSdkVersion 32
versionCode 114515
versionName "1.7.26.6"
versionCode 114516
versionName "1.7.26.7"
resConfigs 'zh', 'zh-rCN', 'zh-rHK', 'zh-rTW', 'es', 'ja', 'ko', 'fr', 'de', 'th'
}
@@ -113,7 +111,6 @@ dependencies {
implementation 'androidx.webkit:webkit:1.4.0'
implementation 'com.drakeet.drawer:drawer:1.0.3'
implementation 'com.google.android.material:material:1.6.0'
implementation 'com.getkeepsafe.relinker:relinker:1.4.4'
implementation 'com.getkeepsafe.taptargetview:taptargetview:1.13.3'
implementation 'com.github.seven332:beerbelly:0.1.4'
implementation 'com.github.seven332:glgallery:0.1.2'
+9 -9
View File
@@ -32,24 +32,24 @@
<application
android:name="com.hippo.ehviewer.EhApplication"
android:allowBackup="true"
android:appCategory="image"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_scheme"
android:hasFragileUserData="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
android:appCategory="image"
android:hasFragileUserData="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme"
tools:ignore="UnusedAttribute"
android:dataExtractionRules="@xml/data_extraction_rules">
tools:ignore="UnusedAttribute">
<activity
android:name="com.hippo.ehviewer.ui.MainActivity"
android:configChanges="screenSize"
android:exported="true"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
android:exported="true">
android:windowSoftInputMode="adjustResize|stateAlwaysHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -90,9 +90,9 @@
<activity
android:name="com.hippo.ehviewer.ui.GalleryActivity"
android:configChanges="screenSize"
android:exported="true"
android:launchMode="singleTask"
android:theme="@style/AppTheme.Gallery"
android:exported="true">
android:theme="@style/AppTheme.Gallery">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
+6 -10
View File
@@ -39,26 +39,17 @@ import okhttp3.OkHttpClient;
@SuppressWarnings("rawtypes")
public final class Conaco<V> {
private static final String TAG = Conaco.class.getSimpleName();
@IntDef({SOURCE_MEMORY, SOURCE_DISK, SOURCE_NETWORK})
@Retention(RetentionPolicy.SOURCE)
public @interface Source {
}
public static final int SOURCE_MEMORY = 0;
public static final int SOURCE_DISK = 1;
public static final int SOURCE_NETWORK = 2;
private static final String TAG = Conaco.class.getSimpleName();
private final ValueHelper<V> mHelper;
private final ValueCache<V> mCache;
private final OkHttpClient mOkHttpClient;
private final Register<V> mRegister;
private final SerialThreadExecutor mDiskExecutor;
private final ThreadPoolExecutor mNetworkExecutor;
private final AtomicInteger mIdGenerator;
private final boolean mDebug;
private Conaco(Builder<V> builder) {
@@ -197,6 +188,11 @@ public final class Conaco<V> {
onUnregisterConacoTask(task);
}
@IntDef({SOURCE_MEMORY, SOURCE_DISK, SOURCE_NETWORK})
@Retention(RetentionPolicy.SOURCE)
public @interface Source {
}
public static class Builder<T> extends BeerBelly.BeerBellyParams {
/**
* The client to get image from internet
+160 -160
View File
@@ -85,6 +85,42 @@ public final class ConacoTask<V> {
mConaco = builder.mConaco;
}
private static void putFromDiskCacheToDataContainer(String key, ValueCache cache, DataContainer container) {
SimpleDiskCache diskCache = cache.getDiskCache();
if (diskCache != null) {
InputStreamPipe pipe = diskCache.getInputStreamPipe(key);
if (pipe != null) {
try {
pipe.obtain();
container.save(pipe.open(), -1L, null, null);
} catch (IOException e) {
Log.d(TAG, "Can't save value from disk cache to data container");
e.printStackTrace();
container.remove();
} finally {
pipe.close();
pipe.release();
}
}
}
}
private static void putFromDataContainerToDiskCache(String key, ValueCache cache, DataContainer container) {
InputStreamPipe pipe = container.get();
if (pipe != null) {
try {
pipe.obtain();
cache.putRawToDisk(key, pipe.open());
} catch (IOException e) {
Log.w(TAG, "Can't save value from data container to disk cache", e);
cache.removeFromDisk(key);
} finally {
pipe.close();
pipe.release();
}
}
}
int getId() {
return mId;
}
@@ -176,39 +212,133 @@ public final class ConacoTask<V> {
return mStop || asyncTask.isCancelled() || unikery == null || unikery.getTaskId() != mId;
}
private static void putFromDiskCacheToDataContainer(String key, ValueCache cache, DataContainer container) {
SimpleDiskCache diskCache = cache.getDiskCache();
if (diskCache != null) {
InputStreamPipe pipe = diskCache.getInputStreamPipe(key);
if (pipe != null) {
try {
pipe.obtain();
container.save(pipe.open(), -1L, null, null);
} catch (IOException e) {
Log.d(TAG, "Can't save value from disk cache to data container");
e.printStackTrace();
container.remove();
} finally {
pipe.close();
pipe.release();
}
@SuppressWarnings({"unused", "UnusedReturnValue", "RedundantSuppression"})
public static class Builder<T> {
private int mId;
private Unikery<T> mUnikery;
private String mKey;
private String mUrl;
private DataContainer mDataContainer;
private boolean mUseMemoryCache = true;
private boolean mUseDiskCache = true;
private boolean mUseNetwork = true;
private ValueHelper<T> mHelper;
private ValueCache<T> mCache;
private OkHttpClient mOkHttpClient;
private Executor mDiskExecutor;
private Executor mNetworkExecutor;
private Conaco<T> mConaco;
public Builder<T> setId(int id) {
mId = id;
return this;
}
public Unikery<T> getUnikery() {
return mUnikery;
}
public Builder<T> setUnikery(Unikery<T> unikery) {
mUnikery = unikery;
return this;
}
public String getKey() {
return mKey;
}
public Builder<T> setKey(String key) {
mKey = key;
return this;
}
public String getUrl() {
return mUrl;
}
public Builder<T> setUrl(String url) {
mUrl = url;
return this;
}
public Builder<T> setDataContainer(DataContainer dataContainer) {
mDataContainer = dataContainer;
return this;
}
boolean isUseMemoryCache() {
return mUseMemoryCache;
}
public Builder<T> setUseMemoryCache(boolean useMemoryCache) {
mUseMemoryCache = useMemoryCache;
return this;
}
boolean isUseDiskCache() {
return mUseDiskCache;
}
public Builder<T> setUseDiskCache(boolean useDiskCache) {
mUseDiskCache = useDiskCache;
return this;
}
boolean isUseNetwork() {
return mUseNetwork;
}
public Builder<T> setUseNetwork(boolean useNetwork) {
mUseNetwork = useNetwork;
return this;
}
ValueHelper<T> getHelper() {
return mHelper;
}
Builder<T> setHelper(ValueHelper<T> helper) {
mHelper = helper;
return this;
}
Builder<T> setCache(ValueCache<T> cache) {
mCache = cache;
return this;
}
Builder<T> setOkHttpClient(OkHttpClient okHttpClient) {
mOkHttpClient = okHttpClient;
return this;
}
Builder<T> setDiskExecutor(Executor diskExecutor) {
mDiskExecutor = diskExecutor;
return this;
}
Builder<T> setNetworkExecutor(Executor networkExecutor) {
mNetworkExecutor = networkExecutor;
return this;
}
Builder<T> setConaco(Conaco<T> conaco) {
mConaco = conaco;
return this;
}
public void isValid() {
if (mUnikery == null) {
throw new IllegalStateException("Must set unikery");
}
if (mKey == null && mUrl == null && mDataContainer == null) {
throw new IllegalStateException("At least one of mKey and mUrl and mDataContainer have to not be null");
}
}
}
private static void putFromDataContainerToDiskCache(String key, ValueCache cache, DataContainer container) {
InputStreamPipe pipe = container.get();
if (pipe != null) {
try {
pipe.obtain();
cache.putRawToDisk(key, pipe.open());
} catch (IOException e) {
Log.w(TAG, "Can't save value from data container to disk cache", e);
cache.removeFromDisk(key);
} finally {
pipe.close();
pipe.release();
}
public ConacoTask<T> build() {
return new ConacoTask<>(this);
}
}
@@ -455,134 +585,4 @@ public final class ConacoTask<V> {
}
}
}
@SuppressWarnings({"unused", "UnusedReturnValue", "RedundantSuppression"})
public static class Builder<T> {
private int mId;
private Unikery<T> mUnikery;
private String mKey;
private String mUrl;
private DataContainer mDataContainer;
private boolean mUseMemoryCache = true;
private boolean mUseDiskCache = true;
private boolean mUseNetwork = true;
private ValueHelper<T> mHelper;
private ValueCache<T> mCache;
private OkHttpClient mOkHttpClient;
private Executor mDiskExecutor;
private Executor mNetworkExecutor;
private Conaco<T> mConaco;
public Builder<T> setId(int id) {
mId = id;
return this;
}
public Builder<T> setUnikery(Unikery<T> unikery) {
mUnikery = unikery;
return this;
}
public Unikery<T> getUnikery() {
return mUnikery;
}
public Builder<T> setKey(String key) {
mKey = key;
return this;
}
public String getKey() {
return mKey;
}
public Builder<T> setUrl(String url) {
mUrl = url;
return this;
}
public String getUrl() {
return mUrl;
}
public Builder<T> setDataContainer(DataContainer dataContainer) {
mDataContainer = dataContainer;
return this;
}
public Builder<T> setUseMemoryCache(boolean useMemoryCache) {
mUseMemoryCache = useMemoryCache;
return this;
}
boolean isUseMemoryCache() {
return mUseMemoryCache;
}
public Builder<T> setUseDiskCache(boolean useDiskCache) {
mUseDiskCache = useDiskCache;
return this;
}
boolean isUseDiskCache() {
return mUseDiskCache;
}
public Builder<T> setUseNetwork(boolean useNetwork) {
mUseNetwork = useNetwork;
return this;
}
boolean isUseNetwork() {
return mUseNetwork;
}
Builder<T> setHelper(ValueHelper<T> helper) {
mHelper = helper;
return this;
}
ValueHelper<T> getHelper() {
return mHelper;
}
Builder<T> setCache(ValueCache<T> cache) {
mCache = cache;
return this;
}
Builder<T> setOkHttpClient(OkHttpClient okHttpClient) {
mOkHttpClient = okHttpClient;
return this;
}
Builder<T> setDiskExecutor(Executor diskExecutor) {
mDiskExecutor = diskExecutor;
return this;
}
Builder<T> setNetworkExecutor(Executor networkExecutor) {
mNetworkExecutor = networkExecutor;
return this;
}
Builder<T> setConaco(Conaco<T> conaco) {
mConaco = conaco;
return this;
}
public void isValid() {
if (mUnikery == null) {
throw new IllegalStateException("Must set unikery");
}
if (mKey == null && mUrl == null && mDataContainer == null) {
throw new IllegalStateException("At least one of mKey and mUrl and mDataContainer have to not be null");
}
}
public ConacoTask<T> build() {
return new ConacoTask<>(this);
}
}
}
@@ -22,13 +22,6 @@ public interface Unikery<V> {
int INVALID_ID = -1;
/**
* Store the conaco task id
*
* @param id the conaco task id
*/
void setTaskId(int id);
/**
* Get the conaco task id
*
@@ -36,6 +29,13 @@ public interface Unikery<V> {
*/
int getTaskId();
/**
* Store the conaco task id
*
* @param id the conaco task id
*/
void setTaskId(int id);
/**
* On miss in the source
*/
@@ -46,9 +46,9 @@ public class MSQLiteBuilder {
JAVA_TYPE_TO_SQLITE_TYPE.put(String.class, "TEXT");
}
private final SparseArray<List<String>> statementsMap = new SparseArray<>();
private int version = 0;
private List<String> statements;
private final SparseArray<List<String>> statementsMap = new SparseArray<>();
private static String javaTypeToSQLiteType(Class clazz) {
String type = JAVA_TYPE_TO_SQLITE_TYPE.get(clazz);
@@ -86,23 +86,19 @@ public class EasyRecyclerView extends BridgeRecyclerView {
double flingMoveDistanceY;
boolean canScrollVertical = true;
boolean canScrollHorizontally = true;
/**
* Controls if/how the user may choose/check items in the list
*/
private int mChoiceMode = CHOICE_MODE_NONE;
/**
* Controls CHOICE_MODE_MULTIPLE_MODAL. null when inactive.
*/
private ActionMode mChoiceActionMode;
/**
* Wrapper for the multiple choice mode callback; AbsListView needs to perform
* a few extra actions around what application code does.
*/
MultiChoiceModeWrapper mMultiChoiceModeCallback;
/**
* Controls if/how the user may choose/check items in the list
*/
private int mChoiceMode = CHOICE_MODE_NONE;
/**
* Controls CHOICE_MODE_MULTIPLE_MODAL. null when inactive.
*/
private ActionMode mChoiceActionMode;
/**
* Listener for custom multiple choices
*/
@@ -161,6 +157,14 @@ public class EasyRecyclerView extends BridgeRecyclerView {
setEnableScroll(!Settings.getEInkMode());
}
public static void setViewChecked(View view, boolean checked) {
if (view instanceof Checkable) {
((Checkable) view).setChecked(checked);
} else {
view.setActivated(checked);
}
}
/**
* {@inheritDoc}
*/
@@ -550,14 +554,6 @@ public class EasyRecyclerView extends BridgeRecyclerView {
}
}
public static void setViewChecked(View view, boolean checked) {
if (view instanceof Checkable) {
((Checkable) view).setChecked(checked);
} else {
view.setActivated(checked);
}
}
private void init(Context context) {
float scale = context.getResources().getDisplayMetrics().density;
final float ppi = scale * 160.0f;
@@ -845,12 +841,78 @@ public class EasyRecyclerView extends BridgeRecyclerView {
return mFlingFriction * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l);
}
public boolean isEnableScroll() {
return enableScroll;
}
public void setEnableScroll(boolean enableScroll) {
this.enableScroll = enableScroll;
}
public boolean isEnableScroll() {
return enableScroll;
@Override
public Parcelable onSaveInstanceState() {
final SavedState ss = new SavedState(super.onSaveInstanceState());
ss.choiceMode = mChoiceMode;
ss.customChoice = mCustomChoice;
ss.checkedItemCount = mCheckedItemCount;
ss.checkState = mCheckStates;
ss.checkIdState = mCheckedIdStates;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setChoiceMode(ss.choiceMode);
mCustomChoice = ss.customChoice;
mCheckedItemCount = ss.checkedItemCount;
if (ss.checkState != null) {
mCheckStates = ss.checkState;
}
if (ss.checkIdState != null) {
mCheckedIdStates = ss.checkIdState;
}
if (mChoiceMode == CHOICE_MODE_MULTIPLE_MODAL && mCheckedItemCount > 0) {
mChoiceActionMode = startActionMode(mMultiChoiceModeCallback);
}
updateOnScreenCheckedViews();
}
/**
* A MultiChoiceModeListener receives events for {@link android.widget.AbsListView#CHOICE_MODE_MULTIPLE_MODAL}.
* It acts as the {@link android.view.ActionMode.Callback} for the selection mode and also receives
* {@link #onItemCheckedStateChanged(android.view.ActionMode, int, long, boolean)} events when the user
* selects and deselects list items.
*/
public interface MultiChoiceModeListener extends ActionMode.Callback {
/**
* Called when an item is checked or unchecked during selection mode.
*
* @param mode The {@link android.view.ActionMode} providing the selection mode
* @param position Adapter position of the item that was checked or unchecked
* @param id Adapter ID of the item that was checked or unchecked
* @param checked <code>true</code> if the item is now checked, <code>false</code>
* if the item is now unchecked.
*/
void onItemCheckedStateChanged(ActionMode mode,
int position, long id, boolean checked);
}
/**
* Custom checked
*/
public interface CustomChoiceListener {
void onIntoCustomChoice(EasyRecyclerView view);
void onOutOfCustomChoice(EasyRecyclerView view);
void onItemCheckedStateChanged(EasyRecyclerView view, int position, long id, boolean checked);
}
/**
@@ -870,13 +932,23 @@ public class EasyRecyclerView extends BridgeRecyclerView {
public static final SavedState EMPTY_STATE = new SavedState() {
};
public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
int choiceMode;
boolean customChoice;
int checkedItemCount;
SparseBooleanArray checkState;
LongSparseArray<Integer> checkIdState;
// This keeps the parent(RecyclerView)'s state
Parcelable mSuperState;
@@ -939,73 +1011,6 @@ public class EasyRecyclerView extends BridgeRecyclerView {
public Parcelable getSuperState() {
return mSuperState;
}
public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
@Override
public Parcelable onSaveInstanceState() {
final SavedState ss = new SavedState(super.onSaveInstanceState());
ss.choiceMode = mChoiceMode;
ss.customChoice = mCustomChoice;
ss.checkedItemCount = mCheckedItemCount;
ss.checkState = mCheckStates;
ss.checkIdState = mCheckedIdStates;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setChoiceMode(ss.choiceMode);
mCustomChoice = ss.customChoice;
mCheckedItemCount = ss.checkedItemCount;
if (ss.checkState != null) {
mCheckStates = ss.checkState;
}
if (ss.checkIdState != null) {
mCheckedIdStates = ss.checkIdState;
}
if (mChoiceMode == CHOICE_MODE_MULTIPLE_MODAL && mCheckedItemCount > 0) {
mChoiceActionMode = startActionMode(mMultiChoiceModeCallback);
}
updateOnScreenCheckedViews();
}
/**
* A MultiChoiceModeListener receives events for {@link android.widget.AbsListView#CHOICE_MODE_MULTIPLE_MODAL}.
* It acts as the {@link android.view.ActionMode.Callback} for the selection mode and also receives
* {@link #onItemCheckedStateChanged(android.view.ActionMode, int, long, boolean)} events when the user
* selects and deselects list items.
*/
public interface MultiChoiceModeListener extends ActionMode.Callback {
/**
* Called when an item is checked or unchecked during selection mode.
*
* @param mode The {@link android.view.ActionMode} providing the selection mode
* @param position Adapter position of the item that was checked or unchecked
* @param id Adapter ID of the item that was checked or unchecked
* @param checked <code>true</code> if the item is now checked, <code>false</code>
* if the item is now unchecked.
*/
void onItemCheckedStateChanged(ActionMode mode,
int position, long id, boolean checked);
}
class MultiChoiceModeWrapper implements MultiChoiceModeListener {
@@ -1064,16 +1069,4 @@ public class EasyRecyclerView extends BridgeRecyclerView {
}
}
}
/**
* Custom checked
*/
public interface CustomChoiceListener {
void onIntoCustomChoice(EasyRecyclerView view);
void onOutOfCustomChoice(EasyRecyclerView view);
void onItemCheckedStateChanged(EasyRecyclerView view, int position, long id, boolean checked);
}
}
@@ -28,9 +28,9 @@ import androidx.annotation.NonNull;
public class HandlerDrawable extends Drawable {
private int mColor = Color.BLACK;
private final Paint mPaint;
private final RectF mTemp = new RectF();
private int mColor = Color.BLACK;
public HandlerDrawable() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -35,13 +35,10 @@ import androidx.recyclerview.widget.RecyclerView;
public class LinearDividerItemDecoration extends RecyclerView.ItemDecoration {
public static final int HORIZONTAL = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL = LinearLayoutManager.VERTICAL;
private boolean mShowFirstDivider = false;
private boolean mShowLastDivider = false;
private final Rect mRect;
private final Paint mPaint;
private boolean mShowFirstDivider = false;
private boolean mShowLastDivider = false;
private int mOrientation;
private int mThickness;
private int mPaddingStart = 0;
@@ -19,13 +19,11 @@ package com.hippo.ehviewer;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.text.TextUtils;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.browser.customtabs.CustomTabColorSchemeParams;
import androidx.browser.customtabs.CustomTabsIntent;
import com.hippo.ehviewer.client.EhUrlOpener;
@@ -36,8 +34,6 @@ import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.scene.Announcer;
import com.hippo.scene.StageActivity;
import rikka.core.res.ResourcesKt;
public final class UrlOpener {
private UrlOpener() {
@@ -92,14 +88,8 @@ public final class UrlOpener {
}
}
boolean isNight = (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_YES) > 0;
CustomTabsIntent.Builder customTabsIntent = new CustomTabsIntent.Builder();
customTabsIntent.setShowTitle(true);
CustomTabColorSchemeParams params = new CustomTabColorSchemeParams.Builder()
.setToolbarColor(ResourcesKt.resolveColor(context.getTheme(), R.attr.toolbarColor))
.build();
customTabsIntent.setDefaultColorSchemeParams(params);
customTabsIntent.setColorScheme(isNight ? CustomTabsIntent.COLOR_SCHEME_DARK : CustomTabsIntent.COLOR_SCHEME_LIGHT);
try {
customTabsIntent.build().launchUrl(context, uri);
} catch (ActivityNotFoundException e) {
@@ -15,14 +15,13 @@ public class WindowInsetsAnimationHelper extends WindowInsetsAnimationCompat.Cal
private final View[] views;
private final HashMap<View, Integer> startPaddings = new HashMap<>();
private final HashMap<View, Integer> endPaddings = new HashMap<>();
WindowInsetsAnimationCompat animation;
public WindowInsetsAnimationHelper(int dispatchMode, View... views) {
super(dispatchMode);
this.views = views;
}
WindowInsetsAnimationCompat animation;
@Override
public void onPrepare(@NonNull WindowInsetsAnimationCompat animation) {
super.onPrepare(animation);
@@ -36,6 +36,7 @@ import com.hippo.ehviewer.client.exception.EhException;
import com.hippo.ehviewer.client.exception.NoHAtHClientException;
import com.hippo.ehviewer.client.exception.ParseException;
import com.hippo.ehviewer.client.parser.ArchiveParser;
import com.hippo.ehviewer.client.parser.EventPaneParser;
import com.hippo.ehviewer.client.parser.FavoritesParser;
import com.hippo.ehviewer.client.parser.ForumsParser;
import com.hippo.ehviewer.client.parser.GalleryApiParser;
@@ -48,7 +49,6 @@ import com.hippo.ehviewer.client.parser.GalleryTokenApiParser;
import com.hippo.ehviewer.client.parser.ProfileParser;
import com.hippo.ehviewer.client.parser.RateGalleryParser;
import com.hippo.ehviewer.client.parser.SignInParser;
import com.hippo.ehviewer.client.parser.EventPaneParser;
import com.hippo.ehviewer.client.parser.TorrentParser;
import com.hippo.ehviewer.client.parser.VoteCommentParser;
import com.hippo.ehviewer.client.parser.VoteTagParser;
@@ -971,7 +971,7 @@ public class EhEngine {
try {
Response response = call.execute();
Log.d(TAG, "" + response.request().url().toString());
Log.d(TAG, "" + response.request().url());
code = response.code();
headers = response.headers();
@@ -56,9 +56,9 @@ import okio.Okio;
public class EhTagDatabase {
private static final Map<String, String> NAMESPACE_TO_PREFIX = new HashMap<>();
private static volatile EhTagDatabase instance;
// TODO more lock for different language
private static final Lock lock = new ReentrantLock();
private static volatile EhTagDatabase instance;
static {
NAMESPACE_TO_PREFIX.put("artist", "a:");
@@ -36,40 +36,29 @@ public class EhUrl {
public static final String DOMAIN_LOFI = "lofi.e-hentai.org";
public static final String HOST_EX = "https://" + DOMAIN_EX + "/";
public static final String HOST_E = "https://" + DOMAIN_E + "/";
public static final String API_SIGN_IN = "https://forums.e-hentai.org/index.php?act=Login&CODE=01";
public static final String API_E = HOST_E + "api.php";
public static final String API_EX = HOST_EX + "api.php";
public static final String URL_FAVORITES_EX = HOST_EX + "favorites.php";
public static final String URL_UCONFIG_EX = HOST_EX + "uconfig.php";
public static final String URL_MY_TAGS_EX = HOST_EX + "mytags";
public static final String URL_WATCHED_EX = HOST_EX + "watched";
public static final String HOST_E = "https://" + DOMAIN_E + "/";
public static final String API_E = HOST_E + "api.php";
public static final String URL_FAVORITES_E = HOST_E + "favorites.php";
public static final String URL_UCONFIG_E = HOST_E + "uconfig.php";
public static final String URL_MY_TAGS_E = HOST_E + "mytags";
public static final String URL_WATCHED_E = HOST_E + "watched";
public static final String API_SIGN_IN = "https://forums.e-hentai.org/index.php?act=Login&CODE=01";
public static final String URL_POPULAR_E = "https://e-hentai.org/popular";
public static final String URL_POPULAR_EX = "https://exhentai.org/popular";
public static final String URL_IMAGE_SEARCH_E = "https://upload.e-hentai.org/image_lookup.php";
public static final String URL_IMAGE_SEARCH_EX = "https://exhentai.org/upload/image_lookup.php";
public static final String URL_SIGN_IN = "https://forums.e-hentai.org/index.php?act=Login";
public static final String URL_REGISTER = "https://forums.e-hentai.org/index.php?act=Reg&CODE=00";
public static final String URL_FAVORITES_E = HOST_E + "favorites.php";
public static final String URL_FAVORITES_EX = HOST_EX + "favorites.php";
public static final String URL_FORUMS = "https://forums.e-hentai.org/";
public static final String REFERER_EX = "https://" + DOMAIN_EX;
public static final String REFERER_E = "https://" + DOMAIN_E;
public static final String ORIGIN_EX = REFERER_EX;
public static final String REFERER_E = "https://" + DOMAIN_E;
public static final String ORIGIN_E = REFERER_E;
public static final String URL_UCONFIG_E = HOST_E + "uconfig.php";
public static final String URL_UCONFIG_EX = HOST_EX + "uconfig.php";
public static final String URL_MY_TAGS_E = HOST_E + "mytags";
public static final String URL_MY_TAGS_EX = HOST_EX + "mytags";
public static final String URL_WATCHED_E = HOST_E + "watched";
public static final String URL_WATCHED_EX = HOST_EX + "watched";
private static final String URL_PREFIX_THUMB_E = "https://ehgt.org/";
private static final String URL_PREFIX_THUMB_EX = "https://exhentai.org/t/";
@@ -40,9 +40,9 @@ import okhttp3.HttpUrl;
public class IdentityCookiePreference extends MessagePreference {
private String message;
@SuppressLint("StaticFieldLeak")
private final SettingsActivity mActivity;
private String message;
public IdentityCookiePreference(Context context) {
super(context);
@@ -143,6 +143,7 @@ public final class SpiderQueen implements Runnable {
private final int mWorkerMaxCount;
private final int mPreloadNumber;
private final int mDownloadDelay;
private final AtomicReference<String> showKey = new AtomicReference<>();
private int mReadReference = 0;
private int mDownloadReference = 0;
// It mQueenThread is null, failed or stopped
@@ -153,7 +154,6 @@ public final class SpiderQueen implements Runnable {
private volatile int[] mPageStateArray;
// For download, when it go to mPageStateArray.size(), done
private volatile int mDownloadPage = -1;
private final AtomicReference<String> showKey = new AtomicReference<>();
private SpiderQueen(EhApplication application, @NonNull GalleryInfo galleryInfo) {
mHttpClient = EhApplication.getOkHttpClient(application);
@@ -130,6 +130,36 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
private GalleryInfo mGalleryInfo;
private int mPage;
private String mCacheFileName;
ActivityResultLauncher<String> saveImageToLauncher = registerForActivityResult(
new ActivityResultContracts.CreateDocument(),
uri -> {
if (uri != null) {
String filepath = AppConfig.getExternalTempDir() + File.separator + mCacheFileName;
File cachefile = new File(filepath);
ContentResolver resolver = getContentResolver();
IoThreadPoolExecutor.getInstance().execute(() -> {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(cachefile);
os = resolver.openOutputStream(uri);
IOUtils.copy(is, os);
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(os);
runOnUiThread(() -> Toast.makeText(GalleryActivity.this, getString(R.string.image_saved, uri.getPath()), Toast.LENGTH_SHORT).show());
}
//noinspection ResultOfMethodCallIgnored
cachefile.delete();
});
}
});
@Nullable
private GLRootView mGLRootView;
@Nullable
@@ -191,10 +221,7 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
private int mLayoutMode;
private int mSize;
private int mCurrentIndex;
private int mSavingPage = -1;
ActivityResultLauncher<String> requestStoragePermissionLauncher = registerForActivityResult(
private int mSavingPage = -1; ActivityResultLauncher<String> requestStoragePermissionLauncher = registerForActivityResult(
new ActivityResultContracts.RequestPermission(),
result -> {
if (result && mSavingPage != -1) {
@@ -204,36 +231,6 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
}
mSavingPage = -1;
});
ActivityResultLauncher<String> saveImageToLauncher = registerForActivityResult(
new ActivityResultContracts.CreateDocument(),
uri -> {
if (uri != null) {
String filepath = AppConfig.getExternalTempDir() + File.separator + mCacheFileName;
File cachefile = new File(filepath);
ContentResolver resolver = getContentResolver();
IoThreadPoolExecutor.getInstance().execute(() -> {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(cachefile);
os = resolver.openOutputStream(uri);
IOUtils.copy(is, os);
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(os);
runOnUiThread(() -> Toast.makeText(GalleryActivity.this, getString(R.string.image_saved, uri.getPath()), Toast.LENGTH_SHORT).show());
}
//noinspection ResultOfMethodCallIgnored
cachefile.delete();
});
}
});
private void buildProvider() {
if (mGalleryProvider != null) {
@@ -1023,6 +1020,29 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
});
}
@Nullable
private String getGalleryDetailUrl() {
long gid;
String token;
if (mGalleryInfo != null) {
gid = mGalleryInfo.gid;
token = mGalleryInfo.token;
} else {
return null;
}
return EhUrl.getGalleryDetailUrl(gid, token, 0, false);
}
@Override
public void onProvideAssistContent(AssistContent outContent) {
super.onProvideAssistContent(outContent);
String url = getGalleryDetailUrl();
if (url != null) {
outContent.setWebUri(Uri.parse(url));
}
}
private class GalleryMenuHelper implements DialogInterface.OnClickListener {
private final View mView;
@@ -1283,26 +1303,5 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
}
}
@Nullable
private String getGalleryDetailUrl() {
long gid;
String token;
if (mGalleryInfo != null) {
gid = mGalleryInfo.gid;
token = mGalleryInfo.token;
} else {
return null;
}
return EhUrl.getGalleryDetailUrl(gid, token, 0, false);
}
@Override
public void onProvideAssistContent(AssistContent outContent) {
super.onProvideAssistContent(outContent);
String url = getGalleryDetailUrl();
if (url != null) {
outContent.setWebUri(Uri.parse(url));
}
}
}
@@ -23,7 +23,6 @@ import android.os.Bundle;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
@@ -174,6 +174,25 @@ public class FilterFragment extends BaseFragment {
.show();
}
@Override
public int getFragmentTitle() {
return R.string.filter;
}
private static class FilterHolder extends RecyclerView.ViewHolder {
private final MaterialCheckBox checkbox;
private final TextView text;
private final ImageView delete;
public FilterHolder(View itemView) {
super(itemView);
checkbox = itemView.findViewById(R.id.checkbox);
text = itemView.findViewById(R.id.text);
delete = itemView.findViewById(R.id.delete);
}
}
private class AddFilterDialogHelper implements View.OnClickListener {
@Nullable
@@ -235,20 +254,6 @@ public class FilterFragment extends BaseFragment {
}
}
private static class FilterHolder extends RecyclerView.ViewHolder {
private final MaterialCheckBox checkbox;
private final TextView text;
private final ImageView delete;
public FilterHolder(View itemView) {
super(itemView);
checkbox = itemView.findViewById(R.id.checkbox);
text = itemView.findViewById(R.id.text);
delete = itemView.findViewById(R.id.delete);
}
}
private class FilterAdapter extends RecyclerView.Adapter<FilterHolder> {
private static final int TYPE_ITEM = 0;
@@ -457,9 +462,4 @@ public class FilterFragment extends BaseFragment {
mEhFilter.triggerFilter(filter);
}
}
@Override
public int getFragmentTitle() {
return R.string.filter;
}
}
@@ -118,6 +118,11 @@ public class HostsFragment extends BaseFragment
adapter.notifyDataSetChanged();
}
@Override
public int getFragmentTitle() {
return R.string.hosts;
}
public abstract static class HostDialogFragment extends DialogFragment {
private HostsFragment hostsFragment;
@@ -266,9 +271,4 @@ public class HostsFragment extends BaseFragment
return data.size();
}
}
@Override
public int getFragmentTitle() {
return R.string.hosts;
}
}
@@ -72,6 +72,11 @@ public class MyTagsFragment extends BaseFragment {
}
}
@Override
public int getFragmentTitle() {
return R.string.my_tags;
}
private class MyTagsWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
@@ -89,9 +94,4 @@ public class MyTagsFragment extends BaseFragment {
progress.setVisibility(View.GONE);
}
}
@Override
public int getFragmentTitle() {
return R.string.my_tags;
}
}
@@ -146,6 +146,16 @@ public class UConfigFragment extends BaseFragment {
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public int getFragmentTitle() {
return R.string.u_config;
}
private class UConfigWebViewClient extends WebViewClient {
@Override
@@ -166,14 +176,4 @@ public class UConfigFragment extends BaseFragment {
loaded = true;
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public int getFragmentTitle() {
return R.string.u_config;
}
}
@@ -41,7 +41,6 @@ import androidx.fragment.app.FragmentActivity;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.scene.SceneFragment;
import com.hippo.util.AppHelper;
public abstract class BaseScene extends SceneFragment {
@@ -378,12 +378,12 @@ public class DownloadsScene extends ToolbarScene
mRecyclerView.scrollToPosition(mInitPosition);
mInitPosition = -1;
}
RecyclerViewKt.addEdgeSpacing(mRecyclerView, 4,4,4,4, TypedValue.COMPLEX_UNIT_DIP);
RecyclerViewKt.addEdgeSpacing(mRecyclerView, 4, 4, 4, 4, TypedValue.COMPLEX_UNIT_DIP);
RecyclerViewKt.fixEdgeEffect(mRecyclerView, false, true);
mFastScroller.attachToRecyclerView(mRecyclerView);
HandlerDrawable handlerDrawable = new HandlerDrawable();
handlerDrawable.setColor(ResourcesKt.resolveColor(getTheme(), R.attr.widgetColorThemeAccent));
handlerDrawable.setColor(com.google.android.material.R.color.material_dynamic_neutral100);
mFastScroller.setHandlerDrawable(handlerDrawable);
mFastScroller.setOnDragHandlerListener(this);
@@ -437,8 +437,8 @@ public class DownloadsScene extends ToolbarScene
TapTargetView.showFor(requireActivity(),
TapTarget.forView(((DownloadHolder) holder).thumb,
getString(R.string.guide_download_thumb_title),
getString(R.string.guide_download_thumb_text))
getString(R.string.guide_download_thumb_title),
getString(R.string.guide_download_thumb_text))
.transparentTarget(true),
new TapTargetView.Listener() {
@Override
@@ -466,8 +466,8 @@ public class DownloadsScene extends ToolbarScene
TapTargetView.showFor(requireActivity(),
TapTarget.forBounds(bounds,
getString(R.string.guide_download_labels_title),
getString(R.string.guide_download_labels_text))
getString(R.string.guide_download_labels_title),
getString(R.string.guide_download_labels_text))
.outerCircleColor(R.color.colorPrimary)
.transparentTarget(true),
new TapTargetView.Listener() {
@@ -999,6 +999,73 @@ public class DownloadsScene extends ToolbarScene
}
}
private static class ThumbDataContainer implements DataContainer {
private final DownloadInfo mInfo;
@Nullable
private UniFile mFile;
public ThumbDataContainer(@NonNull DownloadInfo info) {
mInfo = info;
}
private void ensureFile() {
if (mFile == null) {
UniFile dir = SpiderDen.getGalleryDownloadDir(mInfo);
if (dir != null && dir.isDirectory()) {
mFile = dir.createFile(".thumb");
}
}
}
@Override
public boolean isEnabled() {
ensureFile();
return mFile != null;
}
@Override
public void onUrlMoved(String requestUrl, String responseUrl) {
}
@Override
public boolean save(InputStream is, long length, String mediaType, ProgressNotifier notify) {
ensureFile();
if (mFile == null) {
return false;
}
OutputStream os = null;
try {
os = mFile.openOutputStream();
IOUtils.copy(is, os);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
IOUtils.closeQuietly(os);
}
}
@Override
public InputStreamPipe get() {
ensureFile();
if (mFile != null) {
return new UniFileInputStreamPipe(mFile);
} else {
return null;
}
}
@Override
public void remove() {
if (mFile != null) {
mFile.delete();
}
}
}
private class DownloadLabelAdapter extends RecyclerView.Adapter<DownloadLabelHolder> implements DraggableItemAdapter<DownloadLabelHolder> {
private final LayoutInflater mInflater;
@@ -1392,73 +1459,6 @@ public class DownloadsScene extends ToolbarScene
}
}
private static class ThumbDataContainer implements DataContainer {
private final DownloadInfo mInfo;
@Nullable
private UniFile mFile;
public ThumbDataContainer(@NonNull DownloadInfo info) {
mInfo = info;
}
private void ensureFile() {
if (mFile == null) {
UniFile dir = SpiderDen.getGalleryDownloadDir(mInfo);
if (dir != null && dir.isDirectory()) {
mFile = dir.createFile(".thumb");
}
}
}
@Override
public boolean isEnabled() {
ensureFile();
return mFile != null;
}
@Override
public void onUrlMoved(String requestUrl, String responseUrl) {
}
@Override
public boolean save(InputStream is, long length, String mediaType, ProgressNotifier notify) {
ensureFile();
if (mFile == null) {
return false;
}
OutputStream os = null;
try {
os = mFile.openOutputStream();
IOUtils.copy(is, os);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
IOUtils.closeQuietly(os);
}
}
@Override
public InputStreamPipe get() {
ensureFile();
if (mFile != null) {
return new UniFileInputStreamPipe(mFile);
} else {
return null;
}
}
@Override
public void remove() {
if (mFile != null) {
mFile.delete();
}
}
}
private class RenameLabelDialogHelper implements View.OnClickListener {
private final EditTextDialogBuilder mBuilder;
@@ -27,7 +27,6 @@ import android.os.Bundle;
import android.text.InputType;
import android.text.TextUtils;
import android.util.SparseBooleanArray;
import android.util.TypedValue;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -91,7 +90,6 @@ import java.util.Collections;
import java.util.List;
import rikka.core.res.ResourcesKt;
import rikka.recyclerview.RecyclerViewKt;
// TODO Get favorite, modify favorite, add favorite, what a mess!
@SuppressLint("RtlHardcoded")
@@ -121,6 +119,19 @@ public class FavoritesScene extends BaseScene implements
@Nullable
@ViewLifeCircle
private FabLayout mFabLayout;
private final Runnable showNormalFabsRunnable = new Runnable() {
@Override
public void run() {
if (mFabLayout != null) {
mFabLayout.setSecondaryFabVisibilityAt(0, true);
mFabLayout.setSecondaryFabVisibilityAt(1, true);
mFabLayout.setSecondaryFabVisibilityAt(2, true);
mFabLayout.setSecondaryFabVisibilityAt(3, false);
mFabLayout.setSecondaryFabVisibilityAt(4, false);
mFabLayout.setSecondaryFabVisibilityAt(5, false);
}
}
};
@Nullable
@ViewLifeCircle
private FavoritesAdapter mAdapter;
@@ -166,20 +177,6 @@ public class FavoritesScene extends BaseScene implements
// For modify action
private boolean mModifyAdd;
private final Runnable showNormalFabsRunnable = new Runnable() {
@Override
public void run() {
if (mFabLayout != null) {
mFabLayout.setSecondaryFabVisibilityAt(0, true);
mFabLayout.setSecondaryFabVisibilityAt(1, true);
mFabLayout.setSecondaryFabVisibilityAt(2, true);
mFabLayout.setSecondaryFabVisibilityAt(3, false);
mFabLayout.setSecondaryFabVisibilityAt(4, false);
mFabLayout.setSecondaryFabVisibilityAt(5, false);
}
}
};
@Override
public int getNavCheckedItem() {
return R.id.nav_favourite;
@@ -335,8 +332,8 @@ public class FavoritesScene extends BaseScene implements
TapTargetView.showFor(requireActivity(),
TapTarget.forBounds(bounds,
getString(R.string.guide_collections_title),
getString(R.string.guide_collections_text))
getString(R.string.guide_collections_title),
getString(R.string.guide_collections_text))
.outerCircleColor(R.color.colorPrimary)
.transparentTarget(true),
new TapTargetView.Listener() {
@@ -60,11 +60,11 @@ abstract class GalleryAdapter extends RecyclerView.Adapter<GalleryHolder> {
private final int mPaddingTopSB;
private final int mListThumbWidth;
private final int mListThumbHeight;
private final boolean mShowFavourited;
private final DownloadManager mDownloadManager;
private MarginItemDecoration mListDecoration;
private MarginItemDecoration mGirdDecoration;
private int mType = TYPE_INVALID;
private final boolean mShowFavourited;
private final DownloadManager mDownloadManager;
public GalleryAdapter(@NonNull LayoutInflater inflater, @NonNull Resources resources,
@NonNull RecyclerView recyclerView, int type, boolean showFavourited) {
@@ -45,7 +45,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsAnimationCompat;
@@ -224,7 +223,7 @@ public final class GalleryCommentsScene extends ToolbarScene
if (itemAnimator instanceof DefaultItemAnimator) {
((DefaultItemAnimator) itemAnimator).setSupportsChangeAnimations(false);
}
RecyclerViewKt.addEdgeSpacing(mRecyclerView, 0,0,0,80, TypedValue.COMPLEX_UNIT_DIP);
RecyclerViewKt.addEdgeSpacing(mRecyclerView, 0, 0, 0, 80, TypedValue.COMPLEX_UNIT_DIP);
mSendImage.setOnClickListener(this);
mFab.setOnClickListener(this);
@@ -472,27 +471,27 @@ public final class GalleryCommentsScene extends ToolbarScene
mFab.animate().x(fabEndX).y(fabEndY).scaleX(0.0f).scaleY(0.0f)
.setInterpolator(AnimationUtils.SLOW_FAST_SLOW_INTERPOLATOR)
.setDuration(300L).setListener(new SimpleAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
if (null == mFab || null == mEditPanel) {
return;
}
((View) mFab).setVisibility(View.INVISIBLE);
mEditPanel.setVisibility(View.VISIBLE);
int halfW = mEditPanel.getWidth() / 2;
int halfH = mEditPanel.getHeight() / 2;
Animator animator = ViewAnimationUtils.createCircularReveal(mEditPanel, halfW, halfH, 0,
(float) Math.hypot(halfW, halfH)).setDuration(300L);
animator.addListener(new SimpleAnimatorListener() {
@Override
public void onAnimationEnd(Animator a) {
mInAnimation = false;
public void onAnimationEnd(Animator animation) {
if (null == mFab || null == mEditPanel) {
return;
}
((View) mFab).setVisibility(View.INVISIBLE);
mEditPanel.setVisibility(View.VISIBLE);
int halfW = mEditPanel.getWidth() / 2;
int halfH = mEditPanel.getHeight() / 2;
Animator animator = ViewAnimationUtils.createCircularReveal(mEditPanel, halfW, halfH, 0,
(float) Math.hypot(halfW, halfH)).setDuration(300L);
animator.addListener(new SimpleAnimatorListener() {
@Override
public void onAnimationEnd(Animator a) {
mInAnimation = false;
}
});
animator.start();
}
});
animator.start();
}
}).start();
}).start();
}
private void showEditPanel(boolean animation) {
@@ -544,11 +543,11 @@ public final class GalleryCommentsScene extends ToolbarScene
mFab.animate().translationX(0.0f).translationY(0.0f).scaleX(1.0f).scaleY(1.0f).rotation(0.0f)
.setInterpolator(AnimationUtils.SLOW_FAST_SLOW_INTERPOLATOR)
.setDuration(300L).setListener(new SimpleAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
mInAnimation = false;
}
}).start();
@Override
public void onAnimationEnd(Animator animation) {
mInAnimation = false;
}
}).start();
}
});
animator.start();
@@ -848,6 +847,18 @@ public final class GalleryCommentsScene extends ToolbarScene
}
}
private static class MoreCommentHolder extends CommentHolder {
public MoreCommentHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater, R.layout.item_gallery_comment_more, parent);
}
}
private static class ProgressCommentHolder extends CommentHolder {
public ProgressCommentHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater, R.layout.item_gallery_comment_progress, parent);
}
}
private class ActualCommentHolder extends CommentHolder {
private final TextView user;
@@ -902,18 +913,6 @@ public final class GalleryCommentsScene extends ToolbarScene
}
}
private static class MoreCommentHolder extends CommentHolder {
public MoreCommentHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater, R.layout.item_gallery_comment_more, parent);
}
}
private static class ProgressCommentHolder extends CommentHolder {
public ProgressCommentHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater, R.layout.item_gallery_comment_progress, parent);
}
}
private class CommentAdapter extends RecyclerView.Adapter<CommentHolder> {
private final LayoutInflater mInflater;
@@ -265,12 +265,6 @@ public class GalleryDetailScene extends BaseScene implements View.OnClickListene
private GalleryDetail mGalleryDetail;
private int mRequestId = IntIdGenerator.INVALID_ID;
private Pair<String, String>[] mTorrentList;
private String mArchiveFormParamOr;
private Pair<String, String>[] mArchiveList;
@State
private int mState = STATE_INIT;
private boolean mModifingFavorites;
ActivityResultLauncher<String> requestStoragePermissionLauncher = registerForActivityResult(
new ActivityResultContracts.RequestPermission(),
result -> {
@@ -284,6 +278,24 @@ public class GalleryDetailScene extends BaseScene implements View.OnClickListene
helper.setDialog(dialog, mGalleryDetail.torrentUrl);
}
});
private String mArchiveFormParamOr;
private Pair<String, String>[] mArchiveList;
@State
private int mState = STATE_INIT;
private boolean mModifingFavorites;
@Nullable
private static String getArtist(GalleryTagGroup[] tagGroups) {
if (null == tagGroups) {
return null;
}
for (GalleryTagGroup tagGroup : tagGroups) {
if ("artist".equals(tagGroup.groupName) && tagGroup.size() > 0) {
return tagGroup.getTagAt(0);
}
}
return null;
}
@StringRes
private int getRatingText(float rating) {
@@ -330,19 +342,6 @@ public class GalleryDetailScene extends BaseScene implements View.OnClickListene
return resId;
}
@Nullable
private static String getArtist(GalleryTagGroup[] tagGroups) {
if (null == tagGroups) {
return null;
}
for (GalleryTagGroup tagGroup : tagGroups) {
if ("artist".equals(tagGroup.groupName) && tagGroup.size() > 0) {
return tagGroup.getTagAt(0);
}
}
return null;
}
private void handleArgs(Bundle args) {
if (args == null) {
return;
@@ -1710,6 +1709,16 @@ public class GalleryDetailScene extends BaseScene implements View.OnClickListene
mModifingFavorites = false;
}
@Override
public void onProvideAssistContent(AssistContent outContent) {
super.onProvideAssistContent(outContent);
String url = getGalleryDetailUrl(false);
if (url != null) {
outContent.setWebUri(Uri.parse(url));
}
}
@IntDef({STATE_INIT, STATE_NORMAL, STATE_REFRESH, STATE_REFRESH_HEADER, STATE_FAILED})
@Retention(RetentionPolicy.SOURCE)
private @interface State {
@@ -2223,14 +2232,4 @@ public class GalleryDetailScene extends BaseScene implements View.OnClickListene
EhApplication.getEhClient(context).execute(request);
}
}
@Override
public void onProvideAssistContent(AssistContent outContent) {
super.onProvideAssistContent(outContent);
String url = getGalleryDetailUrl(false);
if (url != null) {
outContent.setWebUri(Uri.parse(url));
}
}
}
@@ -165,6 +165,9 @@ public final class GalleryListScene extends BaseScene
private EasyRecyclerView mRecyclerView;
@Nullable
private SearchLayout mSearchLayout;
ActivityResultLauncher<String[]> selectImageLauncher = registerForActivityResult(
new ActivityResultContracts.OpenDocument(),
result -> mSearchLayout.setImageUri(result));
@Nullable
private SearchBar mSearchBar;
@Nullable
@@ -236,10 +239,6 @@ public final class GalleryListScene extends BaseScene
private FavouriteStatusRouter.Listener mFavouriteStatusRouterListener;
private boolean mIsTopList = false;
ActivityResultLauncher<String[]> selectImageLauncher = registerForActivityResult(
new ActivityResultContracts.OpenDocument(),
result -> mSearchLayout.setImageUri(result));
@Nullable
private static String getSuitableTitleForUrlBuilder(
Resources resources, ListUrlBuilder urlBuilder, boolean appName) {
@@ -657,8 +656,8 @@ public final class GalleryListScene extends BaseScene
TapTargetView.showFor(requireActivity(),
TapTarget.forBounds(bounds,
getString(R.string.guide_quick_search_title),
getString(R.string.guide_quick_search_text))
getString(R.string.guide_quick_search_title),
getString(R.string.guide_quick_search_text))
.outerCircleColor(R.color.colorPrimary)
.transparentTarget(true),
new TapTargetView.Listener() {
@@ -1093,39 +1092,6 @@ public final class GalleryListScene extends BaseScene
return true;
}
private class MoveDialogHelper implements DialogInterface.OnClickListener {
private final String[] mLabels;
private final GalleryInfo mGi;
public MoveDialogHelper(String[] labels, GalleryInfo gi) {
mLabels = labels;
mGi = gi;
}
@Override
public void onClick(DialogInterface dialog, int which) {
// Cancel check mode
Context context = getContext();
if (null == context) {
return;
}
if (null != mRecyclerView) {
mRecyclerView.outOfCustomChoiceMode();
}
DownloadManager downloadManager = EhApplication.getDownloadManager(context);
DownloadInfo downloadInfo = downloadManager.getDownloadInfo(mGi.gid);
if (downloadInfo == null) {
return;
}
String label = which == 0 ? null : mLabels[which];
downloadManager.changeLabel(Collections.singletonList(downloadInfo), label);
}
}
private void showActionFab() {
if (null != mFabLayout && STATE_NORMAL == mState && !mShowActionFab) {
mShowActionFab = true;
@@ -1614,6 +1580,39 @@ public final class GalleryListScene extends BaseScene
}
}
private class MoveDialogHelper implements DialogInterface.OnClickListener {
private final String[] mLabels;
private final GalleryInfo mGi;
public MoveDialogHelper(String[] labels, GalleryInfo gi) {
mLabels = labels;
mGi = gi;
}
@Override
public void onClick(DialogInterface dialog, int which) {
// Cancel check mode
Context context = getContext();
if (null == context) {
return;
}
if (null != mRecyclerView) {
mRecyclerView.outOfCustomChoiceMode();
}
DownloadManager downloadManager = EhApplication.getDownloadManager(context);
DownloadInfo downloadInfo = downloadManager.getDownloadInfo(mGi.gid);
if (downloadInfo == null) {
return;
}
String label = which == 0 ? null : mLabels[which];
downloadManager.changeLabel(Collections.singletonList(downloadInfo), label);
}
}
private class QsDrawerAdapter extends RecyclerView.Adapter<QsDrawerHolder> implements DraggableItemAdapter<QsDrawerHolder> {
private final LayoutInflater mInflater;
@@ -86,7 +86,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import rikka.core.res.ResourcesKt;
import rikka.recyclerview.RecyclerViewKt;
public class HistoryScene extends ToolbarScene {
@@ -234,11 +233,11 @@ public class HistoryScene extends ToolbarScene {
guardManager.attachRecyclerView(mRecyclerView);
swipeManager.attachRecyclerView(mRecyclerView);
RecyclerViewKt.fixEdgeEffect(mRecyclerView, false, true);
RecyclerViewKt.addEdgeSpacing(mRecyclerView, 4,4,4,4, TypedValue.COMPLEX_UNIT_DIP);
RecyclerViewKt.addEdgeSpacing(mRecyclerView, 4, 4, 4, 4, TypedValue.COMPLEX_UNIT_DIP);
mFastScroller.attachToRecyclerView(mRecyclerView);
HandlerDrawable handlerDrawable = new HandlerDrawable();
handlerDrawable.setColor(ResourcesKt.resolveColor(getTheme(), R.attr.widgetColorThemeAccent));
handlerDrawable.setColor(com.google.android.material.R.color.material_dynamic_neutral100);
mFastScroller.setHandlerDrawable(handlerDrawable);
updateLazyList();
@@ -458,39 +457,6 @@ public class HistoryScene extends ToolbarScene {
return true;
}
private class MoveDialogHelper implements DialogInterface.OnClickListener {
private final String[] mLabels;
private final GalleryInfo mGi;
public MoveDialogHelper(String[] labels, GalleryInfo gi) {
mLabels = labels;
mGi = gi;
}
@Override
public void onClick(DialogInterface dialog, int which) {
// Cancel check mode
Context context = getContext();
if (null == context) {
return;
}
if (null != mRecyclerView) {
mRecyclerView.outOfCustomChoiceMode();
}
DownloadManager downloadManager = EhApplication.getDownloadManager(context);
DownloadInfo downloadInfo = downloadManager.getDownloadInfo(mGi.gid);
if (downloadInfo == null) {
return;
}
String label = which == 0 ? null : mLabels[which];
downloadManager.changeLabel(Collections.singletonList(downloadInfo), label);
}
}
private static class AddToFavoriteListener extends EhCallback<GalleryListScene, Void> {
public AddToFavoriteListener(Context context, int stageId, String sceneTag) {
@@ -578,6 +544,39 @@ public class HistoryScene extends ToolbarScene {
}
}
private class MoveDialogHelper implements DialogInterface.OnClickListener {
private final String[] mLabels;
private final GalleryInfo mGi;
public MoveDialogHelper(String[] labels, GalleryInfo gi) {
mLabels = labels;
mGi = gi;
}
@Override
public void onClick(DialogInterface dialog, int which) {
// Cancel check mode
Context context = getContext();
if (null == context) {
return;
}
if (null != mRecyclerView) {
mRecyclerView.outOfCustomChoiceMode();
}
DownloadManager downloadManager = EhApplication.getDownloadManager(context);
DownloadInfo downloadInfo = downloadManager.getDownloadInfo(mGi.gid);
if (downloadInfo == null) {
return;
}
String label = which == 0 ? null : mLabels[which];
downloadManager.changeLabel(Collections.singletonList(downloadInfo), label);
}
}
private class HistoryAdapter extends RecyclerView.Adapter<HistoryHolder>
implements SwipeableItemAdapter<HistoryHolder> {
@@ -41,7 +41,7 @@ import java.util.List;
import java.util.concurrent.Executors;
public class SecurityScene extends SolidScene implements
LockPatternView.OnPatternListener{
LockPatternView.OnPatternListener {
private static final int MAX_RETRY_TIMES = 5;
private static final String KEY_RETRY_TIMES = "retry_times";
@@ -32,19 +32,15 @@ import com.hippo.yorozuya.ObjectUtils;
public class GalleryHeader extends ViewGroup {
private DisplayCutoutCompat displayCutout;
private int topInsets = 0;
private View battery;
private View progress;
private View clock;
private final Rect batteryRect = new Rect();
private final Rect progressRect = new Rect();
private final Rect clockRect = new Rect();
private final int[] location = new int[2];
private DisplayCutoutCompat displayCutout;
private int topInsets = 0;
private View battery;
private View progress;
private View clock;
private int lastX = 0;
private int lastY = 0;
@@ -33,10 +33,9 @@ import java.util.Map;
public abstract class GalleryInfoContentHelper extends ContentLayout.ContentHelper<GalleryInfo> {
private static final String KEY_DATA_MAP = "data_map";
private final FavouriteStatusRouter.Listener listener;
@SuppressLint("UseSparseArrays")
private Map<Long, GalleryInfo> map = new HashMap<>();
private final FavouriteStatusRouter.Listener listener;
public GalleryInfoContentHelper() {
listener = (gid, slot) -> {
@@ -40,7 +40,6 @@ import android.widget.TextView;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.util.Pair;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -491,6 +490,27 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener,
}
}
private String wrapTagKeyword(String keyword) {
keyword = keyword.trim();
int index1 = keyword.indexOf(':');
if (index1 == -1 || index1 >= keyword.length() - 1) {
// Can't find :, or : is the last char
return keyword;
}
if (keyword.charAt(index1 + 1) == '"') {
// The char after : is ", the word must be quoted
return keyword;
}
int index2 = keyword.indexOf(' ');
if (index2 <= index1) {
// Can't find space, or space is before :
return keyword;
}
return keyword.substring(0, index1 + 1) + "\"" + keyword.substring(index1 + 1) + "$\"";
}
public interface Helper {
void onClickTitle();
@@ -666,25 +686,4 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener,
return true;
}
}
private String wrapTagKeyword(String keyword) {
keyword = keyword.trim();
int index1 = keyword.indexOf(':');
if (index1 == -1 || index1 >= keyword.length() - 1) {
// Can't find :, or : is the last char
return keyword;
}
if (keyword.charAt(index1 + 1) == '"') {
// The char after : is ", the word must be quoted
return keyword;
}
int index2 = keyword.indexOf(' ');
if (index2 <= index1) {
// Can't find space, or space is before :
return keyword;
}
return keyword.substring(0, index1 + 1) + "\"" + keyword.substring(index1 + 1) + "$\"";
}
}
@@ -314,6 +314,22 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
void onSelectImage();
}
static class SearchLayoutManager extends LinearLayoutManager {
public SearchLayoutManager(Context context) {
super(context);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
try {
super.onLayoutChildren(recycler, state);
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
}
}
}
private class SearchAdapter extends EasyRecyclerView.Adapter<SimpleHolder> {
@Override
@@ -384,20 +400,4 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
return type;
}
}
static class SearchLayoutManager extends LinearLayoutManager {
public SearchLayoutManager(Context context) {
super(context);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
try {
super.onLayoutChildren(recycler, state);
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
}
}
}
}
@@ -31,8 +31,8 @@ import com.hippo.yorozuya.ViewUtils;
public class SeekBarPanel extends LinearLayout {
private SeekBar mSeekBar;
private final int[] mLocation = new int[2];
private SeekBar mSeekBar;
public SeekBarPanel(Context context) {
super(context);
@@ -36,7 +36,6 @@ public final class ReadableTime {
public static final long DAY_MILLIS = 24 * HOUR_MILLIS;
public static final long WEEK_MILLIS = 7 * DAY_MILLIS;
public static final long YEAR_MILLIS = 365 * DAY_MILLIS;
public static final int SIZE = 5;
public static final long[] MULTIPLES = {
YEAR_MILLIS,
DAY_MILLIS,
@@ -44,6 +43,7 @@ public final class ReadableTime {
MINUTE_MILLIS,
SECOND_MILLIS
};
public static final int SIZE = 5;
public static final int[] UNITS = {
R.plurals.year,
R.plurals.day,
@@ -26,12 +26,9 @@ public class ViewTransition {
protected static final long ANIMATE_TIME = 300L;
private final View[] mViews;
private int mShownView = -1;
protected ViewPropertyAnimator mAnimator1;
protected ViewPropertyAnimator mAnimator2;
private int mShownView = -1;
private OnShowViewListener mOnShowViewListener;
public ViewTransition(View... views) {
@@ -167,8 +167,8 @@ public class AutoWrapLayout extends ViewGroup {
// If it is first item in line, try to show it all
if (lineEndIndex == lineStartIndex) {
child.measure(MeasureSpec.makeMeasureSpec(
maxWidth - paddingLeft - paddingRight
- lp.leftMargin - lp.rightMargin, MeasureSpec.AT_MOST),
maxWidth - paddingLeft - paddingRight
- lp.leftMargin - lp.rightMargin, MeasureSpec.AT_MOST),
MeasureSpec.UNSPECIFIED);
childWidth = child.getMeasuredWidth();
childHeight = child.getMeasuredHeight();
@@ -41,7 +41,7 @@ public class BatteryView extends AppCompatTextView {
private boolean mCharging = false;
private BatteryDrawable mDrawable;
private final Runnable mCharger = new Runnable() {
private boolean mAttached = false; private final Runnable mCharger = new Runnable() {
private int level = 0;
@@ -55,9 +55,14 @@ public class BatteryView extends AppCompatTextView {
getHandler().postDelayed(mCharger, 200);
}
};
private boolean mAttached = false;
private boolean mIsChargerWorking = false;
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
public BatteryView(Context context) {
super(context);
init();
}
public BatteryView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
@SuppressLint("SetTextI18n")
@@ -88,15 +93,6 @@ public class BatteryView extends AppCompatTextView {
}
};
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);
@@ -173,4 +169,8 @@ public class BatteryView extends AppCompatTextView {
private void unregisterReceiver() {
getContext().unregisterReceiver(mIntentReceiver);
}
}
@@ -33,17 +33,12 @@ import com.hippo.ehviewer.R;
public class CheckTextView extends AppCompatCheckedTextView implements View.OnClickListener {
private Drawable mForeground;
private final Rect mSelfBounds = new Rect();
private final Rect mOverlayBounds = new Rect();
private int mForegroundGravity = Gravity.FILL;
protected boolean mForegroundInPadding = true;
boolean mForegroundBoundsChanged = false;
private Drawable mForeground;
private int mForegroundGravity = Gravity.FILL;
public CheckTextView(Context context) {
this(context, null);
@@ -136,6 +131,16 @@ public class CheckTextView extends AppCompatCheckedTextView implements View.OnCl
}
}
/**
* Returns the drawable used as the foreground of this FrameLayout. The
* foreground drawable, if non-null, is always drawn on top of the children.
*
* @return A Drawable or null if no foreground was set.
*/
public Drawable getForeground() {
return mForeground;
}
/**
* Supply a Drawable that is to be rendered on top of all of the child
* views in the frame layout. Any padding in the Drawable will be taken
@@ -171,16 +176,6 @@ public class CheckTextView extends AppCompatCheckedTextView implements View.OnCl
}
}
/**
* Returns the drawable used as the foreground of this FrameLayout. The
* foreground drawable, if non-null, is always drawn on top of the children.
*
* @return A Drawable or null if no foreground was set.
*/
public Drawable getForeground() {
return mForeground;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
@@ -56,7 +56,6 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import rikka.core.res.ResourcesKt;
import rikka.recyclerview.RecyclerViewKt;
public class ContentLayout extends FrameLayout {
@@ -106,7 +105,7 @@ public class ContentLayout extends FrameLayout {
mFastScroller.attachToRecyclerView(mRecyclerView);
HandlerDrawable drawable = new HandlerDrawable();
drawable.setColor(ResourcesKt.resolveColor(context.getTheme(), R.attr.widgetColorThemeAccent));
drawable.setColor(com.google.android.material.R.color.material_dynamic_neutral100);
mFastScroller.setHandlerDrawable(drawable);
mRefreshLayout.setColorSchemeResources(
@@ -125,7 +124,7 @@ public class ContentLayout extends FrameLayout {
resources.getColor(R.color.loading_indicator_orange));
mBottomProgress.setIndeterminateAnimationType(LinearProgressIndicator.INDETERMINATE_ANIMATION_TYPE_CONTIGUOUS);
RecyclerViewKt.addEdgeSpacing(mRecyclerView, 4,4,4,4, TypedValue.COMPLEX_UNIT_DIP);
RecyclerViewKt.addEdgeSpacing(mRecyclerView, 4, 4, 4, 4, TypedValue.COMPLEX_UNIT_DIP);
RecyclerViewKt.fixEdgeEffect(mRecyclerView, false, true);
mRecyclerViewOriginBottom = mRecyclerView.getPaddingBottom();
@@ -263,8 +262,6 @@ public class ContentLayout extends FrameLayout {
private int mCurrentTaskId;
private int mCurrentTaskType;
private int mCurrentTaskPage;
private int mNextPageScrollSize;
private String mEmptyString = "No hint";
private final SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
@@ -278,6 +275,8 @@ public class ContentLayout extends FrameLayout {
}
}
};
private int mNextPageScrollSize;
private String mEmptyString = "No hint";
private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
@@ -134,10 +134,8 @@ public class Slider extends View {
setProgress(a.getInteger(R.styleable.Slider_slider_progress, 0));
mThickness = a.getDimension(R.styleable.Slider_thickness, 2);
mRadius = a.getDimension(R.styleable.Slider_radius, 6);
setColor(a.getColor(R.styleable.Slider_color, Color.BLACK));
mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBgPaint.setColor(a.getBoolean(R.styleable.Slider_dark, false) ? 0x4dffffff : 0x42000000);
a.recycle();
@@ -55,7 +55,7 @@ public class TextClock extends AppCompatTextView {
private boolean mAttached;
private Calendar mTime;
private final Runnable mTicker = new Runnable() {
private String mTimeZone; private final Runnable mTicker = new Runnable() {
@Override
public void run() {
onTimeChanged();
@@ -66,7 +66,16 @@ public class TextClock extends AppCompatTextView {
getHandler().postAtTime(mTicker, next);
}
};
private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mTimeZone == null && Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
final String timeZone = intent.getStringExtra("time-zone");
createTime(timeZone);
}
onTimeChanged();
}
}; private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
chooseFormat();
@@ -79,22 +88,9 @@ public class TextClock extends AppCompatTextView {
onTimeChanged();
}
};
private String mTimeZone;
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mTimeZone == null && Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
final String timeZone = intent.getStringExtra("time-zone");
createTime(timeZone);
}
onTimeChanged();
}
};
public TextClock(Context context) {
this(context, null);
}
public TextClock(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -261,4 +257,8 @@ public class TextClock extends AppCompatTextView {
mTime.setTimeInMillis(System.currentTimeMillis());
setText(DateFormat.format(mFormat, mTime));
}
}
@@ -58,9 +58,6 @@ public class LockPatternView extends View {
private static final int ASPECT_SQUARE = 0; // View will be the minimum of width/height
private static final int ASPECT_LOCK_WIDTH = 1; // Fixed width; height will be minimum of (w,h)
private static final int ASPECT_LOCK_HEIGHT = 2; // Fixed height; width will be minimum of (w,h)
private final Cell[][] mCells;
private static final boolean PROFILE_DRAWING = false;
/**
* How many milliseconds we spend animating each circle of a lock pattern
@@ -73,6 +70,7 @@ public class LockPatternView extends View {
* It didn't seem to have much impact on the devices tested, so currently set to 0.
*/
private static final float DRAG_THRESHOLD = 0.0f;
private final Cell[][] mCells;
private final CellState[][] mCellStates;
private final int mDotSize;
private final int mDotSizeActivated;
@@ -181,6 +179,66 @@ public class LockPatternView extends View {
mLinearOutSlowInInterpolator = new LinearOutSlowInInterpolator();
}
/**
* Returns the greatest common divisor of {@code a, b}. Returns {@code 0} if
* {@code a == 0 && b == 0}.
*
* @throws IllegalArgumentException if {@code a < 0} or {@code b < 0}
*/
private static int gcd(int a, int b) {
/*
* The reason we require both arguments to be >= 0 is because otherwise, what do you return
* on gcd(0, Integer.MIN_VALUE)? BigInteger.gcd would return positive 2^31, but positive
* 2^31 isn't an int.
*/
//checkNonNegative("a", a);
if (a < 0) {
throw new IllegalArgumentException("a (" + a + ") must be >= 0");
}
//checkNonNegative("b", b);
if (b < 0) {
throw new IllegalArgumentException("b (" + b + ") must be >= 0");
}
if (a == 0) {
// 0 % b == 0, so b divides a, but the converse doesn't hold.
// BigInteger.gcd is consistent with this decision.
return b;
} else if (b == 0) {
return a; // similar logic
}
/*
* Uses the binary GCD algorithm; see http://en.wikipedia.org/wiki/Binary_GCD_algorithm.
* This is >40% faster than the Euclidean algorithm in benchmarks.
*/
int aTwos = Integer.numberOfTrailingZeros(a);
a >>= aTwos; // divide out all 2s
int bTwos = Integer.numberOfTrailingZeros(b);
b >>= bTwos; // divide out all 2s
while (a != b) { // both a, b are odd
// The key to the binary GCD algorithm is as follows:
// Both a and b are odd. Assume a > b; then gcd(a - b, b) = gcd(a, b).
// But in gcd(a - b, b), a - b is even and b is odd, so we can divide out powers of two.
// We bend over backwards to avoid branching, adapting a technique from
// http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
int delta = a - b; // can't overflow, since a and b are nonnegative
int minDeltaOrZero = delta & (delta >> (Integer.SIZE - 1));
// equivalent to Math.min(delta, 0)
a = delta - minDeltaOrZero - minDeltaOrZero; // sets a to Math.abs(a - b)
// a is now nonnegative and even
b += minDeltaOrZero; // sets b to min(old a, b)
a >>= Integer.numberOfTrailingZeros(a); // divide out all 2s, since 2 doesn't divide b
}
return a << Math.min(aTwos, bTwos);
}
public int getCellSize() {
return mPattern.size();
}
@@ -333,6 +391,9 @@ public class LockPatternView extends View {
setMeasuredDimension(viewWidth, viewHeight);
}
// From
// https://github.com/google/guava/blob/c462d69329709f72a17a64cb229d15e76e72199c/guava/src/com/google/common/math/IntMath.java
/**
* Determines whether the point x, y will add a new point to the current
* pattern (in addition to finding the cell, also makes heuristic choices
@@ -376,69 +437,6 @@ public class LockPatternView extends View {
return null;
}
// From
// https://github.com/google/guava/blob/c462d69329709f72a17a64cb229d15e76e72199c/guava/src/com/google/common/math/IntMath.java
/**
* Returns the greatest common divisor of {@code a, b}. Returns {@code 0} if
* {@code a == 0 && b == 0}.
*
* @throws IllegalArgumentException if {@code a < 0} or {@code b < 0}
*/
private static int gcd(int a, int b) {
/*
* The reason we require both arguments to be >= 0 is because otherwise, what do you return
* on gcd(0, Integer.MIN_VALUE)? BigInteger.gcd would return positive 2^31, but positive
* 2^31 isn't an int.
*/
//checkNonNegative("a", a);
if (a < 0) {
throw new IllegalArgumentException("a (" + a + ") must be >= 0");
}
//checkNonNegative("b", b);
if (b < 0) {
throw new IllegalArgumentException("b (" + b + ") must be >= 0");
}
if (a == 0) {
// 0 % b == 0, so b divides a, but the converse doesn't hold.
// BigInteger.gcd is consistent with this decision.
return b;
} else if (b == 0) {
return a; // similar logic
}
/*
* Uses the binary GCD algorithm; see http://en.wikipedia.org/wiki/Binary_GCD_algorithm.
* This is >40% faster than the Euclidean algorithm in benchmarks.
*/
int aTwos = Integer.numberOfTrailingZeros(a);
a >>= aTwos; // divide out all 2s
int bTwos = Integer.numberOfTrailingZeros(b);
b >>= bTwos; // divide out all 2s
while (a != b) { // both a, b are odd
// The key to the binary GCD algorithm is as follows:
// Both a and b are odd. Assume a > b; then gcd(a - b, b) = gcd(a, b).
// But in gcd(a - b, b), a - b is even and b is odd, so we can divide out powers of two.
// We bend over backwards to avoid branching, adapting a technique from
// http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
int delta = a - b; // can't overflow, since a and b are nonnegative
int minDeltaOrZero = delta & (delta >> (Integer.SIZE - 1));
// equivalent to Math.min(delta, 0)
a = delta - minDeltaOrZero - minDeltaOrZero; // sets a to Math.abs(a - b)
// a is now nonnegative and even
b += minDeltaOrZero; // sets b to min(old a, b)
a >>= Integer.numberOfTrailingZeros(a); // divide out all 2s, since 2 doesn't divide b
}
return a << Math.min(aTwos, bTwos);
}
private void addCellToPattern(Cell newCell) {
mPatternDrawLookup[newCell.getRow()][newCell.getColumn()] = true;
mPattern.add(newCell);
@@ -1040,14 +1038,14 @@ public class LockPatternView extends View {
}
public static class CellState {
public float lineEndX = Float.MIN_VALUE;
public float lineEndY = Float.MIN_VALUE;
public ValueAnimator lineAnimator;
int row;
int col;
float radius;
float translationY;
float alpha = 1f;
public float lineEndX = Float.MIN_VALUE;
public float lineEndY = Float.MIN_VALUE;
public ValueAnimator lineAnimator;
}
/**
@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2018 Hippo Seven
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/primary_text_disabled_material_black" android:state_enabled="false" />
<item android:color="@color/primary_text_default_material_black" />
</selector>
+2 -2
View File
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="120dp"
android:height="120dp"
android:tint="?drawableColorSecondary"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?drawableColorSecondary">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
+2 -2
View File
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="120dp"
android:height="120dp"
android:tint="?drawableColorSecondary"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?drawableColorSecondary">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
+2 -2
View File
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="120dp"
android:height="120dp"
android:tint="?drawableColorSecondary"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?drawableColorSecondary">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="120dp"
android:height="120dp"
android:tint="?drawableColorSecondary"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?drawableColorSecondary">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -1,23 +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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/divider" />
<size android:height="1dp" />
</shape>
@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2018 Hippo Seven
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/divider_black" />
<size android:height="1dp" />
</shape>
@@ -1,10 +1,10 @@
<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"
android:tint="?attr/colorControlNormal">
<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"/>
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M12,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9s9,-4.03 9,-9c0,-0.46 -0.04,-0.92 -0.1,-1.36c-0.98,1.37 -2.58,2.26 -4.4,2.26c-2.98,0 -5.4,-2.42 -5.4,-5.4c0,-1.81 0.89,-3.42 2.26,-4.4C12.92,3.04 12.46,3 12,3L12,3z" />
</vector>
@@ -1,9 +1,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M2,17h2v0.5L3,17.5v1h1v0.5L2,19v1h3v-4L2,16v1zM3,8h1L4,4L2,4v1h1v3zM2,11h1.8L2,13.1v0.9h3v-1L3.2,13L5,10.9L5,10L2,10v1zM7,5v2h14L21,5L7,5zM7,19h14v-2L7,17v2zM7,13h14v-2L7,11v2z" />
@@ -1,9 +1,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M17.63,5.84C17.27,5.33 16.67,5 16,5L5,5.01C3.9,5.01 3,5.9 3,7v10c0,1.1 0.9,1.99 2,1.99L16,19c0.67,0 1.27,-0.33 1.63,-0.84L22,12l-4.37,-6.16z" />
@@ -1,10 +1,10 @@
<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"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z"/>
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z" />
</vector>
@@ -1,9 +1,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M3,15h18v-2L3,13v2zM3,19h18v-2L3,17v2zM3,11h18L21,9L3,9v2zM3,5v2h18L21,5L3,5z" />
@@ -1,9 +1,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z" />
@@ -9,12 +9,12 @@
android:translateX="35.1"
android:translateY="39.584126">
<path
android:pathData="M39.893,68.066L39.893,75.977L0,75.977L0,4.59L39.893,4.59L39.893,12.5L8.984,12.5L8.984,34.766L38.086,34.766L38.086,42.578L8.984,42.578L8.984,68.066L39.893,68.066Z"
android:fillColor="@color/ic_launcher_foreground"
android:fillType="evenOdd" />
android:fillType="evenOdd"
android:pathData="M39.893,68.066L39.893,75.977L0,75.977L0,4.59L39.893,4.59L39.893,12.5L8.984,12.5L8.984,34.766L38.086,34.766L38.086,42.578L8.984,42.578L8.984,68.066L39.893,68.066Z" />
<path
android:pathData="M99.609,75.977L90.918,75.977L90.918,41.699A23.436,23.436 0,0 0,90.662 38.109Q90.055,34.207 88.013,31.958Q85.629,29.334 81.028,28.863A20.84,20.84 0,0 0,78.906 28.76A23.134,23.134 0,0 0,74.45 29.16Q71.926,29.656 69.994,30.767A11.122,11.122 0,0 0,66.968 33.301A13.32,13.32 0,0 0,64.756 37.276Q63.399,40.971 63.213,46.495A53.517,53.517 0,0 0,63.184 48.291L63.184,75.977L54.395,75.977L54.395,0L63.184,0L63.184,22.266A66.935,66.935 0,0 1,63.115 25.383Q63.043,26.914 62.897,28.251A33.547,33.547 0,0 1,62.695 29.785L63.281,29.785A16.11,16.11 0,0 1,69.394 24.035A19.448,19.448 0,0 1,70.068 23.682A20.88,20.88 0,0 1,77.292 21.622A25.763,25.763 0,0 1,79.98 21.484A32.643,32.643 0,0 1,85.483 21.917Q91.249,22.905 94.678,26.147Q98.472,29.735 99.347,36.631A35.274,35.274 0,0 1,99.609 41.064L99.609,75.977Z"
android:fillColor="@color/ic_launcher_foreground"
android:fillType="evenOdd" />
android:fillType="evenOdd"
android:pathData="M99.609,75.977L90.918,75.977L90.918,41.699A23.436,23.436 0,0 0,90.662 38.109Q90.055,34.207 88.013,31.958Q85.629,29.334 81.028,28.863A20.84,20.84 0,0 0,78.906 28.76A23.134,23.134 0,0 0,74.45 29.16Q71.926,29.656 69.994,30.767A11.122,11.122 0,0 0,66.968 33.301A13.32,13.32 0,0 0,64.756 37.276Q63.399,40.971 63.213,46.495A53.517,53.517 0,0 0,63.184 48.291L63.184,75.977L54.395,75.977L54.395,0L63.184,0L63.184,22.266A66.935,66.935 0,0 1,63.115 25.383Q63.043,26.914 62.897,28.251A33.547,33.547 0,0 1,62.695 29.785L63.281,29.785A16.11,16.11 0,0 1,69.394 24.035A19.448,19.448 0,0 1,70.068 23.682A20.88,20.88 0,0 1,77.292 21.622A25.763,25.763 0,0 1,79.98 21.484A32.643,32.643 0,0 1,85.483 21.917Q91.249,22.905 94.678,26.147Q98.472,29.735 99.347,36.631A35.274,35.274 0,0 1,99.609 41.064L99.609,75.977Z" />
</group>
</vector>
+2 -2
View File
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_file_image" />
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?drawableColorThemePrimary"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?drawableColorThemePrimary">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:tint="@color/red_500"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/red_500">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:tint="?drawableColorThemePrimary"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?drawableColorThemePrimary">
android:viewportHeight="24.0">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?drawableColorThemePrimary"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?drawableColorThemePrimary">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_book_open" />
@@ -1,28 +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="48dp"
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?colorAccent">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_chart" />
</vector>
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_check_all" />
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_check" />
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_clear_all" />
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_close" />
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:tint="@color/brown_500"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/brown_500">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_cookie" />
+2 -2
View File
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_delete" />
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_dots_vertical" />
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_download_box" />
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?drawableColorThemePrimary"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?drawableColorThemePrimary">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
+2 -2
View File
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:tint="?android:attr/textColorSecondary"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/textColorSecondary">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
+2 -2
View File
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_download" />
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_eh_subscription" />
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:tint="?drawableColorThemePrimary"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?drawableColorThemePrimary">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -1,9 +1,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_folder_move" />
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_heart_broken" />
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:tint="?drawableColorThemePrimary"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?drawableColorThemePrimary">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:tint="?drawableColorThemePrimary"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?drawableColorThemePrimary">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
+2 -2
View File
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:tint="?android:attr/textColorSecondary"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/textColorSecondary">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
+2 -2
View File
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_heart" />
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_help_circle" />
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?drawableColorThemePrimary"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?drawableColorThemePrimary">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
+2 -2
View File
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_magnify" />
+2 -2
View File
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_pause" />
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
+2 -2
View File
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="@string/pd_play" />
@@ -17,9 +17,9 @@
<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"
android:tint="?attr/colorControlNormal">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
Loaded 100 of 172 files, more files were not shown because too many files have changed in this diff. Show more