Skip to content

Commit

Permalink
initial work
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed Nov 1, 2023
1 parent c220b64 commit 386b72c
Show file tree
Hide file tree
Showing 21 changed files with 397 additions and 7 deletions.
10 changes: 9 additions & 1 deletion app/shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ kotlin {
api(libs.material)
api(libs.multidex)
api(libs.splashscreen)
api(libs.ktor.android)
api(libs.ktor.jvm)
}
}
val desktopMain by getting {
Expand All @@ -94,6 +94,7 @@ kotlin {
api(libs.coroutines.swing)
api(libs.context.menu)
api(libs.window.styler)
api(libs.ktor.jvm)
}
}
val iosX64Main by getting
Expand All @@ -104,6 +105,10 @@ kotlin {
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
iosSimulatorArm64Main.dependsOn(this)

dependencies {
api(libs.ktor.apple)
}
}
}
}
Expand All @@ -127,6 +132,9 @@ android {
buildConfig = true
}
}
dependencies {
implementation("io.ktor:ktor-client-okhttp-jvm:2.3.5")
}

multiplatformResources {
multiplatformResourcesPackage = artifact
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package dev.datlag.burningseries.common

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainCoroutineDispatcher

actual val Dispatchers.DeviceMain: MainCoroutineDispatcher
get() = Main

actual val Dispatchers.DeviceIO: CoroutineDispatcher
get() = IO

actual val Dispatchers.DeviceDefault : CoroutineDispatcher
get() = Default
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package dev.datlag.burningseries.module

import org.kodein.di.DI

actual object PlatformModule {
actual val di: DI.Module
get() = TODO("Not yet implemented")

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package dev.datlag.burningseries.common

import com.arkivanov.essenty.lifecycle.Lifecycle
import com.arkivanov.essenty.lifecycle.LifecycleOwner
import com.arkivanov.essenty.lifecycle.doOnDestroy
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.MainCoroutineDispatcher
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import kotlin.coroutines.CoroutineContext

fun <T> MutableStateFlow<T>.safeEmit(value: T, scope: CoroutineScope) {
if (!this.tryEmit(value)) {
scope.launch(ioDispatcher()) {
this@safeEmit.emit(value)
}
}
}

fun CoroutineScope(context: CoroutineContext, lifecycle: Lifecycle): CoroutineScope {
val scope = CoroutineScope(context)
lifecycle.doOnDestroy(scope::cancel)
return scope
}

fun LifecycleOwner.coroutineScope(context: CoroutineContext): CoroutineScope = CoroutineScope(context, lifecycle)

fun LifecycleOwner.ioScope() = CoroutineScope(ioDispatcher() + SupervisorJob(), lifecycle)
fun LifecycleOwner.mainScope() = CoroutineScope(mainDispatcher() + SupervisorJob(), lifecycle)
fun LifecycleOwner.defaultScope() = CoroutineScope(defaultDispatcher() + SupervisorJob(), lifecycle)

fun mainDispatcher(): MainCoroutineDispatcher = Dispatchers.DeviceMain
fun ioDispatcher(): CoroutineDispatcher = Dispatchers.DeviceIO
fun defaultDispatcher(): CoroutineDispatcher = Dispatchers.DeviceDefault

fun CoroutineScope.launchIO(block: suspend CoroutineScope.() -> Unit): Job {
return this.launch(ioDispatcher()) {
block()
}
}

fun CoroutineScope.launchMain(block: suspend CoroutineScope.() -> Unit): Job {
return this.launch(mainDispatcher()) {
block()
}
}

fun CoroutineScope.launchDefault(block: suspend CoroutineScope.() -> Unit): Job {
return this.launch(defaultDispatcher()) {
block()
}
}

fun LifecycleOwner.launchIO(block: suspend CoroutineScope.() -> Unit): Job {
return ioScope().launchIO(block)
}

fun LifecycleOwner.launchMain(block: suspend CoroutineScope.() -> Unit): Job {
return mainScope().launchMain(block)
}

fun LifecycleOwner.launchDefault(block: suspend CoroutineScope.() -> Unit): Job {
return defaultScope().launchDefault(block)
}

suspend fun <T> withIOContext(
block: suspend CoroutineScope.() -> T
): T {
return withContext(ioDispatcher()) {
block()
}
}

suspend fun <T> withMainContext(
block: suspend CoroutineScope.() -> T
): T {
return withContext(mainDispatcher()) {
block()
}
}

suspend fun <T> withDefaultContext(
block: suspend CoroutineScope.() -> T
): T {
return withContext(defaultDispatcher()) {
block()
}
}

fun <T> runBlockingIO(block: suspend CoroutineScope.() -> T): T {
return runBlocking(ioDispatcher()) {
block()
}
}

fun <T> runBlockingMain(block: suspend CoroutineScope.() -> T): T {
return runBlocking(mainDispatcher()) {
block()
}
}

fun <T> runBlockingDefault(block: suspend CoroutineScope.() -> T): T {
return runBlocking(defaultDispatcher()) {
block()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package dev.datlag.burningseries.common

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainCoroutineDispatcher

expect val Dispatchers.DeviceMain: MainCoroutineDispatcher
expect val Dispatchers.DeviceIO: CoroutineDispatcher
expect val Dispatchers.DeviceDefault: CoroutineDispatcher
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ object NetworkModule {
const val NAME = "NetworkModule"

val di = DI.Module(NAME) {

import(PlatformModule.di)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package dev.datlag.burningseries.module

import org.kodein.di.DI

expect object PlatformModule {

val di: DI.Module
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,28 @@ package dev.datlag.burningseries.ui.screen.home

import androidx.compose.runtime.Composable
import com.arkivanov.decompose.ComponentContext
import dev.datlag.burningseries.common.ioScope
import dev.datlag.burningseries.common.launchIO
import dev.datlag.burningseries.network.scraper.BurningSeries
import io.ktor.client.*
import org.kodein.di.DI
import org.kodein.di.instance

class HomeScreenComponent(
componentContext: ComponentContext,
override val di: DI
) : HomeComponent, ComponentContext by componentContext {

private val client: HttpClient by di.instance()

@Composable
override fun render() {
HomeScreen(this)
}

init {
ioScope().launchIO {
BurningSeries.testSeries(client)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package dev.datlag.burningseries

import dev.datlag.burningseries.model.common.scopeCatching
import java.awt.Toolkit

object AppIO {

fun applyTitle(title: String) = runCatching {
fun applyTitle(title: String) = scopeCatching {
val toolkit = Toolkit.getDefaultToolkit()
val awtAppClassNameField = toolkit.javaClass.getDeclaredField("awtAppClassName")
val working = try {
awtAppClassNameField.isAccessible = true
awtAppClassNameField.isAccessible
awtAppClassNameField.canAccess(null)
} catch (ignored: Throwable) {
awtAppClassNameField.trySetAccessible()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package dev.datlag.burningseries.common

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainCoroutineDispatcher

actual val Dispatchers.DeviceMain: MainCoroutineDispatcher
get() = Main

actual val Dispatchers.DeviceIO: CoroutineDispatcher
get() = IO

actual val Dispatchers.DeviceDefault : CoroutineDispatcher
get() = Default
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dev.datlag.burningseries.module

import io.ktor.client.*
import io.ktor.client.engine.okhttp.*
import org.kodein.di.DI
import org.kodein.di.bindSingleton

actual object PlatformModule {

private const val NAME = "PlatformModuleDesktop"

actual val di: DI.Module = DI.Module(NAME) {
bindSingleton {
HttpClient(OkHttp) {
engine {
config {
followRedirects(true)
}
}
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dev.datlag.burningseries.common

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.MainCoroutineDispatcher

actual val Dispatchers.DeviceMain: MainCoroutineDispatcher
get() = Main

actual val Dispatchers.DeviceIO: CoroutineDispatcher
get() = IO

actual val Dispatchers.DeviceDefault : CoroutineDispatcher
get() = Default
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package dev.datlag.burningseries.module

import org.kodein.di.DI

actual object PlatformModule {
actual val di: DI.Module
get() = TODO("Not yet implemented")

}
8 changes: 5 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ instesx = "0.1.0-alpha10"
kamel = "0.8.2"
kodein = "7.20.2"
kotlin = "1.9.10"
ksoup = "0.2.1"
ksp = "1.9.10-1.0.13"
ktor = "2.3.5"
ktorfit = "1.9.1"
ktsoup = "0.3.0"
material = "1.10.0"
moko-resources = "0.23.0"
multidex = "2.0.1"
Expand Down Expand Up @@ -60,15 +60,17 @@ insetsx = { group = "com.moriatsushi.insetsx", name = "insetsx", version.ref = "
kamel = { group = "media.kamel", name = "kamel-image", version.ref = "kamel" }
kodein = { group = "org.kodein.di", name = "kodein-di", version.ref = "kodein" }
kodein-compose = { group = "org.kodein.di", name = "kodein-di-framework-compose", version.ref = "kodein" }
ksoup = { group = "com.mohamedrejeb.ksoup", name = "ksoup-html", version.ref = "ksoup" }
ktor = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" }
ktor-android = { group = "io.ktor", name = "ktor-client-okhttp", version.ref = "ktor" }
ktor-jvm = { group = "io.ktor", name = "ktor-client-okhttp", version.ref = "ktor" }
ktor-apple = { group = "io.ktor", name = "ktor-client-darwin", version.ref = "ktor" }
ktor-cio = { group = "io.ktor", name = "ktor-client-cio", version.ref = "ktor" }
ktor-content-negotiation = { group = "io.ktor", name = "ktor-client-content-negotiation", version.ref = "ktor" }
ktor-serialization-json = { group = "io.ktor", name = "ktor-serialization-kotlinx-json", version.ref = "ktor" }
ktorfit = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-lib", version.ref = "ktorfit" }
ktorfit-ksp = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-ksp", version.ref = "ktorfit" }
ktsoup = { group = "org.drewcarlson", name = "ktsoup-core", version.ref = "ktsoup" }
ktsoup-fs = { group = "org.drewcarlson", name = "ktsoup-fs", version.ref = "ktsoup" }
ktsoup-ktor = { group = "org.drewcarlson", name = "ktsoup-ktor", version.ref = "ktsoup" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
moko-resources-compose = { group = "dev.icerock.moko", name = "resources-compose", version.ref = "moko-resources" }
moko-resources-generator = { group = "dev.icerock.moko", name = "resources-generator", version.ref = "moko-resources" }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package dev.datlag.burningseries.model

data object Constants {

data object BurningSeries {
const val PROTOCOL_HTTP = "http://"
const val PROTOCOL_HTTPS = "https://"

const val HOST_BS_TO = "bs.to"

val episodeNumberRegex = "[|({]\\s*Ep([.]|isode)?\\s*(\\d+)\\s*[|)}]".toRegex(RegexOption.IGNORE_CASE)

fun getBurningSeriesLink(href: String, http: Boolean = false, host: String = HOST_BS_TO): String {
return if (!href.matches("^\\w+?://.*".toRegex())) {
if (!href.startsWith("/")) {
"${if (http) PROTOCOL_HTTP else PROTOCOL_HTTPS}${host}/$href"
} else {
"${if (http) PROTOCOL_HTTP else PROTOCOL_HTTPS}${host}${"(?!:|/{2,})(/.*)".toRegex().find(href)?.value}"
}
} else {
href
}
}
}
}
Loading

0 comments on commit 386b72c

Please sign in to comment.