From 25cddb2d6118eaee1605422fc4871fe611071b07 Mon Sep 17 00:00:00 2001 From: tarsin Date: Sun, 4 Dec 2022 12:43:44 +0800 Subject: [PATCH] Migrate to coil imageloader, Drop Conaco and BeerBelly as well TODO: Fix SimilarityScan --- app/build.gradle | 2 +- .../java/com/hippo/beerbelly/BeerBelly.java | 493 ------------------ .../main/java/com/hippo/conaco/Conaco.java | 223 -------- .../java/com/hippo/conaco/ConacoTask.java | 484 ----------------- .../com/hippo/conaco/ProgressNotifier.java | 22 - .../main/java/com/hippo/conaco/Register.java | 72 --- .../main/java/com/hippo/conaco/Unikery.java | 77 --- .../java/com/hippo/conaco/ValueCache.java | 61 --- .../java/com/hippo/conaco/ValueHelper.java | 55 -- .../com/hippo/drawable/UnikeryDrawable.java | 91 +--- .../com/hippo/ehviewer/EhApplication.java | 38 +- .../com/hippo/ehviewer/ImageBitmapHelper.java | 72 --- .../ui/scene/GalleryCommentsScene.java | 3 +- .../ehviewer/ui/scene/GalleryDetailScene.java | 8 +- .../main/java/com/hippo/image/ImageBitmap.kt | 67 --- .../java/com/hippo/text/URLImageGetter.kt | 5 +- .../java/com/hippo/widget/LoadImageView.java | 108 ++-- 17 files changed, 61 insertions(+), 1820 deletions(-) delete mode 100644 app/src/main/java/com/hippo/beerbelly/BeerBelly.java delete mode 100644 app/src/main/java/com/hippo/conaco/Conaco.java delete mode 100644 app/src/main/java/com/hippo/conaco/ConacoTask.java delete mode 100644 app/src/main/java/com/hippo/conaco/ProgressNotifier.java delete mode 100644 app/src/main/java/com/hippo/conaco/Register.java delete mode 100644 app/src/main/java/com/hippo/conaco/Unikery.java delete mode 100644 app/src/main/java/com/hippo/conaco/ValueCache.java delete mode 100644 app/src/main/java/com/hippo/conaco/ValueHelper.java delete mode 100644 app/src/main/java/com/hippo/ehviewer/ImageBitmapHelper.java delete mode 100644 app/src/main/java/com/hippo/image/ImageBitmap.kt diff --git a/app/build.gradle b/app/build.gradle index 1a67ae789..c0d7e75c2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -180,13 +180,13 @@ dependencies { implementation 'com.squareup.okhttp3:okhttp-bom:5.0.0-alpha.10' implementation 'com.squareup.okhttp3:okhttp' - implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps' implementation 'dev.rikka.rikkax.core:core-ktx:1.4.1' implementation 'dev.rikka.rikkax.insets:insets:1.3.0' implementation 'dev.rikka.rikkax.layoutinflater:layoutinflater:1.2.0' implementation 'dev.rikka.rikkax.preference:simplemenu-preference:1.0.3' implementation 'dev.rikka.rikkax.material:material-preference:2.0.0' + implementation 'io.coil-kt:coil:2.2.2' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4' implementation 'org.jsoup:jsoup:1.15.3' } diff --git a/app/src/main/java/com/hippo/beerbelly/BeerBelly.java b/app/src/main/java/com/hippo/beerbelly/BeerBelly.java deleted file mode 100644 index 7e41763e5..000000000 --- a/app/src/main/java/com/hippo/beerbelly/BeerBelly.java +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright (C) 2015-2016 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.beerbelly; - -import android.util.Log; -import android.util.LruCache; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.hippo.streampipe.InputStreamPipe; -import com.hippo.streampipe.OutputStreamPipe; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -public abstract class BeerBelly { - - private static final String TAG = BeerBelly.class.getSimpleName(); - private final boolean mHasMemoryCache; - private final boolean mHasDiskCache; - @Nullable - private MemoryCache mMemoryCache; - @Nullable - private DiskCache mDiskCache; - - public BeerBelly(BeerBellyParams params) { - params.isValid(); - mHasMemoryCache = params.hasMemoryCache; - mHasDiskCache = params.hasDiskCache; - - if (mHasMemoryCache) { - initMemoryCache(params.memoryCacheMaxSize); - } - - if (mHasDiskCache) { - initDiskCache(params.diskCacheDir, params.diskCacheMaxSize); - } - } - - private void initMemoryCache(int maxSize) { - mMemoryCache = new MemoryCache<>(maxSize, this); - } - - private void initDiskCache(File cacheDir, int maxSize) { - // Set up disk cache - try { - mDiskCache = new DiskCache<>(cacheDir, maxSize, this); - } catch (IOException e) { - Log.e(TAG, "Can't create disk cache", e); - } - } - - protected abstract int sizeOf(String key, V value); - - protected abstract void memoryEntryAdded(V value); - - protected abstract void memoryEntryRemoved(boolean evicted, String key, V oldValue, V newValue); - - protected abstract V read(@NonNull InputStreamPipe isPipe); - - protected abstract boolean write(OutputStream os, V value); - - @Nullable - public LruCache getMemoryCache() { - return mMemoryCache; - } - - @Nullable - public SimpleDiskCache getDiskCache() { - if (mDiskCache != null) { - return mDiskCache.mDiskCache; - } else { - return null; - } - } - - /** - * Check if have memory cache - * - * @return true if have memory cache - */ - public boolean hasMemoryCache() { - return mHasMemoryCache; - } - - /** - * Check if have disk cache - * - * @return true if have disk cache - */ - public boolean hasDiskCache() { - return mHasDiskCache; - } - - /** - * Get memory cache usage size - * - * @return {@code -1} for no memory cache - */ - public int memorySize() { - if (mHasMemoryCache && mMemoryCache != null) { - return mMemoryCache.size(); - } else { - return -1; - } - } - - /** - * Get memory cache max size - * - * @return {@code -1} for no memory cache - */ - public int memoryMaxSize() { - if (mHasMemoryCache && mMemoryCache != null) { - return mMemoryCache.maxSize(); - } else { - return -1; - } - } - - /** - * Get disk cache usage size - * - * @return {@code -1L} for no memory cache - */ - public long diskSize() { - if (mHasDiskCache && mDiskCache != null) { - return mDiskCache.size(); - } else { - return -1L; - } - } - - /** - * Get disk cache max size - * - * @return {@code -1L} for no memory cache - */ - public long diskMaxSize() { - if (mHasDiskCache && mDiskCache != null) { - return mDiskCache.getMaxSize(); - } else { - return -1L; - } - } - - /** - * Get value from memory cache - * - * @param key the key to get value - * @return the value you get, null for miss or no memory cache - */ - public V getFromMemory(@NonNull String key) { - if (mHasMemoryCache && mMemoryCache != null) { - return mMemoryCache.get(key); - } else { - return null; - } - } - - /** - * Get value from disk cache. Override {@link #read(InputStreamPipe)} to do it - * - * @param key the key to get value - * @return the value you get, null for miss or no memory cache or get error - */ - public V getFromDisk(@NonNull String key) { - if (mHasDiskCache && mDiskCache != null) { - return mDiskCache.get(key); - } else { - return null; - } - } - - /** - * Get value from memory cache and disk cache. If miss in memory cache and - * get in disk cache, it will put value from disk cache to memory cache. - * - * @param key the key to get value - * @return the value you get - */ - public V get(@NonNull String key) { - V value = getFromMemory(key); - - if (value != null) { - // Get it in memory cache - return value; - } - - value = getFromDisk(key); - - if (value != null) { - // Get it in disk cache - putToMemory(key, value); - return value; - } - - return null; - } - - /** - * Put value to memory cache - * - * @param key the key - * @param value the value - * @return false if no memory cache - */ - public boolean putToMemory(@NonNull String key, @NonNull V value) { - if (mHasMemoryCache && mMemoryCache != null) { - memoryEntryAdded(value); - mMemoryCache.put(key, value); - return true; - } else { - return false; - } - } - - /** - * Put value to disk cache - * - * @param key the key - * @param value the value - * @return false if no disk cache or get error - */ - public boolean putToDisk(@NonNull String key, @NonNull V value) { - if (mHasDiskCache && mDiskCache != null) { - return mDiskCache.put(key, value); - } else { - return false; - } - } - - /** - * Put value to memory cache and disk cache - * - * @param key the key - * @param value the value - */ - public void put(@NonNull String key, @NonNull V value) { - putToMemory(key, value); - putToDisk(key, value); - } - - public void removeFromMemory(@NonNull String key) { - if (mHasMemoryCache && mMemoryCache != null) { - mMemoryCache.remove(key); - } - } - - public void removeFromDisk(@NonNull String key) { - if (mHasDiskCache && mDiskCache != null) { - mDiskCache.remove(key); - } - } - - public void remove(@NonNull String key) { - removeFromMemory(key); - removeFromDisk(key); - } - - public boolean pullFromDiskCache(@NonNull String key, @NonNull OutputStream os) { - if (mHasDiskCache && mDiskCache != null) { - return mDiskCache.pull(key, os); - } else { - return false; - } - } - - /** - * @param key the key - * @param is the input stream to store - * @return false if no disk cache or get error - */ - public boolean putRawToDisk(@NonNull String key, @NonNull InputStream is) { - if (mHasDiskCache && mDiskCache != null) { - return mDiskCache.putRaw(key, is); - } else { - return false; - } - } - - /** - * Evicts all of the items from the memory cache - */ - public void clearMemory() { - if (mHasMemoryCache && mMemoryCache != null) { - mMemoryCache.evictAll(); - } - } - - /** - * Clear disk cache - */ - public void clearDisk() { - if (mHasDiskCache && mDiskCache != null) { - mDiskCache.clear(); - } - } - - public void flush() { - if (mHasDiskCache && mDiskCache != null) { - mDiskCache.flush(); - } - } - - /** - * Evicts all of the items from the memory cache and lets the system know - * now would be a good time to garbage collect - */ - public void clear() { - clearMemory(); - clearDisk(); - } - - /** - * A holder class that contains cache parameters. - */ - public static class BeerBellyParams { - - /** - * is memory cache available - */ - public boolean hasMemoryCache = false; - /** - * the maximum number of bytes the memory cache should use to store - */ - public int memoryCacheMaxSize = 0; - /** - * is disk cache available - */ - public boolean hasDiskCache = false; - /** - * the dir to store disk cache - */ - public File diskCacheDir = null; - /** - * the maximum number of bytes the disk cache should use to store - */ - public int diskCacheMaxSize = 0; - - /** - * Check BeerBellyParams is valid - */ - public void isValid() throws IllegalStateException { - if (!hasMemoryCache && !hasDiskCache) { - throw new IllegalStateException("No memory cache and no disk cache. What can I do for you?"); - } - - if (hasMemoryCache && memoryCacheMaxSize <= 0) { - throw new IllegalStateException("Memory cache max size must be bigger than 0."); - } - - if (hasDiskCache) { - if (diskCacheDir == null) { - throw new IllegalStateException("Disk cache dir can't be null."); - } - if (diskCacheMaxSize <= 0) { - throw new IllegalStateException("Disk cache max size must be bigger than 0."); - } - } - } - } - - private static class DiskCache { - - private static final int IO_BUFFER_SIZE = 8 * 1024; - - private final SimpleDiskCache mDiskCache; - private final BeerBelly mParent; - - private final File mCacheDir; - private final int mMaxSize; - - public DiskCache(File cacheDir, int size, BeerBelly parent) throws IOException { - mDiskCache = new SimpleDiskCache(cacheDir, size); - mParent = parent; - - mCacheDir = cacheDir; - mMaxSize = size; - } - - public File getCacheDir() { - return mCacheDir; - } - - public int getMaxSize() { - return mMaxSize; - } - - public long size() { - return mDiskCache.size(); - } - - public void flush() { - mDiskCache.flush(); - } - - public void clear() { - mDiskCache.clear(); - } - - public E get(String key) { - InputStreamPipe isPipe = mDiskCache.getInputStreamPipe(key); - if (isPipe == null) { - return null; - } else { - return mParent.read(isPipe); - } - } - - public boolean put(String key, E value) { - OutputStreamPipe osPipe = mDiskCache.getOutputStreamPipe(key); - BufferedOutputStream buffOut = null; - try { - osPipe.obtain(); - OutputStream os = osPipe.open(); - buffOut = new BufferedOutputStream(os, IO_BUFFER_SIZE); - return mParent.write(os, value); - } catch (IOException e) { - return false; - } finally { - Util.closeQuietly(buffOut); - osPipe.close(); - osPipe.release(); - } - } - - public boolean putRaw(String key, InputStream is) { - return mDiskCache.put(key, is); - } - - public void remove(String key) { - mDiskCache.remove(key); - } - - public boolean pull(@NonNull String key, @NonNull OutputStream os) { - InputStreamPipe isPipe = mDiskCache.getInputStreamPipe(key); - if (isPipe == null) { - return false; - } else { - try { - isPipe.obtain(); - InputStream is = isPipe.open(); - Util.copy(is, os); - return true; - } catch (IOException e) { - return false; - } finally { - isPipe.close(); - isPipe.release(); - } - } - } - } - - private class MemoryCache extends LruCache { - - public BeerBelly mParent; - - public MemoryCache(int maxSize, BeerBelly parent) { - super(maxSize); - mParent = parent; - } - - @Override - protected int sizeOf(String key, E value) { - return mParent.sizeOf(key, value); - } - - @Override - protected void entryRemoved(boolean evicted, String key, E oldValue, E newValue) { - mParent.memoryEntryRemoved(evicted, key, oldValue, newValue); - } - } -} diff --git a/app/src/main/java/com/hippo/conaco/Conaco.java b/app/src/main/java/com/hippo/conaco/Conaco.java deleted file mode 100644 index 8b4ebd99b..000000000 --- a/app/src/main/java/com/hippo/conaco/Conaco.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2015-2016 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.conaco; - -import android.os.Process; -import android.util.Log; - -import androidx.annotation.IntDef; -import androidx.annotation.UiThread; - -import com.hippo.beerbelly.BeerBelly; -import com.hippo.yorozuya.thread.PriorityThreadFactory; -import com.hippo.yorozuya.thread.SerialThreadExecutor; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.LinkedList; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import okhttp3.OkHttpClient; - -@SuppressWarnings("rawtypes") -public final class Conaco { - - 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 mHelper; - private final ValueCache mCache; - private final OkHttpClient mOkHttpClient; - private final Register mRegister; - private final SerialThreadExecutor mDiskExecutor; - private final ThreadPoolExecutor mNetworkExecutor; - private final AtomicInteger mIdGenerator; - private final boolean mDebug; - - private Conaco(Builder builder) { - mHelper = builder.objectHelper; - - BeerBelly.BeerBellyParams beerBellyParams = new BeerBelly.BeerBellyParams(); - beerBellyParams.hasMemoryCache = builder.hasMemoryCache; - beerBellyParams.memoryCacheMaxSize = builder.memoryCacheMaxSize; - beerBellyParams.hasDiskCache = builder.hasDiskCache; - beerBellyParams.diskCacheDir = builder.diskCacheDir; - beerBellyParams.diskCacheMaxSize = builder.diskCacheMaxSize; - - mCache = new ValueCache<>(beerBellyParams, mHelper); - mOkHttpClient = builder.okHttpClient; - - mRegister = new Register<>(); - - mDiskExecutor = new SerialThreadExecutor(3000L, new LinkedList<>(), - new PriorityThreadFactory("Conaco-Disk", Process.THREAD_PRIORITY_BACKGROUND)); - mNetworkExecutor = new ThreadPoolExecutor(3, 3, 5L, TimeUnit.SECONDS, - new LinkedBlockingQueue<>(), - new PriorityThreadFactory("Conaco-Network", Process.THREAD_PRIORITY_BACKGROUND)); - - mIdGenerator = new AtomicInteger(); - - mDebug = builder.debug; - } - - public BeerBelly getBeerBelly() { - return mCache; - } - - private void onUnregisterConacoTask(ConacoTask task) { - ConacoTask next = mRegister.getByKey(task.getKey()); - if (next != null) { - startConacoTask(next); - } - } - - private void startConacoTask(ConacoTask task) { - Unikery unikery = task.getUnikery(); - - // Can't unikery is gone, finish the task now - if (unikery == null) { - finishConacoTask(task); - return; - } - - String key = task.getKey(); - V value = null; - - // Get from memory - if (key != null && task.useMemoryCache() && mHelper.useMemoryCache(key, null)) { - value = mCache.getFromMemory(key); - } - - if (value == null || !unikery.onGetValue(value, SOURCE_MEMORY)) { - unikery.onMiss(SOURCE_MEMORY); - task.start(); - } else { - // Get the object, finish the task - finishConacoTask(task); - } - } - - @UiThread - public void load(ConacoTask.Builder builder) { - builder.isValid(); - - if (mDebug) { - Log.d(TAG, "Key " + builder.getKey()); - Log.d(TAG, "Url " + builder.getUrl()); - } - - Unikery unikery = builder.getUnikery(); - - // Cancel first - cancel(unikery); - - // Build conaco task - int id; - //noinspection StatementWithEmptyBody - while ((id = mIdGenerator.getAndIncrement()) == Unikery.INVALID_ID) ; - unikery.setTaskId(id); - builder.setId(id) - .setHelper(mHelper) - .setCache(mCache) - .setOkHttpClient(mOkHttpClient) - .setDiskExecutor(mDiskExecutor) - .setNetworkExecutor(mNetworkExecutor) - .setConaco(this); - ConacoTask task = builder.build(); - - if (!mRegister.register(id, task)) { - startConacoTask(task); - } else { - // The key is repeated, wait - unikery.onWait(); - } - } - - @UiThread - public void cancel(Unikery unikery) { - int id = unikery.getTaskId(); - if (id != Unikery.INVALID_ID) { - unikery.setTaskId(Unikery.INVALID_ID); - ConacoTask task = mRegister.unregister(id); - if (task != null) { - task.stop(); - // Don't need unikery anymore - task.clearUnikery(); - // Callback - onUnregisterConacoTask(task); - } else { - Log.e(TAG, "Can't find conaco task by id " + id); - } - } - } - - public boolean isLoading(Unikery unikery) { - int id = unikery.getTaskId(); - return id != Unikery.INVALID_ID && mRegister.contain(id); - } - - /** - * Unregister task, reset unikery id, clear unikery in task, call next - */ - void finishConacoTask(ConacoTask task) { - mRegister.unregister(task.getId()); - Unikery unikery = task.getUnikery(); - if (unikery != null) { - unikery.setTaskId(Unikery.INVALID_ID); - } - task.clearUnikery(); - - onUnregisterConacoTask(task); - } - - @IntDef({SOURCE_MEMORY, SOURCE_DISK, SOURCE_NETWORK}) - @Retention(RetentionPolicy.SOURCE) - public @interface Source { - } - - public static class Builder extends BeerBelly.BeerBellyParams { - /** - * The client to get image from internet - */ - public OkHttpClient okHttpClient = null; - - /** - * Decode, get size and others - */ - public ValueHelper objectHelper = null; - - public boolean debug = false; - - @Override - public void isValid() throws IllegalStateException { - super.isValid(); - - if (okHttpClient == null) { - throw new IllegalStateException("No http client? How can I load image via url?"); - } - } - - public Conaco build() { - isValid(); - return new Conaco<>(this); - } - } -} diff --git a/app/src/main/java/com/hippo/conaco/ConacoTask.java b/app/src/main/java/com/hippo/conaco/ConacoTask.java deleted file mode 100644 index 629f97cae..000000000 --- a/app/src/main/java/com/hippo/conaco/ConacoTask.java +++ /dev/null @@ -1,484 +0,0 @@ -/* - * Copyright 2015-2016 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.conaco; - -import android.annotation.SuppressLint; -import android.os.AsyncTask; -import android.util.Log; - -import androidx.annotation.Nullable; -import androidx.annotation.UiThread; - -import com.hippo.beerbelly.SimpleDiskCache; -import com.hippo.okhttp.ChromeRequestBuilder; -import com.hippo.streampipe.OutputStreamPipe; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.ref.WeakReference; -import java.util.concurrent.Executor; - -import okhttp3.Call; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import okhttp3.ResponseBody; - -@SuppressWarnings({"rawtypes", "deprecation"}) -public final class ConacoTask { - - private static final String TAG = ConacoTask.class.getSimpleName(); - - private final int mId; - private final WeakReference> mUnikeryWeakReference; - private final String mKey; - private final String mUrl; - private final boolean mUseMemoryCache; - private final boolean mUseDiskCache; - private final boolean mUseNetwork; - private final ValueHelper mHelper; - private final ValueCache mCache; - private final OkHttpClient mOkHttpClient; - private final Executor mDiskExecutor; - private final Executor mNetworkExecutor; - private final Conaco mConaco; - - private DiskLoadTask mDiskLoadTask; - private NetworkLoadTask mNetworkLoadTask; - private Call mCall; - private boolean mStart; - private volatile boolean mStop; - - private ConacoTask(Builder builder) { - mId = builder.mId; - mUnikeryWeakReference = new WeakReference<>(builder.mUnikery); - mKey = builder.mKey; - mUrl = builder.mUrl; - mUseMemoryCache = builder.mUseMemoryCache; - mUseDiskCache = builder.mUseDiskCache; - mUseNetwork = builder.mUseNetwork; - mHelper = builder.mHelper; - mCache = builder.mCache; - mOkHttpClient = builder.mOkHttpClient; - mDiskExecutor = builder.mDiskExecutor; - mNetworkExecutor = builder.mNetworkExecutor; - mConaco = builder.mConaco; - } - - int getId() { - return mId; - } - - String getKey() { - return mKey; - } - - boolean useMemoryCache() { - return mUseMemoryCache; - } - - @Nullable - Unikery getUnikery() { - return mUnikeryWeakReference.get(); - } - - void clearUnikery() { - mUnikeryWeakReference.clear(); - } - - private void onFinish() { - if (!mStop) { - mConaco.finishConacoTask(this); - }/* else { - // It is done by Conaco - }*/ - } - - @UiThread - void start() { - if (mStop || mStart) { - return; - } - - mStart = true; - - Unikery unikery = mUnikeryWeakReference.get(); - if (unikery != null && unikery.getTaskId() == mId) { - if (mUseDiskCache) { - mDiskLoadTask = new DiskLoadTask(); - mDiskLoadTask.executeOnExecutor(mDiskExecutor); - return; - } else if (mUseNetwork) { - unikery.onMiss(Conaco.SOURCE_DISK); - unikery.onRequest(); - mNetworkLoadTask = new NetworkLoadTask(); - mNetworkLoadTask.executeOnExecutor(mNetworkExecutor); - return; - } else { - unikery.onMiss(Conaco.SOURCE_DISK); - unikery.onMiss(Conaco.SOURCE_NETWORK); - unikery.onFailure(); - } - } - - onFinish(); - } - - @UiThread - void stop() { - if (mStop) { - return; - } - - mStop = true; - - // Stop jobs - if (mDiskLoadTask != null) { // Getting from disk - mDiskLoadTask.cancel(false); - } else if (mNetworkLoadTask != null) { // Getting from network - mNetworkLoadTask.cancel(false); - if (mCall != null) { - mCall = null; - } - } - - Unikery unikery = mUnikeryWeakReference.get(); - if (unikery != null) { - unikery.onCancel(); - } - - // Conaco handle the clean up - } - - private boolean isNotNecessary(AsyncTask asyncTask) { - Unikery unikery = mUnikeryWeakReference.get(); - return mStop || asyncTask.isCancelled() || unikery == null || unikery.getTaskId() != mId; - } - - @SuppressWarnings({"unused", "UnusedReturnValue", "RedundantSuppression"}) - public static class Builder { - - private int mId; - private Unikery mUnikery; - private String mKey; - private String mUrl; - private boolean mUseMemoryCache = true; - private boolean mUseDiskCache = true; - private boolean mUseNetwork = true; - private ValueHelper mHelper; - private ValueCache mCache; - private OkHttpClient mOkHttpClient; - private Executor mDiskExecutor; - private Executor mNetworkExecutor; - private Conaco mConaco; - - public Builder setId(int id) { - mId = id; - return this; - } - - public Unikery getUnikery() { - return mUnikery; - } - - public Builder setUnikery(Unikery unikery) { - mUnikery = unikery; - return this; - } - - public String getKey() { - return mKey; - } - - public Builder setKey(String key) { - mKey = key; - return this; - } - - public String getUrl() { - return mUrl; - } - - public Builder setUrl(String url) { - mUrl = url; - return this; - } - - boolean isUseMemoryCache() { - return mUseMemoryCache; - } - - public Builder setUseMemoryCache(boolean useMemoryCache) { - mUseMemoryCache = useMemoryCache; - return this; - } - - boolean isUseDiskCache() { - return mUseDiskCache; - } - - public Builder setUseDiskCache(boolean useDiskCache) { - mUseDiskCache = useDiskCache; - return this; - } - - boolean isUseNetwork() { - return mUseNetwork; - } - - public Builder setUseNetwork(boolean useNetwork) { - mUseNetwork = useNetwork; - return this; - } - - ValueHelper getHelper() { - return mHelper; - } - - Builder setHelper(ValueHelper helper) { - mHelper = helper; - return this; - } - - Builder setCache(ValueCache cache) { - mCache = cache; - return this; - } - - Builder setOkHttpClient(OkHttpClient okHttpClient) { - mOkHttpClient = okHttpClient; - return this; - } - - Builder setDiskExecutor(Executor diskExecutor) { - mDiskExecutor = diskExecutor; - return this; - } - - Builder setNetworkExecutor(Executor networkExecutor) { - mNetworkExecutor = networkExecutor; - return this; - } - - Builder setConaco(Conaco conaco) { - mConaco = conaco; - return this; - } - - public void isValid() { - if (mUnikery == null) { - throw new IllegalStateException("Must set unikery"); - } - if (mKey == null && mUrl == null) { - throw new IllegalStateException("At least one of mKey and mUrl and mDataContainer have to not be null"); - } - } - - public ConacoTask build() { - return new ConacoTask<>(this); - } - } - - @SuppressLint("StaticFieldLeak") - private class DiskLoadTask extends AsyncTask { - - @Override - protected V doInBackground(Void... params) { - if (isNotNecessary(this)) { - return null; - } else { - V value = null; - - // Then check disk cache - if (mKey != null) { - if (value == null && mUseDiskCache) { - value = mCache.getFromDisk(mKey); - } - - if (value != null && mUseMemoryCache && mHelper.useMemoryCache(mKey, value)) { - mCache.putToMemory(mKey, value); - } - } - - return value; - } - } - - @Override - protected void onPostExecute(V value) { - mDiskLoadTask = null; - - if (isCancelled() || mStop) { - onCancelled(value); - } else { - Unikery unikery = mUnikeryWeakReference.get(); - if (unikery != null && unikery.getTaskId() == mId) { - boolean getValue = false; - if ((value == null || !(getValue = unikery.onGetValue(value, Conaco.SOURCE_DISK))) && mUseNetwork) { - unikery.onMiss(Conaco.SOURCE_DISK); - unikery.onRequest(); - mNetworkLoadTask = new NetworkLoadTask(); - mNetworkLoadTask.executeOnExecutor(mNetworkExecutor); - return; - } else if (!getValue) { - unikery.onMiss(Conaco.SOURCE_DISK); - unikery.onFailure(); - } - } - onFinish(); - } - } - - @Override - protected void onCancelled(V holder) { - onFinish(); - } - } - - @SuppressLint("StaticFieldLeak") - private class NetworkLoadTask extends AsyncTask implements ProgressNotifier { - - @Override - public void notifyProgress(long singleReceivedSize, long receivedSize, long totalSize) { - if (!isNotNecessary(this)) { - publishProgress(singleReceivedSize, receivedSize, totalSize); - } - } - - private boolean putToDiskCache(InputStream is, long length) { - SimpleDiskCache diskCache = mCache.getDiskCache(); - if (diskCache == null) { - return false; - } - - OutputStreamPipe pipe = diskCache.getOutputStreamPipe(mKey); - try { - pipe.obtain(); - OutputStream os = pipe.open(); - - final byte[] buffer = new byte[1024 * 4]; - long receivedSize = 0; - int bytesRead; - - while ((bytesRead = is.read(buffer)) != -1) { - os.write(buffer, 0, bytesRead); - receivedSize += bytesRead; - notifyProgress(bytesRead, receivedSize, length); - } - - return true; - } catch (IOException e) { - return false; - } finally { - pipe.close(); - pipe.release(); - } - } - - @Override - protected V doInBackground(Void... params) { - if (isNotNecessary(this)) { - return null; - } - - V value; - InputStream is = null; - try { - Log.d("TAG", "Conaco " + mUrl); - - // Load it from internet - Request request = new ChromeRequestBuilder(mUrl).build(); - mCall = mOkHttpClient.newCall(request); - - Response response = mCall.execute(); - ResponseBody body = response.body(); - if (body == null) { - return null; - } - is = body.byteStream(); - - if (isNotNecessary(this)) { - return null; - } - - if (mKey != null) { - if (putToDiskCache(is, body.contentLength())) { - // Get object from disk cache - value = mCache.getFromDisk(mKey); - if (value == null) { - // Maybe bad download, remove it from disk cache - mCache.removeFromDisk(mKey); - } else if (mUseMemoryCache && mHelper.useMemoryCache(mKey, value)) { - // Put it to memory - mCache.putToMemory(mKey, value); - } - return value; - } else { - // Maybe bad download, remove it from disk cache - mCache.removeFromDisk(mKey); - return null; - } - } else { - return null; - } - } catch (Exception e) { - e.printStackTrace(); - return null; - } finally { - mCall = null; - try { - if (is != null) { - is.close(); - } - } catch (IOException e) { - // Ignore - } - } - } - - @Override - protected void onPostExecute(V holder) { - mNetworkLoadTask = null; - - if (isCancelled() || mStop) { - onCancelled(holder); - } else { - Unikery unikery = mUnikeryWeakReference.get(); - if (unikery != null && unikery.getTaskId() == mId) { - if (holder == null || !unikery.onGetValue(holder, Conaco.SOURCE_NETWORK)) { - unikery.onFailure(); - } - } - onFinish(); - } - } - - @Override - protected void onCancelled(V value) { - onFinish(); - } - - @Override - protected void onProgressUpdate(Long... values) { - Unikery unikery = mUnikeryWeakReference.get(); - if (!mStop && !isCancelled() && unikery != null && unikery.getTaskId() == mId) { - unikery.onProgress(values[0], values[1], values[2]); - } - } - } -} diff --git a/app/src/main/java/com/hippo/conaco/ProgressNotifier.java b/app/src/main/java/com/hippo/conaco/ProgressNotifier.java deleted file mode 100644 index ff4af1648..000000000 --- a/app/src/main/java/com/hippo/conaco/ProgressNotifier.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2015 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.conaco; - -public interface ProgressNotifier { - - void notifyProgress(long singleReceivedSize, long receivedSize, long totalSize); -} diff --git a/app/src/main/java/com/hippo/conaco/Register.java b/app/src/main/java/com/hippo/conaco/Register.java deleted file mode 100644 index d6c983951..000000000 --- a/app/src/main/java/com/hippo/conaco/Register.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2016 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.conaco; - -import com.hippo.yorozuya.collect.Multimap; -import com.hippo.yorozuya.collect.SparseILArray; - -import java.util.List; - -class Register { - - private final SparseILArray> mIdMap = new SparseILArray<>(); - private final Multimap> mKeyMap = Multimap.create(); - - /** - * @return true for the key is already registered - */ - public synchronized boolean register(int id, ConacoTask task) { - boolean repeatedKey = false; - String taskKey = task.getKey(); - - // For no-key task, there no need to check - if (taskKey != null) { - repeatedKey = mKeyMap.countElements(taskKey) != 0; - } - - // Append task - mKeyMap.putElement(taskKey, task); - mIdMap.append(id, task); - - return repeatedKey; - } - - public synchronized ConacoTask unregister(int id) { - ConacoTask task = mIdMap.remove(id); - if (task != null) { - mKeyMap.removeElement(task.getKey(), task); - } - return task; - } - - public synchronized boolean contain(int id) { - return mIdMap.indexOfKey(id) >= 0; - } - - public synchronized ConacoTask getByKey(String key) { - if (key == null) { - return null; - } - - List> list = mKeyMap.get(key); - if (list != null && list.size() > 0) { - return list.get(0); - } else { - return null; - } - } -} diff --git a/app/src/main/java/com/hippo/conaco/Unikery.java b/app/src/main/java/com/hippo/conaco/Unikery.java deleted file mode 100644 index 1d73f1227..000000000 --- a/app/src/main/java/com/hippo/conaco/Unikery.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2015 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.conaco; - -import androidx.annotation.NonNull; - -public interface Unikery { - - int INVALID_ID = -1; - - /** - * Get the conaco task id - * - * @return the conaco task id - */ - int getTaskId(); - - /** - * Store the conaco task id - * - * @param id the conaco task id - */ - void setTaskId(int id); - - /** - * On miss in the source - */ - void onMiss(@Conaco.Source int source); - - /** - * On start http request - */ - void onRequest(); - - /** - * On http request progress - */ - void onProgress(long singleReceivedSize, long receivedSize, long totalSize); - - /** - * On start to wait because repeated key - */ - void onWait(); - - /** - * On get the value - * - * @return {@code true} for the {@code Unikery} accepts the value - * and the task ends. {@code false} for the {@code Unikery} - * reject the value and the task goes on or failed - */ - boolean onGetValue(@NonNull V value, @Conaco.Source int source); - - /** - * On failed to get value - */ - void onFailure(); - - /** - * On user cancel the conaco task - */ - void onCancel(); -} diff --git a/app/src/main/java/com/hippo/conaco/ValueCache.java b/app/src/main/java/com/hippo/conaco/ValueCache.java deleted file mode 100644 index d9b75d5b1..000000000 --- a/app/src/main/java/com/hippo/conaco/ValueCache.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2016 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.conaco; - -import androidx.annotation.NonNull; - -import com.hippo.beerbelly.BeerBelly; -import com.hippo.streampipe.InputStreamPipe; - -import java.io.OutputStream; - -class ValueCache extends BeerBelly { - - private final ValueHelper mHelper; - - public ValueCache(BeerBelly.BeerBellyParams params, ValueHelper helper) { - super(params); - mHelper = helper; - } - - @Override - protected int sizeOf(String key, V value) { - return mHelper.sizeOf(key, value); - } - - @Override - protected void memoryEntryAdded(V value) { - mHelper.onAddToMemoryCache(value); - } - - @Override - protected void memoryEntryRemoved(boolean evicted, String key, V oldValue, V newValue) { - if (oldValue != null) { - mHelper.onRemoveFromMemoryCache(key, oldValue); - } - } - - @Override - protected V read(@NonNull InputStreamPipe isPipe) { - return mHelper.decode(isPipe); - } - - @Override - protected boolean write(OutputStream os, V value) { - throw new UnsupportedOperationException("Not support write object"); - } -} diff --git a/app/src/main/java/com/hippo/conaco/ValueHelper.java b/app/src/main/java/com/hippo/conaco/ValueHelper.java deleted file mode 100644 index f2f39d323..000000000 --- a/app/src/main/java/com/hippo/conaco/ValueHelper.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2016 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.conaco; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.hippo.streampipe.InputStreamPipe; - -public interface ValueHelper { - - /** - * Decode object for the {@code InputStreamPipe} - * - * @param isPipe the {@code InputStreamPipe} - * @return the decoded object - */ - @Nullable - V decode(@NonNull InputStreamPipe isPipe); - - /** - * Get the size of the object - */ - int sizeOf(@NonNull String key, @NonNull V value); - - /** - * Called when the object added to memory cache - */ - void onAddToMemoryCache(@NonNull V oldValue); - - /** - * Called when the object removed from memory cache - */ - void onRemoveFromMemoryCache(@NonNull String key, @NonNull V oldValue); - - /** - * Use cache memory or not. Sometimes large object - * should not be stored in memory cache. - */ - boolean useMemoryCache(@NonNull String key, V holder); -} diff --git a/app/src/main/java/com/hippo/drawable/UnikeryDrawable.java b/app/src/main/java/com/hippo/drawable/UnikeryDrawable.java index efdddb61a..25054cd00 100644 --- a/app/src/main/java/com/hippo/drawable/UnikeryDrawable.java +++ b/app/src/main/java/com/hippo/drawable/UnikeryDrawable.java @@ -18,31 +18,23 @@ package com.hippo.drawable; import android.graphics.drawable.AnimatedImageDrawable; import android.graphics.drawable.Drawable; -import android.util.Log; -import androidx.annotation.NonNull; - -import com.hippo.conaco.Conaco; -import com.hippo.conaco.ConacoTask; -import com.hippo.conaco.Unikery; -import com.hippo.image.ImageBitmap; import com.hippo.widget.ObservedTextView; -public class UnikeryDrawable extends WrapDrawable implements Unikery, - ObservedTextView.OnWindowAttachListener { +import coil.Coil; +import coil.request.Disposable; +import coil.request.ImageRequest; + +public class UnikeryDrawable extends WrapDrawable implements ObservedTextView.OnWindowAttachListener { private static final String TAG = UnikeryDrawable.class.getSimpleName(); private final ObservedTextView mTextView; - private final Conaco mConaco; - private int mTaskId = Unikery.INVALID_ID; private String mUrl; + private Disposable task; - private ImageBitmap imageBitmap; - - public UnikeryDrawable(ObservedTextView textView, Conaco conaco) { + public UnikeryDrawable(ObservedTextView textView) { mTextView = textView; mTextView.setOnWindowAttachListener(this); - mConaco = conaco; } @Override @@ -52,23 +44,29 @@ public class UnikeryDrawable extends WrapDrawable implements Unikery().setUnikery(this).setUrl(url).setKey(url)); + var imageLoader = Coil.imageLoader(mTextView.getContext()); + var request = new ImageRequest.Builder(mTextView.getContext()).data(url).memoryCacheKey(url).diskCacheKey(url).target( + drawable -> null, + drawable -> null, + drawable -> { + onGetValue(drawable); + return null; + } + ).build(); + task = imageLoader.enqueue(request); } } private void clearDrawable() { setDrawable(null); - if (imageBitmap != null) { - imageBitmap.release(); - imageBitmap = null; - } } @Override @@ -91,65 +89,16 @@ public class UnikeryDrawable extends WrapDrawable implements Unikery mConaco; private LruCache mGalleryDetailCache; private SimpleDiskCache mSpiderInfoCache; private DownloadManager mDownloadManager; @@ -200,37 +198,10 @@ public class EhApplication extends SceneApplication { return application.mOkHttpCache; } - @NonNull - public static ImageBitmapHelper getImageBitmapHelper(@NonNull Context context) { - EhApplication application = ((EhApplication) context.getApplicationContext()); - if (application.mImageBitmapHelper == null) { - application.mImageBitmapHelper = new ImageBitmapHelper(); - } - return application.mImageBitmapHelper; - } - private static int getMemoryCacheMaxSize() { return Math.min(20 * 1024 * 1024, (int) OSUtils.getAppMaxMemory()); } - @NonNull - public static Conaco getConaco(@NonNull Context context) { - EhApplication application = ((EhApplication) context.getApplicationContext()); - if (application.mConaco == null) { - Conaco.Builder builder = new Conaco.Builder<>(); - builder.hasMemoryCache = true; - builder.memoryCacheMaxSize = getMemoryCacheMaxSize(); - builder.hasDiskCache = true; - builder.diskCacheDir = new File(context.getCacheDir(), "thumb"); - builder.diskCacheMaxSize = 320 * 1024 * 1024; // 320MB - builder.okHttpClient = getOkHttpClient(context); - builder.objectHelper = getImageBitmapHelper(context); - builder.debug = DEBUG_CONACO; - application.mConaco = builder.build(); - } - return application.mConaco; - } - @NonNull public static LruCache getGalleryDetailCache(@NonNull Context context) { EhApplication application = ((EhApplication) context.getApplicationContext()); @@ -329,6 +300,8 @@ public class EhApplication extends SceneApplication { EhEngine.initialize(); BitmapUtils.initialize(this); + Coil.setImageLoader(new ImageLoader.Builder(this).okHttpClient(getOkHttpClient(this)).build()); + // Locales can be managed by system automatically above Snow Cone v2 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) AppCompatDelegate.setApplicationLocales(LocaleListCompat.create(Settings.getLocale())); @@ -458,9 +431,6 @@ public class EhApplication extends SceneApplication { } public void clearMemoryCache() { - if (null != mConaco) { - mConaco.getBeerBelly().clearMemory(); - } if (null != mGalleryDetailCache) { mGalleryDetailCache.evictAll(); } diff --git a/app/src/main/java/com/hippo/ehviewer/ImageBitmapHelper.java b/app/src/main/java/com/hippo/ehviewer/ImageBitmapHelper.java deleted file mode 100644 index 2827abd06..000000000 --- a/app/src/main/java/com/hippo/ehviewer/ImageBitmapHelper.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2016 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.ehviewer; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.hippo.conaco.ValueHelper; -import com.hippo.image.ImageBitmap; -import com.hippo.streampipe.InputStreamPipe; - -import java.io.FileInputStream; -import java.io.IOException; - -public class ImageBitmapHelper implements ValueHelper { - - private static final int MAX_CACHE_SIZE = 512 * 512; - - @Nullable - @Override - public ImageBitmap decode(@NonNull InputStreamPipe isPipe) { - try { - isPipe.obtain(); - FileInputStream is = (FileInputStream) isPipe.open(); - return ImageBitmap.decode(is); - } catch (OutOfMemoryError | IOException e) { - return null; - } finally { - isPipe.close(); - isPipe.release(); - } - } - - @Override - public int sizeOf(@NonNull String key, @NonNull ImageBitmap value) { - return value.getWidth() * value.getHeight() * 4 /* value.getByteCount() TODO Update Image */; - } - - @Override - public void onAddToMemoryCache(@NonNull ImageBitmap oldValue) { - oldValue.obtain(); - } - - @Override - public void onRemoveFromMemoryCache(@NonNull String key, @NonNull ImageBitmap oldValue) { - oldValue.release(); - } - - @Override - public boolean useMemoryCache(@NonNull String key, ImageBitmap value) { - if (value != null) { - return value.getWidth() * value.getHeight() <= MAX_CACHE_SIZE - /* value.getByteCount() <= MAX_CACHE_BYTE_COUNT TODO Update Image */; - } else { - return true; - } - } -} diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryCommentsScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryCommentsScene.java index 419f2a40c..315d08df1 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryCommentsScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryCommentsScene.java @@ -858,8 +858,7 @@ public final class GalleryCommentsScene extends ToolbarScene } private CharSequence generateComment(Context context, ObservedTextView textView, GalleryComment comment) { - Spanned sp = Html.fromHtml(comment.comment, Html.FROM_HTML_MODE_LEGACY, new URLImageGetter(textView, - EhApplication.getConaco(context)), null); + Spanned sp = Html.fromHtml(comment.comment, Html.FROM_HTML_MODE_LEGACY, new URLImageGetter(textView), null); SpannableStringBuilder ssb = new SpannableStringBuilder(sp); diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java index bc72bff39..16b0aa92a 100755 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java @@ -65,7 +65,6 @@ import com.google.android.material.snackbar.Snackbar; import com.hippo.app.BaseDialogBuilder; import com.hippo.app.CheckBoxDialogBuilder; import com.hippo.app.EditTextDialogBuilder; -import com.hippo.beerbelly.BeerBelly; import com.hippo.ehviewer.AppConfig; import com.hippo.ehviewer.EhApplication; import com.hippo.ehviewer.EhDB; @@ -883,7 +882,6 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O Resources resources = getResources(); - mThumb.load(EhCacheKeyFactory.getThumbKey(gd.gid), gd.thumb); setTitle(EhUtils.getSuitableTitle(gd)); mUploader.setText(gd.uploader); mUploader.setAlpha(gd.disowned ? .5f : 1f); @@ -1004,7 +1002,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O ObservedTextView c = v.findViewById(R.id.comment); c.setMaxLines(5); c.setText(Html.fromHtml(comment.comment, Html.FROM_HTML_MODE_LEGACY, - new URLImageGetter(c, EhApplication.getConaco(context)), null)); + new URLImageGetter(c), null)); v.setBackgroundColor(Color.TRANSPARENT); } } @@ -1102,8 +1100,8 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O if (null == temp) { return; } - BeerBelly beerBelly = EhApplication.getConaco(context).getBeerBelly(); + /* OutputStream os = null; try { os = new FileOutputStream(temp); @@ -1119,6 +1117,8 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O } finally { IOUtils.closeQuietly(os); } + + */ } @Override diff --git a/app/src/main/java/com/hippo/image/ImageBitmap.kt b/app/src/main/java/com/hippo/image/ImageBitmap.kt deleted file mode 100644 index e2412e760..000000000 --- a/app/src/main/java/com/hippo/image/ImageBitmap.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2022 Tarsin Norbin - * - * This file is part of EhViewer - * - * EhViewer is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * EhViewer is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with EhViewer. - * If not, see . - */ -package com.hippo.image - -import android.graphics.ImageDecoder -import android.graphics.drawable.Drawable -import java.io.FileInputStream -import kotlin.jvm.Throws - -class ImageBitmap private constructor(image: Image) { - private var mImage: Image? = image - private var mReferences = 0 - - @Synchronized - fun obtain(): Boolean { - return if (mImage?.isRecycled == true) { - false - } else { - ++mReferences - true - } - } - - @Synchronized - fun release() { - --mReferences - if (mReferences <= 0 && !mImage!!.isRecycled) { - mImage!!.recycle() - mImage = null - } - } - - fun getDrawable(): Drawable { - check(obtain()) { "Recycled!" } - return mImage!!.mObtainedDrawable as Drawable - } - - val width: Int - get() = mImage!!.width - - val height: Int - get() = mImage!!.height - - companion object { - @Throws(ImageDecoder.DecodeException::class) - @JvmStatic - fun decode(stream: FileInputStream): ImageBitmap { - val image = Image.decode(stream) - return ImageBitmap(image) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/hippo/text/URLImageGetter.kt b/app/src/main/java/com/hippo/text/URLImageGetter.kt index 0de7e2454..125ff4fa1 100644 --- a/app/src/main/java/com/hippo/text/URLImageGetter.kt +++ b/app/src/main/java/com/hippo/text/URLImageGetter.kt @@ -17,16 +17,13 @@ package com.hippo.text import android.graphics.drawable.Drawable import android.text.Html.ImageGetter -import com.hippo.conaco.Conaco import com.hippo.drawable.UnikeryDrawable -import com.hippo.image.ImageBitmap import com.hippo.widget.ObservedTextView class URLImageGetter( private val mTextView: ObservedTextView, - private val mConaco: Conaco ) : ImageGetter { override fun getDrawable(source: String): Drawable { - return UnikeryDrawable(mTextView, mConaco).apply { load(source) } + return UnikeryDrawable(mTextView).apply { load(source) } } } \ No newline at end of file diff --git a/app/src/main/java/com/hippo/widget/LoadImageView.java b/app/src/main/java/com/hippo/widget/LoadImageView.java index fab228c79..e7cd8e7eb 100644 --- a/app/src/main/java/com/hippo/widget/LoadImageView.java +++ b/app/src/main/java/com/hippo/widget/LoadImageView.java @@ -25,7 +25,6 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.TransitionDrawable; import android.util.AttributeSet; -import android.util.Log; import android.view.View; import androidx.annotation.DrawableRes; @@ -33,26 +32,22 @@ import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; -import com.hippo.conaco.Conaco; -import com.hippo.conaco.ConacoTask; -import com.hippo.conaco.Unikery; import com.hippo.drawable.PreciselyClipDrawable; -import com.hippo.ehviewer.EhApplication; import com.hippo.ehviewer.R; -import com.hippo.image.ImageBitmap; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -public class LoadImageView extends FixedAspectImageView implements Unikery, - View.OnClickListener, View.OnLongClickListener, Animatable { +import coil.Coil; +import coil.request.Disposable; +import coil.request.ImageRequest; + +public class LoadImageView extends FixedAspectImageView implements View.OnClickListener, View.OnLongClickListener, Animatable { public static final int RETRY_TYPE_NONE = 0; public static final int RETRY_TYPE_CLICK = 1; public static final int RETRY_TYPE_LONG_CLICK = 2; private static final String TAG = LoadImageView.class.getSimpleName(); - private int mTaskId = Unikery.INVALID_ID; - private Conaco mConaco; private String mKey; private String mUrl; private boolean mUseNetwork; @@ -63,7 +58,8 @@ public class LoadImageView extends FixedAspectImageView implements Unikery builder = new ConacoTask.Builder() - .setUnikery(this) - .setKey(key) - .setUrl(url) - .setUseNetwork(useNetwork); - mConaco.load(builder); + var imageLoader = Coil.imageLoader(getContext()); + var request = new ImageRequest.Builder(getContext()).data(url).memoryCacheKey(key).diskCacheKey(key).target( + drawable -> { + onWait(); + return null; + }, + drawable -> { + onFailure(); + return null; + }, + drawable -> { + onGetValue(drawable); + return null; + } + ).build(); + task = imageLoader.enqueue(request); } public void load(Drawable drawable) { @@ -239,43 +222,17 @@ public class LoadImageView extends FixedAspectImageView implements Unikery