mirror of
https://github.com/mihonapp/mihon.git
synced 2025-11-15 05:27:28 +01:00
Convert Source tab to use Compose (#6987)
* Use Compose in Source tab * Replace hashCode with key function * Add ability to turn off pins moving on top of source list * Changes from review comments
This commit is contained in:
@@ -1,12 +1,17 @@
|
||||
package eu.kanade.domain
|
||||
|
||||
import eu.kanade.data.history.HistoryRepositoryImpl
|
||||
import eu.kanade.data.source.SourceRepositoryImpl
|
||||
import eu.kanade.domain.history.interactor.DeleteHistoryTable
|
||||
import eu.kanade.domain.history.interactor.GetHistory
|
||||
import eu.kanade.domain.history.interactor.GetNextChapterForManga
|
||||
import eu.kanade.domain.history.interactor.RemoveHistoryById
|
||||
import eu.kanade.domain.history.interactor.RemoveHistoryByMangaId
|
||||
import eu.kanade.domain.history.repository.HistoryRepository
|
||||
import eu.kanade.domain.source.interactor.DisableSource
|
||||
import eu.kanade.domain.source.interactor.GetEnabledSources
|
||||
import eu.kanade.domain.source.interactor.ToggleSourcePin
|
||||
import eu.kanade.domain.source.repository.SourceRepository
|
||||
import uy.kohesive.injekt.api.InjektModule
|
||||
import uy.kohesive.injekt.api.InjektRegistrar
|
||||
import uy.kohesive.injekt.api.addFactory
|
||||
@@ -22,5 +27,9 @@ class DomainModule : InjektModule {
|
||||
addFactory { GetNextChapterForManga(get()) }
|
||||
addFactory { RemoveHistoryById(get()) }
|
||||
addFactory { RemoveHistoryByMangaId(get()) }
|
||||
addSingletonFactory<SourceRepository> { SourceRepositoryImpl(get()) }
|
||||
addFactory { GetEnabledSources(get(), get()) }
|
||||
addFactory { DisableSource(get()) }
|
||||
addFactory { ToggleSourcePin(get()) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import eu.kanade.domain.source.model.Source
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.util.preference.plusAssign
|
||||
|
||||
class DisableSource(
|
||||
private val preferences: PreferencesHelper
|
||||
) {
|
||||
|
||||
fun await(source: Source) {
|
||||
preferences.disabledSources() += source.id.toString()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import eu.kanade.domain.source.model.Pin
|
||||
import eu.kanade.domain.source.model.Pins
|
||||
import eu.kanade.domain.source.model.Source
|
||||
import eu.kanade.domain.source.repository.SourceRepository
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
|
||||
class GetEnabledSources(
|
||||
private val repository: SourceRepository,
|
||||
private val preferences: PreferencesHelper
|
||||
) {
|
||||
|
||||
fun subscribe(): Flow<List<Source>> {
|
||||
return preferences.pinnedSources().asFlow()
|
||||
.combine(preferences.enabledLanguages().asFlow()) { pinList, enabledLanguages ->
|
||||
Config(pinSet = pinList, enabledSources = enabledLanguages)
|
||||
}
|
||||
.combine(preferences.disabledSources().asFlow()) { config, disabledSources ->
|
||||
config.copy(disabledSources = disabledSources)
|
||||
}
|
||||
.combine(preferences.lastUsedSource().asFlow()) { config, lastUsedSource ->
|
||||
config.copy(lastUsedSource = lastUsedSource)
|
||||
}
|
||||
.combine(repository.getSources()) { (pinList, enabledLanguages, disabledSources, lastUsedSource), sources ->
|
||||
val pinsOnTop = preferences.pinsOnTop().get()
|
||||
sources
|
||||
.filter { it.lang in enabledLanguages || it.id == LocalSource.ID }
|
||||
.filterNot { it.id.toString() in disabledSources }
|
||||
.flatMap {
|
||||
val flag = if ("${it.id}" in pinList) Pins.pinned else Pins.unpinned
|
||||
val source = it.copy(pin = flag)
|
||||
val toFlatten = mutableListOf(source)
|
||||
if (source.id == lastUsedSource) {
|
||||
toFlatten.add(source.copy(isUsedLast = true, pin = source.pin - Pin.Actual))
|
||||
}
|
||||
if (pinsOnTop.not() && Pin.Pinned in source.pin) {
|
||||
toFlatten[0] = toFlatten[0].copy(pin = source.pin + Pin.Forced)
|
||||
toFlatten.add(source.copy(pin = source.pin - Pin.Actual))
|
||||
}
|
||||
toFlatten
|
||||
}
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
}
|
||||
|
||||
private data class Config(
|
||||
val pinSet: Set<String> = setOf(),
|
||||
val enabledSources: Set<String> = setOf(),
|
||||
val disabledSources: Set<String> = setOf(),
|
||||
val lastUsedSource: Long? = null
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import eu.kanade.domain.source.model.Source
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.util.preference.minusAssign
|
||||
import eu.kanade.tachiyomi.util.preference.plusAssign
|
||||
|
||||
class ToggleSourcePin(
|
||||
private val preferences: PreferencesHelper
|
||||
) {
|
||||
|
||||
fun await(source: Source) {
|
||||
val isPinned = source.id.toString() in preferences.pinnedSources().get()
|
||||
if (isPinned) {
|
||||
preferences.pinnedSources() -= source.id.toString()
|
||||
} else {
|
||||
preferences.pinnedSources() += source.id.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
78
app/src/main/java/eu/kanade/domain/source/model/Source.kt
Normal file
78
app/src/main/java/eu/kanade/domain/source/model/Source.kt
Normal file
@@ -0,0 +1,78 @@
|
||||
package eu.kanade.domain.source.model
|
||||
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
data class Source(
|
||||
val id: Long,
|
||||
val lang: String,
|
||||
val name: String,
|
||||
val supportsLatest: Boolean,
|
||||
val pin: Pins = Pins.unpinned,
|
||||
val isUsedLast: Boolean = false
|
||||
) {
|
||||
|
||||
val nameWithLanguage: String
|
||||
get() = "$name (${lang.uppercase()})"
|
||||
|
||||
val icon: ImageBitmap?
|
||||
get() {
|
||||
return Injekt.get<ExtensionManager>().getAppIconForSource(id)
|
||||
?.toBitmap()
|
||||
?.asImageBitmap()
|
||||
}
|
||||
|
||||
val key: () -> Long = {
|
||||
when {
|
||||
isUsedLast -> id shr 16
|
||||
Pin.Forced in pin -> id shr 32
|
||||
else -> id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class Pin(val code: Int) {
|
||||
object Unpinned : Pin(0b00)
|
||||
object Pinned : Pin(0b01)
|
||||
object Actual : Pin(0b10)
|
||||
object Forced : Pin(0b100)
|
||||
}
|
||||
|
||||
inline fun Pins(builder: Pins.PinsBuilder.() -> Unit = {}): Pins {
|
||||
return Pins.PinsBuilder().apply(builder).flags()
|
||||
}
|
||||
|
||||
fun Pins(vararg pins: Pin) = Pins {
|
||||
pins.forEach { +it }
|
||||
}
|
||||
|
||||
data class Pins(val code: Int = Pin.Unpinned.code) {
|
||||
|
||||
operator fun contains(pin: Pin): Boolean = pin.code and code == pin.code
|
||||
|
||||
operator fun plus(pin: Pin): Pins = Pins(code or pin.code)
|
||||
|
||||
operator fun minus(pin: Pin): Pins = Pins(code xor pin.code)
|
||||
|
||||
companion object {
|
||||
val unpinned = Pins(Pin.Unpinned)
|
||||
|
||||
val pinned = Pins(Pin.Pinned, Pin.Actual)
|
||||
}
|
||||
|
||||
class PinsBuilder(var code: Int = 0) {
|
||||
operator fun Pin.unaryPlus() {
|
||||
this@PinsBuilder.code = code or this@PinsBuilder.code
|
||||
}
|
||||
|
||||
operator fun Pin.unaryMinus() {
|
||||
this@PinsBuilder.code = code or this@PinsBuilder.code
|
||||
}
|
||||
|
||||
fun flags(): Pins = Pins(code)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package eu.kanade.domain.source.repository
|
||||
|
||||
import eu.kanade.domain.source.model.Source
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface SourceRepository {
|
||||
|
||||
fun getSources(): Flow<List<Source>>
|
||||
}
|
||||
Reference in New Issue
Block a user