mirror of
https://github.com/Suwayomi/TachideskJUI.git
synced 2025-12-10 06:42:05 +01:00
Start working on moving classes to a shared Jvm module
This commit is contained in:
@@ -11,4 +11,5 @@ object Config {
|
||||
const val previewCommit = "b714abddae9f13e91bc53c5daac54aeae564cd2a"
|
||||
|
||||
val desktopJvmTarget = JavaVersion.VERSION_16
|
||||
val androidJvmTarget = JavaVersion.VERSION_11
|
||||
}
|
||||
@@ -14,7 +14,13 @@ repositories {
|
||||
}
|
||||
|
||||
kotlin {
|
||||
android()
|
||||
android {
|
||||
compilations {
|
||||
all {
|
||||
kotlinOptions.jvmTarget = Config.androidJvmTarget.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
jvm("desktop") {
|
||||
compilations {
|
||||
all {
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.core.prefs
|
||||
|
||||
import com.russhwolf.settings.ObservableSettings
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
internal class AndroidPreference<T>(
|
||||
private val preferences: ObservableSettings,
|
||||
private val key: String,
|
||||
private val defaultValue: T,
|
||||
private val adapter: Adapter<T>
|
||||
) : Preference<T> {
|
||||
|
||||
interface Adapter<T> {
|
||||
fun get(key: String, preferences: ObservableSettings): T
|
||||
|
||||
fun set(key: String, value: T, editor: ObservableSettings)
|
||||
|
||||
fun isSet(keys: Set<String>, key: String): Boolean = key in keys
|
||||
|
||||
fun keyListener(key: String) = key
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key of this preference.
|
||||
*/
|
||||
override fun key(): String {
|
||||
return key
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current value of this preference.
|
||||
*/
|
||||
override fun get(): T {
|
||||
return if (isSet()) {
|
||||
adapter.get(key, preferences)
|
||||
} else {
|
||||
defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new [value] for this preference.
|
||||
*/
|
||||
override fun set(value: T) {
|
||||
adapter.set(key, value, preferences)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there's an existing entry for this preference.
|
||||
*/
|
||||
override fun isSet(): Boolean {
|
||||
return adapter.isSet(preferences.keys, key)
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the entry of this preference.
|
||||
*/
|
||||
override fun delete() {
|
||||
preferences.remove(key)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default value of this preference
|
||||
*/
|
||||
override fun defaultValue(): T {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cold [Flow] of this preference to receive updates when its value changes.
|
||||
*/
|
||||
override fun changes(): Flow<T> {
|
||||
return callbackFlow {
|
||||
val listener = preferences.addListener(adapter.keyListener(key)) {
|
||||
trySend(get())
|
||||
}
|
||||
awaitClose { listener.deactivate() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hot [StateFlow] of this preference bound to the given [scope], allowing to read the
|
||||
* current value and receive preference updates.
|
||||
*/
|
||||
override fun stateIn(scope: CoroutineScope): StateFlow<T> {
|
||||
return changes().stateIn(scope, SharingStarted.Eagerly, get())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.core.prefs
|
||||
|
||||
import com.russhwolf.settings.ObservableSettings
|
||||
import com.russhwolf.settings.serialization.decodeValue
|
||||
import com.russhwolf.settings.serialization.encodeValue
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.SetSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.modules.EmptySerializersModule
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
|
||||
internal object StringAdapter : AndroidPreference.Adapter<String> {
|
||||
override fun get(key: String, preferences: ObservableSettings): String {
|
||||
return preferences.getString(key) // Not called unless key is present.
|
||||
}
|
||||
|
||||
override fun set(key: String, value: String, editor: ObservableSettings) {
|
||||
editor.putString(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
internal object LongAdapter : AndroidPreference.Adapter<Long> {
|
||||
override fun get(key: String, preferences: ObservableSettings): Long {
|
||||
return preferences.getLong(key, 0)
|
||||
}
|
||||
|
||||
override fun set(key: String, value: Long, editor: ObservableSettings) {
|
||||
editor.putLong(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
internal object IntAdapter : AndroidPreference.Adapter<Int> {
|
||||
override fun get(key: String, preferences: ObservableSettings): Int {
|
||||
return preferences.getInt(key, 0)
|
||||
}
|
||||
|
||||
override fun set(key: String, value: Int, editor: ObservableSettings) {
|
||||
editor.putInt(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
internal object FloatAdapter : AndroidPreference.Adapter<Float> {
|
||||
override fun get(key: String, preferences: ObservableSettings): Float {
|
||||
return preferences.getFloat(key, 0f)
|
||||
}
|
||||
|
||||
override fun set(key: String, value: Float, editor: ObservableSettings) {
|
||||
editor.putFloat(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
internal object BooleanAdapter : AndroidPreference.Adapter<Boolean> {
|
||||
override fun get(key: String, preferences: ObservableSettings): Boolean {
|
||||
return preferences.getBoolean(key, false)
|
||||
}
|
||||
|
||||
override fun set(key: String, value: Boolean, editor: ObservableSettings) {
|
||||
editor.putBoolean(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
internal object StringSetAdapter : AndroidPreference.Adapter<Set<String>> {
|
||||
override fun get(key: String, preferences: ObservableSettings): Set<String> {
|
||||
return preferences.decodeValue(SetSerializer(String.serializer()), key, emptySet()) // Not called unless key is present.
|
||||
}
|
||||
|
||||
override fun set(key: String, value: Set<String>, editor: ObservableSettings) {
|
||||
editor.encodeValue(SetSerializer(String.serializer()), key, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoding a string set makes a list of keys and a size key, such as key.size and key.0-size
|
||||
*/
|
||||
override fun isSet(keys: Set<String>, key: String): Boolean {
|
||||
return keys.contains("$key.size")
|
||||
}
|
||||
|
||||
/**
|
||||
* Watching the regular key doesnt produce updates for a string set for some reason
|
||||
* TODO make better, doesnt produce updates when you add something and remove something
|
||||
*/
|
||||
override fun keyListener(key: String): String {
|
||||
return "$key.size"
|
||||
}
|
||||
}
|
||||
|
||||
internal class ObjectAdapter<T>(
|
||||
private val serializer: (T) -> String,
|
||||
private val deserializer: (String) -> T
|
||||
) : AndroidPreference.Adapter<T> {
|
||||
|
||||
override fun get(key: String, preferences: ObservableSettings): T {
|
||||
return deserializer(preferences.getString(key)) // Not called unless key is present.
|
||||
}
|
||||
|
||||
override fun set(key: String, value: T, editor: ObservableSettings) {
|
||||
editor.putString(key, serializer(value))
|
||||
}
|
||||
}
|
||||
|
||||
internal class JsonObjectAdapter<T>(
|
||||
private val defaultValue: T,
|
||||
private val serializer: KSerializer<T>,
|
||||
private val serializersModule: SerializersModule = EmptySerializersModule
|
||||
) : AndroidPreference.Adapter<T> {
|
||||
|
||||
override fun get(key: String, preferences: ObservableSettings): T {
|
||||
return preferences.decodeValue(serializer, key, defaultValue, serializersModule) // Not called unless key is present.
|
||||
}
|
||||
|
||||
override fun set(key: String, value: T, editor: ObservableSettings) {
|
||||
editor.encodeValue(serializer, key, value, serializersModule)
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoding a structure makes keys start with the [key] and adds extensions for values,
|
||||
* for a pair it would be like [key].first [key].second.
|
||||
*/
|
||||
override fun isSet(keys: Set<String>, key: String): Boolean {
|
||||
return keys.any { it.startsWith(key) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.core.prefs
|
||||
|
||||
import com.russhwolf.settings.ObservableSettings
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
|
||||
class AndroidPreferenceStore(private val preferences: ObservableSettings) : PreferenceStore {
|
||||
|
||||
/**
|
||||
* Returns an [String] preference for this [key].
|
||||
*/
|
||||
override fun getString(key: String, defaultValue: String): Preference<String> {
|
||||
return AndroidPreference(preferences, key, defaultValue, StringAdapter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Long] preference for this [key].
|
||||
*/
|
||||
override fun getLong(key: String, defaultValue: Long): Preference<Long> {
|
||||
return AndroidPreference(preferences, key, defaultValue, LongAdapter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an [Int] preference for this [key].
|
||||
*/
|
||||
override fun getInt(key: String, defaultValue: Int): Preference<Int> {
|
||||
return AndroidPreference(preferences, key, defaultValue, IntAdapter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Float] preference for this [key].
|
||||
*/
|
||||
override fun getFloat(key: String, defaultValue: Float): Preference<Float> {
|
||||
return AndroidPreference(preferences, key, defaultValue, FloatAdapter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Boolean] preference for this [key].
|
||||
*/
|
||||
override fun getBoolean(key: String, defaultValue: Boolean): Preference<Boolean> {
|
||||
return AndroidPreference(preferences, key, defaultValue, BooleanAdapter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Set<String>] preference for this [key].
|
||||
*/
|
||||
override fun getStringSet(key: String, defaultValue: Set<String>): Preference<Set<String>> {
|
||||
return AndroidPreference(preferences, key, defaultValue, StringSetAdapter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns preference of type [T] for this [key]. The [serializer] and [deserializer] function
|
||||
* must be provided.
|
||||
*/
|
||||
override fun <T> getObject(
|
||||
key: String,
|
||||
defaultValue: T,
|
||||
serializer: (T) -> String,
|
||||
deserializer: (String) -> T
|
||||
): Preference<T> {
|
||||
val adapter = ObjectAdapter(serializer, deserializer)
|
||||
return AndroidPreference(preferences, key, defaultValue, adapter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns preference of type [T] for this [key]. The [serializer] must be provided.
|
||||
*/
|
||||
override fun <T> getJsonObject(
|
||||
key: String,
|
||||
defaultValue: T,
|
||||
serializer: KSerializer<T>,
|
||||
serializersModule: SerializersModule
|
||||
): Preference<T> {
|
||||
val adapter = JsonObjectAdapter(defaultValue, serializer, serializersModule)
|
||||
return AndroidPreference(preferences, key, defaultValue, adapter)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.core.prefs
|
||||
|
||||
import android.content.Context
|
||||
import com.russhwolf.settings.AndroidSettings
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
|
||||
actual class PreferenceStoreFactory @Inject constructor(private val context: Context) {
|
||||
actual fun create(vararg names: String): PreferenceStore {
|
||||
return AndroidPreferenceStore(
|
||||
AndroidSettings(
|
||||
context.getSharedPreferences(names.joinToString(separator = "/"), Context.MODE_PRIVATE)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,10 @@
|
||||
package ca.gosyer.core.prefs
|
||||
|
||||
import com.russhwolf.settings.JvmPreferencesSettings
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import java.util.prefs.Preferences
|
||||
|
||||
actual class PreferenceStoreFactory {
|
||||
actual class PreferenceStoreFactory @Inject constructor() {
|
||||
private val rootNode: Preferences = Preferences.userRoot()
|
||||
.node("ca/gosyer/tachideskjui")
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.core.io
|
||||
|
||||
import ca.gosyer.core.util.decodeBase64
|
||||
import okio.Buffer
|
||||
import okio.Source
|
||||
import okio.Timeout
|
||||
|
||||
class DataUriStringSource(private val data: String) : Source {
|
||||
|
||||
private val timeout = Timeout()
|
||||
|
||||
private val headers = data.substringBefore(",")
|
||||
|
||||
private var pos = headers.length + 1
|
||||
|
||||
private val decoder: (Buffer, String) -> Long = if ("base64" in headers) {
|
||||
{ sink, bytes ->
|
||||
val decoded = bytes.decodeBase64()
|
||||
sink.write(decoded)
|
||||
decoded.size.toLong()
|
||||
}
|
||||
} else {
|
||||
{ sink, bytes ->
|
||||
val decoded = bytes.toByteArray()
|
||||
sink.write(decoded)
|
||||
decoded.size.toLong()
|
||||
}
|
||||
}
|
||||
|
||||
override fun read(sink: Buffer, byteCount: Long): Long {
|
||||
if (pos >= data.length) return -1
|
||||
|
||||
val charsToRead = minOf(data.length - pos, byteCount.toInt())
|
||||
val nextChars = data.substring(pos, pos + charsToRead)
|
||||
|
||||
pos += charsToRead
|
||||
|
||||
return decoder(sink, nextChars)
|
||||
}
|
||||
|
||||
override fun timeout(): Timeout {
|
||||
return timeout
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
}
|
||||
}
|
||||
@@ -8,16 +8,19 @@ package ca.gosyer.core.io
|
||||
|
||||
import ca.gosyer.core.lang.withIOContext
|
||||
import okio.BufferedSink
|
||||
import okio.FileSystem
|
||||
import okio.Path
|
||||
import okio.Source
|
||||
import okio.buffer
|
||||
import okio.sink
|
||||
import okio.use
|
||||
import java.nio.file.Path
|
||||
|
||||
suspend fun Source.saveTo(path: Path) {
|
||||
withIOContext {
|
||||
use { source ->
|
||||
path.sink().buffer().use { it.writeAll(source) }
|
||||
FileSystem.SYSTEM
|
||||
.sink(path)
|
||||
.buffer()
|
||||
.use { it.writeAll(source) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
|
||||
package ca.gosyer.core.prefs
|
||||
|
||||
expect class PreferenceStoreFactory() {
|
||||
expect class PreferenceStoreFactory {
|
||||
fun create(vararg names: String): PreferenceStore
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.core.util
|
||||
|
||||
import okio.ByteString.Companion.decodeBase64
|
||||
import okio.ByteString.Companion.encode
|
||||
|
||||
fun String.decodeBase64() = decodeBase64()!!
|
||||
|
||||
fun String.md5() = encode().md5().hex()
|
||||
@@ -8,7 +8,13 @@ plugins {
|
||||
}
|
||||
|
||||
kotlin {
|
||||
android()
|
||||
android {
|
||||
compilations {
|
||||
all {
|
||||
kotlinOptions.jvmTarget = Config.androidJvmTarget.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
jvm("desktop") {
|
||||
compilations {
|
||||
all {
|
||||
|
||||
96
data/src/androidMain/kotlin/ca/gosyer/data/DataComponent.kt
Normal file
96
data/src/androidMain/kotlin/ca/gosyer/data/DataComponent.kt
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.data
|
||||
|
||||
import android.content.Context
|
||||
import ca.gosyer.core.di.AppScope
|
||||
import ca.gosyer.core.prefs.PreferenceStoreFactory
|
||||
import ca.gosyer.data.catalog.CatalogPreferences
|
||||
import ca.gosyer.data.download.DownloadService
|
||||
import ca.gosyer.data.extension.ExtensionPreferences
|
||||
import ca.gosyer.data.library.LibraryPreferences
|
||||
import ca.gosyer.data.library.LibraryUpdateService
|
||||
import ca.gosyer.data.migration.MigrationPreferences
|
||||
import ca.gosyer.data.migration.Migrations
|
||||
import ca.gosyer.data.reader.ReaderPreferences
|
||||
import ca.gosyer.data.server.Http
|
||||
import ca.gosyer.data.server.HttpProvider
|
||||
import ca.gosyer.data.server.ServerPreferences
|
||||
import ca.gosyer.data.ui.UiPreferences
|
||||
import ca.gosyer.data.update.UpdateChecker
|
||||
import ca.gosyer.data.update.UpdatePreferences
|
||||
import me.tatarka.inject.annotations.Component
|
||||
import me.tatarka.inject.annotations.Provides
|
||||
|
||||
@AppScope
|
||||
@Component
|
||||
actual abstract class DataComponent(
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val context: Context
|
||||
) {
|
||||
protected abstract val preferenceFactory: PreferenceStoreFactory
|
||||
|
||||
protected abstract val httpProvider: HttpProvider
|
||||
|
||||
abstract val downloadService: DownloadService
|
||||
|
||||
abstract val libraryUpdateService: LibraryUpdateService
|
||||
|
||||
abstract val migrations: Migrations
|
||||
|
||||
abstract val updateChecker: UpdateChecker
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val serverPreferences: ServerPreferences
|
||||
get() = ServerPreferences(preferenceFactory.create("server"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val extensionPreferences: ExtensionPreferences
|
||||
get() = ExtensionPreferences(preferenceFactory.create("extension"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val catalogPreferences: CatalogPreferences
|
||||
get() = CatalogPreferences(preferenceFactory.create("catalog"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val libraryPreferences: LibraryPreferences
|
||||
get() = LibraryPreferences(preferenceFactory.create("library"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val readerPreferences: ReaderPreferences
|
||||
get() = ReaderPreferences(preferenceFactory.create("reader")) { name ->
|
||||
preferenceFactory.create("reader", name)
|
||||
}
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val uiPreferences: UiPreferences
|
||||
get() = UiPreferences(preferenceFactory.create("ui"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val migrationPreferences: MigrationPreferences
|
||||
get() = MigrationPreferences(preferenceFactory.create("migration"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val updatePreferences: UpdatePreferences
|
||||
get() = UpdatePreferences(preferenceFactory.create("update"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val http: Http
|
||||
get() = httpProvider.get(serverPreferences)
|
||||
|
||||
companion object
|
||||
}
|
||||
100
data/src/desktopMain/kotlin/ca/gosyer/data/DataComponent.kt
Normal file
100
data/src/desktopMain/kotlin/ca/gosyer/data/DataComponent.kt
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.data
|
||||
|
||||
import ca.gosyer.core.di.AppScope
|
||||
import ca.gosyer.core.prefs.PreferenceStoreFactory
|
||||
import ca.gosyer.data.catalog.CatalogPreferences
|
||||
import ca.gosyer.data.download.DownloadService
|
||||
import ca.gosyer.data.extension.ExtensionPreferences
|
||||
import ca.gosyer.data.library.LibraryPreferences
|
||||
import ca.gosyer.data.library.LibraryUpdateService
|
||||
import ca.gosyer.data.migration.MigrationPreferences
|
||||
import ca.gosyer.data.migration.Migrations
|
||||
import ca.gosyer.data.reader.ReaderPreferences
|
||||
import ca.gosyer.data.server.Http
|
||||
import ca.gosyer.data.server.HttpProvider
|
||||
import ca.gosyer.data.server.ServerHostPreferences
|
||||
import ca.gosyer.data.server.ServerPreferences
|
||||
import ca.gosyer.data.server.ServerService
|
||||
import ca.gosyer.data.ui.UiPreferences
|
||||
import ca.gosyer.data.update.UpdateChecker
|
||||
import ca.gosyer.data.update.UpdatePreferences
|
||||
import me.tatarka.inject.annotations.Component
|
||||
import me.tatarka.inject.annotations.Provides
|
||||
|
||||
@AppScope
|
||||
@Component
|
||||
actual abstract class DataComponent {
|
||||
protected abstract val preferenceFactory: PreferenceStoreFactory
|
||||
|
||||
protected abstract val httpProvider: HttpProvider
|
||||
|
||||
abstract val downloadService: DownloadService
|
||||
|
||||
abstract val libraryUpdateService: LibraryUpdateService
|
||||
|
||||
abstract val migrations: Migrations
|
||||
|
||||
abstract val updateChecker: UpdateChecker
|
||||
|
||||
abstract val serverService: ServerService
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val serverHostPreferences: ServerHostPreferences
|
||||
get() = ServerHostPreferences(preferenceFactory.create("host"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val serverPreferences: ServerPreferences
|
||||
get() = ServerPreferences(preferenceFactory.create("server"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val extensionPreferences: ExtensionPreferences
|
||||
get() = ExtensionPreferences(preferenceFactory.create("extension"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val catalogPreferences: CatalogPreferences
|
||||
get() = CatalogPreferences(preferenceFactory.create("catalog"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val libraryPreferences: LibraryPreferences
|
||||
get() = LibraryPreferences(preferenceFactory.create("library"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val readerPreferences: ReaderPreferences
|
||||
get() = ReaderPreferences(preferenceFactory.create("reader")) { name ->
|
||||
preferenceFactory.create("reader", name)
|
||||
}
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val uiPreferences: UiPreferences
|
||||
get() = UiPreferences(preferenceFactory.create("ui"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val migrationPreferences: MigrationPreferences
|
||||
get() = MigrationPreferences(preferenceFactory.create("migration"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val updatePreferences: UpdatePreferences
|
||||
get() = UpdatePreferences(preferenceFactory.create("update"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val http: Http
|
||||
get() = httpProvider.get(serverPreferences)
|
||||
|
||||
companion object
|
||||
}
|
||||
@@ -6,94 +6,4 @@
|
||||
|
||||
package ca.gosyer.data
|
||||
|
||||
import ca.gosyer.core.di.AppScope
|
||||
import ca.gosyer.core.prefs.PreferenceStoreFactory
|
||||
import ca.gosyer.data.catalog.CatalogPreferences
|
||||
import ca.gosyer.data.download.DownloadService
|
||||
import ca.gosyer.data.extension.ExtensionPreferences
|
||||
import ca.gosyer.data.library.LibraryPreferences
|
||||
import ca.gosyer.data.library.LibraryUpdateService
|
||||
import ca.gosyer.data.migration.MigrationPreferences
|
||||
import ca.gosyer.data.migration.Migrations
|
||||
import ca.gosyer.data.reader.ReaderPreferences
|
||||
import ca.gosyer.data.server.Http
|
||||
import ca.gosyer.data.server.HttpProvider
|
||||
import ca.gosyer.data.server.ServerHostPreferences
|
||||
import ca.gosyer.data.server.ServerPreferences
|
||||
import ca.gosyer.data.server.ServerService
|
||||
import ca.gosyer.data.ui.UiPreferences
|
||||
import ca.gosyer.data.update.UpdateChecker
|
||||
import ca.gosyer.data.update.UpdatePreferences
|
||||
import me.tatarka.inject.annotations.Component
|
||||
import me.tatarka.inject.annotations.Provides
|
||||
|
||||
@AppScope
|
||||
@Component
|
||||
abstract class DataComponent {
|
||||
private val preferenceFactory = PreferenceStoreFactory()
|
||||
protected abstract val httpProvider: HttpProvider
|
||||
|
||||
abstract val serverService: ServerService
|
||||
|
||||
abstract val downloadService: DownloadService
|
||||
|
||||
abstract val libraryUpdateService: LibraryUpdateService
|
||||
|
||||
abstract val migrations: Migrations
|
||||
|
||||
abstract val updateChecker: UpdateChecker
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val serverPreferences: ServerPreferences
|
||||
get() = ServerPreferences(preferenceFactory.create("server"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val serverHostPreferences: ServerHostPreferences
|
||||
get() = ServerHostPreferences(preferenceFactory.create("host"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val extensionPreferences: ExtensionPreferences
|
||||
get() = ExtensionPreferences(preferenceFactory.create("extension"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val catalogPreferences: CatalogPreferences
|
||||
get() = CatalogPreferences(preferenceFactory.create("catalog"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val libraryPreferences: LibraryPreferences
|
||||
get() = LibraryPreferences(preferenceFactory.create("library"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val readerPreferences: ReaderPreferences
|
||||
get() = ReaderPreferences(preferenceFactory.create("reader")) { name ->
|
||||
preferenceFactory.create("reader", name)
|
||||
}
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val uiPreferences: UiPreferences
|
||||
get() = UiPreferences(preferenceFactory.create("ui"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val migrationPreferences: MigrationPreferences
|
||||
get() = MigrationPreferences(preferenceFactory.create("migration"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val updatePreferences: UpdatePreferences
|
||||
get() = UpdatePreferences(preferenceFactory.create("update"))
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
val http: Http
|
||||
get() = httpProvider.get(serverPreferences)
|
||||
|
||||
companion object
|
||||
}
|
||||
expect abstract class DataComponent
|
||||
|
||||
@@ -8,7 +8,13 @@ plugins {
|
||||
}
|
||||
|
||||
kotlin {
|
||||
android()
|
||||
android {
|
||||
compilations {
|
||||
all {
|
||||
kotlinOptions.jvmTarget = Config.androidJvmTarget.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
jvm("desktop") {
|
||||
compilations {
|
||||
all {
|
||||
|
||||
@@ -10,7 +10,13 @@ plugins {
|
||||
}
|
||||
|
||||
kotlin {
|
||||
android()
|
||||
android {
|
||||
compilations {
|
||||
all {
|
||||
kotlinOptions.jvmTarget = Config.androidJvmTarget.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
jvm("desktop") {
|
||||
compilations {
|
||||
all {
|
||||
|
||||
@@ -13,13 +13,15 @@ import io.ktor.client.request.HttpRequestBuilder
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import io.ktor.utils.io.jvm.javaio.copyTo
|
||||
import okio.FileSystem
|
||||
import okio.Path
|
||||
import okio.buffer
|
||||
import org.jetbrains.skia.Image
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.readBytes
|
||||
|
||||
fun imageFromFile(file: Path): ImageBitmap {
|
||||
return Image.makeFromEncoded(file.readBytes()).toComposeImageBitmap()
|
||||
return Image.makeFromEncoded(FileSystem.SYSTEM.source(file).buffer().readByteArray())
|
||||
.toComposeImageBitmap()
|
||||
}
|
||||
|
||||
suspend fun imageFromUrl(client: Http, url: String, block: HttpRequestBuilder.() -> Unit): ImageBitmap {
|
||||
|
||||
@@ -7,7 +7,13 @@ plugins {
|
||||
}
|
||||
|
||||
kotlin {
|
||||
android()
|
||||
android {
|
||||
compilations {
|
||||
all {
|
||||
kotlinOptions.jvmTarget = Config.androidJvmTarget.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
jvm("desktop") {
|
||||
compilations {
|
||||
all {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.uicore.resources
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import dev.icerock.moko.resources.PluralsResource
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import dev.icerock.moko.resources.desc.Plural
|
||||
import dev.icerock.moko.resources.desc.PluralFormatted
|
||||
import dev.icerock.moko.resources.desc.Resource
|
||||
import dev.icerock.moko.resources.desc.ResourceFormatted
|
||||
import dev.icerock.moko.resources.desc.StringDesc
|
||||
|
||||
@Composable
|
||||
actual fun stringResource(resource: StringResource): String {
|
||||
val context = LocalContext.current
|
||||
return StringDesc.Resource(resource).toString(context)
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun stringResource(resource: StringResource, vararg args: Any): String {
|
||||
val context = LocalContext.current
|
||||
return StringDesc.ResourceFormatted(resource, *args).toString(context)
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun stringResource(resource: PluralsResource, quantity: Int): String {
|
||||
val context = LocalContext.current
|
||||
return StringDesc.Plural(resource, quantity).toString(context)
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun stringResource(resource: PluralsResource, quantity: Int, vararg args: Any): String {
|
||||
val context = LocalContext.current
|
||||
return StringDesc.PluralFormatted(resource, quantity, *args).toString(context)
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.uicore.resources
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import dev.icerock.moko.resources.PluralsResource
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
|
||||
@Composable
|
||||
expect fun stringResource(resource: StringResource): String
|
||||
|
||||
@Composable
|
||||
expect fun stringResource(resource: StringResource, vararg args: Any): String
|
||||
|
||||
@Composable
|
||||
expect fun stringResource(resource: PluralsResource, quantity: Int): String
|
||||
|
||||
@Composable
|
||||
expect fun stringResource(resource: PluralsResource, quantity: Int, vararg args: Any): String
|
||||
@@ -16,17 +16,17 @@ import dev.icerock.moko.resources.desc.ResourceFormatted
|
||||
import dev.icerock.moko.resources.desc.StringDesc
|
||||
|
||||
@Composable
|
||||
fun stringResource(resource: StringResource): String =
|
||||
actual fun stringResource(resource: StringResource): String =
|
||||
StringDesc.Resource(resource).localized()
|
||||
|
||||
@Composable
|
||||
fun stringResource(resource: StringResource, vararg args: Any): String =
|
||||
actual fun stringResource(resource: StringResource, vararg args: Any): String =
|
||||
StringDesc.ResourceFormatted(resource, *args).localized()
|
||||
|
||||
@Composable
|
||||
fun stringResource(resource: PluralsResource, quantity: Int): String =
|
||||
actual fun stringResource(resource: PluralsResource, quantity: Int): String =
|
||||
StringDesc.Plural(resource, quantity).localized()
|
||||
|
||||
@Composable
|
||||
fun stringResource(resource: PluralsResource, quantity: Int, vararg args: Any): String =
|
||||
actual fun stringResource(resource: PluralsResource, quantity: Int, vararg args: Any): String =
|
||||
StringDesc.PluralFormatted(resource, quantity, *args).localized()
|
||||
|
||||
Reference in New Issue
Block a user