mirror of
https://github.com/Suwayomi/TachideskJUI.git
synced 2025-12-10 06:42:05 +01:00
Automatic Lint
This commit is contained in:
@@ -21,14 +21,13 @@ class ReaderActivity : AppCompatActivity() {
|
||||
context: Context,
|
||||
mangaId: Long,
|
||||
chapterIndex: Int,
|
||||
): Intent {
|
||||
return Intent(context, ReaderActivity::class.java).apply {
|
||||
): Intent =
|
||||
Intent(context, ReaderActivity::class.java).apply {
|
||||
putExtra("manga", mangaId)
|
||||
putExtra("chapter", chapterIndex)
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@@ -74,9 +74,7 @@ class AndroidDownloadService : Service() {
|
||||
context.stopService(Intent(context, AndroidDownloadService::class.java))
|
||||
}
|
||||
|
||||
fun isRunning(): Boolean {
|
||||
return instance != null
|
||||
}
|
||||
fun isRunning(): Boolean = instance != null
|
||||
|
||||
private val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
@@ -87,9 +85,7 @@ class AndroidDownloadService : Service() {
|
||||
|
||||
private lateinit var ioScope: CoroutineScope
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return null
|
||||
}
|
||||
override fun onBind(intent: Intent): IBinder? = null
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
@@ -123,7 +119,9 @@ class AndroidDownloadService : Service() {
|
||||
Actions.START.name,
|
||||
Actions.RESTART.name,
|
||||
-> startWebsocket()
|
||||
|
||||
Actions.STOP.name -> stopSelf()
|
||||
|
||||
else -> log.info { "This should never happen. No action in the received intent" }
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -73,9 +73,7 @@ class AndroidLibraryService : Service() {
|
||||
context.stopService(Intent(context, AndroidLibraryService::class.java))
|
||||
}
|
||||
|
||||
fun isRunning(): Boolean {
|
||||
return instance != null
|
||||
}
|
||||
fun isRunning(): Boolean = instance != null
|
||||
|
||||
private val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
@@ -86,9 +84,7 @@ class AndroidLibraryService : Service() {
|
||||
|
||||
private lateinit var ioScope: CoroutineScope
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return null
|
||||
}
|
||||
override fun onBind(intent: Intent): IBinder? = null
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
@@ -122,7 +118,9 @@ class AndroidLibraryService : Service() {
|
||||
Actions.START.name,
|
||||
Actions.RESTART.name,
|
||||
-> startWebsocket()
|
||||
|
||||
Actions.STOP.name -> stopSelf()
|
||||
|
||||
else -> log.info { "This should never happen. No action in the received intent" }
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -152,9 +152,11 @@ internal class PriorityChannelImpl<T>(
|
||||
yield()
|
||||
buffer.add(inChannel.receive())
|
||||
}
|
||||
|
||||
buffer.isFull() -> {
|
||||
outChannel.send(buffer.removeHead())
|
||||
}
|
||||
|
||||
else -> {
|
||||
while (buffer.isNotEmpty() && outChannel.trySend(buffer.head).isSuccess) {
|
||||
buffer.removeHead()
|
||||
|
||||
@@ -60,18 +60,14 @@ internal object StringAdapter : Adapter<String> {
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addStringOrNullListener(key) { callback() }
|
||||
}
|
||||
): SettingsListener = preferences.addStringOrNullListener(key) { callback() }
|
||||
}
|
||||
|
||||
internal object LongAdapter : Adapter<Long> {
|
||||
override fun get(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
): Long {
|
||||
return preferences.getLong(key, 0)
|
||||
}
|
||||
): Long = preferences.getLong(key, 0)
|
||||
|
||||
override fun set(
|
||||
key: String,
|
||||
@@ -85,18 +81,14 @@ internal object LongAdapter : Adapter<Long> {
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addLongOrNullListener(key) { callback() }
|
||||
}
|
||||
): SettingsListener = preferences.addLongOrNullListener(key) { callback() }
|
||||
}
|
||||
|
||||
internal object IntAdapter : Adapter<Int> {
|
||||
override fun get(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
): Int {
|
||||
return preferences.getInt(key, 0)
|
||||
}
|
||||
): Int = preferences.getInt(key, 0)
|
||||
|
||||
override fun set(
|
||||
key: String,
|
||||
@@ -110,18 +102,14 @@ internal object IntAdapter : Adapter<Int> {
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addIntOrNullListener(key) { callback() }
|
||||
}
|
||||
): SettingsListener = preferences.addIntOrNullListener(key) { callback() }
|
||||
}
|
||||
|
||||
internal object FloatAdapter : Adapter<Float> {
|
||||
override fun get(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
): Float {
|
||||
return preferences.getFloat(key, 0f)
|
||||
}
|
||||
): Float = preferences.getFloat(key, 0f)
|
||||
|
||||
override fun set(
|
||||
key: String,
|
||||
@@ -135,18 +123,14 @@ internal object FloatAdapter : Adapter<Float> {
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addFloatOrNullListener(key) { callback() }
|
||||
}
|
||||
): SettingsListener = preferences.addFloatOrNullListener(key) { callback() }
|
||||
}
|
||||
|
||||
internal object BooleanAdapter : Adapter<Boolean> {
|
||||
override fun get(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
): Boolean {
|
||||
return preferences.getBoolean(key, false)
|
||||
}
|
||||
): Boolean = preferences.getBoolean(key, false)
|
||||
|
||||
override fun set(
|
||||
key: String,
|
||||
@@ -160,9 +144,7 @@ internal object BooleanAdapter : Adapter<Boolean> {
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addBooleanOrNullListener(key) { callback() }
|
||||
}
|
||||
): SettingsListener = preferences.addBooleanOrNullListener(key) { callback() }
|
||||
}
|
||||
|
||||
internal object StringSetAdapter : Adapter<Set<String>> {
|
||||
@@ -189,9 +171,7 @@ internal object StringSetAdapter : Adapter<Set<String>> {
|
||||
override fun isSet(
|
||||
keys: Set<String>,
|
||||
key: String,
|
||||
): Boolean {
|
||||
return keys.contains("$key.size")
|
||||
}
|
||||
): Boolean = keys.contains("$key.size")
|
||||
|
||||
/**
|
||||
* Watching the regular key doesn't produce updates for a string set for some reason
|
||||
@@ -201,9 +181,7 @@ internal object StringSetAdapter : Adapter<Set<String>> {
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addIntOrNullListener("$key.size") { callback() }
|
||||
}
|
||||
): SettingsListener = preferences.addIntOrNullListener("$key.size") { callback() }
|
||||
}
|
||||
|
||||
internal class ObjectAdapter<T>(
|
||||
@@ -229,9 +207,7 @@ internal class ObjectAdapter<T>(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addStringOrNullListener(key) { callback() }
|
||||
}
|
||||
): SettingsListener = preferences.addStringOrNullListener(key) { callback() }
|
||||
}
|
||||
|
||||
internal class JsonObjectAdapter<T>(
|
||||
@@ -261,9 +237,7 @@ internal class JsonObjectAdapter<T>(
|
||||
override fun isSet(
|
||||
keys: Set<String>,
|
||||
key: String,
|
||||
): Boolean {
|
||||
return keys.any { it.startsWith(key) }
|
||||
}
|
||||
): Boolean = keys.any { it.startsWith(key) }
|
||||
|
||||
/**
|
||||
* Todo doesn't work
|
||||
|
||||
@@ -19,9 +19,7 @@ class StandardPreferenceStore(
|
||||
override fun getString(
|
||||
key: String,
|
||||
defaultValue: String,
|
||||
): Preference<String> {
|
||||
return StandardPreference(preferences, key, defaultValue, StringAdapter)
|
||||
}
|
||||
): Preference<String> = StandardPreference(preferences, key, defaultValue, StringAdapter)
|
||||
|
||||
/**
|
||||
* Returns a [Long] preference for this [key].
|
||||
@@ -29,9 +27,7 @@ class StandardPreferenceStore(
|
||||
override fun getLong(
|
||||
key: String,
|
||||
defaultValue: Long,
|
||||
): Preference<Long> {
|
||||
return StandardPreference(preferences, key, defaultValue, LongAdapter)
|
||||
}
|
||||
): Preference<Long> = StandardPreference(preferences, key, defaultValue, LongAdapter)
|
||||
|
||||
/**
|
||||
* Returns an [Int] preference for this [key].
|
||||
@@ -39,9 +35,7 @@ class StandardPreferenceStore(
|
||||
override fun getInt(
|
||||
key: String,
|
||||
defaultValue: Int,
|
||||
): Preference<Int> {
|
||||
return StandardPreference(preferences, key, defaultValue, IntAdapter)
|
||||
}
|
||||
): Preference<Int> = StandardPreference(preferences, key, defaultValue, IntAdapter)
|
||||
|
||||
/**
|
||||
* Returns a [Float] preference for this [key].
|
||||
@@ -49,9 +43,7 @@ class StandardPreferenceStore(
|
||||
override fun getFloat(
|
||||
key: String,
|
||||
defaultValue: Float,
|
||||
): Preference<Float> {
|
||||
return StandardPreference(preferences, key, defaultValue, FloatAdapter)
|
||||
}
|
||||
): Preference<Float> = StandardPreference(preferences, key, defaultValue, FloatAdapter)
|
||||
|
||||
/**
|
||||
* Returns a [Boolean] preference for this [key].
|
||||
@@ -59,9 +51,7 @@ class StandardPreferenceStore(
|
||||
override fun getBoolean(
|
||||
key: String,
|
||||
defaultValue: Boolean,
|
||||
): Preference<Boolean> {
|
||||
return StandardPreference(preferences, key, defaultValue, BooleanAdapter)
|
||||
}
|
||||
): Preference<Boolean> = StandardPreference(preferences, key, defaultValue, BooleanAdapter)
|
||||
|
||||
/**
|
||||
* Returns a [Set<String>] preference for this [key].
|
||||
@@ -69,9 +59,7 @@ class StandardPreferenceStore(
|
||||
override fun getStringSet(
|
||||
key: String,
|
||||
defaultValue: Set<String>,
|
||||
): Preference<Set<String>> {
|
||||
return StandardPreference(preferences, key, defaultValue, StringSetAdapter)
|
||||
}
|
||||
): Preference<Set<String>> = StandardPreference(preferences, key, defaultValue, StringSetAdapter)
|
||||
|
||||
/**
|
||||
* Returns preference of type [T] for this [key]. The [serializer] and [deserializer] function
|
||||
|
||||
@@ -14,15 +14,14 @@ object ImageUtil {
|
||||
private val gifMagic = "GIF8".toByteArray()
|
||||
private val webpMagic = "RIFF".toByteArray()
|
||||
|
||||
fun findType(bytes: ByteArray): ImageType? {
|
||||
return when {
|
||||
fun findType(bytes: ByteArray): ImageType? =
|
||||
when {
|
||||
bytes.compareWith(jpgMagic) -> ImageType.JPG
|
||||
bytes.compareWith(pngMagic) -> ImageType.PNG
|
||||
bytes.compareWith(gifMagic) -> ImageType.GIF
|
||||
bytes.compareWith(webpMagic) -> ImageType.WEBP
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun ByteArray.compareWith(magic: ByteArray): Boolean {
|
||||
for (i in magic.indices) {
|
||||
|
||||
@@ -22,8 +22,8 @@ class FlowConverterFactory : Converter.Factory {
|
||||
val typeData: TypeData,
|
||||
val ktorfit: Ktorfit,
|
||||
) : Converter.ResponseConverter<HttpResponse, Flow<Any?>> {
|
||||
override fun convert(getResponse: suspend () -> HttpResponse): Flow<Any?> {
|
||||
return flow {
|
||||
override fun convert(getResponse: suspend () -> HttpResponse): Flow<Any?> =
|
||||
flow {
|
||||
val response = getResponse()
|
||||
|
||||
val convertedBody = ktorfit.nextSuspendResponseConverter(
|
||||
@@ -34,7 +34,6 @@ class FlowConverterFactory : Converter.Factory {
|
||||
emit(convertedBody)
|
||||
}.flowOn(Dispatchers.IO)
|
||||
}
|
||||
}
|
||||
|
||||
override fun responseConverter(
|
||||
typeData: TypeData,
|
||||
|
||||
@@ -35,6 +35,7 @@ actual class DateHandler
|
||||
setTimeStyle(NSDateFormatterNoStyle)
|
||||
setLocale(Locale.current.toPlatform())
|
||||
}
|
||||
|
||||
else -> NSDateFormatter()
|
||||
.apply {
|
||||
setDateFormat(format)
|
||||
|
||||
@@ -32,6 +32,7 @@ actual class DateHandler
|
||||
"" -> DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
|
||||
.withLocale(Locale.current.toPlatform())
|
||||
.withZone(ZoneId.systemDefault())
|
||||
|
||||
else -> DateTimeFormatter.ofPattern(format)
|
||||
.withZone(ZoneId.systemDefault())
|
||||
}.let { formatter ->
|
||||
|
||||
@@ -130,7 +130,9 @@ suspend fun main() {
|
||||
SystemTheme.LIGHT, SystemTheme.UNKNOWN -> IntelliJTheme()
|
||||
SystemTheme.DARK -> DarculaTheme()
|
||||
}
|
||||
|
||||
ThemeMode.Light -> IntelliJTheme()
|
||||
|
||||
ThemeMode.Dark -> DarculaTheme()
|
||||
}
|
||||
withUIContext {
|
||||
@@ -188,10 +190,12 @@ suspend fun main() {
|
||||
// backPressHandler.handle()
|
||||
false
|
||||
}
|
||||
|
||||
Key.F3 -> {
|
||||
displayDebugInfoFlow.value = !displayDebugInfoFlow.value
|
||||
true
|
||||
}
|
||||
|
||||
else -> false
|
||||
}
|
||||
} else {
|
||||
@@ -220,6 +224,7 @@ suspend fun main() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ServerResult.STARTING, ServerResult.FAILED -> {
|
||||
Surface {
|
||||
LoadingScreen(
|
||||
|
||||
@@ -57,12 +57,14 @@ fun httpClient(
|
||||
engine {
|
||||
proxy = when (serverPreferences.proxy().get()) {
|
||||
Proxy.NO_PROXY -> null
|
||||
|
||||
Proxy.HTTP_PROXY -> ProxyBuilder.http(
|
||||
URLBuilder(
|
||||
host = serverPreferences.proxyHttpHost().get(),
|
||||
port = serverPreferences.proxyHttpPort().get(),
|
||||
).build(),
|
||||
)
|
||||
|
||||
Proxy.SOCKS_PROXY -> ProxyBuilder.socks(
|
||||
serverPreferences.proxySocksHost().get(),
|
||||
serverPreferences.proxySocksPort().get(),
|
||||
@@ -71,6 +73,7 @@ fun httpClient(
|
||||
}
|
||||
when (serverPreferences.auth().get()) {
|
||||
Auth.NONE -> Unit
|
||||
|
||||
Auth.BASIC -> AuthPlugin {
|
||||
basic {
|
||||
sendWithoutRequest {
|
||||
@@ -84,6 +87,7 @@ fun httpClient(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Auth.DIGEST -> AuthPlugin {
|
||||
digest {
|
||||
credentials {
|
||||
|
||||
@@ -143,6 +143,7 @@ class UpdatesPager
|
||||
updates.map {
|
||||
when (it) {
|
||||
is Updates.Date -> it
|
||||
|
||||
is Updates.Update -> it.copy(
|
||||
manga = changedManga[it.manga.id] ?: it.manga,
|
||||
chapter = changedChapters[it.chapter.id] ?: it.chapter,
|
||||
|
||||
@@ -77,12 +77,10 @@ class ServerService
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRuntimeJava(): String? {
|
||||
return System.getProperty("java.home")?.let { getJavaFromPath(it.toPath().resolve("bin")) }
|
||||
}
|
||||
private fun getRuntimeJava(): String? = System.getProperty("java.home")?.let { getJavaFromPath(it.toPath().resolve("bin")) }
|
||||
|
||||
private fun getPossibleJava(): String? {
|
||||
return System.getProperty("java.library.path")?.split(pathSeparatorChar)
|
||||
private fun getPossibleJava(): String? =
|
||||
System.getProperty("java.library.path")?.split(pathSeparatorChar)
|
||||
.orEmpty()
|
||||
.asSequence()
|
||||
.mapNotNull {
|
||||
@@ -99,7 +97,6 @@ class ServerService
|
||||
}
|
||||
.mapNotNull { getJavaFromPath(it) }
|
||||
.firstOrNull()
|
||||
}
|
||||
|
||||
private suspend fun runService() {
|
||||
process?.destroy()
|
||||
@@ -154,6 +151,7 @@ class ServerService
|
||||
when {
|
||||
it.contains("Javalin started") ->
|
||||
_initialized.value = ServerResult.STARTED
|
||||
|
||||
it.contains("Javalin has stopped") ->
|
||||
_initialized.value = ServerResult.FAILED
|
||||
}
|
||||
|
||||
@@ -17,9 +17,7 @@ sealed class ServerHostPreference<T : Any> {
|
||||
protected abstract val defaultValue: T
|
||||
protected abstract val serverValue: T
|
||||
|
||||
private fun validate(value: T): Boolean {
|
||||
return value != serverValue
|
||||
}
|
||||
private fun validate(value: T): Boolean = value != serverValue
|
||||
|
||||
fun getProperty(): String? {
|
||||
val preference = preference().get().takeIf(::validate)
|
||||
|
||||
@@ -117,12 +117,14 @@ fun ChapterDownloadIcon(
|
||||
onClick = { onClickDelete(chapter.chapter) },
|
||||
)
|
||||
}
|
||||
|
||||
ChapterDownloadState.Downloading -> {
|
||||
DownloadingIconButton(
|
||||
downloadChapter,
|
||||
onClick = { onClickStop(chapter.chapter) },
|
||||
)
|
||||
}
|
||||
|
||||
ChapterDownloadState.NotDownloaded -> {
|
||||
DownloadIconButton(onClick = { onClickDownload(chapter.chapter) })
|
||||
}
|
||||
@@ -172,6 +174,7 @@ private fun DownloadingIconButton(
|
||||
LocalContentColor.current.copy(alpha = ContentAlpha.disabled),
|
||||
2.dp,
|
||||
)
|
||||
|
||||
DownloadState.Downloading -> if (downloadChapter.progress != 0.0F) {
|
||||
val animatedProgress by animateFloatAsState(
|
||||
targetValue = downloadChapter.progress,
|
||||
@@ -202,6 +205,7 @@ private fun DownloadingIconButton(
|
||||
2.dp,
|
||||
)
|
||||
}
|
||||
|
||||
DownloadState.Error -> Surface(shape = CircleShape, color = LocalContentColor.current) {
|
||||
Icon(
|
||||
Icons.Rounded.Error,
|
||||
@@ -212,6 +216,7 @@ private fun DownloadingIconButton(
|
||||
Color.Red,
|
||||
)
|
||||
}
|
||||
|
||||
DownloadState.Finished -> Surface(shape = CircleShape, color = LocalContentColor.current) {
|
||||
Icon(
|
||||
Icons.Rounded.Check,
|
||||
|
||||
@@ -40,8 +40,8 @@ class ImageLoaderProvider
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
val serverUrl = serverPreferences.serverUrl().stateIn(GlobalScope)
|
||||
|
||||
fun get(imageCache: ImageCache): ImageLoader {
|
||||
return ImageLoader {
|
||||
fun get(imageCache: ImageCache): ImageLoader =
|
||||
ImageLoader {
|
||||
components {
|
||||
register(context, http)
|
||||
add(MokoResourceFetcher.Factory())
|
||||
@@ -60,7 +60,6 @@ class ImageLoaderProvider
|
||||
bitmapMemoryCacheConfig { configure(context) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class MangaCoverMapper : Mapper<Url> {
|
||||
override fun map(
|
||||
|
||||
@@ -103,6 +103,7 @@ fun ActionMenu(
|
||||
is ActionGroup -> {
|
||||
{ openGroup = item }
|
||||
}
|
||||
|
||||
is ActionItem -> item.doAction
|
||||
},
|
||||
enabled = item.enabled,
|
||||
@@ -158,6 +159,7 @@ fun ActionMenu(
|
||||
onClick = {
|
||||
when (item) {
|
||||
is ActionGroup -> openGroup = item
|
||||
|
||||
is ActionItem -> {
|
||||
openGroup = null
|
||||
item()
|
||||
@@ -200,9 +202,11 @@ private fun separateIntoIconAndOverflow(
|
||||
OverflowMode.NEVER_OVERFLOW -> {
|
||||
iconActions.add(item)
|
||||
}
|
||||
|
||||
OverflowMode.ALWAYS_OVERFLOW -> {
|
||||
overflowActions.add(item)
|
||||
}
|
||||
|
||||
OverflowMode.IF_NECESSARY -> {
|
||||
if (iconsAvailableBeforeOverflow > 0) {
|
||||
iconActions.add(item)
|
||||
@@ -211,6 +215,7 @@ private fun separateIntoIconAndOverflow(
|
||||
overflowActions.add(item)
|
||||
}
|
||||
}
|
||||
|
||||
OverflowMode.NOT_SHOWN -> {
|
||||
// skip
|
||||
}
|
||||
|
||||
@@ -208,10 +208,18 @@ private fun ColorPresetItem(
|
||||
private fun getColorShades(color: Color): ImmutableList<Color> {
|
||||
val f = color.toLong()
|
||||
return listOf(
|
||||
shadeColor(f, 0.9), shadeColor(f, 0.7), shadeColor(f, 0.5),
|
||||
shadeColor(f, 0.333), shadeColor(f, 0.166), shadeColor(f, -0.125),
|
||||
shadeColor(f, -0.25), shadeColor(f, -0.375), shadeColor(f, -0.5),
|
||||
shadeColor(f, -0.675), shadeColor(f, -0.7), shadeColor(f, -0.775),
|
||||
shadeColor(f, 0.9),
|
||||
shadeColor(f, 0.7),
|
||||
shadeColor(f, 0.5),
|
||||
shadeColor(f, 0.333),
|
||||
shadeColor(f, 0.166),
|
||||
shadeColor(f, -0.125),
|
||||
shadeColor(f, -0.25),
|
||||
shadeColor(f, -0.375),
|
||||
shadeColor(f, -0.5),
|
||||
shadeColor(f, -0.675),
|
||||
shadeColor(f, -0.7),
|
||||
shadeColor(f, -0.775),
|
||||
).toImmutableList()
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,7 @@ import kotlinx.coroutines.internal.synchronized
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
fun <T> SavedStateHandle.getStateFlow(initialValue: () -> T): SavedStateHandleDelegate<T> {
|
||||
return SavedStateHandleDelegate(this, initialValue)
|
||||
}
|
||||
fun <T> SavedStateHandle.getStateFlow(initialValue: () -> T): SavedStateHandleDelegate<T> = SavedStateHandleDelegate(this, initialValue)
|
||||
|
||||
@OptIn(InternalCoroutinesApi::class)
|
||||
class SavedStateHandleDelegate<T>(
|
||||
@@ -30,8 +28,8 @@ class SavedStateHandleDelegate<T>(
|
||||
override fun getValue(
|
||||
thisRef: ViewModel,
|
||||
property: KProperty<*>,
|
||||
): SavedStateHandleStateFlow<T> {
|
||||
return item ?: synchronized(synchronizedObject) {
|
||||
): SavedStateHandleStateFlow<T> =
|
||||
item ?: synchronized(synchronizedObject) {
|
||||
if (item == null) {
|
||||
savedStateHandle.getSavedStateFlow(property.name, initialValue)
|
||||
.also { item = it }
|
||||
@@ -40,7 +38,6 @@ class SavedStateHandleDelegate<T>(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SavedStateHandleStateFlow<T>(
|
||||
private val key: String,
|
||||
|
||||
@@ -107,10 +107,9 @@ class AppThemeViewModel
|
||||
fun getTheme(
|
||||
id: Int,
|
||||
isLight: Boolean,
|
||||
): Theme {
|
||||
return themes.find { it.id == id && it.colors.isLight == isLight }
|
||||
): Theme =
|
||||
themes.find { it.id == id && it.colors.isLight == isLight }
|
||||
?: themes.first { it.colors.isLight == isLight }
|
||||
}
|
||||
|
||||
return when (themeMode) {
|
||||
ThemeMode.System -> if (!isSystemInDarkTheme()) {
|
||||
@@ -118,7 +117,9 @@ class AppThemeViewModel
|
||||
} else {
|
||||
getTheme(darkTheme, false)
|
||||
}
|
||||
|
||||
ThemeMode.Light -> getTheme(lightTheme, true)
|
||||
|
||||
ThemeMode.Dark -> getTheme(darkTheme, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,6 +148,7 @@ fun ExtensionsScreenContent(
|
||||
modifier = Modifier.animateItemPlacement()
|
||||
.padding(16.dp, 16.dp, 16.dp, 4.dp),
|
||||
)
|
||||
|
||||
is ExtensionUI.ExtensionItem -> Column {
|
||||
ExtensionItem(
|
||||
Modifier.animateItemPlacement(),
|
||||
|
||||
@@ -111,6 +111,7 @@ private fun LibraryMap.setManga(
|
||||
val flow = getManga(id)
|
||||
when (val state = flow.value) {
|
||||
is CategoryState.Loaded -> state.unfilteredItems.value = manga
|
||||
|
||||
else -> {
|
||||
val unfilteredItems = MutableStateFlow(manga)
|
||||
flow.value = CategoryState.Loaded(getItemsFlow(unfilteredItems), unfilteredItems)
|
||||
@@ -160,11 +161,13 @@ class LibraryScreenViewModel
|
||||
FilterState.EXCLUDED -> manga.downloadCount == null || manga.downloadCount == 0
|
||||
FilterState.INCLUDED -> manga.downloadCount != null && (manga.downloadCount ?: 0) > 0
|
||||
FilterState.IGNORED -> true
|
||||
} && when (unread) {
|
||||
} &&
|
||||
when (unread) {
|
||||
FilterState.EXCLUDED -> manga.unreadCount == null || manga.unreadCount == 0
|
||||
FilterState.INCLUDED -> manga.unreadCount != null && (manga.unreadCount ?: 0) > 0
|
||||
FilterState.IGNORED -> true
|
||||
} && when (completed) {
|
||||
} &&
|
||||
when (completed) {
|
||||
FilterState.EXCLUDED -> manga.status != MangaStatus.COMPLETED
|
||||
FilterState.INCLUDED -> manga.status == MangaStatus.COMPLETED
|
||||
FilterState.IGNORED -> true
|
||||
@@ -238,17 +241,22 @@ class LibraryScreenViewModel
|
||||
collator.compare(a.title.toLowerCase(locale), b.title.toLowerCase(locale))
|
||||
}
|
||||
}
|
||||
|
||||
Sort.UNREAD -> {
|
||||
{ a, b ->
|
||||
when {
|
||||
// Ensure unread content comes first
|
||||
(a.unreadCount ?: 0) == (b.unreadCount ?: 0) -> 0
|
||||
|
||||
a.unreadCount == null || a.unreadCount == 0 -> if (ascending) 1 else -1
|
||||
|
||||
b.unreadCount == null || b.unreadCount == 0 -> if (ascending) -1 else 1
|
||||
|
||||
else -> (a.unreadCount ?: 0).compareTo(b.unreadCount ?: 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Sort.DATE_ADDED -> {
|
||||
{ a, b ->
|
||||
a.inLibraryAt.compareTo(b.inLibraryAt)
|
||||
|
||||
@@ -40,7 +40,9 @@ fun LibraryPager(
|
||||
HorizontalPager(state = pagerState) {
|
||||
when (val library = getLibraryForPage(categories[it].id).value) {
|
||||
CategoryState.Loading -> LoadingScreen()
|
||||
|
||||
is CategoryState.Failed -> ErrorScreen(library.e.message)
|
||||
|
||||
is CategoryState.Loaded -> LibraryLoadedPage(
|
||||
library = library,
|
||||
displayMode = displayMode,
|
||||
@@ -83,6 +85,7 @@ private fun LibraryLoadedPage(
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal,
|
||||
)
|
||||
|
||||
DisplayMode.ComfortableGrid -> LibraryMangaComfortableGrid(
|
||||
library = items,
|
||||
gridColumns = gridColumns,
|
||||
@@ -94,6 +97,7 @@ private fun LibraryLoadedPage(
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal,
|
||||
)
|
||||
|
||||
DisplayMode.CoverOnlyGrid -> LibraryMangaCoverOnlyGrid(
|
||||
library = items,
|
||||
gridColumns = gridColumns,
|
||||
@@ -105,6 +109,7 @@ private fun LibraryLoadedPage(
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal,
|
||||
)
|
||||
|
||||
DisplayMode.List -> LibraryMangaList(
|
||||
library = items,
|
||||
onClickManga = onClickManga,
|
||||
@@ -114,6 +119,7 @@ private fun LibraryLoadedPage(
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal,
|
||||
)
|
||||
|
||||
else -> Box {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,9 +220,11 @@ fun WideLibraryScreenContent(
|
||||
is LibraryState.Failed -> {
|
||||
ErrorScreen(libraryState.e.message)
|
||||
}
|
||||
|
||||
LibraryState.Loading -> {
|
||||
LoadingScreen(true)
|
||||
}
|
||||
|
||||
is LibraryState.Loaded -> {
|
||||
LibraryPager(
|
||||
pagerState = pagerState,
|
||||
@@ -296,6 +298,7 @@ fun ThinLibraryScreenContent(
|
||||
confirmValueChange = {
|
||||
when (it) {
|
||||
ModalBottomSheetValue.Hidden -> setShowingSheet(false)
|
||||
|
||||
ModalBottomSheetValue.Expanded,
|
||||
ModalBottomSheetValue.HalfExpanded,
|
||||
-> setShowingSheet(true)
|
||||
@@ -359,9 +362,11 @@ fun ThinLibraryScreenContent(
|
||||
LibraryState.Loading -> {
|
||||
LoadingScreen(true)
|
||||
}
|
||||
|
||||
is LibraryState.Failed -> {
|
||||
ErrorScreen(libraryState.e.message)
|
||||
}
|
||||
|
||||
is LibraryState.Loaded -> {
|
||||
LibraryPager(
|
||||
pagerState = pagerState,
|
||||
|
||||
@@ -265,6 +265,7 @@ private fun LinkDisplay() {
|
||||
contentDescription = name,
|
||||
modifier = modifier,
|
||||
)
|
||||
|
||||
is LinkIcon.Icon -> Icon(
|
||||
imageVector = it.icon.icon,
|
||||
contentDescription = name,
|
||||
@@ -288,6 +289,7 @@ private fun LinkDisplay() {
|
||||
contentDescription = name,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
|
||||
is LinkIcon.Icon -> Icon(
|
||||
imageVector = it.icon.icon,
|
||||
contentDescription = name,
|
||||
|
||||
@@ -39,6 +39,7 @@ fun DownloadsExtraInfo() {
|
||||
val list by vm.downloadQueue.collectAsState()
|
||||
val text = when (serviceStatus) {
|
||||
WebsocketService.Status.STARTING -> stringResource(MR.strings.downloads_loading)
|
||||
|
||||
WebsocketService.Status.RUNNING -> {
|
||||
if (list.isNotEmpty()) {
|
||||
val remainingDownloads = stringResource(MR.strings.downloads_remaining, list.size)
|
||||
@@ -51,6 +52,7 @@ fun DownloadsExtraInfo() {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
WebsocketService.Status.STOPPED -> null
|
||||
}
|
||||
if (!text.isNullOrBlank()) {
|
||||
|
||||
@@ -55,6 +55,7 @@ fun LibraryUpdatesExtraInfo() {
|
||||
|
||||
val text = when (serviceStatus) {
|
||||
WebsocketService.Status.STARTING -> stringResource(MR.strings.downloads_loading)
|
||||
|
||||
WebsocketService.Status.RUNNING -> {
|
||||
if (updateStatus.running) {
|
||||
stringResource(MR.strings.notification_updating, current, total)
|
||||
@@ -62,6 +63,7 @@ fun LibraryUpdatesExtraInfo() {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
WebsocketService.Status.STOPPED -> null
|
||||
}
|
||||
if (!text.isNullOrBlank()) {
|
||||
|
||||
@@ -615,6 +615,7 @@ fun ChapterSeparator(
|
||||
previousChapter == null && nextChapter != null -> {
|
||||
Text(stringResource(MR.strings.no_previous_chapter))
|
||||
}
|
||||
|
||||
previousChapter != null && nextChapter != null -> {
|
||||
val prevChapter by previousChapter.stateObserver.collectAsState()
|
||||
when (prevChapter) {
|
||||
@@ -624,6 +625,7 @@ fun ChapterSeparator(
|
||||
}
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
Text(stringResource(MR.strings.previous_chapter, previousChapter.chapter.name))
|
||||
@@ -637,9 +639,11 @@ fun ChapterSeparator(
|
||||
}
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
previousChapter != null && nextChapter == null -> {
|
||||
Text(stringResource(MR.strings.no_next_chapter))
|
||||
}
|
||||
|
||||
@@ -208,20 +208,26 @@ class ReaderMenuViewModel
|
||||
setReaderSettingsMenuOpen(!readerSettingsMenuOpen.value)
|
||||
null
|
||||
}
|
||||
|
||||
Navigation.NEXT -> MoveTo.Next
|
||||
|
||||
Navigation.PREV -> MoveTo.Previous
|
||||
|
||||
Navigation.RIGHT -> when (readerModeSettings.direction.value) {
|
||||
Direction.Left -> MoveTo.Previous
|
||||
else -> MoveTo.Next
|
||||
}
|
||||
|
||||
Navigation.LEFT -> when (readerModeSettings.direction.value) {
|
||||
Direction.Left -> MoveTo.Next
|
||||
else -> MoveTo.Previous
|
||||
}
|
||||
|
||||
Navigation.DOWN -> when (readerModeSettings.direction.value) {
|
||||
Direction.Up -> MoveTo.Previous
|
||||
else -> MoveTo.Next
|
||||
}
|
||||
|
||||
Navigation.UP -> when (readerModeSettings.direction.value) {
|
||||
Direction.Up -> MoveTo.Next
|
||||
else -> MoveTo.Previous
|
||||
|
||||
@@ -154,8 +154,8 @@ class TachideskPageLoader(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getImageFromCache(page: ReaderPage): ReaderPage.ImageDecodeState {
|
||||
return chapterCache.openSnapshot(page.cacheKey)?.use {
|
||||
private suspend fun getImageFromCache(page: ReaderPage): ReaderPage.ImageDecodeState =
|
||||
chapterCache.openSnapshot(page.cacheKey)?.use {
|
||||
it.source().use { source ->
|
||||
val decoder = bitmapDecoderFactory.create(
|
||||
ImageResult.OfSource(
|
||||
@@ -183,7 +183,6 @@ class TachideskPageLoader(
|
||||
}
|
||||
}
|
||||
} ?: ReaderPage.ImageDecodeState.FailedToGetSnapShot
|
||||
}
|
||||
|
||||
/**
|
||||
* Preloads the given [amount] of pages after the [currentPage] with a lower priority.
|
||||
|
||||
@@ -86,6 +86,7 @@ fun ContinuousReader(
|
||||
)
|
||||
Unit
|
||||
}
|
||||
|
||||
is PageMove.Page -> {
|
||||
val pageNumber = pages.indexOf(pageMove.page)
|
||||
if (pageNumber > -1) {
|
||||
@@ -155,6 +156,7 @@ fun ContinuousReader(
|
||||
reverseLayout = direction == Direction.Up,
|
||||
)
|
||||
}
|
||||
|
||||
false -> {
|
||||
LazyRow(
|
||||
state = state,
|
||||
@@ -217,6 +219,7 @@ private fun LazyListScope.items(
|
||||
retry = retry,
|
||||
)
|
||||
}
|
||||
|
||||
is ReaderPageSeparator -> ChapterSeparator(
|
||||
previousChapter = image.previousChapter,
|
||||
nextChapter = image.nextChapter,
|
||||
|
||||
@@ -63,6 +63,7 @@ fun PagerReader(
|
||||
state.animateScrollToPage(page)
|
||||
}
|
||||
}
|
||||
|
||||
is PageMove.Page -> {
|
||||
val pageNumber = pages.indexOf(pageMove.page)
|
||||
if (pageNumber > -1) {
|
||||
@@ -158,6 +159,7 @@ fun HandlePager(
|
||||
contentScale = pageContentScale,
|
||||
)
|
||||
}
|
||||
|
||||
is ReaderPageSeparator -> ChapterSeparator(
|
||||
previousChapter = image.previousChapter,
|
||||
nextChapter = image.nextChapter,
|
||||
|
||||
@@ -434,11 +434,13 @@ private fun PreferenceFile(
|
||||
modifier = modifier,
|
||||
tint = Color.Red,
|
||||
)
|
||||
|
||||
Status.Success -> Icon(
|
||||
Icons.Rounded.Check,
|
||||
contentDescription = null,
|
||||
modifier = modifier,
|
||||
)
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,6 +210,7 @@ fun SettingsServerScreenContent(
|
||||
}
|
||||
when (proxyValue) {
|
||||
Proxy.NO_PROXY -> Unit
|
||||
|
||||
Proxy.HTTP_PROXY -> {
|
||||
item {
|
||||
EditTextPreference(
|
||||
@@ -226,6 +227,7 @@ fun SettingsServerScreenContent(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Proxy.SOCKS_PROXY -> {
|
||||
item {
|
||||
EditTextPreference(
|
||||
|
||||
@@ -119,6 +119,7 @@ class SourceScreenViewModel(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
isLatest.value -> {
|
||||
{ page ->
|
||||
getLatestManga.await(
|
||||
@@ -128,6 +129,7 @@ class SourceScreenViewModel(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
{ page ->
|
||||
getPopularManga.await(
|
||||
|
||||
@@ -285,6 +285,7 @@ private fun SourceThinScreenContent(
|
||||
confirmValueChange = {
|
||||
when (it) {
|
||||
ModalBottomSheetValue.Hidden -> setShowingFilters(false)
|
||||
|
||||
ModalBottomSheetValue.Expanded,
|
||||
ModalBottomSheetValue.HalfExpanded,
|
||||
-> setShowingFilters(true)
|
||||
@@ -492,6 +493,7 @@ private fun MangaTable(
|
||||
hasNextPage = hasNextPage,
|
||||
onLoadNextPage = onLoadNextPage,
|
||||
)
|
||||
|
||||
DisplayMode.ComfortableGrid -> SourceMangaComfortableGrid(
|
||||
mangas = mangas,
|
||||
gridColumns = gridColumns,
|
||||
@@ -500,12 +502,14 @@ private fun MangaTable(
|
||||
hasNextPage = hasNextPage,
|
||||
onLoadNextPage = onLoadNextPage,
|
||||
)
|
||||
|
||||
DisplayMode.List -> SourceMangaList(
|
||||
mangas = mangas,
|
||||
onClickManga = onMangaClick,
|
||||
hasNextPage = hasNextPage,
|
||||
onLoadNextPage = onLoadNextPage,
|
||||
)
|
||||
|
||||
else -> Box {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,11 +155,13 @@ fun SourcesSideMenu(
|
||||
contentDescription = stringResource(MR.strings.sources_home),
|
||||
modifier = modifier,
|
||||
)
|
||||
|
||||
SourceNavigatorScreen.SearchScreen -> Icon(
|
||||
imageVector = Icons.Rounded.Search,
|
||||
contentDescription = stringResource(MR.strings.location_global_search),
|
||||
modifier = modifier,
|
||||
)
|
||||
|
||||
is SourceNavigatorScreen.SourceScreen -> Box(Modifier.align(Alignment.Center)) {
|
||||
ImageLoaderImage(
|
||||
data = screen.source,
|
||||
|
||||
@@ -196,12 +196,14 @@ fun GlobalSearchItem(
|
||||
) {
|
||||
ErrorScreen(search.e)
|
||||
}
|
||||
|
||||
Search.Searching -> Box(
|
||||
Modifier.fillMaxWidth().padding(vertical = 8.dp, horizontal = 16.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
|
||||
is Search.Success -> Box(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
|
||||
@@ -185,6 +185,7 @@ fun WideSourcesMenu(
|
||||
sourceUI.header,
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||
)
|
||||
|
||||
is SourceUI.SourceItem -> WideSourceItem(
|
||||
sourceUI,
|
||||
onSourceClicked = onAddSource,
|
||||
@@ -285,6 +286,7 @@ fun ThinSourcesMenu(
|
||||
sourceUI.header,
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||
)
|
||||
|
||||
is SourceUI.SourceItem -> ThinSourceItem(
|
||||
sourceUI,
|
||||
onSourceClicked = onAddSource,
|
||||
|
||||
@@ -87,12 +87,15 @@ fun SourceSettingsScreenContent(settings: ImmutableList<SourceSettingsView<*, *>
|
||||
is CheckBox, is Switch -> {
|
||||
TwoStatePreference(it as TwoState, it is CheckBox)
|
||||
}
|
||||
|
||||
is List -> {
|
||||
ListPreference(it)
|
||||
}
|
||||
|
||||
is EditText -> {
|
||||
EditTextPreference(it)
|
||||
}
|
||||
|
||||
is MultiSelect -> {
|
||||
MultiSelectPreference(it)
|
||||
}
|
||||
|
||||
@@ -184,6 +184,7 @@ fun UpdatesScreenContent(
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
|
||||
fontWeight = FontWeight.Medium,
|
||||
)
|
||||
|
||||
is UpdatesUI.Item -> {
|
||||
val manga = item.chapterDownloadItem.manga!!
|
||||
val chapter = item.chapterDownloadItem.chapter
|
||||
|
||||
@@ -21,11 +21,17 @@ actual fun stringFormat(
|
||||
@Suppress("MagicNumber")
|
||||
return when (args.size) {
|
||||
0 -> NSString.stringWithFormat(objcFormat)
|
||||
|
||||
1 -> NSString.stringWithFormat(objcFormat, args[0])
|
||||
|
||||
2 -> NSString.stringWithFormat(objcFormat, args[0], args[1])
|
||||
|
||||
3 -> NSString.stringWithFormat(objcFormat, args[0], args[1], args[2])
|
||||
|
||||
4 -> NSString.stringWithFormat(objcFormat, args[0], args[1], args[2], args[3])
|
||||
|
||||
5 -> NSString.stringWithFormat(objcFormat, args[0], args[1], args[2], args[3], args[4])
|
||||
|
||||
6 -> NSString.stringWithFormat(
|
||||
objcFormat,
|
||||
args[0],
|
||||
@@ -35,6 +41,7 @@ actual fun stringFormat(
|
||||
args[4],
|
||||
args[5],
|
||||
)
|
||||
|
||||
7 -> NSString.stringWithFormat(
|
||||
objcFormat,
|
||||
args[0],
|
||||
@@ -45,6 +52,7 @@ actual fun stringFormat(
|
||||
args[5],
|
||||
args[6],
|
||||
)
|
||||
|
||||
8 -> NSString.stringWithFormat(
|
||||
objcFormat,
|
||||
args[0],
|
||||
@@ -56,6 +64,7 @@ actual fun stringFormat(
|
||||
args[6],
|
||||
args[7],
|
||||
)
|
||||
|
||||
9 -> NSString.stringWithFormat(
|
||||
objcFormat,
|
||||
args[0],
|
||||
@@ -68,6 +77,7 @@ actual fun stringFormat(
|
||||
args[7],
|
||||
args[8],
|
||||
)
|
||||
|
||||
else -> throw IllegalArgumentException("can't handle more then 9 arguments now")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,12 +82,15 @@ internal actual fun RealVerticalScrollbar(
|
||||
is ScrollStateScrollbarAdapter -> {
|
||||
Modifier.drawScrollbar(adapter.scrollState, Orientation.Vertical, reverseLayout)
|
||||
}
|
||||
|
||||
is LazyListStateScrollbarAdapter -> {
|
||||
Modifier.drawScrollbar(adapter.lazyListState, Orientation.Vertical, reverseLayout)
|
||||
}
|
||||
|
||||
is LazyGridStateScrollbarAdapter -> {
|
||||
Modifier.drawScrollbar(adapter.lazyGridState, adapter.gridCells, adapter.spacing, Orientation.Vertical, reverseLayout)
|
||||
}
|
||||
|
||||
else -> Modifier
|
||||
}
|
||||
Box(modifier then Modifier.fillMaxSize() then scrollbarModifier)
|
||||
@@ -105,49 +108,47 @@ internal actual fun RealHorizontalScrollbar(
|
||||
is ScrollStateScrollbarAdapter -> {
|
||||
Modifier.drawScrollbar(adapter.scrollState, Orientation.Horizontal, reverseLayout)
|
||||
}
|
||||
|
||||
is LazyListStateScrollbarAdapter -> {
|
||||
Modifier.drawScrollbar(adapter.lazyListState, Orientation.Horizontal, reverseLayout)
|
||||
}
|
||||
|
||||
else -> Modifier
|
||||
}
|
||||
Box(modifier then Modifier.fillMaxSize() then scrollbarModifier)
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun rememberScrollbarAdapter(scrollState: ScrollState): ScrollbarAdapter {
|
||||
return remember(scrollState) {
|
||||
actual fun rememberScrollbarAdapter(scrollState: ScrollState): ScrollbarAdapter =
|
||||
remember(scrollState) {
|
||||
ScrollStateScrollbarAdapter(scrollState)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun rememberScrollbarAdapter(scrollState: LazyListState): ScrollbarAdapter {
|
||||
return remember(scrollState) {
|
||||
actual fun rememberScrollbarAdapter(scrollState: LazyListState): ScrollbarAdapter =
|
||||
remember(scrollState) {
|
||||
LazyListStateScrollbarAdapter(scrollState)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal actual fun realRememberVerticalScrollbarAdapter(
|
||||
scrollState: LazyGridState,
|
||||
gridCells: GridCells,
|
||||
arrangement: Arrangement.Vertical?,
|
||||
): ScrollbarAdapter {
|
||||
return remember(scrollState, gridCells) {
|
||||
): ScrollbarAdapter =
|
||||
remember(scrollState, gridCells) {
|
||||
LazyGridStateScrollbarAdapter(scrollState, gridCells, arrangement?.spacing ?: Dp.Hairline)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal actual fun realRememberHorizontalScrollbarAdapter(
|
||||
scrollState: LazyGridState,
|
||||
gridCells: GridCells,
|
||||
arrangement: Arrangement.Horizontal?,
|
||||
): ScrollbarAdapter {
|
||||
return remember(scrollState, gridCells) {
|
||||
): ScrollbarAdapter =
|
||||
remember(scrollState, gridCells) {
|
||||
LazyGridStateScrollbarAdapter(scrollState, gridCells, arrangement?.spacing ?: Dp.Hairline)
|
||||
}
|
||||
}
|
||||
|
||||
actual fun Modifier.scrollbarPadding() = this
|
||||
|
||||
|
||||
@@ -98,14 +98,17 @@ fun ImageLoaderImage(
|
||||
error.value = action.error
|
||||
ImageLoaderImageState.Failure
|
||||
}
|
||||
|
||||
is ImageAction.Loading -> {
|
||||
progress.value = 0.0F
|
||||
ImageLoaderImageState.Loading
|
||||
}
|
||||
|
||||
is ImageAction.Success -> {
|
||||
progress.value = 1.0F
|
||||
ImageLoaderImageState.Success
|
||||
}
|
||||
|
||||
else -> {
|
||||
ImageLoaderImageState.Loading
|
||||
}
|
||||
@@ -117,6 +120,7 @@ fun ImageLoaderImage(
|
||||
ImageLoaderImageState.Loading -> if (onLoading != null) {
|
||||
onLoading(progress.value)
|
||||
}
|
||||
|
||||
ImageLoaderImageState.Success -> Image(
|
||||
painter = rememberImageActionPainter(
|
||||
imageAction,
|
||||
@@ -129,6 +133,7 @@ fun ImageLoaderImage(
|
||||
alpha = alpha,
|
||||
colorFilter = colorFilter,
|
||||
)
|
||||
|
||||
ImageLoaderImageState.Failure -> {
|
||||
if (onFailure != null) {
|
||||
onFailure(error.value ?: return@Crossfade)
|
||||
|
||||
@@ -300,9 +300,7 @@ private fun lazyListSnapLayoutInfoProvider(
|
||||
lowerBound: Float,
|
||||
upperBound: Float,
|
||||
): Float {
|
||||
fun Float.isValidDistance(): Boolean {
|
||||
return this != Float.POSITIVE_INFINITY && this != Float.NEGATIVE_INFINITY
|
||||
}
|
||||
fun Float.isValidDistance(): Boolean = this != Float.POSITIVE_INFINITY && this != Float.NEGATIVE_INFINITY
|
||||
|
||||
val finalDistance = when (sign(velocity)) {
|
||||
0f -> {
|
||||
@@ -314,7 +312,9 @@ private fun lazyListSnapLayoutInfoProvider(
|
||||
}
|
||||
|
||||
1f -> upperBound
|
||||
|
||||
-1f -> lowerBound
|
||||
|
||||
else -> 0f
|
||||
}
|
||||
|
||||
|
||||
@@ -81,12 +81,15 @@ internal actual fun RealVerticalScrollbar(
|
||||
is ScrollStateScrollbarAdapter -> {
|
||||
Modifier.drawScrollbar(adapter.scrollState, Orientation.Vertical, reverseLayout)
|
||||
}
|
||||
|
||||
is LazyListStateScrollbarAdapter -> {
|
||||
Modifier.drawScrollbar(adapter.lazyListState, Orientation.Vertical, reverseLayout)
|
||||
}
|
||||
|
||||
is LazyGridStateScrollbarAdapter -> {
|
||||
Modifier.drawScrollbar(adapter.lazyGridState, adapter.gridCells, adapter.spacing, Orientation.Vertical, reverseLayout)
|
||||
}
|
||||
|
||||
else -> Modifier
|
||||
}
|
||||
Box(modifier then Modifier.fillMaxSize() then scrollbarModifier)
|
||||
@@ -104,49 +107,47 @@ internal actual fun RealHorizontalScrollbar(
|
||||
is ScrollStateScrollbarAdapter -> {
|
||||
Modifier.drawScrollbar(adapter.scrollState, Orientation.Horizontal, reverseLayout)
|
||||
}
|
||||
|
||||
is LazyListStateScrollbarAdapter -> {
|
||||
Modifier.drawScrollbar(adapter.lazyListState, Orientation.Horizontal, reverseLayout)
|
||||
}
|
||||
|
||||
else -> Modifier
|
||||
}
|
||||
Box(modifier then Modifier.fillMaxSize() then scrollbarModifier)
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun rememberScrollbarAdapter(scrollState: ScrollState): ScrollbarAdapter {
|
||||
return remember(scrollState) {
|
||||
actual fun rememberScrollbarAdapter(scrollState: ScrollState): ScrollbarAdapter =
|
||||
remember(scrollState) {
|
||||
ScrollStateScrollbarAdapter(scrollState)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun rememberScrollbarAdapter(scrollState: LazyListState): ScrollbarAdapter {
|
||||
return remember(scrollState) {
|
||||
actual fun rememberScrollbarAdapter(scrollState: LazyListState): ScrollbarAdapter =
|
||||
remember(scrollState) {
|
||||
LazyListStateScrollbarAdapter(scrollState)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal actual fun realRememberVerticalScrollbarAdapter(
|
||||
scrollState: LazyGridState,
|
||||
gridCells: GridCells,
|
||||
arrangement: Arrangement.Vertical?,
|
||||
): ScrollbarAdapter {
|
||||
return remember(scrollState, gridCells) {
|
||||
): ScrollbarAdapter =
|
||||
remember(scrollState, gridCells) {
|
||||
LazyGridStateScrollbarAdapter(scrollState, gridCells, arrangement?.spacing ?: Dp.Hairline)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal actual fun realRememberHorizontalScrollbarAdapter(
|
||||
scrollState: LazyGridState,
|
||||
gridCells: GridCells,
|
||||
arrangement: Arrangement.Horizontal?,
|
||||
): ScrollbarAdapter {
|
||||
return remember(scrollState, gridCells) {
|
||||
): ScrollbarAdapter =
|
||||
remember(scrollState, gridCells) {
|
||||
LazyGridStateScrollbarAdapter(scrollState, gridCells, arrangement?.spacing ?: Dp.Hairline)
|
||||
}
|
||||
}
|
||||
|
||||
actual fun Modifier.scrollbarPadding() = this
|
||||
|
||||
|
||||
@@ -36,10 +36,9 @@ import platform.CoreGraphics.CGImageGetWidth
|
||||
import platform.UIKit.UIImage
|
||||
|
||||
@Composable
|
||||
actual fun ImageResource.toPainter(): Painter {
|
||||
return remember { toUIImage()?.toSkiaImage()?.toComposeImageBitmap()?.let(::BitmapPainter) }
|
||||
actual fun ImageResource.toPainter(): Painter =
|
||||
remember { toUIImage()?.toSkiaImage()?.toComposeImageBitmap()?.let(::BitmapPainter) }
|
||||
?: rememberVectorPainter(Icons.Rounded.BrokenImage)
|
||||
}
|
||||
|
||||
// Taken from https://github.com/touchlab/DroidconKotlin/blob/main/shared-ui/src/iosMain/kotlin/co/touchlab/droidcon/ui/util/ToSkiaImage.kt
|
||||
// TODO: Add support for remaining color spaces when the Skia library supports them.
|
||||
@@ -60,13 +59,16 @@ private fun UIImage.toSkiaImage(): Image? {
|
||||
CGImageAlphaInfo.kCGImageAlphaPremultipliedFirst,
|
||||
CGImageAlphaInfo.kCGImageAlphaPremultipliedLast,
|
||||
-> ColorAlphaType.PREMUL
|
||||
|
||||
CGImageAlphaInfo.kCGImageAlphaFirst,
|
||||
CGImageAlphaInfo.kCGImageAlphaLast,
|
||||
-> ColorAlphaType.UNPREMUL
|
||||
|
||||
CGImageAlphaInfo.kCGImageAlphaNone,
|
||||
CGImageAlphaInfo.kCGImageAlphaNoneSkipFirst,
|
||||
CGImageAlphaInfo.kCGImageAlphaNoneSkipLast,
|
||||
-> ColorAlphaType.OPAQUE
|
||||
|
||||
else -> ColorAlphaType.UNKNOWN
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user