diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 6bb2cde05..f65a28139 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -216,8 +216,6 @@ dependencies {
// https://square.github.io/okhttp/changelogs/changelog/
implementation(platform(libs.okhttp.bom))
- implementation(platform(libs.okio.bom))
-
implementation(libs.logcat)
implementation(libs.diff)
diff --git a/app/src/main/kotlin/com/google/accompanist/systemuicontroller/SystemUiController.kt b/app/src/main/kotlin/com/google/accompanist/systemuicontroller/SystemUiController.kt
deleted file mode 100644
index 58a478380..000000000
--- a/app/src/main/kotlin/com/google/accompanist/systemuicontroller/SystemUiController.kt
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.accompanist.systemuicontroller
-
-import android.app.Activity
-import android.content.Context
-import android.content.ContextWrapper
-import android.view.View
-import android.view.Window
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Stable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.platform.LocalView
-import androidx.compose.ui.window.DialogWindowProvider
-import androidx.core.view.ViewCompat
-import androidx.core.view.WindowCompat
-import androidx.core.view.WindowInsetsCompat
-import androidx.core.view.WindowInsetsControllerCompat
-
-/**
- * A class which provides easy-to-use utilities for updating the System UI bar
- * colors within Jetpack Compose.
- */
-@Stable
-interface SystemUiController {
-
- /**
- * Control for the behavior of the system bars. This value should be one of the
- * [WindowInsetsControllerCompat] behavior constants:
- * [WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH] (Deprecated),
- * [WindowInsetsControllerCompat.BEHAVIOR_DEFAULT] and
- * [WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE].
- */
- var systemBarsBehavior: Int
-
- /**
- * Property which holds the status bar visibility. If set to true, show the status bar,
- * otherwise hide the status bar.
- */
- var isStatusBarVisible: Boolean
-
- /**
- * Property which holds the navigation bar visibility. If set to true, show the navigation bar,
- * otherwise hide the navigation bar.
- */
- var isNavigationBarVisible: Boolean
-
- /**
- * Property which holds the status & navigation bar visibility. If set to true, show both bars,
- * otherwise hide both bars.
- */
- var isSystemBarsVisible: Boolean
- get() = isNavigationBarVisible && isStatusBarVisible
- set(value) {
- isStatusBarVisible = value
- isNavigationBarVisible = value
- }
-
- /**
- * Property which holds whether the status bar icons + content are 'dark' or not.
- */
- var statusBarDarkContentEnabled: Boolean
-}
-
-/**
- * Remembers a [SystemUiController] for the given [window].
- *
- * If no [window] is provided, an attempt to find the correct [Window] is made.
- *
- * First, if the [LocalView]'s parent is a [DialogWindowProvider], then that dialog's [Window] will
- * be used.
- *
- * Second, we attempt to find [Window] for the [Activity] containing the [LocalView].
- *
- * If none of these are found (such as may happen in a preview), then the functionality of the
- * returned [SystemUiController] will be degraded, but won't throw an exception.
- */
-@Composable
-fun rememberSystemUiController(
- window: Window? = findWindow(),
-): SystemUiController {
- val view = LocalView.current
- return remember(view, window) { AndroidSystemUiController(view, window) }
-}
-
-@Composable
-private fun findWindow(): Window? = (LocalView.current.parent as? DialogWindowProvider)?.window
- ?: LocalView.current.context.findWindow()
-
-private tailrec fun Context.findWindow(): Window? = when (this) {
- is Activity -> window
- is ContextWrapper -> baseContext.findWindow()
- else -> null
-}
-
-/**
- * A helper class for setting the navigation and status bar colors for a [View], gracefully
- * degrading behavior based upon API level.
- *
- * Typically you would use [rememberSystemUiController] to remember an instance of this.
- */
-internal class AndroidSystemUiController(
- private val view: View,
- window: Window?,
-) : SystemUiController {
- private val windowInsetsController = window?.let {
- WindowCompat.getInsetsController(it, view)
- }
-
- override var systemBarsBehavior: Int
- get() = windowInsetsController?.systemBarsBehavior ?: 0
- set(value) {
- windowInsetsController?.systemBarsBehavior = value
- }
-
- override var isStatusBarVisible: Boolean
- get() {
- return ViewCompat.getRootWindowInsets(view)
- ?.isVisible(WindowInsetsCompat.Type.statusBars()) == true
- }
- set(value) {
- if (value) {
- windowInsetsController?.show(WindowInsetsCompat.Type.statusBars())
- } else {
- windowInsetsController?.hide(WindowInsetsCompat.Type.statusBars())
- }
- }
-
- override var isNavigationBarVisible: Boolean
- get() {
- return ViewCompat.getRootWindowInsets(view)
- ?.isVisible(WindowInsetsCompat.Type.navigationBars()) == true
- }
- set(value) {
- if (value) {
- windowInsetsController?.show(WindowInsetsCompat.Type.navigationBars())
- } else {
- windowInsetsController?.hide(WindowInsetsCompat.Type.navigationBars())
- }
- }
-
- override var statusBarDarkContentEnabled: Boolean
- get() = windowInsetsController?.isAppearanceLightStatusBars == true
- set(value) {
- windowInsetsController?.isAppearanceLightStatusBars = value
- }
-}
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/EhApplication.kt b/app/src/main/kotlin/com/hippo/ehviewer/EhApplication.kt
index 4740dcbbd..8155dcfdd 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/EhApplication.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/EhApplication.kt
@@ -38,8 +38,14 @@ import coil3.request.allowRgb565
import coil3.request.crossfade
import coil3.serviceLoaderEnabled
import coil3.util.DebugLogger
+import com.ehviewer.core.files.deleteContent
import com.ehviewer.core.ui.util.initSETConnection
+import com.ehviewer.core.util.isAtLeastO
+import com.ehviewer.core.util.isAtLeastP
+import com.ehviewer.core.util.isAtLeastS
+import com.ehviewer.core.util.isAtLeastSExtension7
import com.ehviewer.core.util.launchIO
+import com.ehviewer.core.util.logcat
import com.ehviewer.core.util.withUIContext
import com.hippo.ehviewer.client.EhTagDatabase
import com.hippo.ehviewer.coil.AnimatedWebPDecoder
@@ -68,12 +74,6 @@ import com.hippo.ehviewer.util.CrashHandler
import com.hippo.ehviewer.util.FavouriteStatusRouter
import com.hippo.ehviewer.util.FileUtils
import com.hippo.ehviewer.util.OSUtils
-import com.hippo.ehviewer.util.isAtLeastO
-import com.hippo.ehviewer.util.isAtLeastP
-import com.hippo.ehviewer.util.isAtLeastS
-import com.hippo.ehviewer.util.isAtLeastSExtension7
-import com.hippo.files.deleteContent
-import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.client.HttpClient
import io.ktor.client.engine.okhttp.OkHttp
import kotlinx.coroutines.Dispatchers
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/EhDB.kt b/app/src/main/kotlin/com/hippo/ehviewer/EhDB.kt
index afc2e30d4..37125ef4a 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/EhDB.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/EhDB.kt
@@ -19,6 +19,7 @@ import android.content.Context
import android.net.Uri
import arrow.fx.coroutines.resource
import arrow.fx.coroutines.resourceScope
+import com.ehviewer.core.files.sendTo
import com.hippo.ehviewer.client.data.BaseGalleryInfo
import com.hippo.ehviewer.dao.DownloadArtist
import com.hippo.ehviewer.dao.DownloadDirname
@@ -32,7 +33,6 @@ import com.hippo.ehviewer.dao.ProgressInfo
import com.hippo.ehviewer.dao.QuickSearch
import com.hippo.ehviewer.dao.Schema17to18
import com.hippo.ehviewer.download.DownloadManager
-import com.hippo.ehviewer.util.sendTo
import kotlinx.coroutines.flow.Flow
import okio.Path
import okio.Path.Companion.toOkioPath
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/SettingsCollector.kt b/app/src/main/kotlin/com/hippo/ehviewer/SettingsCollector.kt
index fda29068f..bca27d907 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/SettingsCollector.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/SettingsCollector.kt
@@ -4,13 +4,13 @@ import android.app.UiModeManager
import androidx.appcompat.app.AppCompatDelegate
import arrow.core.Either.Companion.catch
import com.ehviewer.core.preferences.PrefDelegate
+import com.ehviewer.core.util.isAtLeastS
+import com.ehviewer.core.util.logcat
import com.ehviewer.core.util.withIOContext
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.system.logcat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/client/EhEngine.kt b/app/src/main/kotlin/com/hippo/ehviewer/client/EhEngine.kt
index 6599ef5b4..02c83fcbb 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/client/EhEngine.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/client/EhEngine.kt
@@ -22,6 +22,7 @@ import arrow.core.right
import arrow.fx.coroutines.parMap
import arrow.fx.coroutines.parZip
import com.ehviewer.core.i18n.R
+import com.ehviewer.core.util.logcat
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.data.BaseGalleryInfo
@@ -61,7 +62,6 @@ import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.ReadableTime
import com.hippo.ehviewer.util.bodyAsUtf8Text
import com.hippo.ehviewer.util.ensureSuccess
-import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.client.statement.HttpResponse
import io.ktor.client.statement.HttpStatement
import io.ktor.client.statement.bodyAsChannel
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/client/EhRequestBuilder.kt b/app/src/main/kotlin/com/hippo/ehviewer/client/EhRequestBuilder.kt
index b4a3c3875..56b8a0db9 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/client/EhRequestBuilder.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/client/EhRequestBuilder.kt
@@ -15,11 +15,11 @@
*/
package com.hippo.ehviewer.client
+import com.ehviewer.core.util.logcat
import com.hippo.ehviewer.EhApplication.Companion.ktorClient
import com.hippo.ehviewer.EhApplication.Companion.noRedirectKtorClient
import com.hippo.ehviewer.util.bodyAsUtf8Text
import com.hippo.ehviewer.util.ensureSuccess
-import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.forms.FormDataContent
import io.ktor.client.request.header
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/client/EhTagDatabase.kt b/app/src/main/kotlin/com/hippo/ehviewer/client/EhTagDatabase.kt
index fffa2d9e0..f5a43f818 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/client/EhTagDatabase.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/client/EhTagDatabase.kt
@@ -20,6 +20,10 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import arrow.core.Either
+import com.ehviewer.core.files.metadataOrNull
+import com.ehviewer.core.files.read
+import com.ehviewer.core.files.write
+import com.ehviewer.core.util.logcat
import com.hippo.ehviewer.EhApplication.Companion.ktorClient
import com.hippo.ehviewer.R
import com.hippo.ehviewer.client.data.TagNamespace
@@ -27,10 +31,6 @@ import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.bodyAsUtf8Text
import com.hippo.ehviewer.util.ensureSuccess
import com.hippo.ehviewer.util.utf8
-import com.hippo.files.metadataOrNull
-import com.hippo.files.read
-import com.hippo.files.write
-import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.client.request.prepareGet
import kotlin.time.Clock
import kotlin.time.Duration.Companion.days
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/client/data/GalleryInfo.kt b/app/src/main/kotlin/com/hippo/ehviewer/client/data/GalleryInfo.kt
index ba26e92f1..024268aca 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/client/data/GalleryInfo.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/client/data/GalleryInfo.kt
@@ -15,7 +15,7 @@
*/
package com.hippo.ehviewer.client.data
-import moe.tarsin.kt.unreachable
+import com.ehviewer.core.util.unreachable
interface GalleryInfo {
var gid: Long
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/client/parser/FavoritesParser.kt b/app/src/main/kotlin/com/hippo/ehviewer/client/parser/FavoritesParser.kt
index b24131425..a7cab2ae5 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/client/parser/FavoritesParser.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/client/parser/FavoritesParser.kt
@@ -1,7 +1,7 @@
package com.hippo.ehviewer.client.parser
+import com.ehviewer.core.util.unescapeXml
import com.hippo.ehviewer.client.exception.ParseException
-import com.hippo.ehviewer.util.unescapeXml
import java.nio.ByteBuffer
import kotlinx.serialization.Serializable
import moe.tarsin.coroutines.runSuspendCatching
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/client/parser/GalleryApiParser.kt b/app/src/main/kotlin/com/hippo/ehviewer/client/parser/GalleryApiParser.kt
index 1d3c02491..bb33c6669 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/client/parser/GalleryApiParser.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/client/parser/GalleryApiParser.kt
@@ -15,11 +15,11 @@
*/
package com.hippo.ehviewer.client.parser
+import com.ehviewer.core.util.unescapeXml
import com.hippo.ehviewer.client.EhUtils.getCategory
import com.hippo.ehviewer.client.data.GalleryInfo
import com.hippo.ehviewer.client.getThumbKey
import com.hippo.ehviewer.client.parseAs
-import com.hippo.ehviewer.util.unescapeXml
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/client/parser/GalleryPageParser.kt b/app/src/main/kotlin/com/hippo/ehviewer/client/parser/GalleryPageParser.kt
index e54373b64..c21e92c51 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/client/parser/GalleryPageParser.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/client/parser/GalleryPageParser.kt
@@ -15,8 +15,8 @@
*/
package com.hippo.ehviewer.client.parser
+import com.ehviewer.core.util.unescapeXml
import com.hippo.ehviewer.client.exception.ParseException
-import com.hippo.ehviewer.util.unescapeXml
object GalleryPageParser {
private val PATTERN_IMAGE_URL = Regex("
]*src=\"([^\"]+)\" style")
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/client/parser/ParserUtils.kt b/app/src/main/kotlin/com/hippo/ehviewer/client/parser/ParserUtils.kt
index a310b6a0b..43c6ba529 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/client/parser/ParserUtils.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/client/parser/ParserUtils.kt
@@ -15,9 +15,9 @@
*/
package com.hippo.ehviewer.client.parser
-import com.hippo.ehviewer.util.toEpochMillis
-import com.hippo.ehviewer.util.toIntOrDefault
-import com.hippo.ehviewer.util.toLocalDateTime
+import com.ehviewer.core.util.toEpochMillis
+import com.ehviewer.core.util.toIntOrDefault
+import com.ehviewer.core.util.toLocalDateTime
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.format.char
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/coil/AnimatedWebPDrawable.kt b/app/src/main/kotlin/com/hippo/ehviewer/coil/AnimatedWebPDrawable.kt
index 617836a01..ffe247658 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/coil/AnimatedWebPDrawable.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/coil/AnimatedWebPDrawable.kt
@@ -9,7 +9,7 @@ import android.graphics.drawable.Animatable
import android.graphics.drawable.Drawable
import android.os.SystemClock
import androidx.core.graphics.createBitmap
-import eu.kanade.tachiyomi.util.system.logcat
+import com.ehviewer.core.util.logcat
import java.nio.ByteBuffer
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/coil/CropBorderInterceptor.kt b/app/src/main/kotlin/com/hippo/ehviewer/coil/CropBorderInterceptor.kt
index a3a62dbf1..fe8972503 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/coil/CropBorderInterceptor.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/coil/CropBorderInterceptor.kt
@@ -12,9 +12,9 @@ import coil3.asImage
import coil3.intercept.Interceptor
import coil3.request.ImageResult
import coil3.request.SuccessResult
+import com.ehviewer.core.util.isAtLeastQ
+import com.ehviewer.core.util.logcat
import com.hippo.ehviewer.image.copyBitmapToAHB
-import com.hippo.ehviewer.util.isAtLeastQ
-import eu.kanade.tachiyomi.util.system.logcat
import moe.tarsin.coroutines.runSuspendCatching
@RequiresApi(Build.VERSION_CODES.O)
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/coil/DownloadThumbInterceptor.kt b/app/src/main/kotlin/com/hippo/ehviewer/coil/DownloadThumbInterceptor.kt
index 135bb75e0..24a459e64 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/coil/DownloadThumbInterceptor.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/coil/DownloadThumbInterceptor.kt
@@ -6,16 +6,16 @@ import coil3.intercept.Interceptor
import coil3.request.ImageRequest
import coil3.request.ImageResult
import coil3.request.SuccessResult
+import com.ehviewer.core.files.delete
+import com.ehviewer.core.files.isDirectory
+import com.ehviewer.core.files.isFile
+import com.ehviewer.core.files.sendTo
+import com.ehviewer.core.files.toUri
import com.hippo.ehviewer.EhApplication.Companion.imageCache
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.client.getThumbKey
import com.hippo.ehviewer.dao.DownloadInfo
import com.hippo.ehviewer.download.downloadLocation
-import com.hippo.ehviewer.util.sendTo
-import com.hippo.files.delete
-import com.hippo.files.isDirectory
-import com.hippo.files.isFile
-import com.hippo.files.toUri
private val downloadInfoKey = Extras.Key(default = null)
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/dailycheck/DailyCheckWork.kt b/app/src/main/kotlin/com/hippo/ehviewer/dailycheck/DailyCheckWork.kt
index 581f74001..7cf91a52e 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/dailycheck/DailyCheckWork.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/dailycheck/DailyCheckWork.kt
@@ -19,11 +19,11 @@ import androidx.work.PeriodicWorkRequest
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.WorkerParameters
+import com.ehviewer.core.util.logcat
import com.ehviewer.core.util.withIOContext
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhEngine
-import eu.kanade.tachiyomi.util.system.logcat
import java.time.Duration
import java.util.concurrent.TimeUnit
import kotlin.time.Clock
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/download/DownloadManager.kt b/app/src/main/kotlin/com/hippo/ehviewer/download/DownloadManager.kt
index 6d4bfd841..d164c721b 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/download/DownloadManager.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/download/DownloadManager.kt
@@ -26,7 +26,13 @@ import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.core.util.size
import arrow.fx.coroutines.parMapNotNull
+import com.ehviewer.core.files.delete
+import com.ehviewer.core.files.find
+import com.ehviewer.core.files.toOkioPath
+import com.ehviewer.core.files.toUri
import com.ehviewer.core.preferences.edit
+import com.ehviewer.core.util.logcat
+import com.ehviewer.core.util.mapNotNull
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.data.BaseGalleryInfo
@@ -46,13 +52,7 @@ import com.hippo.ehviewer.spider.readCompatFromPath
import com.hippo.ehviewer.spider.toSimpleTags
import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.insertWith
-import com.hippo.ehviewer.util.mapNotNull
import com.hippo.ehviewer.util.runAssertingNotMainThread
-import com.hippo.files.delete
-import com.hippo.files.find
-import com.hippo.files.toOkioPath
-import com.hippo.files.toUri
-import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/download/DownloadService.kt b/app/src/main/kotlin/com/hippo/ehviewer/download/DownloadService.kt
index dbf9c1054..0270b071b 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/download/DownloadService.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/download/DownloadService.kt
@@ -32,6 +32,8 @@ import androidx.core.content.ContextCompat
import androidx.savedstate.serialization.decodeFromSavedState
import androidx.savedstate.serialization.encodeToSavedState
import com.ehviewer.core.i18n.R
+import com.ehviewer.core.util.isAtLeastS
+import com.ehviewer.core.util.logcat
import com.ehviewer.core.util.unsafeLazy
import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.client.data.BaseGalleryInfo
@@ -43,8 +45,6 @@ import com.hippo.ehviewer.dao.DownloadInfo
import com.hippo.ehviewer.ui.MainActivity
import com.hippo.ehviewer.util.FileUtils
import com.hippo.ehviewer.util.ReadableTime
-import com.hippo.ehviewer.util.isAtLeastS
-import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/gallery/ArchivePageLoader.kt b/app/src/main/kotlin/com/hippo/ehviewer/gallery/ArchivePageLoader.kt
index aec122c9f..303b78f90 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/gallery/ArchivePageLoader.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/gallery/ArchivePageLoader.kt
@@ -16,6 +16,8 @@
package com.hippo.ehviewer.gallery
import arrow.autoCloseScope
+import com.ehviewer.core.files.openFileDescriptor
+import com.ehviewer.core.util.logcat
import com.hippo.ehviewer.Settings.archivePasswds
import com.hippo.ehviewer.image.ImageSource
import com.hippo.ehviewer.image.byteBufferSource
@@ -29,8 +31,6 @@ import com.hippo.ehviewer.jni.providePassword
import com.hippo.ehviewer.jni.releaseByteBuffer
import com.hippo.ehviewer.util.FileUtils
import com.hippo.ehviewer.util.displayName
-import com.hippo.files.openFileDescriptor
-import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.coroutineScope
import moe.tarsin.kt.install
import okio.Path
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/gallery/PageLoader.kt b/app/src/main/kotlin/com/hippo/ehviewer/gallery/PageLoader.kt
index 04cfce5aa..8edf6580f 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/gallery/PageLoader.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/gallery/PageLoader.kt
@@ -4,6 +4,7 @@ import androidx.collection.SieveCache
import androidx.collection.mutableIntObjectMapOf
import arrow.fx.coroutines.ExitCase
import arrow.fx.coroutines.bracketCase
+import com.ehviewer.core.util.isAtLeastO
import com.ehviewer.core.util.withNonCancellableContext
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.Settings
@@ -13,7 +14,6 @@ import com.hippo.ehviewer.util.FileUtils
import com.hippo.ehviewer.util.OSUtils
import com.hippo.ehviewer.util.detectAds
import com.hippo.ehviewer.util.displayString
-import com.hippo.ehviewer.util.isAtLeastO
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.atomics.AtomicInt
import kotlin.concurrent.read
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/image/Image.kt b/app/src/main/kotlin/com/hippo/ehviewer/image/Image.kt
index fb11bfc15..a95e8a892 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/image/Image.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/image/Image.kt
@@ -36,6 +36,10 @@ import coil3.size.Dimension
import coil3.size.Precision
import coil3.size.Size
import coil3.size.SizeResolver
+import com.ehviewer.core.files.openFileDescriptor
+import com.ehviewer.core.files.toUri
+import com.ehviewer.core.util.isAtLeastP
+import com.ehviewer.core.util.isAtLeastU
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.coil.AnimatedWebPDrawable
import com.hippo.ehviewer.coil.BitmapImageWithExtraInfo
@@ -48,10 +52,6 @@ import com.hippo.ehviewer.jni.munmap
import com.hippo.ehviewer.jni.rewriteGifSource
import com.hippo.ehviewer.ktbuilder.execute
import com.hippo.ehviewer.ktbuilder.imageRequest
-import com.hippo.ehviewer.util.isAtLeastP
-import com.hippo.ehviewer.util.isAtLeastU
-import com.hippo.files.openFileDescriptor
-import com.hippo.files.toUri
import java.nio.ByteBuffer
import kotlin.concurrent.atomics.AtomicInt
import kotlin.concurrent.atomics.decrementAndFetch
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ktor/OkhttpExtensions.kt b/app/src/main/kotlin/com/hippo/ehviewer/ktor/OkhttpExtensions.kt
index 7b6068204..a13cc9003 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ktor/OkhttpExtensions.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ktor/OkhttpExtensions.kt
@@ -1,6 +1,6 @@
package com.hippo.ehviewer.ktor
-import com.hippo.ehviewer.util.isAtLeastQ
+import com.ehviewer.core.util.isAtLeastQ
import io.ktor.client.engine.okhttp.OkHttpConfig
import okhttp3.AsyncDns
import okhttp3.android.AndroidAsyncDns
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/legacy/SpiderInfoCompat.kt b/app/src/main/kotlin/com/hippo/ehviewer/legacy/SpiderInfoCompat.kt
index 9c67dac8b..47c534a4c 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/legacy/SpiderInfoCompat.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/legacy/SpiderInfoCompat.kt
@@ -1,7 +1,7 @@
package com.hippo.ehviewer.legacy
+import com.ehviewer.core.files.read
import com.hippo.ehviewer.spider.SpiderInfo
-import com.hippo.files.read
import kotlinx.io.readLineStrict
import okio.Path
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/spider/ComicInfo.kt b/app/src/main/kotlin/com/hippo/ehviewer/spider/ComicInfo.kt
index f9305a9b6..b336a5e59 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/spider/ComicInfo.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/spider/ComicInfo.kt
@@ -1,5 +1,7 @@
package com.hippo.ehviewer.spider
+import com.ehviewer.core.files.read
+import com.ehviewer.core.files.write
import com.hippo.ehviewer.client.EhUrl
import com.hippo.ehviewer.client.data.GalleryDetail
import com.hippo.ehviewer.client.data.GalleryInfo
@@ -17,8 +19,6 @@ import com.hippo.ehviewer.client.data.TagNamespace.Male
import com.hippo.ehviewer.client.data.TagNamespace.Mixed
import com.hippo.ehviewer.client.data.TagNamespace.Other
import com.hippo.ehviewer.client.data.TagNamespace.Parody
-import com.hippo.files.read
-import com.hippo.files.write
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderDen.kt b/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderDen.kt
index 7c2df96c0..ad52aa43b 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderDen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderDen.kt
@@ -20,6 +20,16 @@ import arrow.fx.coroutines.autoCloseable
import arrow.fx.coroutines.closeable
import arrow.fx.coroutines.parMap
import arrow.fx.coroutines.resourceScope
+import com.ehviewer.core.files.delete
+import com.ehviewer.core.files.exists
+import com.ehviewer.core.files.find
+import com.ehviewer.core.files.isDirectory
+import com.ehviewer.core.files.list
+import com.ehviewer.core.files.mkdirs
+import com.ehviewer.core.files.moveTo
+import com.ehviewer.core.files.openFileDescriptor
+import com.ehviewer.core.files.sendTo
+import com.ehviewer.core.util.logcat
import com.hippo.ehviewer.EhApplication.Companion.imageCache as sCache
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.Settings
@@ -39,17 +49,7 @@ import com.hippo.ehviewer.image.PathSource
import com.hippo.ehviewer.jni.archiveFdBatch
import com.hippo.ehviewer.util.FileUtils
import com.hippo.ehviewer.util.copyTo
-import com.hippo.ehviewer.util.sendTo
import com.hippo.ehviewer.util.sha1
-import com.hippo.files.delete
-import com.hippo.files.exists
-import com.hippo.files.find
-import com.hippo.files.isDirectory
-import com.hippo.files.list
-import com.hippo.files.mkdirs
-import com.hippo.files.moveTo
-import com.hippo.files.openFileDescriptor
-import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.client.statement.HttpResponse
import io.ktor.client.statement.bodyAsChannel
import io.ktor.client.statement.request
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderInfo.kt b/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderInfo.kt
index 3eda78073..d8ecb0fb4 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderInfo.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderInfo.kt
@@ -1,12 +1,12 @@
package com.hippo.ehviewer.spider
+import com.ehviewer.core.files.read
+import com.ehviewer.core.files.write
+import com.ehviewer.core.util.logcat
import com.hippo.ehviewer.coil.edit
import com.hippo.ehviewer.coil.read
import com.hippo.ehviewer.ktbuilder.diskCache
import com.hippo.ehviewer.legacy.readLegacySpiderInfo
-import com.hippo.files.read
-import com.hippo.files.write
-import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.io.readByteArray
import kotlinx.serialization.Serializable
import kotlinx.serialization.cbor.Cbor
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderQueen.kt b/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderQueen.kt
index a0e799513..292d28c6c 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderQueen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderQueen.kt
@@ -20,7 +20,9 @@ import androidx.annotation.IntDef
import arrow.core.Either
import arrow.core.getOrElse
import arrow.core.partially1
+import com.ehviewer.core.files.find
import com.ehviewer.core.i18n.R
+import com.ehviewer.core.util.logcat
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhEngine
import com.hippo.ehviewer.client.EhUrl
@@ -32,8 +34,6 @@ import com.hippo.ehviewer.client.data.GalleryPreview
import com.hippo.ehviewer.client.exception.FatalException
import com.hippo.ehviewer.client.exception.QuotaExceededException
import com.hippo.ehviewer.util.displayString
-import com.hippo.files.find
-import eu.kanade.tachiyomi.util.system.logcat
import kotlin.concurrent.atomics.AtomicInt
import kotlin.concurrent.atomics.decrementAndFetch
import kotlin.concurrent.atomics.incrementAndFetch
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/CommonOperations.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/CommonOperations.kt
index e3eee11d5..9fd14d1a9 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/CommonOperations.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/CommonOperations.kt
@@ -35,8 +35,16 @@ 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.files.delete
+import com.ehviewer.core.files.exists
+import com.ehviewer.core.files.isDirectory
+import com.ehviewer.core.files.write
import com.ehviewer.core.i18n.R
import com.ehviewer.core.ui.component.LabeledCheckbox
+import com.ehviewer.core.util.isAtLeastT
+import com.ehviewer.core.util.mapToLongArray
+import com.ehviewer.core.util.toEpochMillis
+import com.ehviewer.core.util.toLocalDateTime
import com.ehviewer.core.util.withIOContext
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.Settings
@@ -65,16 +73,8 @@ import com.hippo.ehviewer.ui.tools.awaitSelectItemWithIcon
import com.hippo.ehviewer.ui.tools.awaitSelectItemWithIconAndTextField
import com.hippo.ehviewer.util.FavouriteStatusRouter
import com.hippo.ehviewer.util.bgWork
-import com.hippo.ehviewer.util.isAtLeastT
-import com.hippo.ehviewer.util.mapToLongArray
import com.hippo.ehviewer.util.requestPermission
import com.hippo.ehviewer.util.restartApplication
-import com.hippo.ehviewer.util.toEpochMillis
-import com.hippo.ehviewer.util.toLocalDateTime
-import com.hippo.files.delete
-import com.hippo.files.exists
-import com.hippo.files.isDirectory
-import com.hippo.files.write
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlin.time.Clock
import kotlinx.coroutines.sync.Mutex
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/EhActivity.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/EhActivity.kt
index 25a8683f7..b68e0f160 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/EhActivity.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/EhActivity.kt
@@ -20,8 +20,8 @@ import android.view.View
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.ActivityNavigator
+import com.ehviewer.core.util.isAtLeastR
import com.hippo.ehviewer.Settings
-import com.hippo.ehviewer.util.isAtLeastR
import eu.kanade.tachiyomi.util.view.setSecureScreen
abstract class EhActivity : AppCompatActivity() {
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/MainActivity.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/MainActivity.kt
index e26b41281..c10e69503 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/MainActivity.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/MainActivity.kt
@@ -102,6 +102,8 @@ import androidx.core.net.toUri
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.lifecycle.compose.LifecycleResumeEffect
import androidx.navigation.compose.rememberNavController
+import com.ehviewer.core.files.isDirectory
+import com.ehviewer.core.files.toOkioPath
import com.ehviewer.core.i18n.R
import com.ehviewer.core.ui.component.LabeledCheckbox
import com.ehviewer.core.ui.component.LocalSideSheetState
@@ -110,6 +112,8 @@ import com.ehviewer.core.ui.icons.EhIcons
import com.ehviewer.core.ui.icons.filled.Subscriptions
import com.ehviewer.core.ui.util.LocalSnackBarFabPadding
import com.ehviewer.core.ui.util.LocalWindowSizeClass
+import com.ehviewer.core.util.isAtLeastQ
+import com.ehviewer.core.util.isAtLeastS
import com.ehviewer.core.util.withIOContext
import com.hippo.ehviewer.EhApplication.Companion.initialized
import com.hippo.ehviewer.Settings
@@ -144,11 +148,7 @@ import com.hippo.ehviewer.util.calculateFraction
import com.hippo.ehviewer.util.displayString
import com.hippo.ehviewer.util.getParcelableExtraCompat
import com.hippo.ehviewer.util.getUrlFromClipboard
-import com.hippo.ehviewer.util.isAtLeastQ
-import com.hippo.ehviewer.util.isAtLeastS
import com.hippo.ehviewer.util.sha1
-import com.hippo.files.isDirectory
-import com.hippo.files.toOkioPath
import com.ramcosta.composedestinations.DestinationsNavHost
import com.ramcosta.composedestinations.spec.Direction
import com.ramcosta.composedestinations.utils.currentDestinationAsState
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/Theme.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/Theme.kt
index 90abc2a51..7aae11774 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/Theme.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/Theme.kt
@@ -14,10 +14,10 @@ import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.navigation.NavBackStackEntry
+import com.ehviewer.core.ui.util.ProvideVectorPainterCache
import com.hippo.ehviewer.ui.theme.EhTheme
import com.hippo.ehviewer.ui.tools.DialogState
import com.hippo.ehviewer.ui.tools.LocalGlobalDialogState
-import com.hippo.ehviewer.ui.tools.ProvideVectorPainterCache
import com.ramcosta.composedestinations.animations.NavHostAnimatedDestinationStyle
import me.zhanghai.compose.preference.ProvidePreferenceTheme
import me.zhanghai.compose.preference.preferenceTheme
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/legacy/CoilImageGetter.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/legacy/CoilImageGetter.kt
index f61a69873..5c0ddae87 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/legacy/CoilImageGetter.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/legacy/CoilImageGetter.kt
@@ -7,8 +7,8 @@ import coil3.decode.DecodeUtils
import coil3.imageLoader
import coil3.request.crossfade
import coil3.size.Scale
+import com.ehviewer.core.util.toIntOrDefault
import com.hippo.ehviewer.ktbuilder.imageRequest
-import com.hippo.ehviewer.util.toIntOrDefault
import kotlin.math.roundToInt
import splitties.init.appCtx
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/login/PostLogin.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/login/PostLogin.kt
index 68ae604c0..5bfd12217 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/login/PostLogin.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/login/PostLogin.kt
@@ -1,11 +1,11 @@
package com.hippo.ehviewer.ui.login
import arrow.core.Either.Companion.catch
+import com.ehviewer.core.util.logcat
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhCookieStore
import com.hippo.ehviewer.client.EhEngine
import com.hippo.ehviewer.client.EhUrl
-import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/login/SignInScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/login/SignInScreen.kt
index 23fb3c6eb..4a2f5cc2c 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/login/SignInScreen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/login/SignInScreen.kt
@@ -60,6 +60,7 @@ import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import com.ehviewer.core.i18n.R
import com.ehviewer.core.ui.util.LocalWindowSizeClass
+import com.ehviewer.core.ui.util.ifTrueThen
import com.ehviewer.core.ui.util.isExpanded
import com.ehviewer.core.ui.util.thenIf
import com.ehviewer.core.util.launchIO
@@ -73,7 +74,6 @@ import com.hippo.ehviewer.ui.destinations.WebViewSignInScreenDestination
import com.hippo.ehviewer.ui.openBrowser
import com.hippo.ehviewer.ui.tools.awaitConfirmationOrCancel
import com.hippo.ehviewer.util.displayString
-import com.jamal.composeprefs3.ui.ifTrueThen
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/main/DownloadCard.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/main/DownloadCard.kt
index cffd11e9d..b14c766fb 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/main/DownloadCard.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/main/DownloadCard.kt
@@ -41,13 +41,13 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.ehviewer.core.i18n.R
import com.ehviewer.core.ui.component.CrystalCard
+import com.ehviewer.core.ui.component.GalleryListCardRating
import com.ehviewer.core.ui.util.TransitionsVisibilityScope
import com.ehviewer.core.ui.util.listThumbGenerator
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.dao.DownloadInfo
import com.hippo.ehviewer.download.DownloadManager
-import com.hippo.ehviewer.ui.tools.GalleryListCardRating
import com.hippo.ehviewer.util.FileUtils
@Composable
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/main/GalleryInfo.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/main/GalleryInfo.kt
index ddb819de8..daa7d00ae 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/main/GalleryInfo.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/main/GalleryInfo.kt
@@ -40,6 +40,7 @@ import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage
import com.ehviewer.core.ui.component.CrystalCard
import com.ehviewer.core.ui.component.ElevatedCard
+import com.ehviewer.core.ui.component.GalleryListCardRating
import com.ehviewer.core.ui.util.SharedElementBox
import com.ehviewer.core.ui.util.TransitionsVisibilityScope
import com.ehviewer.core.ui.util.listThumbGenerator
@@ -48,7 +49,6 @@ import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.client.data.GalleryInfo
import com.hippo.ehviewer.client.data.GalleryInfo.Companion.NOT_FAVORITED
import com.hippo.ehviewer.download.DownloadManager
-import com.hippo.ehviewer.ui.tools.GalleryListCardRating
import com.hippo.ehviewer.util.FavouriteStatusRouter
@Composable
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/main/SearchFilter.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/main/SearchFilter.kt
index b2a9492cf..da52633e8 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/main/SearchFilter.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/main/SearchFilter.kt
@@ -37,6 +37,7 @@ import com.ehviewer.core.i18n.R
import com.ehviewer.core.ui.component.DropdownFilterChip
import com.ehviewer.core.ui.util.thenIf
import com.ehviewer.core.util.launch
+import com.ehviewer.core.util.toIntOrDefault
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhTagDatabase
import com.hippo.ehviewer.client.EhUtils
@@ -44,7 +45,6 @@ import com.hippo.ehviewer.client.data.GalleryInfo.Companion.S_LANG_TAGS
import com.hippo.ehviewer.collectAsState
import com.hippo.ehviewer.ui.tools.DialogState
import com.hippo.ehviewer.ui.tools.awaitResult
-import com.hippo.ehviewer.util.toIntOrDefault
import kotlinx.coroutines.CoroutineScope
private val categoryTable = arrayOf(
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/PageActions.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/PageActions.kt
index ffd41499d..91a5cddfb 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/PageActions.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/PageActions.kt
@@ -13,7 +13,11 @@ import android.webkit.MimeTypeMap
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.material3.SnackbarHostState
import androidx.core.content.FileProvider
+import com.ehviewer.core.files.toOkioPath
import com.ehviewer.core.i18n.R
+import com.ehviewer.core.util.isAtLeastQ
+import com.ehviewer.core.util.isAtLeastT
+import com.ehviewer.core.util.logcat
import com.hippo.ehviewer.BuildConfig.APPLICATION_ID
import com.hippo.ehviewer.client.EhUrl
import com.hippo.ehviewer.client.data.GalleryInfo
@@ -23,11 +27,7 @@ import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.FileUtils
import com.hippo.ehviewer.util.awaitActivityResult
import com.hippo.ehviewer.util.displayPath
-import com.hippo.ehviewer.util.isAtLeastQ
-import com.hippo.ehviewer.util.isAtLeastT
import com.hippo.ehviewer.util.requestPermission
-import com.hippo.files.toOkioPath
-import eu.kanade.tachiyomi.util.system.logcat
import java.io.File
import kotlin.time.Clock
import moe.tarsin.coroutines.runSuspendCatching
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/PagerItem.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/PagerItem.kt
index 9c3f86f66..0fd22b9f0 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/PagerItem.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/PagerItem.kt
@@ -39,6 +39,7 @@ import coil3.compose.SubcomposeAsyncImage
import coil3.compose.SubcomposeAsyncImageContent
import com.ehviewer.core.i18n.R
import com.ehviewer.core.ui.util.thenIf
+import com.ehviewer.core.util.unreachable
import com.google.accompanist.drawablepainter.DrawablePainter
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.collectAsState
@@ -52,7 +53,6 @@ import com.hippo.ehviewer.util.AdsPlaceholderFile
import eu.kanade.tachiyomi.ui.reader.viewer.CombinedCircularProgressIndicator
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.drop
-import moe.tarsin.kt.unreachable
@Composable
fun PagerItem(
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/ReaderGeneralSetting.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/ReaderGeneralSetting.kt
index af40e3568..ca563ed67 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/ReaderGeneralSetting.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/ReaderGeneralSetting.kt
@@ -12,9 +12,9 @@ import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource
import com.ehviewer.core.i18n.R
+import com.ehviewer.core.util.isAtLeastP
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.asMutableState
-import com.hippo.ehviewer.util.isAtLeastP
@Composable
fun ReaderGeneralSetting() = Column(modifier = Modifier.verticalScroll(rememberScrollState()).navigationBarsPadding()) {
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/ReaderScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/ReaderScreen.kt
index ee4026518..87a092d60 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/ReaderScreen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/ReaderScreen.kt
@@ -54,7 +54,6 @@ import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.keepScreenOn
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.zIndex
-import androidx.core.view.WindowInsetsControllerCompat
import arrow.core.Either
import arrow.core.Either.Companion.catch
import arrow.core.raise.ensure
@@ -62,10 +61,11 @@ import arrow.core.right
import com.ehviewer.core.i18n.R
import com.ehviewer.core.ui.util.Await
import com.ehviewer.core.ui.util.asyncInVM
+import com.ehviewer.core.ui.util.rememberSystemUiController
import com.ehviewer.core.ui.util.thenIf
import com.ehviewer.core.util.launch
import com.ehviewer.core.util.launchIO
-import com.google.accompanist.systemuicontroller.rememberSystemUiController
+import com.ehviewer.core.util.unreachable
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.data.BaseGalleryInfo
@@ -104,7 +104,6 @@ import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.sample
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.serialization.Serializable
-import moe.tarsin.kt.unreachable
import moe.tarsin.string
import okio.Path.Companion.toPath
@@ -209,10 +208,10 @@ fun ReaderScreen(pageLoader: PageLoader, info: BaseGalleryInfo?) {
val keepScreenOn by Settings.keepScreenOn.collectAsState()
val uiController = rememberSystemUiController()
DisposableEffect(uiController) {
- uiController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+ uiController.showTransientSystemBarsBySwipe = true
onDispose {
uiController.isSystemBarsVisible = true
- uiController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_DEFAULT
+ uiController.showTransientSystemBarsBySwipe = false
}
}
val lazyListState = rememberLazyListState(LazyLayoutCacheWindow(SCROLL_FRACTION, SCROLL_FRACTION), pageLoader.startPage)
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/DownloadsFilterState.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/DownloadsFilterState.kt
index af461a3b8..46fc138ac 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/DownloadsFilterState.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/DownloadsFilterState.kt
@@ -1,8 +1,8 @@
package com.hippo.ehviewer.ui.screen
+import com.ehviewer.core.util.containsIgnoreCase
import com.hippo.ehviewer.dao.DownloadInfo
import com.hippo.ehviewer.download.DownloadsFilterMode
-import com.hippo.ehviewer.util.containsIgnoreCase
import kotlinx.serialization.Serializable
@Serializable
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/DownloadsScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/DownloadsScreen.kt
index 53096a640..aaca6af3e 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/DownloadsScreen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/DownloadsScreen.kt
@@ -92,11 +92,16 @@ import com.ehviewer.core.ui.component.ProvideSideSheetContent
import com.ehviewer.core.ui.icons.EhIcons
import com.ehviewer.core.ui.icons.big.Download
import com.ehviewer.core.ui.util.Await
+import com.ehviewer.core.ui.util.HapticFeedbackType
import com.ehviewer.core.ui.util.asyncState
+import com.ehviewer.core.ui.util.ifTrueThen
+import com.ehviewer.core.ui.util.rememberHapticFeedback
import com.ehviewer.core.ui.util.rememberInVM
+import com.ehviewer.core.ui.util.takeAndClear
import com.ehviewer.core.ui.util.thenIf
import com.ehviewer.core.util.launch
import com.ehviewer.core.util.launchIO
+import com.ehviewer.core.util.mapToLongArray
import com.ehviewer.core.util.onEachLatest
import com.ehviewer.core.util.withNonCancellableContext
import com.ehviewer.core.util.withUIContext
@@ -121,16 +126,11 @@ import com.hippo.ehviewer.ui.main.plus
import com.hippo.ehviewer.ui.navToReader
import com.hippo.ehviewer.ui.showMoveDownloadLabelList
import com.hippo.ehviewer.ui.tools.DialogState
-import com.hippo.ehviewer.ui.tools.HapticFeedbackType
import com.hippo.ehviewer.ui.tools.awaitConfirmationOrCancel
import com.hippo.ehviewer.ui.tools.awaitInputText
import com.hippo.ehviewer.ui.tools.awaitSelectAction
import com.hippo.ehviewer.ui.tools.awaitSelectItemWithCheckBox
import com.hippo.ehviewer.ui.tools.awaitSingleChoice
-import com.hippo.ehviewer.ui.tools.rememberHapticFeedback
-import com.hippo.ehviewer.util.mapToLongArray
-import com.hippo.ehviewer.util.takeAndClear
-import com.jamal.composeprefs3.ui.ifTrueThen
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/FavoritesScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/FavoritesScreen.kt
index 47eff419e..6a5f216c3 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/FavoritesScreen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/FavoritesScreen.kt
@@ -61,8 +61,10 @@ import com.ehviewer.core.ui.component.ProvideSideSheetContent
import com.ehviewer.core.ui.icons.EhIcons
import com.ehviewer.core.ui.icons.filled.GoTo
import com.ehviewer.core.ui.util.asyncState
+import com.ehviewer.core.ui.util.takeAndClear
import com.ehviewer.core.ui.util.thenIf
import com.ehviewer.core.util.launch
+import com.ehviewer.core.util.mapToLongArray
import com.ehviewer.core.util.onEachLatest
import com.ehviewer.core.util.withUIContext
import com.hippo.ehviewer.EhDB
@@ -81,8 +83,6 @@ import com.hippo.ehviewer.ui.main.GalleryList
import com.hippo.ehviewer.ui.startDownload
import com.hippo.ehviewer.ui.tools.awaitConfirmationOrCancel
import com.hippo.ehviewer.ui.tools.awaitSelectItem
-import com.hippo.ehviewer.util.mapToLongArray
-import com.hippo.ehviewer.util.takeAndClear
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryCommentsScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryCommentsScreen.kt
index 721d274b7..0525e053e 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryCommentsScreen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryCommentsScreen.kt
@@ -88,6 +88,7 @@ import com.ehviewer.core.ui.util.snackBarPadding
import com.ehviewer.core.ui.util.thenIf
import com.ehviewer.core.util.launch
import com.ehviewer.core.util.launchIO
+import com.ehviewer.core.util.logcat
import com.ehviewer.core.util.withUIContext
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhEngine
@@ -116,7 +117,6 @@ import com.hippo.ehviewer.util.displayString
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
-import eu.kanade.tachiyomi.util.system.logcat
import kotlin.math.roundToInt
import moe.tarsin.coroutines.runSuspendCatching
import moe.tarsin.navigate
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryDetailContent.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryDetailContent.kt
index 29d69fd76..342b414e4 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryDetailContent.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryDetailContent.kt
@@ -73,16 +73,20 @@ import com.ehviewer.core.ui.component.CrystalCard
import com.ehviewer.core.ui.component.FastScrollLazyVerticalGrid
import com.ehviewer.core.ui.component.FilledTertiaryIconButton
import com.ehviewer.core.ui.component.FilledTertiaryIconToggleButton
+import com.ehviewer.core.ui.component.GalleryDetailRating
+import com.ehviewer.core.ui.component.GalleryRatingBar
import com.ehviewer.core.ui.icons.EhIcons
import com.ehviewer.core.ui.icons.filled.Magnet
import com.ehviewer.core.ui.util.LocalWindowSizeClass
import com.ehviewer.core.ui.util.TransitionsVisibilityScope
+import com.ehviewer.core.ui.util.flattenForEach
import com.ehviewer.core.ui.util.isExpanded
import com.ehviewer.core.ui.util.rememberInVM
import com.ehviewer.core.util.async
import com.ehviewer.core.util.launch
import com.ehviewer.core.util.launchIO
import com.ehviewer.core.util.launchUI
+import com.ehviewer.core.util.logcat
import com.ehviewer.core.util.withIOContext
import com.ehviewer.core.util.withUIContext
import com.hippo.ehviewer.EhDB
@@ -132,8 +136,6 @@ import com.hippo.ehviewer.ui.navToReader
import com.hippo.ehviewer.ui.openBrowser
import com.hippo.ehviewer.ui.startDownload
import com.hippo.ehviewer.ui.tools.DialogState
-import com.hippo.ehviewer.ui.tools.GalleryDetailRating
-import com.hippo.ehviewer.ui.tools.GalleryRatingBar
import com.hippo.ehviewer.ui.tools.awaitConfirmationOrCancel
import com.hippo.ehviewer.ui.tools.awaitResult
import com.hippo.ehviewer.ui.tools.awaitSelectAction
@@ -148,9 +150,7 @@ import com.hippo.ehviewer.util.FavouriteStatusRouter
import com.hippo.ehviewer.util.addTextToClipboard
import com.hippo.ehviewer.util.bgWork
import com.hippo.ehviewer.util.displayString
-import com.hippo.ehviewer.util.flattenForEach
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
-import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.http.encodeURLParameter
import kotlin.coroutines.resume
import kotlin.math.roundToInt
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryDetailScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryDetailScreen.kt
index 22bebc26e..95b0de115 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryDetailScreen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryDetailScreen.kt
@@ -34,12 +34,15 @@ 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.files.delete
+import com.ehviewer.core.files.toOkioPath
import com.ehviewer.core.i18n.R
import com.ehviewer.core.ui.util.LocalWindowSizeClass
import com.ehviewer.core.ui.util.isExpanded
import com.ehviewer.core.ui.util.launchInVM
import com.ehviewer.core.ui.util.rememberInVM
import com.ehviewer.core.util.launchIO
+import com.ehviewer.core.util.logcat
import com.ehviewer.core.util.withIOContext
import com.hippo.ehviewer.EhApplication.Companion.imageCache
import com.hippo.ehviewer.EhDB
@@ -70,12 +73,9 @@ import com.hippo.ehviewer.util.AppHelper
import com.hippo.ehviewer.util.awaitActivityResult
import com.hippo.ehviewer.util.bgWork
import com.hippo.ehviewer.util.displayString
-import com.hippo.files.delete
-import com.hippo.files.toOkioPath
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
-import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.serialization.Serializable
import moe.tarsin.coroutines.runSuspendCatching
import moe.tarsin.snackbar
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryListScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryListScreen.kt
index b5f9366a0..f6cb86892 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryListScreen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryListScreen.kt
@@ -78,7 +78,9 @@ import com.ehviewer.core.ui.component.ProvideSideSheetContent
import com.ehviewer.core.ui.icons.EhIcons
import com.ehviewer.core.ui.icons.filled.GoTo
import com.ehviewer.core.ui.util.Await
+import com.ehviewer.core.ui.util.HapticFeedbackType
import com.ehviewer.core.ui.util.asyncState
+import com.ehviewer.core.ui.util.rememberHapticFeedback
import com.ehviewer.core.ui.util.thenIf
import com.ehviewer.core.util.launch
import com.ehviewer.core.util.launchIO
@@ -113,11 +115,9 @@ import com.hippo.ehviewer.ui.main.GalleryInfoListItem
import com.hippo.ehviewer.ui.main.GalleryList
import com.hippo.ehviewer.ui.main.SearchFilter
import com.hippo.ehviewer.ui.tools.DialogState
-import com.hippo.ehviewer.ui.tools.HapticFeedbackType
import com.hippo.ehviewer.ui.tools.awaitConfirmationOrCancel
import com.hippo.ehviewer.ui.tools.awaitInputText
import com.hippo.ehviewer.ui.tools.awaitInputTextWithCheckBox
-import com.hippo.ehviewer.ui.tools.rememberHapticFeedback
import com.hippo.ehviewer.ui.tools.rememberMutableStateInDataStore
import com.hippo.ehviewer.util.FavouriteStatusRouter
import com.ramcosta.composedestinations.annotation.Destination
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/ImageSearchScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/ImageSearchScreen.kt
index b0f05e497..1196de5be 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/ImageSearchScreen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/ImageSearchScreen.kt
@@ -27,6 +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.ehviewer.core.files.toOkioPath
import com.ehviewer.core.i18n.R
import com.ehviewer.core.ui.util.snackBarPadding
import com.ehviewer.core.util.launch
@@ -39,7 +40,6 @@ import com.hippo.ehviewer.ui.main.ImageSearch
import com.hippo.ehviewer.ui.main.plus
import com.hippo.ehviewer.util.pickVisualMedia
import com.hippo.ehviewer.util.sha1
-import com.hippo.files.toOkioPath
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/SearchBarScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/SearchBarScreen.kt
index beeb23218..39da2db87 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/SearchBarScreen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/SearchBarScreen.kt
@@ -66,6 +66,8 @@ 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.ehviewer.core.ui.util.ifNotNullThen
+import com.ehviewer.core.ui.util.ifTrueThen
import com.ehviewer.core.ui.util.thenIf
import com.hippo.ehviewer.EhApplication.Companion.searchDatabase
import com.hippo.ehviewer.Settings
@@ -80,8 +82,6 @@ import com.hippo.ehviewer.ui.theme.scrim
import com.hippo.ehviewer.ui.tools.DialogState
import com.hippo.ehviewer.ui.tools.awaitConfirmationOrCancel
import com.hippo.ehviewer.ui.tools.rememberCompositionActiveState
-import com.jamal.composeprefs3.ui.ifNotNullThen
-import com.jamal.composeprefs3.ui.ifTrueThen
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/AboutScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/AboutScreen.kt
index 5a488f9fb..c5180bde4 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/AboutScreen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/AboutScreen.kt
@@ -21,6 +21,7 @@ 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.files.delete
import com.ehviewer.core.i18n.R
import com.ehviewer.core.util.launch
import com.ehviewer.core.util.withUIContext
@@ -40,7 +41,6 @@ import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.ReadableTime
import com.hippo.ehviewer.util.displayString
import com.hippo.ehviewer.util.installPackage
-import com.hippo.files.delete
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/AdvancedScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/AdvancedScreen.kt
index ed60a45cd..185cf8e56 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/AdvancedScreen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/AdvancedScreen.kt
@@ -30,8 +30,14 @@ 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.files.delete
+import com.ehviewer.core.files.sendTo
+import com.ehviewer.core.files.toOkioPath
import com.ehviewer.core.i18n.R
+import com.ehviewer.core.util.isAtLeastO
+import com.ehviewer.core.util.isAtLeastSExtension7
import com.ehviewer.core.util.launch
+import com.ehviewer.core.util.logcat
import com.ehviewer.core.util.withIOContext
import com.hippo.ehviewer.BuildConfig
import com.hippo.ehviewer.EhDB
@@ -50,16 +56,10 @@ import com.hippo.ehviewer.util.ReadableTime
import com.hippo.ehviewer.util.displayPath
import com.hippo.ehviewer.util.getAppLanguage
import com.hippo.ehviewer.util.getLanguages
-import com.hippo.ehviewer.util.isAtLeastO
-import com.hippo.ehviewer.util.isAtLeastSExtension7
-import com.hippo.ehviewer.util.sendTo
import com.hippo.ehviewer.util.setAppLanguage
-import com.hippo.files.delete
-import com.hippo.files.toOkioPath
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
-import eu.kanade.tachiyomi.util.system.logcat
import java.io.File
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/DownloadScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/DownloadScreen.kt
index 7209074cd..52289c657 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/DownloadScreen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/DownloadScreen.kt
@@ -29,9 +29,19 @@ 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.files.delete
+import com.ehviewer.core.files.find
+import com.ehviewer.core.files.isDirectory
+import com.ehviewer.core.files.list
+import com.ehviewer.core.files.metadataOrNull
+import com.ehviewer.core.files.mkdirs
+import com.ehviewer.core.files.toOkioPath
+import com.ehviewer.core.files.toUri
import com.ehviewer.core.i18n.R
+import com.ehviewer.core.util.isAtLeastQ
import com.ehviewer.core.util.launch
import com.ehviewer.core.util.launchIO
+import com.ehviewer.core.util.logcat
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.asMutableState
@@ -60,20 +70,10 @@ import com.hippo.ehviewer.ui.tools.observed
import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.displayPath
import com.hippo.ehviewer.util.displayString
-import com.hippo.ehviewer.util.isAtLeastQ
import com.hippo.ehviewer.util.requestPermission
-import com.hippo.files.delete
-import com.hippo.files.find
-import com.hippo.files.isDirectory
-import com.hippo.files.list
-import com.hippo.files.metadataOrNull
-import com.hippo.files.mkdirs
-import com.hippo.files.toOkioPath
-import com.hippo.files.toUri
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
-import eu.kanade.tachiyomi.util.system.logcat
import moe.tarsin.coroutines.runSuspendCatching
import moe.tarsin.snackbar
import moe.tarsin.string
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/EhScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/EhScreen.kt
index 55bdddbba..8425bd410 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/EhScreen.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/EhScreen.kt
@@ -29,6 +29,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.fromHtml
import com.ehviewer.core.i18n.R
+import com.ehviewer.core.util.isAtLeastT
import com.ehviewer.core.util.launch
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.asMutableState
@@ -45,7 +46,6 @@ import com.hippo.ehviewer.ui.tools.awaitConfirmationOrCancel
import com.hippo.ehviewer.ui.tools.awaitSelectItem
import com.hippo.ehviewer.ui.tools.awaitSelectTime
import com.hippo.ehviewer.util.copyTextToClipboard
-import com.hippo.ehviewer.util.isAtLeastT
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/theme/Theme.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/theme/Theme.kt
index 61d96a349..48f1bd206 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/theme/Theme.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/theme/Theme.kt
@@ -19,10 +19,10 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import com.ehviewer.core.ui.component.scrollbarStyle
+import com.ehviewer.core.util.isAtLeastOMR1
+import com.ehviewer.core.util.isAtLeastS
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.collectAsState
-import com.hippo.ehviewer.util.isAtLeastOMR1
-import com.hippo.ehviewer.util.isAtLeastS
import com.materialkolor.dynamicColorScheme
fun ColorScheme.amoled(amoled: Boolean) = if (amoled) {
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/BBCodeTextContextMenu.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/BBCodeTextContextMenu.kt
index 0b847912f..da4df909e 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/BBCodeTextContextMenu.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/BBCodeTextContextMenu.kt
@@ -25,15 +25,13 @@ import androidx.compose.ui.text.input.getTextBeforeSelection
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.withStyle
import com.ehviewer.core.i18n.R
+import com.ehviewer.core.util.unreachable
import com.hippo.ehviewer.util.toRangeSet
import io.github.petertrr.diffutils.diffInline
-import io.github.petertrr.diffutils.patch.ChangeDelta
import io.github.petertrr.diffutils.patch.DeleteDelta
-import io.github.petertrr.diffutils.patch.EqualDelta
import io.github.petertrr.diffutils.patch.InsertDelta
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
-import moe.tarsin.kt.unreachable
import moe.tarsin.string
fun TextFieldValue.updateSpan(origin: TextFieldValue): TextFieldValue {
@@ -58,8 +56,6 @@ fun TextFieldValue.updateSpan(origin: TextFieldValue): TextFieldValue {
append(annoStr.subSequence(end, len))
}
}
- is ChangeDelta -> unreachable()
- is EqualDelta -> unreachable()
is InsertDelta -> {
val pos = delta.source.position
val toIns = delta.target.lines.first()
@@ -69,6 +65,7 @@ fun TextFieldValue.updateSpan(origin: TextFieldValue): TextFieldValue {
append(annoStr.subSequence(pos, len))
}
}
+ else -> unreachable()
}
// Update span range for updated comment
return copy(annotatedString = str)
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/Dialog.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/Dialog.kt
index c46cd8d21..7a2cf7cba 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/Dialog.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/Dialog.kt
@@ -96,10 +96,10 @@ import arrow.core.right
import com.ehviewer.core.i18n.R
import com.ehviewer.core.ui.component.FastScrollLazyColumn
import com.ehviewer.core.ui.component.LabeledCheckbox
+import com.ehviewer.core.ui.util.ifNotNullThen
+import com.ehviewer.core.ui.util.ifTrueThen
import com.hippo.ehviewer.client.EhTagDatabase
import com.hippo.ehviewer.client.EhTagDatabase.suggestion
-import com.jamal.composeprefs3.ui.ifNotNullThen
-import com.jamal.composeprefs3.ui.ifTrueThen
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlinx.coroutines.CancellableContinuation
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/PausableDialog.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/PausableDialog.kt
index e1ad59d31..f8c64f61f 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/PausableDialog.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/PausableDialog.kt
@@ -34,13 +34,13 @@ import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.round
import androidx.compose.ui.unit.toSize
import androidx.compose.ui.util.lerp
+import com.ehviewer.core.util.unreachable
import kotlinx.coroutines.launch
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
-import moe.tarsin.kt.unreachable
fun lerp(start: IntOffset, stop: IntOffset, fraction: Float) = IntOffset(
lerp(start.x, stop.x, fraction),
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/updater/AppUpdater.kt b/app/src/main/kotlin/com/hippo/ehviewer/updater/AppUpdater.kt
index e4577cf31..001def373 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/updater/AppUpdater.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/updater/AppUpdater.kt
@@ -1,12 +1,12 @@
package com.hippo.ehviewer.updater
+import com.ehviewer.core.files.write
import com.hippo.ehviewer.BuildConfig
import com.hippo.ehviewer.EhApplication.Companion.ktorClient
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.executeAndParseAs
import com.hippo.ehviewer.spider.timeoutBySpeed
import com.hippo.ehviewer.util.copyTo
-import com.hippo.files.write
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.accept
import io.ktor.client.request.bearerAuth
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/AppConfig.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/AppConfig.kt
index 12c9a0963..c428e6542 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/AppConfig.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/util/AppConfig.kt
@@ -17,11 +17,11 @@ package com.hippo.ehviewer.util
import android.os.Build
import android.os.Environment
+import com.ehviewer.core.files.exists
+import com.ehviewer.core.files.isDirectory
+import com.ehviewer.core.files.mkdirs
import com.hippo.ehviewer.BuildConfig
import com.hippo.ehviewer.client.parser.ParserUtils
-import com.hippo.files.exists
-import com.hippo.files.isDirectory
-import com.hippo.files.mkdirs
import java.io.File
import okio.Path
import okio.Path.Companion.toOkioPath
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/CollectionsExtensions.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/CollectionsExtensions.kt
index 2904a568d..14ba5f196 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/CollectionsExtensions.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/util/CollectionsExtensions.kt
@@ -1,17 +1,8 @@
package com.hippo.ehviewer.util
-import androidx.compose.runtime.snapshots.SnapshotStateMap
-import androidx.compose.ui.util.fastForEach
-
fun MutableList.insertWith(element: T, comparator: Comparator) {
val index = binarySearch(element, comparator).let {
if (it < 0) -it - 1 else it
}
add(index, element)
}
-
-inline fun List>.flattenForEach(action: (T) -> Unit) = fastForEach { list ->
- list.fastForEach { item -> action(item) }
-}
-
-fun SnapshotStateMap.takeAndClear() = toMap().values.also { clear() }
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/CrashHandler.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/CrashHandler.kt
index 36ecba07b..9e7085d1e 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/CrashHandler.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/util/CrashHandler.kt
@@ -2,9 +2,9 @@ package com.hippo.ehviewer.util
import android.os.Build
import android.os.Debug
+import com.ehviewer.core.util.logcat
import com.hippo.ehviewer.BuildConfig
import com.hippo.ehviewer.Settings
-import eu.kanade.tachiyomi.util.system.logcat
import java.io.File
import java.io.PrintWriter
import java.io.Writer
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/ExceptionUtils.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/ExceptionUtils.kt
index dbaead5a4..e8bfb00d9 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/ExceptionUtils.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/util/ExceptionUtils.kt
@@ -16,7 +16,7 @@
package com.hippo.ehviewer.util
import com.ehviewer.core.i18n.R
-import eu.kanade.tachiyomi.util.system.logcat
+import com.ehviewer.core.util.logcat
import io.ktor.client.network.sockets.ConnectTimeoutException
import io.ktor.client.network.sockets.SocketTimeoutException
import io.ktor.client.plugins.HttpRequestTimeoutException
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/FDUtils.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/FDUtils.kt
deleted file mode 100644
index 2ca659651..000000000
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/FDUtils.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.hippo.ehviewer.util
-
-import com.hippo.files.SystemFileSystem
-import okio.Path
-
-infix fun Path.sendTo(file: Path) = SystemFileSystem.copy(this, file)
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/FileUtils.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/FileUtils.kt
index 6fc9012cd..39f2d07a8 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/FileUtils.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/util/FileUtils.kt
@@ -15,7 +15,7 @@
*/
package com.hippo.ehviewer.util
-import com.hippo.files.write
+import com.ehviewer.core.files.write
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.InternalAPI
import io.ktor.utils.io.rethrowCloseCauseIfNeeded
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/LauncherUtils.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/LauncherUtils.kt
index 0f1adae55..fa04d91c7 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/LauncherUtils.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/util/LauncherUtils.kt
@@ -22,6 +22,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.ehviewer.core.i18n.R
+import com.ehviewer.core.util.isAtLeastO
import com.ehviewer.core.util.withIOContext
import com.ehviewer.core.util.withUIContext
import java.io.File
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/OSUtils.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/OSUtils.kt
index a7382191f..2e75db51f 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/OSUtils.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/util/OSUtils.kt
@@ -16,7 +16,7 @@
package com.hippo.ehviewer.util
import com.ehviewer.core.mainthread.checkNotMainThread
-import eu.kanade.tachiyomi.util.system.logcat
+import com.ehviewer.core.util.logcat
import java.io.File
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.runBlocking
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/PathUtils.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/PathUtils.kt
index a04799177..8131f155a 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/PathUtils.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/util/PathUtils.kt
@@ -6,10 +6,10 @@ import android.os.Environment
import android.provider.DocumentsContract
import androidx.core.provider.DocumentsContractCompat
import arrow.core.Either
+import com.ehviewer.core.files.openFileDescriptor
+import com.ehviewer.core.files.read
+import com.ehviewer.core.files.toUri
import com.hippo.ehviewer.jni.sha1 as nativeSha1
-import com.hippo.files.openFileDescriptor
-import com.hippo.files.read
-import com.hippo.files.toUri
import kotlinx.io.readString
import okio.Path
import splitties.init.appCtx
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/ReadableTime.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/ReadableTime.kt
index c73120324..71729b97e 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/ReadableTime.kt
+++ b/app/src/main/kotlin/com/hippo/ehviewer/util/ReadableTime.kt
@@ -19,6 +19,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import com.ehviewer.core.i18n.R
+import com.ehviewer.core.util.toLocalDateTime
import java.util.Locale
import kotlin.time.Clock
import kotlin.time.Instant
diff --git a/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ChapterNavigator.kt b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ChapterNavigator.kt
index 1d96bf636..f77549b66 100644
--- a/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ChapterNavigator.kt
+++ b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ChapterNavigator.kt
@@ -21,10 +21,10 @@ import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import com.ehviewer.core.ui.component.Slider
import com.ehviewer.core.ui.component.defaultMaxTickCount
+import com.ehviewer.core.ui.util.HapticFeedbackType
import com.ehviewer.core.ui.util.LocalWindowSizeClass
import com.ehviewer.core.ui.util.isExpanded
-import com.hippo.ehviewer.ui.tools.HapticFeedbackType
-import com.hippo.ehviewer.ui.tools.rememberHapticFeedback
+import com.ehviewer.core.ui.util.rememberHapticFeedback
@Composable
fun ChapterNavigator(
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index c04d732fd..e4c2ced74 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -24,10 +24,6 @@
8dp
-
- 16dp
- 1dp
-
12dp
12dp
4dp
diff --git a/core/common/build.gradle.kts b/core/common/build.gradle.kts
index d32da33ed..66123e15f 100644
--- a/core/common/build.gradle.kts
+++ b/core/common/build.gradle.kts
@@ -7,6 +7,9 @@ kotlin {
commonMain {
dependencies {
api(libs.kotlinx.coroutines.core)
+ api(libs.kotlinx.datetime)
+ api(libs.kotlinx.io)
+ api(libs.okio)
api(libs.logcat)
api(project.dependencies.platform(libs.arrow.stack))
api(libs.bundles.arrow)
@@ -15,6 +18,8 @@ kotlin {
androidMain {
dependencies {
api(libs.kotlinx.coroutines.android)
+ api(libs.splitties.appctx)
+ implementation(libs.androidx.core)
}
}
}
diff --git a/app/src/main/kotlin/com/hippo/files/AndroidFileSystem.kt b/core/common/src/androidMain/kotlin/com/ehviewer/core/files/AndroidFileSystem.kt
similarity index 98%
rename from app/src/main/kotlin/com/hippo/files/AndroidFileSystem.kt
rename to core/common/src/androidMain/kotlin/com/ehviewer/core/files/AndroidFileSystem.kt
index 3a2fbdd2e..befebf945 100644
--- a/app/src/main/kotlin/com/hippo/files/AndroidFileSystem.kt
+++ b/core/common/src/androidMain/kotlin/com/ehviewer/core/files/AndroidFileSystem.kt
@@ -1,4 +1,4 @@
-package com.hippo.files
+package com.ehviewer.core.files
import android.content.Context
import android.net.Uri
@@ -22,7 +22,6 @@ import okio.IOException
import okio.Path
import okio.Sink
import okio.Source
-import splitties.init.appCtx
class AndroidFileSystem(context: Context) : FileSystem() {
private val contentResolver = context.contentResolver
@@ -237,5 +236,3 @@ class AndroidFileSystem(context: Context) : FileSystem() {
private fun Path.isPhysicalFile() = toString().startsWith('/')
private fun Uri.isCifsDocument() = authority == "com.wa2c.android.cifsdocumentsprovider.documents"
-
-val SystemFileSystem = AndroidFileSystem(appCtx)
diff --git a/core/common/src/androidMain/kotlin/com/ehviewer/core/files/FileSystem.android.kt b/core/common/src/androidMain/kotlin/com/ehviewer/core/files/FileSystem.android.kt
new file mode 100644
index 000000000..7e6ee9136
--- /dev/null
+++ b/core/common/src/androidMain/kotlin/com/ehviewer/core/files/FileSystem.android.kt
@@ -0,0 +1,10 @@
+package com.ehviewer.core.files
+
+import okio.FileSystem
+import splitties.init.appCtx
+
+actual val SystemFileSystem: FileSystem
+ get() = PlatformSystemFileSystem
+
+@PublishedApi
+internal val PlatformSystemFileSystem = AndroidFileSystem(appCtx)
diff --git a/app/src/main/kotlin/com/hippo/files/Paths.kt b/core/common/src/androidMain/kotlin/com/ehviewer/core/files/Paths.android.kt
similarity index 54%
rename from app/src/main/kotlin/com/hippo/files/Paths.kt
rename to core/common/src/androidMain/kotlin/com/ehviewer/core/files/Paths.android.kt
index e772d5084..9486f0094 100644
--- a/app/src/main/kotlin/com/hippo/files/Paths.kt
+++ b/core/common/src/androidMain/kotlin/com/ehviewer/core/files/Paths.android.kt
@@ -1,4 +1,4 @@
-package com.hippo.files
+package com.ehviewer.core.files
import android.content.ContentResolver
import android.net.Uri
@@ -9,31 +9,11 @@ import kotlinx.io.buffered
import okio.Path
import okio.Path.Companion.toPath
-val Path.isDirectory get() = SystemFileSystem.metadataOrNull(this)?.isDirectory == true
+fun Path.openFileDescriptor(mode: String) = PlatformSystemFileSystem.openFileDescriptor(this, mode)
-val Path.isFile get() = SystemFileSystem.metadataOrNull(this)?.isRegularFile == true
+actual inline fun Path.read(f: Source.() -> T) = PlatformSystemFileSystem.rawSource(this).buffered().use(f)
-fun Path.metadataOrNull() = SystemFileSystem.metadataOrNull(this)
-
-fun Path.find(name: String) = resolve(name).takeIf { it.exists() }
-
-fun Path.exists() = SystemFileSystem.exists(this)
-
-fun Path.delete() = SystemFileSystem.deleteRecursively(this)
-
-fun Path.deleteContent() = SystemFileSystem.listOrNull(this)?.forEach(Path::delete)
-
-fun Path.list() = SystemFileSystem.listOrNull(this).orEmpty()
-
-fun Path.mkdirs() = SystemFileSystem.createDirectories(this)
-
-infix fun Path.moveTo(target: Path) = SystemFileSystem.atomicMove(this, target)
-
-fun Path.openFileDescriptor(mode: String) = SystemFileSystem.openFileDescriptor(this, mode)
-
-inline fun Path.read(f: Source.() -> T) = SystemFileSystem.rawSource(this).buffered().use(f)
-
-inline fun Path.write(f: Sink.() -> T) = SystemFileSystem.rawSink(this).buffered().use(f)
+actual inline fun Path.write(f: Sink.() -> T) = PlatformSystemFileSystem.rawSink(this).buffered().use(f)
fun Path.toUri(): Uri {
val str = toString()
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/SDKUtils.kt b/core/common/src/androidMain/kotlin/com/ehviewer/core/util/SDKUtils.kt
similarity index 57%
rename from app/src/main/kotlin/com/hippo/ehviewer/util/SDKUtils.kt
rename to core/common/src/androidMain/kotlin/com/ehviewer/core/util/SDKUtils.kt
index 71f2f6ab2..c35879482 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/SDKUtils.kt
+++ b/core/common/src/androidMain/kotlin/com/ehviewer/core/util/SDKUtils.kt
@@ -1,15 +1,35 @@
-package com.hippo.ehviewer.util
+package com.ehviewer.core.util
import android.os.Build
import android.os.ext.SdkExtensions
+import androidx.annotation.ChecksSdkIntAtLeast
+@ChecksSdkIntAtLeast(Build.VERSION_CODES.N)
val isAtLeastN = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
+
+@ChecksSdkIntAtLeast(Build.VERSION_CODES.O)
val isAtLeastO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
+
+@ChecksSdkIntAtLeast(Build.VERSION_CODES.O_MR1)
val isAtLeastOMR1 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1
+
+@ChecksSdkIntAtLeast(Build.VERSION_CODES.P)
val isAtLeastP = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
+
+@ChecksSdkIntAtLeast(Build.VERSION_CODES.Q)
val isAtLeastQ = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
+
+@ChecksSdkIntAtLeast(Build.VERSION_CODES.R)
val isAtLeastR = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
+
+@ChecksSdkIntAtLeast(Build.VERSION_CODES.S)
val isAtLeastS = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
+
+@ChecksSdkIntAtLeast(Build.VERSION_CODES.TIRAMISU)
val isAtLeastT = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
+
+@ChecksSdkIntAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
val isAtLeastU = Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
+
+@ChecksSdkIntAtLeast(api = 7, extension = Build.VERSION_CODES.S)
val isAtLeastSExtension7 = isAtLeastR && SdkExtensions.getExtensionVersion(Build.VERSION_CODES.S) >= 7
diff --git a/core/common/src/commonMain/kotlin/com/ehviewer/core/files/FileSystem.kt b/core/common/src/commonMain/kotlin/com/ehviewer/core/files/FileSystem.kt
new file mode 100644
index 000000000..315d8e4ce
--- /dev/null
+++ b/core/common/src/commonMain/kotlin/com/ehviewer/core/files/FileSystem.kt
@@ -0,0 +1,5 @@
+package com.ehviewer.core.files
+
+import okio.FileSystem
+
+expect val SystemFileSystem: FileSystem
diff --git a/core/common/src/commonMain/kotlin/com/ehviewer/core/files/Paths.kt b/core/common/src/commonMain/kotlin/com/ehviewer/core/files/Paths.kt
new file mode 100644
index 000000000..25107d893
--- /dev/null
+++ b/core/common/src/commonMain/kotlin/com/ehviewer/core/files/Paths.kt
@@ -0,0 +1,31 @@
+package com.ehviewer.core.files
+
+import kotlinx.io.Sink
+import kotlinx.io.Source
+import okio.Path
+
+val Path.isDirectory get() = SystemFileSystem.metadataOrNull(this)?.isDirectory == true
+
+val Path.isFile get() = SystemFileSystem.metadataOrNull(this)?.isRegularFile == true
+
+fun Path.metadataOrNull() = SystemFileSystem.metadataOrNull(this)
+
+fun Path.find(name: String) = resolve(name).takeIf { it.exists() }
+
+fun Path.exists() = SystemFileSystem.exists(this)
+
+fun Path.delete() = SystemFileSystem.deleteRecursively(this)
+
+fun Path.deleteContent() = SystemFileSystem.listOrNull(this)?.forEach(Path::delete)
+
+fun Path.list() = SystemFileSystem.listOrNull(this).orEmpty()
+
+fun Path.mkdirs() = SystemFileSystem.createDirectories(this)
+
+infix fun Path.moveTo(target: Path) = SystemFileSystem.atomicMove(this, target)
+
+infix fun Path.sendTo(target: Path) = SystemFileSystem.copy(this, target)
+
+expect inline fun Path.read(f: Source.() -> T): T
+
+expect inline fun Path.write(f: Sink.() -> T): T
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/ArrayUtils.kt b/core/common/src/commonMain/kotlin/com/ehviewer/core/util/ArrayUtils.kt
similarity index 94%
rename from app/src/main/kotlin/com/hippo/ehviewer/util/ArrayUtils.kt
rename to core/common/src/commonMain/kotlin/com/ehviewer/core/util/ArrayUtils.kt
index d14e48599..e36283c93 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/ArrayUtils.kt
+++ b/core/common/src/commonMain/kotlin/com/ehviewer/core/util/ArrayUtils.kt
@@ -1,4 +1,4 @@
-package com.hippo.ehviewer.util
+package com.ehviewer.core.util
inline fun > LongArray.mapNotNullTo(destination: C, transform: (Long) -> R?): C {
forEach { element -> transform(element)?.let { destination.add(it) } }
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/DateTimeUtil.kt b/core/common/src/commonMain/kotlin/com/ehviewer/core/util/DateTimeUtil.kt
similarity index 95%
rename from app/src/main/kotlin/com/hippo/ehviewer/util/DateTimeUtil.kt
rename to core/common/src/commonMain/kotlin/com/ehviewer/core/util/DateTimeUtil.kt
index e9f32d07c..9c1b2bc32 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/DateTimeUtil.kt
+++ b/core/common/src/commonMain/kotlin/com/ehviewer/core/util/DateTimeUtil.kt
@@ -1,4 +1,4 @@
-package com.hippo.ehviewer.util
+package com.ehviewer.core.util
import kotlin.time.Instant
import kotlinx.datetime.LocalDate
diff --git a/app/src/main/kotlin/eu/kanade/tachiyomi/util/system/Logcat.kt b/core/common/src/commonMain/kotlin/com/ehviewer/core/util/Logcat.kt
similarity index 93%
rename from app/src/main/kotlin/eu/kanade/tachiyomi/util/system/Logcat.kt
rename to core/common/src/commonMain/kotlin/com/ehviewer/core/util/Logcat.kt
index e1b39af49..424f1b036 100644
--- a/app/src/main/kotlin/eu/kanade/tachiyomi/util/system/Logcat.kt
+++ b/core/common/src/commonMain/kotlin/com/ehviewer/core/util/Logcat.kt
@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.util.system
+package com.ehviewer.core.util
import logcat.LogPriority
import logcat.asLog
diff --git a/app/src/main/kotlin/moe/tarsin/kt/PreConditions.kt b/core/common/src/commonMain/kotlin/com/ehviewer/core/util/PreConditions.kt
similarity index 63%
rename from app/src/main/kotlin/moe/tarsin/kt/PreConditions.kt
rename to core/common/src/commonMain/kotlin/com/ehviewer/core/util/PreConditions.kt
index bc8c4f771..fa3157b19 100644
--- a/app/src/main/kotlin/moe/tarsin/kt/PreConditions.kt
+++ b/core/common/src/commonMain/kotlin/com/ehviewer/core/util/PreConditions.kt
@@ -1,3 +1,3 @@
-package moe.tarsin.kt
+package com.ehviewer.core.util
fun unreachable(): Nothing = error("Unreachable!!!")
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/StringUtils.kt b/core/common/src/commonMain/kotlin/com/ehviewer/core/util/StringUtils.kt
similarity index 93%
rename from app/src/main/kotlin/com/hippo/ehviewer/util/StringUtils.kt
rename to core/common/src/commonMain/kotlin/com/ehviewer/core/util/StringUtils.kt
index 33c22a1b9..d62601140 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/util/StringUtils.kt
+++ b/core/common/src/commonMain/kotlin/com/ehviewer/core/util/StringUtils.kt
@@ -1,4 +1,4 @@
-package com.hippo.ehviewer.util
+package com.ehviewer.core.util
private val EntityRegex = "&(?:amp|lt|gt|quot|#039);".toRegex()
private val EntityMap = mapOf(
diff --git a/core/data/build.gradle.kts b/core/data/build.gradle.kts
index 727964c45..71b0f4bcb 100644
--- a/core/data/build.gradle.kts
+++ b/core/data/build.gradle.kts
@@ -7,13 +7,11 @@ kotlin {
commonMain {
dependencies {
api(projects.core.common)
- api(project.dependencies.platform(libs.okio.bom))
api(libs.androidx.datastore)
}
}
androidMain {
dependencies {
- api(libs.splitties.appctx)
}
}
}
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/HapticFeedback.kt b/core/ui/src/androidMain/kotlin/com/ehviewer/core/ui/util/HapticFeedback.android.kt
similarity index 79%
rename from app/src/main/kotlin/com/hippo/ehviewer/ui/tools/HapticFeedback.kt
rename to core/ui/src/androidMain/kotlin/com/ehviewer/core/ui/util/HapticFeedback.android.kt
index e4f6c09e9..fe9d471e8 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/HapticFeedback.kt
+++ b/core/ui/src/androidMain/kotlin/com/ehviewer/core/ui/util/HapticFeedback.android.kt
@@ -1,26 +1,16 @@
-package com.hippo.ehviewer.ui.tools
+package com.ehviewer.core.ui.util
import android.view.HapticFeedbackConstants
import android.view.View
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalView
-import com.hippo.ehviewer.util.isAtLeastOMR1
-import com.hippo.ehviewer.util.isAtLeastR
-import com.hippo.ehviewer.util.isAtLeastU
-
-enum class HapticFeedbackType {
- START,
- MOVE,
- END,
-}
-
-interface HapticFeedback {
- fun performHapticFeedback(hapticFeedbackType: HapticFeedbackType)
-}
+import com.ehviewer.core.util.isAtLeastOMR1
+import com.ehviewer.core.util.isAtLeastR
+import com.ehviewer.core.util.isAtLeastU
@Composable
-fun rememberHapticFeedback(): HapticFeedback {
+actual fun rememberHapticFeedback(): HapticFeedback {
val view = LocalView.current
return remember(view) { AndroidHapticFeedback(view) }
}
diff --git a/core/ui/src/androidMain/kotlin/com/ehviewer/core/ui/util/SystemUiController.android.kt b/core/ui/src/androidMain/kotlin/com/ehviewer/core/ui/util/SystemUiController.android.kt
new file mode 100644
index 000000000..df1f8db2f
--- /dev/null
+++ b/core/ui/src/androidMain/kotlin/com/ehviewer/core/ui/util/SystemUiController.android.kt
@@ -0,0 +1,77 @@
+package com.ehviewer.core.ui.util
+
+import android.app.Activity
+import android.content.Context
+import android.content.ContextWrapper
+import android.view.View
+import android.view.Window
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.platform.LocalView
+import androidx.compose.ui.window.DialogWindowProvider
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.WindowInsetsControllerCompat
+
+@Composable
+actual fun rememberSystemUiController(): SystemUiController {
+ val view = LocalView.current
+ val window = findWindow()
+ return remember(view, window) { AndroidSystemUiController(view, window) }
+}
+
+@Composable
+private fun findWindow(): Window? = (LocalView.current.parent as? DialogWindowProvider)?.window
+ ?: LocalView.current.context.findWindow()
+
+private tailrec fun Context.findWindow(): Window? = when (this) {
+ is Activity -> window
+ is ContextWrapper -> baseContext.findWindow()
+ else -> null
+}
+
+internal class AndroidSystemUiController(
+ private val view: View,
+ window: Window?,
+) : SystemUiController {
+ private val windowInsetsController = window?.let {
+ WindowCompat.getInsetsController(it, view)
+ }
+
+ override var showTransientSystemBarsBySwipe: Boolean
+ get() = windowInsetsController?.systemBarsBehavior == WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+ set(value) {
+ windowInsetsController?.systemBarsBehavior = if (value) {
+ WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+ } else {
+ WindowInsetsControllerCompat.BEHAVIOR_DEFAULT
+ }
+ }
+
+ override var isStatusBarVisible: Boolean
+ get() = ViewCompat.getRootWindowInsets(view)?.isVisible(WindowInsetsCompat.Type.statusBars()) == true
+ set(value) {
+ if (value) {
+ windowInsetsController?.show(WindowInsetsCompat.Type.statusBars())
+ } else {
+ windowInsetsController?.hide(WindowInsetsCompat.Type.statusBars())
+ }
+ }
+
+ override var isNavigationBarVisible: Boolean
+ get() = ViewCompat.getRootWindowInsets(view)?.isVisible(WindowInsetsCompat.Type.navigationBars()) == true
+ set(value) {
+ if (value) {
+ windowInsetsController?.show(WindowInsetsCompat.Type.navigationBars())
+ } else {
+ windowInsetsController?.hide(WindowInsetsCompat.Type.navigationBars())
+ }
+ }
+
+ override var statusBarDarkContentEnabled: Boolean
+ get() = windowInsetsController?.isAppearanceLightStatusBars == true
+ set(value) {
+ windowInsetsController?.isAppearanceLightStatusBars = value
+ }
+}
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/RatingWidget.kt b/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/component/RatingWidget.kt
similarity index 84%
rename from app/src/main/kotlin/com/hippo/ehviewer/ui/tools/RatingWidget.kt
rename to core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/component/RatingWidget.kt
index c88424542..f33ce936b 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/RatingWidget.kt
+++ b/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/component/RatingWidget.kt
@@ -1,4 +1,4 @@
-package com.hippo.ehviewer.ui.tools
+package com.ehviewer.core.ui.component
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
import androidx.compose.foundation.gestures.detectTapGestures
@@ -18,10 +18,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
-import com.hippo.ehviewer.R
+import com.ehviewer.core.ui.util.IconCached
import kotlin.math.roundToInt
private val colorYellow800 = Color(0xfff9a825)
@@ -34,7 +33,7 @@ private fun getImageVector(index: Int, rating: Int) = when {
}
@Composable
-fun MetaRatingWidgetReuse(rating: Float, ratingSize: Dp, ratingInterval: Dp, modifier: Modifier = Modifier) {
+fun RatingWidgetReuse(rating: Float, ratingSize: Dp, ratingInterval: Dp, modifier: Modifier = Modifier) {
val r = (rating * 2).roundToInt().coerceIn(0, 10)
Row(modifier = modifier) {
repeat(5) {
@@ -50,7 +49,7 @@ fun MetaRatingWidgetReuse(rating: Float, ratingSize: Dp, ratingInterval: Dp, mod
}
@Composable
-fun MetaRatingWidget(rating: Float, ratingSize: Dp, ratingInterval: Dp, modifier: Modifier = Modifier, onRatingChange: ((Float) -> Unit)? = null) {
+fun RatingWidget(rating: Float, ratingSize: Dp, ratingInterval: Dp, modifier: Modifier = Modifier, onRatingChange: ((Float) -> Unit)? = null) {
val r = (rating * 2).roundToInt().coerceIn(0, 10)
val density = LocalDensity.current
val ratingSizePx = remember { with(density) { ratingSize.toPx() } }
@@ -89,22 +88,22 @@ fun MetaRatingWidget(rating: Float, ratingSize: Dp, ratingInterval: Dp, modifier
@Composable
fun GalleryListCardRating(rating: Float, modifier: Modifier = Modifier) {
- MetaRatingWidgetReuse(
+ RatingWidgetReuse(
rating = rating,
- ratingSize = dimensionResource(id = R.dimen.rating_size),
- ratingInterval = dimensionResource(id = R.dimen.rating_interval),
+ ratingSize = 16.dp,
+ ratingInterval = 1.dp,
modifier = modifier,
)
}
@Composable
fun GalleryDetailRating(rating: Float) {
- MetaRatingWidget(rating = rating, ratingSize = 48.dp, ratingInterval = 12.dp)
+ RatingWidget(rating = rating, ratingSize = 48.dp, ratingInterval = 12.dp)
}
@Composable
fun GalleryRatingBar(rating: Float, onRatingChange: (Float) -> Unit, modifier: Modifier = Modifier) {
- MetaRatingWidget(
+ RatingWidget(
rating = rating,
ratingSize = 48.dp,
ratingInterval = 0.dp,
diff --git a/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/CollectionsExtensions.kt b/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/CollectionsExtensions.kt
new file mode 100644
index 000000000..d316294f5
--- /dev/null
+++ b/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/CollectionsExtensions.kt
@@ -0,0 +1,10 @@
+package com.ehviewer.core.ui.util
+
+import androidx.compose.runtime.snapshots.SnapshotStateMap
+import androidx.compose.ui.util.fastForEach
+
+inline fun List>.flattenForEach(action: (T) -> Unit) = fastForEach { list ->
+ list.fastForEach { item -> action(item) }
+}
+
+fun SnapshotStateMap.takeAndClear() = toMap().values.also { clear() }
diff --git a/app/src/main/kotlin/com/jamal/composeprefs3/ui/PrefsUtils.kt b/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/ComposableLambdaHelper.kt
similarity index 88%
rename from app/src/main/kotlin/com/jamal/composeprefs3/ui/PrefsUtils.kt
rename to core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/ComposableLambdaHelper.kt
index 247ea7a29..2a905c279 100644
--- a/app/src/main/kotlin/com/jamal/composeprefs3/ui/PrefsUtils.kt
+++ b/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/ComposableLambdaHelper.kt
@@ -1,4 +1,4 @@
-package com.jamal.composeprefs3.ui
+package com.ehviewer.core.ui.util
import androidx.compose.runtime.Composable
diff --git a/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/HapticFeedback.kt b/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/HapticFeedback.kt
new file mode 100644
index 000000000..01e54939d
--- /dev/null
+++ b/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/HapticFeedback.kt
@@ -0,0 +1,16 @@
+package com.ehviewer.core.ui.util
+
+import androidx.compose.runtime.Composable
+
+enum class HapticFeedbackType {
+ START,
+ MOVE,
+ END,
+}
+
+interface HapticFeedback {
+ fun performHapticFeedback(hapticFeedbackType: HapticFeedbackType)
+}
+
+@Composable
+expect fun rememberHapticFeedback(): HapticFeedback
diff --git a/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/SystemUiController.kt b/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/SystemUiController.kt
new file mode 100644
index 000000000..427b82ce9
--- /dev/null
+++ b/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/SystemUiController.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.ehviewer.core.ui.util
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Stable
+
+/**
+ * A class which provides easy-to-use utilities for updating the System UI bar
+ * colors within Jetpack Compose.
+ */
+@Stable
+interface SystemUiController {
+
+ var showTransientSystemBarsBySwipe: Boolean
+
+ /**
+ * Property which holds the status bar visibility. If set to true, show the status bar,
+ * otherwise hide the status bar.
+ */
+ var isStatusBarVisible: Boolean
+
+ /**
+ * Property which holds the navigation bar visibility. If set to true, show the navigation bar,
+ * otherwise hide the navigation bar.
+ */
+ var isNavigationBarVisible: Boolean
+
+ /**
+ * Property which holds the status & navigation bar visibility. If set to true, show both bars,
+ * otherwise hide both bars.
+ */
+ var isSystemBarsVisible: Boolean
+ get() = isNavigationBarVisible && isStatusBarVisible
+ set(value) {
+ isStatusBarVisible = value
+ isNavigationBarVisible = value
+ }
+
+ /**
+ * Property which holds whether the status bar icons + content are 'dark' or not.
+ */
+ var statusBarDarkContentEnabled: Boolean
+}
+
+@Composable
+expect fun rememberSystemUiController(): SystemUiController
diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/Workaround.kt b/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/Workaround.kt
similarity index 97%
rename from app/src/main/kotlin/com/hippo/ehviewer/ui/tools/Workaround.kt
rename to core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/Workaround.kt
index 63e53595f..b5f7e6599 100644
--- a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/Workaround.kt
+++ b/core/ui/src/commonMain/kotlin/com/ehviewer/core/ui/util/Workaround.kt
@@ -1,4 +1,4 @@
-package com.hippo.ehviewer.ui.tools
+package com.ehviewer.core.ui.util
import androidx.collection.MutableScatterMap
import androidx.collection.mutableScatterMapOf
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 568e13fad..11ab929f9 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -22,6 +22,7 @@ compose-preference = "2.1.0"
kotlin = "2.2.20"
kotlinx-coroutines = "1.10.2"
kotlinx-datetime = "0.7.1"
+kotlinx-io = "0.8.0"
kotlinx-serialization = "1.9.0"
ksp = "2.2.20-2.0.3"
ktor = "3.3.0"
@@ -94,6 +95,7 @@ diff = "io.github.petertrr:kotlin-multiplatform-diff:1.1.0"
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }
+kotlinx-io = { module = "org.jetbrains.kotlinx:kotlinx-io-core", version.ref = "kotlinx-io" }
ktlint = "com.pinterest.ktlint:ktlint-cli:1.7.1"
@@ -104,7 +106,7 @@ logcat = "com.squareup.logcat:logcat:0.4"
moko-resources = { module = "dev.icerock.moko:resources", version.ref = "moko-resources" }
-okio-bom = { module = "com.squareup.okio:okio-bom", version.ref = "okio" }
+okio = { module = "com.squareup.okio:okio", version.ref = "okio" }
reorderable = "sh.calvin.reorderable:reorderable:3.0.0"