mirror of
https://github.com/KRTirtho/spotube.git
synced 2026-09-20 06:34:00 +00:00
feat: integrate Nucleus framework for enhanced window management and webview support
This commit is contained in:
parent
d95e1aad70
commit
94903dcc33
@ -20,6 +20,7 @@
|
|||||||
## Dependencies
|
## Dependencies
|
||||||
- `gradle/libs.versions.toml` is the single source of truth for all version pins and library declarations.
|
- `gradle/libs.versions.toml` is the single source of truth for all version pins and library declarations.
|
||||||
- Kotlin: `2.3.0`, JVM target: `11` (compile/target compatibility in both `composeApp/build.gradle.kts` and `plugin_interfaces/build.gradle.kts`).
|
- Kotlin: `2.3.0`, JVM target: `11` (compile/target compatibility in both `composeApp/build.gradle.kts` and `plugin_interfaces/build.gradle.kts`).
|
||||||
|
- **compose-webview (desktop) dispatcher hijack:** `dev.nucleusframework:composewebview` transitively pulls `nucleus.decorated-window-tao`, which registers a `TaoMainDispatcherFactory` (`loadPriority = 100`) via `META-INF/services` that hijacks `Dispatchers.Main` away from the Swing EDT. This breaks lifecycle's `enforceMainThreadIfNeeded` (window fails with "Method addObserver must be called on the main thread"). The app overrides it with `SwingMainDispatcherFactory` (`composeApp/src/jvmMain/.../core/coroutines/`, `loadPriority = Int.MAX_VALUE`) which pins `Dispatchers.Main` back to the Swing EDT. Keep that factory + its `META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory` resource; the long-term fix is in the webview (make the Tao dispatcher opt-in or lower its priority).
|
||||||
|
|
||||||
## Codegen and plugin packaging
|
## Codegen and plugin packaging
|
||||||
- JS plugin bundles: `:js_plugin_example:packageDevelopmentPlugin` and `:js_plugin_example:packageProductionPlugin`. Output is `.smplug` files in `js_plugin_example/build/distributions/`.
|
- JS plugin bundles: `:js_plugin_example:packageDevelopmentPlugin` and `:js_plugin_example:packageProductionPlugin`. Output is `.smplug` files in `js_plugin_example/build/distributions/`.
|
||||||
|
|||||||
@ -33,4 +33,5 @@ plugins {
|
|||||||
alias(libs.plugins.uniffi) apply false
|
alias(libs.plugins.uniffi) apply false
|
||||||
alias(libs.plugins.cargo) apply false
|
alias(libs.plugins.cargo) apply false
|
||||||
alias(libs.plugins.mokkery) apply false
|
alias(libs.plugins.mokkery) apply false
|
||||||
|
alias(libs.plugins.neucleusFramework) apply false
|
||||||
}
|
}
|
||||||
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import gobley.gradle.GobleyHost
|
import gobley.gradle.GobleyHost
|
||||||
import gobley.gradle.cargo.dsl.jvm
|
import gobley.gradle.cargo.dsl.jvm
|
||||||
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
import dev.nucleusframework.desktop.application.dsl.TargetFormat
|
||||||
import org.jetbrains.compose.reload.gradle.ComposeHotRun
|
import org.jetbrains.compose.reload.gradle.ComposeHotRun
|
||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
@ -35,6 +35,7 @@ plugins {
|
|||||||
alias(libs.plugins.uniffi)
|
alias(libs.plugins.uniffi)
|
||||||
alias(libs.plugins.cargo)
|
alias(libs.plugins.cargo)
|
||||||
alias(libs.plugins.mokkery)
|
alias(libs.plugins.mokkery)
|
||||||
|
alias(libs.plugins.neucleusFramework)
|
||||||
kotlin("plugin.atomicfu") version libs.versions.kotlin
|
kotlin("plugin.atomicfu") version libs.versions.kotlin
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,6 +221,10 @@ kotlin {
|
|||||||
|
|
||||||
implementation(libs.appdirs)
|
implementation(libs.appdirs)
|
||||||
implementation(libs.jna)
|
implementation(libs.jna)
|
||||||
|
|
||||||
|
implementation(libs.nucleus.core.runtime)
|
||||||
|
implementation(libs.nucleus.nucleus.application)
|
||||||
|
implementation(libs.nucleus.decorated.window.tao)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,56 +285,56 @@ dependencies {
|
|||||||
debugImplementation(libs.compose.uiTooling)
|
debugImplementation(libs.compose.uiTooling)
|
||||||
}
|
}
|
||||||
|
|
||||||
compose.desktop {
|
nucleus.application {
|
||||||
application {
|
mainClass = "dev.krtirtho.spotube.MainKt"
|
||||||
mainClass = "dev.krtirtho.spotube.MainKt"
|
|
||||||
|
|
||||||
jvmArgs += listOf(
|
jvmArgs += listOf(
|
||||||
"--enable-native-access=ALL-UNNAMED", // need for JNA for compose-webview (wry) to work
|
"--enable-native-access=ALL-UNNAMED", // need for JNA for compose-webview (wry) to work
|
||||||
// --- ADD THESE FOR SPEED & LOW RAM ---
|
// --- ADD THESE FOR SPEED & LOW RAM ---
|
||||||
"-Xms64m", // Start with a tiny heap (prevents grabbing 500MB upfront)
|
"-Xms64m", // Start with a tiny heap (prevents grabbing 500MB upfront)
|
||||||
"-Xmx384m", // Cap the max heap (VLC and WebView need a bit of room)
|
"-Xmx384m", // Cap the max heap (VLC and WebView need a bit of room)
|
||||||
"-XX:TieredStopAtLevel=1", // Disables the heavy C2 compiler. Huge startup speedup!
|
"-XX:TieredStopAtLevel=1", // Disables the heavy C2 compiler. Huge startup speedup!
|
||||||
"-XX:+UseSerialGC" // The Serial GC is the most efficient for heaps under 512MB
|
"-XX:+UseSerialGC" // The Serial GC is the most efficient for heaps under 512MB
|
||||||
|
)
|
||||||
|
|
||||||
|
nativeDistributions {
|
||||||
|
packageName = "dev.krtirtho.spotube"
|
||||||
|
packageVersion = project.findProperty("versionName") as String? ?: "6.0.0"
|
||||||
|
licenseFile = project.file("../LICENSE")
|
||||||
|
|
||||||
|
appResourcesRootDir.set(vlcjBundler.vlcNativesDirectory)
|
||||||
|
|
||||||
|
targetFormats(
|
||||||
|
TargetFormat.Dmg,
|
||||||
|
TargetFormat.Deb,
|
||||||
|
TargetFormat.Rpm,
|
||||||
|
TargetFormat.AppImage,
|
||||||
|
TargetFormat.Msi,
|
||||||
|
TargetFormat.Exe,
|
||||||
)
|
)
|
||||||
|
|
||||||
nativeDistributions {
|
modules("jdk.unsupported")
|
||||||
packageName = "dev.krtirtho.spotube"
|
|
||||||
packageVersion = project.findProperty("versionName") as String? ?: "6.0.0"
|
|
||||||
licenseFile = project.file("../LICENSE")
|
|
||||||
|
|
||||||
targetFormats(
|
linux {
|
||||||
TargetFormat.Dmg,
|
modules("jdk.security.auth")
|
||||||
TargetFormat.Deb,
|
}
|
||||||
TargetFormat.Rpm,
|
windows {
|
||||||
TargetFormat.AppImage,
|
shortcut = true
|
||||||
TargetFormat.Msi,
|
menu = true
|
||||||
TargetFormat.Exe,
|
dirChooser = true
|
||||||
)
|
perUserInstall = true
|
||||||
|
|
||||||
modules("jdk.unsupported")
|
|
||||||
|
|
||||||
linux {
|
|
||||||
modules("jdk.security.auth")
|
|
||||||
}
|
|
||||||
windows {
|
|
||||||
shortcut = true
|
|
||||||
menu = true
|
|
||||||
dirChooser = true
|
|
||||||
perUserInstall = true
|
|
||||||
}
|
|
||||||
|
|
||||||
macOS {
|
|
||||||
notarization {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes.release.proguard {
|
macOS {
|
||||||
configurationFiles.from(project.file("proguard-rules.pro"))
|
notarization {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildTypes.release.proguard {
|
||||||
|
configurationFiles.from(project.file("proguard-rules.pro"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue with compose plugin
|
// Issue with compose plugin
|
||||||
|
|||||||
@ -20,7 +20,7 @@ package dev.krtirtho.spotube.core.webview
|
|||||||
import android.webkit.CookieManager
|
import android.webkit.CookieManager
|
||||||
import android.webkit.WebStorage
|
import android.webkit.WebStorage
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import io.github.kdroidfilter.webview.web.WebViewState
|
import dev.nucleusframework.webview.web.WebViewState
|
||||||
|
|
||||||
actual fun platformWebviewConfig(webView: WebViewState, pluginId: String?) {
|
actual fun platformWebviewConfig(webView: WebViewState, pluginId: String?) {
|
||||||
val nativeWebView = webView.webView?.nativeWebView as? WebView ?: return
|
val nativeWebView = webView.webView?.nativeWebView as? WebView ?: return
|
||||||
|
|||||||
@ -17,9 +17,9 @@
|
|||||||
|
|
||||||
package dev.krtirtho.spotube.core.webview
|
package dev.krtirtho.spotube.core.webview
|
||||||
|
|
||||||
import io.github.kdroidfilter.webview.web.WebContent
|
import dev.nucleusframework.webview.web.WebContent
|
||||||
import io.github.kdroidfilter.webview.web.WebViewNavigator
|
import dev.nucleusframework.webview.web.WebViewNavigator
|
||||||
import io.github.kdroidfilter.webview.cookie.CookieManager
|
import dev.nucleusframework.webview.cookie.CookieManager
|
||||||
import dev.krtirtho.plugin_interfaces.host_apis.Cookie
|
import dev.krtirtho.plugin_interfaces.host_apis.Cookie
|
||||||
import dev.krtirtho.spotube.core.di.injectLogger
|
import dev.krtirtho.spotube.core.di.injectLogger
|
||||||
import dev.krtirtho.spotube.core.navigation.NavigationCommands
|
import dev.krtirtho.spotube.core.navigation.NavigationCommands
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
package dev.krtirtho.spotube.core.webview
|
package dev.krtirtho.spotube.core.webview
|
||||||
|
|
||||||
import io.github.kdroidfilter.webview.web.WebViewState
|
import dev.nucleusframework.webview.web.WebViewState
|
||||||
|
|
||||||
expect fun platformWebviewConfig(webView: WebViewState, pluginId: String?)
|
expect fun platformWebviewConfig(webView: WebViewState, pluginId: String?)
|
||||||
|
|
||||||
|
|||||||
@ -51,13 +51,13 @@ import compose.icons.feathericons.ChevronLeft
|
|||||||
import compose.icons.feathericons.ChevronRight
|
import compose.icons.feathericons.ChevronRight
|
||||||
import compose.icons.feathericons.X
|
import compose.icons.feathericons.X
|
||||||
import dev.krtirtho.spotube.core.tools.user_agents.UserAgents
|
import dev.krtirtho.spotube.core.tools.user_agents.UserAgents
|
||||||
import io.github.kdroidfilter.webview.jsbridge.IJsMessageHandler
|
import dev.nucleusframework.webview.jsbridge.IJsMessageHandler
|
||||||
import io.github.kdroidfilter.webview.jsbridge.JsMessage
|
import dev.nucleusframework.webview.jsbridge.JsMessage
|
||||||
import io.github.kdroidfilter.webview.jsbridge.rememberWebViewJsBridge
|
import dev.nucleusframework.webview.jsbridge.rememberWebViewJsBridge
|
||||||
import io.github.kdroidfilter.webview.web.WebView
|
import dev.nucleusframework.webview.web.WebView
|
||||||
import io.github.kdroidfilter.webview.web.WebViewNavigator
|
import dev.nucleusframework.webview.web.WebViewNavigator
|
||||||
import io.github.kdroidfilter.webview.web.WebViewState
|
import dev.nucleusframework.webview.web.WebViewState
|
||||||
import io.github.kdroidfilter.webview.web.rememberWebViewNavigator
|
import dev.nucleusframework.webview.web.rememberWebViewNavigator
|
||||||
|
|
||||||
class PostMessageHandler(
|
class PostMessageHandler(
|
||||||
private val onMessageReceived: (String) -> Unit = {}
|
private val onMessageReceived: (String) -> Unit = {}
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
package dev.krtirtho.spotube.core.webview
|
package dev.krtirtho.spotube.core.webview
|
||||||
|
|
||||||
import io.github.kdroidfilter.webview.web.WebViewState
|
import dev.nucleusframework.webview.web.WebViewState
|
||||||
import kotlinx.cinterop.ExperimentalForeignApi
|
import kotlinx.cinterop.ExperimentalForeignApi
|
||||||
import platform.Foundation.NSDate
|
import platform.Foundation.NSDate
|
||||||
import platform.Foundation.NSHTTPCookieStorage
|
import platform.Foundation.NSHTTPCookieStorage
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import androidx.compose.foundation.layout.Box
|
|||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.window.WindowDraggableArea
|
import androidx.compose.foundation.window.WindowDraggableArea
|
||||||
@ -44,6 +45,10 @@ import dev.krtirtho.spotube.resources.iconsax.FluentMaximize
|
|||||||
import dev.krtirtho.spotube.resources.iconsax.FluentMinus
|
import dev.krtirtho.spotube.resources.iconsax.FluentMinus
|
||||||
import dev.krtirtho.spotube.resources.iconsax.FluentSquareMultiple
|
import dev.krtirtho.spotube.resources.iconsax.FluentSquareMultiple
|
||||||
import dev.krtirtho.spotube.resources.iconsax.Iconsax
|
import dev.krtirtho.spotube.resources.iconsax.Iconsax
|
||||||
|
import dev.nucleusframework.window.WindowControls
|
||||||
|
import dev.nucleusframework.window.WindowControlsRenderer
|
||||||
|
import dev.nucleusframework.window.WindowDoubleClickAction
|
||||||
|
import dev.nucleusframework.window.windowDragArea
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
|
|
||||||
|
|
||||||
@ -55,27 +60,27 @@ actual fun ApplicationMainBar(
|
|||||||
actions: @Composable (RowScope.() -> Unit),
|
actions: @Composable (RowScope.() -> Unit),
|
||||||
backButton: Boolean,
|
backButton: Boolean,
|
||||||
) {
|
) {
|
||||||
LocalWindowScope.current.WindowDraggableArea {
|
Box(
|
||||||
Box(
|
modifier = Modifier.fillMaxWidth()
|
||||||
modifier = Modifier.fillMaxWidth()
|
.windowDragArea(doubleClickAction = WindowDoubleClickAction.ToggleMaximize)
|
||||||
) {
|
) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = title,
|
title = title,
|
||||||
actions = {
|
actions = {
|
||||||
actions()
|
actions()
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
if (backButton) {
|
if (backButton) {
|
||||||
ApplicationBackButton()
|
ApplicationBackButton()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
subtitle = subtitle,
|
subtitle = subtitle,
|
||||||
modifier = Modifier.padding(end = 125.dp) // To avoid overlap with window buttons
|
modifier = Modifier.padding(end = 125.dp) // To avoid overlap with window buttons
|
||||||
)
|
)
|
||||||
WindowButtons(
|
LocalWindowScope.current.WindowControls(
|
||||||
modifier = Modifier.align(Alignment.TopEnd)
|
modifier = Modifier.align(Alignment.TopEnd).heightIn(max = 48.dp),
|
||||||
)
|
renderer = WindowControlsRenderer.Platform, // default
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,8 @@ package dev.krtirtho.spotube.core.ui.component
|
|||||||
|
|
||||||
import androidx.compose.runtime.staticCompositionLocalOf
|
import androidx.compose.runtime.staticCompositionLocalOf
|
||||||
import androidx.compose.ui.window.ApplicationScope
|
import androidx.compose.ui.window.ApplicationScope
|
||||||
|
import dev.nucleusframework.application.NucleusApplicationScope
|
||||||
|
|
||||||
val LocalApplicationScope = staticCompositionLocalOf<ApplicationScope> {
|
val LocalApplicationScope = staticCompositionLocalOf< NucleusApplicationScope> {
|
||||||
error("No ApplicationScope found in LocalApplicationScope")
|
error("No ApplicationScope found in LocalApplicationScope")
|
||||||
}
|
}
|
||||||
@ -18,11 +18,11 @@
|
|||||||
package dev.krtirtho.spotube.core.ui.component
|
package dev.krtirtho.spotube.core.ui.component
|
||||||
|
|
||||||
import androidx.compose.runtime.compositionLocalOf
|
import androidx.compose.runtime.compositionLocalOf
|
||||||
import androidx.compose.ui.window.FrameWindowScope
|
|
||||||
import androidx.compose.ui.window.WindowState
|
import androidx.compose.ui.window.WindowState
|
||||||
|
import dev.nucleusframework.application.NucleusDecoratedWindowScope
|
||||||
|
|
||||||
// LocalWindow is a LocalComposition that provides access to the current Window instance in the composition hierarchy.
|
// LocalWindow is a LocalComposition that provides access to the current Window instance in the composition hierarchy.
|
||||||
val LocalWindowScope = compositionLocalOf<FrameWindowScope> {
|
val LocalWindowScope = compositionLocalOf<NucleusDecoratedWindowScope> {
|
||||||
error("No Window found in LocalWindowScope")
|
error("No Window found in LocalWindowScope")
|
||||||
}
|
}
|
||||||
val LocalWindowState = compositionLocalOf<WindowState> {
|
val LocalWindowState = compositionLocalOf<WindowState> {
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
package dev.krtirtho.spotube.core.webview
|
package dev.krtirtho.spotube.core.webview
|
||||||
|
|
||||||
import dev.krtirtho.spotube.core.paths.Paths
|
import dev.krtirtho.spotube.core.paths.Paths
|
||||||
import io.github.kdroidfilter.webview.web.WebViewState
|
import dev.nucleusframework.webview.web.WebViewState
|
||||||
import okio.FileSystem
|
import okio.FileSystem
|
||||||
import okio.Path.Companion.toPath
|
import okio.Path.Companion.toPath
|
||||||
import org.koin.core.context.GlobalContext
|
import org.koin.core.context.GlobalContext
|
||||||
|
|||||||
@ -25,9 +25,6 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Window
|
|
||||||
import androidx.compose.ui.window.WindowDecoration
|
|
||||||
import androidx.compose.ui.window.application
|
|
||||||
import androidx.compose.ui.window.rememberWindowState
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
import dev.krtirtho.spotube.core.di.initKoin
|
import dev.krtirtho.spotube.core.di.initKoin
|
||||||
import dev.krtirtho.spotube.core.newpipe.NewPipeDownloader
|
import dev.krtirtho.spotube.core.newpipe.NewPipeDownloader
|
||||||
@ -37,6 +34,9 @@ import dev.krtirtho.spotube.core.ui.component.LocalApplicationScope
|
|||||||
import dev.krtirtho.spotube.core.ui.component.LocalWindowScope
|
import dev.krtirtho.spotube.core.ui.component.LocalWindowScope
|
||||||
import dev.krtirtho.spotube.core.ui.component.LocalWindowState
|
import dev.krtirtho.spotube.core.ui.component.LocalWindowState
|
||||||
import dev.krtirtho.spotube.modules.settings.SettingsProvider
|
import dev.krtirtho.spotube.modules.settings.SettingsProvider
|
||||||
|
import dev.nucleusframework.application.DecoratedWindow
|
||||||
|
import dev.nucleusframework.application.NucleusBackend
|
||||||
|
import dev.nucleusframework.application.nucleusApplication
|
||||||
import io.github.vinceglb.filekit.FileKit
|
import io.github.vinceglb.filekit.FileKit
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -61,7 +61,7 @@ fun main() {
|
|||||||
NewPipeDownloader.init(KoinPathsProvider.paths)
|
NewPipeDownloader.init(KoinPathsProvider.paths)
|
||||||
val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||||
|
|
||||||
application {
|
nucleusApplication(backend = NucleusBackend.Tao) {
|
||||||
val windowState = rememberWindowState(
|
val windowState = rememberWindowState(
|
||||||
width = 1080.dp,
|
width = 1080.dp,
|
||||||
height = 720.dp
|
height = 720.dp
|
||||||
@ -84,7 +84,7 @@ fun main() {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
Window(
|
DecoratedWindow(
|
||||||
state = windowState,
|
state = windowState,
|
||||||
onCloseRequest = {
|
onCloseRequest = {
|
||||||
if (minimizeToTray) {
|
if (minimizeToTray) {
|
||||||
@ -96,12 +96,11 @@ fun main() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
title = "Spotube",
|
title = "Spotube",
|
||||||
decoration = WindowDecoration.Undecorated(),
|
|
||||||
visible = isWindowVisible,
|
visible = isWindowVisible,
|
||||||
) {
|
) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalApplicationScope provides this@application,
|
LocalApplicationScope provides this@nucleusApplication,
|
||||||
LocalWindowScope provides this@Window,
|
LocalWindowScope provides this@DecoratedWindow,
|
||||||
LocalWindowState provides windowState
|
LocalWindowState provides windowState
|
||||||
) {
|
) {
|
||||||
App()
|
App()
|
||||||
|
|||||||
@ -47,6 +47,7 @@ materialKolor = "4.1.1"
|
|||||||
murmurhash = "0.4.2"
|
murmurhash = "0.4.2"
|
||||||
newpipeextractor = "v0.26.2"
|
newpipeextractor = "v0.26.2"
|
||||||
newpipeExtractorKmp = "1.3.0"
|
newpipeExtractorKmp = "1.3.0"
|
||||||
|
nucleusNucleusApplication = "2.4.4"
|
||||||
semver = "2.1.0"
|
semver = "2.1.0"
|
||||||
vlcj = "4.12.1"
|
vlcj = "4.12.1"
|
||||||
vlcjNative = "4.12.0"
|
vlcjNative = "4.12.0"
|
||||||
@ -56,7 +57,7 @@ kotlinStdlib = "2.3.21"
|
|||||||
runner = "1.7.0"
|
runner = "1.7.0"
|
||||||
core = "1.7.0"
|
core = "1.7.0"
|
||||||
filekit = "0.14.2"
|
filekit = "0.14.2"
|
||||||
compose-webview = "0.1.0-SNAPSHOT"
|
compose-webview = "1.0.1"
|
||||||
koin = "4.2.2"
|
koin = "4.2.2"
|
||||||
multiplatform-nav3-ui = "1.1.1"
|
multiplatform-nav3-ui = "1.1.1"
|
||||||
compose-multiplatform-adaptive = "1.3.0-beta02"
|
compose-multiplatform-adaptive = "1.3.0-beta02"
|
||||||
@ -119,6 +120,9 @@ material-kolor = { module = "com.materialkolor:material-kolor", version.ref = "m
|
|||||||
murmurhash = { module = "com.goncalossilva:murmurhash", version.ref = "murmurhash" }
|
murmurhash = { module = "com.goncalossilva:murmurhash", version.ref = "murmurhash" }
|
||||||
newpipe-extractor-kmp = { module = "io.github.yushosei:newpipe-extractor-kmp", version.ref = "newpipeExtractorKmp" }
|
newpipe-extractor-kmp = { module = "io.github.yushosei:newpipe-extractor-kmp", version.ref = "newpipeExtractorKmp" }
|
||||||
newpipeextractor = { module = "com.github.teamnewpipe:NewPipeExtractor", version.ref = "newpipeextractor" }
|
newpipeextractor = { module = "com.github.teamnewpipe:NewPipeExtractor", version.ref = "newpipeextractor" }
|
||||||
|
nucleus-core-runtime = { module = "dev.nucleusframework:nucleus.core-runtime", version.ref = "nucleusNucleusApplication" }
|
||||||
|
nucleus-decorated-window-tao = { module = "dev.nucleusframework:nucleus.decorated-window-tao", version.ref = "nucleusNucleusApplication" }
|
||||||
|
nucleus-nucleus-application = { module = "dev.nucleusframework:nucleus.nucleus-application", version.ref = "nucleusNucleusApplication" }
|
||||||
semver = { module = "net.swiftzer.semver:semver", version.ref = "semver" }
|
semver = { module = "net.swiftzer.semver:semver", version.ref = "semver" }
|
||||||
vlcj = { module = "uk.co.caprica:vlcj", version.ref = "vlcj" }
|
vlcj = { module = "uk.co.caprica:vlcj", version.ref = "vlcj" }
|
||||||
vlcj-natives = { module = "uk.co.caprica:vlcj-natives", version.ref = "vlcjNative" }
|
vlcj-natives = { module = "uk.co.caprica:vlcj-natives", version.ref = "vlcjNative" }
|
||||||
@ -140,7 +144,7 @@ androidx-core = { group = "androidx.test", name = "core", version.ref = "core" }
|
|||||||
filekit-core = { group = "io.github.vinceglb", name = "filekit-core", version.ref = "filekit" }
|
filekit-core = { group = "io.github.vinceglb", name = "filekit-core", version.ref = "filekit" }
|
||||||
filekit-dialogs = { group = "io.github.vinceglb", name = "filekit-dialogs", version.ref = "filekit" }
|
filekit-dialogs = { group = "io.github.vinceglb", name = "filekit-dialogs", version.ref = "filekit" }
|
||||||
filekit-dialogs-compose = { group = "io.github.vinceglb", name = "filekit-dialogs-compose", version.ref = "filekit" }
|
filekit-dialogs-compose = { group = "io.github.vinceglb", name = "filekit-dialogs-compose", version.ref = "filekit" }
|
||||||
compose-webview = { module = "io.github.kdroidfilter:composewebview", version.ref = "compose-webview" }
|
compose-webview = { module = "dev.nucleusframework:composewebview", version.ref = "compose-webview" }
|
||||||
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
|
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
|
||||||
koin-compose = { module = "io.insert-koin:koin-compose", version.ref = "koin" }
|
koin-compose = { module = "io.insert-koin:koin-compose", version.ref = "koin" }
|
||||||
koin-compose-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel", version.ref = "koin" }
|
koin-compose-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel", version.ref = "koin" }
|
||||||
@ -182,4 +186,5 @@ kotlinxAtomicFu = { id = "org.jetbrains.kotlinx.atomicfu", version.ref = "kotlin
|
|||||||
uniffi = { id = "dev.gobley.uniffi", version.ref = "uniffi" }
|
uniffi = { id = "dev.gobley.uniffi", version.ref = "uniffi" }
|
||||||
cargo = { id = "dev.gobley.cargo", version.ref = "uniffi" }
|
cargo = { id = "dev.gobley.cargo", version.ref = "uniffi" }
|
||||||
mokkery = { id = "dev.mokkery", version.ref = "mokkery" }
|
mokkery = { id = "dev.mokkery", version.ref = "mokkery" }
|
||||||
vanniktechMavenPublish = { id = "com.vanniktech.maven.publish", version.ref = "vanniktechMavenPublish" }
|
vanniktechMavenPublish = { id = "com.vanniktech.maven.publish", version.ref = "vanniktechMavenPublish" }
|
||||||
|
neucleusFramework = { id = "dev.nucleusframework", version.ref = "nucleusNucleusApplication" }
|
||||||
Loading…
Reference in New Issue
Block a user