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,7 +21,6 @@ import org.lighthousegames.logging.logging
|
||||
import java.util.Locale
|
||||
|
||||
class App : Application(), DefaultLifecycleObserver {
|
||||
|
||||
override fun onCreate() {
|
||||
super<Application>.onCreate()
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ abstract class AppComponent(
|
||||
@get:Provides
|
||||
val context: Context,
|
||||
) : ViewModelComponent, DataComponent, DomainComponent, UiComponent {
|
||||
|
||||
abstract val appMigrations: AppMigrations
|
||||
|
||||
@get:AppScope
|
||||
@@ -39,7 +38,8 @@ abstract class AppComponent(
|
||||
private var appComponentInstance: AppComponent? = null
|
||||
|
||||
@Suppress("UNRESOLVED_REFERENCE", "EXPRESSION_EXPECTED_PACKAGE_FOUND")
|
||||
fun getInstance(context: Context) = appComponentInstance ?: create(context)
|
||||
.also { appComponentInstance = it }
|
||||
fun getInstance(context: Context) =
|
||||
appComponentInstance ?: create(context)
|
||||
.also { appComponentInstance = it }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,24 +11,25 @@ import ca.gosyer.jui.domain.migration.service.MigrationPreferences
|
||||
import ca.gosyer.jui.uicore.vm.ContextWrapper
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
|
||||
class AppMigrations @Inject constructor(
|
||||
private val migrationPreferences: MigrationPreferences,
|
||||
private val contextWrapper: ContextWrapper,
|
||||
) {
|
||||
class AppMigrations
|
||||
@Inject
|
||||
constructor(
|
||||
private val migrationPreferences: MigrationPreferences,
|
||||
private val contextWrapper: ContextWrapper,
|
||||
) {
|
||||
fun runMigrations(): Boolean {
|
||||
val oldVersion = migrationPreferences.appVersion().get()
|
||||
if (oldVersion < BuildConfig.VERSION_CODE) {
|
||||
migrationPreferences.appVersion().set(BuildConfig.VERSION_CODE)
|
||||
|
||||
fun runMigrations(): Boolean {
|
||||
val oldVersion = migrationPreferences.appVersion().get()
|
||||
if (oldVersion < BuildConfig.VERSION_CODE) {
|
||||
migrationPreferences.appVersion().set(BuildConfig.VERSION_CODE)
|
||||
UpdateCheckWorker.setupTask(contextWrapper)
|
||||
|
||||
UpdateCheckWorker.setupTask(contextWrapper)
|
||||
|
||||
// Fresh install
|
||||
if (oldVersion == 0) {
|
||||
return false
|
||||
// Fresh install
|
||||
if (oldVersion == 0) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return true
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,12 @@ import ca.gosyer.jui.ui.base.theme.AppTheme
|
||||
import ca.gosyer.jui.ui.reader.ReaderMenu
|
||||
|
||||
class ReaderActivity : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
fun newIntent(context: Context, mangaId: Long, chapterIndex: Int): Intent {
|
||||
fun newIntent(
|
||||
context: Context,
|
||||
mangaId: Long,
|
||||
chapterIndex: Int,
|
||||
): Intent {
|
||||
return Intent(context, ReaderActivity::class.java).apply {
|
||||
putExtra("manga", mangaId)
|
||||
putExtra("chapter", chapterIndex)
|
||||
|
||||
@@ -55,11 +55,13 @@ import org.lighthousegames.logging.logging
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class AndroidDownloadService : Service() {
|
||||
|
||||
companion object {
|
||||
private var instance: AndroidDownloadService? = null
|
||||
|
||||
fun start(context: Context, actions: Actions) {
|
||||
fun start(
|
||||
context: Context,
|
||||
actions: Actions,
|
||||
) {
|
||||
if (!isRunning() && actions != Actions.STOP) {
|
||||
val intent = Intent(context, AndroidDownloadService::class.java).apply {
|
||||
action = actions.name
|
||||
@@ -106,7 +108,11 @@ class AndroidDownloadService : Service() {
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
override fun onStartCommand(
|
||||
intent: Intent?,
|
||||
flags: Int,
|
||||
startId: Int,
|
||||
): Int {
|
||||
instance = this
|
||||
ioScope.coroutineContext.job.cancelChildren()
|
||||
|
||||
|
||||
@@ -55,11 +55,13 @@ import kotlinx.serialization.json.Json
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class AndroidLibraryService : Service() {
|
||||
|
||||
companion object {
|
||||
private var instance: AndroidLibraryService? = null
|
||||
|
||||
fun start(context: Context, actions: Actions) {
|
||||
fun start(
|
||||
context: Context,
|
||||
actions: Actions,
|
||||
) {
|
||||
if (!isRunning() && actions != Actions.STOP) {
|
||||
val intent = Intent(context, AndroidLibraryService::class.java).apply {
|
||||
action = actions.name
|
||||
@@ -106,7 +108,11 @@ class AndroidLibraryService : Service() {
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
override fun onStartCommand(
|
||||
intent: Intent?,
|
||||
flags: Int,
|
||||
startId: Int,
|
||||
): Int {
|
||||
instance = this
|
||||
ioScope.coroutineContext.job.cancelChildren()
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import ca.gosyer.jui.i18n.MR
|
||||
import dev.icerock.moko.resources.desc.desc
|
||||
|
||||
object Notifications {
|
||||
|
||||
/**
|
||||
* Notification channel and ids used by the downloader.
|
||||
*/
|
||||
|
||||
@@ -37,7 +37,10 @@ fun Context.acquireWakeLock(tag: String): PowerManager.WakeLock {
|
||||
* @param block the function that will execute inside the builder.
|
||||
* @return a notification to be displayed or updated.
|
||||
*/
|
||||
fun Context.notificationBuilder(channelId: String, block: (NotificationCompat.Builder.() -> Unit)? = null): NotificationCompat.Builder {
|
||||
fun Context.notificationBuilder(
|
||||
channelId: String,
|
||||
block: (NotificationCompat.Builder.() -> Unit)? = null,
|
||||
): NotificationCompat.Builder {
|
||||
val builder = NotificationCompat.Builder(this, channelId)
|
||||
// .setColor(getColor(R.color.accent_blue))
|
||||
if (block != null) {
|
||||
@@ -53,7 +56,10 @@ fun Context.notificationBuilder(channelId: String, block: (NotificationCompat.Bu
|
||||
* @param block the function that will execute inside the builder.
|
||||
* @return a notification to be displayed or updated.
|
||||
*/
|
||||
fun Context.notification(channelId: String, block: (NotificationCompat.Builder.() -> Unit)?): Notification {
|
||||
fun Context.notification(
|
||||
channelId: String,
|
||||
block: (NotificationCompat.Builder.() -> Unit)?,
|
||||
): Notification {
|
||||
val builder = notificationBuilder(channelId, block)
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
@@ -10,15 +10,17 @@ import android.content.Context
|
||||
import com.russhwolf.settings.SharedPreferencesSettings
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
|
||||
actual class PreferenceStoreFactory @Inject constructor(private val context: Context) {
|
||||
actual fun create(vararg names: String): PreferenceStore {
|
||||
return StandardPreferenceStore(
|
||||
SharedPreferencesSettings(
|
||||
context.getSharedPreferences(
|
||||
names.joinToString(separator = "_"),
|
||||
Context.MODE_PRIVATE,
|
||||
actual class PreferenceStoreFactory
|
||||
@Inject
|
||||
constructor(private val context: Context) {
|
||||
actual fun create(vararg names: String): PreferenceStore {
|
||||
return StandardPreferenceStore(
|
||||
SharedPreferencesSettings(
|
||||
context.getSharedPreferences(
|
||||
names.joinToString(separator = "_"),
|
||||
Context.MODE_PRIVATE,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,17 +48,11 @@ fun CoroutineScope.launchIO(
|
||||
block: suspend CoroutineScope.() -> Unit,
|
||||
) = launch(Dispatchers.IO, start, block)
|
||||
|
||||
suspend fun <T> withDefaultContext(
|
||||
block: suspend CoroutineScope.() -> T,
|
||||
): T = withContext(Dispatchers.Default, block)
|
||||
suspend fun <T> withDefaultContext(block: suspend CoroutineScope.() -> T): T = withContext(Dispatchers.Default, block)
|
||||
|
||||
suspend fun <T> withUIContext(
|
||||
block: suspend CoroutineScope.() -> T,
|
||||
): T = withContext(Dispatchers.Main, block)
|
||||
suspend fun <T> withUIContext(block: suspend CoroutineScope.() -> T): T = withContext(Dispatchers.Main, block)
|
||||
|
||||
suspend fun <T> withIOContext(
|
||||
block: suspend CoroutineScope.() -> T,
|
||||
): T = withContext(Dispatchers.IO, block)
|
||||
suspend fun <T> withIOContext(block: suspend CoroutineScope.() -> T): T = withContext(Dispatchers.IO, block)
|
||||
|
||||
fun Throwable.throwIfCancellation() { if (this is CancellationException) throw this }
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ internal open class ProcessChannel<T>(
|
||||
internal val inChannel: Channel<T>,
|
||||
internal val outChannel: Channel<T>,
|
||||
) : Channel<T> {
|
||||
|
||||
@DelicateCoroutinesApi
|
||||
override val isClosedForReceive: Boolean
|
||||
get() = outChannel.isClosedForReceive
|
||||
|
||||
@@ -10,7 +10,10 @@ package ca.gosyer.jui.core.lang
|
||||
* Replaces the given string to have at most [count] characters using [replacement] at its end.
|
||||
* If [replacement] is longer than [count] an exception will be thrown when `length > count`.
|
||||
*/
|
||||
fun String.chop(count: Int, replacement: String = "…"): String {
|
||||
fun String.chop(
|
||||
count: Int,
|
||||
replacement: String = "…",
|
||||
): String {
|
||||
return if (length > count) {
|
||||
take(count - replacement.length) + replacement
|
||||
} else {
|
||||
|
||||
@@ -16,46 +16,63 @@ import kotlinx.serialization.modules.SerializersModule
|
||||
class LazyPreferenceStore(
|
||||
private val lazyStore: Lazy<PreferenceStore>,
|
||||
) : PreferenceStore {
|
||||
|
||||
/**
|
||||
* Returns an [String] preference for this [key].
|
||||
*/
|
||||
override fun getString(key: String, defaultValue: String): Preference<String> {
|
||||
override fun getString(
|
||||
key: String,
|
||||
defaultValue: String,
|
||||
): Preference<String> {
|
||||
return lazyStore.value.getString(key, defaultValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Long] preference for this [key].
|
||||
*/
|
||||
override fun getLong(key: String, defaultValue: Long): Preference<Long> {
|
||||
override fun getLong(
|
||||
key: String,
|
||||
defaultValue: Long,
|
||||
): Preference<Long> {
|
||||
return lazyStore.value.getLong(key, defaultValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an [Int] preference for this [key].
|
||||
*/
|
||||
override fun getInt(key: String, defaultValue: Int): Preference<Int> {
|
||||
override fun getInt(
|
||||
key: String,
|
||||
defaultValue: Int,
|
||||
): Preference<Int> {
|
||||
return lazyStore.value.getInt(key, defaultValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Float] preference for this [key].
|
||||
*/
|
||||
override fun getFloat(key: String, defaultValue: Float): Preference<Float> {
|
||||
override fun getFloat(
|
||||
key: String,
|
||||
defaultValue: Float,
|
||||
): Preference<Float> {
|
||||
return lazyStore.value.getFloat(key, defaultValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Boolean] preference for this [key].
|
||||
*/
|
||||
override fun getBoolean(key: String, defaultValue: Boolean): Preference<Boolean> {
|
||||
override fun getBoolean(
|
||||
key: String,
|
||||
defaultValue: Boolean,
|
||||
): Preference<Boolean> {
|
||||
return lazyStore.value.getBoolean(key, defaultValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Set<String>] preference for this [key].
|
||||
*/
|
||||
override fun getStringSet(key: String, defaultValue: Set<String>): Preference<Set<String>> {
|
||||
override fun getStringSet(
|
||||
key: String,
|
||||
defaultValue: Set<String>,
|
||||
): Preference<Set<String>> {
|
||||
return lazyStore.value.getStringSet(key, defaultValue)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import kotlinx.coroutines.flow.onStart
|
||||
* this interface must be provided through a [PreferenceStore].
|
||||
*/
|
||||
interface Preference<T> {
|
||||
|
||||
/**
|
||||
* Returns the key of this preference.
|
||||
*/
|
||||
|
||||
@@ -15,36 +15,53 @@ import kotlinx.serialization.modules.SerializersModule
|
||||
* persist these preferences on disk.
|
||||
*/
|
||||
interface PreferenceStore {
|
||||
|
||||
/**
|
||||
* Returns an [String] preference for this [key].
|
||||
*/
|
||||
fun getString(key: String, defaultValue: String = ""): Preference<String>
|
||||
fun getString(
|
||||
key: String,
|
||||
defaultValue: String = "",
|
||||
): Preference<String>
|
||||
|
||||
/**
|
||||
* Returns a [Long] preference for this [key].
|
||||
*/
|
||||
fun getLong(key: String, defaultValue: Long = 0): Preference<Long>
|
||||
fun getLong(
|
||||
key: String,
|
||||
defaultValue: Long = 0,
|
||||
): Preference<Long>
|
||||
|
||||
/**
|
||||
* Returns an [Int] preference for this [key].
|
||||
*/
|
||||
fun getInt(key: String, defaultValue: Int = 0): Preference<Int>
|
||||
fun getInt(
|
||||
key: String,
|
||||
defaultValue: Int = 0,
|
||||
): Preference<Int>
|
||||
|
||||
/**
|
||||
* Returns a [Float] preference for this [key].
|
||||
*/
|
||||
fun getFloat(key: String, defaultValue: Float = 0f): Preference<Float>
|
||||
fun getFloat(
|
||||
key: String,
|
||||
defaultValue: Float = 0f,
|
||||
): Preference<Float>
|
||||
|
||||
/**
|
||||
* Returns a [Boolean] preference for this [key].
|
||||
*/
|
||||
fun getBoolean(key: String, defaultValue: Boolean = false): Preference<Boolean>
|
||||
fun getBoolean(
|
||||
key: String,
|
||||
defaultValue: Boolean = false,
|
||||
): Preference<Boolean>
|
||||
|
||||
/**
|
||||
* Returns a [Set<String>] preference for this [key].
|
||||
*/
|
||||
fun getStringSet(key: String, defaultValue: Set<String> = emptySet()): Preference<Set<String>>
|
||||
fun getStringSet(
|
||||
key: String,
|
||||
defaultValue: Set<String> = emptySet(),
|
||||
): Preference<Set<String>>
|
||||
|
||||
/**
|
||||
* Returns preference of type [T] for this [key]. The [serializer] and [deserializer] function
|
||||
|
||||
@@ -17,81 +17,150 @@ import kotlinx.serialization.modules.EmptySerializersModule
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
|
||||
interface Adapter<T> {
|
||||
fun get(key: String, preferences: ObservableSettings): T
|
||||
fun get(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
): T
|
||||
|
||||
fun set(key: String, value: T, editor: ObservableSettings)
|
||||
fun set(
|
||||
key: String,
|
||||
value: T,
|
||||
editor: ObservableSettings,
|
||||
)
|
||||
|
||||
fun isSet(keys: Set<String>, key: String): Boolean = key in keys
|
||||
fun isSet(
|
||||
keys: Set<String>,
|
||||
key: String,
|
||||
): Boolean = key in keys
|
||||
|
||||
fun addListener(key: String, preferences: ObservableSettings, callback: () -> Unit): SettingsListener
|
||||
fun addListener(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener
|
||||
}
|
||||
|
||||
internal object StringAdapter : Adapter<String> {
|
||||
override fun get(key: String, preferences: ObservableSettings): 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) {
|
||||
override fun set(
|
||||
key: String,
|
||||
value: String,
|
||||
editor: ObservableSettings,
|
||||
) {
|
||||
editor.putString(key, value)
|
||||
}
|
||||
|
||||
override fun addListener(key: String, preferences: ObservableSettings, callback: () -> Unit): SettingsListener {
|
||||
override fun addListener(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addStringOrNullListener(key) { callback() }
|
||||
}
|
||||
}
|
||||
|
||||
internal object LongAdapter : Adapter<Long> {
|
||||
override fun get(key: String, preferences: ObservableSettings): Long {
|
||||
override fun get(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
): Long {
|
||||
return preferences.getLong(key, 0)
|
||||
}
|
||||
|
||||
override fun set(key: String, value: Long, editor: ObservableSettings) {
|
||||
override fun set(
|
||||
key: String,
|
||||
value: Long,
|
||||
editor: ObservableSettings,
|
||||
) {
|
||||
editor.putLong(key, value)
|
||||
}
|
||||
|
||||
override fun addListener(key: String, preferences: ObservableSettings, callback: () -> Unit): SettingsListener {
|
||||
override fun addListener(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addLongOrNullListener(key) { callback() }
|
||||
}
|
||||
}
|
||||
|
||||
internal object IntAdapter : Adapter<Int> {
|
||||
override fun get(key: String, preferences: ObservableSettings): Int {
|
||||
override fun get(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
): Int {
|
||||
return preferences.getInt(key, 0)
|
||||
}
|
||||
|
||||
override fun set(key: String, value: Int, editor: ObservableSettings) {
|
||||
override fun set(
|
||||
key: String,
|
||||
value: Int,
|
||||
editor: ObservableSettings,
|
||||
) {
|
||||
editor.putInt(key, value)
|
||||
}
|
||||
|
||||
override fun addListener(key: String, preferences: ObservableSettings, callback: () -> Unit): SettingsListener {
|
||||
override fun addListener(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addIntOrNullListener(key) { callback() }
|
||||
}
|
||||
}
|
||||
|
||||
internal object FloatAdapter : Adapter<Float> {
|
||||
override fun get(key: String, preferences: ObservableSettings): Float {
|
||||
override fun get(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
): Float {
|
||||
return preferences.getFloat(key, 0f)
|
||||
}
|
||||
|
||||
override fun set(key: String, value: Float, editor: ObservableSettings) {
|
||||
override fun set(
|
||||
key: String,
|
||||
value: Float,
|
||||
editor: ObservableSettings,
|
||||
) {
|
||||
editor.putFloat(key, value)
|
||||
}
|
||||
|
||||
override fun addListener(key: String, preferences: ObservableSettings, callback: () -> Unit): SettingsListener {
|
||||
override fun addListener(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addFloatOrNullListener(key) { callback() }
|
||||
}
|
||||
}
|
||||
|
||||
internal object BooleanAdapter : Adapter<Boolean> {
|
||||
override fun get(key: String, preferences: ObservableSettings): Boolean {
|
||||
override fun get(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
): Boolean {
|
||||
return preferences.getBoolean(key, false)
|
||||
}
|
||||
|
||||
override fun set(key: String, value: Boolean, editor: ObservableSettings) {
|
||||
override fun set(
|
||||
key: String,
|
||||
value: Boolean,
|
||||
editor: ObservableSettings,
|
||||
) {
|
||||
editor.putBoolean(key, value)
|
||||
}
|
||||
|
||||
override fun addListener(key: String, preferences: ObservableSettings, callback: () -> Unit): SettingsListener {
|
||||
override fun addListener(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addBooleanOrNullListener(key) { callback() }
|
||||
}
|
||||
}
|
||||
@@ -99,18 +168,28 @@ internal object BooleanAdapter : Adapter<Boolean> {
|
||||
internal object StringSetAdapter : Adapter<Set<String>> {
|
||||
private val serializer = SetSerializer(String.serializer())
|
||||
|
||||
override fun get(key: String, preferences: ObservableSettings): Set<String> {
|
||||
override fun get(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
): Set<String> {
|
||||
return preferences.decodeValue(serializer, key, emptySet()) // Not called unless key is present.
|
||||
}
|
||||
|
||||
override fun set(key: String, value: Set<String>, editor: ObservableSettings) {
|
||||
override fun set(
|
||||
key: String,
|
||||
value: Set<String>,
|
||||
editor: ObservableSettings,
|
||||
) {
|
||||
editor.encodeValue(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 {
|
||||
override fun isSet(
|
||||
keys: Set<String>,
|
||||
key: String,
|
||||
): Boolean {
|
||||
return keys.contains("$key.size")
|
||||
}
|
||||
|
||||
@@ -118,7 +197,11 @@ internal object StringSetAdapter : Adapter<Set<String>> {
|
||||
* Watching the regular key doesn't produce updates for a string set for some reason
|
||||
* TODO make better, doesn't produce updates when you add something and remove something
|
||||
*/
|
||||
override fun addListener(key: String, preferences: ObservableSettings, callback: () -> Unit): SettingsListener {
|
||||
override fun addListener(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addIntOrNullListener("$key.size") { callback() }
|
||||
}
|
||||
}
|
||||
@@ -127,16 +210,26 @@ internal class ObjectAdapter<T>(
|
||||
private val serializer: (T) -> String,
|
||||
private val deserializer: (String) -> T,
|
||||
) : Adapter<T> {
|
||||
|
||||
override fun get(key: String, preferences: ObservableSettings): 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) {
|
||||
override fun set(
|
||||
key: String,
|
||||
value: T,
|
||||
editor: ObservableSettings,
|
||||
) {
|
||||
editor.putString(key, serializer(value))
|
||||
}
|
||||
|
||||
override fun addListener(key: String, preferences: ObservableSettings, callback: () -> Unit): SettingsListener {
|
||||
override fun addListener(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
return preferences.addStringOrNullListener(key) { callback() }
|
||||
}
|
||||
}
|
||||
@@ -146,12 +239,18 @@ internal class JsonObjectAdapter<T>(
|
||||
private val serializer: KSerializer<T>,
|
||||
private val serializersModule: SerializersModule = EmptySerializersModule(),
|
||||
) : Adapter<T> {
|
||||
|
||||
override fun get(key: String, preferences: ObservableSettings): 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) {
|
||||
override fun set(
|
||||
key: String,
|
||||
value: T,
|
||||
editor: ObservableSettings,
|
||||
) {
|
||||
editor.encodeValue(serializer, key, value, serializersModule)
|
||||
}
|
||||
|
||||
@@ -159,14 +258,21 @@ internal class JsonObjectAdapter<T>(
|
||||
* 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 {
|
||||
override fun isSet(
|
||||
keys: Set<String>,
|
||||
key: String,
|
||||
): Boolean {
|
||||
return keys.any { it.startsWith(key) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Todo doesn't work
|
||||
*/
|
||||
override fun addListener(key: String, preferences: ObservableSettings, callback: () -> Unit): SettingsListener {
|
||||
override fun addListener(
|
||||
key: String,
|
||||
preferences: ObservableSettings,
|
||||
callback: () -> Unit,
|
||||
): SettingsListener {
|
||||
@Suppress("DEPRECATION") // Because we don't care about the type, and it crashes with any other listener
|
||||
return preferences.addListener(key) { callback() }
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ internal class StandardPreference<T>(
|
||||
private val defaultValue: T,
|
||||
private val adapter: Adapter<T>,
|
||||
) : Preference<T> {
|
||||
|
||||
/**
|
||||
* Returns the key of this preference.
|
||||
*/
|
||||
|
||||
@@ -11,46 +11,63 @@ import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
|
||||
class StandardPreferenceStore(private val preferences: ObservableSettings) : PreferenceStore {
|
||||
|
||||
/**
|
||||
* Returns an [String] preference for this [key].
|
||||
*/
|
||||
override fun getString(key: String, defaultValue: String): Preference<String> {
|
||||
override fun getString(
|
||||
key: String,
|
||||
defaultValue: String,
|
||||
): Preference<String> {
|
||||
return StandardPreference(preferences, key, defaultValue, StringAdapter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Long] preference for this [key].
|
||||
*/
|
||||
override fun getLong(key: String, defaultValue: Long): Preference<Long> {
|
||||
override fun getLong(
|
||||
key: String,
|
||||
defaultValue: Long,
|
||||
): Preference<Long> {
|
||||
return StandardPreference(preferences, key, defaultValue, LongAdapter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an [Int] preference for this [key].
|
||||
*/
|
||||
override fun getInt(key: String, defaultValue: Int): Preference<Int> {
|
||||
override fun getInt(
|
||||
key: String,
|
||||
defaultValue: Int,
|
||||
): Preference<Int> {
|
||||
return StandardPreference(preferences, key, defaultValue, IntAdapter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Float] preference for this [key].
|
||||
*/
|
||||
override fun getFloat(key: String, defaultValue: Float): Preference<Float> {
|
||||
override fun getFloat(
|
||||
key: String,
|
||||
defaultValue: Float,
|
||||
): Preference<Float> {
|
||||
return StandardPreference(preferences, key, defaultValue, FloatAdapter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Boolean] preference for this [key].
|
||||
*/
|
||||
override fun getBoolean(key: String, defaultValue: Boolean): Preference<Boolean> {
|
||||
override fun getBoolean(
|
||||
key: String,
|
||||
defaultValue: Boolean,
|
||||
): Preference<Boolean> {
|
||||
return StandardPreference(preferences, key, defaultValue, BooleanAdapter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Set<String>] preference for this [key].
|
||||
*/
|
||||
override fun getStringSet(key: String, defaultValue: Set<String>): Preference<Set<String>> {
|
||||
override fun getStringSet(
|
||||
key: String,
|
||||
defaultValue: Set<String>,
|
||||
): Preference<Set<String>> {
|
||||
return StandardPreference(preferences, key, defaultValue, StringSetAdapter)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,10 @@ package ca.gosyer.jui.core.util
|
||||
/**
|
||||
* Returns a new list that replaces the item at the given [position] with [newItem].
|
||||
*/
|
||||
fun <T> List<T>.replace(position: Int, newItem: T): List<T> {
|
||||
fun <T> List<T>.replace(
|
||||
position: Int,
|
||||
newItem: T,
|
||||
): List<T> {
|
||||
val newList = toMutableList()
|
||||
newList[position] = newItem
|
||||
return newList
|
||||
@@ -19,7 +22,10 @@ fun <T> List<T>.replace(position: Int, newItem: T): List<T> {
|
||||
* Returns a new list that replaces the first occurrence that matches the given [predicate] with
|
||||
* [newItem]. If no item matches the predicate, the same list is returned (and unmodified).
|
||||
*/
|
||||
inline fun <T> List<T>.replaceFirst(predicate: (T) -> Boolean, newItem: T): List<T> {
|
||||
inline fun <T> List<T>.replaceFirst(
|
||||
predicate: (T) -> Boolean,
|
||||
newItem: T,
|
||||
): List<T> {
|
||||
forEachIndexed { index, element ->
|
||||
if (predicate(element)) {
|
||||
return replace(index, newItem)
|
||||
|
||||
@@ -9,7 +9,6 @@ package ca.gosyer.jui.core.util
|
||||
import io.ktor.utils.io.core.toByteArray
|
||||
|
||||
object ImageUtil {
|
||||
|
||||
private val jpgMagic = charByteArrayOf(0xFF, 0xD8, 0xFF)
|
||||
private val pngMagic = charByteArrayOf(0x89, 0x50, 0x4E, 0x47)
|
||||
private val gifMagic = "GIF8".toByteArray()
|
||||
|
||||
@@ -10,15 +10,17 @@ import com.russhwolf.settings.PreferencesSettings
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import java.util.prefs.Preferences
|
||||
|
||||
actual class PreferenceStoreFactory @Inject constructor() {
|
||||
private val rootNode: Preferences = Preferences.userRoot()
|
||||
.node("ca/gosyer/tachideskjui")
|
||||
actual class PreferenceStoreFactory
|
||||
@Inject
|
||||
constructor() {
|
||||
private val rootNode: Preferences = Preferences.userRoot()
|
||||
.node("ca/gosyer/tachideskjui")
|
||||
|
||||
actual fun create(vararg names: String): PreferenceStore {
|
||||
return StandardPreferenceStore(
|
||||
PreferencesSettings(
|
||||
rootNode.node(names.joinToString(separator = "/")),
|
||||
),
|
||||
)
|
||||
actual fun create(vararg names: String): PreferenceStore {
|
||||
return StandardPreferenceStore(
|
||||
PreferencesSettings(
|
||||
rootNode.node(names.joinToString(separator = "/")),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,14 +17,16 @@ fun Locale.toPlatform(): PlatformLocale = PlatformLocale(toLanguageTag())
|
||||
* First Locale: en_IN
|
||||
* Language: English
|
||||
*/
|
||||
actual fun Locale.getDisplayLanguage(displayLocale: Locale): String = toPlatform()
|
||||
.localizedStringForLanguageCode(displayLocale.toLanguageTag())!!
|
||||
actual fun Locale.getDisplayLanguage(displayLocale: Locale): String =
|
||||
toPlatform()
|
||||
.localizedStringForLanguageCode(displayLocale.toLanguageTag())!!
|
||||
|
||||
/**
|
||||
* First Locale: en_US
|
||||
* Language: English (United States)
|
||||
*/
|
||||
actual fun Locale.getDisplayName(displayLocale: Locale): String = toPlatform()
|
||||
.localizedStringForLocaleIdentifier(displayLocale.toLanguageTag())
|
||||
actual fun Locale.getDisplayName(displayLocale: Locale): String =
|
||||
toPlatform()
|
||||
.localizedStringForLocaleIdentifier(displayLocale.toLanguageTag())
|
||||
|
||||
actual val Locale.displayName: String get() = getDisplayLanguage(this)
|
||||
|
||||
@@ -10,12 +10,14 @@ import com.russhwolf.settings.NSUserDefaultsSettings
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import platform.Foundation.NSUserDefaults
|
||||
|
||||
actual class PreferenceStoreFactory @Inject constructor() {
|
||||
actual fun create(vararg names: String): PreferenceStore {
|
||||
return StandardPreferenceStore(
|
||||
NSUserDefaultsSettings(
|
||||
NSUserDefaults.standardUserDefaults,
|
||||
),
|
||||
)
|
||||
actual class PreferenceStoreFactory
|
||||
@Inject
|
||||
constructor() {
|
||||
actual fun create(vararg names: String): PreferenceStore {
|
||||
return StandardPreferenceStore(
|
||||
NSUserDefaultsSettings(
|
||||
NSUserDefaults.standardUserDefaults,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,10 +11,12 @@ import java.util.Locale as PlatformLocale
|
||||
|
||||
fun Locale.toPlatform(): PlatformLocale = PlatformLocale.forLanguageTag(toLanguageTag())
|
||||
|
||||
actual fun Locale.getDisplayLanguage(displayLocale: Locale): String = toPlatform()
|
||||
.getDisplayLanguage(displayLocale.toPlatform())
|
||||
actual fun Locale.getDisplayLanguage(displayLocale: Locale): String =
|
||||
toPlatform()
|
||||
.getDisplayLanguage(displayLocale.toPlatform())
|
||||
|
||||
actual fun Locale.getDisplayName(displayLocale: Locale): String = toPlatform()
|
||||
.getDisplayName(displayLocale.toPlatform())
|
||||
actual fun Locale.getDisplayName(displayLocale: Locale): String =
|
||||
toPlatform()
|
||||
.getDisplayName(displayLocale.toPlatform())
|
||||
|
||||
actual val Locale.displayName: String get() = toPlatform().displayName
|
||||
|
||||
@@ -24,9 +24,11 @@ import de.jensklingenberg.ktorfit.Ktorfit
|
||||
import me.tatarka.inject.annotations.Provides
|
||||
|
||||
interface DataComponent {
|
||||
|
||||
@Provides
|
||||
fun ktorfit(http: Http, serverPreferences: ServerPreferences) = Ktorfit
|
||||
fun ktorfit(
|
||||
http: Http,
|
||||
serverPreferences: ServerPreferences,
|
||||
) = Ktorfit
|
||||
.Builder()
|
||||
.httpClient(http)
|
||||
.converterFactories(FlowConverterFactory())
|
||||
|
||||
@@ -18,19 +18,17 @@ import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
|
||||
class FlowConverterFactory : Converter.Factory {
|
||||
|
||||
private class FlowResponseConverter(
|
||||
val typeData: TypeData,
|
||||
val ktorfit: Ktorfit
|
||||
val ktorfit: Ktorfit,
|
||||
) : Converter.ResponseConverter<HttpResponse, Flow<Any?>> {
|
||||
|
||||
override fun convert(getResponse: suspend () -> HttpResponse): Flow<Any?> {
|
||||
return flow {
|
||||
val response = getResponse()
|
||||
|
||||
val convertedBody = ktorfit.nextSuspendResponseConverter(
|
||||
null,
|
||||
typeData.typeArgs.first()
|
||||
typeData.typeArgs.first(),
|
||||
)?.convert(response)
|
||||
?: response.body(typeData.typeArgs.first().typeInfo)
|
||||
emit(convertedBody)
|
||||
@@ -40,7 +38,7 @@ class FlowConverterFactory : Converter.Factory {
|
||||
|
||||
override fun responseConverter(
|
||||
typeData: TypeData,
|
||||
ktorfit: Ktorfit
|
||||
ktorfit: Ktorfit,
|
||||
): Converter.ResponseConverter<HttpResponse, *>? {
|
||||
if (typeData.typeInfo.type == Flow::class) {
|
||||
return FlowResponseConverter(typeData, ktorfit)
|
||||
@@ -50,9 +48,8 @@ class FlowConverterFactory : Converter.Factory {
|
||||
|
||||
override fun suspendResponseConverter(
|
||||
typeData: TypeData,
|
||||
ktorfit: Ktorfit
|
||||
ktorfit: Ktorfit,
|
||||
): Converter.SuspendResponseConverter<HttpResponse, *>? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,44 +15,47 @@ import platform.Foundation.NSDateFormatter
|
||||
import platform.Foundation.NSDateFormatterNoStyle
|
||||
import platform.Foundation.NSDateFormatterShortStyle
|
||||
|
||||
actual class DateHandler @Inject constructor() {
|
||||
actual val formatOptions by lazy {
|
||||
listOf(
|
||||
"",
|
||||
"MM/dd/yy",
|
||||
"dd/MM/yy",
|
||||
"yyyy-MM-dd",
|
||||
)
|
||||
}
|
||||
|
||||
actual fun getDateFormat(format: String): (Instant) -> String = when (format) {
|
||||
"" -> NSDateFormatter()
|
||||
.apply {
|
||||
setDateStyle(NSDateFormatterShortStyle)
|
||||
setTimeStyle(NSDateFormatterNoStyle)
|
||||
setLocale(Locale.current.toPlatform())
|
||||
}
|
||||
else -> NSDateFormatter()
|
||||
.apply {
|
||||
setDateFormat(format)
|
||||
}
|
||||
}.let { formatter ->
|
||||
{
|
||||
formatter.stringFromDate(it.toNSDate())
|
||||
actual class DateHandler
|
||||
@Inject
|
||||
constructor() {
|
||||
actual val formatOptions by lazy {
|
||||
listOf(
|
||||
"",
|
||||
"MM/dd/yy",
|
||||
"dd/MM/yy",
|
||||
"yyyy-MM-dd",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
actual val dateTimeFormat: (Instant) -> String by lazy {
|
||||
NSDateFormatter()
|
||||
.apply {
|
||||
setDateStyle(NSDateFormatterShortStyle)
|
||||
setTimeStyle(NSDateFormatterShortStyle)
|
||||
setLocale(Locale.current.toPlatform())
|
||||
}
|
||||
.let { formatter ->
|
||||
actual fun getDateFormat(format: String): (Instant) -> String =
|
||||
when (format) {
|
||||
"" -> NSDateFormatter()
|
||||
.apply {
|
||||
setDateStyle(NSDateFormatterShortStyle)
|
||||
setTimeStyle(NSDateFormatterNoStyle)
|
||||
setLocale(Locale.current.toPlatform())
|
||||
}
|
||||
else -> NSDateFormatter()
|
||||
.apply {
|
||||
setDateFormat(format)
|
||||
}
|
||||
}.let { formatter ->
|
||||
{
|
||||
formatter.stringFromDate(it.toNSDate())
|
||||
}
|
||||
}
|
||||
|
||||
actual val dateTimeFormat: (Instant) -> String by lazy {
|
||||
NSDateFormatter()
|
||||
.apply {
|
||||
setDateStyle(NSDateFormatterShortStyle)
|
||||
setTimeStyle(NSDateFormatterShortStyle)
|
||||
setLocale(Locale.current.toPlatform())
|
||||
}
|
||||
.let { formatter ->
|
||||
{
|
||||
formatter.stringFromDate(it.toNSDate())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,37 +15,40 @@ import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
|
||||
actual class DateHandler @Inject constructor() {
|
||||
actual val formatOptions by lazy {
|
||||
listOf(
|
||||
"",
|
||||
"MM/dd/yy",
|
||||
"dd/MM/yy",
|
||||
"yyyy-MM-dd",
|
||||
)
|
||||
}
|
||||
|
||||
actual fun getDateFormat(format: String): (Instant) -> String = when (format) {
|
||||
"" -> DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
|
||||
.withLocale(Locale.current.toPlatform())
|
||||
.withZone(ZoneId.systemDefault())
|
||||
else -> DateTimeFormatter.ofPattern(format)
|
||||
.withZone(ZoneId.systemDefault())
|
||||
}.let { formatter ->
|
||||
{
|
||||
formatter.format(it.toJavaInstant())
|
||||
actual class DateHandler
|
||||
@Inject
|
||||
constructor() {
|
||||
actual val formatOptions by lazy {
|
||||
listOf(
|
||||
"",
|
||||
"MM/dd/yy",
|
||||
"dd/MM/yy",
|
||||
"yyyy-MM-dd",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
actual val dateTimeFormat: (Instant) -> String by lazy {
|
||||
DateTimeFormatter
|
||||
.ofLocalizedDateTime(FormatStyle.SHORT)
|
||||
.withLocale(Locale.current.toPlatform())
|
||||
.withZone(ZoneId.systemDefault())
|
||||
.let { formatter ->
|
||||
actual fun getDateFormat(format: String): (Instant) -> String =
|
||||
when (format) {
|
||||
"" -> DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
|
||||
.withLocale(Locale.current.toPlatform())
|
||||
.withZone(ZoneId.systemDefault())
|
||||
else -> DateTimeFormatter.ofPattern(format)
|
||||
.withZone(ZoneId.systemDefault())
|
||||
}.let { formatter ->
|
||||
{
|
||||
formatter.format(it.toJavaInstant())
|
||||
}
|
||||
}
|
||||
|
||||
actual val dateTimeFormat: (Instant) -> String by lazy {
|
||||
DateTimeFormatter
|
||||
.ofLocalizedDateTime(FormatStyle.SHORT)
|
||||
.withLocale(Locale.current.toPlatform())
|
||||
.withZone(ZoneId.systemDefault())
|
||||
.let { formatter ->
|
||||
{
|
||||
formatter.format(it.toJavaInstant())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ abstract class AppComponent(
|
||||
@get:Provides
|
||||
val context: ContextWrapper,
|
||||
) : ViewModelComponent, DataComponent, DomainComponent, UiComponent {
|
||||
|
||||
abstract val appMigrations: AppMigrations
|
||||
|
||||
@get:AppScope
|
||||
@@ -35,7 +34,8 @@ abstract class AppComponent(
|
||||
companion object {
|
||||
private var appComponentInstance: AppComponent? = null
|
||||
|
||||
fun getInstance(context: ContextWrapper) = appComponentInstance ?: create(context)
|
||||
.also { appComponentInstance = it }
|
||||
fun getInstance(context: ContextWrapper) =
|
||||
appComponentInstance ?: create(context)
|
||||
.also { appComponentInstance = it }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,22 +11,23 @@ import ca.gosyer.jui.domain.migration.service.MigrationPreferences
|
||||
import ca.gosyer.jui.uicore.vm.ContextWrapper
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
|
||||
class AppMigrations @Inject constructor(
|
||||
private val migrationPreferences: MigrationPreferences,
|
||||
private val contextWrapper: ContextWrapper,
|
||||
) {
|
||||
class AppMigrations
|
||||
@Inject
|
||||
constructor(
|
||||
private val migrationPreferences: MigrationPreferences,
|
||||
private val contextWrapper: ContextWrapper,
|
||||
) {
|
||||
fun runMigrations(): Boolean {
|
||||
val oldVersion = migrationPreferences.appVersion().get()
|
||||
if (oldVersion < BuildConfig.MIGRATION_CODE) {
|
||||
migrationPreferences.appVersion().set(BuildConfig.MIGRATION_CODE)
|
||||
|
||||
fun runMigrations(): Boolean {
|
||||
val oldVersion = migrationPreferences.appVersion().get()
|
||||
if (oldVersion < BuildConfig.MIGRATION_CODE) {
|
||||
migrationPreferences.appVersion().set(BuildConfig.MIGRATION_CODE)
|
||||
|
||||
// Fresh install
|
||||
if (oldVersion == 0) {
|
||||
return false
|
||||
// Fresh install
|
||||
if (oldVersion == 0) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return true
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,32 +12,46 @@ import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class Slf4jLogFactory : LogFactory {
|
||||
|
||||
override fun createKmLog(tag: String, className: String): KmLog {
|
||||
override fun createKmLog(
|
||||
tag: String,
|
||||
className: String,
|
||||
): KmLog {
|
||||
return Slf4jLog(tag)
|
||||
}
|
||||
}
|
||||
|
||||
class Slf4jLog(tag: String) : KmLog(tag) {
|
||||
|
||||
private val logger: Logger = LoggerFactory.getLogger(tag)
|
||||
|
||||
override fun verbose(tag: String, msg: String) {
|
||||
override fun verbose(
|
||||
tag: String,
|
||||
msg: String,
|
||||
) {
|
||||
super.verbose(tag, msg)
|
||||
logger.trace(msg)
|
||||
}
|
||||
|
||||
override fun debug(tag: String, msg: String) {
|
||||
override fun debug(
|
||||
tag: String,
|
||||
msg: String,
|
||||
) {
|
||||
super.debug(tag, msg)
|
||||
logger.debug(msg)
|
||||
}
|
||||
|
||||
override fun info(tag: String, msg: String) {
|
||||
override fun info(
|
||||
tag: String,
|
||||
msg: String,
|
||||
) {
|
||||
super.info(tag, msg)
|
||||
logger.info(msg)
|
||||
}
|
||||
|
||||
override fun warn(tag: String, msg: String, t: Throwable?) {
|
||||
override fun warn(
|
||||
tag: String,
|
||||
msg: String,
|
||||
t: Throwable?,
|
||||
) {
|
||||
super.warn(tag, msg, t)
|
||||
if (t != null) {
|
||||
logger.warn(msg, t)
|
||||
@@ -46,7 +60,11 @@ class Slf4jLog(tag: String) : KmLog(tag) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun error(tag: String, msg: String, t: Throwable?) {
|
||||
override fun error(
|
||||
tag: String,
|
||||
msg: String,
|
||||
t: Throwable?,
|
||||
) {
|
||||
super.error(tag, msg, t)
|
||||
if (t != null) {
|
||||
logger.error(msg, t)
|
||||
|
||||
@@ -253,7 +253,10 @@ suspend fun main() {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ToastOverlay(modifier: Modifier, context: ContextWrapper) {
|
||||
fun ToastOverlay(
|
||||
modifier: Modifier,
|
||||
context: ContextWrapper,
|
||||
) {
|
||||
var toast by remember { mutableStateOf<Pair<String, Length>?>(null) }
|
||||
LaunchedEffect(Unit) {
|
||||
context.toasts
|
||||
|
||||
@@ -23,36 +23,40 @@ import kotlinx.coroutines.launch
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ServerListeners @Inject constructor() {
|
||||
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||
class ServerListeners
|
||||
@Inject
|
||||
constructor() {
|
||||
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||
|
||||
private fun <T> Flow<T>.startWith(value: T) = onStart { emit(value) }
|
||||
private fun <T> Flow<T>.startWith(value: T) = onStart { emit(value) }
|
||||
|
||||
private val _mangaListener = MutableSharedFlow<List<Long>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val mangaListener = _mangaListener.asSharedFlow()
|
||||
private val _mangaListener = MutableSharedFlow<List<Long>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val mangaListener = _mangaListener.asSharedFlow()
|
||||
|
||||
private val _chapterIndexesListener = MutableSharedFlow<Pair<Long, List<Int>?>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val chapterIndexesListener = _chapterIndexesListener.asSharedFlow()
|
||||
private val _chapterIndexesListener = MutableSharedFlow<Pair<Long, List<Int>?>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val chapterIndexesListener = _chapterIndexesListener.asSharedFlow()
|
||||
|
||||
private val _chapterIdsListener = MutableSharedFlow<Pair<Long?, List<Long>>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val chapterIdsListener = _chapterIdsListener.asSharedFlow()
|
||||
private val _chapterIdsListener = MutableSharedFlow<Pair<Long?, List<Long>>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val chapterIdsListener = _chapterIdsListener.asSharedFlow()
|
||||
|
||||
private val categoryMangaListener = MutableSharedFlow<Long>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
private val categoryMangaListener = MutableSharedFlow<Long>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
|
||||
private val extensionListener = MutableSharedFlow<List<String>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
private val extensionListener = MutableSharedFlow<List<String>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
|
||||
fun <T> combineMangaUpdates(flow: Flow<T>, predate: (suspend (List<Long>) -> Boolean)? = null) =
|
||||
if (predate != null) {
|
||||
fun <T> combineMangaUpdates(
|
||||
flow: Flow<T>,
|
||||
predate: (suspend (List<Long>) -> Boolean)? = null,
|
||||
) = if (predate != null) {
|
||||
_mangaListener
|
||||
.filter(predate)
|
||||
.startWith(Unit)
|
||||
@@ -62,14 +66,16 @@ class ServerListeners @Inject constructor() {
|
||||
.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
.flatMapLatest { flow }
|
||||
|
||||
fun updateManga(vararg ids: Long) {
|
||||
scope.launch {
|
||||
_mangaListener.emit(ids.toList())
|
||||
fun updateManga(vararg ids: Long) {
|
||||
scope.launch {
|
||||
_mangaListener.emit(ids.toList())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> combineCategoryManga(flow: Flow<T>, predate: (suspend (Long) -> Boolean)? = null) =
|
||||
if (predate != null) {
|
||||
fun <T> combineCategoryManga(
|
||||
flow: Flow<T>,
|
||||
predate: (suspend (Long) -> Boolean)? = null,
|
||||
) = if (predate != null) {
|
||||
categoryMangaListener.filter(predate).startWith(-1)
|
||||
} else {
|
||||
categoryMangaListener.startWith(-1)
|
||||
@@ -77,58 +83,70 @@ class ServerListeners @Inject constructor() {
|
||||
.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
.flatMapLatest { flow }
|
||||
|
||||
fun updateCategoryManga(id: Long) {
|
||||
scope.launch {
|
||||
categoryMangaListener.emit(id)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> combineChapters(
|
||||
flow: Flow<T>,
|
||||
indexPredate: (suspend (Long, List<Int>?) -> Boolean)? = null,
|
||||
idPredate: (suspend (Long?, List<Long>) -> Boolean)? = null,
|
||||
): Flow<T> {
|
||||
val indexListener = if (indexPredate != null) {
|
||||
_chapterIndexesListener.filter { indexPredate(it.first, it.second) }.startWith(Unit)
|
||||
} else {
|
||||
_chapterIndexesListener.startWith(Unit)
|
||||
}
|
||||
val idsListener = if (idPredate != null) {
|
||||
_chapterIdsListener.filter { idPredate(it.first, it.second) }.startWith(Unit)
|
||||
} else {
|
||||
_chapterIdsListener.startWith(Unit)
|
||||
fun updateCategoryManga(id: Long) {
|
||||
scope.launch {
|
||||
categoryMangaListener.emit(id)
|
||||
}
|
||||
}
|
||||
|
||||
return combine(indexListener, idsListener) { _, _ -> }
|
||||
.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
.flatMapLatest { flow }
|
||||
}
|
||||
fun <T> combineChapters(
|
||||
flow: Flow<T>,
|
||||
indexPredate: (suspend (Long, List<Int>?) -> Boolean)? = null,
|
||||
idPredate: (suspend (Long?, List<Long>) -> Boolean)? = null,
|
||||
): Flow<T> {
|
||||
val indexListener = if (indexPredate != null) {
|
||||
_chapterIndexesListener.filter { indexPredate(it.first, it.second) }.startWith(Unit)
|
||||
} else {
|
||||
_chapterIndexesListener.startWith(Unit)
|
||||
}
|
||||
val idsListener = if (idPredate != null) {
|
||||
_chapterIdsListener.filter { idPredate(it.first, it.second) }.startWith(Unit)
|
||||
} else {
|
||||
_chapterIdsListener.startWith(Unit)
|
||||
}
|
||||
|
||||
fun updateChapters(mangaId: Long, chapterIndexes: List<Int>) {
|
||||
scope.launch {
|
||||
_chapterIndexesListener.emit(mangaId to chapterIndexes.ifEmpty { null })
|
||||
return combine(indexListener, idsListener) { _, _ -> }
|
||||
.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
.flatMapLatest { flow }
|
||||
}
|
||||
|
||||
fun updateChapters(
|
||||
mangaId: Long,
|
||||
chapterIndexes: List<Int>,
|
||||
) {
|
||||
scope.launch {
|
||||
_chapterIndexesListener.emit(mangaId to chapterIndexes.ifEmpty { null })
|
||||
}
|
||||
}
|
||||
|
||||
fun updateChapters(
|
||||
mangaId: Long,
|
||||
vararg chapterIndexes: Int,
|
||||
) {
|
||||
scope.launch {
|
||||
_chapterIndexesListener.emit(mangaId to chapterIndexes.toList().ifEmpty { null })
|
||||
}
|
||||
}
|
||||
|
||||
fun updateChapters(
|
||||
mangaId: Long?,
|
||||
chapterIds: List<Long>,
|
||||
) {
|
||||
scope.launch {
|
||||
_chapterIdsListener.emit(mangaId to chapterIds)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateChapters(
|
||||
mangaId: Long?,
|
||||
vararg chapterIds: Long,
|
||||
) {
|
||||
scope.launch {
|
||||
_chapterIdsListener.emit(mangaId to chapterIds.toList())
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
fun updateChapters(mangaId: Long, vararg chapterIndexes: Int) {
|
||||
scope.launch {
|
||||
_chapterIndexesListener.emit(mangaId to chapterIndexes.toList().ifEmpty { null })
|
||||
}
|
||||
}
|
||||
|
||||
fun updateChapters(mangaId: Long?, chapterIds: List<Long>) {
|
||||
scope.launch {
|
||||
_chapterIdsListener.emit(mangaId to chapterIds)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateChapters(mangaId: Long?, vararg chapterIds: Long) {
|
||||
scope.launch {
|
||||
_chapterIdsListener.emit(mangaId to chapterIds.toList())
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,8 +60,10 @@ interface SharedDomainComponent : CoreComponent {
|
||||
|
||||
@AppScope
|
||||
@Provides
|
||||
fun httpFactory(serverPreferences: ServerPreferences, json: Json) =
|
||||
httpClient(serverPreferences, json)
|
||||
fun httpFactory(
|
||||
serverPreferences: ServerPreferences,
|
||||
json: Json,
|
||||
) = httpClient(serverPreferences, json)
|
||||
|
||||
@get:AppScope
|
||||
@get:Provides
|
||||
|
||||
@@ -13,19 +13,22 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ExportBackupFile @Inject constructor(private val backupRepository: BackupRepository) {
|
||||
class ExportBackupFile
|
||||
@Inject
|
||||
constructor(private val backupRepository: BackupRepository) {
|
||||
suspend fun await(
|
||||
block: HttpRequestBuilder.() -> Unit = {},
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to export backup" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(block: HttpRequestBuilder.() -> Unit = {}, onError: suspend (Throwable) -> Unit = {}) = asFlow(block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to export backup" }
|
||||
fun asFlow(block: HttpRequestBuilder.() -> Unit = {}) = backupRepository.exportBackupFile(block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(block: HttpRequestBuilder.() -> Unit = {}) =
|
||||
backupRepository.exportBackupFile(block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,19 +14,26 @@ import me.tatarka.inject.annotations.Inject
|
||||
import okio.Path
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ImportBackupFile @Inject constructor(private val backupRepository: BackupRepository) {
|
||||
class ImportBackupFile
|
||||
@Inject
|
||||
constructor(private val backupRepository: BackupRepository) {
|
||||
suspend fun await(
|
||||
file: Path,
|
||||
block: HttpRequestBuilder.() -> Unit = {},
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(file, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to import backup ${file.name}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(file: Path, block: HttpRequestBuilder.() -> Unit = {}, onError: suspend (Throwable) -> Unit = {}) = asFlow(file, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to import backup ${file.name}" }
|
||||
fun asFlow(
|
||||
file: Path,
|
||||
block: HttpRequestBuilder.() -> Unit = {},
|
||||
) = backupRepository.importBackupFile(BackupRepository.buildBackupFormData(file), block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(file: Path, block: HttpRequestBuilder.() -> Unit = {}) =
|
||||
backupRepository.importBackupFile(BackupRepository.buildBackupFormData(file), block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,19 +14,26 @@ import me.tatarka.inject.annotations.Inject
|
||||
import okio.Path
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ValidateBackupFile @Inject constructor(private val backupRepository: BackupRepository) {
|
||||
class ValidateBackupFile
|
||||
@Inject
|
||||
constructor(private val backupRepository: BackupRepository) {
|
||||
suspend fun await(
|
||||
file: Path,
|
||||
block: HttpRequestBuilder.() -> Unit = {},
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(file, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to validate backup ${file.name}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(file: Path, block: HttpRequestBuilder.() -> Unit = {}, onError: suspend (Throwable) -> Unit = {}) = asFlow(file, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to validate backup ${file.name}" }
|
||||
fun asFlow(
|
||||
file: Path,
|
||||
block: HttpRequestBuilder.() -> Unit = {},
|
||||
) = backupRepository.validateBackupFile(BackupRepository.buildBackupFormData(file), block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(file: Path, block: HttpRequestBuilder.() -> Unit = {}) =
|
||||
backupRepository.validateBackupFile(BackupRepository.buildBackupFormData(file), block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import okio.Path
|
||||
import okio.buffer
|
||||
|
||||
interface BackupRepository {
|
||||
|
||||
@Multipart
|
||||
@POST("api/v1/backup/import/file")
|
||||
fun importBackupFile(
|
||||
@@ -47,15 +46,16 @@ interface BackupRepository {
|
||||
): Flow<HttpResponse>
|
||||
|
||||
companion object {
|
||||
fun buildBackupFormData(file: Path) = formData {
|
||||
append(
|
||||
"backup.proto.gz",
|
||||
FileSystem.SYSTEM.source(file).buffer().readByteArray(),
|
||||
Headers.build {
|
||||
append(HttpHeaders.ContentType, ContentType.MultiPart.FormData.toString())
|
||||
append(HttpHeaders.ContentDisposition, "filename=backup.proto.gz")
|
||||
},
|
||||
)
|
||||
}
|
||||
fun buildBackupFormData(file: Path) =
|
||||
formData {
|
||||
append(
|
||||
"backup.proto.gz",
|
||||
FileSystem.SYSTEM.source(file).buffer().readByteArray(),
|
||||
Headers.build {
|
||||
append(HttpHeaders.ContentType, ContentType.MultiPart.FormData.toString())
|
||||
append(HttpHeaders.ContentDisposition, "filename=backup.proto.gz")
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,46 +17,61 @@ import kotlinx.coroutines.flow.map
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class AddMangaToCategory @Inject constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class AddMangaToCategory
|
||||
@Inject
|
||||
constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add $mangaId to category $categoryId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(mangaId: Long, categoryId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId, categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add $mangaId to category $categoryId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add ${manga.title}(${manga.id}) to category ${category.name}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
categoryId: Long,
|
||||
) = if (categoryId != 0L) {
|
||||
categoryRepository.addMangaToCategory(mangaId, categoryId)
|
||||
.map { serverListeners.updateCategoryManga(categoryId) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(categoryId)
|
||||
emit(Unit)
|
||||
}
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(manga: Manga, category: Category, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga, category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add ${manga.title}(${manga.id}) to category ${category.name}" }
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
category: Category,
|
||||
) = if (category.id != 0L) {
|
||||
categoryRepository.addMangaToCategory(manga.id, category.id)
|
||||
.map { serverListeners.updateCategoryManga(category.id) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(category.id)
|
||||
emit(Unit)
|
||||
}
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(mangaId: Long, categoryId: Long) = if (categoryId != 0L) {
|
||||
categoryRepository.addMangaToCategory(mangaId, categoryId)
|
||||
.map { serverListeners.updateCategoryManga(categoryId) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(categoryId)
|
||||
emit(Unit)
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
fun asFlow(manga: Manga, category: Category) = if (category.id != 0L) {
|
||||
categoryRepository.addMangaToCategory(manga.id, category.id)
|
||||
.map { serverListeners.updateCategoryManga(category.id) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(category.id)
|
||||
emit(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,18 +12,22 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class CreateCategory @Inject constructor(private val categoryRepository: CategoryRepository) {
|
||||
class CreateCategory
|
||||
@Inject
|
||||
constructor(private val categoryRepository: CategoryRepository) {
|
||||
suspend fun await(
|
||||
name: String,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(name)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to create category $name" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(name: String, onError: suspend (Throwable) -> Unit = {}) = asFlow(name)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to create category $name" }
|
||||
fun asFlow(name: String) = categoryRepository.createCategory(name)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(name: String) = categoryRepository.createCategory(name)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,27 +13,34 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class DeleteCategory @Inject constructor(private val categoryRepository: CategoryRepository) {
|
||||
class DeleteCategory
|
||||
@Inject
|
||||
constructor(private val categoryRepository: CategoryRepository) {
|
||||
suspend fun await(
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete category $categoryId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(categoryId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete category $categoryId" }
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete category ${category.name}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(categoryId: Long) = categoryRepository.deleteCategory(categoryId)
|
||||
|
||||
fun asFlow(category: Category) = categoryRepository.deleteCategory(category.id)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(category: Category, onError: suspend (Throwable) -> Unit = {}) = asFlow(category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete category ${category.name}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(categoryId: Long) = categoryRepository.deleteCategory(categoryId)
|
||||
|
||||
fun asFlow(category: Category) = categoryRepository.deleteCategory(category.id)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,25 +13,30 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetCategories @Inject constructor(private val categoryRepository: CategoryRepository) {
|
||||
|
||||
suspend fun await(dropDefault: Boolean = false, onError: suspend (Throwable) -> Unit = {}) = asFlow(dropDefault)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get categories" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(dropDefault: Boolean = false) = categoryRepository.getCategories()
|
||||
.map { categories ->
|
||||
if (dropDefault) {
|
||||
categories.filterNot { it.name.equals("default", true) }
|
||||
} else {
|
||||
categories
|
||||
class GetCategories
|
||||
@Inject
|
||||
constructor(private val categoryRepository: CategoryRepository) {
|
||||
suspend fun await(
|
||||
dropDefault: Boolean = false,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(dropDefault)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get categories" }
|
||||
}
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
fun asFlow(dropDefault: Boolean = false) =
|
||||
categoryRepository.getCategories()
|
||||
.map { categories ->
|
||||
if (dropDefault) {
|
||||
categories.filterNot { it.name.equals("default", true) }
|
||||
} else {
|
||||
categories
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,27 +13,34 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetMangaCategories @Inject constructor(private val categoryRepository: CategoryRepository) {
|
||||
class GetMangaCategories
|
||||
@Inject
|
||||
constructor(private val categoryRepository: CategoryRepository) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get categories for $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get categories for $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get categories for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = categoryRepository.getMangaCategories(mangaId)
|
||||
|
||||
fun asFlow(manga: Manga) = categoryRepository.getMangaCategories(manga.id)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(manga: Manga, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get categories for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = categoryRepository.getMangaCategories(mangaId)
|
||||
|
||||
fun asFlow(manga: Manga) = categoryRepository.getMangaCategories(manga.id)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,36 +15,45 @@ import kotlinx.coroutines.flow.take
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetMangaListFromCategory @Inject constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class GetMangaListFromCategory
|
||||
@Inject
|
||||
constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(categoryId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga list from category $categoryId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(categoryId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(categoryId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga list from category $categoryId" }
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(category)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga list from category ${category.name}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(categoryId: Long) =
|
||||
serverListeners.combineCategoryManga(
|
||||
categoryRepository.getMangaFromCategory(categoryId),
|
||||
) { categoryId == it }
|
||||
|
||||
fun asFlow(category: Category) =
|
||||
serverListeners.combineCategoryManga(
|
||||
categoryRepository.getMangaFromCategory(category.id),
|
||||
) { category.id == it }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(category: Category, onError: suspend (Throwable) -> Unit = {}) = asFlow(category)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga list from category ${category.name}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(categoryId: Long) = serverListeners.combineCategoryManga(
|
||||
categoryRepository.getMangaFromCategory(categoryId),
|
||||
) { categoryId == it }
|
||||
|
||||
fun asFlow(category: Category) = serverListeners.combineCategoryManga(
|
||||
categoryRepository.getMangaFromCategory(category.id),
|
||||
) { category.id == it }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,35 +13,50 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ModifyCategory @Inject constructor(private val categoryRepository: CategoryRepository) {
|
||||
class ModifyCategory
|
||||
@Inject
|
||||
constructor(private val categoryRepository: CategoryRepository) {
|
||||
suspend fun await(
|
||||
categoryId: Long,
|
||||
name: String,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(
|
||||
categoryId = categoryId,
|
||||
name = name,
|
||||
).catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to modify category $categoryId with options: name=$name" }
|
||||
}.collect()
|
||||
|
||||
suspend fun await(categoryId: Long, name: String, onError: suspend (Throwable) -> Unit = {}) = asFlow(
|
||||
categoryId = categoryId,
|
||||
name = name,
|
||||
).catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to modify category $categoryId with options: name=$name" }
|
||||
}.collect()
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
name: String? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(
|
||||
category = category,
|
||||
name = name,
|
||||
).catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to modify category ${category.name} with options: name=$name" }
|
||||
}.collect()
|
||||
|
||||
suspend fun await(category: Category, name: String? = null, onError: suspend (Throwable) -> Unit = {}) = asFlow(
|
||||
category = category,
|
||||
name = name,
|
||||
).catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to modify category ${category.name} with options: name=$name" }
|
||||
}.collect()
|
||||
fun asFlow(
|
||||
categoryId: Long,
|
||||
name: String,
|
||||
) = categoryRepository.modifyCategory(
|
||||
categoryId = categoryId,
|
||||
name = name,
|
||||
)
|
||||
|
||||
fun asFlow(categoryId: Long, name: String) = categoryRepository.modifyCategory(
|
||||
categoryId = categoryId,
|
||||
name = name,
|
||||
)
|
||||
fun asFlow(
|
||||
category: Category,
|
||||
name: String? = null,
|
||||
) = categoryRepository.modifyCategory(
|
||||
categoryId = category.id,
|
||||
name = name ?: category.name,
|
||||
)
|
||||
|
||||
fun asFlow(category: Category, name: String? = null) = categoryRepository.modifyCategory(
|
||||
categoryId = category.id,
|
||||
name = name ?: category.name,
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,46 +17,61 @@ import kotlinx.coroutines.flow.map
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class RemoveMangaFromCategory @Inject constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class RemoveMangaFromCategory
|
||||
@Inject
|
||||
constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove $mangaId from category $categoryId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(mangaId: Long, categoryId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId, categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove $mangaId from category $categoryId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove ${manga.title}(${manga.id}) from category ${category.name}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
categoryId: Long,
|
||||
) = if (categoryId != 0L) {
|
||||
categoryRepository.removeMangaFromCategory(mangaId, categoryId)
|
||||
.map { serverListeners.updateCategoryManga(categoryId) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(categoryId)
|
||||
emit(Unit)
|
||||
}
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(manga: Manga, category: Category, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga, category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove ${manga.title}(${manga.id}) from category ${category.name}" }
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
category: Category,
|
||||
) = if (category.id != 0L) {
|
||||
categoryRepository.removeMangaFromCategory(manga.id, category.id)
|
||||
.map { serverListeners.updateCategoryManga(category.id) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(category.id)
|
||||
emit(Unit)
|
||||
}
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(mangaId: Long, categoryId: Long) = if (categoryId != 0L) {
|
||||
categoryRepository.removeMangaFromCategory(mangaId, categoryId)
|
||||
.map { serverListeners.updateCategoryManga(categoryId) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(categoryId)
|
||||
emit(Unit)
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
fun asFlow(manga: Manga, category: Category) = if (category.id != 0L) {
|
||||
categoryRepository.removeMangaFromCategory(manga.id, category.id)
|
||||
.map { serverListeners.updateCategoryManga(category.id) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(category.id)
|
||||
emit(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,18 +12,26 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ReorderCategory @Inject constructor(private val categoryRepository: CategoryRepository) {
|
||||
class ReorderCategory
|
||||
@Inject
|
||||
constructor(private val categoryRepository: CategoryRepository) {
|
||||
suspend fun await(
|
||||
to: Int,
|
||||
from: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(to, from)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to move category from $from to $to" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(to: Int, from: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(to, from)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to move category from $from to $to" }
|
||||
fun asFlow(
|
||||
to: Int,
|
||||
from: Int,
|
||||
) = categoryRepository.reorderCategory(to, from)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(to: Int, from: Int) = categoryRepository.reorderCategory(to, from)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,34 +14,35 @@ import kotlinx.coroutines.flow.flow
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateCategoryMeta @Inject constructor(private val categoryRepository: CategoryRepository) {
|
||||
class UpdateCategoryMeta
|
||||
@Inject
|
||||
constructor(private val categoryRepository: CategoryRepository) {
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
example: Int = category.meta.example,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(category, example)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update ${category.name}(${category.id}) meta" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
example: Int = category.meta.example,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(category, example)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update ${category.name}(${category.id}) meta" }
|
||||
fun asFlow(
|
||||
category: Category,
|
||||
example: Int = category.meta.example,
|
||||
) = flow {
|
||||
if (example != category.meta.example) {
|
||||
categoryRepository.updateCategoryMeta(
|
||||
category.id,
|
||||
"example",
|
||||
example.toString(),
|
||||
).collect()
|
||||
}
|
||||
emit(Unit)
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
category: Category,
|
||||
example: Int = category.meta.example,
|
||||
) = flow {
|
||||
if (example != category.meta.example) {
|
||||
categoryRepository.updateCategoryMeta(
|
||||
category.id,
|
||||
"example",
|
||||
example.toString(),
|
||||
).collect()
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
emit(Unit)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,236 +20,237 @@ import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
import kotlin.jvm.JvmName
|
||||
|
||||
class BatchUpdateChapter @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class BatchUpdateChapter
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
@JvmName("awaitChapters")
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
chapters: List<Chapter>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, chapters, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update multiple chapters of $mangaId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
@JvmName("awaitChapters")
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
chapters: List<Chapter>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, chapters, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update multiple chapters of $mangaId" }
|
||||
}
|
||||
.collect()
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, chapterIds, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update multiple chapters of $mangaId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, chapterIds, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update multiple chapters of $mangaId" }
|
||||
}
|
||||
.collect()
|
||||
@JvmName("awaitChapters")
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
chapters: List<Chapter>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, chapters, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update multiple chapters of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
@JvmName("awaitChapters")
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
chapters: List<Chapter>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, chapters, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update multiple chapters of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, chapterIds, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update multiple chapters of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, chapterIds, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update multiple chapters of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
@JvmName("awaitChapters")
|
||||
suspend fun await(
|
||||
chapters: List<Chapter>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapters, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update multiple chapters" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
@JvmName("awaitChapters")
|
||||
suspend fun await(
|
||||
chapters: List<Chapter>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapters, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update multiple chapters" }
|
||||
}
|
||||
.collect()
|
||||
suspend fun await(
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterIds, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update update multiple chapters" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterIds, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update update multiple chapters" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
@JvmName("asFlowChapters")
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
chapters: List<Chapter>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = mangaId,
|
||||
chapterIds = chapters.map { it.id },
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = mangaId,
|
||||
chapterIds = chapterIds,
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
@JvmName("asFlowChapters")
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
chapters: List<Chapter>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = manga.id,
|
||||
chapterIds = chapters.map { it.id },
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = manga.id,
|
||||
chapterIds = chapterIds,
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
@JvmName("asFlowChapters")
|
||||
fun asFlow(
|
||||
chapters: List<Chapter>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = null,
|
||||
chapterIds = chapters.map { it.id },
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = null,
|
||||
chapterIds = chapterIds,
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
private fun getFlow(
|
||||
mangaId: Long?,
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = if (mangaId != null) {
|
||||
chapterRepository.batchUpdateChapter(
|
||||
mangaId,
|
||||
MangaChapterBatchEditInput(
|
||||
chapterIds = chapterIds,
|
||||
change = ChapterChange(
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
),
|
||||
),
|
||||
@JvmName("asFlowChapters")
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
chapters: List<Chapter>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = mangaId,
|
||||
chapterIds = chapters.map { it.id },
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
)
|
||||
} else {
|
||||
chapterRepository.batchUpdateChapter(
|
||||
ChapterBatchEditInput(
|
||||
chapterIds = chapterIds,
|
||||
change = ChapterChange(
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
),
|
||||
),
|
||||
)
|
||||
}.onEach {
|
||||
serverListeners.updateChapters(mangaId, chapterIds)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = mangaId,
|
||||
chapterIds = chapterIds,
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
@JvmName("asFlowChapters")
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
chapters: List<Chapter>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = manga.id,
|
||||
chapterIds = chapters.map { it.id },
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = manga.id,
|
||||
chapterIds = chapterIds,
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
@JvmName("asFlowChapters")
|
||||
fun asFlow(
|
||||
chapters: List<Chapter>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = null,
|
||||
chapterIds = chapters.map { it.id },
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = null,
|
||||
chapterIds = chapterIds,
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
private fun getFlow(
|
||||
mangaId: Long?,
|
||||
chapterIds: List<Long>,
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
) = if (mangaId != null) {
|
||||
chapterRepository.batchUpdateChapter(
|
||||
mangaId,
|
||||
MangaChapterBatchEditInput(
|
||||
chapterIds = chapterIds,
|
||||
change = ChapterChange(
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
chapterRepository.batchUpdateChapter(
|
||||
ChapterBatchEditInput(
|
||||
chapterIds = chapterIds,
|
||||
change = ChapterChange(
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete,
|
||||
),
|
||||
),
|
||||
)
|
||||
}.onEach {
|
||||
serverListeners.updateChapters(mangaId, chapterIds)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,42 +16,61 @@ import kotlinx.coroutines.flow.onEach
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class DeleteChapterDownload @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class DeleteChapterDownload
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for $index of $mangaId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(mangaId: Long, index: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for $index of $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for $index of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
) = chapterRepository.deleteChapterDownload(mangaId, index)
|
||||
.onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
) = chapterRepository.deleteChapterDownload(manga.id, index)
|
||||
.onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(chapter: Chapter) =
|
||||
chapterRepository.deleteChapterDownload(chapter.mangaId, chapter.index)
|
||||
.onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(manga: Manga, index: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for $index of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(chapter: Chapter, onError: suspend (Throwable) -> Unit = {}) = asFlow(chapter)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(mangaId: Long, index: Int) = chapterRepository.deleteChapterDownload(mangaId, index)
|
||||
.onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(manga: Manga, index: Int) = chapterRepository.deleteChapterDownload(manga.id, index)
|
||||
.onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(chapter: Chapter) = chapterRepository.deleteChapterDownload(chapter.mangaId, chapter.index)
|
||||
.onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,60 +16,79 @@ import kotlinx.coroutines.flow.take
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetChapter @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class GetChapter
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapter $index for $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(mangaId: Long, index: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId, index)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapter $index for $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapter $index for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapter ${chapter.index} for ${chapter.mangaId}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
) = serverListeners.combineChapters(
|
||||
chapterRepository.getChapter(mangaId, index),
|
||||
indexPredate = { id, chapterIndexes ->
|
||||
id == mangaId && (chapterIndexes == null || index in chapterIndexes)
|
||||
},
|
||||
idPredate = { id, _ -> id == mangaId },
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
) = serverListeners.combineChapters(
|
||||
chapterRepository.getChapter(manga.id, index),
|
||||
indexPredate = { id, chapterIndexes ->
|
||||
id == manga.id && (chapterIndexes == null || index in chapterIndexes)
|
||||
},
|
||||
idPredate = { id, _ -> id == manga.id },
|
||||
)
|
||||
|
||||
fun asFlow(chapter: Chapter) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapter(chapter.mangaId, chapter.index),
|
||||
indexPredate = { id, chapterIndexes ->
|
||||
id == chapter.mangaId && (chapterIndexes == null || chapter.index in chapterIndexes)
|
||||
},
|
||||
idPredate = { id, _ -> id == chapter.mangaId },
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(manga: Manga, index: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga, index)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapter $index for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(chapter: Chapter, onError: suspend (Throwable) -> Unit = {}) = asFlow(chapter)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapter ${chapter.index} for ${chapter.mangaId}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long, index: Int) = serverListeners.combineChapters(
|
||||
chapterRepository.getChapter(mangaId, index),
|
||||
indexPredate = { id, chapterIndexes ->
|
||||
id == mangaId && (chapterIndexes == null || index in chapterIndexes)
|
||||
},
|
||||
idPredate = { id, _ -> id == mangaId },
|
||||
)
|
||||
|
||||
fun asFlow(manga: Manga, index: Int) = serverListeners.combineChapters(
|
||||
chapterRepository.getChapter(manga.id, index),
|
||||
indexPredate = { id, chapterIndexes ->
|
||||
id == manga.id && (chapterIndexes == null || index in chapterIndexes)
|
||||
},
|
||||
idPredate = { id, _ -> id == manga.id },
|
||||
)
|
||||
|
||||
fun asFlow(chapter: Chapter) = serverListeners.combineChapters(
|
||||
chapterRepository.getChapter(chapter.mangaId, chapter.index),
|
||||
indexPredate = { id, chapterIndexes ->
|
||||
id == chapter.mangaId && (chapterIndexes == null || chapter.index in chapterIndexes)
|
||||
},
|
||||
idPredate = { id, _ -> id == chapter.mangaId },
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,67 +15,68 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetChapterPage @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
class GetChapterPage
|
||||
@Inject
|
||||
constructor(private val chapterRepository: ChapterRepository) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index, pageNum, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get page $pageNum for chapter $index for $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index, pageNum, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get page $pageNum for chapter $index for $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index, pageNum, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get page $pageNum for chapter $index for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, pageNum, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get page $pageNum for chapter ${chapter.index} for ${chapter.mangaId}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
) = chapterRepository.getPage(mangaId, index, pageNum, block)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
) = chapterRepository.getPage(manga.id, index, pageNum, block)
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
) = chapterRepository.getPage(chapter.mangaId, chapter.index, pageNum, block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index, pageNum, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get page $pageNum for chapter $index for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, pageNum, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get page $pageNum for chapter ${chapter.index} for ${chapter.mangaId}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
) = chapterRepository.getPage(mangaId, index, pageNum, block)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
) = chapterRepository.getPage(manga.id, index, pageNum, block)
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
) = chapterRepository.getPage(chapter.mangaId, chapter.index, pageNum, block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,40 +15,49 @@ import kotlinx.coroutines.flow.take
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetChapters @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class GetChapters
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapters for $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapters for $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapters for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapters(mangaId),
|
||||
indexPredate = { id, _ -> id == mangaId },
|
||||
idPredate = { id, _ -> id == mangaId },
|
||||
)
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapters(manga.id),
|
||||
indexPredate = { id, _ -> id == manga.id },
|
||||
idPredate = { id, _ -> id == manga.id },
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(manga: Manga, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapters for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = serverListeners.combineChapters(
|
||||
chapterRepository.getChapters(mangaId),
|
||||
indexPredate = { id, _ -> id == mangaId },
|
||||
idPredate = { id, _ -> id == mangaId },
|
||||
)
|
||||
|
||||
fun asFlow(manga: Manga) = serverListeners.combineChapters(
|
||||
chapterRepository.getChapters(manga.id),
|
||||
indexPredate = { id, _ -> id == manga.id },
|
||||
idPredate = { id, _ -> id == manga.id },
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,32 +15,41 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class RefreshChapters @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class RefreshChapters
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh chapters for $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh chapters for $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh chapters for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
chapterRepository.getChapters(mangaId, true)
|
||||
.onEach { serverListeners.updateChapters(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
chapterRepository.getChapters(manga.id, true)
|
||||
.onEach { serverListeners.updateChapters(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(manga: Manga, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh chapters for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = chapterRepository.getChapters(mangaId, true)
|
||||
.onEach { serverListeners.updateChapters(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) = chapterRepository.getChapters(manga.id, true)
|
||||
.onEach { serverListeners.updateChapters(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,76 +16,77 @@ import kotlinx.coroutines.flow.onEach
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterBookmarked @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class UpdateChapterBookmarked
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index, bookmarked)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapter $index of $mangaId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index, bookmarked)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapter $index of $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index, bookmarked)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapter $index of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
bookmarked: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, bookmarked)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
bookmarked = bookmarked,
|
||||
).onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
bookmarked = bookmarked,
|
||||
).onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
bookmarked: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
bookmarked = bookmarked,
|
||||
).onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index, bookmarked)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapter $index of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
bookmarked: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, bookmarked)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
bookmarked = bookmarked,
|
||||
).onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
bookmarked = bookmarked,
|
||||
).onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
bookmarked: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
bookmarked = bookmarked,
|
||||
).onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,76 +16,77 @@ import kotlinx.coroutines.flow.onEach
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterLastPageRead @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class UpdateChapterLastPageRead
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter last page read for chapter $index of $mangaId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter last page read for chapter $index of $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter last page read for chapter $index of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
lastPageRead: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter last page read for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter last page read for chapter $index of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
lastPageRead: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter last page read for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,70 +16,70 @@ import kotlinx.coroutines.flow.onEach
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterMarkPreviousRead @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class UpdateChapterMarkPreviousRead
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter $index of $mangaId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter $index of $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter $index of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
markPreviousRead = true,
|
||||
).onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
markPreviousRead = true,
|
||||
).onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(chapter: Chapter) =
|
||||
chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
markPreviousRead = true,
|
||||
).onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter $index of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
markPreviousRead = true,
|
||||
).onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
markPreviousRead = true,
|
||||
).onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
markPreviousRead = true,
|
||||
).onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,39 +15,40 @@ import kotlinx.coroutines.flow.flow
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterMeta @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class UpdateChapterMeta
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
pageOffset: Int = chapter.meta.juiPageOffset,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, pageOffset)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update ${chapter.name}(${chapter.index}) meta" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
pageOffset: Int = chapter.meta.juiPageOffset,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, pageOffset)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update ${chapter.name}(${chapter.index}) meta" }
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
pageOffset: Int = chapter.meta.juiPageOffset,
|
||||
) = flow {
|
||||
if (pageOffset != chapter.meta.juiPageOffset) {
|
||||
chapterRepository.updateChapterMeta(
|
||||
chapter.mangaId,
|
||||
chapter.index,
|
||||
"juiPageOffset",
|
||||
pageOffset.toString(),
|
||||
).collect()
|
||||
serverListeners.updateChapters(chapter.mangaId, chapter.index)
|
||||
}
|
||||
emit(Unit)
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
pageOffset: Int = chapter.meta.juiPageOffset,
|
||||
) = flow {
|
||||
if (pageOffset != chapter.meta.juiPageOffset) {
|
||||
chapterRepository.updateChapterMeta(
|
||||
chapter.mangaId,
|
||||
chapter.index,
|
||||
"juiPageOffset",
|
||||
pageOffset.toString(),
|
||||
).collect()
|
||||
serverListeners.updateChapters(chapter.mangaId, chapter.index)
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
emit(Unit)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,76 +16,77 @@ import kotlinx.coroutines.flow.onEach
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterRead @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class UpdateChapterRead
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index, read)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter $index of $mangaId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index, read)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter $index of $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index, read)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter $index of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
read: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, read)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index, read)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter $index of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
read: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, read)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import io.ktor.client.statement.HttpResponse
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ChapterRepository {
|
||||
|
||||
@GET("api/v1/manga/{mangaId}/chapters")
|
||||
fun getChapters(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
|
||||
@@ -13,27 +13,34 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class BatchChapterDownload @Inject constructor(private val downloadRepository: DownloadRepository) {
|
||||
class BatchChapterDownload
|
||||
@Inject
|
||||
constructor(private val downloadRepository: DownloadRepository) {
|
||||
suspend fun await(
|
||||
chapterIds: List<Long>,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterIds)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapters $chapterIds for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(chapterIds: List<Long>, onError: suspend (Throwable) -> Unit = {}) = asFlow(chapterIds)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapters $chapterIds for a download" }
|
||||
suspend fun await(
|
||||
vararg chapterIds: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(*chapterIds)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapters ${chapterIds.asList()} for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(chapterIds: List<Long>) = downloadRepository.batchDownload(DownloadEnqueue(chapterIds))
|
||||
|
||||
fun asFlow(vararg chapterIds: Long) = downloadRepository.batchDownload(DownloadEnqueue(chapterIds.asList()))
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(vararg chapterIds: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(*chapterIds)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapters ${chapterIds.asList()} for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(chapterIds: List<Long>) = downloadRepository.batchDownload(DownloadEnqueue(chapterIds))
|
||||
|
||||
fun asFlow(vararg chapterIds: Long) = downloadRepository.batchDownload(DownloadEnqueue(chapterIds.asList()))
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,18 +12,20 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ClearDownloadQueue @Inject constructor(private val downloadRepository: DownloadRepository) {
|
||||
class ClearDownloadQueue
|
||||
@Inject
|
||||
constructor(private val downloadRepository: DownloadRepository) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to clear download queue" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) = asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to clear download queue" }
|
||||
fun asFlow() = downloadRepository.clearDownloadQueue()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow() = downloadRepository.clearDownloadQueue()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,36 +14,54 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class QueueChapterDownload @Inject constructor(private val downloadRepository: DownloadRepository) {
|
||||
class QueueChapterDownload
|
||||
@Inject
|
||||
constructor(private val downloadRepository: DownloadRepository) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapter $index of $mangaId for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(mangaId: Long, index: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapter $index of $mangaId for a download" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapter $index of ${manga.title}(${manga.id}) for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapter ${chapter.index} of ${chapter.mangaId} for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
) = downloadRepository.queueChapterDownload(mangaId, index)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
) = downloadRepository.queueChapterDownload(manga.id, index)
|
||||
|
||||
fun asFlow(chapter: Chapter) = downloadRepository.queueChapterDownload(chapter.mangaId, chapter.index)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(manga: Manga, index: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapter $index of ${manga.title}(${manga.id}) for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(chapter: Chapter, onError: suspend (Throwable) -> Unit = {}) = asFlow(chapter)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapter ${chapter.index} of ${chapter.mangaId} for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(mangaId: Long, index: Int) = downloadRepository.queueChapterDownload(mangaId, index)
|
||||
|
||||
fun asFlow(manga: Manga, index: Int) = downloadRepository.queueChapterDownload(manga.id, index)
|
||||
|
||||
fun asFlow(chapter: Chapter) = downloadRepository.queueChapterDownload(chapter.mangaId, chapter.index)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,36 +14,62 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ReorderChapterDownload @Inject constructor(private val downloadRepository: DownloadRepository) {
|
||||
class ReorderChapterDownload
|
||||
@Inject
|
||||
constructor(private val downloadRepository: DownloadRepository) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
to: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index, to)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to reorder chapter download for $index of $mangaId to $to" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(mangaId: Long, index: Int, to: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId, index, to)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to reorder chapter download for $index of $mangaId to $to" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
to: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index, to)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to reorder chapter download for $index of ${manga.title}(${manga.id}) to $to" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
to: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, to)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to reorder chapter download for ${chapter.index} of ${chapter.mangaId} to $to" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
to: Int,
|
||||
) = downloadRepository.reorderChapterDownload(mangaId, index, to)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
to: Int,
|
||||
) = downloadRepository.reorderChapterDownload(manga.id, index, to)
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
to: Int,
|
||||
) = downloadRepository.reorderChapterDownload(chapter.mangaId, chapter.index, to)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(manga: Manga, index: Int, to: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga, index, to)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to reorder chapter download for $index of ${manga.title}(${manga.id}) to $to" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(chapter: Chapter, to: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(chapter, to)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to reorder chapter download for ${chapter.index} of ${chapter.mangaId} to $to" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(mangaId: Long, index: Int, to: Int) = downloadRepository.reorderChapterDownload(mangaId, index, to)
|
||||
|
||||
fun asFlow(manga: Manga, index: Int, to: Int) = downloadRepository.reorderChapterDownload(manga.id, index, to)
|
||||
|
||||
fun asFlow(chapter: Chapter, to: Int) = downloadRepository.reorderChapterDownload(chapter.mangaId, chapter.index, to)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,18 +12,20 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class StartDownloading @Inject constructor(private val downloadRepository: DownloadRepository) {
|
||||
class StartDownloading
|
||||
@Inject
|
||||
constructor(private val downloadRepository: DownloadRepository) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to start downloader" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) = asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to start downloader" }
|
||||
fun asFlow() = downloadRepository.startDownloading()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow() = downloadRepository.startDownloading()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,36 +14,54 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class StopChapterDownload @Inject constructor(private val downloadRepository: DownloadRepository) {
|
||||
class StopChapterDownload
|
||||
@Inject
|
||||
constructor(private val downloadRepository: DownloadRepository) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to stop chapter download for $index of $mangaId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(mangaId: Long, index: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to stop chapter download for $index of $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to stop chapter download for $index of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to stop chapter download for ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
) = downloadRepository.stopChapterDownload(mangaId, index)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
) = downloadRepository.stopChapterDownload(manga.id, index)
|
||||
|
||||
fun asFlow(chapter: Chapter) = downloadRepository.stopChapterDownload(chapter.mangaId, chapter.index)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(manga: Manga, index: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to stop chapter download for $index of ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(chapter: Chapter, onError: suspend (Throwable) -> Unit = {}) = asFlow(chapter)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to stop chapter download for ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(mangaId: Long, index: Int) = downloadRepository.stopChapterDownload(mangaId, index)
|
||||
|
||||
fun asFlow(manga: Manga, index: Int) = downloadRepository.stopChapterDownload(manga.id, index)
|
||||
|
||||
fun asFlow(chapter: Chapter) = downloadRepository.stopChapterDownload(chapter.mangaId, chapter.index)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,18 +12,20 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class StopDownloading @Inject constructor(private val downloadRepository: DownloadRepository) {
|
||||
class StopDownloading
|
||||
@Inject
|
||||
constructor(private val downloadRepository: DownloadRepository) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to stop downloader" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) = asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to stop downloader" }
|
||||
fun asFlow() = downloadRepository.stopDownloading()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow() = downloadRepository.stopDownloading()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,36 +19,38 @@ import kotlinx.coroutines.flow.map
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
|
||||
class DownloadService @Inject constructor(
|
||||
serverPreferences: ServerPreferences,
|
||||
client: Http,
|
||||
) : WebsocketService(serverPreferences, client) {
|
||||
override val _status: MutableStateFlow<Status>
|
||||
get() = status
|
||||
class DownloadService
|
||||
@Inject
|
||||
constructor(
|
||||
serverPreferences: ServerPreferences,
|
||||
client: Http,
|
||||
) : WebsocketService(serverPreferences, client) {
|
||||
override val _status: MutableStateFlow<Status>
|
||||
get() = status
|
||||
|
||||
override val query: String
|
||||
get() = "/api/v1/downloads"
|
||||
override val query: String
|
||||
get() = "/api/v1/downloads"
|
||||
|
||||
override suspend fun onReceived(frame: Frame.Text) {
|
||||
val status = json.decodeFromString<DownloadStatus>(frame.readText())
|
||||
downloaderStatus.value = status.status
|
||||
downloadQueue.value = status.queue
|
||||
override suspend fun onReceived(frame: Frame.Text) {
|
||||
val status = json.decodeFromString<DownloadStatus>(frame.readText())
|
||||
downloaderStatus.value = status.status
|
||||
downloadQueue.value = status.queue
|
||||
}
|
||||
|
||||
companion object {
|
||||
val status = MutableStateFlow(Status.STARTING)
|
||||
val downloadQueue = MutableStateFlow(emptyList<DownloadChapter>())
|
||||
val downloaderStatus = MutableStateFlow(DownloaderStatus.Stopped)
|
||||
|
||||
fun registerWatch(mangaId: Long) =
|
||||
downloadQueue
|
||||
.map {
|
||||
it.filter { it.mangaId == mangaId }
|
||||
}
|
||||
fun registerWatches(mangaIds: Set<Long>) =
|
||||
downloadQueue
|
||||
.map {
|
||||
it.filter { it.mangaId in mangaIds }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val status = MutableStateFlow(Status.STARTING)
|
||||
val downloadQueue = MutableStateFlow(emptyList<DownloadChapter>())
|
||||
val downloaderStatus = MutableStateFlow(DownloaderStatus.Stopped)
|
||||
|
||||
fun registerWatch(mangaId: Long) =
|
||||
downloadQueue
|
||||
.map {
|
||||
it.filter { it.mangaId == mangaId }
|
||||
}
|
||||
fun registerWatches(mangaIds: Set<Long>) =
|
||||
downloadQueue
|
||||
.map {
|
||||
it.filter { it.mangaId in mangaIds }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,18 +12,20 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetExtensionList @Inject constructor(private val extensionRepository: ExtensionRepository) {
|
||||
class GetExtensionList
|
||||
@Inject
|
||||
constructor(private val extensionRepository: ExtensionRepository) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get extension list" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) = asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get extension list" }
|
||||
fun asFlow() = extensionRepository.getExtensionList()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow() = extensionRepository.getExtensionList()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,18 +13,22 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class InstallExtension @Inject constructor(private val extensionRepository: ExtensionRepository) {
|
||||
class InstallExtension
|
||||
@Inject
|
||||
constructor(private val extensionRepository: ExtensionRepository) {
|
||||
suspend fun await(
|
||||
extension: Extension,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(extension)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to install extension ${extension.apkName}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(extension: Extension, onError: suspend (Throwable) -> Unit = {}) = asFlow(extension)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to install extension ${extension.apkName}" }
|
||||
fun asFlow(extension: Extension) = extensionRepository.installExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(extension: Extension) = extensionRepository.installExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,18 +13,22 @@ import me.tatarka.inject.annotations.Inject
|
||||
import okio.Path
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class InstallExtensionFile @Inject constructor(private val extensionRepository: ExtensionRepository) {
|
||||
class InstallExtensionFile
|
||||
@Inject
|
||||
constructor(private val extensionRepository: ExtensionRepository) {
|
||||
suspend fun await(
|
||||
path: Path,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(path)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to install extension from $path" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(path: Path, onError: suspend (Throwable) -> Unit = {}) = asFlow(path)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to install extension from $path" }
|
||||
fun asFlow(path: Path) = extensionRepository.installExtension(ExtensionRepository.buildExtensionFormData(path))
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(path: Path) = extensionRepository.installExtension(ExtensionRepository.buildExtensionFormData(path))
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,18 +13,22 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UninstallExtension @Inject constructor(private val extensionRepository: ExtensionRepository) {
|
||||
class UninstallExtension
|
||||
@Inject
|
||||
constructor(private val extensionRepository: ExtensionRepository) {
|
||||
suspend fun await(
|
||||
extension: Extension,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(extension)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to uninstall extension ${extension.apkName}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(extension: Extension, onError: suspend (Throwable) -> Unit = {}) = asFlow(extension)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to uninstall extension ${extension.apkName}" }
|
||||
fun asFlow(extension: Extension) = extensionRepository.uninstallExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(extension: Extension) = extensionRepository.uninstallExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,18 +13,22 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateExtension @Inject constructor(private val extensionRepository: ExtensionRepository) {
|
||||
class UpdateExtension
|
||||
@Inject
|
||||
constructor(private val extensionRepository: ExtensionRepository) {
|
||||
suspend fun await(
|
||||
extension: Extension,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(extension)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update extension ${extension.apkName}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(extension: Extension, onError: suspend (Throwable) -> Unit = {}) = asFlow(extension)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update extension ${extension.apkName}" }
|
||||
fun asFlow(extension: Extension) = extensionRepository.updateExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(extension: Extension) = extensionRepository.updateExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,15 +58,16 @@ interface ExtensionRepository {
|
||||
): Flow<ByteReadChannel>
|
||||
|
||||
companion object {
|
||||
fun buildExtensionFormData(file: okio.Path) = formData {
|
||||
append(
|
||||
"file",
|
||||
FileSystem.SYSTEM.source(file).buffer().readByteArray(),
|
||||
Headers.build {
|
||||
append(HttpHeaders.ContentType, ContentType.MultiPart.FormData.toString())
|
||||
append(HttpHeaders.ContentDisposition, "filename=file")
|
||||
},
|
||||
)
|
||||
}
|
||||
fun buildExtensionFormData(file: okio.Path) =
|
||||
formData {
|
||||
append(
|
||||
"file",
|
||||
FileSystem.SYSTEM.source(file).buffer().readByteArray(),
|
||||
Headers.build {
|
||||
append(HttpHeaders.ContentType, ContentType.MultiPart.FormData.toString())
|
||||
append(HttpHeaders.ContentDisposition, "filename=file")
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,18 +12,20 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetGlobalMeta @Inject constructor(private val globalRepository: GlobalRepository) {
|
||||
class GetGlobalMeta
|
||||
@Inject
|
||||
constructor(private val globalRepository: GlobalRepository) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get global meta" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) = asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get global meta" }
|
||||
fun asFlow() = globalRepository.getGlobalMeta()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow() = globalRepository.getGlobalMeta()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,33 +14,34 @@ import kotlinx.coroutines.flow.flow
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateGlobalMeta @Inject constructor(private val globalRepository: GlobalRepository) {
|
||||
class UpdateGlobalMeta
|
||||
@Inject
|
||||
constructor(private val globalRepository: GlobalRepository) {
|
||||
suspend fun await(
|
||||
globalMeta: GlobalMeta,
|
||||
example: Int = globalMeta.example,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(globalMeta, example)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update global meta" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
globalMeta: GlobalMeta,
|
||||
example: Int = globalMeta.example,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(globalMeta, example)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update global meta" }
|
||||
fun asFlow(
|
||||
globalMeta: GlobalMeta,
|
||||
example: Int = globalMeta.example,
|
||||
) = flow {
|
||||
if (example != globalMeta.example) {
|
||||
globalRepository.updateGlobalMeta(
|
||||
"example",
|
||||
example.toString(),
|
||||
).collect()
|
||||
}
|
||||
emit(Unit)
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
globalMeta: GlobalMeta,
|
||||
example: Int = globalMeta.example,
|
||||
) = flow {
|
||||
if (example != globalMeta.example) {
|
||||
globalRepository.updateGlobalMeta(
|
||||
"example",
|
||||
example.toString(),
|
||||
).collect()
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
emit(Unit)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,32 +15,41 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class AddMangaToLibrary @Inject constructor(
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class AddMangaToLibrary
|
||||
@Inject
|
||||
constructor(
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add $mangaId to library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add $mangaId to library" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add ${manga.title}(${manga.id}) to library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
libraryRepository.addMangaToLibrary(mangaId)
|
||||
.onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
libraryRepository.addMangaToLibrary(manga.id)
|
||||
.onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(manga: Manga, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add ${manga.title}(${manga.id}) to library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = libraryRepository.addMangaToLibrary(mangaId)
|
||||
.onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) = libraryRepository.addMangaToLibrary(manga.id)
|
||||
.onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,32 +15,41 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class RemoveMangaFromLibrary @Inject constructor(
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class RemoveMangaFromLibrary
|
||||
@Inject
|
||||
constructor(
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove $mangaId from library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove $mangaId from library" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove ${manga.title}(${manga.id}) from library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
libraryRepository.removeMangaFromLibrary(mangaId)
|
||||
.onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
libraryRepository.removeMangaFromLibrary(manga.id)
|
||||
.onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(manga: Manga, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove ${manga.title}(${manga.id}) from library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = libraryRepository.removeMangaFromLibrary(mangaId)
|
||||
.onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) = libraryRepository.removeMangaFromLibrary(manga.id)
|
||||
.onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,9 @@ import kotlinx.serialization.Transient
|
||||
|
||||
@Serializable
|
||||
@Stable
|
||||
enum class DisplayMode(@Transient val res: StringResource) {
|
||||
enum class DisplayMode(
|
||||
@Transient val res: StringResource,
|
||||
) {
|
||||
CompactGrid(MR.strings.display_compact),
|
||||
ComfortableGrid(MR.strings.display_comfortable),
|
||||
CoverOnlyGrid(MR.strings.display_cover_only),
|
||||
|
||||
@@ -14,7 +14,9 @@ import kotlinx.serialization.Transient
|
||||
|
||||
@Serializable
|
||||
@Stable
|
||||
enum class Sort(@Transient val res: StringResource) {
|
||||
enum class Sort(
|
||||
@Transient val res: StringResource,
|
||||
) {
|
||||
ALPHABETICAL(MR.strings.sort_alphabetical),
|
||||
|
||||
// LAST_READ,
|
||||
|
||||
@@ -12,7 +12,6 @@ import ca.gosyer.jui.domain.library.model.FilterState
|
||||
import ca.gosyer.jui.domain.library.model.Sort
|
||||
|
||||
class LibraryPreferences(private val preferenceStore: PreferenceStore) {
|
||||
|
||||
fun showAllCategory(): Preference<Boolean> {
|
||||
return preferenceStore.getBoolean("show_all_category", false)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import io.ktor.client.statement.HttpResponse
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface LibraryRepository {
|
||||
|
||||
@GET("api/v1/manga/{mangaId}/library")
|
||||
fun addMangaToLibrary(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
|
||||
@@ -17,25 +17,26 @@ import kotlinx.serialization.decodeFromString
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class LibraryUpdateService @Inject constructor(
|
||||
serverPreferences: ServerPreferences,
|
||||
client: Http,
|
||||
) : WebsocketService(serverPreferences, client) {
|
||||
class LibraryUpdateService
|
||||
@Inject
|
||||
constructor(
|
||||
serverPreferences: ServerPreferences,
|
||||
client: Http,
|
||||
) : WebsocketService(serverPreferences, client) {
|
||||
override val _status: MutableStateFlow<Status>
|
||||
get() = status
|
||||
|
||||
override val _status: MutableStateFlow<Status>
|
||||
get() = status
|
||||
override val query: String
|
||||
get() = "/api/v1/update"
|
||||
|
||||
override val query: String
|
||||
get() = "/api/v1/update"
|
||||
override suspend fun onReceived(frame: Frame.Text) {
|
||||
updateStatus.value = json.decodeFromString<UpdateStatus>(frame.readText())
|
||||
}
|
||||
|
||||
override suspend fun onReceived(frame: Frame.Text) {
|
||||
updateStatus.value = json.decodeFromString<UpdateStatus>(frame.readText())
|
||||
companion object {
|
||||
private val log = logging()
|
||||
|
||||
val status = MutableStateFlow(Status.STARTING)
|
||||
val updateStatus = MutableStateFlow(UpdateStatus(emptyMap(), false))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
|
||||
val status = MutableStateFlow(Status.STARTING)
|
||||
val updateStatus = MutableStateFlow(UpdateStatus(emptyMap(), false))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,36 +15,45 @@ import kotlinx.coroutines.flow.take
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetManga @Inject constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class GetManga
|
||||
@Inject
|
||||
constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getManga(mangaId),
|
||||
) { mangaId in it }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getManga(manga.id),
|
||||
) { manga.id in it }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(manga: Manga, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getManga(mangaId),
|
||||
) { mangaId in it }
|
||||
|
||||
fun asFlow(manga: Manga) = serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getManga(manga.id),
|
||||
) { manga.id in it }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,36 +15,45 @@ import kotlinx.coroutines.flow.take
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetMangaFull @Inject constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class GetMangaFull
|
||||
@Inject
|
||||
constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get full manga $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get full manga $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get full manga ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getMangaFull(mangaId),
|
||||
) { mangaId in it }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getMangaFull(manga.id),
|
||||
) { manga.id in it }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(manga: Manga, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get full manga ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getMangaFull(mangaId),
|
||||
) { mangaId in it }
|
||||
|
||||
fun asFlow(manga: Manga) = serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getMangaFull(manga.id),
|
||||
) { manga.id in it }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,34 +16,39 @@ import kotlinx.coroutines.flow.take
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class RefreshManga @Inject constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class RefreshManga
|
||||
@Inject
|
||||
constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh manga $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh manga $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh manga ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = mangaRepository.getManga(mangaId, true).onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) = mangaRepository.getManga(manga.id, true).onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(manga: Manga, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh manga ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
mangaRepository.getManga(mangaId, true).onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
mangaRepository.getManga(manga.id, true).onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,34 +16,39 @@ import kotlinx.coroutines.flow.take
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class RefreshMangaFull @Inject constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class RefreshMangaFull
|
||||
@Inject
|
||||
constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh full manga $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh full manga $mangaId" }
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh full manga ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = mangaRepository.getMangaFull(mangaId, true).onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) = mangaRepository.getMangaFull(manga.id, true).onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(manga: Manga, onError: suspend (Throwable) -> Unit = {}) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh full manga ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
mangaRepository.getMangaFull(mangaId, true).onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
mangaRepository.getMangaFull(manga.id, true).onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,38 +17,39 @@ import kotlinx.coroutines.flow.flow
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateMangaMeta @Inject constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
class UpdateMangaMeta
|
||||
@Inject
|
||||
constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
readerMode: String = manga.meta.juiReaderMode,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, readerMode)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update ${manga.title}(${manga.id}) meta" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
readerMode: String = manga.meta.juiReaderMode,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, readerMode)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update ${manga.title}(${manga.id}) meta" }
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
readerMode: String = manga.meta.juiReaderMode.decodeURLQueryComponent(),
|
||||
) = flow {
|
||||
if (readerMode.encodeURLQueryComponent() != manga.meta.juiReaderMode) {
|
||||
mangaRepository.updateMangaMeta(
|
||||
manga.id,
|
||||
"juiReaderMode",
|
||||
readerMode,
|
||||
).collect()
|
||||
serverListeners.updateManga(manga.id)
|
||||
}
|
||||
emit(Unit)
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
readerMode: String = manga.meta.juiReaderMode.decodeURLQueryComponent(),
|
||||
) = flow {
|
||||
if (readerMode.encodeURLQueryComponent() != manga.meta.juiReaderMode) {
|
||||
mangaRepository.updateMangaMeta(
|
||||
manga.id,
|
||||
"juiReaderMode",
|
||||
readerMode,
|
||||
).collect()
|
||||
serverListeners.updateManga(manga.id)
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
emit(Unit)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,9 @@ data class MangaMeta(
|
||||
|
||||
@Serializable
|
||||
@Stable
|
||||
enum class MangaStatus(@Transient val res: StringResource) {
|
||||
enum class MangaStatus(
|
||||
@Transient val res: StringResource,
|
||||
) {
|
||||
UNKNOWN(MR.strings.status_unknown),
|
||||
ONGOING(MR.strings.status_ongoing),
|
||||
COMPLETED(MR.strings.status_completed),
|
||||
|
||||
@@ -11,19 +11,20 @@ import ca.gosyer.jui.domain.migration.service.MigrationPreferences
|
||||
import ca.gosyer.jui.domain.reader.service.ReaderPreferences
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
|
||||
class RunMigrations @Inject constructor(
|
||||
private val migrationPreferences: MigrationPreferences,
|
||||
private val readerPreferences: ReaderPreferences,
|
||||
) {
|
||||
|
||||
fun runMigrations() {
|
||||
val code = migrationPreferences.version().get()
|
||||
if (code <= 0) {
|
||||
readerPreferences.modes().get().forEach {
|
||||
readerPreferences.getMode(it).direction().delete()
|
||||
class RunMigrations
|
||||
@Inject
|
||||
constructor(
|
||||
private val migrationPreferences: MigrationPreferences,
|
||||
private val readerPreferences: ReaderPreferences,
|
||||
) {
|
||||
fun runMigrations() {
|
||||
val code = migrationPreferences.version().get()
|
||||
if (code <= 0) {
|
||||
readerPreferences.modes().get().forEach {
|
||||
readerPreferences.getMode(it).direction().delete()
|
||||
}
|
||||
migrationPreferences.version().set(BuildKonfig.MIGRATION_CODE)
|
||||
return
|
||||
}
|
||||
migrationPreferences.version().set(BuildKonfig.MIGRATION_CODE)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,9 @@ import kotlinx.serialization.Transient
|
||||
|
||||
@Serializable
|
||||
@Stable
|
||||
enum class Direction(@Transient val res: StringResource) {
|
||||
enum class Direction(
|
||||
@Transient val res: StringResource,
|
||||
) {
|
||||
Down(MR.strings.dir_down),
|
||||
Left(MR.strings.dir_rtl),
|
||||
Right(MR.strings.dir_ltr),
|
||||
|
||||
@@ -14,7 +14,9 @@ import kotlinx.serialization.Transient
|
||||
|
||||
@Serializable
|
||||
@Stable
|
||||
enum class ImageScale(@Transient val res: StringResource) {
|
||||
enum class ImageScale(
|
||||
@Transient val res: StringResource,
|
||||
) {
|
||||
FitScreen(MR.strings.scale_fit_screen),
|
||||
Stretch(MR.strings.scale_stretch),
|
||||
FitWidth(MR.strings.scale_fit_width),
|
||||
|
||||
@@ -14,7 +14,9 @@ import kotlinx.serialization.Transient
|
||||
|
||||
@Serializable
|
||||
@Stable
|
||||
enum class NavigationMode(@Transient val res: StringResource) {
|
||||
enum class NavigationMode(
|
||||
@Transient val res: StringResource,
|
||||
) {
|
||||
Disabled(MR.strings.disabled),
|
||||
LNavigation(MR.strings.nav_l_shaped),
|
||||
KindlishNavigation(MR.strings.nav_kindle_ish),
|
||||
|
||||
@@ -13,7 +13,6 @@ import kotlinx.serialization.builtins.ListSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
|
||||
class ReaderPreferences(private val preferenceStore: PreferenceStore, private val factory: (String) -> PreferenceStore) {
|
||||
|
||||
fun preload(): Preference<Int> {
|
||||
return preferenceStore.getInt("preload", 3)
|
||||
}
|
||||
|
||||
@@ -40,7 +40,10 @@ expect val Engine: HttpClientEngineFactory<HttpClientEngineConfig>
|
||||
|
||||
expect fun HttpClientConfig<HttpClientEngineConfig>.configurePlatform()
|
||||
|
||||
fun httpClient(serverPreferences: ServerPreferences, json: Json): Http {
|
||||
fun httpClient(
|
||||
serverPreferences: ServerPreferences,
|
||||
json: Json,
|
||||
): Http {
|
||||
return HttpClient(Engine) {
|
||||
configurePlatform()
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import ca.gosyer.jui.domain.server.model.ServerUrlPreference
|
||||
import io.ktor.http.Url
|
||||
|
||||
class ServerPreferences(private val preferenceStore: PreferenceStore) {
|
||||
|
||||
fun server(): Preference<String> {
|
||||
return preferenceStore.getString("server_url", "http://localhost")
|
||||
}
|
||||
|
||||
@@ -12,18 +12,20 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class AboutServer @Inject constructor(private val settingsRepository: SettingsRepository) {
|
||||
class AboutServer
|
||||
@Inject
|
||||
constructor(private val settingsRepository: SettingsRepository) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get server information" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) = asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get server information" }
|
||||
fun asFlow() = settingsRepository.aboutServer()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow() = settingsRepository.aboutServer()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,18 +12,20 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class CheckUpdate @Inject constructor(private val settingsRepository: SettingsRepository) {
|
||||
class CheckUpdate
|
||||
@Inject
|
||||
constructor(private val settingsRepository: SettingsRepository) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to check for server updates" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) = asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to check for server updates" }
|
||||
fun asFlow() = settingsRepository.checkUpdate()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow() = settingsRepository.checkUpdate()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,27 +13,42 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetFilterList @Inject constructor(private val sourceRepository: SourceRepository) {
|
||||
class GetFilterList
|
||||
@Inject
|
||||
constructor(private val sourceRepository: SourceRepository) {
|
||||
suspend fun await(
|
||||
source: Source,
|
||||
reset: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(source.id, reset)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get filter list for ${source.displayName} with reset = $reset" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(source: Source, reset: Boolean, onError: suspend (Throwable) -> Unit = {}) = asFlow(source.id, reset)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get filter list for ${source.displayName} with reset = $reset" }
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
reset: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(sourceId, reset)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get filter list for $sourceId with reset = $reset" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
source: Source,
|
||||
reset: Boolean,
|
||||
) = sourceRepository.getFilterList(source.id, reset)
|
||||
|
||||
fun asFlow(
|
||||
sourceId: Long,
|
||||
reset: Boolean,
|
||||
) = sourceRepository.getFilterList(sourceId, reset)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(sourceId: Long, reset: Boolean, onError: suspend (Throwable) -> Unit = {}) = asFlow(sourceId, reset)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get filter list for $sourceId with reset = $reset" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(source: Source, reset: Boolean) = sourceRepository.getFilterList(source.id, reset)
|
||||
|
||||
fun asFlow(sourceId: Long, reset: Boolean) = sourceRepository.getFilterList(sourceId, reset)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,27 +13,42 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetLatestManga @Inject constructor(private val sourceRepository: SourceRepository) {
|
||||
class GetLatestManga
|
||||
@Inject
|
||||
constructor(private val sourceRepository: SourceRepository) {
|
||||
suspend fun await(
|
||||
source: Source,
|
||||
page: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(source.id, page)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get latest manga from ${source.displayName} on page $page" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(source: Source, page: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(source.id, page)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get latest manga from ${source.displayName} on page $page" }
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
page: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(sourceId, page)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get latest manga from $sourceId on page $page" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
source: Source,
|
||||
page: Int,
|
||||
) = sourceRepository.getLatestManga(source.id, page)
|
||||
|
||||
fun asFlow(
|
||||
sourceId: Long,
|
||||
page: Int,
|
||||
) = sourceRepository.getLatestManga(sourceId, page)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(sourceId: Long, page: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(sourceId, page)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get latest manga from $sourceId on page $page" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(source: Source, page: Int) = sourceRepository.getLatestManga(source.id, page)
|
||||
|
||||
fun asFlow(sourceId: Long, page: Int) = sourceRepository.getLatestManga(sourceId, page)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user