Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fe59520879 |
@@ -28,7 +28,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Log into registry ${{ env.REGISTRY }}
|
- name: Log into registry ${{ env.REGISTRY }}
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.REGISTRY }}
|
registry: ${{ env.REGISTRY }}
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
|
|||||||
+6
-6
@@ -1,8 +1,8 @@
|
|||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.multiplatform) apply false
|
alias(libs.plugins.multiplatform).apply(false)
|
||||||
alias(libs.plugins.compose.compiler) apply false
|
alias(libs.plugins.compose.compiler).apply(false)
|
||||||
alias(libs.plugins.compose) apply false
|
alias(libs.plugins.compose).apply(false)
|
||||||
alias(libs.plugins.compose.hot.reload) apply false
|
alias(libs.plugins.compose.hot.reload).apply(false)
|
||||||
alias(libs.plugins.android.application) apply false
|
alias(libs.plugins.android.application).apply(false)
|
||||||
alias(libs.plugins.kotlinx.serialization) apply false
|
alias(libs.plugins.kotlinx.serialization).apply(false)
|
||||||
}
|
}
|
||||||
|
|||||||
+52
-31
@@ -2,6 +2,8 @@ import org.jetbrains.compose.ExperimentalComposeLibrary
|
|||||||
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
||||||
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
@@ -13,6 +15,21 @@ plugins {
|
|||||||
alias(libs.plugins.kotlinx.serialization)
|
alias(libs.plugins.kotlinx.serialization)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType<KotlinCompile>().configureEach {
|
||||||
|
compilerOptions {
|
||||||
|
freeCompilerArgs.addAll(
|
||||||
|
"-opt-in=kotlin.RequiresOptIn",
|
||||||
|
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||||
|
"-opt-in=kotlinx.coroutines.FlowPreview",
|
||||||
|
"-Xexpect-actual-classes"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compose.resources {
|
||||||
|
nameOfResClass = "R"
|
||||||
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
androidTarget {
|
androidTarget {
|
||||||
compilerOptions {
|
compilerOptions {
|
||||||
@@ -22,7 +39,9 @@ kotlin {
|
|||||||
|
|
||||||
jvm()
|
jvm()
|
||||||
|
|
||||||
|
if (providers.gradleProperty("include_ios").get().toBoolean()) {
|
||||||
listOf(
|
listOf(
|
||||||
|
iosX64(),
|
||||||
iosArm64(),
|
iosArm64(),
|
||||||
iosSimulatorArm64()
|
iosSimulatorArm64()
|
||||||
).forEach { iosTarget ->
|
).forEach { iosTarget ->
|
||||||
@@ -31,39 +50,42 @@ kotlin {
|
|||||||
isStatic = true
|
isStatic = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
js {
|
|
||||||
browser()
|
|
||||||
binaries.executable()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (providers.gradleProperty("include_wasm").get().toBoolean()) {
|
||||||
@OptIn(ExperimentalWasmDsl::class)
|
@OptIn(ExperimentalWasmDsl::class)
|
||||||
wasmJs {
|
wasmJs {
|
||||||
browser()
|
outputModuleName = "composeApp"
|
||||||
|
browser {
|
||||||
|
val rootDirPath = project.rootDir.path
|
||||||
|
val projectDirPath = project.projectDir.path
|
||||||
|
commonWebpackConfig {
|
||||||
|
outputFileName = "composeApp.js"
|
||||||
|
devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply {
|
||||||
|
static = (static ?: mutableListOf()).apply {
|
||||||
|
// Serve sources to debug inside browser
|
||||||
|
add(rootDirPath)
|
||||||
|
add(projectDirPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
binaries.executable()
|
binaries.executable()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
androidMain.dependencies {
|
|
||||||
implementation(compose.preview)
|
|
||||||
implementation(libs.androidx.activityCompose)
|
|
||||||
implementation(libs.kotlinx.coroutines.android)
|
|
||||||
implementation(libs.ktor.client.okhttp)
|
|
||||||
implementation(libs.kstore.file)
|
|
||||||
}
|
|
||||||
|
|
||||||
commonMain.dependencies {
|
commonMain.dependencies {
|
||||||
implementation(compose.runtime)
|
implementation(compose.runtime)
|
||||||
implementation(compose.foundation)
|
implementation(compose.foundation)
|
||||||
implementation(compose.material3)
|
implementation(compose.material3)
|
||||||
implementation(compose.materialIconsExtended)
|
implementation(compose.materialIconsExtended)
|
||||||
implementation(compose.components.resources)
|
implementation(compose.components.resources)
|
||||||
implementation(compose.components.uiToolingPreview)
|
|
||||||
implementation(libs.androidx.navigation.compose)
|
implementation(libs.androidx.navigation.compose)
|
||||||
implementation(libs.coil)
|
implementation(libs.coil)
|
||||||
implementation(libs.coil.network.ktor)
|
implementation(libs.coil.network.ktor)
|
||||||
implementation(libs.kotlinx.coroutines.core)
|
implementation(libs.kotlinx.coroutines.core)
|
||||||
implementation(libs.ktor.client.core)
|
implementation(libs.ktor.core)
|
||||||
implementation(libs.ktor.client.content.negotiation)
|
implementation(libs.ktor.client.content.negotiation)
|
||||||
implementation(libs.ktor.kotlinx.serialization.json)
|
implementation(libs.ktor.kotlinx.serialization.json)
|
||||||
implementation(libs.kotlinx.serialization.json)
|
implementation(libs.kotlinx.serialization.json)
|
||||||
@@ -80,12 +102,20 @@ kotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
commonTest.dependencies {
|
commonTest.dependencies {
|
||||||
implementation(libs.kotlin.test)
|
implementation(kotlin("test"))
|
||||||
@OptIn(ExperimentalComposeLibrary::class)
|
@OptIn(ExperimentalComposeLibrary::class)
|
||||||
implementation(compose.uiTest)
|
implementation(compose.uiTest)
|
||||||
implementation(libs.kotlinx.coroutines.test)
|
implementation(libs.kotlinx.coroutines.test)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
androidMain.dependencies {
|
||||||
|
implementation(compose.uiTooling)
|
||||||
|
implementation(libs.androidx.activityCompose)
|
||||||
|
implementation(libs.kotlinx.coroutines.android)
|
||||||
|
implementation(libs.ktor.client.okhttp)
|
||||||
|
implementation(libs.kstore.file)
|
||||||
|
}
|
||||||
|
|
||||||
jvmMain.dependencies {
|
jvmMain.dependencies {
|
||||||
implementation(compose.desktop.currentOs)
|
implementation(compose.desktop.currentOs)
|
||||||
implementation(libs.kotlinx.coroutines.swing)
|
implementation(libs.kotlinx.coroutines.swing)
|
||||||
@@ -94,16 +124,20 @@ kotlin {
|
|||||||
implementation(libs.kstore.file)
|
implementation(libs.kstore.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
iosMain.dependencies {
|
findByName("iosMain")?.run {
|
||||||
|
dependencies {
|
||||||
implementation(libs.ktor.client.darwin)
|
implementation(libs.ktor.client.darwin)
|
||||||
implementation(libs.kstore.file)
|
implementation(libs.kstore.file)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
webMain.dependencies {
|
findByName("wasmJsMain")?.run {
|
||||||
|
dependencies {
|
||||||
implementation(libs.kstore.storage)
|
implementation(libs.kstore.storage)
|
||||||
implementation(libs.ktor.client.js)
|
implementation(libs.ktor.client.js)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@@ -177,10 +211,6 @@ dependencies {
|
|||||||
debugImplementation(compose.uiTooling)
|
debugImplementation(compose.uiTooling)
|
||||||
}
|
}
|
||||||
|
|
||||||
compose.resources {
|
|
||||||
nameOfResClass = "R"
|
|
||||||
}
|
|
||||||
|
|
||||||
compose.desktop {
|
compose.desktop {
|
||||||
application {
|
application {
|
||||||
mainClass = "MainKt"
|
mainClass = "MainKt"
|
||||||
@@ -192,12 +222,3 @@ compose.desktop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
|
||||||
compilerOptions.freeCompilerArgs.addAll(
|
|
||||||
"-opt-in=kotlin.RequiresOptIn",
|
|
||||||
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
|
||||||
"-opt-in=kotlinx.coroutines.FlowPreview",
|
|
||||||
"-Xexpect-actual-classes"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
package dev.meloda.overseerr
|
|
||||||
|
|
||||||
import android.os.Build
|
|
||||||
|
|
||||||
class AndroidPlatform : Platform {
|
|
||||||
override val name: String = "Android ${Build.VERSION.SDK_INT}"
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun getPlatform(): Platform = AndroidPlatform()
|
|
||||||
@@ -1,5 +1,16 @@
|
|||||||
package dev.meloda.overseerr.common
|
package dev.meloda.overseerr.common
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import dev.meloda.overseerr.di.appModule
|
||||||
|
import org.koin.core.context.startKoin
|
||||||
|
|
||||||
class AppGlobal : Application()
|
class AppGlobal : Application() {
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
|
||||||
|
startKoin {
|
||||||
|
modules(appModule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,19 +8,16 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import dev.meloda.overseerr.datastore.SettingsController
|
import dev.meloda.overseerr.datastore.SettingsController
|
||||||
import dev.meloda.overseerr.di.appModule
|
|
||||||
import dev.meloda.overseerr.screens.main.MainScreen
|
import dev.meloda.overseerr.screens.main.MainScreen
|
||||||
import dev.meloda.overseerr.theme.AppTheme
|
import dev.meloda.overseerr.theme.AppTheme
|
||||||
import io.github.aakira.napier.DebugAntilog
|
import io.github.aakira.napier.DebugAntilog
|
||||||
import io.github.aakira.napier.Napier
|
import io.github.aakira.napier.Napier
|
||||||
import org.koin.compose.KoinApplication
|
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
|
|
||||||
var appDir: String = ""
|
var appDir: String = ""
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun App() {
|
internal fun App() {
|
||||||
KoinApplication(application = { modules(appModule) }) {
|
|
||||||
LaunchedEffect(true) {
|
LaunchedEffect(true) {
|
||||||
Napier.base(DebugAntilog())
|
Napier.base(DebugAntilog())
|
||||||
}
|
}
|
||||||
@@ -37,5 +34,4 @@ internal fun App() {
|
|||||||
MainScreen()
|
MainScreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
package dev.meloda.overseerr
|
|
||||||
|
|
||||||
interface Platform {
|
|
||||||
val name: String
|
|
||||||
}
|
|
||||||
|
|
||||||
expect fun getPlatform(): Platform
|
|
||||||
+21
-13
@@ -1,35 +1,43 @@
|
|||||||
package dev.meloda.overseerr.datastore
|
package dev.meloda.overseerr.datastore
|
||||||
|
|
||||||
|
import dev.meloda.overseerr.ext.setValue
|
||||||
import dev.meloda.overseerr.datastore.model.AppSettings
|
import dev.meloda.overseerr.datastore.model.AppSettings
|
||||||
import dev.meloda.overseerr.datastore.model.ThemeMode
|
import dev.meloda.overseerr.datastore.model.ThemeMode
|
||||||
import dev.meloda.overseerr.ext.setValue
|
|
||||||
import io.github.xxfast.kstore.KStore
|
import io.github.xxfast.kstore.KStore
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
|
||||||
|
|
||||||
|
interface SettingsController {
|
||||||
|
val settings: StateFlow<AppSettings>
|
||||||
|
|
||||||
class SettingsController(
|
suspend fun saveAppSettings()
|
||||||
private val store: KStore<AppSettings>,
|
suspend fun updateAppSettings(update: (AppSettings) -> AppSettings)
|
||||||
) {
|
suspend fun loadAppSettings(): AppSettings
|
||||||
private val _settings = MutableStateFlow(AppSettings.EMPTY)
|
|
||||||
val settings: StateFlow<AppSettings> = _settings.asStateFlow()
|
|
||||||
|
|
||||||
suspend fun saveAppSettings() {
|
fun updateThemeMode(newThemeMode: ThemeMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
class SettingsControllerImpl(
|
||||||
|
private val store: KStore<AppSettings>
|
||||||
|
) : SettingsController {
|
||||||
|
|
||||||
|
override val settings = MutableStateFlow(AppSettings.EMPTY)
|
||||||
|
|
||||||
|
override suspend fun saveAppSettings() {
|
||||||
store.set(settings.value)
|
store.set(settings.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateAppSettings(update: (AppSettings) -> AppSettings) {
|
override suspend fun updateAppSettings(update: (AppSettings) -> AppSettings) {
|
||||||
store.set(update(settings.value))
|
store.set(update(settings.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun loadAppSettings(): AppSettings {
|
override suspend fun loadAppSettings(): AppSettings {
|
||||||
val loadedSettings = store.get() ?: AppSettings.EMPTY
|
val loadedSettings = store.get() ?: AppSettings.EMPTY
|
||||||
_settings.setValue { loadedSettings }
|
settings.setValue { loadedSettings }
|
||||||
return loadedSettings
|
return loadedSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateThemeMode(newThemeMode: ThemeMode) {
|
override fun updateThemeMode(newThemeMode: ThemeMode) {
|
||||||
_settings.setValue { old -> old.copy(themeMode = newThemeMode) }
|
settings.setValue { old -> old.copy(themeMode = newThemeMode) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -1,11 +1,13 @@
|
|||||||
package dev.meloda.overseerr.datastore.di
|
package dev.meloda.overseerr.datastore.di
|
||||||
|
|
||||||
import dev.meloda.overseerr.datastore.SettingsController
|
import dev.meloda.overseerr.datastore.SettingsController
|
||||||
|
import dev.meloda.overseerr.datastore.SettingsControllerImpl
|
||||||
import dev.meloda.overseerr.datastore.SettingsStoreProvider
|
import dev.meloda.overseerr.datastore.SettingsStoreProvider
|
||||||
import org.koin.core.module.dsl.singleOf
|
import org.koin.core.module.dsl.singleOf
|
||||||
|
import org.koin.dsl.bind
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val dataStoreModule = module {
|
val dataStoreModule = module {
|
||||||
single { SettingsStoreProvider().provideStore() }
|
single { SettingsStoreProvider().provideStore() }
|
||||||
singleOf(::SettingsController)
|
singleOf(::SettingsControllerImpl) bind SettingsController::class
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable
|
|||||||
data class AppSettings(
|
data class AppSettings(
|
||||||
val url: String? = null,
|
val url: String? = null,
|
||||||
val plexToken: String? = null,
|
val plexToken: String? = null,
|
||||||
val themeMode: ThemeMode = ThemeMode.System
|
val themeMode: ThemeMode = ThemeMode.System,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
val EMPTY: AppSettings = AppSettings()
|
val EMPTY: AppSettings = AppSettings()
|
||||||
|
|||||||
+1
@@ -21,6 +21,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import dev.chrisbanes.haze.hazeSource
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
|
import dev.chrisbanes.haze.materials.HazeMaterials
|
||||||
import dev.meloda.overseerr.screens.requests.RequestsViewModel
|
import dev.meloda.overseerr.screens.requests.RequestsViewModel
|
||||||
import dev.meloda.overseerr.screens.requests.RequestsViewModelImpl
|
import dev.meloda.overseerr.screens.requests.RequestsViewModelImpl
|
||||||
import dev.meloda.overseerr.screens.requests.model.RequestsScreenState
|
import dev.meloda.overseerr.screens.requests.model.RequestsScreenState
|
||||||
|
|||||||
+1
@@ -6,6 +6,7 @@ import androidx.compose.foundation.text.KeyboardOptions
|
|||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
package dev.meloda.overseerr
|
|
||||||
|
|
||||||
import platform.UIKit.UIDevice
|
|
||||||
|
|
||||||
class IOSPlatform : Platform {
|
|
||||||
override val name: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun getPlatform(): Platform = IOSPlatform()
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package dev.meloda.overseerr.model
|
||||||
|
|
||||||
|
internal actual class Platform actual constructor() {
|
||||||
|
actual val name: String
|
||||||
|
get() = "iOS"
|
||||||
|
}
|
||||||
-8
@@ -1,8 +0,0 @@
|
|||||||
package dev.meloda.overseerr.network
|
|
||||||
|
|
||||||
import io.ktor.client.engine.HttpClientEngineFactory
|
|
||||||
import io.ktor.client.engine.darwin.Darwin
|
|
||||||
|
|
||||||
actual class HttpClientEngineFactoryProvider actual constructor() {
|
|
||||||
actual fun get(): HttpClientEngineFactory<*> = Darwin
|
|
||||||
}
|
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package dev.meloda.overseerr.network.model
|
||||||
|
|
||||||
|
import io.ktor.client.engine.*
|
||||||
|
import io.ktor.client.engine.darwin.*
|
||||||
|
|
||||||
|
actual class HttpClientEngineFactoryProvider actual constructor() {
|
||||||
|
actual fun get(): HttpClientEngineFactory<*> = Darwin
|
||||||
|
}
|
||||||
+1
-2
@@ -1,7 +1,6 @@
|
|||||||
package dev.meloda.overseerr.datastore
|
package dev.meloda.overseerr.settings.model
|
||||||
|
|
||||||
import dev.meloda.overseerr.appDir
|
import dev.meloda.overseerr.appDir
|
||||||
import dev.meloda.overseerr.datastore.model.AppSettings
|
|
||||||
import io.github.xxfast.kstore.KStore
|
import io.github.xxfast.kstore.KStore
|
||||||
import io.github.xxfast.kstore.file.storeOf
|
import io.github.xxfast.kstore.file.storeOf
|
||||||
import kotlinx.io.files.Path
|
import kotlinx.io.files.Path
|
||||||
+8
-1
@@ -1,5 +1,12 @@
|
|||||||
import androidx.compose.ui.window.ComposeUIViewController
|
import androidx.compose.ui.window.ComposeUIViewController
|
||||||
import dev.meloda.overseerr.App
|
import dev.meloda.overseerr.App
|
||||||
|
import dev.meloda.overseerr.di.appModule
|
||||||
|
import org.koin.core.context.startKoin
|
||||||
import platform.UIKit.UIViewController
|
import platform.UIKit.UIViewController
|
||||||
|
|
||||||
fun MainViewController(): UIViewController = ComposeUIViewController { App() }
|
fun MainViewController(): UIViewController = ComposeUIViewController {
|
||||||
|
startKoin {
|
||||||
|
modules(appModule)
|
||||||
|
}
|
||||||
|
App()
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package dev.meloda.overseerr
|
|
||||||
|
|
||||||
class JsPlatform : Platform {
|
|
||||||
override val name: String = "Web with Kotlin/JS"
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun getPlatform(): Platform = JsPlatform()
|
|
||||||
-8
@@ -1,8 +0,0 @@
|
|||||||
package dev.meloda.overseerr.network
|
|
||||||
|
|
||||||
import io.ktor.client.engine.HttpClientEngineFactory
|
|
||||||
import io.ktor.client.engine.js.Js
|
|
||||||
|
|
||||||
actual class HttpClientEngineFactoryProvider actual constructor() {
|
|
||||||
actual fun get(): HttpClientEngineFactory<*> = Js
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import kotlinx.browser.window
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
actual fun ResizableWindow(content: @Composable () -> Unit) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier.fillMaxSize(),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.width(window.innerWidth.coerceIn(360..600).dp)
|
|
||||||
.height(window.innerHeight.coerceIn(minimumValue = 360, maximumValue = null).dp)
|
|
||||||
) {
|
|
||||||
content()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package dev.meloda.overseerr
|
|
||||||
|
|
||||||
class JVMPlatform : Platform {
|
|
||||||
override val name: String = "Java ${System.getProperty("java.version")}"
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun getPlatform(): Platform = JVMPlatform()
|
|
||||||
@@ -5,8 +5,10 @@ import androidx.compose.ui.window.application
|
|||||||
import androidx.compose.ui.window.rememberWindowState
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
import dev.meloda.overseerr.App
|
import dev.meloda.overseerr.App
|
||||||
import dev.meloda.overseerr.appDir
|
import dev.meloda.overseerr.appDir
|
||||||
|
import dev.meloda.overseerr.di.appModule
|
||||||
import io.github.aakira.napier.Napier
|
import io.github.aakira.napier.Napier
|
||||||
import net.harawata.appdirs.AppDirsFactory
|
import net.harawata.appdirs.AppDirsFactory
|
||||||
|
import org.koin.compose.KoinApplication
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -26,10 +28,10 @@ fun main() = application {
|
|||||||
state = state,
|
state = state,
|
||||||
onCloseRequest = ::exitApplication
|
onCloseRequest = ::exitApplication
|
||||||
) {
|
) {
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
window.minimumSize = Dimension(320, 480)
|
window.minimumSize = Dimension(320, 480)
|
||||||
}
|
|
||||||
|
|
||||||
|
KoinApplication(application = { modules(appModule) }) {
|
||||||
App()
|
App()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
package dev.meloda.overseerr
|
|
||||||
|
|
||||||
class WasmPlatform : Platform {
|
|
||||||
override val name: String = "Web with Kotlin/Wasm"
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun getPlatform(): Platform = WasmPlatform()
|
|
||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
package dev.meloda.overseerr.network
|
package dev.meloda.overseerr.network
|
||||||
|
|
||||||
import io.ktor.client.engine.HttpClientEngineFactory
|
import io.ktor.client.engine.*
|
||||||
import io.ktor.client.engine.js.Js
|
import io.ktor.client.engine.js.*
|
||||||
|
|
||||||
actual class HttpClientEngineFactoryProvider actual constructor() {
|
actual class HttpClientEngineFactoryProvider actual constructor() {
|
||||||
actual fun get(): HttpClientEngineFactory<*> = Js
|
actual fun get(): HttpClientEngineFactory<*> = Js
|
||||||
|
|||||||
+2
@@ -1,12 +1,14 @@
|
|||||||
package dev.meloda.overseerr.theme
|
package dev.meloda.overseerr.theme
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.navigation.ExperimentalBrowserHistoryApi
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal actual fun SystemAppearance(isDark: Boolean) {
|
internal actual fun SystemAppearance(isDark: Boolean) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalBrowserHistoryApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
internal actual fun NavigationSettings(navController: NavController) {
|
internal actual fun NavigationSettings(navController: NavController) {
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.ComposeViewport
|
||||||
|
import dev.meloda.overseerr.App
|
||||||
|
import dev.meloda.overseerr.di.appModule
|
||||||
|
import kotlinx.browser.document
|
||||||
|
import kotlinx.browser.window
|
||||||
|
import org.koin.compose.KoinApplication
|
||||||
|
|
||||||
|
@OptIn(ExperimentalComposeUiApi::class)
|
||||||
|
fun main() {
|
||||||
|
ComposeViewport(document.body!!) {
|
||||||
|
KoinApplication(application = { modules(appModule) }) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(window.innerWidth.coerceIn(360..600).dp)
|
||||||
|
.height(window.innerHeight.coerceIn(minimumValue = 360, maximumValue = null).dp)
|
||||||
|
) {
|
||||||
|
App()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import kotlinx.browser.window
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
actual fun ResizableWindow(content: @Composable () -> Unit) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier.fillMaxSize(),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.width(window.innerWidth.coerceIn(360..600).dp)
|
|
||||||
.height(window.innerHeight.coerceIn(minimumValue = 360, maximumValue = null).dp)
|
|
||||||
) {
|
|
||||||
content()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Web App</title>
|
<title>Wasm App</title>
|
||||||
<link type="text/css" rel="stylesheet" href="styles.css">
|
<link type="text/css" rel="stylesheet" href="styles.css">
|
||||||
<script type="application/javascript" src="composeApp.js"></script>
|
<script type="application/javascript" src="composeApp.js"></script>
|
||||||
</head>
|
</head>
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
|
||||||
import androidx.compose.ui.window.ComposeViewport
|
|
||||||
import dev.meloda.overseerr.App
|
|
||||||
|
|
||||||
@OptIn(ExperimentalComposeUiApi::class)
|
|
||||||
fun main() {
|
|
||||||
ComposeViewport {
|
|
||||||
ResizableWindow {
|
|
||||||
App()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
expect fun ResizableWindow(content: @Composable () -> Unit)
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* Temporary workaround for [KT-80582](https://youtrack.jetbrains.com/issue/KT-80582)
|
|
||||||
*
|
|
||||||
* This file should be safe to be removed once the ticket is closed and the project is updated to Kotlin version which solves that issue.
|
|
||||||
*/
|
|
||||||
config.watchOptions = config.watchOptions || {
|
|
||||||
ignored: ["**/*.kt", "**/node_modules"]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.devServer) {
|
|
||||||
config.devServer.static = config.devServer.static.map(file => {
|
|
||||||
if (typeof file === "string") {
|
|
||||||
return {
|
|
||||||
directory: file,
|
|
||||||
watch: false,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
+10
-4
@@ -1,16 +1,22 @@
|
|||||||
#Kotlin
|
|
||||||
kotlin.code.style=official
|
|
||||||
kotlin.daemon.jvmargs=-Xmx4G
|
|
||||||
#Gradle
|
#Gradle
|
||||||
org.gradle.jvmargs=-Xmx4096M -Dfile.encoding=UTF-8
|
org.gradle.jvmargs=-Xmx4G
|
||||||
org.gradle.caching=true
|
org.gradle.caching=true
|
||||||
org.gradle.configuration-cache=true
|
org.gradle.configuration-cache=true
|
||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
|
|
||||||
|
#Kotlin
|
||||||
|
kotlin.code.style=official
|
||||||
|
kotlin.daemon.jvmargs=-Xmx4G
|
||||||
|
kotlin.native.ignoreDisabledTargets=true
|
||||||
|
kotlin.native.enableKlibsCrossCompilation=true
|
||||||
|
|
||||||
#Android
|
#Android
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.nonTransitiveRClass=true
|
android.nonTransitiveRClass=true
|
||||||
|
|
||||||
|
include_wasm=true
|
||||||
include_ios=false
|
include_ios=false
|
||||||
|
|
||||||
#Flip this to false when including the ios targets
|
#Flip this to false when including the ios targets
|
||||||
org.gradle.unsafe.configuration-cache=true
|
org.gradle.unsafe.configuration-cache=true
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-c
|
|||||||
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
|
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
|
||||||
kotlinx-coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" }
|
kotlinx-coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" }
|
||||||
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
|
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
|
||||||
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
|
ktor-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
|
||||||
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
|
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
|
||||||
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
|
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
|
||||||
ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" }
|
ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" }
|
||||||
@@ -52,8 +52,6 @@ kstore-storage = { module = "io.github.xxfast:kstore-storage", version.ref = "ks
|
|||||||
appdirs = { module = "net.harawata:appdirs", version.ref = "appdirs" }
|
appdirs = { module = "net.harawata:appdirs", version.ref = "appdirs" }
|
||||||
napier = { module = "io.github.aakira:napier", version.ref = "napier" }
|
napier = { module = "io.github.aakira:napier", version.ref = "napier" }
|
||||||
|
|
||||||
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
|
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
|
multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
|
||||||
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
) -> Bool {
|
) -> Bool {
|
||||||
window = UIWindow(frame: UIScreen.main.bounds)
|
window = UIWindow(frame: UIScreen.main.bounds)
|
||||||
if let window = window {
|
if let window = window {
|
||||||
window.rootViewController = MainViewControllerKt.MainViewController()
|
window.rootViewController = MainKt.MainViewController()
|
||||||
window.makeKeyAndVisible()
|
window.makeKeyAndVisible()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
+13
-13
@@ -4,32 +4,32 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
|||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
google {
|
google {
|
||||||
mavenContent {
|
content {
|
||||||
includeGroupAndSubgroups("androidx")
|
includeGroupByRegex("com\\.android.*")
|
||||||
includeGroupAndSubgroups("com.android")
|
includeGroupByRegex("com\\.google.*")
|
||||||
includeGroupAndSubgroups("com.google")
|
includeGroupByRegex("androidx.*")
|
||||||
|
includeGroupByRegex("android.*")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
plugins {
|
||||||
|
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
|
||||||
|
}
|
||||||
|
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
repositories {
|
repositories {
|
||||||
google {
|
google {
|
||||||
mavenContent {
|
content {
|
||||||
includeGroupAndSubgroups("androidx")
|
includeGroupByRegex("com\\.android.*")
|
||||||
includeGroupAndSubgroups("com.android")
|
includeGroupByRegex("com\\.google.*")
|
||||||
includeGroupAndSubgroups("com.google")
|
includeGroupByRegex("androidx.*")
|
||||||
|
includeGroupByRegex("android.*")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
|
||||||
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
|
|
||||||
}
|
|
||||||
|
|
||||||
include(":composeApp")
|
include(":composeApp")
|
||||||
|
|||||||
Reference in New Issue
Block a user