Compare commits

..
Author SHA1 Message Date
txyyh 956b7c719e Make release
Releases / Build (push) Has been cancelled
2022-08-15 14:30:55 +00:00
txyyh 56e13559a0 Describe CI pages 2022-08-15 14:27:45 +00:00
txyyh 261ed86047 Rename apks on releases 2022-08-15 14:24:48 +00:00
tarsin d9b18358d2 Fix a wrong place res 2022-08-15 22:00:19 +08:00
tarsin a5161bba6f Support resize thumb, Implement #193 2022-08-15 21:52:49 +08:00
tarsin 62b00c758c IsLightStatusBar always follow night mode, Fix #199 2022-08-15 20:42:44 +08:00
tarsin 8663b4fa40 Rename .java to .kt 2022-08-15 20:42:44 +08:00
tarsin 6304c12bd0 Fix #196 2022-08-15 20:05:29 +08:00
EdwardWu efe2473ecf Ehviewer: Re-Add warning (#195) 2022-08-12 22:38:46 +08:00
tarsin 6ba494a4f1 Fixup! Re-add warning
Releases / Build (push) Has been cancelled
2022-08-12 20:43:24 +08:00
tarsin b81572ffff Re-add warning 2022-08-12 20:40:13 +08:00
tarsin d2ae1567be import jetpack compose 2022-08-12 19:01:59 +08:00
tarsin d00055a5f8 Add back doh 2022-08-12 18:09:59 +08:00
tarsin 896a2684d9 Make release 2022-08-12 17:28:13 +08:00
tarsin b98ecb17d3 Checkout to nettle 3.8.1 2022-08-12 17:24:31 +08:00
tarsin cd9af7feee Silence a warning 2022-08-12 15:29:39 +08:00
tarsin 1c38f77b5c Refactor history with room paging 2022-08-12 15:29:04 +08:00
tarsin c5977e358e Rename .java to .kt 2022-08-12 15:29:04 +08:00
tarsin 78e58e6894 Import android paging 2022-08-12 12:02:54 +08:00
tarsin 30433c5cbf Drop history limit 2022-08-12 12:00:50 +08:00
renovate[bot] fe8e3766c0 Update dependency com.google.android.material:material to v1.7.0-beta01 2022-08-11 22:02:01 +00:00
txyyh 90c95d9788 Enable renovate automerge 2022-08-11 09:57:41 +00:00
tarsin 3930a79a47 Update AndroidManifest.xml 2022-08-11 14:17:32 +08:00
renovate[bot] fc852780f8 Update activity_version to v1.6.0-beta01 (1.8.x.x) (#177)
Update activity_version to v1.6.0-beta01

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-11 09:11:58 +08:00
renovate[bot] 35315c38cd Update dependency androidx.annotation:annotation to v1.5.0-alpha02 (1.8.x.x) (#179)
Update dependency androidx.annotation:annotation to v1.5.0-alpha02

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-11 09:11:41 +08:00
renovate[bot] 0b40f37418 Update dependency androidx.webkit:webkit to v1.5.0-rc01 (1.8.x.x) (#183)
Update dependency androidx.webkit:webkit to v1.5.0-rc01

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-11 09:11:07 +08:00
renovate[bot] 5a5f0421d8 Update dependency androidx.annotation:annotation-experimental to v1.3.0-beta01 (1.8.x.x) (#180)
Update dependency androidx.annotation:annotation-experimental to v1.3.0-beta01

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-11 09:10:38 +08:00
renovate[bot] 86c5c5bc59 Update dependency androidx.appcompat:appcompat to v1.6.0-beta01 (1.8.x.x) (#181)
Update dependency androidx.appcompat:appcompat to v1.6.0-beta01

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-11 09:08:04 +08:00
renovate[bot] 776a088de9 Update core_version to v1.9.0-beta01 (1.8.x.x) (#178)
Update core_version to v1.9.0-beta01

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-11 09:07:45 +08:00
renovate[bot] ba54655877 Update dependency androidx.recyclerview:recyclerview to v1.3.0-beta02 (1.8.x.x) (#182)
Update dependency androidx.recyclerview:recyclerview to v1.3.0-beta02

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-11 09:07:30 +08:00
txyyh 9f47ae438c Disable blank issue 2022-08-10 16:49:39 +00:00
txyyh 1717233f5a Add LICENSE header 2022-08-10 09:00:26 +00:00
txyyh cf71feb89d Use ic_launcher_foreground on scene_login (#174) 2022-08-10 16:23:09 +08:00
txyyh 21e393246a Use new icon (#173)
* Use new icon

* Add monochrome icon
2022-08-10 15:45:15 +08:00
txyyh c368f234f0 Fix wrong deploy username 2022-08-09 05:04:44 +00:00
tarsin c3d8610e2a Update AndroidManifest.xml 2022-08-09 08:43:24 +08:00
txyyh 1a10e330aa Only build CI on branches (#170) 2022-08-08 00:59:21 +08:00
txyyh d992897506 Auto deploy release to fdroid repo (#169) 2022-08-07 19:21:55 +08:00
tarsin a0fe6f0d7d Revert "archive: Use memfd instead"
* It sucks, seems simplify the conditions, but more syscalls are
  made(read/seek/write), more context switch, futhermore AImageDecoder itself does support
  read raw buffer, and we are not intend to support multi-process decoding

This reverts commit f4826ea727.
2022-08-07 19:14:25 +08:00
tarsin f4826ea727 archive: Use memfd instead 2022-08-07 17:13:48 +08:00
tarsin a17b254494 Call mmap/munmap in native code 2022-08-07 15:23:32 +08:00
tarsin 0190fc07bd Fix thumb card margin 2022-08-07 14:38:27 +08:00
tarsin c8dab6a88f Archive: ignore crc32 2022-08-07 11:43:27 +08:00
renovate[bot] fbafadfd98 Update dependency gradle to v7.5.1 (1.8.x.x) (#167)
Update dependency gradle to v7.5.1

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-06 07:42:25 +08:00
61 changed files with 897 additions and 932 deletions

No files matched your search

+1 -1
View File
@@ -57,7 +57,7 @@ body:
id: ci
attributes:
label: EhViewer CI 版本 / EhViewer CI Version
description: 直接将对应 CI 下载页面网址填入即可 / Simply drop CI download page url here
description: 直接将对应 GitHub Action CI 下载页面网址填入即可 / Simply drop GitHub Action CI download page url here
placeholder: https://github.com/Ehviewer-Overhauled/Ehviewer/actions/runs/XXXXXXXXXX
validations:
required: true
+1
View File
@@ -1,3 +1,4 @@
blank_issues_enabled: false
contact_links:
- name: 所有其他问题 / All other questions
url: https://github.com/Ehviewer-Overhauled/Ehviewer/discussions
+1 -1
View File
@@ -56,7 +56,7 @@ body:
id: ci
attributes:
label: EhViewer CI 版本 / EhViewer CI Version
description: 直接将对应 CI 下载页面网址填入即可 / Simply drop CI download page url here
description: 直接将对应 GitHub Action CI 下载页面网址填入即可 / Simply drop GitHub Action CI download page url here
placeholder: https://github.com/Ehviewer-Overhauled/Ehviewer/actions/runs/XXXXXXXXXX
validations:
required: true
+6 -1
View File
@@ -1,6 +1,11 @@
name: CI
on: [push]
on:
push:
branches:
- '*'
tags-ignore:
- "*"
jobs:
linux:
+33 -5
View File
@@ -30,14 +30,42 @@ jobs:
with:
arguments: assembleRelease
- name: Rename Apks
run: |
cp app/build/outputs/apk/release/app-universal-release.apk app/build/outputs/apk/release/EhViewer-universal-A12+.apk
cp app/build/outputs/apk/release/app-arm64-v8a-release.apk app/build/outputs/apk/release/EhViewer-arm64-v8a-A12+.apk
cp app/build/outputs/apk/release/app-x86_64-release.apk app/build/outputs/apk/release/EhViewer-x86_64-A12+.apk
cp app/build/outputs/apk/release/app-x86-release.apk app/build/outputs/apk/release/EhViewer-x86-A12+.apk
cp app/build/outputs/apk/release/app-armeabi-v7a-release.apk app/build/outputs/apk/release/EhViewer-armeabi-v7a-A12+.apk
- name: Releases
uses: softprops/action-gh-release@v1
with:
body: Bump Version
discussion_category_name: Announcements
files: |
app/build/outputs/apk/release/app-universal-release.apk
app/build/outputs/apk/release/app-arm64-v8a-release.apk
app/build/outputs/apk/release/app-x86_64-release.apk
app/build/outputs/apk/release/app-x86-release.apk
app/build/outputs/apk/release/app-armeabi-v7a-release.apk
app/build/outputs/apk/release/EhViewer-universal-A12+.apk
app/build/outputs/apk/release/EhViewer-arm64-v8a-A12+.apk
app/build/outputs/apk/release/EhViewer-x86_64-A12+.apk
app/build/outputs/apk/release/EhViewer-x86-A12+.apk
app/build/outputs/apk/release/EhViewer-armeabi-v7a-A12+.apk
- name: Collect Apks
run: |
mkdir app/build/outputs/apk/release/fdroid
cp app/build/outputs/apk/release/app-arm64-v8a-release.apk app/build/outputs/apk/release/fdroid/EhViewer-v$GITHUB_REF_NAME.apk
cp app/build/outputs/apk/release/app-armeabi-v7a-release.apk app/build/outputs/apk/release/fdroid/EhViewer-v$GITHUB_REF_NAME-armv7.apk
- name: Push Apks
uses: cpina/github-action-push-to-another-repository@v1.5
env:
SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }}
with:
source-directory: app/build/outputs/apk/release/fdroid
destination-github-username: Ehviewer-Overhauled
destination-repository-name: fdroid-repo
user-name: 'github-actions[bot]'
user-email: 'github-actions[bot]@users.noreply.github.com'
target-branch: deploy
commit-message: Add apks from $GITHUB_REF
target-directory: fdroid/tmp-apks
+1 -1
View File
@@ -11,7 +11,7 @@
</p>
<h1 align="center">
<img src="art/launcher_icon-web.png" width="200">
<img src="art/launcher_icon-web.svg" width="200">
<br>EhViewer<br>
</h1>
+39 -12
View File
@@ -36,8 +36,8 @@ android {
applicationId "moe.tarsin.ehviewer"
minSdkVersion 31
targetSdkVersion 33
versionCode 180006
versionName "1.8.1.0-alpha02"
versionCode 180008
versionName "1.8.1.1"
resConfigs 'zh', 'zh-rCN', 'zh-rHK', 'zh-rTW', 'es', 'ja', 'ko', 'fr', 'de', 'th'
}
@@ -86,17 +86,25 @@ android {
}
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.3.0"
}
namespace 'com.hippo.ehviewer'
}
dependencies {
def activity_version = "1.6.0-alpha05"
def activity_version = "1.6.0-beta01"
implementation "androidx.activity:activity:$activity_version"
implementation "androidx.activity:activity-ktx:$activity_version"
implementation "androidx.annotation:annotation:1.5.0-alpha01"
implementation "androidx.annotation:annotation-experimental:1.3.0-alpha01"
implementation "androidx.appcompat:appcompat:1.6.0-alpha05"
implementation "androidx.annotation:annotation:1.5.0-alpha02"
implementation "androidx.annotation:annotation-experimental:1.3.0-beta01"
implementation "androidx.appcompat:appcompat:1.6.0-beta01"
def arch_core_version = "2.1.0"
implementation "androidx.arch.core:core-common:$arch_core_version"
@@ -109,10 +117,20 @@ dependencies {
implementation "androidx.collection:collection:$collection_version"
implementation "androidx.collection:collection-ktx:$collection_version"
def compose_version = "1.3.0-alpha03"
implementation "androidx.compose.animation:animation:$compose_version"
implementation "androidx.compose.foundation:foundation:$compose_version"
implementation "androidx.compose.foundation:foundation-layout:$compose_version"
implementation "androidx.compose.runtime:runtime:$compose_version"
implementation "androidx.compose.runtime:runtime-saveable:$compose_version"
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material3:material3:1.0.0-alpha16"
implementation "androidx.constraintlayout:constraintlayout:2.2.0-alpha03"
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
def core_version = "1.9.0-alpha05"
def core_version = "1.9.0-beta01"
implementation "androidx.core:core:$core_version"
implementation "androidx.core:core-ktx:$core_version"
@@ -124,7 +142,7 @@ dependencies {
implementation "androidx.fragment:fragment-ktx:$fragment_version"
def lifecycle_version = "2.6.0-alpha01"
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-core-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
@@ -139,12 +157,15 @@ dependencies {
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
implementation "androidx.paging:paging-runtime:3.2.0-alpha02"
implementation 'androidx.preference:preference:1.2.0'
implementation 'androidx.recyclerview:recyclerview:1.3.0-beta01'
implementation 'androidx.recyclerview:recyclerview:1.3.0-beta02'
def room_version = "2.5.0-alpha02"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-paging:$room_version"
implementation 'androidx.startup:startup-runtime:1.2.0-alpha01'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01'
@@ -153,20 +174,26 @@ dependencies {
implementation "androidx.vectordrawable:vectordrawable-animated:1.1.0"
implementation 'androidx.viewpager:viewpager:1.1.0-alpha01'
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
implementation 'androidx.webkit:webkit:1.5.0-beta01'
implementation 'androidx.webkit:webkit:1.5.0-rc01'
implementation 'com.drakeet.drawer:drawer:1.0.3'
implementation 'com.google.android.material:material:1.7.0-alpha03'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.10'
implementation 'com.google.android.material:material:1.7.0-beta01'
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 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
implementation 'org.jsoup:jsoup:1.15.2'
}
configurations.all {
exclude group: 'dev.rikka.rikkax.appcompat', module: 'appcompat'
exclude group: 'dev.rikka.rikkax.material', module: 'material'
exclude group: 'androidx.compose.material'
}
+28 -11
View File
@@ -17,15 +17,17 @@
* EhViewer. If not, see <https://www.gnu.org/licenses/>.
*/
#include <jni.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <jni.h>
#include <android/log.h>
#include <archive.h>
#include <archive_entry.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdbool.h>
#define LOG_TAG "libarchive_wrapper"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG ,__VA_ARGS__)
@@ -91,17 +93,21 @@ static int archive_alloc() {
arc = archive_read_new();
archive_read_support_format_all(arc);
archive_read_support_filter_all(arc);
archive_read_set_option(arc, "zip", "ignorecrc32", "1");
if (passwd)
archive_read_add_passphrase(arc, passwd);
return archive_read_open_memory(arc, archiveAddr, archiveSize);
}
JNIEXPORT jint JNICALL
Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *_, jobject thiz, jlong addr, jlong size) {
archiveAddr = (void *) addr;
Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *_, jobject thiz, jint fd, jlong size) {
archiveAddr = mmap64(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (archiveAddr == MAP_FAILED) {
LOGE("%s%d", "mmap64 failed with errno ", errno);
return 0;
}
archiveSize = size;
env = _;
madvise(archiveAddr, archiveSize, MADV_SEQUENTIAL | MADV_WILLNEED);
long r = archive_alloc();
if (r) {
r = 0;
@@ -120,7 +126,18 @@ Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *_, jobject thiz, jlong add
default:
need_encrypt = false;
}
LOGI("%s%d", "archive_read_has_encrypted_entries returns ", encryptRet);
// madvise for readahead optimization
int format = archive_format(arc);
switch (format) {
case ARCHIVE_FORMAT_ZIP:
case ARCHIVE_FORMAT_RAR:
case ARCHIVE_FORMAT_RAR_V5:
madvise(archiveAddr, archiveSize, MADV_SEQUENTIAL | MADV_WILLNEED);
break;
default:
;
}
}
archive_release();
return r;
@@ -144,7 +161,7 @@ Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *_, jobject thiz,
if (!filename_is_playable_file(archive_entry_pathname(entry)))
continue;
if (cur_index++ == index) {
memarea->size = archive_entry_size(entry);
memarea->size = (long) archive_entry_size(entry);
memarea->buffer = malloc(memarea->size);
ret = archive_read_data(arc, memarea->buffer, memarea->size);
if (ret != memarea->size)
@@ -161,6 +178,7 @@ JNIEXPORT void JNICALL
Java_com_hippo_UriArchiveAccessor_closeArchive(JNIEnv *jniEnv, jobject thiz) {
archive_release();
free(passwd);
munmap(archiveAddr, archiveSize);
}
JNIEXPORT jboolean JNICALL
@@ -178,17 +196,16 @@ Java_com_hippo_UriArchiveAccessor_providePassword(JNIEnv *_, jobject thiz, jstri
passwd = calloc(len, sizeof(char));
strcpy(passwd, (*env)->GetStringUTFChars(env, str, NULL));
archive_alloc();
void *tmpBuf = alloca(4096);
while (archive_read_next_header(arc, &entry) == ARCHIVE_OK) {
if (!filename_is_playable_file(archive_entry_pathname(entry)))
continue;
if (!archive_entry_is_encrypted(entry))
continue;
void *tmpBuf = malloc(4096);
if (archive_read_data(arc, tmpBuf, 4096) < ARCHIVE_OK) {
LOGE("%s%s", "Archive read failed:", archive_error_string(arc));
ret = false;
}
free(tmpBuf);
break;
}
archive_release();
+2 -2
View File
@@ -149,7 +149,7 @@
#define PACKAGE_NAME "nettle"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "nettle 3.8"
#define PACKAGE_STRING "nettle 3.8.1"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "nettle"
@@ -158,7 +158,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "3.8"
#define PACKAGE_VERSION "3.8.1"
/* The size of `long', as computed by sizeof. */
#define SIZEOF_LONG __SIZEOF_LONG__
@@ -28,8 +28,6 @@ import java.io.FileDescriptor;
public class UriArchiveAccessor {
ParcelFileDescriptor pfd;
FileDescriptor fd;
long archiveAddr;
Context ctx;
Uri uri;
@@ -40,12 +38,10 @@ public class UriArchiveAccessor {
public int open() throws Exception {
pfd = ctx.getContentResolver().openFileDescriptor(uri, "r");
fd = pfd.getFileDescriptor();
archiveAddr = Os.mmap(0, pfd.getStatSize(), OsConstants.PROT_READ, OsConstants.MAP_PRIVATE, fd, 0);
return openArchive(archiveAddr, pfd.getStatSize());
return openArchive(pfd.getFd(), pfd.getStatSize());
}
private native int openArchive(long addr, long size);
private native int openArchive(int fd, long size);
public native long extracttoOutputStream(int index);
@@ -57,8 +53,6 @@ public class UriArchiveAccessor {
public void close() throws Exception {
closeArchive();
Os.munmap(archiveAddr, pfd.getStatSize());
Os.close(fd);
pfd.close();
}
}
@@ -22,6 +22,7 @@ import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.paging.PagingSource;
import androidx.room.Room;
import com.hippo.ehviewer.client.data.GalleryInfo;
@@ -57,8 +58,6 @@ import java.util.List;
public class EhDB {
private static final int CUR_DB_VER = 4;
private static final int MAX_HISTORY_COUNT = 200;
private static EhDatabase db;
private static void upgradeDB(SQLiteDatabase db, int oldVersion) {
@@ -328,10 +327,14 @@ public class EhDB {
dao.update(list);
}
public static synchronized List<HistoryInfo> getHistoryLazyList() {
public static synchronized List<HistoryInfo> getHistoryList() {
return db.historyDao().list();
}
public static synchronized PagingSource<Integer, HistoryInfo> getHistoryLazyList() {
return db.historyDao().listLazy();
}
public static synchronized void putHistoryInfo(GalleryInfo galleryInfo) {
HistoryDao dao = db.historyDao();
HistoryInfo info = dao.load(galleryInfo.gid);
@@ -344,8 +347,6 @@ public class EhDB {
info = new HistoryInfo(galleryInfo);
info.time = System.currentTimeMillis();
dao.insert(info);
List<HistoryInfo> list = dao.list(MAX_HISTORY_COUNT, -1);
dao.delete(list);
}
}
@@ -356,9 +357,6 @@ public class EhDB {
dao.insert(info);
}
}
List<HistoryInfo> list = dao.list(MAX_HISTORY_COUNT, -1);
dao.delete(list);
}
public static synchronized void deleteHistoryInfo(HistoryInfo info) {
@@ -100,6 +100,11 @@ public class Settings {
private static final int DEFAULT_VERSION_CODE = 0;
private static final String KEY_DISPLAY_NAME = "display_name";
private static final String DEFAULT_DISPLAY_NAME = null;
public static final String KEY_LIST_THUMB_SIZE = "list_tile_size";
private static final int DEFAULT_LIST_THUMB_SIZE = 40;
private static int LIST_THUMB_SIZE = 40;
public static boolean LIST_THUMB_SIZE_INITED = false;
private static final String KEY_AVATAR = "avatar";
private static final String DEFAULT_AVATAR = null;
private static final String KEY_SHOW_WARNING = "show_warning";
@@ -1168,4 +1173,14 @@ public class Settings {
public static void putPasswdToArchivePasswds(String value) {
putStringToStringSet(KEY_ARCHIVE_PASSWDS, value);
}
public static int getListThumbSize() {
if (LIST_THUMB_SIZE_INITED) {
return LIST_THUMB_SIZE;
}
int size = 3 * getInt(KEY_LIST_THUMB_SIZE, DEFAULT_LIST_THUMB_SIZE);
LIST_THUMB_SIZE = size;
LIST_THUMB_SIZE_INITED = true;
return size;
}
}
@@ -1,5 +1,6 @@
package com.hippo.ehviewer.dao;
import androidx.paging.PagingSource;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
@@ -19,6 +20,9 @@ public interface HistoryDao extends BasicDao<HistoryInfo> {
@Query("SELECT * FROM HISTORY ORDER BY TIME DESC LIMIT :limit OFFSET :offset")
List<HistoryInfo> list(int offset, int limit);
@Query("SELECT * FROM HISTORY ORDER BY TIME DESC")
PagingSource<Integer, HistoryInfo> listLazy();
@Update
void update(HistoryInfo historyInfo);
@@ -406,17 +406,22 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
}
switch (event.getAction()) {
case MotionEvent.ACTION_SCROLL:
if (event.getAxisValue(MotionEvent.AXIS_VSCROLL) < 0.0f) {
float scroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL) * 300;
if (scroll < 0.0f) {
if (mLayoutMode == GalleryView.LAYOUT_RIGHT_TO_LEFT) {
mGalleryView.pageLeft();
} else {
} else if (mLayoutMode == GalleryView.LAYOUT_LEFT_TO_RIGHT){
mGalleryView.pageRight();
} else if (mLayoutMode == GalleryView.LAYOUT_TOP_TO_BOTTOM) {
mGalleryView.onScroll(0, -scroll, 0, -scroll, 0, -scroll);
}
} else {
if (mLayoutMode == GalleryView.LAYOUT_RIGHT_TO_LEFT) {
mGalleryView.pageRight();
} else {
} else if (mLayoutMode == GalleryView.LAYOUT_LEFT_TO_RIGHT) {
mGalleryView.pageLeft();
} else if (mLayoutMode == GalleryView.LAYOUT_TOP_TO_BOTTOM) {
mGalleryView.onScroll(0, -scroll, 0, -scroll, 0, -scroll);
}
}
}
@@ -288,7 +288,6 @@ public final class MainActivity extends StageActivity
mStageLayout = (EhStageLayout) ViewUtils.$$(this, R.id.fragment_container);
mDrawerLayout = (DrawerLayout) ViewUtils.$$(this, R.id.draw_view);
mDrawerLayout.setStatusBarBackgroundColor(0);
mNavView = (NavigationView) ViewUtils.$$(this, R.id.nav_view);
mRightDrawer = (DrawerView) ViewUtils.$$(this, R.id.right_drawer);
@@ -1,68 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.ui;
import android.os.Bundle;
import android.view.MenuItem;
import androidx.annotation.StringRes;
import androidx.appcompat.app.ActionBar;
import androidx.fragment.app.FragmentTransaction;
import com.google.android.material.snackbar.Snackbar;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.ui.fragment.SettingsFragment;
import com.hippo.ehviewer.ui.scene.BaseScene;
public final class SettingsActivity extends EhActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preference);
setSupportActionBar(findViewById(R.id.toolbar));
ActionBar bar = getSupportActionBar();
if (bar != null) {
bar.setDisplayHomeAsUpEnabled(true);
}
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_MATCH_ACTIVITY_OPEN)
.replace(R.id.fragment, new SettingsFragment())
.commitAllowingStateLoss();
}
}
public void showTip(@StringRes int id, int length) {
showTip(getString(id), length);
}
public void showTip(CharSequence message, int length) {
Snackbar.make(findViewById(R.id.snackbar), message,
length == BaseScene.LENGTH_LONG ? Snackbar.LENGTH_LONG : Snackbar.LENGTH_SHORT).show();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
}
@@ -0,0 +1,64 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.ui
import android.content.res.Configuration
import android.os.Bundle
import android.view.MenuItem
import androidx.annotation.StringRes
import androidx.core.view.WindowCompat
import androidx.fragment.app.FragmentTransaction
import com.google.android.material.snackbar.Snackbar
import com.hippo.ehviewer.R
import com.hippo.ehviewer.ui.fragment.SettingsFragment
import com.hippo.ehviewer.ui.scene.BaseScene
class SettingsActivity : EhActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_preference)
setSupportActionBar(findViewById(R.id.toolbar))
val bar = supportActionBar
bar?.setDisplayHomeAsUpEnabled(true)
WindowCompat.getInsetsController(window, window.decorView).isAppearanceLightStatusBars = (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_YES) <= 0
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_MATCH_ACTIVITY_OPEN)
.replace(R.id.fragment, SettingsFragment())
.commitAllowingStateLoss()
}
}
fun showTip(@StringRes id: Int, length: Int) {
showTip(getString(id), length)
}
fun showTip(message: CharSequence?, length: Int) {
Snackbar.make(
findViewById(R.id.snackbar), message!!,
if (length == BaseScene.LENGTH_LONG) Snackbar.LENGTH_LONG else Snackbar.LENGTH_SHORT
).show()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
onBackPressed()
return true
}
return super.onOptionsItemSelected(item)
}
}
@@ -38,6 +38,7 @@ public class EhFragment extends BasePreferenceFragment {
Preference blackDarkTheme = findPreference(Settings.KEY_BLACK_DARK_THEME);
Preference gallerySite = findPreference(Settings.KEY_GALLERY_SITE);
Preference listMode = findPreference(Settings.KEY_LIST_MODE);
Preference listThumbSize = findPreference(Settings.KEY_LIST_THUMB_SIZE);
Preference detailSize = findPreference(Settings.KEY_DETAIL_SIZE);
Preference thumbSize = findPreference(Settings.KEY_THUMB_SIZE);
Preference showTagTranslations = findPreference(Settings.KEY_SHOW_TAG_TRANSLATIONS);
@@ -46,6 +47,7 @@ public class EhFragment extends BasePreferenceFragment {
theme.setOnPreferenceChangeListener(this);
gallerySite.setOnPreferenceChangeListener(this);
listMode.setOnPreferenceChangeListener(this);
listThumbSize.setOnPreferenceChangeListener(this);
detailSize.setOnPreferenceChangeListener(this);
thumbSize.setOnPreferenceChangeListener(this);
showTagTranslations.setOnPreferenceChangeListener(this);
@@ -70,6 +72,10 @@ public class EhFragment extends BasePreferenceFragment {
} else if (Settings.KEY_LIST_MODE.equals(key)) {
requireActivity().setResult(Activity.RESULT_OK);
return true;
} else if (Settings.KEY_LIST_THUMB_SIZE.equals(key)) {
Settings.LIST_THUMB_SIZE_INITED = false;
requireActivity().setResult(Activity.RESULT_OK);
return true;
} else if (Settings.KEY_DETAIL_SIZE.equals(key)) {
requireActivity().setResult(Activity.RESULT_OK);
} else if (Settings.KEY_THUMB_SIZE.equals(key)) {
@@ -56,7 +56,6 @@ public abstract class BaseScene extends SceneFragment {
private View drawerView;
@Nullable
private SparseArray<Parcelable> drawerViewState;
private boolean needWhiteStatusBar = needWhiteStatusBar();
public void addAboveSnackView(View view) {
FragmentActivity activity = getActivity();
@@ -118,10 +117,6 @@ public abstract class BaseScene extends SceneFragment {
return true;
}
public boolean needWhiteStatusBar() {
return true;
}
public int getNavCheckedItem() {
return 0;
}
@@ -176,14 +171,6 @@ public abstract class BaseScene extends SceneFragment {
drawerView = null;
}
public void setLightStatusBar(boolean set) {
var insetsController = getInsetsController();
if (insetsController != null) {
insetsController.setAppearanceLightStatusBars(set && (requireActivity().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_YES) <= 0);
}
needWhiteStatusBar = set;
}
public void onDestroyDrawerView() {
}
@@ -213,7 +200,11 @@ public abstract class BaseScene extends SceneFragment {
// Hide soft ime
hideSoftInput();
setLightStatusBar(needWhiteStatusBar);
insetsController = getInsetsController();
if (insetsController != null) {
insetsController.setAppearanceLightStatusBars((requireActivity().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_YES) <= 0);
}
}
@Nullable
@@ -559,12 +559,6 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
ViewGroup main = (ViewGroup) ViewUtils.$$(view, R.id.main);
ScrollView mainView = (ScrollView) ViewUtils.$$(main, R.id.scroll_view);
mainView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
if (mActionGroup != null && mHeader != null) {
//noinspection IntegerDivisionInFloatingPointContext
setLightStatusBar(mActionGroup.getY() - mHeader.findViewById(R.id.header_content).getPaddingTop() / 2 < scrollY);
}
});
View progressView = ViewUtils.$$(main, R.id.progress_view);
mTip = (TextView) ViewUtils.$$(main, R.id.tip);
mViewTransition = new ViewTransition(mainView, progressView, mTip);
@@ -668,11 +662,6 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
return view;
}
@Override
public boolean needWhiteStatusBar() {
return false;
}
@Override
public void onDestroyView() {
super.onDestroyView();
@@ -841,19 +830,16 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
switch (state) {
case STATE_NORMAL:
setLightStatusBar(false);
// Show mMainView
mViewTransition.showView(0, animation);
// Show mBelowHeader
mViewTransition2.showView(0, animation);
break;
case STATE_REFRESH:
setLightStatusBar(true);
// Show mProgressView
mViewTransition.showView(1, animation);
break;
case STATE_REFRESH_HEADER:
setLightStatusBar(false);
// Show mMainView
mViewTransition.showView(0, animation);
// Show mProgress
@@ -862,7 +848,6 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
default:
case STATE_INIT:
case STATE_FAILED:
setLightStatusBar(true);
// Show mFailedView
mViewTransition.showView(2, animation);
break;
@@ -1,647 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.ui.scene;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.hippo.easyrecyclerview.EasyRecyclerView;
import com.hippo.easyrecyclerview.FastScroller;
import com.hippo.easyrecyclerview.HandlerDrawable;
import com.hippo.easyrecyclerview.MarginItemDecoration;
import com.hippo.ehviewer.EhApplication;
import com.hippo.ehviewer.EhDB;
import com.hippo.ehviewer.FavouriteStatusRouter;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.Settings;
import com.hippo.ehviewer.client.EhCacheKeyFactory;
import com.hippo.ehviewer.client.EhUtils;
import com.hippo.ehviewer.client.data.GalleryInfo;
import com.hippo.ehviewer.dao.DownloadInfo;
import com.hippo.ehviewer.dao.DownloadLabel;
import com.hippo.ehviewer.dao.HistoryInfo;
import com.hippo.ehviewer.download.DownloadManager;
import com.hippo.ehviewer.ui.CommonOperations;
import com.hippo.ehviewer.ui.GalleryActivity;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.ehviewer.ui.dialog.SelectItemWithIconAdapter;
import com.hippo.ehviewer.widget.SimpleRatingView;
import com.hippo.scene.Announcer;
import com.hippo.scene.SceneFragment;
import com.hippo.view.ViewTransition;
import com.hippo.widget.LoadImageView;
import com.hippo.widget.recyclerview.AutoStaggeredGridLayoutManager;
import com.hippo.yorozuya.AssertUtils;
import com.hippo.yorozuya.ViewUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import rikka.core.res.ResourcesKt;
public class HistoryScene extends ToolbarScene {
/*---------------
View life cycle
---------------*/
@Nullable
private TextView mTip;
@Nullable
private FastScroller mFastScroller;
@Nullable
private EasyRecyclerView mRecyclerView;
@Nullable
private ViewTransition mViewTransition;
@Nullable
private RecyclerView.Adapter<?> mAdapter;
@Nullable
private List<HistoryInfo> mLazyList;
private DownloadManager mDownloadManager;
private DownloadManager.DownloadInfoListener mDownloadInfoListener;
private FavouriteStatusRouter mFavouriteStatusRouter;
private FavouriteStatusRouter.Listener mFavouriteStatusRouterListener;
@Override
public void onDestroy() {
super.onDestroy();
mDownloadManager.removeDownloadInfoListener(mDownloadInfoListener);
mFavouriteStatusRouter.removeListener(mFavouriteStatusRouterListener);
}
@Override
public int getNavCheckedItem() {
return R.id.nav_history;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Context context = getContext();
assert context != null;
mDownloadManager = EhApplication.getDownloadManager(context);
mDownloadManager = EhApplication.getDownloadManager(context);
mFavouriteStatusRouter = EhApplication.getFavouriteStatusRouter(context);
mDownloadInfoListener = new DownloadManager.DownloadInfoListener() {
@Override
public void onAdd(@NonNull DownloadInfo info, @NonNull List<DownloadInfo> list, int position) {
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
}
@Override
public void onUpdate(@NonNull DownloadInfo info, @NonNull List<DownloadInfo> list) {
}
@Override
public void onUpdateAll() {
}
@Override
public void onReload() {
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
}
@Override
public void onChange() {
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
}
@Override
public void onRenameLabel(String from, String to) {
}
@Override
public void onRemove(@NonNull DownloadInfo info, @NonNull List<DownloadInfo> list, int position) {
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
}
@Override
public void onUpdateLabels() {
}
};
mDownloadManager.addDownloadInfoListener(mDownloadInfoListener);
mFavouriteStatusRouterListener = (gid, slot) -> {
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
};
mFavouriteStatusRouter.addListener(mFavouriteStatusRouterListener);
}
@Nullable
@Override
public View onCreateViewWithToolbar(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.scene_history, container, false);
View content = ViewUtils.$$(view, R.id.content);
mRecyclerView = (EasyRecyclerView) ViewUtils.$$(content, R.id.recycler_view);
mFastScroller = (FastScroller) ViewUtils.$$(content, R.id.fast_scroller);
mTip = (TextView) ViewUtils.$$(view, R.id.tip);
mViewTransition = new ViewTransition(content, mTip);
Context context = getContext();
AssertUtils.assertNotNull(context);
Resources resources = context.getResources();
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.big_history);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
mTip.setCompoundDrawables(null, drawable, null, null);
mAdapter = new HistoryAdapter();
mAdapter.setHasStableIds(true);
mRecyclerView.setAdapter(mAdapter);
AutoStaggeredGridLayoutManager layoutManager = new AutoStaggeredGridLayoutManager(
0, StaggeredGridLayoutManager.VERTICAL);
layoutManager.setColumnSize(resources.getDimensionPixelOffset(Settings.getDetailSizeResId()));
layoutManager.setStrategy(AutoStaggeredGridLayoutManager.STRATEGY_MIN_SIZE);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setClipToPadding(false);
mRecyclerView.setClipChildren(false);
int interval = resources.getDimensionPixelOffset(R.dimen.gallery_list_interval);
int paddingH = resources.getDimensionPixelOffset(R.dimen.gallery_list_margin_h);
int paddingV = resources.getDimensionPixelOffset(R.dimen.gallery_list_margin_v);
MarginItemDecoration decoration = new MarginItemDecoration(interval, paddingH, paddingV, paddingH, paddingV);
mRecyclerView.addItemDecoration(decoration);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new HistoryItemTouchHelperCallback());
itemTouchHelper.attachToRecyclerView(mRecyclerView);
mFastScroller.attachToRecyclerView(mRecyclerView);
HandlerDrawable handlerDrawable = new HandlerDrawable();
handlerDrawable.setColor(ResourcesKt.resolveColor(getTheme(), com.google.android.material.R.attr.colorPrimary));
mFastScroller.setHandlerDrawable(handlerDrawable);
updateLazyList();
updateView(false);
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setTitle(R.string.history);
setNavigationIcon(R.drawable.ic_baseline_menu_24);
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (null != mLazyList) {
mLazyList = null;
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
}
if (null != mRecyclerView) {
mRecyclerView.stopScroll();
mRecyclerView = null;
}
mViewTransition = null;
mAdapter = null;
}
// Remember to notify
private void updateLazyList() {
mLazyList = EhDB.getHistoryLazyList();
}
private void updateView(boolean animation) {
if (null == mAdapter || null == mViewTransition) {
return;
}
if (mAdapter.getItemCount() == 0) {
mViewTransition.showView(1, animation);
} else {
mViewTransition.showView(0, animation);
}
}
@SuppressLint("RtlHardcoded")
@Override
public void onNavigationClick() {
toggleDrawer(Gravity.LEFT);
}
@Override
public int getMenuResId() {
return R.menu.scene_history;
}
private void showClearAllDialog() {
new MaterialAlertDialogBuilder(requireContext())
.setMessage(R.string.clear_all_history)
.setPositiveButton(R.string.clear_all, (dialog, which) -> {
if (DialogInterface.BUTTON_POSITIVE != which || null == mAdapter) {
return;
}
EhDB.clearHistoryInfo();
updateLazyList();
mAdapter.notifyDataSetChanged();
updateView(true);
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
@Override
public boolean onMenuItemClick(MenuItem item) {
// Skip when in choice mode
Context context = getContext();
if (null == context) {
return false;
}
int id = item.getItemId();
if (id == R.id.action_clear_all) {
showClearAllDialog();
return true;
}
return false;
}
public boolean onItemClick(View view, int position) {
if (null == mLazyList) {
return false;
}
Bundle args = new Bundle();
args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GALLERY_INFO);
args.putParcelable(GalleryDetailScene.KEY_GALLERY_INFO, mLazyList.get(position));
Announcer announcer = new Announcer(GalleryDetailScene.class).setArgs(args);
startScene(announcer);
return true;
}
public boolean onItemLongClick(int position) {
final Context context = getContext();
final MainActivity activity = getMainActivity();
if (null == context || null == activity || null == mLazyList) {
return false;
}
final GalleryInfo gi = mLazyList.get(position);
if (gi == null) {
return true;
}
boolean downloaded = mDownloadManager.getDownloadState(gi.gid) != DownloadInfo.STATE_INVALID;
boolean favourited = gi.favoriteSlot != -2;
CharSequence[] items = downloaded ? new CharSequence[]{
context.getString(R.string.read),
context.getString(R.string.delete_downloads),
context.getString(favourited ? R.string.remove_from_favourites : R.string.add_to_favourites),
context.getString(R.string.delete),
context.getString(R.string.download_move_dialog_title),
} : new CharSequence[]{
context.getString(R.string.read),
context.getString(R.string.download),
context.getString(favourited ? R.string.remove_from_favourites : R.string.add_to_favourites),
context.getString(R.string.delete),
};
int[] icons = downloaded ? new int[]{
R.drawable.v_book_open_x24,
R.drawable.v_delete_x24,
favourited ? R.drawable.v_heart_broken_x24 : R.drawable.v_heart_x24,
R.drawable.v_delete_x24,
R.drawable.v_folder_move_x24,
} : new int[]{
R.drawable.v_book_open_x24,
R.drawable.v_download_x24,
favourited ? R.drawable.v_heart_broken_x24 : R.drawable.v_heart_x24,
R.drawable.v_delete_x24,
};
new MaterialAlertDialogBuilder(context)
.setTitle(EhUtils.getSuitableTitle(gi))
.setAdapter(new SelectItemWithIconAdapter(context, items, icons), (dialog, which) -> {
switch (which) {
case 0: // Read
Intent intent = new Intent(activity, GalleryActivity.class);
intent.setAction(GalleryActivity.ACTION_EH);
intent.putExtra(GalleryActivity.KEY_GALLERY_INFO, gi);
startActivity(intent);
break;
case 1: // Download
if (downloaded) {
new MaterialAlertDialogBuilder(context)
.setTitle(R.string.download_remove_dialog_title)
.setMessage(getString(R.string.download_remove_dialog_message, gi.title))
.setPositiveButton(android.R.string.ok, (dialog1, which1) -> mDownloadManager.deleteDownload(gi.gid))
.show();
} else {
CommonOperations.startDownload(activity, gi, false);
}
break;
case 2: // Favorites
if (favourited) {
CommonOperations.removeFromFavorites(activity, gi, new RemoveFromFavoriteListener(context, activity.getStageId(), getTag()));
} else {
CommonOperations.addToFavorites(activity, gi, new AddToFavoriteListener(context, activity.getStageId(), getTag()));
}
break;
case 3: // Delete
if (null == mLazyList || null == mAdapter) {
return;
}
HistoryInfo info = mLazyList.get(position);
EhDB.deleteHistoryInfo(info);
updateLazyList();
mAdapter.notifyDataSetChanged();
updateView(true);
break;
case 4: // Move
List<DownloadLabel> labelRawList = EhApplication.getDownloadManager(context).getLabelList();
List<String> labelList = new ArrayList<>(labelRawList.size() + 1);
labelList.add(getString(R.string.default_download_label_name));
for (int i = 0, n = labelRawList.size(); i < n; i++) {
labelList.add(labelRawList.get(i).getLabel());
}
String[] labels = labelList.toArray(new String[0]);
MoveDialogHelper helper = new MoveDialogHelper(labels, gi);
new MaterialAlertDialogBuilder(context)
.setTitle(R.string.download_move_dialog_title)
.setItems(labels, helper)
.show();
break;
}
}).show();
return true;
}
private static class AddToFavoriteListener extends EhCallback<GalleryListScene, Void> {
public AddToFavoriteListener(Context context, int stageId, String sceneTag) {
super(context, stageId, sceneTag);
}
@Override
public void onSuccess(Void result) {
showTip(R.string.add_to_favorite_success, LENGTH_SHORT);
}
@Override
public void onFailure(Exception e) {
showTip(R.string.add_to_favorite_failure, LENGTH_LONG);
}
@Override
public void onCancel() {
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof GalleryListScene;
}
}
private static class RemoveFromFavoriteListener extends EhCallback<GalleryListScene, Void> {
public RemoveFromFavoriteListener(Context context, int stageId, String sceneTag) {
super(context, stageId, sceneTag);
}
@Override
public void onSuccess(Void result) {
showTip(R.string.remove_from_favorite_success, LENGTH_SHORT);
}
@Override
public void onFailure(Exception e) {
showTip(R.string.remove_from_favorite_failure, LENGTH_LONG);
}
@Override
public void onCancel() {
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof GalleryListScene;
}
}
private static class HistoryHolder extends RecyclerView.ViewHolder {
public final View card;
public final LoadImageView thumb;
public final TextView title;
public final TextView uploader;
public final SimpleRatingView rating;
public final TextView category;
public final TextView posted;
public final TextView simpleLanguage;
public final TextView pages;
public final ImageView downloaded;
public HistoryHolder(View itemView) {
super(itemView);
card = itemView.findViewById(R.id.card);
thumb = itemView.findViewById(R.id.thumb);
title = itemView.findViewById(R.id.title);
uploader = itemView.findViewById(R.id.uploader);
rating = itemView.findViewById(R.id.rating);
category = itemView.findViewById(R.id.category);
posted = itemView.findViewById(R.id.posted);
simpleLanguage = itemView.findViewById(R.id.simple_language);
pages = itemView.findViewById(R.id.pages);
downloaded = itemView.findViewById(R.id.downloaded);
}
}
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> {
private final LayoutInflater mInflater;
private final int mListThumbWidth;
private final int mListThumbHeight;
public HistoryAdapter() {
mInflater = getLayoutInflater();
@SuppressLint("InflateParams") View calculator = mInflater.inflate(R.layout.item_gallery_list_thumb_height, null);
ViewUtils.measureView(calculator, 1024, ViewGroup.LayoutParams.WRAP_CONTENT);
mListThumbHeight = calculator.getMeasuredHeight();
mListThumbWidth = mListThumbHeight * 2 / 3;
}
@Override
public long getItemId(int position) {
if (null == mLazyList) {
return super.getItemId(position);
} else {
return mLazyList.get(position).gid;
}
}
@NonNull
@Override
public HistoryHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
HistoryHolder holder = new HistoryHolder(mInflater.inflate(R.layout.item_history, parent, false));
ViewGroup.LayoutParams lp = holder.thumb.getLayoutParams();
lp.width = mListThumbWidth;
lp.height = mListThumbHeight;
holder.thumb.setLayoutParams(lp);
return holder;
}
@Override
public void onBindViewHolder(@NonNull HistoryHolder holder, int position) {
if (null == mLazyList) {
return;
}
GalleryInfo gi = mLazyList.get(position);
holder.thumb.load(EhCacheKeyFactory.getThumbKey(gi.gid), gi.thumb);
holder.title.setText(EhUtils.getSuitableTitle(gi));
holder.uploader.setText(gi.uploader);
holder.rating.setRating(gi.rating);
TextView category = holder.category;
String newCategoryText = EhUtils.getCategory(gi.category);
if (!newCategoryText.contentEquals(category.getText())) {
category.setText(newCategoryText);
category.setBackgroundColor(EhUtils.getCategoryColor(gi.category));
}
holder.posted.setText(gi.posted);
holder.pages.setText(null);
holder.pages.setVisibility(View.GONE);
if (TextUtils.isEmpty(gi.simpleLanguage)) {
holder.simpleLanguage.setText(null);
holder.simpleLanguage.setVisibility(View.GONE);
} else {
holder.simpleLanguage.setText(gi.simpleLanguage);
holder.simpleLanguage.setVisibility(View.VISIBLE);
}
holder.downloaded.setVisibility(mDownloadManager.containDownloadInfo(gi.gid) ? View.VISIBLE : View.GONE);
// Update transition name
long gid = gi.gid;
ViewCompat.setTransitionName(holder.thumb, TransitionNameFactory.getThumbTransitionName(gid));
holder.card.setOnClickListener(v -> onItemClick(holder.itemView, position));
holder.card.setOnLongClickListener(v -> onItemLongClick(position));
}
@Override
public int getItemCount() {
return null != mLazyList ? mLazyList.size() : 0;
}
}
private class HistoryItemTouchHelperCallback extends ItemTouchHelper.Callback {
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
return makeMovementFlags(0, ItemTouchHelper.LEFT);
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
int mPosition = viewHolder.getBindingAdapterPosition();
if (null == mLazyList || mAdapter == null) {
return;
}
HistoryInfo info = mLazyList.get(mPosition);
EhDB.deleteHistoryInfo(info);
updateLazyList();
mAdapter.notifyItemRemoved(mPosition);
updateView(true);
}
}
}
@@ -0,0 +1,489 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.ui.scene
import android.annotation.SuppressLint
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import android.view.*
import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.lifecycle.lifecycleScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingDataAdapter
import androidx.paging.cachedIn
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.hippo.easyrecyclerview.EasyRecyclerView
import com.hippo.easyrecyclerview.FastScroller
import com.hippo.easyrecyclerview.HandlerDrawable
import com.hippo.easyrecyclerview.MarginItemDecoration
import com.hippo.ehviewer.*
import com.hippo.ehviewer.client.EhCacheKeyFactory
import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.client.data.GalleryInfo
import com.hippo.ehviewer.dao.DownloadInfo
import com.hippo.ehviewer.dao.HistoryInfo
import com.hippo.ehviewer.download.DownloadManager
import com.hippo.ehviewer.download.DownloadManager.DownloadInfoListener
import com.hippo.ehviewer.ui.CommonOperations
import com.hippo.ehviewer.ui.GalleryActivity
import com.hippo.ehviewer.ui.dialog.SelectItemWithIconAdapter
import com.hippo.ehviewer.widget.SimpleRatingView
import com.hippo.scene.Announcer
import com.hippo.scene.SceneFragment
import com.hippo.view.ViewTransition
import com.hippo.widget.LoadImageView
import com.hippo.widget.recyclerview.AutoStaggeredGridLayoutManager
import com.hippo.yorozuya.ViewUtils
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import rikka.core.res.resolveColor
class HistoryScene : ToolbarScene() {
private var mRecyclerView: EasyRecyclerView? = null
private var mViewTransition: ViewTransition? = null
private var mAdapter: HistoryAdapter? = null
private var mDownloadManager: DownloadManager? = null
private var mDownloadInfoListener: DownloadInfoListener? = null
private var mFavouriteStatusRouter: FavouriteStatusRouter? = null
private var mFavouriteStatusRouterListener: FavouriteStatusRouter.Listener? = null
override fun onDestroy() {
super.onDestroy()
mDownloadManager!!.removeDownloadInfoListener(mDownloadInfoListener)
mFavouriteStatusRouter!!.removeListener(mFavouriteStatusRouterListener)
}
override fun getNavCheckedItem(): Int {
return R.id.nav_history
}
@SuppressLint("NotifyDataSetChanged")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val context = requireContext()
mDownloadManager = EhApplication.getDownloadManager(context)
mFavouriteStatusRouter = EhApplication.getFavouriteStatusRouter(context)
mDownloadInfoListener = object : DownloadInfoListener {
override fun onAdd(info: DownloadInfo, list: List<DownloadInfo>, position: Int) {
mAdapter?.notifyDataSetChanged()
}
override fun onUpdate(info: DownloadInfo, list: List<DownloadInfo>) {}
override fun onUpdateAll() {}
override fun onReload() {
mAdapter?.notifyDataSetChanged()
}
override fun onChange() {
mAdapter?.notifyDataSetChanged()
}
override fun onRenameLabel(from: String, to: String) {}
override fun onRemove(info: DownloadInfo, list: List<DownloadInfo>, position: Int) {
mAdapter?.notifyDataSetChanged()
}
override fun onUpdateLabels() {}
}
mDownloadManager!!.addDownloadInfoListener(mDownloadInfoListener)
mFavouriteStatusRouterListener = FavouriteStatusRouter.Listener { _: Long, _: Int ->
mAdapter?.notifyDataSetChanged()
}
mFavouriteStatusRouter!!.addListener(mFavouriteStatusRouterListener)
}
override fun onCreateViewWithToolbar(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.scene_history, container, false)
val content = ViewUtils.`$$`(view, R.id.content)
val recyclerView = ViewUtils.`$$`(content, R.id.recycler_view) as EasyRecyclerView
val mFastScroller = ViewUtils.`$$`(content, R.id.fast_scroller) as FastScroller
val mTip = ViewUtils.`$$`(view, R.id.tip) as TextView
mViewTransition = ViewTransition(content, mTip)
val resources = requireContext().resources
val drawable = ContextCompat.getDrawable(requireContext(), R.drawable.big_history)
drawable!!.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
mTip.setCompoundDrawables(null, drawable, null, null)
val historyData = Pager(
PagingConfig(20)
) {
EhDB.getHistoryLazyList()
}.flow.cachedIn(viewLifecycleOwner.lifecycleScope)
mAdapter = HistoryAdapter(object : DiffUtil.ItemCallback<HistoryInfo>() {
override fun areItemsTheSame(oldItem: HistoryInfo, newItem: HistoryInfo): Boolean {
return oldItem.gid == newItem.gid
}
override fun areContentsTheSame(oldItem: HistoryInfo, newItem: HistoryInfo): Boolean {
return oldItem.gid == newItem.gid
}
})
recyclerView.adapter = mAdapter
val layoutManager = AutoStaggeredGridLayoutManager(
0, StaggeredGridLayoutManager.VERTICAL
)
layoutManager.setColumnSize(resources.getDimensionPixelOffset(Settings.getDetailSizeResId()))
layoutManager.setStrategy(AutoStaggeredGridLayoutManager.STRATEGY_MIN_SIZE)
recyclerView.layoutManager = layoutManager
recyclerView.clipToPadding = false
recyclerView.clipChildren = false
val interval = resources.getDimensionPixelOffset(R.dimen.gallery_list_interval)
val paddingH = resources.getDimensionPixelOffset(R.dimen.gallery_list_margin_h)
val paddingV = resources.getDimensionPixelOffset(R.dimen.gallery_list_margin_v)
val decoration = MarginItemDecoration(interval, paddingH, paddingV, paddingH, paddingV)
recyclerView.addItemDecoration(decoration)
val itemTouchHelper = ItemTouchHelper(HistoryItemTouchHelperCallback())
itemTouchHelper.attachToRecyclerView(recyclerView)
mFastScroller.attachToRecyclerView(recyclerView)
mRecyclerView = recyclerView
val handlerDrawable = HandlerDrawable()
handlerDrawable.setColor(theme.resolveColor(com.google.android.material.R.attr.colorPrimary))
mFastScroller.setHandlerDrawable(handlerDrawable)
viewLifecycleOwner.lifecycleScope.launch {
historyData.collectLatest { value ->
mAdapter!!.submitData(
value
)
}
}
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setTitle(R.string.history)
setNavigationIcon(R.drawable.ic_baseline_menu_24)
}
override fun onDestroyView() {
super.onDestroyView()
mRecyclerView?.stopScroll()
mRecyclerView = null
mViewTransition = null
mAdapter = null
}
@SuppressLint("RtlHardcoded")
override fun onNavigationClick() {
toggleDrawer(Gravity.LEFT)
}
override fun getMenuResId(): Int {
return R.menu.scene_history
}
@SuppressLint("NotifyDataSetChanged")
private fun showClearAllDialog() {
MaterialAlertDialogBuilder(requireContext())
.setMessage(R.string.clear_all_history)
.setPositiveButton(R.string.clear_all) { _: DialogInterface?, which: Int ->
if (DialogInterface.BUTTON_POSITIVE != which || null == mAdapter) {
return@setPositiveButton
}
EhDB.clearHistoryInfo()
mAdapter!!.refresh()
mAdapter!!.notifyDataSetChanged()
}
.setNegativeButton(android.R.string.cancel, null)
.show()
}
override fun onMenuItemClick(item: MenuItem): Boolean {
// Skip when in choice mode
context ?: return false
val id = item.itemId
if (id == R.id.action_clear_all) {
showClearAllDialog()
return true
}
return false
}
fun onItemClick(position: Int): Boolean {
val args = Bundle()
args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GALLERY_INFO)
args.putParcelable(GalleryDetailScene.KEY_GALLERY_INFO, mAdapter?.peek(position))
val announcer = Announcer(GalleryDetailScene::class.java).setArgs(args)
startScene(announcer)
return true
}
fun onItemLongClick(position: Int): Boolean {
val context = requireContext()
val activity = mainActivity ?: return false
val gi: GalleryInfo = mAdapter?.peek(position) ?: return true
val downloaded = mDownloadManager!!.getDownloadState(gi.gid) != DownloadInfo.STATE_INVALID
val favourited = gi.favoriteSlot != -2
val items = if (downloaded) arrayOf<CharSequence>(
context.getString(R.string.read),
context.getString(R.string.delete_downloads),
context.getString(if (favourited) R.string.remove_from_favourites else R.string.add_to_favourites),
context.getString(R.string.download_move_dialog_title)
) else arrayOf<CharSequence>(
context.getString(R.string.read),
context.getString(R.string.download),
context.getString(if (favourited) R.string.remove_from_favourites else R.string.add_to_favourites),
)
val icons = if (downloaded) intArrayOf(
R.drawable.v_book_open_x24,
R.drawable.v_delete_x24,
if (favourited) R.drawable.v_heart_broken_x24 else R.drawable.v_heart_x24,
R.drawable.v_folder_move_x24
) else intArrayOf(
R.drawable.v_book_open_x24,
R.drawable.v_download_x24,
if (favourited) R.drawable.v_heart_broken_x24 else R.drawable.v_heart_x24,
)
MaterialAlertDialogBuilder(context)
.setTitle(EhUtils.getSuitableTitle(gi))
.setAdapter(
SelectItemWithIconAdapter(
context,
items,
icons
)
) { _: DialogInterface?, which: Int ->
when (which) {
0 -> {
val intent = Intent(activity, GalleryActivity::class.java)
intent.action = GalleryActivity.ACTION_EH
intent.putExtra(GalleryActivity.KEY_GALLERY_INFO, gi)
startActivity(intent)
}
1 -> if (downloaded) {
MaterialAlertDialogBuilder(context)
.setTitle(R.string.download_remove_dialog_title)
.setMessage(
getString(
R.string.download_remove_dialog_message,
gi.title
)
)
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int ->
mDownloadManager!!.deleteDownload(
gi.gid
)
}
.show()
} else {
CommonOperations.startDownload(activity, gi, false)
}
2 -> if (favourited) {
CommonOperations.removeFromFavorites(
activity,
gi,
RemoveFromFavoriteListener(context, activity.stageId, tag)
)
} else {
CommonOperations.addToFavorites(
activity,
gi,
AddToFavoriteListener(context, activity.stageId, tag)
)
}
3 -> {
val labelRawList = EhApplication.getDownloadManager(context).labelList
val labelList: MutableList<String> = ArrayList(labelRawList.size + 1)
labelList.add(getString(R.string.default_download_label_name))
var i = 0
val n = labelRawList.size
while (i < n) {
labelList.add(labelRawList[i].label)
i++
}
val labels = labelList.toTypedArray()
val helper = MoveDialogHelper(labels, gi)
MaterialAlertDialogBuilder(context)
.setTitle(R.string.download_move_dialog_title)
.setItems(labels, helper)
.show()
}
}
}.show()
return true
}
private class AddToFavoriteListener(context: Context?, stageId: Int, sceneTag: String?) :
EhCallback<GalleryListScene?, Void?>(context, stageId, sceneTag) {
override fun onSuccess(result: Void?) {
showTip(R.string.add_to_favorite_success, LENGTH_SHORT)
}
override fun onFailure(e: Exception) {
showTip(R.string.add_to_favorite_failure, LENGTH_LONG)
}
override fun onCancel() {}
override fun isInstance(scene: SceneFragment): Boolean {
return scene is GalleryListScene
}
}
private class RemoveFromFavoriteListener(context: Context?, stageId: Int, sceneTag: String?) :
EhCallback<GalleryListScene?, Void?>(context, stageId, sceneTag) {
override fun onSuccess(result: Void?) {
showTip(R.string.remove_from_favorite_success, LENGTH_SHORT)
}
override fun onFailure(e: Exception) {
showTip(R.string.remove_from_favorite_failure, LENGTH_LONG)
}
override fun onCancel() {}
override fun isInstance(scene: SceneFragment): Boolean {
return scene is GalleryListScene
}
}
private class HistoryHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val card: View
val thumb: LoadImageView
val title: TextView
val uploader: TextView
val rating: SimpleRatingView
val category: TextView
val posted: TextView
val simpleLanguage: TextView
val pages: TextView
val downloaded: ImageView
init {
card = itemView.findViewById(R.id.card)
thumb = itemView.findViewById(R.id.thumb)
title = itemView.findViewById(R.id.title)
uploader = itemView.findViewById(R.id.uploader)
rating = itemView.findViewById(R.id.rating)
category = itemView.findViewById(R.id.category)
posted = itemView.findViewById(R.id.posted)
simpleLanguage = itemView.findViewById(R.id.simple_language)
pages = itemView.findViewById(R.id.pages)
downloaded = itemView.findViewById(R.id.downloaded)
}
}
private inner class MoveDialogHelper(
private val mLabels: Array<String>,
private val mGi: GalleryInfo
) : DialogInterface.OnClickListener {
override fun onClick(dialog: DialogInterface, which: Int) {
mRecyclerView?.outOfCustomChoiceMode()
val downloadManager = EhApplication.getDownloadManager(requireContext())
val downloadInfo = downloadManager.getDownloadInfo(mGi.gid) ?: return
val label = if (which == 0) null else mLabels[which]
downloadManager.changeLabel(listOf(downloadInfo), label)
}
}
private inner class HistoryAdapter(diffCallback: DiffUtil.ItemCallback<HistoryInfo>) :
PagingDataAdapter<HistoryInfo, HistoryHolder>(diffCallback) {
private val mInflater: LayoutInflater = layoutInflater
private val mListThumbWidth: Int
private val mListThumbHeight: Int
init {
@SuppressLint("InflateParams") val calculator =
mInflater.inflate(R.layout.item_gallery_list_thumb_height, null)
ViewUtils.measureView(calculator, 1024, ViewGroup.LayoutParams.WRAP_CONTENT)
mListThumbHeight = calculator.measuredHeight
mListThumbWidth = mListThumbHeight * 2 / 3
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HistoryHolder {
val holder = HistoryHolder(mInflater.inflate(R.layout.item_history, parent, false))
val lp = holder.thumb.layoutParams
lp.width = mListThumbWidth
lp.height = mListThumbHeight
holder.thumb.layoutParams = lp
return holder
}
override fun onBindViewHolder(holder: HistoryHolder, position: Int) {
val gi: GalleryInfo? = getItem(position)
gi ?: return
holder.thumb.load(EhCacheKeyFactory.getThumbKey(gi.gid), gi.thumb)
holder.title.text = EhUtils.getSuitableTitle(gi)
holder.uploader.text = gi.uploader
holder.rating.rating = gi.rating
val category = holder.category
val newCategoryText = EhUtils.getCategory(gi.category)
if (!newCategoryText!!.contentEquals(category.text)) {
category.text = newCategoryText
category.setBackgroundColor(EhUtils.getCategoryColor(gi.category))
}
holder.posted.text = gi.posted
holder.pages.text = null
holder.pages.visibility = View.GONE
if (TextUtils.isEmpty(gi.simpleLanguage)) {
holder.simpleLanguage.text = null
holder.simpleLanguage.visibility = View.GONE
} else {
holder.simpleLanguage.text = gi.simpleLanguage
holder.simpleLanguage.visibility = View.VISIBLE
}
holder.downloaded.visibility =
if (mDownloadManager!!.containDownloadInfo(gi.gid)) View.VISIBLE else View.GONE
// Update transition name
val gid = gi.gid
ViewCompat.setTransitionName(
holder.thumb,
TransitionNameFactory.getThumbTransitionName(gid)
)
holder.card.setOnClickListener { onItemClick(position) }
holder.card.setOnLongClickListener { onItemLongClick(position) }
}
}
private inner class HistoryItemTouchHelperCallback : ItemTouchHelper.Callback() {
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
return makeMovementFlags(0, ItemTouchHelper.LEFT)
}
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
return false
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val mPosition = viewHolder.bindingAdapterPosition
if (mAdapter == null) {
return
}
val info: HistoryInfo = mAdapter!!.peek(mPosition)!!
EhDB.deleteHistoryInfo(info)
mAdapter!!.refresh()
}
}
}
@@ -87,12 +87,6 @@ public abstract class ToolbarScene extends BaseScene {
}
}
@Override
public boolean needWhiteStatusBar() {
return false;
}
public int getMenuResId() {
return 0;
}
@@ -53,11 +53,6 @@ public class FixedThumb extends LoadImageView {
a.recycle();
}
public void setFix(float minAspect, float maxAspect) {
this.minAspect = minAspect;
this.maxAspect = maxAspect;
}
@Override
public void onPreSetImageDrawable(Drawable drawable, boolean isTarget) {
if (alwaysCutAndScale) {
@@ -0,0 +1,13 @@
package com.hippo.ehviewer.widget
import android.content.Context
import android.util.AttributeSet
import com.hippo.ehviewer.Settings
class ResizeableFixedThumb @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : FixedThumb(context, attrs) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
setMeasuredDimension(Settings.getListThumbSize() * 2, Settings.getListThumbSize() * 3)
}
}
@@ -1,38 +1,51 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ 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 GeneralPublic 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 <https://www.gnu.org/licenses/>.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="0.37947997"
android:scaleY="0.37947997"
android:translateX="35.1"
android:translateY="39.584126">
<path
android:fillColor="@color/ic_launcher_foreground"
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:fillColor="@color/ic_launcher_foreground"
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>
<group android:scaleX="0.7425"
android:scaleY="0.7425"
android:translateX="30.68"
android:translateY="30.68">
<path
android:pathData="M11,9H34"
android:strokeWidth="8"
android:fillColor="#00000000"
android:strokeColor="#FBBD06"
android:strokeLineCap="round"/>
<path
android:pathData="M11,54H23"
android:strokeWidth="8"
android:fillColor="#00000000"
android:strokeColor="#FBBD06"
android:strokeLineCap="round"/>
<path
android:pathData="M11,9L11,54"
android:strokeWidth="8"
android:fillColor="#00000000"
android:strokeColor="#35AA53"
android:strokeLineCap="round"/>
<path
android:pathData="M11,31L52,31"
android:strokeWidth="8"
android:fillColor="#00000000"
android:strokeColor="#FBBD06"
android:strokeLineCap="round"/>
<path
android:pathData="M52,31L52,54"
android:strokeWidth="8"
android:fillColor="#00000000"
android:strokeColor="#4586F3"
android:strokeLineCap="round"/>
<path
android:pathData="M34,21L34,54"
android:strokeWidth="8"
android:fillColor="#00000000"
android:strokeColor="#EB4334"
android:strokeLineCap="round"/>
<path
android:pathData="M15,35H11C8.791,35 7,33.209 7,31C7,28.791 8.791,27 11,27H15V35Z"
android:fillColor="#FBBD06"
android:fillType="evenOdd"/>
</group>
</vector>
@@ -1,38 +1,55 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ 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 GeneralPublic 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 <https://www.gnu.org/licenses/>.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="44dp"
android:height="44dp"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="0.37947997"
android:scaleY="0.37947997"
android:translateX="35.1"
android:translateY="39.584126">
<path
android:fillColor="@android:color/white"
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:fillColor="@android:color/white"
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>
<group android:scaleX="0.7425"
android:scaleY="0.7425"
android:translateX="30.68"
android:translateY="30.68">
<path
android:pathData="M11,9H34"
android:strokeAlpha="0.8"
android:strokeWidth="8"
android:fillColor="#00000000"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
<path
android:pathData="M11,54H23"
android:strokeAlpha="0.8"
android:strokeWidth="8"
android:fillColor="#00000000"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
<path
android:pathData="M11,9L11,54"
android:strokeAlpha="0.8"
android:strokeWidth="8"
android:fillColor="#00000000"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
<path
android:pathData="M11,31L52,31"
android:strokeAlpha="0.8"
android:strokeWidth="8"
android:fillColor="#00000000"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
<path
android:pathData="M52,31L52,54"
android:strokeWidth="8"
android:fillColor="#00000000"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
<path
android:pathData="M34,21L34,54"
android:strokeWidth="8"
android:fillColor="#00000000"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
<path
android:pathData="M15,35H11C8.791,35 7,33.209 7,31C7,28.791 8.791,27 11,27H15V35Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
</group>
</vector>
@@ -42,7 +42,7 @@
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:padding="@dimen/keyline_margin"
app:srcCompat="@mipmap/ic_launcher" />
app:srcCompat="@drawable/ic_launcher_foreground" />
</LinearLayout>
@@ -102,6 +102,15 @@
</com.google.android.material.textfield.TextInputLayout>
<TextView
style="@style/TextAppearance.Material3.LabelLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:paddingTop="24dp"
android:maxWidth="@dimen/single_max_width"
android:text="@string/app_waring"/>
<Space
android:layout_width="match_parent"
android:layout_height="40dp" />
@@ -77,10 +77,11 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.hippo.widget.LoadImageView
<com.hippo.ehviewer.widget.FixedThumb
android:id="@+id/thumb"
android:layout_width="@dimen/gallery_detail_thumb_width"
android:layout_height="@dimen/gallery_detail_thumb_height" />
android:layout_height="@dimen/gallery_detail_thumb_height"
app:alwaysCutAndScale="true"/>
</com.google.android.material.card.MaterialCardView>
+3 -3
View File
@@ -29,10 +29,10 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.hippo.ehviewer.widget.FixedThumb
<com.hippo.ehviewer.widget.ResizeableFixedThumb
android:id="@+id/thumb"
android:layout_width="@dimen/gallery_list_thumb_width"
android:layout_height="@dimen/gallery_list_thumb_height"
android:layout_width="0dp"
android:layout_height="0dp"
app:alwaysCutAndScale="true"
app:retryType="longClick" />
@@ -15,6 +15,7 @@
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/card"
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="match_parent"
@@ -31,15 +32,15 @@
<com.google.android.material.card.MaterialCardView
android:id="@+id/thumb_card"
style="@style/Widget.Material3.CardView.Filled"
android:layout_width="@dimen/gallery_list_thumb_width"
android:layout_height="@dimen/gallery_list_thumb_height">
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.hippo.ehviewer.widget.FixedThumb
<com.hippo.ehviewer.widget.ResizeableFixedThumb
android:id="@+id/thumb"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_height="0dp"
app:alwaysCutAndScale="true"
app:retryType="click" />
app:retryType="click"/>
</com.google.android.material.card.MaterialCardView>
+10 -1
View File
@@ -38,7 +38,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:padding="@dimen/keyline_margin"
app:srcCompat="@mipmap/ic_launcher" />
app:srcCompat="@drawable/ic_launcher_foreground" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/username_layout"
@@ -83,6 +83,15 @@
</com.google.android.material.textfield.TextInputLayout>
<TextView
style="@style/TextAppearance.Material3.LabelLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:paddingTop="24dp"
android:maxWidth="@dimen/single_max_width"
android:text="@string/app_waring"/>
<Space
android:layout_width="wrap_content"
android:layout_height="0dp"
@@ -15,8 +15,9 @@
~ You should have received a copy of the GNU General Public License along with EhViewer.
~ If not, see <https://www.gnu.org/licenses/>.
-->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
<background android:drawable="@android:color/white"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>
@@ -15,8 +15,9 @@
~ You should have received a copy of the GNU General Public License along with EhViewer.
~ If not, see <https://www.gnu.org/licenses/>.
-->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
<background android:drawable="@android:color/white"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 838 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 832 B

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

+2 -1
View File
@@ -95,7 +95,7 @@
<string name="kokomade_tip">设置->Eh->画廊站点->e-hentai</string>
<string name="app_waring">本应用中内容来自互联网,部分内容可能对您的生理及心理造成难以恢复的伤害。本应用作者不会对由本应用造成的任何后果负责。\n\n未成年人应在监护人指导下使用本应用。</string>
<string name="app_waring">本应用中内容来自互联网,部分内容可能对您的生理及心理造成难以恢复的伤害。本应用作者不会对由本应用造成的任何后果负责。\n\n未成年人应在监护人指导下使用本应用。\n\n继续使用即代表您同意上述条款。</string>
<string name="error_username_cannot_empty">用户名不可为空</string>
<string name="error_password_cannot_empty">密码不可为空</string>
<string name="skip_signing_in">跳过登录</string>
@@ -768,4 +768,5 @@
<string name="archive_need_passwd">归档文件需要密码</string>
<string name="passwd_wrong">密码错误</string>
<string name="passwd_cannot_be_empty">密码不能为空</string>
<string name="list_tile_thumb_size">详情模式下缩略图大小</string>
</resources>
+1 -1
View File
@@ -95,7 +95,7 @@
<string name="kokomade_tip">設定->Eh->圖庫站台->e-hentai</string>
<string name="app_waring">本應用程式中內容來自網際網路,部分內容可能對您的生理及心理造成難以恢復的傷害。本應用程式的作者不會對由其所造成的任何影響負責。\n\n未成年人應在監護人指導下使用本應用程式。</string>
<string name="app_waring">本應用程式中內容來自網際網路,部分內容可能對您的生理及心理造成難以恢復的傷害。本應用程式的作者不會對由其所造成的任何影響負責。\n\n未成年人應在監護人指導下使用本應用程式。\n\n繼續使用即代表您同意上述條款。</string>
<string name="error_username_cannot_empty">使用者名稱欄位不能為空</string>
<string name="error_password_cannot_empty">密碼欄位不能為空</string>
<string name="skip_signing_in">略過登入</string>
-4
View File
@@ -134,10 +134,6 @@
<attr name="url" format="string" />
</declare-styleable>
<declare-styleable name="SeekBarPreference">
<attr name="max" format="integer" />
</declare-styleable>
<declare-styleable name="FastScroller">
<attr name="handler" format="reference" />
<attr name="draggable" format="boolean" />
@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ 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 GeneralPublic 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 <https://www.gnu.org/licenses/>.
-->
<resources>
<color name="ic_launcher_background">#E2E0D0</color>
<color name="ic_launcher_foreground">#5C0D11</color>
</resources>
-2
View File
@@ -31,8 +31,6 @@
<dimen name="rating_size">16dp</dimen>
<dimen name="rating_interval">1dp</dimen>
<dimen name="gallery_list_thumb_height">120dp</dimen>
<dimen name="gallery_list_thumb_width">80dp</dimen>
<!-- 4dp - 4dp, 4dp for card padding -->
<dimen name="gallery_list_interval">0dp</dimen>
<!-- 8dp - 4dp, 4dp for card padding -->
+2 -1
View File
@@ -137,7 +137,7 @@
<string name="kokomade_tip">Settings->Eh->Gallery Site->e-hentai</string>
<string name="app_waring">The content of this application is from the Internet. Some of it may do physical or mental harm to you. You have learnt the risks above and would like to undertake them.</string>
<string name="app_waring">The content of this application is from the Internet. Some of it may do physical or mental harm to you. You have learnt the risks above and would like to undertake them. By continuing to use it, you agree to the above terms.</string>
<string name="error_username_cannot_empty">Username cannot be an empty string</string>
<string name="error_password_cannot_empty">Password cannot be an empty string</string>
<string name="skip_signing_in">Continue without signing in</string>
@@ -832,4 +832,5 @@
<string name="archive_need_passwd">Archive need password</string>
<string name="passwd_wrong">Password Wrong</string>
<string name="passwd_cannot_be_empty">Password can\'t be empty</string>
<string name="list_tile_thumb_size">Thumb size in thumb mode</string>
</resources>
+9
View File
@@ -82,6 +82,15 @@
app:entryValues="@array/list_mode_entry_values"
app:iconSpaceReserved="false" />
<SeekBarPreference
android:defaultValue="40"
android:key="list_tile_size"
android:title="@string/list_tile_thumb_size"
android:max="60"
app:iconSpaceReserved="false"
app:min="30"
app:showSeekBarValue="true" />
<rikka.preference.SimpleMenuPreference
android:defaultValue="0"
android:key="detail_size"
+1 -1
View File
@@ -122,8 +122,8 @@
android:dependency="custom_screen_lightness"
android:key="screen_lightness"
android:title="@string/settings_read_screen_lightness"
android:max="200"
app:iconSpaceReserved="false"
app:max="200"
app:showSeekBarValue="true" />
</PreferenceScreen>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

+10
View File
@@ -0,0 +1,10 @@
<svg width="108" height="108" viewBox="0 0 108 108" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="108" height="108" rx="10" fill="white"/>
<path d="M32 31H55" stroke="#FBBD06" stroke-width="8" stroke-linecap="round"/>
<path d="M32 76H44" stroke="#FBBD06" stroke-width="8" stroke-linecap="round"/>
<line x1="32" y1="31" x2="32" y2="76" stroke="#35AA53" stroke-width="8" stroke-linecap="round"/>
<line x1="32" y1="53" x2="73" y2="53" stroke="#FBBD06" stroke-width="8" stroke-linecap="round"/>
<line x1="73" y1="53" x2="73" y2="76" stroke="#4586F3" stroke-width="8" stroke-linecap="round"/>
<path d="M55 43L55 76" stroke="#EB4334" stroke-width="8" stroke-linecap="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M36 57H32C29.7909 57 28 55.2091 28 53C28 50.7909 29.7909 49 32 49H36V57Z" fill="#FBBD06"/>
</svg>

After

Width:  |  Height:  |  Size: 832 B

+2 -2
View File
@@ -1,7 +1,7 @@
plugins {
id 'com.android.application' version '7.2.2' apply false
id 'org.jetbrains.kotlin.android' version '1.7.20-Beta' apply false
id 'com.google.devtools.ksp' version '1.7.20-Beta-1.0.6' apply false
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
id 'com.google.devtools.ksp' version '1.7.10-1.0.6' apply false
}
task clean(type: Delete) {
+1 -1
View File
@@ -11,7 +11,7 @@
</p>
<h1 align="center">
<img src="../../art/launcher_icon-web.png" width="200">
<img src="../../art/launcher_icon-web.svg" width="200">
<br>EhViewer<br>
</h1>
+1 -1
View File
@@ -11,7 +11,7 @@
</p>
<h1 align="center">
<img src="../../art/launcher_icon-web.png" width="200">
<img src="../../art/launcher_icon-web.svg" width="200">
<br>EhViewer<br>
</h1>
+1 -1
View File
@@ -11,7 +11,7 @@
</p>
<h1 align="center">
<img src="../../art/launcher_icon-web.png" width="200">
<img src="../../art/launcher_icon-web.svg" width="200">
<br>EhViewer<br>
</h1>
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+4
View File
@@ -4,6 +4,10 @@
"1.7.x.x"
],
"automerge": true,
"automergeType": "pr",
"automergeStrategy": "squash",
"extends": [
"config:base"
]