Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43ddf6ccc4 | ||
|
|
b55da640e1 | ||
|
|
90534c3c9f | ||
|
|
88c9e5e902 | ||
|
|
ac41117a78 | ||
|
|
2418c5f625 | ||
|
|
52156aa9ff | ||
|
|
6010fb69a4 | ||
|
|
d5abbb3584 | ||
|
|
8c27504ee2 | ||
|
|
8a20525da3 | ||
|
|
c7b8326b52 | ||
|
|
ee8b80651e | ||
|
|
589676c52a | ||
|
|
83085d5f9a | ||
|
|
a1a204d0d5 | ||
|
|
9a43c36758 | ||
|
|
e017efe35f | ||
|
|
1645c17ab7 | ||
|
|
075b800932 | ||
|
|
56f9138db4 | ||
|
|
20c1b7acdb | ||
|
|
a10022d797 | ||
|
|
aafbbbec38 | ||
|
|
028a994070 | ||
|
|
581125db62 | ||
|
|
295770002a | ||
|
|
1a66d84bd0 | ||
|
|
cd3f51b66d | ||
|
|
6d8ac4c3da | ||
|
|
156382eaad |
No files matched your search
@@ -25,7 +25,7 @@ jobs:
|
||||
sudo udevadm trigger --name-match=kvm
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
java-version: 21
|
||||
|
||||
- name: Install Rust Toolchain
|
||||
run: rustup target add armv7-linux-androideabi aarch64-linux-android x86_64-linux-android
|
||||
run: rustup target add armv7-linux-androideabi
|
||||
|
||||
- name: Rust Cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
java-version: 21
|
||||
|
||||
- name: Install Rust Toolchain
|
||||
run: rustup target add armv7-linux-androideabi aarch64-linux-android x86_64-linux-android
|
||||
run: rustup target add armv7-linux-androideabi
|
||||
|
||||
- name: Rust Cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
@@ -42,6 +42,9 @@ jobs:
|
||||
with:
|
||||
cache-read-only: true
|
||||
|
||||
- name: Check build-logic
|
||||
run: ./gradlew :build-logic:convention:check
|
||||
|
||||
- name: Spotless Check
|
||||
run: ./gradlew spotlessCheck
|
||||
|
||||
@@ -52,7 +55,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
@@ -61,7 +64,7 @@ jobs:
|
||||
java-version: 21
|
||||
|
||||
- name: Install Rust Toolchain
|
||||
run: rustup target add armv7-linux-androideabi aarch64-linux-android x86_64-linux-android
|
||||
run: rustup target add armv7-linux-androideabi
|
||||
|
||||
- name: Rust Cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
@@ -79,7 +82,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: app/.cxx
|
||||
key: cmake-default-${{ hashFiles('settings.gradle.kts', 'app/src/main/cpp/CMakeLists.txt', 'app/src/main/rust/Cargo.lock') }}
|
||||
key: cmake-default-${{ hashFiles('rust-toolchain.toml', 'settings.gradle.kts', 'app/src/main/cpp/CMakeLists.txt', 'app/src/main/rust/Cargo.lock') }}
|
||||
restore-keys: cmake-default-
|
||||
|
||||
- name: Build
|
||||
@@ -120,7 +123,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
@@ -129,7 +132,7 @@ jobs:
|
||||
java-version: 21
|
||||
|
||||
- name: Install Rust Toolchain
|
||||
run: rustup target add armv7-linux-androideabi aarch64-linux-android x86_64-linux-android
|
||||
run: rustup target add armv7-linux-androideabi
|
||||
|
||||
- name: Rust Cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
@@ -147,7 +150,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: app/.cxx
|
||||
key: cmake-marshmallow-${{ hashFiles('settings.gradle.kts', 'app/src/main/cpp/CMakeLists.txt', 'app/src/main/rust/Cargo.lock') }}
|
||||
key: cmake-marshmallow-${{ hashFiles('rust-toolchain.toml', 'settings.gradle.kts', 'app/src/main/cpp/CMakeLists.txt', 'app/src/main/rust/Cargo.lock') }}
|
||||
restore-keys: cmake-marshmallow-
|
||||
|
||||
- name: Build
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
sudo udevadm trigger --name-match=kvm
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
java-version: 21
|
||||
|
||||
- name: Install Rust Toolchain
|
||||
run: rustup target add armv7-linux-androideabi aarch64-linux-android x86_64-linux-android
|
||||
run: rustup target add armv7-linux-androideabi
|
||||
|
||||
- name: Rust Cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
+3
-2
@@ -1,8 +1,9 @@
|
||||
.gradle
|
||||
/local.properties
|
||||
.DS_Store
|
||||
/build
|
||||
/.kotlin
|
||||
build
|
||||
.cxx
|
||||
.kotlin
|
||||
*.iml
|
||||
.idea
|
||||
.vscode
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
# 变更日志
|
||||
|
||||
## [1.14.2] - 2025-08-16
|
||||
|
||||
### 改进
|
||||
|
||||
* [下载] 支持将最低下载速度设为 0 [#2545](https://github.com/FooIbar/EhViewer/issues/2545)
|
||||
* [下载] 移除令人困惑的连接超时设置 [#2556](https://github.com/FooIbar/EhViewer/issues/2556)
|
||||
|
||||
### Bug 修复
|
||||
|
||||
* 下载速度计算不准确导致下载失败误报 [#2545](https://github.com/FooIbar/EhViewer/issues/2545)
|
||||
* 无法解析带有 location: 标签的画廊
|
||||
|
||||
|
||||
## [1.14.1] - 2025-07-31
|
||||
|
||||
### 改进
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
/build
|
||||
/.cxx
|
||||
+12
-56
@@ -1,20 +1,15 @@
|
||||
import com.mikepenz.aboutlibraries.plugin.DuplicateMode
|
||||
import com.mikepenz.aboutlibraries.plugin.DuplicateRule
|
||||
import java.util.regex.Pattern
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode
|
||||
|
||||
val isRelease: Boolean
|
||||
get() = gradle.startParameter.taskNames.any { it.contains("Release") }
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.kotlin.compose)
|
||||
alias(libs.plugins.ehviewer.android.application)
|
||||
alias(libs.plugins.kotlin.serialization)
|
||||
alias(libs.plugins.ksp)
|
||||
alias(libs.plugins.spotless)
|
||||
alias(libs.plugins.aboutlibrariesPlugin)
|
||||
alias(libs.plugins.composeCompilerReportGenerator)
|
||||
alias(libs.plugins.baselineprofile)
|
||||
}
|
||||
|
||||
@@ -61,7 +56,7 @@ android {
|
||||
defaultConfig {
|
||||
applicationId = "moe.tarsin.ehviewer"
|
||||
versionCode = 180063
|
||||
versionName = "1.14.1"
|
||||
versionName = "1.14.2"
|
||||
// versionNameSuffix = "-SNAPSHOT"
|
||||
buildConfigField("String", "RAW_VERSION_NAME", "\"$versionName${versionNameSuffix.orEmpty()}\"")
|
||||
buildConfigField("String", "COMMIT_SHA", "\"$commitSha\"")
|
||||
@@ -79,9 +74,10 @@ android {
|
||||
flavorDimensions += "api"
|
||||
|
||||
productFlavors {
|
||||
create("default")
|
||||
create("default") {
|
||||
minSdk = 26
|
||||
}
|
||||
create("marshmallow") {
|
||||
minSdk = 23
|
||||
applicationIdSuffix = ".m"
|
||||
versionNameSuffix = "-M"
|
||||
}
|
||||
@@ -97,12 +93,6 @@ android {
|
||||
isCoreLibraryDesugaringEnabled = true
|
||||
}
|
||||
|
||||
lint {
|
||||
checkReleaseBuilds = false
|
||||
disable += setOf("MissingTranslation", "MissingQuantity")
|
||||
error += setOf("InlinedApi")
|
||||
}
|
||||
|
||||
packaging {
|
||||
dex {
|
||||
useLegacyPackaging = false
|
||||
@@ -176,6 +166,9 @@ baselineProfile {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.core.data)
|
||||
implementation(projects.core.i18n)
|
||||
|
||||
// https://developer.android.com/jetpack/androidx/releases/activity
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(libs.androidx.appcompat)
|
||||
@@ -189,7 +182,10 @@ dependencies {
|
||||
implementation(libs.compose.destinations.core)
|
||||
ksp(libs.compose.destinations.compiler)
|
||||
|
||||
implementation(libs.compose.preference)
|
||||
implementation(libs.compose.preference) {
|
||||
// R8 won't remove it because it adds a content provider
|
||||
exclude(group = "org.jetbrains.compose.components", module = "components-resources")
|
||||
}
|
||||
|
||||
implementation(libs.androidx.core)
|
||||
implementation(libs.androidx.core.splashscreen)
|
||||
@@ -254,38 +250,11 @@ dependencies {
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21)
|
||||
|
||||
// https://kotlinlang.org/docs/gradle-compiler-options.html#all-compiler-options
|
||||
compilerOptions {
|
||||
jvmDefault = JvmDefaultMode.NO_COMPATIBILITY
|
||||
progressiveMode = true
|
||||
optIn.addAll(
|
||||
"coil3.annotation.ExperimentalCoilApi",
|
||||
"androidx.compose.foundation.layout.ExperimentalLayoutApi",
|
||||
"androidx.compose.material3.ExperimentalMaterial3Api",
|
||||
"androidx.compose.material3.ExperimentalMaterial3ExpressiveApi",
|
||||
"androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi",
|
||||
"androidx.compose.ui.ExperimentalComposeUiApi",
|
||||
"androidx.compose.foundation.ExperimentalFoundationApi",
|
||||
"androidx.compose.animation.ExperimentalAnimationApi",
|
||||
"androidx.compose.animation.ExperimentalSharedTransitionApi",
|
||||
"androidx.compose.runtime.ExperimentalComposeRuntimeApi",
|
||||
"androidx.paging.ExperimentalPagingApi",
|
||||
"kotlin.ExperimentalStdlibApi",
|
||||
"kotlin.concurrent.atomics.ExperimentalAtomicApi",
|
||||
"kotlin.contracts.ExperimentalContracts",
|
||||
"kotlin.time.ExperimentalTime",
|
||||
"kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||
"kotlinx.coroutines.FlowPreview",
|
||||
"kotlinx.serialization.ExperimentalSerializationApi",
|
||||
"splitties.experimental.ExperimentalSplittiesApi",
|
||||
"splitties.preferences.DataStorePreferencesPreview",
|
||||
)
|
||||
freeCompilerArgs.addAll(
|
||||
"-Xcontext-parameters",
|
||||
"-Xwhen-expressions=indy",
|
||||
"-Xannotation-default-target=param-property",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -305,16 +274,3 @@ aboutLibraries {
|
||||
duplicationRule = DuplicateRule.GROUP
|
||||
}
|
||||
}
|
||||
|
||||
val ktlintVersion = libs.ktlint.get().version
|
||||
|
||||
spotless {
|
||||
kotlin {
|
||||
// https://github.com/diffplug/spotless/issues/111
|
||||
target("src/**/*.kt")
|
||||
ktlint(ktlintVersion)
|
||||
}
|
||||
kotlinGradle {
|
||||
ktlint(ktlintVersion)
|
||||
}
|
||||
}
|
||||
@@ -129,6 +129,8 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
set(ANDROID 1)
|
||||
endif ()
|
||||
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ../../../../rust-toolchain.toml)
|
||||
unset(Rust_TOOLCHAIN CACHE)
|
||||
FetchContent_Declare(
|
||||
Corrosion
|
||||
GIT_REPOSITORY https://github.com/corrosion-rs/corrosion.git
|
||||
|
||||
@@ -130,7 +130,7 @@ class EhApplication :
|
||||
launchIO { dataStateFlow.value }
|
||||
launchIO { OSUtils.totalMemory }
|
||||
launch {
|
||||
if (DownloadManager.labelList.isNotEmpty() && Settings.downloadFilterMode.key !in Settings.prefs) {
|
||||
if (DownloadManager.labelList.isNotEmpty() && Settings.downloadFilterMode !in Settings.snapshot()) {
|
||||
Settings.downloadFilterMode.value = DownloadsFilterMode.CUSTOM.flag
|
||||
}
|
||||
DownloadManager.readMetadataFromLocal()
|
||||
|
||||
@@ -9,6 +9,9 @@ import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import com.ehviewer.core.preferences.DataStorePreferences
|
||||
import com.ehviewer.core.preferences.PrefDelegate
|
||||
import com.ehviewer.core.preferences.edit
|
||||
import com.hippo.ehviewer.client.EhCookieStore
|
||||
import com.hippo.ehviewer.client.data.FavListUrlBuilder
|
||||
import com.hippo.ehviewer.download.DownloadsFilterMode
|
||||
@@ -25,47 +28,12 @@ import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.flatMapMerge
|
||||
import kotlinx.coroutines.flow.map
|
||||
import splitties.preferences.BoolPref
|
||||
import splitties.preferences.DataStorePreferences
|
||||
import splitties.preferences.FloatPref
|
||||
import splitties.preferences.IntPref
|
||||
import splitties.preferences.LongPref
|
||||
import splitties.preferences.PrefDelegate
|
||||
import splitties.preferences.StringOrNullPref
|
||||
import splitties.preferences.StringPref
|
||||
import splitties.preferences.StringSetOrNullPref
|
||||
import splitties.preferences.StringSetPref
|
||||
import splitties.preferences.edit
|
||||
|
||||
@Suppress("IMPLICIT_CAST_TO_ANY", "UNCHECKED_CAST")
|
||||
fun <T> PrefDelegate<T>.getValue(): T = when (this) {
|
||||
is BoolPref -> value
|
||||
is IntPref -> value
|
||||
is FloatPref -> value
|
||||
is LongPref -> value
|
||||
is StringPref -> value
|
||||
is StringOrNullPref -> value
|
||||
is StringSetPref -> value
|
||||
is StringSetOrNullPref -> value
|
||||
} as T
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T> PrefDelegate<T>.setValue(newValue: T) = when (this) {
|
||||
is BoolPref -> value = newValue as Boolean
|
||||
is IntPref -> value = newValue as Int
|
||||
is FloatPref -> value = newValue as Float
|
||||
is LongPref -> value = newValue as Long
|
||||
is StringPref -> value = newValue as String
|
||||
is StringOrNullPref -> value = newValue as? String
|
||||
is StringSetPref -> value = newValue as Set<String?>
|
||||
is StringSetOrNullPref -> value = newValue as? Set<String?>
|
||||
}
|
||||
|
||||
@Stable
|
||||
@Composable
|
||||
inline fun <R, T> PrefDelegate<T>.collectAsState(crossinline transform: @DisallowComposableCalls (T) -> R): State<R> {
|
||||
val flow = remember { valueFlow().map { transform(it) } }
|
||||
val init = getValue()
|
||||
val init = value
|
||||
return flow.collectAsState(transform(init))
|
||||
}
|
||||
|
||||
@@ -73,32 +41,28 @@ inline fun <R, T> PrefDelegate<T>.collectAsState(crossinline transform: @Disallo
|
||||
@Composable
|
||||
fun <T> PrefDelegate<T>.collectAsState(): State<T> {
|
||||
val flow = remember { valueFlow() }
|
||||
val init = getValue()
|
||||
val init = value
|
||||
return flow.collectAsState(init)
|
||||
}
|
||||
|
||||
@Stable
|
||||
@Composable
|
||||
fun <T> PrefDelegate<T>.asMutableState(): MutableState<T> {
|
||||
val flow = remember { valueFlow() }
|
||||
val init = getValue()
|
||||
val readOnly = flow.collectAsState(init)
|
||||
val readOnly = collectAsState()
|
||||
return remember {
|
||||
object : MutableState<T> {
|
||||
override var value: T
|
||||
get() = readOnly.value
|
||||
set(value) {
|
||||
setValue(value)
|
||||
this@asMutableState.value = value
|
||||
}
|
||||
override fun component1() = readOnly.value
|
||||
override fun component2() = ::setValue
|
||||
override fun component2() = this@asMutableState::value::set
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object Settings : DataStorePreferences(null) {
|
||||
private const val KEY_SHOW_TAG_TRANSLATIONS = "show_tag_translations"
|
||||
|
||||
@Suppress("ktlint:standard:backing-property-naming")
|
||||
private val _favFlow = MutableSharedFlow<Unit>()
|
||||
val favChangesFlow = _favFlow.debounce(1000)
|
||||
@@ -107,9 +71,9 @@ object Settings : DataStorePreferences(null) {
|
||||
var favCloudCount by intPref("fav_cloud", 0).emitTo(_favFlow)
|
||||
|
||||
// Eh
|
||||
val gallerySite = intPref("gallery_site_2", 0).observed { updateWhenGallerySiteChanges() }
|
||||
val gallerySite = intPref("gallery_site_2", 0).observed(::updateWhenGallerySiteChanges)
|
||||
val defaultFavSlot = intPref("default_favorite_slot", -2)
|
||||
val theme = intPref("theme_2", -1).observed { updateWhenThemeChanges() }
|
||||
val theme = intPref("theme_2", -1).observed(::updateWhenThemeChanges)
|
||||
val blackDarkTheme = boolPref("black_dark_theme", false)
|
||||
val harmonizeCategoryColor = boolPref("harmonize_category_color", true)
|
||||
val launchPage = intPref("launch_page_2", 0)
|
||||
@@ -121,17 +85,16 @@ object Settings : DataStorePreferences(null) {
|
||||
val showVoteStatus = boolPref("show_vote_status", false)
|
||||
val showComments = boolPref("show_gallery_comments", true)
|
||||
val commentThreshold = intPref("comment_threshold", -100)
|
||||
val showTagTranslations = boolPref(KEY_SHOW_TAG_TRANSLATIONS, false).observed { updateWhenTagTranslationChanges() }
|
||||
val showTagTranslations = boolPref("show_tag_translations", false).observed(::updateWhenTagTranslationChanges)
|
||||
val meteredNetworkWarning = boolPref("cellular_network_warning", false)
|
||||
val showJpnTitle = boolPref("show_jpn_title", false)
|
||||
val requestNews = boolPref("request_news", false).observed { updateWhenRequestNewsChanges() }
|
||||
val hideHvEvents = boolPref("hide_hv_events", false)
|
||||
|
||||
// Download
|
||||
val mediaScan = boolPref("media_scan", false).observed { updateWhenKeepMediaStatusChanges() }
|
||||
val mediaScan = boolPref("media_scan", false).observed(::updateWhenKeepMediaStatusChanges)
|
||||
val multiThreadDownload = intPref("download_thread_2", 3)
|
||||
val downloadDelay = intPref("download_delay_3", 1000)
|
||||
val connTimeout = intPref("conn_timeout", 10)
|
||||
val timeoutSpeed = intPref("timeout_speed_level", 6)
|
||||
val preloadImage = intPref("preload_image_2", 5)
|
||||
val downloadOriginImage = boolPref("download_origin_image", false)
|
||||
@@ -167,15 +130,15 @@ object Settings : DataStorePreferences(null) {
|
||||
val needSignIn = boolPref("need_sign_in", true)
|
||||
val gridView = boolPref("grid_view", false)
|
||||
val qSSaveProgress = boolPref("qs_save_progress", true)
|
||||
val displayName = stringOrNullPref("display_name", null)
|
||||
val avatar = stringOrNullPref("avatar", null)
|
||||
val recentDownloadLabel = stringOrNullPref("recent_download_label", null)
|
||||
val displayName = stringOrNullPref("display_name")
|
||||
val avatar = stringOrNullPref("avatar")
|
||||
val recentDownloadLabel = stringOrNullPref("recent_download_label")
|
||||
|
||||
var downloadScheme by stringOrNullPref("image_scheme", null)
|
||||
var downloadAuthority by stringOrNullPref("image_authority", null)
|
||||
var downloadPath by stringOrNullPref("image_path", null)
|
||||
var downloadQuery by stringOrNullPref("image_query", null)
|
||||
var downloadFragment by stringOrNullPref("image_fragment", null)
|
||||
var downloadScheme by stringOrNullPref("image_scheme")
|
||||
var downloadAuthority by stringOrNullPref("image_authority")
|
||||
var downloadPath by stringOrNullPref("image_path")
|
||||
var downloadQuery by stringOrNullPref("image_query")
|
||||
var downloadFragment by stringOrNullPref("image_fragment")
|
||||
var archivePasswds by stringSetPref("archive_passwds")
|
||||
var appLinkVerifyTip by boolPref("app_link_verify_tip", false)
|
||||
var hasDefaultDownloadLabel by boolPref("has_default_download_label", false)
|
||||
@@ -185,7 +148,7 @@ object Settings : DataStorePreferences(null) {
|
||||
var requestNewsTime by intPref("request_news_time", 0).observed { updateWhenRequestNewsChanges() }
|
||||
var lastDawnDays by intPref("last_dawn_days", 0)
|
||||
var recentToplist by stringPref("recent_toplist", "11")
|
||||
var defaultDownloadLabel by stringOrNullPref("default_download_label", null)
|
||||
var defaultDownloadLabel by stringOrNullPref("default_download_label")
|
||||
var lastUpdateTime by longPref("last_update_time", BuildConfig.COMMIT_TIME)
|
||||
|
||||
// Reader
|
||||
@@ -223,43 +186,39 @@ object Settings : DataStorePreferences(null) {
|
||||
val stripExtraneousAds = boolPref("strip_extraneous_ads", false)
|
||||
|
||||
init {
|
||||
if ("CN" == Locale.getDefault().country) {
|
||||
edit {
|
||||
if (KEY_SHOW_TAG_TRANSLATIONS !in prefs) showTagTranslations.value = true
|
||||
edit { pref ->
|
||||
if ("CN" == Locale.getDefault().country) {
|
||||
if (showTagTranslations !in pref) pref[showTagTranslations] = true
|
||||
}
|
||||
if (pref[downloadFilterMode] == DownloadsFilterMode.ARTIST.flag && pref[recentDownloadLabel] == null) {
|
||||
pref[recentDownloadLabel] = ""
|
||||
}
|
||||
}
|
||||
if (downloadFilterMode.value == DownloadsFilterMode.ARTIST.flag && recentDownloadLabel.value == null) {
|
||||
recentDownloadLabel.value = ""
|
||||
}
|
||||
}
|
||||
|
||||
interface Delegate<R> {
|
||||
val flowGetter: () -> Flow<Unit>
|
||||
fun changesFlow(): Flow<Unit>
|
||||
operator fun getValue(thisRef: Any?, prop: KProperty<*>?): R
|
||||
operator fun setValue(thisRef: Any?, prop: KProperty<*>?, value: R)
|
||||
}
|
||||
|
||||
private fun intArrayPref(key: String, count: Int) = object : Delegate<IntArray> {
|
||||
override val flowGetter: () -> Flow<Unit> = { _value.asFlow().flatMapMerge { it.changesFlow() }.conflate() }
|
||||
|
||||
@Suppress("ktlint:standard:backing-property-naming")
|
||||
private var _value = (0 until count).map { intPref("${key}_$it", 0) }.toTypedArray()
|
||||
override fun getValue(thisRef: Any?, prop: KProperty<*>?): IntArray = _value.map { it.value }.toIntArray()
|
||||
private val delegates = Array(count) { intPref("${key}_$it", 0) }
|
||||
override fun changesFlow(): Flow<Unit> = delegates.asFlow().flatMapMerge { it.changesFlow() }.conflate()
|
||||
override fun getValue(thisRef: Any?, prop: KProperty<*>?) = IntArray(delegates.size) { delegates[it].value }
|
||||
override fun setValue(thisRef: Any?, prop: KProperty<*>?, value: IntArray) {
|
||||
check(value.size == count)
|
||||
edit { value.zip(_value) { v, d -> d.value = v } }
|
||||
edit { pref -> value.zip(delegates) { v, d -> pref[d] = v } }
|
||||
}
|
||||
}
|
||||
|
||||
private fun stringArrayPref(key: String, count: Int, defMetaValue: String) = object : Delegate<Array<String>> {
|
||||
override val flowGetter: () -> Flow<Unit> = { _value.asFlow().flatMapMerge { it.changesFlow() }.conflate() }
|
||||
|
||||
@Suppress("ktlint:standard:backing-property-naming")
|
||||
private var _value = (0 until count).map { stringPref("${key}_$it", "$defMetaValue $it") }.toTypedArray()
|
||||
override fun getValue(thisRef: Any?, prop: KProperty<*>?): Array<String> = _value.map { it.value }.toTypedArray()
|
||||
private val delegates = Array(count) { stringPref("${key}_$it", "$defMetaValue $it") }
|
||||
override fun changesFlow(): Flow<Unit> = delegates.asFlow().flatMapMerge { it.changesFlow() }.conflate()
|
||||
override fun getValue(thisRef: Any?, prop: KProperty<*>?) = Array(delegates.size) { delegates[it].value }
|
||||
override fun setValue(thisRef: Any?, prop: KProperty<*>?, value: Array<String>) {
|
||||
check(value.size == count)
|
||||
edit { value.zip(_value) { v, d -> d.value = v } }
|
||||
edit { pref -> value.zip(delegates) { v, d -> pref[d] = v } }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,68 +2,73 @@ package com.hippo.ehviewer
|
||||
|
||||
import android.app.UiModeManager
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import arrow.core.Either.Companion.catch
|
||||
import com.ehviewer.core.preferences.PrefDelegate
|
||||
import com.hippo.ehviewer.client.EhEngine
|
||||
import com.hippo.ehviewer.client.EhTagDatabase
|
||||
import com.hippo.ehviewer.dailycheck.updateDailyCheckWork
|
||||
import com.hippo.ehviewer.ui.keepNoMediaFileStatus
|
||||
import com.hippo.ehviewer.util.isAtLeastS
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.launch
|
||||
import splitties.init.appCtx
|
||||
import splitties.preferences.PrefDelegate
|
||||
import splitties.systemservices.uiModeManager
|
||||
|
||||
private val collectScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||
fun <T, R : PrefDelegate<T>> R.observed(func: (Unit) -> Unit) = apply { collectScope.launch { changesFlow().collect(func) } }
|
||||
fun <T, R : Settings.Delegate<T>> R.observed(func: (Unit) -> Unit) = apply { collectScope.launch { flowGetter().collect(func) } }
|
||||
fun <T, R : Settings.Delegate<T>> R.emitTo(flow: MutableSharedFlow<Unit>) = apply { collectScope.launch { flowGetter().collect { flow.emit(Unit) } } }
|
||||
fun <T, R : PrefDelegate<T>> R.emitTo(flow: MutableSharedFlow<Unit>) = apply { collectScope.launch { changesFlow().collect { flow.emit(Unit) } } }
|
||||
private const val TAG = "SettingsCollector"
|
||||
|
||||
fun updateWhenKeepMediaStatusChanges() {
|
||||
collectScope.launchIO {
|
||||
runCatching {
|
||||
keepNoMediaFileStatus()
|
||||
private val collectScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||
fun <T, R : PrefDelegate<T>> R.observed(func: suspend (T) -> Unit) = apply { collectScope.launch { valueFlow().drop(1).collectLatest(func) } }
|
||||
fun <T, R : Settings.Delegate<T>> R.emitTo(flow: MutableSharedFlow<Unit>) = apply { collectScope.launch { flow.emitAll(changesFlow()) } }
|
||||
fun <T, R : PrefDelegate<T>> R.emitTo(flow: MutableSharedFlow<Unit>) = apply { collectScope.launch { flow.emitAll(changesFlow()) } }
|
||||
|
||||
suspend fun updateWhenKeepMediaStatusChanges(mediaScan: Boolean) {
|
||||
withIOContext {
|
||||
catch {
|
||||
keepNoMediaFileStatus(mediaScan = mediaScan)
|
||||
}.onLeft {
|
||||
logcat(TAG, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateWhenThemeChanges() {
|
||||
collectScope.launch {
|
||||
delay(100) // Avoid recompose being cancelled
|
||||
if (isAtLeastS) {
|
||||
val mode = when (Settings.theme.value) {
|
||||
AppCompatDelegate.MODE_NIGHT_NO -> UiModeManager.MODE_NIGHT_NO
|
||||
AppCompatDelegate.MODE_NIGHT_YES -> UiModeManager.MODE_NIGHT_YES
|
||||
else -> UiModeManager.MODE_NIGHT_AUTO
|
||||
}
|
||||
uiModeManager.setApplicationNightMode(mode)
|
||||
suspend fun updateWhenThemeChanges(theme: Int) {
|
||||
delay(100) // Avoid recompose being cancelled
|
||||
if (isAtLeastS) {
|
||||
val mode = when (theme) {
|
||||
AppCompatDelegate.MODE_NIGHT_NO -> UiModeManager.MODE_NIGHT_NO
|
||||
AppCompatDelegate.MODE_NIGHT_YES -> UiModeManager.MODE_NIGHT_YES
|
||||
else -> UiModeManager.MODE_NIGHT_AUTO
|
||||
}
|
||||
AppCompatDelegate.setDefaultNightMode(Settings.theme.value)
|
||||
uiModeManager.setApplicationNightMode(mode)
|
||||
}
|
||||
AppCompatDelegate.setDefaultNightMode(theme)
|
||||
}
|
||||
|
||||
fun updateWhenRequestNewsChanges() {
|
||||
updateDailyCheckWork(appCtx)
|
||||
}
|
||||
|
||||
fun updateWhenGallerySiteChanges() {
|
||||
suspend fun updateWhenGallerySiteChanges(gallerySite: Int) {
|
||||
if (Settings.hasSignedIn.value) {
|
||||
collectScope.launchIO {
|
||||
runCatching {
|
||||
EhEngine.getUConfig()
|
||||
}.onFailure {
|
||||
logcat(it)
|
||||
}
|
||||
catch {
|
||||
EhEngine.getUConfig(gallerySite)
|
||||
}.onLeft {
|
||||
logcat(TAG, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateWhenTagTranslationChanges() {
|
||||
EhTagDatabase.launchUpdate()
|
||||
fun updateWhenTagTranslationChanges(enabled: Boolean) {
|
||||
if (enabled) {
|
||||
EhTagDatabase.launchUpdate()
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,8 @@ import arrow.core.partially2
|
||||
import arrow.core.right
|
||||
import arrow.fx.coroutines.parMap
|
||||
import arrow.fx.coroutines.parZip
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
import com.hippo.ehviewer.client.data.FavListUrlBuilder
|
||||
@@ -212,7 +212,8 @@ object EhEngine {
|
||||
return ehRequest(url, EhUrl.URL_FORUMS).fetchUsingAsByteBuffer(ProfileParser::parse)
|
||||
}
|
||||
|
||||
suspend fun getUConfig(url: String = EhUrl.uConfigUrl) {
|
||||
suspend fun getUConfig(gallerySite: Int) {
|
||||
val url = EhUrl.getUConfigUrl(gallerySite)
|
||||
runSuspendCatching {
|
||||
ehRequest(url).fetchUsingAsByteBuffer(UserConfigParser::parse)
|
||||
}.onFailure { throwable ->
|
||||
|
||||
@@ -68,6 +68,7 @@ object EhTagDatabase : CoroutineScope {
|
||||
// Copied from https://github.com/EhTagTranslation/EhSyringe/blob/c0cf88da04081072492829673aca34380b14dae6/src/plugin/suggest.ts#L37
|
||||
// TODO: Optimize
|
||||
private val nsScore = mapOf(
|
||||
TagNamespace.Location.prefix to 10f,
|
||||
TagNamespace.Other.prefix to 10f,
|
||||
TagNamespace.Female.prefix to 9f,
|
||||
TagNamespace.Male.prefix to 8.5f,
|
||||
|
||||
@@ -80,12 +80,11 @@ object EhUrl {
|
||||
else -> ORIGIN_E
|
||||
}
|
||||
|
||||
val uConfigUrl: String
|
||||
get() = when (Settings.gallerySite.value) {
|
||||
SITE_E -> URL_UCONFIG_E
|
||||
SITE_EX -> URL_UCONFIG_EX
|
||||
else -> URL_UCONFIG_E
|
||||
}
|
||||
fun getUConfigUrl(gallerySite: Int = Settings.gallerySite.value) = when (gallerySite) {
|
||||
SITE_E -> URL_UCONFIG_E
|
||||
SITE_EX -> URL_UCONFIG_EX
|
||||
else -> URL_UCONFIG_E
|
||||
}
|
||||
|
||||
val myTagsUrl: String
|
||||
get() = when (Settings.gallerySite.value) {
|
||||
|
||||
@@ -16,6 +16,7 @@ sealed class TagNamespace(val value: String, val prefix: String?) {
|
||||
object Female : TagNamespace("female", "f")
|
||||
object Group : TagNamespace("group", "g")
|
||||
object Language : TagNamespace("language", "l")
|
||||
object Location : TagNamespace("location", "loc")
|
||||
object Male : TagNamespace("male", "m")
|
||||
object Mixed : TagNamespace("mixed", "x")
|
||||
object Other : TagNamespace("other", "o")
|
||||
@@ -31,6 +32,7 @@ sealed class TagNamespace(val value: String, val prefix: String?) {
|
||||
Female.value -> Female
|
||||
Group.value -> Group
|
||||
Language.value -> Language
|
||||
Location.value -> Location
|
||||
Male.value -> Male
|
||||
Mixed.value -> Mixed
|
||||
Other.value -> Other
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
package com.hippo.ehviewer.client.exception
|
||||
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
|
||||
class CloudflareBypassException : EhException(R.string.cloudflare_bypass_failed)
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
package com.hippo.ehviewer.client.exception
|
||||
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
|
||||
class InsufficientFundsException : EhException(R.string.insufficient_funds)
|
||||
@@ -15,6 +15,6 @@
|
||||
*/
|
||||
package com.hippo.ehviewer.client.exception
|
||||
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
|
||||
class NoHathClientException() : EhException(R.string.download_archive_failure_no_hath)
|
||||
@@ -1,5 +1,5 @@
|
||||
package com.hippo.ehviewer.client.exception
|
||||
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
|
||||
class NoHitsFoundException : EhException(R.string.gallery_list_empty_hit)
|
||||
@@ -1,5 +1,5 @@
|
||||
package com.hippo.ehviewer.client.exception
|
||||
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
|
||||
class NotLoggedInException : EhException(R.string.sign_in_first)
|
||||
@@ -1,5 +1,5 @@
|
||||
package com.hippo.ehviewer.client.exception
|
||||
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
|
||||
class QuotaExceededException : EhException(R.string.error_509)
|
||||
@@ -5,6 +5,7 @@ import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.MapColumn
|
||||
import androidx.room.Query
|
||||
import androidx.room.RoomWarnings
|
||||
import androidx.room.Transaction
|
||||
import androidx.room.Update
|
||||
import androidx.room.Upsert
|
||||
@@ -12,11 +13,12 @@ import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface DownloadsDao {
|
||||
@Suppress("ktlint:standard:annotation")
|
||||
// https://issuetracker.google.com/327583152
|
||||
@Suppress("ktlint:standard:annotation", RoomWarnings.UNNECESSARY_NULLABILITY_IN_DAO_RETURN_TYPE)
|
||||
@Query("SELECT LABEL, COUNT(*) AS COUNT FROM DOWNLOADS LEFT JOIN DOWNLOAD_LABELS USING(LABEL) GROUP BY LABEL")
|
||||
fun countByLabel(): Flow<Map<@MapColumn("LABEL") String?, @MapColumn("COUNT") Int>>
|
||||
|
||||
@Suppress("ktlint:standard:annotation")
|
||||
@Suppress("ktlint:standard:annotation", RoomWarnings.UNNECESSARY_NULLABILITY_IN_DAO_RETURN_TYPE)
|
||||
@Query("SELECT ARTIST, COUNT(*) AS COUNT FROM DOWNLOADS LEFT JOIN DOWNLOAD_ARTISTS USING(GID) GROUP BY ARTIST ORDER BY COUNT DESC, ARTIST")
|
||||
fun countByArtist(): Flow<Map<@MapColumn("ARTIST") String?, @MapColumn("COUNT") Int>>
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.core.util.size
|
||||
import arrow.fx.coroutines.parMapNotNull
|
||||
import com.ehviewer.core.preferences.edit
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
@@ -64,7 +65,6 @@ import logcat.LogPriority
|
||||
import okio.Path
|
||||
import okio.Path.Companion.toOkioPath
|
||||
import okio.Path.Companion.toPath
|
||||
import splitties.preferences.edit
|
||||
|
||||
object DownloadManager : OnSpiderListener, CoroutineScope {
|
||||
override val coroutineContext = Dispatchers.IO + Job()
|
||||
@@ -711,9 +711,7 @@ object DownloadManager : OnSpiderListener, CoroutineScope {
|
||||
fun start() {
|
||||
if (currentJob == null) {
|
||||
currentJob = launch {
|
||||
tracker.speedFlow().collect { speed ->
|
||||
updateSpeed(speed.toLong())
|
||||
}
|
||||
tracker.speedFlow().collect(::updateSpeed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.savedstate.serialization.decodeFromSavedState
|
||||
import androidx.savedstate.serialization.encodeToSavedState
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.client.EhUtils
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
import com.hippo.ehviewer.dao.DownloadInfo
|
||||
@@ -137,7 +137,7 @@ class DownloadService :
|
||||
.setAutoCancel(false)
|
||||
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
|
||||
.addAction(
|
||||
R.drawable.v_pause_x24,
|
||||
com.hippo.ehviewer.R.drawable.v_pause_x24,
|
||||
getString(R.string.stat_download_action_stop_all),
|
||||
piStopAll,
|
||||
)
|
||||
@@ -174,7 +174,7 @@ class DownloadService :
|
||||
|
||||
private fun init509Notification(): NotificationHandler {
|
||||
val builder = NotificationCompat.Builder(applicationContext, channelId)
|
||||
.setSmallIcon(R.drawable.ic_baseline_warning_24)
|
||||
.setSmallIcon(com.hippo.ehviewer.R.drawable.ic_baseline_warning_24)
|
||||
.setContentTitle(getString(R.string.stat_509_alert_title))
|
||||
.setContentText(getString(R.string.stat_509_alert_text))
|
||||
.setStyle(
|
||||
|
||||
@@ -53,7 +53,7 @@ suspend inline fun <T> useArchivePageLoader(
|
||||
{ _, _ -> closeArchive() },
|
||||
)
|
||||
check(size > 0) { "Archive have no content!" }
|
||||
if (needPassword() && archivePasswds.filterNotNull().none(::providePassword)) {
|
||||
if (needPassword() && archivePasswds.none(::providePassword)) {
|
||||
archivePasswds += passwdProvider(::providePassword)
|
||||
}
|
||||
val loader = install(
|
||||
|
||||
@@ -10,6 +10,7 @@ import android.net.http.UrlRequest
|
||||
import android.net.http.UrlResponseInfo
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresExtension
|
||||
import com.ehviewer.core.preferences.edit
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.util.restartApplication
|
||||
import io.ktor.client.engine.HttpClientEngineBase
|
||||
@@ -40,7 +41,6 @@ import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.channels.consumeEach
|
||||
import kotlinx.coroutines.job
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import splitties.preferences.edit
|
||||
|
||||
class CronetEngine(override val config: CronetConfig) : HttpClientEngineBase("Cronet") {
|
||||
// Limit thread to 1 since we are async & non-blocking
|
||||
@@ -108,7 +108,7 @@ class CronetEngine(override val config: CronetConfig) : HttpClientEngineBase("Cr
|
||||
val message = error.message.orEmpty()
|
||||
if ("ERR_FILE_NOT_FOUND" in message || "ERR_PROXY_CONNECTION_FAILED" in message) {
|
||||
Settings.edit(true) {
|
||||
enableCronet.value = false
|
||||
it[enableCronet] = false
|
||||
}
|
||||
with(config.context) { restartApplication() }
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.hippo.ehviewer.client.data.TagNamespace.Character
|
||||
import com.hippo.ehviewer.client.data.TagNamespace.Cosplayer
|
||||
import com.hippo.ehviewer.client.data.TagNamespace.Female
|
||||
import com.hippo.ehviewer.client.data.TagNamespace.Group
|
||||
import com.hippo.ehviewer.client.data.TagNamespace.Location
|
||||
import com.hippo.ehviewer.client.data.TagNamespace.Male
|
||||
import com.hippo.ehviewer.client.data.TagNamespace.Mixed
|
||||
import com.hippo.ehviewer.client.data.TagNamespace.Other
|
||||
@@ -60,7 +61,7 @@ fun GalleryInfo.getComicInfo(): ComicInfo {
|
||||
Group -> groups.addAll(list)
|
||||
Character -> characters.addAll(list)
|
||||
Parody -> parodies.addAll(list)
|
||||
Other -> otherTags.addAll(list)
|
||||
Location, Other -> otherTags.addAll(list)
|
||||
Female, Male, Mixed -> ns.prefix.let { prefix ->
|
||||
list.forEach { tag -> otherTags.add("$prefix:$tag") }
|
||||
}
|
||||
@@ -76,7 +77,7 @@ fun GalleryInfo.getComicInfo(): ComicInfo {
|
||||
Group -> groups.add(tag)
|
||||
Character -> characters.add(tag)
|
||||
Parody -> if (tag != TAG_ORIGINAL) parodies.add(tag)
|
||||
Other -> otherTags.add(tag)
|
||||
Location, Other -> otherTags.add(tag)
|
||||
Female, Male, Mixed -> ns.prefix.let { otherTags.add("$it:$tag") }
|
||||
else -> Unit
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import kotlin.time.Duration.Companion.seconds
|
||||
import kotlin.time.Instant
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
@@ -47,7 +47,7 @@ class SpeedTracker(val window: Duration = 1.seconds) {
|
||||
}
|
||||
}
|
||||
|
||||
fun speedFlow(sample: Duration = 1.seconds) = fixedRate(sample).map {
|
||||
fun speedFlow(sample: Duration = 1.seconds) = fixedRate(sample).mapNotNull {
|
||||
mutex.withLock {
|
||||
start?.let { start ->
|
||||
val now = Clock.System.now()
|
||||
@@ -55,8 +55,8 @@ class SpeedTracker(val window: Duration = 1.seconds) {
|
||||
val window = passed.coerceIn(10.milliseconds, window)
|
||||
val cutoff = now - window
|
||||
received.removeIf { time, _ -> time < cutoff }
|
||||
received.fold(0) { total, _, v -> total + v } / (window / 1.seconds)
|
||||
} ?: 0.0
|
||||
(received.fold(0) { total, _, v -> total + v } / (window / 1.seconds)).toLong()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,16 +72,21 @@ suspend inline fun <R> timeoutBySpeed(
|
||||
) = coroutineScope {
|
||||
val onTimeout = AtomicReference<OnTimeout?>(t).let { { e: IOException -> it.exchange(null)?.invoke(e) } }
|
||||
val watchdog = launch {
|
||||
delay(Settings.connTimeout.value.seconds)
|
||||
onTimeout(ConnectTimeoutException(url, Settings.connTimeout.value * 1000L))
|
||||
val timeout = 10.seconds
|
||||
delay(timeout)
|
||||
onTimeout(ConnectTimeoutException(url, timeout.inWholeMilliseconds))
|
||||
}
|
||||
val tracker = SpeedTracker(2.seconds)
|
||||
request {
|
||||
var prev = 0L
|
||||
onDownload { done, total ->
|
||||
val bytesRead = (done - prev).toInt()
|
||||
tracker.track(bytesRead)
|
||||
l(total!!, done, bytesRead)
|
||||
if (done == total!!) {
|
||||
tracker.reset()
|
||||
} else {
|
||||
tracker.track(bytesRead)
|
||||
}
|
||||
l(total, done, bytesRead)
|
||||
prev = done
|
||||
}
|
||||
timeout { reset() }
|
||||
@@ -89,10 +94,10 @@ suspend inline fun <R> timeoutBySpeed(
|
||||
watchdog.cancel()
|
||||
resp.status.ensureSuccess()
|
||||
val speedWatchdog = launch {
|
||||
val timeoutSpeed = speedLevelToSpeed(Settings.timeoutSpeed.value) * 1024.0
|
||||
tracker.speedFlow(1.seconds).collect { speed ->
|
||||
if (timeoutSpeed != 0.0 && speed < timeoutSpeed) {
|
||||
onTimeout(LowSpeedException(url, speed.toLong()))
|
||||
val timeoutSpeed = speedLevelToSpeed(Settings.timeoutSpeed.value) * 1024L
|
||||
tracker.speedFlow().collect { speed ->
|
||||
if (speed < timeoutSpeed) {
|
||||
onTimeout(LowSpeedException(url, speed))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,7 +109,9 @@ suspend inline fun <R> timeoutBySpeed(
|
||||
}
|
||||
}
|
||||
|
||||
fun speedLevelToSpeed(level: Int) = 2f.pow(level).roundToInt()
|
||||
const val MIN_SPEED_LEVEL = 3
|
||||
|
||||
fun speedLevelToSpeed(level: Int) = if (level == MIN_SPEED_LEVEL) 0 else 2f.pow(level).roundToInt()
|
||||
|
||||
inline fun <T, R> MutableObjectIntMap<T>.fold(initial: R, operation: (acc: R, T, Int) -> R): R {
|
||||
var accumulator = initial
|
||||
|
||||
@@ -20,7 +20,7 @@ import androidx.annotation.IntDef
|
||||
import arrow.core.Either
|
||||
import arrow.core.getOrElse
|
||||
import arrow.core.partially1
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhEngine
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
|
||||
@@ -35,8 +35,8 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhEngine
|
||||
import com.hippo.ehviewer.client.EhUtils
|
||||
@@ -100,10 +100,10 @@ private fun ensureNoMediaFile(downloadDir: Path) {
|
||||
|
||||
private val lck = Mutex()
|
||||
|
||||
suspend fun keepNoMediaFileStatus(downloadDir: Path = downloadLocation) {
|
||||
suspend fun keepNoMediaFileStatus(downloadDir: Path = downloadLocation, mediaScan: Boolean = Settings.mediaScan.value) {
|
||||
if (downloadDir.isDirectory) {
|
||||
lck.withLock {
|
||||
if (Settings.mediaScan.value) {
|
||||
if (mediaScan) {
|
||||
removeNoMediaFile(downloadDir)
|
||||
} else {
|
||||
ensureNoMediaFile(downloadDir)
|
||||
|
||||
@@ -24,7 +24,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
import com.hippo.ehviewer.client.EhUtils
|
||||
@@ -76,7 +76,7 @@ fun GalleryInfoBottomSheet(detail: GalleryDetail) {
|
||||
LazyColumn(contentPadding = WindowInsets.systemBars.only(WindowInsetsSides.Bottom).asPaddingValues()) {
|
||||
itemsIndexed(data) { index, (key, content) ->
|
||||
Row(
|
||||
modifier = Modifier.padding(horizontal = dimensionResource(id = R.dimen.keyline_margin)).clickable {
|
||||
modifier = Modifier.padding(horizontal = dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)).clickable {
|
||||
if (index == INDEX_PARENT) {
|
||||
if (content != null) {
|
||||
navWithUrl(content)
|
||||
|
||||
@@ -104,7 +104,7 @@ import androidx.core.net.toUri
|
||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||
import androidx.lifecycle.compose.LifecycleResumeEffect
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder
|
||||
import com.hippo.ehviewer.client.parser.GalleryDetailUrlParser
|
||||
@@ -394,7 +394,7 @@ class MainActivity : EhActivity() {
|
||||
.windowInsetsPadding(WindowInsets.systemBars.only(WindowInsetsSides.Bottom)),
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.sadpanda_low_poly),
|
||||
painter = painterResource(id = com.hippo.ehviewer.R.drawable.sadpanda_low_poly),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
|
||||
contentScale = ContentScale.FillWidth,
|
||||
|
||||
@@ -29,7 +29,7 @@ import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
||||
import androidx.biometric.registerForAuthenticationResult
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
|
||||
context(ctx: Context)
|
||||
|
||||
@@ -20,7 +20,7 @@ import android.content.Context
|
||||
import android.widget.Toast
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import androidx.core.net.toUri
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.client.data.GalleryDetail
|
||||
import com.hippo.ehviewer.client.parser.GalleryPageUrlParser
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
@@ -32,7 +32,7 @@ fun openBrowser(url: String) {
|
||||
if (url.isEmpty()) return
|
||||
try {
|
||||
intent.launchUrl(ctx, url.toUri())
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
} catch (_: ActivityNotFoundException) {
|
||||
Toast.makeText(ctx, R.string.no_browser_installed, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ fun postLogin() = GlobalScope.async(Dispatchers.IO) {
|
||||
// Get cookies for image limits
|
||||
launch {
|
||||
catch {
|
||||
EhEngine.getUConfig(EhUrl.URL_UCONFIG_E)
|
||||
EhEngine.getUConfig(EhUrl.SITE_E)
|
||||
EhCookieStore.flush()
|
||||
}.onLeft {
|
||||
logcat(it)
|
||||
@@ -45,7 +45,7 @@ fun postLogin() = GlobalScope.async(Dispatchers.IO) {
|
||||
|
||||
// Sad panda check
|
||||
catch {
|
||||
EhEngine.getUConfig(EhUrl.URL_UCONFIG_EX)
|
||||
EhEngine.getUConfig(EhUrl.SITE_EX)
|
||||
EhCookieStore.flush()
|
||||
Settings.gallerySite.value = EhUrl.SITE_EX
|
||||
}.onLeft {
|
||||
|
||||
@@ -58,7 +58,7 @@ import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhEngine
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
@@ -142,7 +142,7 @@ fun AnimatedVisibilityScope.SignInScreen(navigator: DestinationsNavigator) = Scr
|
||||
fun UsernameAndPasswordTextField() {
|
||||
OutlinedTextField(
|
||||
state = username,
|
||||
modifier = Modifier.width(dimensionResource(id = R.dimen.single_max_width))
|
||||
modifier = Modifier.width(dimensionResource(id = com.hippo.ehviewer.R.dimen.single_max_width))
|
||||
.semantics { contentType = ContentType.Username }
|
||||
.thenIf(!showUsernameError) { padding(bottom = 16.dp) },
|
||||
label = { Text(stringResource(R.string.username)) },
|
||||
@@ -154,7 +154,7 @@ fun AnimatedVisibilityScope.SignInScreen(navigator: DestinationsNavigator) = Scr
|
||||
)
|
||||
OutlinedSecureTextField(
|
||||
state = password,
|
||||
modifier = Modifier.width(dimensionResource(id = R.dimen.single_max_width))
|
||||
modifier = Modifier.width(dimensionResource(id = com.hippo.ehviewer.R.dimen.single_max_width))
|
||||
.semantics { contentType = ContentType.Password }
|
||||
.thenIf(!showPasswordError) { padding(bottom = 16.dp) },
|
||||
label = { Text(stringResource(R.string.password)) },
|
||||
@@ -180,27 +180,27 @@ fun AnimatedVisibilityScope.SignInScreen(navigator: DestinationsNavigator) = Scr
|
||||
when {
|
||||
!windowSizeClass.isExpanded -> {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).systemBarsPadding().padding(dimensionResource(id = R.dimen.keyline_margin)),
|
||||
modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).systemBarsPadding().padding(dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_launcher_foreground),
|
||||
painter = painterResource(id = com.hippo.ehviewer.R.drawable.ic_launcher_foreground),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.padding(dimensionResource(id = R.dimen.keyline_margin)),
|
||||
modifier = Modifier.padding(dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)),
|
||||
)
|
||||
UsernameAndPasswordTextField()
|
||||
Text(
|
||||
text = stringResource(id = R.string.app_waring),
|
||||
modifier = Modifier.widthIn(max = dimensionResource(id = R.dimen.single_max_width)).padding(top = 24.dp),
|
||||
modifier = Modifier.widthIn(max = dimensionResource(id = com.hippo.ehviewer.R.dimen.single_max_width)).padding(top = 24.dp),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.app_waring_2),
|
||||
modifier = Modifier.widthIn(max = dimensionResource(id = R.dimen.single_max_width)).padding(top = 12.dp),
|
||||
modifier = Modifier.widthIn(max = dimensionResource(id = com.hippo.ehviewer.R.dimen.single_max_width)).padding(top = 12.dp),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(dimensionResource(id = R.dimen.keyline_margin)))
|
||||
Row(modifier = Modifier.padding(top = dimensionResource(R.dimen.keyline_margin))) {
|
||||
Spacer(modifier = Modifier.height(dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)))
|
||||
Row(modifier = Modifier.padding(top = dimensionResource(com.hippo.ehviewer.R.dimen.keyline_margin))) {
|
||||
FilledTonalButton(
|
||||
onClick = { openBrowser(EhUrl.URL_REGISTER) },
|
||||
shapes = ButtonDefaults.shapes(),
|
||||
@@ -255,18 +255,18 @@ fun AnimatedVisibilityScope.SignInScreen(navigator: DestinationsNavigator) = Scr
|
||||
}
|
||||
else -> {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).systemBarsPadding().padding(dimensionResource(id = R.dimen.keyline_margin)),
|
||||
modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).systemBarsPadding().padding(dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.width(dimensionResource(id = R.dimen.signinscreen_landscape_caption_frame_width)).padding(dimensionResource(id = R.dimen.keyline_margin)),
|
||||
modifier = Modifier.width(dimensionResource(id = com.hippo.ehviewer.R.dimen.signinscreen_landscape_caption_frame_width)).padding(dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_launcher_foreground),
|
||||
painter = painterResource(id = com.hippo.ehviewer.R.drawable.ic_launcher_foreground),
|
||||
contentDescription = null,
|
||||
alignment = Alignment.Center,
|
||||
modifier = Modifier.padding(dimensionResource(id = R.dimen.keyline_margin)),
|
||||
modifier = Modifier.padding(dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)),
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.app_waring),
|
||||
|
||||
@@ -22,7 +22,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.client.parser.Archive
|
||||
import com.hippo.ehviewer.client.parser.Funds
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ import arrow.core.none
|
||||
import arrow.core.some
|
||||
import coil3.compose.AsyncImage
|
||||
import coil3.network.HttpException
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhEngine
|
||||
import com.hippo.ehviewer.client.EhUtils
|
||||
@@ -107,7 +107,7 @@ fun AvatarIcon() {
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
CircularWavyProgressIndicator()
|
||||
Spacer(modifier = Modifier.size(dimensionResource(id = R.dimen.keyline_margin)))
|
||||
Spacer(modifier = Modifier.size(dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)))
|
||||
Text(text = placeholder)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhUtils
|
||||
import com.hippo.ehviewer.dao.DownloadInfo
|
||||
|
||||
@@ -156,7 +156,7 @@ fun FabLayout(
|
||||
}
|
||||
}
|
||||
onExpandChanged(false)
|
||||
} catch (e: CancellationException) {
|
||||
} catch (_: CancellationException) {
|
||||
launch { state.expand() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.text.parseAsHtml
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.client.data.GalleryComment
|
||||
import com.hippo.ehviewer.ui.legacy.CoilImageGetter
|
||||
import com.hippo.ehviewer.ui.legacy.LinkifyTextView
|
||||
@@ -50,7 +50,7 @@ fun GalleryCommentCard(
|
||||
},
|
||||
modifier = modifier,
|
||||
) {
|
||||
val margin = dimensionResource(id = R.dimen.keyline_margin)
|
||||
val margin = dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)
|
||||
Row(
|
||||
modifier = Modifier.padding(horizontal = margin, vertical = 8.dp).fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
|
||||
@@ -32,7 +32,7 @@ import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.client.EhUtils
|
||||
import com.hippo.ehviewer.client.data.GalleryDetail
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo
|
||||
@@ -91,21 +91,21 @@ fun GalleryDetailHeaderCard(
|
||||
EhThumbCard(
|
||||
key = remember(info.gid) { info },
|
||||
modifier = Modifier.size(
|
||||
dimensionResource(id = R.dimen.gallery_detail_thumb_width),
|
||||
dimensionResource(id = R.dimen.gallery_detail_thumb_height),
|
||||
dimensionResource(id = com.hippo.ehviewer.R.dimen.gallery_detail_thumb_width),
|
||||
dimensionResource(id = com.hippo.ehviewer.R.dimen.gallery_detail_thumb_height),
|
||||
),
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(0.5F))
|
||||
Column(
|
||||
modifier = Modifier.height(dimensionResource(id = R.dimen.gallery_detail_thumb_height)),
|
||||
modifier = Modifier.height(dimensionResource(id = com.hippo.ehviewer.R.dimen.gallery_detail_thumb_height)),
|
||||
horizontalAlignment = Alignment.End,
|
||||
) {
|
||||
(info as? GalleryDetail)?.let {
|
||||
GalleryDetailHeaderInfoCard(
|
||||
detail = it,
|
||||
onClick = onInfoCardClick,
|
||||
modifier = Modifier.padding(top = 8.dp, end = dimensionResource(id = R.dimen.keyline_margin)),
|
||||
modifier = Modifier.padding(top = 8.dp, end = dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)),
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(1F))
|
||||
@@ -113,7 +113,7 @@ fun GalleryDetailHeaderCard(
|
||||
AssistChip(
|
||||
onClick = onCategoryChipClick,
|
||||
label = { Text(text = categoryText, overflow = TextOverflow.Visible, softWrap = false, maxLines = 1) },
|
||||
modifier = Modifier.padding(horizontal = dimensionResource(id = R.dimen.keyline_margin)),
|
||||
modifier = Modifier.padding(horizontal = dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)),
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.Label,
|
||||
@@ -125,7 +125,7 @@ fun GalleryDetailHeaderCard(
|
||||
AssistChip(
|
||||
onClick = onUploaderChipClick,
|
||||
label = { Text(text = uploaderText, overflow = TextOverflow.Visible, softWrap = false, maxLines = 1) },
|
||||
modifier = Modifier.padding(horizontal = dimensionResource(id = R.dimen.keyline_margin)),
|
||||
modifier = Modifier.padding(horizontal = dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)),
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.NoAccounts,
|
||||
|
||||
@@ -51,7 +51,7 @@ import androidx.paging.LoadState
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.itemContentType
|
||||
import androidx.paging.compose.itemKey
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
import com.hippo.ehviewer.client.exception.NoHitsFoundException
|
||||
@@ -95,8 +95,8 @@ fun GalleryList(
|
||||
onRefresh: () -> Unit,
|
||||
onLoading: () -> Unit,
|
||||
) {
|
||||
val marginH = dimensionResource(id = R.dimen.gallery_list_margin_h)
|
||||
val marginV = dimensionResource(id = R.dimen.gallery_list_margin_v)
|
||||
val marginH = dimensionResource(id = com.hippo.ehviewer.R.dimen.gallery_list_margin_h)
|
||||
val marginV = dimensionResource(id = com.hippo.ehviewer.R.dimen.gallery_list_margin_v)
|
||||
|
||||
var isRefreshing by remember { mutableStateOf(false) }
|
||||
val refreshState = rememberPullToRefreshState()
|
||||
@@ -132,8 +132,8 @@ fun GalleryList(
|
||||
modifier = contentModifier.fillMaxSize(),
|
||||
state = detailListState,
|
||||
contentPadding = contentPadding + PaddingValues(marginH, marginV),
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.gallery_list_interval)),
|
||||
horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.gallery_list_interval)),
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(com.hippo.ehviewer.R.dimen.gallery_list_interval)),
|
||||
horizontalArrangement = Arrangement.spacedBy(dimensionResource(com.hippo.ehviewer.R.dimen.gallery_list_interval)),
|
||||
) {
|
||||
items(
|
||||
count = data.itemCount,
|
||||
@@ -155,7 +155,7 @@ fun GalleryList(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val gridInterval = dimensionResource(R.dimen.gallery_grid_interval)
|
||||
val gridInterval = dimensionResource(com.hippo.ehviewer.R.dimen.gallery_grid_interval)
|
||||
val thumbColumns by Settings.thumbColumns.collectAsState()
|
||||
FastScrollLazyVerticalStaggeredGrid(
|
||||
columns = StaggeredGridCells.Fixed(thumbColumns),
|
||||
|
||||
@@ -17,7 +17,7 @@ import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil3.compose.AsyncImage
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
|
||||
@Composable
|
||||
fun ImageSearch(
|
||||
@@ -29,7 +29,7 @@ fun ImageSearch(
|
||||
) {
|
||||
AnimatedVisibility(visible = image != null, modifier = Modifier.align(Alignment.CenterHorizontally)) {
|
||||
Card {
|
||||
val maxSize = dimensionResource(id = R.dimen.image_search_max_size)
|
||||
val maxSize = dimensionResource(id = com.hippo.ehviewer.R.dimen.image_search_max_size)
|
||||
AsyncImage(
|
||||
model = image,
|
||||
contentDescription = null,
|
||||
|
||||
@@ -10,7 +10,7 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.paging.LoadState
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.util.displayString
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -33,7 +33,7 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.dp
|
||||
import arrow.core.raise.ensure
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhTagDatabase
|
||||
import com.hippo.ehviewer.client.EhUtils
|
||||
@@ -117,7 +117,7 @@ fun SearchFilter(
|
||||
selectedItemIndex = language + 1,
|
||||
onSelectedItemIndexChange = { onLanguageChange(it - 1) },
|
||||
)
|
||||
val minRatingItems = stringArrayResource(id = R.array.search_min_rating)
|
||||
val minRatingItems = stringArrayResource(id = com.hippo.ehviewer.R.array.search_min_rating)
|
||||
val minRatingStr = stringResource(id = R.string.search_sr)
|
||||
DropdownFilterChip(
|
||||
label = minRatingStr,
|
||||
|
||||
@@ -22,7 +22,7 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.client.parser.Torrent
|
||||
import com.hippo.ehviewer.client.parser.format
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import androidx.core.graphics.alpha
|
||||
import androidx.core.graphics.blue
|
||||
import androidx.core.graphics.green
|
||||
import androidx.core.graphics.red
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.asMutableState
|
||||
import com.hippo.ehviewer.ui.main.RollingNumber
|
||||
@@ -87,7 +87,7 @@ fun ColorFilterSetting() = Column(modifier = Modifier.verticalScroll(rememberScr
|
||||
}
|
||||
SpinnerChoice(
|
||||
title = stringResource(id = R.string.pref_color_filter_mode),
|
||||
entries = stringArrayResource(id = R.array.color_filter_modes),
|
||||
entries = stringArrayResource(id = com.hippo.ehviewer.R.array.color_filter_modes),
|
||||
values = arrayOf("0", "1", "2", "3", "4", "5"),
|
||||
field = Settings.colorFilterMode.asMutableState(),
|
||||
)
|
||||
|
||||
@@ -13,8 +13,8 @@ import android.webkit.MimeTypeMap
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.core.content.FileProvider
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.BuildConfig.APPLICATION_ID
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo
|
||||
import com.hippo.ehviewer.gallery.Page
|
||||
@@ -121,7 +121,7 @@ suspend fun save(page: Page) {
|
||||
try {
|
||||
ctx.contentResolver.delete(imageUri, null, null)
|
||||
} catch (e: Exception) {
|
||||
e.logcat(e)
|
||||
logcat("SavePage", e)
|
||||
}
|
||||
snackbar(cannotSave)
|
||||
} else if (isAtLeastQ) {
|
||||
|
||||
@@ -37,8 +37,8 @@ import coil3.DrawableImage
|
||||
import coil3.compose.AsyncImagePainter
|
||||
import coil3.compose.SubcomposeAsyncImage
|
||||
import coil3.compose.SubcomposeAsyncImageContent
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.google.accompanist.drawablepainter.DrawablePainter
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.collectAsState
|
||||
import com.hippo.ehviewer.gallery.Page
|
||||
|
||||
@@ -11,7 +11,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.res.stringArrayResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.asMutableState
|
||||
import com.hippo.ehviewer.util.isAtLeastP
|
||||
@@ -20,8 +20,8 @@ import com.hippo.ehviewer.util.isAtLeastP
|
||||
fun ReaderGeneralSetting() = Column(modifier = Modifier.verticalScroll(rememberScrollState()).navigationBarsPadding()) {
|
||||
SpinnerChoice(
|
||||
title = stringResource(id = R.string.pref_reader_theme),
|
||||
entries = stringArrayResource(id = R.array.reader_themes),
|
||||
values = stringArrayResource(id = R.array.reader_themes_values),
|
||||
entries = stringArrayResource(id = com.hippo.ehviewer.R.array.reader_themes),
|
||||
values = stringArrayResource(id = com.hippo.ehviewer.R.array.reader_themes_values),
|
||||
field = Settings.readerTheme.asMutableState(),
|
||||
)
|
||||
SwitchChoice(
|
||||
|
||||
@@ -17,7 +17,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringArrayResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.asMutableState
|
||||
import com.hippo.ehviewer.collectAsState
|
||||
@@ -27,13 +27,13 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
|
||||
fun ReaderModeSetting() = Column(modifier = Modifier.verticalScroll(rememberScrollState()).navigationBarsPadding()) {
|
||||
SpinnerChoice(
|
||||
title = stringResource(id = R.string.pref_category_reading_mode),
|
||||
entries = stringArrayResource(id = R.array.viewers_selector),
|
||||
entries = stringArrayResource(id = com.hippo.ehviewer.R.array.viewers_selector),
|
||||
values = arrayOf("0", "1", "2", "3", "4", "5"),
|
||||
field = Settings.readingMode.asMutableState(),
|
||||
)
|
||||
SpinnerChoice(
|
||||
title = stringResource(id = R.string.rotation_type),
|
||||
entries = stringArrayResource(id = R.array.rotation_type),
|
||||
entries = stringArrayResource(id = com.hippo.ehviewer.R.array.rotation_type),
|
||||
values = arrayOf("0", "8", "16", "24", "32", "40", "48"),
|
||||
field = Settings.orientationMode.asMutableState(),
|
||||
)
|
||||
@@ -60,7 +60,7 @@ private fun PagerSetting() = Column {
|
||||
val pagerNav = Settings.readerPagerNav.asMutableState()
|
||||
SpinnerChoice(
|
||||
title = stringResource(id = R.string.pref_viewer_nav),
|
||||
entries = stringArrayResource(id = R.array.pager_nav),
|
||||
entries = stringArrayResource(id = com.hippo.ehviewer.R.array.pager_nav),
|
||||
values = arrayOf("0", "1", "2", "3", "4", "5"),
|
||||
field = pagerNav,
|
||||
)
|
||||
@@ -68,7 +68,7 @@ private fun PagerSetting() = Column {
|
||||
Column {
|
||||
SpinnerChoice(
|
||||
title = stringResource(id = R.string.pref_read_with_tapping_inverted),
|
||||
entries = stringArrayResource(id = R.array.invert_tapping_mode),
|
||||
entries = stringArrayResource(id = com.hippo.ehviewer.R.array.invert_tapping_mode),
|
||||
values = arrayOf("0", "1", "2", "3"),
|
||||
field = Settings.readerPagerNavInverted.asMutableState(),
|
||||
)
|
||||
@@ -81,7 +81,7 @@ private fun PagerSetting() = Column {
|
||||
val scaleType = Settings.imageScaleType.asMutableState()
|
||||
SpinnerChoice(
|
||||
title = stringResource(id = R.string.pref_image_scale_type),
|
||||
entries = stringArrayResource(id = R.array.image_scale_type),
|
||||
entries = stringArrayResource(id = com.hippo.ehviewer.R.array.image_scale_type),
|
||||
values = arrayOf("1", "2", "3", "4", "5", "6"),
|
||||
field = scaleType,
|
||||
)
|
||||
@@ -93,7 +93,7 @@ private fun PagerSetting() = Column {
|
||||
}
|
||||
SpinnerChoice(
|
||||
title = stringResource(id = R.string.pref_zoom_start),
|
||||
entries = stringArrayResource(id = R.array.zoom_start),
|
||||
entries = stringArrayResource(id = com.hippo.ehviewer.R.array.zoom_start),
|
||||
values = arrayOf("1", "2", "3", "4"),
|
||||
field = Settings.zoomStart.asMutableState(),
|
||||
)
|
||||
@@ -113,22 +113,22 @@ private fun WebtoonSetting() = Column {
|
||||
val webtoonNav = Settings.readerWebtoonNav.asMutableState()
|
||||
SpinnerChoice(
|
||||
title = stringResource(id = R.string.pref_viewer_nav),
|
||||
entries = stringArrayResource(id = R.array.webtoon_nav),
|
||||
entries = stringArrayResource(id = com.hippo.ehviewer.R.array.webtoon_nav),
|
||||
values = arrayOf("0", "1", "2", "3", "4", "5"),
|
||||
field = webtoonNav,
|
||||
)
|
||||
AnimatedVisibility(visible = webtoonNav.value != 5) {
|
||||
SpinnerChoice(
|
||||
title = stringResource(id = R.string.pref_read_with_tapping_inverted),
|
||||
entries = stringArrayResource(id = R.array.invert_tapping_mode),
|
||||
entries = stringArrayResource(id = com.hippo.ehviewer.R.array.invert_tapping_mode),
|
||||
values = arrayOf("0", "1", "2", "3"),
|
||||
field = Settings.readerWebtoonNavInverted.asMutableState(),
|
||||
)
|
||||
}
|
||||
SpinnerChoice(
|
||||
title = stringResource(id = R.string.pref_webtoon_side_padding),
|
||||
entries = stringArrayResource(id = R.array.webtoon_side_padding),
|
||||
values = stringArrayResource(id = R.array.webtoon_side_padding_values),
|
||||
entries = stringArrayResource(id = com.hippo.ehviewer.R.array.webtoon_side_padding),
|
||||
values = stringArrayResource(id = com.hippo.ehviewer.R.array.webtoon_side_padding_values),
|
||||
field = Settings.webtoonSidePadding.asMutableState(),
|
||||
)
|
||||
SwitchChoice(
|
||||
|
||||
@@ -59,9 +59,9 @@ import arrow.core.Either
|
||||
import arrow.core.Either.Companion.catch
|
||||
import arrow.core.raise.ensure
|
||||
import arrow.core.right
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
import com.hippo.ehviewer.collectAsState
|
||||
@@ -407,7 +407,7 @@ suspend inline fun <T> usePageLoader(args: ReaderScreenArgs, crossinline block:
|
||||
|
||||
@Composable
|
||||
private fun collectBackgroundColorAsState(): State<Color> {
|
||||
val grey = colorResource(R.color.reader_background_dark)
|
||||
val grey = colorResource(com.hippo.ehviewer.R.color.reader_background_dark)
|
||||
val dark = isSystemInDarkTheme()
|
||||
return Settings.readerTheme.collectAsState { theme ->
|
||||
when (theme) {
|
||||
|
||||
@@ -15,7 +15,7 @@ import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
private val tabs = intArrayOf(
|
||||
|
||||
@@ -80,8 +80,8 @@ import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import arrow.core.partially1
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.asMutableState
|
||||
import com.hippo.ehviewer.client.EhTagDatabase
|
||||
@@ -523,7 +523,7 @@ fun AnimatedVisibilityScope.DownloadsScreen(navigator: DestinationsNavigator) =
|
||||
},
|
||||
) { contentPadding ->
|
||||
val height by collectListThumbSizeAsState()
|
||||
val realPadding = contentPadding + PaddingValues(dimensionResource(id = R.dimen.gallery_list_margin_h), dimensionResource(id = R.dimen.gallery_list_margin_v))
|
||||
val realPadding = contentPadding + PaddingValues(dimensionResource(id = com.hippo.ehviewer.R.dimen.gallery_list_margin_h), dimensionResource(id = com.hippo.ehviewer.R.dimen.gallery_list_margin_v))
|
||||
val searchBarConnection = remember {
|
||||
val slop = ViewConfiguration.get(contextOf<Context>()).scaledTouchSlop
|
||||
val topPaddingPx = with(density) { contentPadding.calculateTopPadding().roundToPx() }
|
||||
@@ -548,7 +548,7 @@ fun AnimatedVisibilityScope.DownloadsScreen(navigator: DestinationsNavigator) =
|
||||
|
||||
Crossfade(targetState = gridView, label = "Downloads") { showGridView ->
|
||||
if (showGridView) {
|
||||
val gridInterval = dimensionResource(R.dimen.gallery_grid_interval)
|
||||
val gridInterval = dimensionResource(com.hippo.ehviewer.R.dimen.gallery_grid_interval)
|
||||
val thumbColumns by Settings.thumbColumns.collectAsState()
|
||||
FastScrollLazyVerticalStaggeredGrid(
|
||||
columns = StaggeredGridCells.Fixed(thumbColumns),
|
||||
@@ -571,7 +571,7 @@ fun AnimatedVisibilityScope.DownloadsScreen(navigator: DestinationsNavigator) =
|
||||
FastScrollLazyColumn(
|
||||
modifier = Modifier.nestedScroll(searchBarConnection).fillMaxSize(),
|
||||
contentPadding = realPadding,
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.gallery_list_interval)),
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(com.hippo.ehviewer.R.dimen.gallery_list_interval)),
|
||||
) {
|
||||
items(list, key = { it.gid }) { info ->
|
||||
val checked = info.gid in checkedInfoMap
|
||||
@@ -660,7 +660,7 @@ fun AnimatedVisibilityScope.DownloadsScreen(navigator: DestinationsNavigator) =
|
||||
}
|
||||
onClick(Icons.AutoMirrored.Default.Sort) {
|
||||
val oldMode = SortMode.from(sortMode)
|
||||
val sortModes = contextOf<Context>().resources.getStringArray(R.array.download_sort_modes).toList()
|
||||
val sortModes = contextOf<Context>().resources.getStringArray(com.hippo.ehviewer.R.array.download_sort_modes).toList()
|
||||
val (selected, checked) = awaitSelectItemWithCheckBox(
|
||||
sortModes,
|
||||
R.string.sort_by,
|
||||
@@ -674,7 +674,7 @@ fun AnimatedVisibilityScope.DownloadsScreen(navigator: DestinationsNavigator) =
|
||||
invalidateKey = !invalidateKey
|
||||
}
|
||||
onClick(Icons.Default.FilterList) {
|
||||
val downloadStates = contextOf<Context>().resources.getStringArray(R.array.download_state).toList()
|
||||
val downloadStates = contextOf<Context>().resources.getStringArray(com.hippo.ehviewer.R.array.download_state).toList()
|
||||
val state = awaitSingleChoice(
|
||||
downloadStates,
|
||||
filterState.state + 1,
|
||||
|
||||
@@ -53,8 +53,8 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhEngine
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
|
||||
@@ -84,7 +84,7 @@ import androidx.core.text.buildSpannedString
|
||||
import androidx.core.text.getSpans
|
||||
import androidx.core.text.inSpans
|
||||
import androidx.core.text.parseAsHtml
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhEngine
|
||||
import com.hippo.ehviewer.client.EhFilter.remember
|
||||
@@ -298,7 +298,7 @@ fun AnimatedVisibilityScope.GalleryCommentsScreen(gid: Long, navigator: Destinat
|
||||
}
|
||||
},
|
||||
) { paddingValues ->
|
||||
val keylineMargin = dimensionResource(id = R.dimen.keyline_margin)
|
||||
val keylineMargin = dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)
|
||||
var editTextMeasured by remember { mutableStateOf(MinimumContentPaddingEditText) }
|
||||
var isRefreshing by remember { mutableStateOf(false) }
|
||||
val refreshState = rememberPullToRefreshState()
|
||||
|
||||
@@ -68,8 +68,8 @@ import androidx.paging.compose.itemKey
|
||||
import arrow.core.partially1
|
||||
import arrow.fx.coroutines.parMap
|
||||
import arrow.fx.coroutines.parZip
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhEngine
|
||||
import com.hippo.ehviewer.client.EhFilter.remember
|
||||
@@ -174,7 +174,7 @@ fun GalleryDetailContent(
|
||||
voteTag: VoteTag,
|
||||
modifier: Modifier,
|
||||
) {
|
||||
val keylineMargin = dimensionResource(R.dimen.keyline_margin)
|
||||
val keylineMargin = dimensionResource(com.hippo.ehviewer.R.dimen.keyline_margin)
|
||||
val galleryDetail = galleryInfo.asGalleryDetail()
|
||||
val windowSizeClass = LocalWindowSizeClass.current
|
||||
val thumbColumns by Settings.thumbColumns.collectAsState()
|
||||
@@ -262,8 +262,8 @@ fun GalleryDetailContent(
|
||||
columns = GridCells.Fixed(thumbColumns),
|
||||
contentPadding = contentPadding,
|
||||
modifier = modifier.padding(horizontal = keylineMargin),
|
||||
horizontalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.strip_item_padding)),
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.strip_item_padding_v)),
|
||||
horizontalArrangement = Arrangement.spacedBy(dimensionResource(id = com.hippo.ehviewer.R.dimen.strip_item_padding)),
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(id = com.hippo.ehviewer.R.dimen.strip_item_padding_v)),
|
||||
) {
|
||||
item(
|
||||
key = "header",
|
||||
@@ -325,8 +325,8 @@ fun GalleryDetailContent(
|
||||
columns = GridCells.Fixed(thumbColumns),
|
||||
contentPadding = contentPadding,
|
||||
modifier = modifier.padding(horizontal = keylineMargin),
|
||||
horizontalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.strip_item_padding)),
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.strip_item_padding_v)),
|
||||
horizontalArrangement = Arrangement.spacedBy(dimensionResource(id = com.hippo.ehviewer.R.dimen.strip_item_padding)),
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(id = com.hippo.ehviewer.R.dimen.strip_item_padding_v)),
|
||||
) {
|
||||
item(
|
||||
key = "header",
|
||||
@@ -340,7 +340,7 @@ fun GalleryDetailContent(
|
||||
onUploaderChipClick = ::onUploaderChipClick.partially1(galleryInfo),
|
||||
onBlockUploaderIconClick = ::showFilterUploaderDialog.partially1(galleryInfo),
|
||||
onCategoryChipClick = ::onCategoryChipClick,
|
||||
modifier = Modifier.width(dimensionResource(id = R.dimen.gallery_detail_card_landscape_width)).padding(vertical = keylineMargin),
|
||||
modifier = Modifier.width(dimensionResource(id = com.hippo.ehviewer.R.dimen.gallery_detail_card_landscape_width)).padding(vertical = keylineMargin),
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
@@ -443,7 +443,7 @@ fun BelowHeader(galleryDetail: GalleryDetail, voteTag: VoteTag) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = dimensionResource(id = R.dimen.strip_item_padding_v))
|
||||
.padding(bottom = dimensionResource(id = com.hippo.ehviewer.R.dimen.strip_item_padding_v))
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.clickable(onClick = ::navigateToCommentScreen),
|
||||
contentAlignment = Alignment.Center,
|
||||
@@ -463,7 +463,7 @@ fun BelowHeader(galleryDetail: GalleryDetail, voteTag: VoteTag) {
|
||||
navigate(info.gid asDstWith info.token)
|
||||
}
|
||||
}
|
||||
val keylineMargin = dimensionResource(R.dimen.keyline_margin)
|
||||
val keylineMargin = dimensionResource(com.hippo.ehviewer.R.dimen.keyline_margin)
|
||||
Spacer(modifier = Modifier.size(keylineMargin))
|
||||
if (galleryDetail.newerVersions.isNotEmpty()) {
|
||||
Box(contentAlignment = Alignment.Center) {
|
||||
@@ -765,7 +765,7 @@ fun BelowHeader(galleryDetail: GalleryDetail, voteTag: VoteTag) {
|
||||
Spacer(modifier = Modifier.size(keylineMargin))
|
||||
if (Settings.showComments.value) {
|
||||
GalleryDetailComment(galleryDetail.comments.comments)
|
||||
Spacer(modifier = Modifier.size(dimensionResource(id = R.dimen.strip_item_padding_v)))
|
||||
Spacer(modifier = Modifier.size(dimensionResource(id = com.hippo.ehviewer.R.dimen.strip_item_padding_v)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.util.fastJoinToString
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.EhApplication.Companion.imageCache
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhEngine
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
@@ -249,7 +249,7 @@ fun AnimatedVisibilityScope.GalleryDetailScreen(args: GalleryDetailScreenArgs, n
|
||||
) {
|
||||
Text(text = stringResource(id = R.string.clear_image_cache_confirm))
|
||||
}
|
||||
(0..<gd.pages).forEach {
|
||||
repeat(gd.pages) {
|
||||
val key = getImageKey(gd.gid, it)
|
||||
imageCache.remove(key)
|
||||
}
|
||||
|
||||
@@ -69,8 +69,8 @@ import androidx.paging.LoadState
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import arrow.core.raise.ensure
|
||||
import arrow.core.raise.ensureNotNull
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.asMutableState
|
||||
import com.hippo.ehviewer.client.EhTagDatabase
|
||||
@@ -194,8 +194,8 @@ fun AnimatedVisibilityScope.GalleryListScreen(
|
||||
FavouriteStatusRouter.Observe(data)
|
||||
val listMode by Settings.listMode.collectAsState()
|
||||
|
||||
val entries = stringArrayResource(id = R.array.toplist_entries)
|
||||
val values = stringArrayResource(id = R.array.toplist_values)
|
||||
val entries = stringArrayResource(id = com.hippo.ehviewer.R.array.toplist_entries)
|
||||
val values = stringArrayResource(id = com.hippo.ehviewer.R.array.toplist_values)
|
||||
val toplists = remember { entries zip values }
|
||||
val quickSearchName = getSuitableTitleForUrlBuilder(urlBuilder, false)
|
||||
var saveProgress by Settings.qSSaveProgress.asMutableState()
|
||||
|
||||
@@ -42,8 +42,8 @@ import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import androidx.paging.compose.itemContentType
|
||||
import androidx.paging.compose.itemKey
|
||||
import androidx.paging.map
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.collectAsState
|
||||
import com.hippo.ehviewer.icons.EhIcons
|
||||
@@ -133,13 +133,13 @@ fun AnimatedVisibilityScope.HistoryScreen(navigator: DestinationsNavigator) = Sc
|
||||
}
|
||||
}
|
||||
}
|
||||
val marginH = dimensionResource(id = R.dimen.gallery_list_margin_h)
|
||||
val marginH = dimensionResource(id = com.hippo.ehviewer.R.dimen.gallery_list_margin_h)
|
||||
val cardHeight by collectListThumbSizeAsState()
|
||||
val showPages by Settings.showGalleryPages.collectAsState()
|
||||
FastScrollLazyColumn(
|
||||
modifier = Modifier.nestedScroll(searchBarConnection).fillMaxSize(),
|
||||
contentPadding = paddingValues,
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.gallery_list_interval)),
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(com.hippo.ehviewer.R.dimen.gallery_list_interval)),
|
||||
) {
|
||||
items(
|
||||
count = historyData.itemCount,
|
||||
|
||||
@@ -27,7 +27,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder.Companion.MODE_IMAGE_SEARCH
|
||||
import com.hippo.ehviewer.ui.Screen
|
||||
@@ -50,8 +50,8 @@ import moe.tarsin.snackbar
|
||||
@Composable
|
||||
fun AnimatedVisibilityScope.ImageSearchScreen(navigator: DestinationsNavigator) = Screen(navigator) {
|
||||
val selectImageFirst = stringResource(R.string.select_image_first)
|
||||
val marginH = dimensionResource(id = R.dimen.gallery_list_margin_h)
|
||||
val marginV = dimensionResource(id = R.dimen.gallery_list_margin_v)
|
||||
val marginH = dimensionResource(id = com.hippo.ehviewer.R.dimen.gallery_list_margin_h)
|
||||
val marginV = dimensionResource(id = com.hippo.ehviewer.R.dimen.gallery_list_margin_v)
|
||||
var imageUri by rememberSaveable { mutableStateOf<Uri?>(null) }
|
||||
|
||||
Scaffold(
|
||||
@@ -87,19 +87,19 @@ fun AnimatedVisibilityScope.ImageSearchScreen(navigator: DestinationsNavigator)
|
||||
modifier = Modifier.padding(
|
||||
paddingValues = contentPadding + PaddingValues(marginH, marginV),
|
||||
).padding(
|
||||
vertical = dimensionResource(id = R.dimen.search_layout_margin_v),
|
||||
vertical = dimensionResource(id = com.hippo.ehviewer.R.dimen.search_layout_margin_v),
|
||||
),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(
|
||||
horizontal = dimensionResource(id = R.dimen.search_category_padding_h),
|
||||
vertical = dimensionResource(id = R.dimen.search_category_padding_v),
|
||||
horizontal = dimensionResource(id = com.hippo.ehviewer.R.dimen.search_category_padding_h),
|
||||
vertical = dimensionResource(id = com.hippo.ehviewer.R.dimen.search_category_padding_v),
|
||||
).fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.search_image),
|
||||
modifier = Modifier.height(dimensionResource(id = R.dimen.search_category_title_height)),
|
||||
modifier = Modifier.height(dimensionResource(id = com.hippo.ehviewer.R.dimen.search_category_title_height)),
|
||||
fontWeight = FontWeight.Bold,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
)
|
||||
|
||||
@@ -21,7 +21,7 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.client.EhEngine
|
||||
import com.hippo.ehviewer.icons.EhIcons
|
||||
import com.hippo.ehviewer.icons.big.SadAndroid
|
||||
|
||||
@@ -65,8 +65,8 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.coerceAtMost
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.EhApplication.Companion.searchDatabase
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhTagDatabase
|
||||
import com.hippo.ehviewer.client.data.TagNamespace
|
||||
|
||||
@@ -21,9 +21,9 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.fromHtml
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.BuildConfig
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.asMutableState
|
||||
import com.hippo.ehviewer.download.downloadLocation
|
||||
@@ -108,8 +108,8 @@ fun AnimatedVisibilityScope.AboutScreen(navigator: DestinationsNavigator) = Scre
|
||||
)
|
||||
SimpleMenuPreferenceInt(
|
||||
title = stringResource(id = R.string.auto_updates),
|
||||
entry = R.array.update_frequency,
|
||||
entryValueRes = R.array.update_frequency_values,
|
||||
entry = com.hippo.ehviewer.R.array.update_frequency,
|
||||
entryValueRes = com.hippo.ehviewer.R.array.update_frequency_values,
|
||||
state = Settings.updateIntervalDays.asMutableState(),
|
||||
)
|
||||
WorkPreference(title = stringResource(id = R.string.settings_about_check_for_updates)) {
|
||||
|
||||
@@ -30,9 +30,9 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.core.net.toUri
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.BuildConfig
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.asMutableState
|
||||
import com.hippo.ehviewer.client.EhEngine
|
||||
@@ -169,8 +169,8 @@ fun AnimatedVisibilityScope.AdvancedScreen(navigator: DestinationsNavigator) = S
|
||||
}
|
||||
SimpleMenuPreferenceInt(
|
||||
title = stringResource(id = R.string.settings_advanced_read_cache_size),
|
||||
entry = R.array.read_cache_size_entries,
|
||||
entryValueRes = R.array.read_cache_size_entry_values,
|
||||
entry = com.hippo.ehviewer.R.array.read_cache_size_entries,
|
||||
entryValueRes = com.hippo.ehviewer.R.array.read_cache_size_entry_values,
|
||||
state = Settings.readCacheSize.asMutableState(),
|
||||
)
|
||||
var currentLanguage by remember { mutableStateOf(getAppLanguage()) }
|
||||
|
||||
@@ -29,8 +29,8 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import arrow.fx.coroutines.parMap
|
||||
import arrow.fx.coroutines.parMapNotNull
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.asMutableState
|
||||
import com.hippo.ehviewer.client.EhEngine.fillGalleryListByApi
|
||||
@@ -44,6 +44,7 @@ import com.hippo.ehviewer.download.DownloadManager
|
||||
import com.hippo.ehviewer.download.downloadDir
|
||||
import com.hippo.ehviewer.download.downloadLocation
|
||||
import com.hippo.ehviewer.spider.COMIC_INFO_FILE
|
||||
import com.hippo.ehviewer.spider.MIN_SPEED_LEVEL
|
||||
import com.hippo.ehviewer.spider.SpiderDen
|
||||
import com.hippo.ehviewer.spider.SpiderQueen.Companion.SPIDER_INFO_FILENAME
|
||||
import com.hippo.ehviewer.spider.readComicInfo
|
||||
@@ -178,29 +179,21 @@ fun AnimatedVisibilityScope.DownloadScreen(navigator: DestinationsNavigator) = S
|
||||
SimpleMenuPreferenceInt(
|
||||
title = stringResource(id = R.string.settings_download_concurrency),
|
||||
summary = stringResource(id = R.string.settings_download_concurrency_summary, multiThreadDownload.value),
|
||||
entry = R.array.multi_thread_download_entries,
|
||||
entryValueRes = R.array.multi_thread_download_entry_values,
|
||||
entry = com.hippo.ehviewer.R.array.multi_thread_download_entries,
|
||||
entryValueRes = com.hippo.ehviewer.R.array.multi_thread_download_entry_values,
|
||||
state = multiThreadDownload,
|
||||
)
|
||||
val downloadDelay = Settings.downloadDelay.asMutableState()
|
||||
SimpleMenuPreferenceInt(
|
||||
title = stringResource(id = R.string.settings_download_download_delay),
|
||||
summary = stringResource(id = R.string.settings_download_download_delay_summary, downloadDelay.value),
|
||||
entry = R.array.download_delay_entries,
|
||||
entryValueRes = R.array.download_delay_entry_values,
|
||||
entry = com.hippo.ehviewer.R.array.download_delay_entries,
|
||||
entryValueRes = com.hippo.ehviewer.R.array.download_delay_entry_values,
|
||||
state = downloadDelay,
|
||||
)
|
||||
IntSliderPreference(
|
||||
maxValue = 10,
|
||||
minValue = 2,
|
||||
step = 7,
|
||||
title = stringResource(id = R.string.settings_download_connection_timeout),
|
||||
state = Settings.connTimeout.asMutableState(),
|
||||
)
|
||||
IntSliderPreference(
|
||||
maxValue = 10,
|
||||
minValue = 4,
|
||||
step = 5,
|
||||
minValue = MIN_SPEED_LEVEL,
|
||||
title = stringResource(id = R.string.settings_download_timeout_speed),
|
||||
state = Settings.timeoutSpeed.asMutableState(),
|
||||
display = ::speedLevelToSpeed,
|
||||
@@ -209,8 +202,8 @@ fun AnimatedVisibilityScope.DownloadScreen(navigator: DestinationsNavigator) = S
|
||||
SimpleMenuPreferenceInt(
|
||||
title = stringResource(id = R.string.settings_download_preload_image),
|
||||
summary = stringResource(id = R.string.settings_download_preload_image_summary, preloadImage.value),
|
||||
entry = R.array.preload_image_entries,
|
||||
entryValueRes = R.array.preload_image_entry_values,
|
||||
entry = com.hippo.ehviewer.R.array.preload_image_entries,
|
||||
entryValueRes = com.hippo.ehviewer.R.array.preload_image_entry_values,
|
||||
state = preloadImage,
|
||||
)
|
||||
SwitchPreference(
|
||||
|
||||
@@ -28,7 +28,7 @@ import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.fromHtml
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.asMutableState
|
||||
import com.hippo.ehviewer.client.EhCookieStore
|
||||
@@ -94,7 +94,7 @@ fun AnimatedVisibilityScope.EhScreen(navigator: DestinationsNavigator) = Screen(
|
||||
val warning = stringResource(id = R.string.settings_eh_identity_cookies_signed)
|
||||
val state = rememberTextFieldState(cookies.joinToString("\n") { (k, v) -> "$k: $v" })
|
||||
Text(text = AnnotatedString.fromHtml(warning))
|
||||
Spacer(modifier = Modifier.size(dimensionResource(id = R.dimen.keyline_margin)))
|
||||
Spacer(modifier = Modifier.size(dimensionResource(id = com.hippo.ehviewer.R.dimen.keyline_margin)))
|
||||
OutlinedTextField(
|
||||
state = state,
|
||||
readOnly = true,
|
||||
@@ -119,8 +119,8 @@ fun AnimatedVisibilityScope.EhScreen(navigator: DestinationsNavigator) = Screen(
|
||||
val gallerySite = Settings.gallerySite.asMutableState()
|
||||
SimpleMenuPreferenceInt(
|
||||
title = stringResource(id = R.string.settings_eh_gallery_site),
|
||||
entry = R.array.gallery_site_entries,
|
||||
entryValueRes = R.array.gallery_site_entry_values,
|
||||
entry = com.hippo.ehviewer.R.array.gallery_site_entries,
|
||||
entryValueRes = com.hippo.ehviewer.R.array.gallery_site_entry_values,
|
||||
state = gallerySite,
|
||||
)
|
||||
Preference(
|
||||
@@ -161,8 +161,8 @@ fun AnimatedVisibilityScope.EhScreen(navigator: DestinationsNavigator) = Screen(
|
||||
}
|
||||
SimpleMenuPreferenceInt(
|
||||
title = stringResource(id = R.string.dark_theme),
|
||||
entry = R.array.night_mode_entries,
|
||||
entryValueRes = R.array.night_mode_values,
|
||||
entry = com.hippo.ehviewer.R.array.night_mode_entries,
|
||||
entryValueRes = com.hippo.ehviewer.R.array.night_mode_values,
|
||||
state = Settings.theme.asMutableState(),
|
||||
)
|
||||
SwitchPreference(
|
||||
@@ -175,15 +175,15 @@ fun AnimatedVisibilityScope.EhScreen(navigator: DestinationsNavigator) = Screen(
|
||||
)
|
||||
SimpleMenuPreferenceInt(
|
||||
title = stringResource(id = R.string.settings_eh_launch_page),
|
||||
entry = R.array.launch_page_entries,
|
||||
entryValueRes = R.array.launch_page_entry_values,
|
||||
entry = com.hippo.ehviewer.R.array.launch_page_entries,
|
||||
entryValueRes = com.hippo.ehviewer.R.array.launch_page_entry_values,
|
||||
state = Settings.launchPage.asMutableState(),
|
||||
)
|
||||
val listMode = Settings.listMode.asMutableState()
|
||||
SimpleMenuPreferenceInt(
|
||||
title = stringResource(id = R.string.settings_eh_list_mode),
|
||||
entry = R.array.list_mode_entries,
|
||||
entryValueRes = R.array.list_mode_entry_values,
|
||||
entry = com.hippo.ehviewer.R.array.list_mode_entries,
|
||||
entryValueRes = com.hippo.ehviewer.R.array.list_mode_entry_values,
|
||||
state = listMode,
|
||||
)
|
||||
AnimatedVisibility(visible = listMode.value == 0) {
|
||||
@@ -197,8 +197,8 @@ fun AnimatedVisibilityScope.EhScreen(navigator: DestinationsNavigator) = Screen(
|
||||
)
|
||||
SimpleMenuPreferenceInt(
|
||||
title = stringResource(id = R.string.settings_eh_detail_size),
|
||||
entry = R.array.detail_size_entries,
|
||||
entryValueRes = R.array.detail_size_entry_values,
|
||||
entry = com.hippo.ehviewer.R.array.detail_size_entries,
|
||||
entryValueRes = com.hippo.ehviewer.R.array.detail_size_entry_values,
|
||||
state = Settings.detailSize.asMutableState(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ import androidx.compose.ui.res.stringArrayResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhFilter
|
||||
import com.hippo.ehviewer.client.EhFilter.forget
|
||||
@@ -88,7 +88,7 @@ fun AnimatedVisibilityScope.FilterScreen(navigator: DestinationsNavigator) = Scr
|
||||
fun addFilter() {
|
||||
launch {
|
||||
dialog { cont ->
|
||||
val types = stringArrayResource(id = R.array.filter_entries)
|
||||
val types = stringArrayResource(id = com.hippo.ehviewer.R.array.filter_entries)
|
||||
val type = rememberTextFieldState(types[0])
|
||||
val state = rememberTextFieldState()
|
||||
var error by remember { mutableStateOf<String?>(null) }
|
||||
|
||||
@@ -13,7 +13,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.ui.Screen
|
||||
import com.hippo.ehviewer.ui.main.NavigationIcon
|
||||
import com.hippo.ehviewer.ui.openBrowser
|
||||
@@ -37,7 +37,7 @@ fun AnimatedVisibilityScope.LicenseScreen(navigator: DestinationsNavigator) = Sc
|
||||
)
|
||||
},
|
||||
) { paddingValues ->
|
||||
val libraries by rememberLibraries(R.raw.aboutlibraries)
|
||||
val libraries by rememberLibraries(com.hippo.ehviewer.R.raw.aboutlibraries)
|
||||
LibrariesContainer(
|
||||
libraries = libraries,
|
||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
|
||||
@@ -9,9 +9,9 @@ import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.google.accompanist.web.WebView
|
||||
import com.google.accompanist.web.rememberWebViewState
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
import com.hippo.ehviewer.ui.Screen
|
||||
import com.hippo.ehviewer.ui.main.NavigationIcon
|
||||
|
||||
@@ -12,8 +12,8 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.EhApplication.Companion.searchDatabase
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.asMutableState
|
||||
import com.hippo.ehviewer.ui.Screen
|
||||
|
||||
@@ -16,7 +16,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.icons.EhIcons
|
||||
import com.hippo.ehviewer.icons.filled.SadPanda
|
||||
import com.hippo.ehviewer.ui.Screen
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.hippo.ehviewer.ui.settings
|
||||
|
||||
import android.webkit.WebView
|
||||
import androidx.compose.animation.AnimatedVisibilityScope
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@@ -16,10 +15,10 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.google.accompanist.web.WebView
|
||||
import com.google.accompanist.web.rememberWebViewNavigator
|
||||
import com.google.accompanist.web.rememberWebViewState
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.client.EhCookieStore
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
import com.hippo.ehviewer.ui.Screen
|
||||
@@ -36,7 +35,7 @@ private const val APPLY_JS = "javascript:(function(){var apply = document.getEle
|
||||
@Destination<RootGraph>
|
||||
@Composable
|
||||
fun AnimatedVisibilityScope.UConfigScreen(navigator: DestinationsNavigator) = Screen(navigator) {
|
||||
val url = EhUrl.uConfigUrl
|
||||
val url = EhUrl.getUConfigUrl()
|
||||
val wvNavigator = rememberWebViewNavigator()
|
||||
Scaffold(
|
||||
topBar = {
|
||||
|
||||
@@ -4,11 +4,11 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisallowComposableCalls
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.datastore.dataStoreFile
|
||||
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
|
||||
import androidx.datastore.preferences.core.byteArrayPreferencesKey
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.emptyPreferences
|
||||
import androidx.datastore.preferences.preferencesDataStoreFile
|
||||
import androidx.lifecycle.compose.LifecycleResumeEffect
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -22,7 +22,7 @@ import kotlinx.serialization.serializer
|
||||
import splitties.init.appCtx
|
||||
|
||||
val dataStoreScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||
val dataStore = PreferenceDataStoreFactory.create { appCtx.dataStoreFile("Remembered.preferences_pb") }
|
||||
val dataStore = PreferenceDataStoreFactory.create { appCtx.preferencesDataStoreFile("Remembered") }
|
||||
val dataStateFlow = dataStore.data.stateIn(dataStoreScope, SharingStarted.Eagerly, emptyPreferences())
|
||||
|
||||
// Find out how make this work with any generic `Serializable` type
|
||||
|
||||
@@ -93,7 +93,7 @@ import arrow.core.Either
|
||||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.either
|
||||
import arrow.core.right
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.client.EhTagDatabase
|
||||
import com.hippo.ehviewer.client.EhTagDatabase.suggestion
|
||||
import com.jamal.composeprefs3.ui.ifNotNullThen
|
||||
|
||||
@@ -75,7 +75,7 @@ fun animateFloatMergePredictiveBackAsState(
|
||||
animatable.snapTo(transformed)
|
||||
}
|
||||
onBack()
|
||||
} catch (e: CancellationException) {
|
||||
} catch (_: CancellationException) {
|
||||
channel.trySend(0f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import android.content.Intent
|
||||
import android.widget.Toast
|
||||
import arrow.core.Either
|
||||
import arrow.core.getOrElse
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
|
||||
object AppHelper {
|
||||
fun share(from: Activity, text: String?): Boolean {
|
||||
|
||||
@@ -24,7 +24,7 @@ import android.content.Context
|
||||
import android.os.Build
|
||||
import android.view.textclassifier.TextClassifier
|
||||
import androidx.core.os.persistableBundleOf
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.ui.MainActivity
|
||||
import moe.tarsin.tip
|
||||
import splitties.systemservices.clipboardManager
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.hippo.ehviewer.util
|
||||
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import io.ktor.client.network.sockets.ConnectTimeoutException
|
||||
import io.ktor.client.network.sockets.SocketTimeoutException
|
||||
|
||||
@@ -20,9 +20,6 @@ import io.ktor.utils.io.ByteReadChannel
|
||||
import io.ktor.utils.io.InternalAPI
|
||||
import io.ktor.utils.io.rethrowCloseCauseIfNeeded
|
||||
import java.io.File
|
||||
import java.util.Locale
|
||||
import kotlin.math.ln
|
||||
import kotlin.math.pow
|
||||
import okio.Path
|
||||
|
||||
object FileUtils {
|
||||
@@ -38,15 +35,15 @@ object FileUtils {
|
||||
* @param bytes the bytes to convert
|
||||
* @return the human readable string
|
||||
*/
|
||||
// http://stackoverflow.com/questions/3758606/
|
||||
fun humanReadableByteCount(bytes: Long): String {
|
||||
if (bytes < 1024) return "$bytes B"
|
||||
val exp = (ln(bytes.toDouble()) / ln(1024f)).toInt()
|
||||
return "%.1f %sB".format(
|
||||
Locale.US,
|
||||
bytes / 1024.toDouble().pow(exp.toDouble()),
|
||||
("KMGTPE")[exp - 1].toString() + "i",
|
||||
)
|
||||
val units = "KMGTPE"
|
||||
var exp = -1
|
||||
var result = bytes.toDouble()
|
||||
while (result >= 1024.0 && exp < units.length - 1) {
|
||||
exp++
|
||||
result /= 1024.0
|
||||
}
|
||||
return if (exp == -1) "$bytes B" else "%.1f %siB".format(result, units[exp])
|
||||
}
|
||||
|
||||
fun cleanupDirectory(dir: File?, maxFiles: Int = 10) {
|
||||
|
||||
@@ -3,13 +3,13 @@ package com.hippo.ehviewer.util
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
|
||||
context(ctx: Context)
|
||||
fun getLanguages(): Map<String, String> = with(ctx) {
|
||||
val languages = mutableMapOf("system" to getString(R.string.app_language_system))
|
||||
resources.getXml(R.xml._generated_res_locale_config).use { parser ->
|
||||
resources.getXml(com.hippo.ehviewer.R.xml._generated_res_locale_config).use { parser ->
|
||||
var event = parser.eventType
|
||||
while (event != XmlPullParser.END_DOCUMENT) {
|
||||
if (event == XmlPullParser.START_TAG && parser.name == "locale") {
|
||||
|
||||
@@ -21,7 +21,7 @@ import androidx.core.net.toUri
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import java.io.File
|
||||
import kotlin.concurrent.atomics.AtomicInt
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.hippo.ehviewer.util
|
||||
|
||||
import android.os.Looper
|
||||
import com.ehviewer.core.mainthread.checkNotMainThread
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import java.io.File
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -51,11 +51,4 @@ object OSUtils {
|
||||
}
|
||||
}
|
||||
|
||||
val isMainThread: Boolean
|
||||
get() = Looper.getMainLooper().thread === Thread.currentThread()
|
||||
|
||||
fun assertNotMainThread() {
|
||||
check(!isMainThread) { "Cannot access database on the main thread since" + " it may potentially lock the UI for a long period of time." }
|
||||
}
|
||||
|
||||
fun <T> runAssertingNotMainThread(block: suspend CoroutineScope.() -> T) = assertNotMainThread().run { runBlocking(block = block) }
|
||||
fun <T> runAssertingNotMainThread(block: suspend CoroutineScope.() -> T) = checkNotMainThread().run { runBlocking(block = block) }
|
||||
@@ -16,7 +16,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import com.hippo.ehviewer.R.string
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.ui.tools.DialogState
|
||||
import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
|
||||
import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn
|
||||
@@ -40,7 +40,7 @@ fun ProgressDialog() {
|
||||
) {
|
||||
CircularWavyProgressIndicator()
|
||||
Spacer(modifier = Modifier.size(18.dp))
|
||||
Text(text = stringResource(id = string.please_wait))
|
||||
Text(text = stringResource(id = R.string.please_wait))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ package com.hippo.ehviewer.util
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import java.util.Locale
|
||||
import kotlin.time.Clock
|
||||
import kotlin.time.Instant
|
||||
|
||||
@@ -26,7 +26,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.asMutableState
|
||||
import com.hippo.ehviewer.collectAsState
|
||||
|
||||
@@ -26,7 +26,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import moe.tarsin.kt.andThen
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.reader.setting
|
||||
|
||||
import android.content.pm.ActivityInfo
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.icons.EhIcons
|
||||
import com.hippo.ehviewer.icons.reader.Landscape
|
||||
import com.hippo.ehviewer.icons.reader.LandscapeLocked
|
||||
|
||||
@@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.reader.setting
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import com.hippo.ehviewer.icons.EhIcons
|
||||
import com.hippo.ehviewer.icons.reader.ContinuousVertical
|
||||
import com.hippo.ehviewer.icons.reader.Default
|
||||
|
||||
@@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.reader.viewer
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import com.hippo.ehviewer.R
|
||||
import com.ehviewer.core.i18n.R
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.TappingInvertMode
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.DisabledNavigation
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.EdgeNavigation
|
||||
@@ -14,11 +14,11 @@ import eu.kanade.tachiyomi.util.lang.invert
|
||||
|
||||
abstract class ViewerNavigation {
|
||||
sealed class NavigationRegion(@StringRes val nameRes: Int, val colorRes: Int) {
|
||||
data object MENU : NavigationRegion(R.string.action_menu, R.color.navigation_menu)
|
||||
data object PREV : NavigationRegion(R.string.nav_zone_prev, R.color.navigation_prev)
|
||||
data object NEXT : NavigationRegion(R.string.nav_zone_next, R.color.navigation_next)
|
||||
data object LEFT : NavigationRegion(R.string.nav_zone_left, R.color.navigation_left)
|
||||
data object RIGHT : NavigationRegion(R.string.nav_zone_right, R.color.navigation_right)
|
||||
data object MENU : NavigationRegion(R.string.action_menu, com.hippo.ehviewer.R.color.navigation_menu)
|
||||
data object PREV : NavigationRegion(R.string.nav_zone_prev, com.hippo.ehviewer.R.color.navigation_prev)
|
||||
data object NEXT : NavigationRegion(R.string.nav_zone_next, com.hippo.ehviewer.R.color.navigation_next)
|
||||
data object LEFT : NavigationRegion(R.string.nav_zone_left, com.hippo.ehviewer.R.color.navigation_left)
|
||||
data object RIGHT : NavigationRegion(R.string.nav_zone_right, com.hippo.ehviewer.R.color.navigation_right)
|
||||
}
|
||||
|
||||
data class Region(val rect: Rect, val type: NavigationRegion) {
|
||||
|
||||
Generated
+30
-29
@@ -126,9 +126,9 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.23.1"
|
||||
version = "1.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422"
|
||||
checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder-lite"
|
||||
@@ -144,9 +144,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.30"
|
||||
version = "1.2.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7"
|
||||
checksum = "2352e5597e9c544d5e6d9c95190d5d27738ade584fa8db0a16e130e5c2b5296e"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
@@ -491,9 +491,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.11"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785"
|
||||
checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes",
|
||||
@@ -516,9 +516,9 @@ checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.4"
|
||||
version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
|
||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
@@ -1206,18 +1206,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
version = "1.0.96"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
checksum = "beef09f85ae72cea1ef96ba6870c51e6382ebfa4f0e85b643459331f3daa5be0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.38.0"
|
||||
version = "0.38.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8927b0664f5c5a98265138b7e3f90aa19a6b21353182469ace36d4ac527b7b1b"
|
||||
checksum = "9845d9dccf565065824e69f9f235fafba1587031eda353c1f1561cd6a6be78f4"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -1353,9 +1353,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.30"
|
||||
version = "0.23.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "069a8df149a16b1a12dcc31497c3396a173844be3cac4bd40c9e7671fef96671"
|
||||
checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"rustls-pki-types",
|
||||
@@ -1386,9 +1386,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.21"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
|
||||
[[package]]
|
||||
name = "rxing"
|
||||
@@ -1501,9 +1501,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.141"
|
||||
version = "1.0.142"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
|
||||
checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
@@ -1537,9 +1537,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.10"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
|
||||
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
@@ -1691,9 +1691,9 @@ source = "git+https://github.com/y21/tl.git?rev=13ed128e35ce04c4f16c41cb1e38347d
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.47.0"
|
||||
version = "1.47.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35"
|
||||
checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
@@ -1740,9 +1740,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.15"
|
||||
version = "0.7.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
|
||||
checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
@@ -2122,7 +2122,7 @@ version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||
dependencies = [
|
||||
"windows-targets 0.53.2",
|
||||
"windows-targets 0.53.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2158,10 +2158,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.53.2"
|
||||
version = "0.53.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
|
||||
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows_aarch64_gnullvm 0.53.0",
|
||||
"windows_aarch64_msvc 0.53.0",
|
||||
"windows_i686_gnu 0.53.0",
|
||||
@@ -2398,9 +2399,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerovec"
|
||||
version = "0.11.2"
|
||||
version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
|
||||
checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
|
||||
dependencies = [
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/build
|
||||
@@ -0,0 +1,46 @@
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
alias(libs.plugins.spotless)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.android.gradlePlugin)
|
||||
compileOnly(libs.kotlin.gradlePlugin)
|
||||
compileOnly(libs.spotless.gradlePlugin)
|
||||
|
||||
// https://github.com/gradle/gradle/issues/15383#issuecomment-779893192
|
||||
compileOnly(files(libs::class.java.superclass.protectionDomain.codeSource.location))
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
register("androidApplication") {
|
||||
id = libs.plugins.ehviewer.android.application.get().pluginId
|
||||
implementationClass = "AndroidApplicationConventionPlugin"
|
||||
}
|
||||
register("multiplatformLibrary") {
|
||||
id = libs.plugins.ehviewer.multiplatform.library.asProvider().get().pluginId
|
||||
implementationClass = "MultiplatformLibraryConventionPlugin"
|
||||
}
|
||||
register("multiplatformLibraryCompose") {
|
||||
id = libs.plugins.ehviewer.multiplatform.library.compose.get().pluginId
|
||||
implementationClass = "MultiplatformLibraryComposeConventionPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21)
|
||||
}
|
||||
|
||||
spotless {
|
||||
val ktlintVersion = libs.ktlint.get().version
|
||||
kotlin {
|
||||
// https://github.com/diffplug/spotless/issues/111
|
||||
target("src/**/*.kt")
|
||||
ktlint(ktlintVersion)
|
||||
}
|
||||
kotlinGradle {
|
||||
ktlint(ktlintVersion)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import com.android.build.api.dsl.ApplicationExtension
|
||||
import com.android.build.api.dsl.Lint
|
||||
import com.ehviewer.configureKotlin
|
||||
import com.ehviewer.configureKotlinCompose
|
||||
import com.ehviewer.configureLint
|
||||
import com.ehviewer.configureSpotless
|
||||
import com.ehviewer.libs
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.apply
|
||||
import org.gradle.kotlin.dsl.assign
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidExtension
|
||||
|
||||
@Suppress("unused")
|
||||
class AndroidApplicationConventionPlugin : Plugin<Project> {
|
||||
override fun apply(target: Project) = with(target) {
|
||||
apply(plugin = libs.plugins.kotlin.android.get().pluginId)
|
||||
apply(plugin = libs.plugins.android.application.get().pluginId)
|
||||
apply(plugin = libs.plugins.compose.compiler.get().pluginId)
|
||||
apply(plugin = libs.plugins.composeCompilerReportGenerator.get().pluginId)
|
||||
|
||||
configure<KotlinAndroidExtension> {
|
||||
jvmToolchain(21)
|
||||
compilerOptions {
|
||||
configureKotlin()
|
||||
configureKotlinCompose()
|
||||
jvmDefault = JvmDefaultMode.NO_COMPATIBILITY
|
||||
}
|
||||
}
|
||||
configure<ApplicationExtension> {
|
||||
lint(Lint::configureLint)
|
||||
}
|
||||
configureSpotless()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import com.ehviewer.configureKotlinCompose
|
||||
import com.ehviewer.libs
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.apply
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
|
||||
@Suppress("unused")
|
||||
class MultiplatformLibraryComposeConventionPlugin : Plugin<Project> {
|
||||
override fun apply(target: Project) = with(target) {
|
||||
apply<MultiplatformLibraryConventionPlugin>()
|
||||
apply(plugin = libs.plugins.compose.compiler.get().pluginId)
|
||||
apply(plugin = libs.plugins.compose.multiplatform.get().pluginId)
|
||||
apply(plugin = libs.plugins.composeCompilerReportGenerator.get().pluginId)
|
||||
|
||||
configure<KotlinMultiplatformExtension> {
|
||||
compilerOptions {
|
||||
configureKotlinCompose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget
|
||||
import com.android.build.api.dsl.Lint
|
||||
import com.android.build.api.dsl.androidLibrary
|
||||
import com.ehviewer.configureKotlin
|
||||
import com.ehviewer.configureLint
|
||||
import com.ehviewer.configureSpotless
|
||||
import com.ehviewer.libs
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.apply
|
||||
import org.gradle.kotlin.dsl.assign
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.gradle.kotlin.dsl.dependencies
|
||||
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
|
||||
@OptIn(ExperimentalKotlinGradlePluginApi::class)
|
||||
class MultiplatformLibraryConventionPlugin : Plugin<Project> {
|
||||
override fun apply(target: Project) = with(target) {
|
||||
apply(plugin = libs.plugins.kotlin.multiplatform.get().pluginId)
|
||||
apply(plugin = libs.plugins.android.kotlin.multiplatform.library.get().pluginId)
|
||||
apply(plugin = libs.plugins.android.lint.get().pluginId)
|
||||
|
||||
configure<KotlinMultiplatformExtension> {
|
||||
jvmToolchain(21)
|
||||
compilerOptions {
|
||||
configureKotlin()
|
||||
}
|
||||
|
||||
applyHierarchyTemplate {
|
||||
common {
|
||||
group("jvm") {
|
||||
withCompilations { it.target is KotlinMultiplatformAndroidLibraryTarget }
|
||||
withJvm()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// jvm("desktop") {
|
||||
// compilerOptions {
|
||||
// jvmDefault = JvmDefaultMode.NO_COMPATIBILITY
|
||||
// }
|
||||
// }
|
||||
|
||||
androidLibrary {
|
||||
namespace = "com.ehviewer${path.replace(':', '.')}"
|
||||
|
||||
withHostTestBuilder {
|
||||
}
|
||||
|
||||
enableCoreLibraryDesugaring = true
|
||||
|
||||
compilerOptions {
|
||||
jvmDefault = JvmDefaultMode.NO_COMPATIBILITY
|
||||
}
|
||||
}
|
||||
}
|
||||
configure<Lint>(Lint::configureLint)
|
||||
configureSpotless()
|
||||
|
||||
dependencies {
|
||||
"coreLibraryDesugaring"(libs.desugar)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.ehviewer
|
||||
|
||||
import org.gradle.kotlin.dsl.assign
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
|
||||
|
||||
// https://kotlinlang.org/docs/gradle-compiler-options.html#all-compiler-options
|
||||
internal fun KotlinCommonCompilerOptions.configureKotlin() {
|
||||
progressiveMode = true
|
||||
allWarningsAsErrors = true
|
||||
optIn.addAll(
|
||||
"kotlin.ExperimentalStdlibApi",
|
||||
"kotlin.concurrent.atomics.ExperimentalAtomicApi",
|
||||
"kotlin.contracts.ExperimentalContracts",
|
||||
"kotlin.time.ExperimentalTime",
|
||||
"kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||
"kotlinx.coroutines.FlowPreview",
|
||||
)
|
||||
freeCompilerArgs.addAll(
|
||||
"-Xcontext-parameters",
|
||||
"-Xwhen-expressions=indy",
|
||||
"-Xannotation-default-target=param-property",
|
||||
)
|
||||
}
|
||||
|
||||
internal fun KotlinCommonCompilerOptions.configureKotlinCompose() {
|
||||
optIn.addAll(
|
||||
"androidx.compose.animation.ExperimentalAnimationApi",
|
||||
"androidx.compose.animation.ExperimentalSharedTransitionApi",
|
||||
"androidx.compose.foundation.ExperimentalFoundationApi",
|
||||
"androidx.compose.foundation.layout.ExperimentalLayoutApi",
|
||||
"androidx.compose.material3.ExperimentalMaterial3Api",
|
||||
"androidx.compose.material3.ExperimentalMaterial3ExpressiveApi",
|
||||
"androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi",
|
||||
"androidx.compose.runtime.ExperimentalComposeRuntimeApi",
|
||||
"androidx.compose.ui.ExperimentalComposeUiApi",
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.ehviewer
|
||||
|
||||
import com.android.build.api.dsl.Lint
|
||||
|
||||
internal fun Lint.configureLint() {
|
||||
checkReleaseBuilds = false
|
||||
disable += setOf("MissingTranslation", "MissingQuantity")
|
||||
error += setOf("InlinedApi")
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.ehviewer
|
||||
|
||||
import org.gradle.accessors.dm.LibrariesForLibs
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.the
|
||||
|
||||
internal val Project.libs
|
||||
get(): LibrariesForLibs = the()
|
||||
Loaded 100 of 144 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user