Convert source modules to Kotlin Multiplatform (#9172)
Use KMP in source modules Use KMP in source-api Expect LocalSource
This commit is contained in:
parent
b41565f879
commit
1abf01c4a0
@ -48,9 +48,7 @@ import tachiyomi.data.Mangas
|
|||||||
import tachiyomi.data.dateAdapter
|
import tachiyomi.data.dateAdapter
|
||||||
import tachiyomi.data.listOfStringsAdapter
|
import tachiyomi.data.listOfStringsAdapter
|
||||||
import tachiyomi.data.updateStrategyAdapter
|
import tachiyomi.data.updateStrategyAdapter
|
||||||
import tachiyomi.source.local.image.AndroidLocalCoverManager
|
|
||||||
import tachiyomi.source.local.image.LocalCoverManager
|
import tachiyomi.source.local.image.LocalCoverManager
|
||||||
import tachiyomi.source.local.io.AndroidLocalSourceFileSystem
|
|
||||||
import tachiyomi.source.local.io.LocalSourceFileSystem
|
import tachiyomi.source.local.io.LocalSourceFileSystem
|
||||||
import uy.kohesive.injekt.api.InjektModule
|
import uy.kohesive.injekt.api.InjektModule
|
||||||
import uy.kohesive.injekt.api.InjektRegistrar
|
import uy.kohesive.injekt.api.InjektRegistrar
|
||||||
@ -137,8 +135,8 @@ class AppModule(val app: Application) : InjektModule {
|
|||||||
|
|
||||||
addSingletonFactory { ImageSaver(app) }
|
addSingletonFactory { ImageSaver(app) }
|
||||||
|
|
||||||
addSingletonFactory<LocalSourceFileSystem> { AndroidLocalSourceFileSystem(app) }
|
addSingletonFactory { LocalSourceFileSystem(app) }
|
||||||
addSingletonFactory<LocalCoverManager> { AndroidLocalCoverManager(app, get()) }
|
addSingletonFactory { LocalCoverManager(app, get()) }
|
||||||
|
|
||||||
// Asynchronously init expensive components for a faster cold start
|
// Asynchronously init expensive components for a faster cold start
|
||||||
ContextCompat.getMainExecutor(app).execute {
|
ContextCompat.getMainExecutor(app).execute {
|
||||||
|
@ -22,3 +22,5 @@ org.gradle.caching=true
|
|||||||
|
|
||||||
# AndroidX support
|
# AndroidX support
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
|
|
||||||
|
kotlin.mpp.androidSourceSetLayoutVersion=2
|
@ -1,7 +1,27 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("com.android.library")
|
kotlin("multiplatform")
|
||||||
kotlin("android")
|
|
||||||
kotlin("plugin.serialization")
|
kotlin("plugin.serialization")
|
||||||
|
id("com.android.library")
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
android()
|
||||||
|
sourceSets {
|
||||||
|
val commonMain by getting {
|
||||||
|
dependencies {
|
||||||
|
api(kotlinx.serialization.json)
|
||||||
|
api(libs.injekt.core)
|
||||||
|
api(libs.rxjava)
|
||||||
|
api(libs.jsoup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val androidMain by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":core"))
|
||||||
|
api(libs.preferencektx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@ -11,13 +31,3 @@ android {
|
|||||||
consumerProguardFile("consumer-proguard.pro")
|
consumerProguardFile("consumer-proguard.pro")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(project(":core"))
|
|
||||||
|
|
||||||
api(kotlinx.serialization.json)
|
|
||||||
api(libs.injekt.core)
|
|
||||||
api(libs.rxjava)
|
|
||||||
api(libs.preferencektx)
|
|
||||||
api(libs.jsoup)
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
package eu.kanade.tachiyomi.source
|
||||||
|
|
||||||
|
actual typealias PreferenceScreen = androidx.preference.PreferenceScreen
|
@ -0,0 +1,6 @@
|
|||||||
|
package eu.kanade.tachiyomi.util
|
||||||
|
|
||||||
|
import rx.Observable
|
||||||
|
import tachiyomi.core.util.lang.awaitSingle
|
||||||
|
|
||||||
|
actual suspend fun <T> Observable<T>.awaitSingle(): T = awaitSingle()
|
@ -1,7 +1,5 @@
|
|||||||
package eu.kanade.tachiyomi.source
|
package eu.kanade.tachiyomi.source
|
||||||
|
|
||||||
import androidx.preference.PreferenceScreen
|
|
||||||
|
|
||||||
interface ConfigurableSource : Source {
|
interface ConfigurableSource : Source {
|
||||||
|
|
||||||
fun setupPreferenceScreen(screen: PreferenceScreen)
|
fun setupPreferenceScreen(screen: PreferenceScreen)
|
@ -0,0 +1,3 @@
|
|||||||
|
package eu.kanade.tachiyomi.source
|
||||||
|
|
||||||
|
expect class PreferenceScreen
|
@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.source
|
|||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.util.awaitSingle
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import tachiyomi.core.util.lang.awaitSingle
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A basic interface for creating a source. It could be an online source, a local source, etc...
|
* A basic interface for creating a source. It could be an online source, a local source, etc...
|
@ -0,0 +1,5 @@
|
|||||||
|
package eu.kanade.tachiyomi.util
|
||||||
|
|
||||||
|
import rx.Observable
|
||||||
|
|
||||||
|
expect suspend fun <T> Observable<T>.awaitSingle(): T
|
@ -1,29 +1,37 @@
|
|||||||
plugins {
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
id("com.android.library")
|
id("com.android.library")
|
||||||
kotlin("android")
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
android()
|
||||||
|
sourceSets {
|
||||||
|
val commonMain by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":source-api"))
|
||||||
|
implementation(libs.unifile)
|
||||||
|
implementation(libs.junrar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val androidMain by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":core"))
|
||||||
|
implementation(project(":core-metadata"))
|
||||||
|
|
||||||
|
// Move ChapterRecognition to separate module?
|
||||||
|
implementation(project(":domain"))
|
||||||
|
|
||||||
|
implementation(kotlinx.bundles.serialization)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "tachiyomi.source.local"
|
namespace = "tachiyomi.source.local"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
consumerProguardFiles("consumer-rules.pro")
|
consumerProguardFiles("consumer-rules.pro")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
|
||||||
|
|
||||||
implementation(project(":source-api"))
|
|
||||||
implementation(project(":core"))
|
|
||||||
implementation(project(":core-metadata"))
|
|
||||||
|
|
||||||
// Move ChapterRecognition to separate module?
|
|
||||||
implementation(project(":domain"))
|
|
||||||
|
|
||||||
implementation(kotlinx.bundles.serialization)
|
|
||||||
|
|
||||||
implementation(libs.unifile)
|
|
||||||
implementation(libs.junrar)
|
|
||||||
}
|
|
||||||
|
@ -40,7 +40,7 @@ import java.util.concurrent.TimeUnit
|
|||||||
import java.util.zip.ZipFile
|
import java.util.zip.ZipFile
|
||||||
import com.github.junrar.Archive as JunrarArchive
|
import com.github.junrar.Archive as JunrarArchive
|
||||||
|
|
||||||
class LocalSource(
|
actual class LocalSource(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val fileSystem: LocalSourceFileSystem,
|
private val fileSystem: LocalSourceFileSystem,
|
||||||
private val coverManager: LocalCoverManager,
|
private val coverManager: LocalCoverManager,
|
@ -11,12 +11,12 @@ import java.io.InputStream
|
|||||||
|
|
||||||
private const val DEFAULT_COVER_NAME = "cover.jpg"
|
private const val DEFAULT_COVER_NAME = "cover.jpg"
|
||||||
|
|
||||||
class AndroidLocalCoverManager(
|
actual class LocalCoverManager(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val fileSystem: LocalSourceFileSystem,
|
private val fileSystem: LocalSourceFileSystem,
|
||||||
) : LocalCoverManager {
|
) {
|
||||||
|
|
||||||
override fun find(mangaUrl: String): File? {
|
actual fun find(mangaUrl: String): File? {
|
||||||
return fileSystem.getFilesInMangaDirectory(mangaUrl)
|
return fileSystem.getFilesInMangaDirectory(mangaUrl)
|
||||||
// Get all file whose names start with 'cover'
|
// Get all file whose names start with 'cover'
|
||||||
.filter { it.isFile && it.nameWithoutExtension.equals("cover", ignoreCase = true) }
|
.filter { it.isFile && it.nameWithoutExtension.equals("cover", ignoreCase = true) }
|
||||||
@ -26,7 +26,10 @@ class AndroidLocalCoverManager(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun update(manga: SManga, inputStream: InputStream): File? {
|
actual fun update(
|
||||||
|
manga: SManga,
|
||||||
|
inputStream: InputStream,
|
||||||
|
): File? {
|
||||||
val directory = fileSystem.getMangaDirectory(manga.url)
|
val directory = fileSystem.getMangaDirectory(manga.url)
|
||||||
if (directory == null) {
|
if (directory == null) {
|
||||||
inputStream.close()
|
inputStream.close()
|
@ -5,31 +5,31 @@ import eu.kanade.tachiyomi.util.storage.DiskUtil
|
|||||||
import tachiyomi.source.local.R
|
import tachiyomi.source.local.R
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class AndroidLocalSourceFileSystem(
|
actual class LocalSourceFileSystem(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
) : LocalSourceFileSystem {
|
) {
|
||||||
|
|
||||||
private val baseFolderLocation = "${context.getString(R.string.app_name)}${File.separator}local"
|
private val baseFolderLocation = "${context.getString(R.string.app_name)}${File.separator}local"
|
||||||
|
|
||||||
override fun getBaseDirectories(): Sequence<File> {
|
actual fun getBaseDirectories(): Sequence<File> {
|
||||||
return DiskUtil.getExternalStorages(context)
|
return DiskUtil.getExternalStorages(context)
|
||||||
.map { File(it.absolutePath, baseFolderLocation) }
|
.map { File(it.absolutePath, baseFolderLocation) }
|
||||||
.asSequence()
|
.asSequence()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFilesInBaseDirectories(): Sequence<File> {
|
actual fun getFilesInBaseDirectories(): Sequence<File> {
|
||||||
return getBaseDirectories()
|
return getBaseDirectories()
|
||||||
// Get all the files inside all baseDir
|
// Get all the files inside all baseDir
|
||||||
.flatMap { it.listFiles().orEmpty().toList() }
|
.flatMap { it.listFiles().orEmpty().toList() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMangaDirectory(name: String): File? {
|
actual fun getMangaDirectory(name: String): File? {
|
||||||
return getFilesInBaseDirectories()
|
return getFilesInBaseDirectories()
|
||||||
// Get the first mangaDir or null
|
// Get the first mangaDir or null
|
||||||
.firstOrNull { it.isDirectory && it.name == name }
|
.firstOrNull { it.isDirectory && it.name == name }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFilesInMangaDirectory(name: String): Sequence<File> {
|
actual fun getFilesInMangaDirectory(name: String): Sequence<File> {
|
||||||
return getFilesInBaseDirectories()
|
return getFilesInBaseDirectories()
|
||||||
// Filter out ones that are not related to the manga and is not a directory
|
// Filter out ones that are not related to the manga and is not a directory
|
||||||
.filter { it.isDirectory && it.name == name }
|
.filter { it.isDirectory && it.name == name }
|
@ -0,0 +1,6 @@
|
|||||||
|
package tachiyomi.source.local
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
|
import eu.kanade.tachiyomi.source.UnmeteredSource
|
||||||
|
|
||||||
|
expect class LocalSource : CatalogueSource, UnmeteredSource
|
@ -4,7 +4,7 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
interface LocalCoverManager {
|
expect class LocalCoverManager {
|
||||||
|
|
||||||
fun find(mangaUrl: String): File?
|
fun find(mangaUrl: String): File?
|
||||||
|
|
@ -2,7 +2,7 @@ package tachiyomi.source.local.io
|
|||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
interface LocalSourceFileSystem {
|
expect class LocalSourceFileSystem {
|
||||||
|
|
||||||
fun getBaseDirectories(): Sequence<File>
|
fun getBaseDirectories(): Sequence<File>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user