Просмотр исходного кода

code improvements

code improvements

code improvements

code improvements

code improvements

code improvements

code improvements

code improvements

code improvements

code improvements

code improvements

code improvements

code improvements

code improvements

code improvements
Milan Jurkulak 1 год назад
Родитель
Сommit
718277f36b
34 измененных файлов с 347 добавлено и 668 удалено
  1. 0 15
      build.gradle.kts
  2. 29 2
      buildSrc/build.gradle.kts
  3. 17 20
      buildSrc/src/main/kotlin/BuildExt.kt
  4. 26 9
      buildSrc/src/main/kotlin/KotlinDependencyHandlerExt.kt
  5. 29 52
      composeApp/composeApp.gradle.kts
  6. 1 1
      composeApp/src/androidMain/kotlin/org/mjdev/desktop/context/DesktopContext.kt
  7. 1 1
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/chart/DonutChart.kt
  8. 1 1
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/desktoppanel/applets/DesktopPanelIcon.kt
  9. 0 28
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/web/ComposeWebView.kt
  10. 0 23
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/web/CookieManagerCompat.kt
  11. 0 86
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/web/WebEngineKt.kt
  12. 26 236
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/web/WebView.kt
  13. 0 23
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/web/WebViewImpl.kt
  14. 17 5
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/extensions/CustomExt.kt
  15. 1 0
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/extensions/FocusState.kt
  16. 2 1
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/extensions/LaunchedEffect.kt
  17. 11 2
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/extensions/System.kt
  18. 1 1
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/log/Log.kt
  19. 0 2
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/AiManager.kt
  20. 4 2
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/actions/ActionCurrentTime.kt
  21. 1 1
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/actions/base/ActionsProvider.kt
  22. 6 3
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/plugins/AiPluginEmpty.kt
  23. 35 38
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/plugins/AiPluginGemini.kt
  24. 30 8
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/plugins/AiPluginOllama.kt
  25. 35 60
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/plugins/AiPluginOpenAi.kt
  26. 0 10
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/plugins/AiPluginPerplexity.kt
  27. 6 0
      composeApp/src/desktopMain/kotlin/org/mjdev/desktop/components/main/MainWindow.kt
  28. 1 3
      composeApp/src/desktopMain/kotlin/org/mjdev/desktop/context/DeskptopContext.kt
  29. 4 5
      composeApp/src/desktopMain/kotlin/org/mjdev/desktop/main/Main.kt
  30. 6 2
      composeApp/src/desktopMain/kotlin/org/mjdev/desktop/managers/apps/AppsManager.kt
  31. 6 5
      composeApp/src/desktopMain/kotlin/org/mjdev/desktop/managers/theme/linux/ThemeManagerLinux.kt
  32. 1 1
      gradle.properties
  33. 33 7
      gradle/libs.versions.toml
  34. 17 15
      settings.gradle.kts

+ 0 - 15
build.gradle.kts

@@ -14,7 +14,6 @@ plugins {
     alias(libs.plugins.gradle.ktlint)
     alias(libs.plugins.gradle.ktlint)
     alias(libs.plugins.manes.versions) apply false
     alias(libs.plugins.manes.versions) apply false
     alias(libs.plugins.kotlin.android) apply false
     alias(libs.plugins.kotlin.android) apply false
-//    alias(libs.plugins.vlc.setup) apply true
 //    id("com.github.gmazzo.buildconfig") version "5.6.5"
 //    id("com.github.gmazzo.buildconfig") version "5.6.5"
 }
 }
 
 
@@ -45,20 +44,6 @@ plugins {
 //    buildConfigField("com.github.gmazzo.buildconfig.demos.kts.SomeData", "DATA", "SomeData(\"a\", 1)")
 //    buildConfigField("com.github.gmazzo.buildconfig.demos.kts.SomeData", "DATA", "SomeData(\"a\", 1)")
 //}
 //}
 
 
-// vlc setup
-//vlcSetup {
-//    // todo
-//    //val vlcVersionLibs: String = libs.versions.vlc.get().toString()
-//    vlcVersion.set("3.0.21-2")
-//
-//    shouldCompressVlcFiles = true
-//    shouldIncludeAllVlcFiles = true
-//
-//    pathToCopyVlcLinuxFilesTo = rootDir.resolve("composeApp/src/commonMain/composeResources/vlc/")
-//    pathToCopyVlcMacosFilesTo = rootDir.resolve("composeApp/src/commonMain/composeResources/vlc/")
-//    pathToCopyVlcLinuxFilesTo = rootDir.resolve("composeApp/src/commonMain/composeResources/vlc/")
-//}
-
 //dependencies {
 //dependencies {
 //    kover(project(":composeApp"))
 //    kover(project(":composeApp"))
 //}
 //}

+ 29 - 2
buildSrc/build.gradle.kts

@@ -2,12 +2,35 @@
 
 
 plugins {
 plugins {
     `kotlin-dsl`
     `kotlin-dsl`
+    alias(libs.plugins.kotlin.multiplatform) apply false
 }
 }
 
 
 repositories {
 repositories {
     mavenLocal()
     mavenLocal()
     gradlePluginPortal()
     gradlePluginPortal()
     mavenCentral()
     mavenCentral()
+    maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
+    maven("https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental")
+    maven("https://androidx.dev/storage/compose-compiler/repository")
+    maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev")
+    maven("https://gitlab.com/api/v4/projects/38224197/packages/maven")
+    maven("https://oss.sonatype.org/content/repositories/snapshots")
+    maven("https://jogamp.org/deployment/maven")
+    maven("https://jitpack.io")
+    maven("https://maven.mozilla.org/maven2/")
+    maven("https://maven.pkg.github.com/tuProlog/2p-kt")
+    maven("https://dl.bintray.com/animeshz/maven")
+    maven("https://plugins.gradle.org/m2/")
+    maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
+    maven("https://dl.bintray.com/kotlin/ktor")
+    maven("https://central.sonatype.com/repository/maven-snapshots")
+//        google {
+//            mavenContent {
+//                includeGroupAndSubgroups("androidx")
+//                includeGroupAndSubgroups("com.android")
+//                includeGroupAndSubgroups("com.google")
+//            }
+//        }
     google()
     google()
 }
 }
 
 
@@ -41,9 +64,13 @@ val TASK_BUILD_PLUGIN = "installPlugin"
 val PROJECT_IDE_PLUGIN = "studio-plugin"
 val PROJECT_IDE_PLUGIN = "studio-plugin"
 val DEPENDENCY_BUILD_SRC = ":$PROJECT_IDE_PLUGIN:$TASK_BUILD_PLUGIN"
 val DEPENDENCY_BUILD_SRC = ":$PROJECT_IDE_PLUGIN:$TASK_BUILD_PLUGIN"
 
 
-fun Task.execute(action: Action<ExecSpec>) = this.project.providers.exec(action)
+fun Task.execute(
+    action: Action<ExecSpec>
+) = project.providers.exec(action)
+
 val Task.pluginProject
 val Task.pluginProject
-    get() = this.project.rootProject.project(PROJECT_IDE_PLUGIN)
+    get() = project.rootProject.project(PROJECT_IDE_PLUGIN)
+
 val Task.pluginDistributionFile
 val Task.pluginDistributionFile
     get() = "${pluginProject.path}/$FOLDER_BUILD/$FOLDER_DISTRIBUTION/$PLUGIN_FILE_NAME"
     get() = "${pluginProject.path}/$FOLDER_BUILD/$FOLDER_DISTRIBUTION/$PLUGIN_FILE_NAME"
 
 

+ 17 - 20
buildSrc/src/main/kotlin/BuildExt.kt

@@ -1,25 +1,23 @@
-import org.gradle.api.NamedDomainObjectContainer
 import org.gradle.api.Project
 import org.gradle.api.Project
 import org.gradle.api.plugins.JavaPluginExtension
 import org.gradle.api.plugins.JavaPluginExtension
 import org.gradle.api.provider.Provider
 import org.gradle.api.provider.Provider
 import org.gradle.jvm.toolchain.JavaLanguageVersion
 import org.gradle.jvm.toolchain.JavaLanguageVersion
 import org.gradle.kotlin.dsl.getByType
 import org.gradle.kotlin.dsl.getByType
-import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
 
 
-enum class OS { WINDOWS, LINUX, MAC, OTHER }
-
-fun getCurrentOs(): OS {
-    val osName = System
-        .getProperty("os.name")
-        .lowercase()
-        .trim()
-    return when {
-        osName.startsWith("win") -> OS.WINDOWS
-        osName.startsWith("mac") -> OS.MAC
-        osName == "linux" -> OS.LINUX
-        else -> OS.OTHER
-    }
-}
+//enum class OS { WINDOWS, LINUX, MAC, OTHER }
+
+//fun getCurrentOs(): OS {
+//    val osName = System
+//        .getProperty("os.name")
+//        .lowercase()
+//        .trim()
+//    return when {
+//        osName.startsWith("win") -> OS.WINDOWS
+//        osName.startsWith("mac") -> OS.MAC
+//        osName == "linux" -> OS.LINUX
+//        else -> OS.OTHER
+//    }
+//}
 
 
 val Project.java: JavaPluginExtension
 val Project.java: JavaPluginExtension
     get() = extensions.getByType()
     get() = extensions.getByType()
@@ -32,9 +30,9 @@ fun Project.setJavaLanguageVersion(
     java.toolchain.languageVersion.set(jlv)
     java.toolchain.languageVersion.set(jlv)
 }
 }
 
 
-fun NamedDomainObjectContainer<KotlinSourceSet>.getOrCreate(
-    name: String
-): KotlinSourceSet = findByName(name) ?: create(name)
+//fun NamedDomainObjectContainer<KotlinSourceSet>.getOrCreate(
+//    name: String
+//): KotlinSourceSet = findByName(name) ?: create(name)
 
 
 //fun Project.kotlinSourceSets(
 //fun Project.kotlinSourceSets(
 //    config: Action<NamedDomainObjectContainer<KotlinSourceSet>>
 //    config: Action<NamedDomainObjectContainer<KotlinSourceSet>>
@@ -61,4 +59,3 @@ fun NamedDomainObjectContainer<KotlinSourceSet>.getOrCreate(
 //) = with(kotlin) {
 //) = with(kotlin) {
 //    sourceSets(config)
 //    sourceSets(config)
 //}
 //}
-

+ 26 - 9
buildSrc/src/main/kotlin/KotlinDependencyHandlerExt.kt

@@ -1,9 +1,26 @@
-//    fun KotlinDependencyHandler.kapt(
-//        dependency:String
-//    ) = configurations["kapt"].dependencies.add(dependency)
-
-//    fun DependencyHandlerScope.kapt(
-//        dependency: Provider<MinimalExternalModuleDependency>
-//    ) {
-//        configurations["kapt"].dependencies.add(dependency.get())
-//    }
+import org.gradle.api.Action
+import org.gradle.api.NamedDomainObjectContainer
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Dependency
+import org.gradle.api.artifacts.MinimalExternalModuleDependency
+import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
+import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
+
+//fun KotlinDependencyHandler.kapt(
+//    dependency: String
+//) = configurations["kapt"].dependencies.add(dependency)
+
+//fun DependencyHandlerScope.kapt(
+//    dependency: Provider<MinimalExternalModuleDependency>
+//) {
+//    configurations["kapt"].dependencies.add(dependency.get())
+//}
+
+//fun Project.kotlinSourceSets(
+//    config: Action<NamedDomainObjectContainer<KotlinSourceSet>>
+//) = with(kotlin) {
+//    sourceSets(config)
+//}
+
+fun KotlinDependencyHandler.implementationPlatform(dependencyNotation: Any): Dependency? =
+    implementation(project.dependencies.platform(dependencyNotation))

+ 29 - 52
composeApp/composeApp.gradle.kts

@@ -31,6 +31,7 @@ plugins {
     alias(libs.plugins.compose)
     alias(libs.plugins.compose)
     alias(libs.plugins.compose.compiler)
     alias(libs.plugins.compose.compiler)
     alias(libs.plugins.vlc.setup)
     alias(libs.plugins.vlc.setup)
+    alias(libs.plugins.devtools.ksp)
 }
 }
 
 
 //</editor-fold>------------------------------------------------------------------------------------
 //</editor-fold>------------------------------------------------------------------------------------
@@ -51,11 +52,6 @@ fun KotlinTargetContainerWithPresetFunctions.desktopTarget(
     configure.execute(this)
     configure.execute(this)
 }
 }
 
 
-@OptIn(ExperimentalWasmDsl::class)
-fun KotlinTargetContainerWithWasmPresetFunctions.wasmJsTarget(
-    configure: Action<KotlinWasmJsTargetDsl>
-) = wasmJs(configure)
-
 val Project.compose: ComposeExtension
 val Project.compose: ComposeExtension
     get() = extensions.getByType()
     get() = extensions.getByType()
 
 
@@ -71,20 +67,6 @@ fun targets(
     config: Action<KotlinMultiplatformExtension>
     config: Action<KotlinMultiplatformExtension>
 ) = kotlin(config)
 ) = kotlin(config)
 
 
-// todo
-@Suppress("UNUSED_PARAMETER", "UnusedReceiverParameter")
-fun Project.wasmjs(config: DesktopExtension.() -> Unit) {
-    // todo
-//    compose.wasmJs(config)
-}
-
-// todo
-fun Project.kotlinSourceSets(
-    config: Action<NamedDomainObjectContainer<KotlinSourceSet>>
-) = with(kotlin) {
-    sourceSets(config)
-}
-
 //</editor-fold>------------------------------------------------------------------------------------
 //</editor-fold>------------------------------------------------------------------------------------
 
 
 //<editor-fold desc="configurations">---------------------------------------------------------------
 //<editor-fold desc="configurations">---------------------------------------------------------------
@@ -129,7 +111,6 @@ targets {
             jvmTarget.set(JvmTarget.JVM_17)
             jvmTarget.set(JvmTarget.JVM_17)
         }
         }
     }
     }
-
 }
 }
 
 
 //</editor-fold>------------------------------------------------------------------------------------
 //</editor-fold>------------------------------------------------------------------------------------
@@ -173,6 +154,8 @@ kotlin {
                 implementation(libs.kotlinx.serialization.json)
                 implementation(libs.kotlinx.serialization.json)
                 // desktop file linux
                 // desktop file linux
                 implementation(libs.ini4j)
                 implementation(libs.ini4j)
+                // files
+                implementation(libs.okio)
                 // tts
                 // tts
                 implementation(libs.tts)
                 implementation(libs.tts)
                 implementation(libs.tts.compose)
                 implementation(libs.tts.compose)
@@ -185,35 +168,39 @@ kotlin {
                 // timeline
                 // timeline
                 implementation(libs.jetlime)
                 implementation(libs.jetlime)
                 // html to text
                 // html to text
-                implementation("com.github.BartoszJarocki:android-boilerpipe:-SNAPSHOT")
+                implementation(libs.html2text)
                 // markdown
                 // markdown
-                implementation("io.noties.markwon:core:4.6.2")
-                // open ai
-                implementation (platform("com.aallam.openai:openai-client-bom:3.2.0"))
-                implementation ("com.aallam.openai:openai-client")
+                implementation(libs.markwon)
+                // strings
+                implementation(libs.human.readable)
+                // alerts
+                implementation(libs.alert.kmp)
+                // ai plugins
+                implementation(libs.flock.aigentic.core)
+                implementation(libs.flock.aigentic.openai)
+                implementation(libs.flock.aigentic.gemini)
+                implementation(libs.flock.aigentic.ollama)
+                implementation(libs.flock.aigentic.vertexai)
+                implementation(libs.flock.aigentic.http)
+                implementation(libs.flock.aigentic.openapi)
+//                ksp("community.flock.aigentic:ksp-processor:0.1.0")
                 // ktor
                 // ktor
-                implementation("io.ktor:ktor-client-core:2.3.9")
-                implementation("io.ktor:ktor-client-cio:2.3.9")
-                implementation("io.ktor:ktor-client-content-negotiation:2.3.9")
-                implementation("io.ktor:ktor-client-logging:2.3.9")
-                implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.9")
+                implementation(libs.ktor.client.core)
+                implementation(libs.ktor.client.cio)
+                implementation(libs.ktor.client.content.negotiation)
+                implementation(libs.ktor.client.logging)
+                implementation(libs.ktor.serialization.kotlinx.json)
                 // okhttp
                 // okhttp
-                implementation("com.squareup.okhttp3:okhttp:4.12.0")
-                implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
-                implementation("com.squareup.okhttp3:okhttp-urlconnection:4.12.0")
-                implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:4.12.0")
-                implementation("com.squareup.okhttp3:okhttp-tls:4.12.0")
+                implementation(libs.okhttp3.client)
+                implementation(libs.okhttp3.logging.interceptor)
+                implementation(libs.okhttp3.urlconnection)
+                implementation(libs.okhttp3.dnsoverhttps)
+                implementation(libs.okhttp3.tls)
 //                implementation("com.squareup.okhttp3:okhttp-ws:4.12.0")
 //                implementation("com.squareup.okhttp3:okhttp-ws:4.12.0")
                 // notification
                 // notification
                 // implementation("io.github.shadmanadman:knotif:0.56.0")
                 // implementation("io.github.shadmanadman:knotif:0.56.0")
                 // sensors
                 // sensors
                 //implementation("io.github.shadmanadman:KSensor:0.59.0")
                 //implementation("io.github.shadmanadman:KSensor:0.59.0")
-                // flowmvi
-//                implementation(libs.flowmvi.core)
-//                implementation(libs.flowmvi.compose)
-//                implementation(libs.flowmvi.android)
-//                implementation(libs.flowmvi.savedstate)
-//                implementation(libs.flowmvi.debugger)
                 // locale
                 // locale
 //            implementation(libs.i18n4k)
 //            implementation(libs.i18n4k)
                 // anims kottie
                 // anims kottie
@@ -231,15 +218,8 @@ kotlin {
 //            implementation("com.mohamedrejeb.richeditor:richeditor-compose:1.0.0-rc10")
 //            implementation("com.mohamedrejeb.richeditor:richeditor-compose:1.0.0-rc10")
 //                implementation (libs.popkorn)
 //                implementation (libs.popkorn)
 //                kapt(libs.popkorn.compiler)
 //                kapt(libs.popkorn.compiler)
-//                implementation("io.github.khubaibkhan4:mediaplayer-kmp:2.0.6")
-                // strings
-                implementation(libs.human.readable)
-                // alerts
-                implementation(libs.alert.kmp)
                 // tor
                 // tor
                 // implementation("io.matthewnelson.kmp-tor:runtime:2.1.0")
                 // implementation("io.matthewnelson.kmp-tor:runtime:2.1.0")
-                // files
-                implementation(libs.okio)
             }
             }
         }
         }
 
 
@@ -260,8 +240,6 @@ kotlin {
                 implementation(libs.androidx.core.splashscreen)
                 implementation(libs.androidx.core.splashscreen)
                 // permissions
                 // permissions
                 implementation(libs.accompanist.permissions)
                 implementation(libs.accompanist.permissions)
-                // ai gemini
-                implementation(libs.sh.google.generative.ai)
                 // sensors
                 // sensors
                 //implementation("io.github.shadmanadman:KSensor:0.59.0")
                 //implementation("io.github.shadmanadman:KSensor:0.59.0")
             }
             }
@@ -282,8 +260,6 @@ kotlin {
                 implementation(libs.okhttp3.client)
                 implementation(libs.okhttp3.client)
                 // images okhttp
                 // images okhttp
                 implementation(libs.coil.okhttp)
                 implementation(libs.coil.okhttp)
-                // ai gemini
-                implementation(libs.sh.google.generative.ai)
                 // chatgpt
                 // chatgpt
                 implementation(libs.ychat)
                 implementation(libs.ychat)
                 // desktop files
                 // desktop files
@@ -341,6 +317,7 @@ desktop {
     group = libs.versions.app.pkg.name.get()
     group = libs.versions.app.pkg.name.get()
     version = libs.versions.app.pkg.version.get()
     version = libs.versions.app.pkg.version.get()
     application {
     application {
+        jvmArgs("-Dprism.order=sw")
         mainClass = "org.mjdev.desktop.main.MainKt"
         mainClass = "org.mjdev.desktop.main.MainKt"
         nativeDistributions {
         nativeDistributions {
             packageName = libs.versions.app.name.get()
             packageName = libs.versions.app.name.get()

+ 1 - 1
composeApp/src/androidMain/kotlin/org/mjdev/desktop/context/DesktopContext.kt

@@ -133,7 +133,7 @@ class DesktopContext(
         IAiManager::class -> AiManager(
         IAiManager::class -> AiManager(
             context = this,
             context = this,
             // todo user can configure
             // todo user can configure
-            pluginAI = AiPluginOpenAi(this@DesktopContext),
+            pluginAI = AiPluginGemini(this@DesktopContext),
             pluginTTS = TTSPluginAndroid(this@DesktopContext),
             pluginTTS = TTSPluginAndroid(this@DesktopContext),
             pluginSTT = STTPluginEmpty(this@DesktopContext)
             pluginSTT = STTPluginEmpty(this@DesktopContext)
         )
         )

+ 1 - 1
composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/chart/DonutChart.kt

@@ -61,7 +61,7 @@ fun DonutChart(
     LaunchedEffect(Unit) {
     LaunchedEffect(Unit) {
         while (isActive) {
         while (isActive) {
             delay(refreshTimeout)
             delay(refreshTimeout)
-            needRefresh = currentTimeMillis()
+            needRefresh = currentTimeMillis
         }
         }
     }
     }
 }
 }

+ 1 - 1
composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/desktoppanel/applets/DesktopPanelIcon.kt

@@ -64,7 +64,7 @@ fun DesktopPanelIcon(
     }
     }
     val isStarting by rememberCalculated(app) { app?.isStarting ?: false }
     val isStarting by rememberCalculated(app) { app?.isStarting ?: false }
     val isRunning by rememberCalculated(app) {
     val isRunning by rememberCalculated(app) {
-        app?.isRunning == true || processManager.hasAppProcess(app)
+        app?.isRunning == true // || processManager.hasAppProcess(app) // todo
     }
     }
     Box(
     Box(
         modifier = Modifier
         modifier = Modifier

+ 0 - 28
composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/web/ComposeWebView.kt

@@ -1,28 +0,0 @@
-package org.mjdev.desktop.components.web
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import org.jetbrains.compose.ui.tooling.preview.Preview
-import org.mjdev.desktop.extensions.Compose.preview
-import org.mjdev.desktop.context.DesktopContextScope.Companion.withDesktopContext
-
-@Suppress( "FunctionName", "unused")
-@Composable
-fun ComposeWebView(
-    modifier: Modifier = Modifier,
-    url: String = "https://m.youtube.com/watch?v=BwY6LD7KAQk",
-) = withDesktopContext {
-//    val state = rememberWebViewState(url)
-//    val navigator: WebViewNavigator = rememberWebViewNavigator()
-//    WebView(
-//        modifier = modifier,
-//        state = state,
-//        navigator = navigator
-//    )
-}
-
-@Preview
-@Composable
-fun PreviewComposeWebView() = preview {
-    ComposeWebView()
-}

+ 0 - 23
composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/web/CookieManagerCompat.kt

@@ -1,23 +0,0 @@
-package org.mjdev.desktop.components.web
-
-//import java.net.CookieHandler
-//import java.net.URI
-
-object CookieManagerCompat {
-//    fun setCookie(
-//        url: String,
-//        headers: HashMap<String, String>
-//    ) {
-//        LinkedHashMap<String, List<String>>().apply {
-//            this["Set-Cookie"] = headers.map { "${it.key}=${it.value}" }
-//        }.also { nHeaders ->
-//            CookieHandler.getDefault().put(URI.create(url), nHeaders)
-//        }
-//    }
-//
-//    fun getCookie(uri: URI): MutableMap<String, String>? {
-//        return CookieHandler.getDefault().get(uri, HashMap()).map {
-//            it.key to it.value[0]
-//        }.toMap().toMutableMap()
-//    }
-}

+ 0 - 86
composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/web/WebEngineKt.kt

@@ -1,86 +0,0 @@
-package org.mjdev.desktop.components.web
-
-//import javafx.scene.web.WebEngine
-//import javafx.scene.web.WebView
-//import java.net.CookieHandler
-//import java.net.URI
-//
-//fun WebView.load(url: String) {
-//    engine.load(url)
-//}
-//
-//fun WebView.loadContent(content: String) {
-//    engine.loadContent(content)
-//}
-//
-//fun WebView.stopLoading() {
-//    engine.stopLoading()
-//}
-//
-//fun WebView.goForward() {
-//    engine.goForward()
-//}
-//
-//fun WebView.goBack() {
-//    engine.goBack()
-//}
-//
-//fun WebView.canGoBack(): Boolean {
-//    return engine.canGoBack()
-//}
-//
-//fun WebView.canGoForward(): Boolean {
-//    return engine.canGoForward()
-//}
-//
-//fun WebView.getCurrentUrl(): String? {
-//    return engine.getCurrentUrl()
-//}
-//
-//fun WebView.goRoot() {
-//    engine.history.go(-engine.history.currentIndex)
-//}
-//
-//fun WebView.executeScript(script: String) {
-//    engine.executeScript(script)
-//}
-//
-//fun WebView.setCookie(url: String, headers: HashMap<String, List<String>>) {
-//    val uri: URI = URI.create(url)
-//    CookieHandler.getDefault().put(uri, headers)
-//}
-//
-//fun WebView.getCookies(): MutableMap<String, MutableList<String>>? {
-//    val cookieHandler = CookieHandler.getDefault()
-//    val uri = URI.create(engine.location)
-//    return cookieHandler.get(uri, HashMap())
-//}
-//
-//fun WebEngine.getCurrentUrl(): String? {
-//    if (history.entries.size <= 0) return null
-//    return history.entries[history.currentIndex].url
-//}
-//
-//fun WebEngine.stopLoading() {
-//    loadWorker.cancel()
-//}
-//
-//fun WebEngine.goForward() {
-//    if (canGoForward()) {
-//        history.go(1)
-//    }
-//}
-//
-//fun WebEngine.goBack() {
-//    if (canGoBack()) {
-//        history.go(-1)
-//    }
-//}
-//
-//fun WebEngine.canGoBack(): Boolean {
-//    return history.maxSize > 0 && history.currentIndex != 0
-//}
-//
-//fun WebEngine.canGoForward(): Boolean {
-//    return history.maxSize > 0 && history.currentIndex != history.maxSize - 1
-//}

+ 26 - 236
composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/web/WebView.kt

@@ -7,239 +7,29 @@
  */
  */
 
 
 package org.mjdev.desktop.components.web
 package org.mjdev.desktop.components.web
-//
-//import androidx.compose.runtime.*
-//import androidx.compose.runtime.snapshots.SnapshotStateList
-//import androidx.compose.ui.Modifier
-//import androidx.compose.ui.awt.SwingPanel
-//import javafx.application.Platform
-//import javafx.concurrent.Worker.State.*
-//import javafx.embed.swing.JFXPanel
-//import javafx.scene.Scene
-//import javafx.scene.layout.StackPane
-//import javafx.scene.web.WebView
-//import kotlinx.coroutines.CoroutineScope
-//import kotlinx.coroutines.flow.MutableSharedFlow
-//import kotlinx.coroutines.launch
-//
-//// todo key handler
-//@Composable
-//internal fun WebView(
-//    state: WebViewState,
-//    modifier: Modifier = Modifier,
-//    navigator: WebViewNavigator = rememberWebViewNavigator(),
-//    onCreated: (WebView) -> Unit = {},
-//    onDispose: (WebView) -> Unit = {},
-//) {
-//    var webView by remember { mutableStateOf<WebView?>(null) }
-//    LaunchedEffect(webView, navigator) {
-//        with(navigator) {
-//            webView?.handleNavigationEvents()
-//        }
-//    }
-//    val currentOnDispose by rememberUpdatedState(onDispose)
-//    webView?.let { wv ->
-//        DisposableEffect(wv) {
-//            onDispose { currentOnDispose(wv) }
-//        }
-//    }
-//    SwingPanel(factory = {
-//        JFXPanel().also { jfxP ->
-//            Platform.runLater {
-//                val rootVewView = WebView()
-//                webView = rootVewView
-//                rootVewView.isVisible = true
-//                val root = StackPane()
-//                root.children.add(webView)
-//                val scene = Scene(root)
-//                onCreated.invoke(rootVewView)
-//                addEngineListener(rootVewView, state, navigator)
-//                when (val content = state.content) {
-//                    is WebContent.Url -> {
-//                        val url = content.url
-//                        if (url.isNotEmpty() && url != rootVewView.getCurrentUrl()) {
-//                            rootVewView.load(url)
-//                        }
-//                    }
-//
-//                    is WebContent.Data -> {
-//                        rootVewView.loadContent(content.data)
-//                    }
-//                }
-//                jfxP.scene = scene
-//            }
-//        }
-//    }, modifier = modifier) { _ ->
-//    }
-//}
-//
-//fun addEngineListener(
-//    webView: WebView,
-//    state: WebViewState,
-//    navigator: WebViewNavigator
-//) {
-//    val engine = webView.engine
-//    engine.loadWorker.exceptionProperty().addListener { _, _, newError ->
-//        println("page load error : $newError")
-//        state.errorsForCurrentRequest.add(
-//            WebViewError(
-//                engine.getCurrentUrl(),
-//                newError.message.toString()
-//            )
-//        )
-//    }
-//    engine.setOnError { error -> println("onError : $error") }
-//    engine.titleProperty().addListener { observable, oldValue, newValue ->
-//        println("page load titleProperty : $newValue")
-//        state.pageTitle = newValue
-//    }
-//    engine.loadWorker.progressProperty().addListener { observable, oldValue, newValue ->
-//        println("page load progressProperty : $newValue")
-//        if (newValue.toFloat() >= 0f) {
-//            state.loadingState = LoadingState.Loading(newValue.toFloat())
-//        }
-//    }
-//    engine.history.currentIndexProperty().addListener { observable, oldValue, newValue ->
-//        val url = engine.getCurrentUrl()
-//        if (url != null &&
-//            !url.startsWith("data:text/html") &&
-//            state.content.getCurrentUrl() != url
-//        ) {
-//            state.content = state.content.withUrl(url)
-//        }
-//    }
-//    engine.loadWorker.stateProperty().addListener { _, _, newState ->
-//        when (newState) {
-//            SUCCEEDED -> {
-//                state.loadingState = LoadingState.Finished
-//                navigator.canGoBack = engine.canGoBack()
-//                navigator.canGoForward = engine.canGoForward()
-//            }
-//
-//            FAILED -> {}
-//            RUNNING -> {
-//                state.loadingState = LoadingState.Loading(0f)
-//            }
-//
-//            CANCELLED -> {}
-//            READY, SCHEDULED -> {
-//                state.loadingState = LoadingState.Initializing
-//                state.errorsForCurrentRequest.clear()
-//            }
-//        }
-//    }
-//}
-//
-//@Composable
-//fun rememberWebViewNavigator(
-//    coroutineScope: CoroutineScope = rememberCoroutineScope()
-//): WebViewNavigator = remember(coroutineScope) { WebViewNavigator(coroutineScope) }
-//
-//sealed class WebContent {
-//    data class Url(
-//        val url: String,
-//        val additionalHttpHeaders: Map<String, String> = emptyMap(),
-//    ) : WebContent()
-//
-//    data class Data(val data: String) : WebContent()
-//
-//    fun getCurrentUrl(): String? {
-//        return when (this) {
-//            is Url -> url
-//            is Data -> null
-//        }
-//    }
-//}
-//
-//fun WebContent.withUrl(url: String) = when (this) {
-//    is WebContent.Url -> copy(url = url)
-//    else -> WebContent.Url(url)
-//}
-//
-//@Stable
-//class WebViewState(webContent: WebContent) {
-//    var content: WebContent by mutableStateOf(webContent)
-//    var loadingState: LoadingState by mutableStateOf(LoadingState.Finished)
-//        internal set
-//    val isLoading: Boolean
-//        get() = loadingState !is LoadingState.Finished
-//    var pageTitle: String? by mutableStateOf(null)
-//        internal set
-//    val errorsForCurrentRequest: SnapshotStateList<WebViewError> = mutableStateListOf()
-//}
-//
-//@Stable
-//class WebViewNavigator(private val coroutineScope: CoroutineScope) {
-//    private enum class NavigationEvent { BACK, FORWARD, RELOAD, STOP_LOADING }
-//
-//    private val navigationEvents: MutableSharedFlow<NavigationEvent> = MutableSharedFlow()
-//    suspend fun WebView.handleNavigationEvents() {
-//        navigationEvents.collect { event ->
-//            when (event) {
-//                NavigationEvent.BACK -> {
-//                    if (canGoBack) {
-//                        engine.goBack()
-//                    }
-//                }
-//
-//                NavigationEvent.FORWARD -> {
-//                    if (canGoForward) {
-//                        engine.goForward()
-//                    }
-//                }
-//
-//                NavigationEvent.RELOAD -> engine.reload()
-//                NavigationEvent.STOP_LOADING -> engine.stopLoading()
-//            }
-//        }
-//    }
-//
-//    var canGoBack: Boolean by mutableStateOf(false)
-//        internal set
-//
-//    var canGoForward: Boolean by mutableStateOf(false)
-//        internal set
-//
-//    fun navigateBack() {
-//        coroutineScope.launch { navigationEvents.emit(NavigationEvent.BACK) }
-//    }
-//
-//    fun navigateForward() {
-//        coroutineScope.launch { navigationEvents.emit(NavigationEvent.FORWARD) }
-//    }
-//
-//    fun reload() {
-//        coroutineScope.launch { navigationEvents.emit(NavigationEvent.RELOAD) }
-//    }
-//
-//    fun stopLoading() {
-//        coroutineScope.launch { navigationEvents.emit(NavigationEvent.STOP_LOADING) }
-//    }
-//}
-//
-//@Immutable
-//data class WebViewError(
-//    val request: String?,
-//    val error: String
-//)
-//
-//@Composable
-//fun rememberWebViewState(
-//    url: String,
-//    additionalHttpHeaders: Map<String, String> = mapOf()
-//): WebViewState = remember(url, additionalHttpHeaders) {
-//    WebViewState(
-//        WebContent.Url(
-//            url = url,
-//            additionalHttpHeaders = additionalHttpHeaders
-//        )
-//    )
-//}
-//
-//@Composable
-//fun rememberWebViewStateWithHTMLData(
-//    data: String,
-//    baseUrl: String?
-//): WebViewState = remember(data) {
-//    WebViewState(WebContent.Data(data))
-//}
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.ui.Modifier
+import org.mjdev.desktop.context.DesktopContextScope.Companion.withDesktopContext
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.text.style.TextAlign
+import org.mjdev.desktop.components.text.TextAny
+
+@Composable
+fun WebView(
+    url: String = "https://google.com",
+    modifier: Modifier = Modifier,
+) = withDesktopContext {
+    Box(
+        modifier = modifier.background(backgroundColor)
+    ) {
+        TextAny(
+            text = "WebView is not supported on this platform.\n$url",
+            modifier = Modifier.align(Alignment.Center),
+            textAlign = TextAlign.Left,
+            color = textColor,
+        )
+    }
+}

+ 0 - 23
composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/web/WebViewImpl.kt

@@ -1,23 +0,0 @@
-/*
- * Copyright (c) Milan Jurkulák 2024.
- *  Contact:
- *  e: mimoccc@gmail.com
- *  e: mj@mjdev.org
- *  w: https://mjdev.org
- */
-
-package org.mjdev.desktop.components.web
-//
-//import androidx.compose.runtime.Composable
-//import androidx.compose.ui.Modifier
-//
-//@Composable
-//internal fun WebViewImpl(
-//    state: WebViewState,
-//    modifier: Modifier,
-//    navigator: WebViewNavigator
-//) {
-//    WebView(state, modifier, navigator, onCreated = {
-//    }, onDispose = {
-//    })
-//}

+ 17 - 5
composeApp/src/commonMain/kotlin/org/mjdev/desktop/extensions/CustomExt.kt

@@ -5,21 +5,33 @@ import androidx.compose.runtime.collectAsState
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.channelFlow
 import kotlinx.coroutines.flow.channelFlow
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.launch
-import kotlinx.datetime.Clock
 import kotlinx.datetime.Instant
 import kotlinx.datetime.Instant
 import kotlinx.datetime.toLocalDateTime
 import kotlinx.datetime.toLocalDateTime
 import kotlinx.datetime.TimeZone.Companion.currentSystemDefault
 import kotlinx.datetime.TimeZone.Companion.currentSystemDefault
 import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.json.Json
 import kotlinx.serialization.json.Json
+import org.mjdev.desktop.extensions.System.currentTime
 import org.mjdev.desktop.log.Log
 import org.mjdev.desktop.log.Log
 import kotlin.coroutines.suspendCoroutine
 import kotlin.coroutines.suspendCoroutine
+import kotlin.time.ExperimentalTime
 
 
+@OptIn(ExperimentalTime::class)
 @Suppress("unused")
 @Suppress("unused")
 object CustomExt {
 object CustomExt {
 
 
+//    fun runSafe(
+//        shouldLog: Boolean = true,
+//        block: () -> Unit
+//    ) = runCatching {
+//        block()
+//    }.onFailure { err ->
+//        if (shouldLog) Log.e(err)
+//    }
+
     // todo
     // todo
+
     private fun Instant.formatDate(): String {
     private fun Instant.formatDate(): String {
-        val localDateTime = this.toLocalDateTime(currentSystemDefault())
+        val localDateTime = toLocalDateTime(currentSystemDefault())
         val day = localDateTime.date.dayOfMonth.toString().padStart(2, '0')
         val day = localDateTime.date.dayOfMonth.toString().padStart(2, '0')
         val month = localDateTime.date.monthNumber.toString().padStart(2, '0')
         val month = localDateTime.date.monthNumber.toString().padStart(2, '0')
         val year = localDateTime.date.year.toString()
         val year = localDateTime.date.year.toString()
@@ -28,7 +40,7 @@ object CustomExt {
 
 
     // todo
     // todo
     private fun Instant.formatTime(): String {
     private fun Instant.formatTime(): String {
-        val localDateTime = this.toLocalDateTime(currentSystemDefault())
+        val localDateTime = toLocalDateTime(currentSystemDefault())
         val hours = localDateTime.hour.toString().padStart(2, '0')
         val hours = localDateTime.hour.toString().padStart(2, '0')
         val minutes = localDateTime.minute.toString().padStart(2, '0')
         val minutes = localDateTime.minute.toString().padStart(2, '0')
         val seconds = localDateTime.second.toString().padStart(2, '0')
         val seconds = localDateTime.second.toString().padStart(2, '0')
@@ -42,7 +54,7 @@ object CustomExt {
                 var date = "1.1.1970"
                 var date = "1.1.1970"
                 do {
                 do {
                     // todo
                     // todo
-                    Clock.System.now().formatDate().also { t ->
+                    currentTime.formatDate().also { t ->
                         if (date != t) {
                         if (date != t) {
                             date = t
                             date = t
                             send(date)
                             send(date)
@@ -59,7 +71,7 @@ object CustomExt {
             launch {
             launch {
                 var time = "00:00:00"
                 var time = "00:00:00"
                 do {
                 do {
-                    Clock.System.now().formatTime().also { t ->
+                    currentTime.formatTime().also { t ->
                         if (time != t) {
                         if (time != t) {
                             time = t
                             time = t
                             send(time)
                             send(time)

+ 1 - 0
composeApp/src/commonMain/kotlin/org/mjdev/desktop/extensions/FocusState.kt

@@ -87,6 +87,7 @@ object FocusState {
         }
         }
     )
     )
 
 
+    @Suppress("SuspiciousModifierThen")
     @Composable
     @Composable
     fun Modifier.requestFocusOnTouch(
     fun Modifier.requestFocusOnTouch(
         focusRequester: FocusRequester,
         focusRequester: FocusRequester,

+ 2 - 1
composeApp/src/commonMain/kotlin/org/mjdev/desktop/extensions/LaunchedEffect.kt

@@ -16,6 +16,7 @@ import kotlinx.coroutines.flow.flow
 import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.launch
 import org.mjdev.desktop.extensions.MutableStateExt.rememberState
 import org.mjdev.desktop.extensions.MutableStateExt.rememberState
+import org.mjdev.desktop.extensions.System.currentTimeMillis
 import kotlin.coroutines.CoroutineContext
 import kotlin.coroutines.CoroutineContext
 
 
 @Suppress("ComposableNaming")
 @Suppress("ComposableNaming")
@@ -59,7 +60,7 @@ object LaunchedEffect {
             }
             }
             if (delay > 0L) {
             if (delay > 0L) {
                 delay(delay)
                 delay(delay)
-                state = System.currentTimeMillis()
+                state = currentTimeMillis
             }
             }
         }
         }
         return result
         return result

+ 11 - 2
composeApp/src/commonMain/kotlin/org/mjdev/desktop/extensions/System.kt

@@ -1,7 +1,16 @@
 package org.mjdev.desktop.extensions
 package org.mjdev.desktop.extensions
 
 
-import kotlinx.datetime.Clock
+import kotlin.time.Clock
+import kotlin.time.ExperimentalTime
+import kotlinx.datetime.Instant
 
 
+@OptIn(ExperimentalTime::class)
 object System {
 object System {
-    fun currentTimeMillis() = Clock.System.now().toEpochMilliseconds()
+
+    val currentTimeMillis
+        get() = Clock.System.now().toEpochMilliseconds()
+
+    val currentTime
+        get() = Instant.fromEpochMilliseconds(currentTimeMillis)
+
 }
 }

+ 1 - 1
composeApp/src/commonMain/kotlin/org/mjdev/desktop/log/Log.kt

@@ -13,7 +13,7 @@ import org.mjdev.desktop.extensions.System.currentTimeMillis
 
 
 // todo colors
 // todo colors
 object Log {
 object Log {
-    private val creationDate = currentTimeMillis().toString()
+    private val creationDate = currentTimeMillis.toString()
     private val logFile = "/var/tmp/mjdev-desktop/log/$creationDate.log".toPath()
     private val logFile = "/var/tmp/mjdev-desktop/log/$creationDate.log".toPath()
 //    private val logWriter = PrintWriter(logFile.apply {
 //    private val logWriter = PrintWriter(logFile.apply {
 //        runCatching {
 //        runCatching {

+ 0 - 2
composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/AiManager.kt

@@ -15,12 +15,10 @@ import org.mjdev.desktop.managers.ai.tts.base.TTSPlugin
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.launch
 import org.mjdev.desktop.context.IDesktopContext
 import org.mjdev.desktop.context.IDesktopContext
-import org.mjdev.desktop.managers.ai.plugins.AiPluginGemini
 import org.mjdev.desktop.managers.ai.actions.ActionCalculator
 import org.mjdev.desktop.managers.ai.actions.ActionCalculator
 import org.mjdev.desktop.managers.ai.actions.base.ActionsProvider
 import org.mjdev.desktop.managers.ai.actions.base.ActionsProvider
 import org.mjdev.desktop.managers.ai.actions.ActionCurrentTime
 import org.mjdev.desktop.managers.ai.actions.ActionCurrentTime
 import org.mjdev.desktop.managers.ai.actions.base.ActionException.ActionNone
 import org.mjdev.desktop.managers.ai.actions.base.ActionException.ActionNone
-import org.mjdev.desktop.managers.ai.plugins.AiPluginOpenAi
 import org.mjdev.desktop.managers.ai.plugins.base.AIPlugin
 import org.mjdev.desktop.managers.ai.plugins.base.AIPlugin
 import org.mjdev.desktop.managers.ai.tts.TTSPluginEmpty
 import org.mjdev.desktop.managers.ai.tts.TTSPluginEmpty
 
 

+ 4 - 2
composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/actions/ActionCurrentTime.kt

@@ -2,15 +2,17 @@ package org.mjdev.desktop.managers.ai.actions
 
 
 import kotlinx.datetime.TimeZone
 import kotlinx.datetime.TimeZone
 import kotlinx.datetime.toLocalDateTime
 import kotlinx.datetime.toLocalDateTime
+import org.mjdev.desktop.extensions.System.currentTime
 import org.mjdev.desktop.managers.ai.actions.base.ActionsProvider
 import org.mjdev.desktop.managers.ai.actions.base.ActionsProvider
+import kotlin.time.ExperimentalTime
 
 
+@OptIn(ExperimentalTime::class)
 val ActionsProvider.ActionCurrentTime
 val ActionsProvider.ActionCurrentTime
     get() = action(
     get() = action(
         "current time"
         "current time"
     ) {
     ) {
         val timeZone = TimeZone.currentSystemDefault()
         val timeZone = TimeZone.currentSystemDefault()
-        val localDateTime = kotlinx.datetime.Clock.System.now()
-            .toLocalDateTime(timeZone)
+        val localDateTime = currentTime.toLocalDateTime(timeZone)
         val hours = localDateTime.hour.toString().padStart(2, '0')
         val hours = localDateTime.hour.toString().padStart(2, '0')
         val minutes = localDateTime.minute.toString().padStart(2, '0')
         val minutes = localDateTime.minute.toString().padStart(2, '0')
         val seconds = localDateTime.second.toString().padStart(2, '0')
         val seconds = localDateTime.second.toString().padStart(2, '0')

+ 1 - 1
composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/actions/base/ActionsProvider.kt

@@ -69,7 +69,7 @@ class ActionsProvider(
                 }
                 }
             }
             }
             if (action != null) {
             if (action != null) {
-                action.lastSeen = currentTimeMillis()
+                action.lastSeen = currentTimeMillis
                 action.history.addIfNotExists(t) { t1, t2 -> t1.contentEquals(t2, true) }
                 action.history.addIfNotExists(t) { t1, t2 -> t1.contentEquals(t2, true) }
                 action.action.invoke(ActionProviderScope(context)).let { r ->
                 action.action.invoke(ActionProviderScope(context)).let { r ->
                     when (r) {
                     when (r) {

+ 6 - 3
composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/plugins/AiPluginEmpty.kt

@@ -15,6 +15,9 @@ import org.mjdev.desktop.managers.ai.plugins.base.AIPlugin
 class AiPluginEmpty(
 class AiPluginEmpty(
     context: IDesktopContext
     context: IDesktopContext
 ) : AIPlugin {
 ) : AIPlugin {
-    override suspend fun ask(question: String): String =
-        "No a.i. provider selected please read manual."
-}
+
+    override suspend fun ask(
+        question: String
+    ): String = "No a.i. provider selected please read manual."
+
+}

+ 35 - 38
composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/plugins/AiPluginGemini.kt

@@ -8,50 +8,47 @@
 
 
 package org.mjdev.desktop.managers.ai.plugins
 package org.mjdev.desktop.managers.ai.plugins
 
 
-import dev.shreyaspatil.ai.client.generativeai.GenerativeModel
-import dev.shreyaspatil.ai.client.generativeai.type.content
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.async
+import community.flock.aigentic.core.agent.start
+import community.flock.aigentic.core.agent.tool.Result.Fatal
+import community.flock.aigentic.core.agent.tool.Result.Finished
+import community.flock.aigentic.core.agent.tool.Result.Stuck
+import community.flock.aigentic.core.dsl.agent
+import community.flock.aigentic.gemini.dsl.geminiModel
+import community.flock.aigentic.gemini.model.GeminiModelIdentifier
+import community.flock.aigentic.gemini.model.GeminiModelIdentifier.Gemini1_5Pro
 import org.mjdev.desktop.context.IDesktopContext
 import org.mjdev.desktop.context.IDesktopContext
+import org.mjdev.desktop.log.Log
 import org.mjdev.desktop.managers.ai.plugins.base.AIPlugin
 import org.mjdev.desktop.managers.ai.plugins.base.AIPlugin
 
 
-/*
-* Gemini key : https://makersuite.google.com/app/apikey
-* */
+// todo tools = actions
+// Gemini key : https://makersuite.google.com/app/apikey
 class AiPluginGemini(
 class AiPluginGemini(
     private val context: IDesktopContext,
     private val context: IDesktopContext,
-    private val aiModel: GeminiModel = GeminiModel.Gemini1_5Pro,
-    private val scope: CoroutineScope = context.scope
+    private val apiKey: String = context.keysManager.loadKey("gemini"),
+    private val model: GeminiModelIdentifier = Gemini1_5Pro,
 ) : AIPlugin {
 ) : AIPlugin {
-    private val apiKey = context.keysManager.loadKey("gemini")
-    private val generativeModel: GenerativeModel? by lazy {
-        if (apiKey.isNotEmpty()) {
-            GenerativeModel(
-                modelName = aiModel.model,
-                apiKey = apiKey
-            )
-        } else null
-    }
 
 
-    override suspend fun ask(question: String): String = scope.async {
-        var error: Throwable? = null
-        runCatching {
-            if (apiKey.isEmpty()) {
-                throw (Exception("Error: No gemini api key provided, pleas read manual and provide Your api key."))
-            } else {
-                generativeModel?.generateContent(
-                    content {
-                        text(question)
-                    }
-                )?.text
-            }
-        }.onFailure { e ->
-            error = e
-        }.getOrNull() ?: error?.message ?: ""
-    }.await()
-
-    @Suppress("EnumEntryName")
-    enum class GeminiModel(val model: String) {
-        Gemini1_5Pro("gemini-1.5-pro-latest")
+    override suspend fun ask(
+        question: String
+    ): String = agent {
+//        Log.d("Using api key : $apiKey")
+        geminiModel {
+            apiKey(apiKey)
+            modelIdentifier(model)
+        }
+        task("Provide information") {
+            addInstruction("Respond to user queries with relevant information.")
+        }
+        context {
+            addText(question)
+        }
+        finishResponse()
+    }.start().result.let { result ->
+        when (result) {
+            is Finished<*> -> result.response.toString()
+            is Stuck -> result.reason
+            is Fatal -> result.message
+        }
     }
     }
+
 }
 }

+ 30 - 8
composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/plugins/AiPluginOllama.kt

@@ -1,18 +1,40 @@
 package org.mjdev.desktop.managers.ai.plugins
 package org.mjdev.desktop.managers.ai.plugins
 
 
-import kotlinx.coroutines.CoroutineScope
+import community.flock.aigentic.core.agent.start
+import community.flock.aigentic.core.agent.tool.Result.Fatal
+import community.flock.aigentic.core.agent.tool.Result.Finished
+import community.flock.aigentic.core.agent.tool.Result.Stuck
+import community.flock.aigentic.core.dsl.agent
+import community.flock.aigentic.ollama.dsl.ollamaModel
 import org.mjdev.desktop.context.IDesktopContext
 import org.mjdev.desktop.context.IDesktopContext
 import org.mjdev.desktop.managers.ai.plugins.base.AIPlugin
 import org.mjdev.desktop.managers.ai.plugins.base.AIPlugin
 
 
-// todo
+// todo tools = actions
+// todo test with ollama model
 class AiPluginOllama(
 class AiPluginOllama(
     private val context: IDesktopContext,
     private val context: IDesktopContext,
-    private val scope: CoroutineScope = context.scope
+    private val apiKey: String = context.keysManager.loadKey("ollama"),
 ) : AIPlugin {
 ) : AIPlugin {
-//    private val ollama by lazy { null }
 
 
-    override suspend fun ask(question: String): String {
-//        ollama.setModel("")
-        return "" // todo
+    override suspend fun ask(
+        question: String
+    ): String = agent {
+        ollamaModel {
+            apiUrl(apiKey)
+        }
+        task("Provide information") {
+            addInstruction("Respond to user queries with relevant information.")
+        }
+        context {
+            addText(question)
+        }
+        finishResponse()
+    }.start().result.let { result ->
+        when (result) {
+            is Finished<*> -> result.response.toString()
+            is Stuck -> result.reason
+            is Fatal -> result.message
+        }
     }
     }
-}
+
+}

+ 35 - 60
composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/plugins/AiPluginOpenAi.kt

@@ -1,71 +1,46 @@
 package org.mjdev.desktop.managers.ai.plugins
 package org.mjdev.desktop.managers.ai.plugins
 
 
-import kotlinx.coroutines.CoroutineScope
 import org.mjdev.desktop.context.IDesktopContext
 import org.mjdev.desktop.context.IDesktopContext
 import org.mjdev.desktop.managers.ai.plugins.base.AIPlugin
 import org.mjdev.desktop.managers.ai.plugins.base.AIPlugin
-import kotlin.time.Duration.Companion.seconds
-import com.aallam.openai.api.BetaOpenAI
-import com.aallam.openai.api.chat.ChatCompletionChunk
-import com.aallam.openai.api.chat.ChatCompletionRequest
-import com.aallam.openai.api.chat.ChatMessage
-import com.aallam.openai.api.chat.ChatRole
-import com.aallam.openai.api.http.Timeout
-import com.aallam.openai.api.logging.LogLevel
-import com.aallam.openai.api.logging.Logger
-import com.aallam.openai.api.model.ModelId
-import com.aallam.openai.client.OpenAI
-import com.aallam.openai.client.OpenAIConfig
-import kotlinx.coroutines.async
-import kotlinx.coroutines.flow.first
+import community.flock.aigentic.core.agent.tool.Result.Stuck
+import community.flock.aigentic.core.agent.tool.Result.Fatal
+import community.flock.aigentic.core.agent.tool.Result.Finished
+import community.flock.aigentic.core.agent.start
+import community.flock.aigentic.core.dsl.agent
+import community.flock.aigentic.openai.dsl.openAIModel
+import community.flock.aigentic.openai.model.OpenAIModelIdentifier
+import community.flock.aigentic.openai.model.OpenAIModelIdentifier.GPT4OMini
 import org.mjdev.desktop.log.Log
 import org.mjdev.desktop.log.Log
 
 
-// todo test
+// todo tools = actions
+// Open AI keys: https://platform.openai.com/api-keys
 class AiPluginOpenAi(
 class AiPluginOpenAi(
     private val context: IDesktopContext,
     private val context: IDesktopContext,
-    private val scope: CoroutineScope = context.scope
+    private val apiKey: String = context.keysManager.loadKey("open-ai"),
+    private val model: OpenAIModelIdentifier = GPT4OMini,
 ) : AIPlugin {
 ) : AIPlugin {
-    private val apiKey = context.keysManager.loadKey("open-ai")
-    private val modelId = ModelId("gpt-3.5-turbo")
-    private val openAI: OpenAI? = runCatching {
-        if (apiKey.isNotEmpty()) OpenAI(
-            OpenAIConfig(
-                token = apiKey,
-                logLevel = LogLevel.All,
-                logger = Logger.Simple,
-                timeout = Timeout(socket = 60.seconds),
-            )
-        ) else {
-            Log.w("OpenAI API key is not set, using empty OpenAI client.")
-            null
+
+    override suspend fun ask(
+        question: String
+    ): String = agent {
+//        Log.d("Using api key : $apiKey")
+        openAIModel {
+            apiKey(apiKey)
+            modelIdentifier(model)
+        }
+        task("Provide information") {
+            addInstruction("Respond to user queries with relevant information.")
+        }
+        context {
+            addText(question)
+        }
+        finishResponse()
+    }.start().result.let { result ->
+        when (result) {
+            is Finished<*> -> result.response.toString()
+            is Stuck -> result.reason
+            is Fatal -> result.message
         }
         }
-    }.onFailure { e ->
-        Log.e(e)
-    }.getOrNull()
+    }
 
 
-    @OptIn(BetaOpenAI::class)
-    override suspend fun ask(question: String): String = scope.async {
-        runCatching {
-            openAI?.chatCompletions(
-                ChatCompletionRequest(
-                    model = modelId,
-                    messages = listOf(
-                        ChatMessage(
-                            role = ChatRole.User,
-                            content = question
-                        )
-                    ),
-                    maxTokens = 1000,
-                    temperature = 0.0
-                )
-            )?.first().let { chunk ->
-                if (chunk is ChatCompletionChunk) {
-                    chunk.choices.firstOrNull()?.delta?.content ?: ""
-                } else {
-                    ""
-                }
-            }
-        }.onFailure { e ->
-            Log.e(e)
-        }.getOrDefault("")
-    }.await()
-}
+}

+ 0 - 10
composeApp/src/commonMain/kotlin/org/mjdev/desktop/managers/ai/plugins/AiPluginPerplexity.kt

@@ -1,10 +0,0 @@
-package org.mjdev.desktop.managers.ai.plugins
-
-import org.mjdev.desktop.managers.ai.plugins.base.AIPlugin
-
-// todo
-class AiPluginPerplexity : AIPlugin  {
-    override suspend fun ask(question: String): String {
-        TODO("Not yet implemented")
-    }
-}

+ 6 - 0
composeApp/src/desktopMain/kotlin/org/mjdev/desktop/components/main/MainWindow.kt

@@ -79,6 +79,12 @@ fun MainWindow() = withDesktopContext {
                     modifier = Modifier.size(350.dp, 300.dp)
                     modifier = Modifier.size(350.dp, 300.dp)
                         .align(Alignment.BottomEnd)
                         .align(Alignment.BottomEnd)
                 )
                 )
+//                WebView(
+//                    modifier = Modifier
+//                        .size(800.dp, 600.dp)
+//                        .align(Alignment.Center),
+//                    url = "https://www.google.com"
+//                )
             },
             },
             onLeftMouseClick = {
             onLeftMouseClick = {
                 runAsync {
                 runAsync {

+ 1 - 3
composeApp/src/desktopMain/kotlin/org/mjdev/desktop/context/DeskptopContext.kt

@@ -19,7 +19,6 @@ import org.mjdev.desktop.data.User
 import org.mjdev.desktop.extensions.Compose.isDesign
 import org.mjdev.desktop.extensions.Compose.isDesign
 import org.mjdev.desktop.helpers.application.ApplicationScope
 import org.mjdev.desktop.helpers.application.ApplicationScope
 import org.mjdev.desktop.helpers.image.ImageLoader.asyncImageLoader
 import org.mjdev.desktop.helpers.image.ImageLoader.asyncImageLoader
-import org.mjdev.desktop.helpers.persistence.StorageProvider
 import org.mjdev.desktop.managers.palette.Palette
 import org.mjdev.desktop.managers.palette.Palette
 import org.mjdev.desktop.helpers.system.shell.Shell
 import org.mjdev.desktop.helpers.system.shell.Shell
 import org.mjdev.desktop.interfaces.IApp
 import org.mjdev.desktop.interfaces.IApp
@@ -32,7 +31,6 @@ import org.mjdev.desktop.log.Log
 import org.mjdev.desktop.managers.ai.AiManager
 import org.mjdev.desktop.managers.ai.AiManager
 import org.mjdev.desktop.managers.ai.IAiManager
 import org.mjdev.desktop.managers.ai.IAiManager
 import org.mjdev.desktop.managers.ai.plugins.AiPluginGemini
 import org.mjdev.desktop.managers.ai.plugins.AiPluginGemini
-import org.mjdev.desktop.managers.ai.plugins.AiPluginOpenAi
 import org.mjdev.desktop.managers.ai.stt.STTPluginEmpty
 import org.mjdev.desktop.managers.ai.stt.STTPluginEmpty
 import org.mjdev.desktop.managers.ai.tts.TTSPluginSwift
 import org.mjdev.desktop.managers.ai.tts.TTSPluginSwift
 import org.mjdev.desktop.managers.apps.IAppsManager
 import org.mjdev.desktop.managers.apps.IAppsManager
@@ -248,7 +246,7 @@ class DesktopContext(
         IAiManager::class -> AiManager(
         IAiManager::class -> AiManager(
             context = this,
             context = this,
             // todo user can configure
             // todo user can configure
-            pluginAI = AiPluginOpenAi(this@DesktopContext),
+            pluginAI = AiPluginGemini(this@DesktopContext),
             pluginTTS = TTSPluginSwift(this@DesktopContext),
             pluginTTS = TTSPluginSwift(this@DesktopContext),
             pluginSTT = STTPluginEmpty(this@DesktopContext)
             pluginSTT = STTPluginEmpty(this@DesktopContext)
         )
         )

+ 4 - 5
composeApp/src/desktopMain/kotlin/org/mjdev/desktop/main/Main.kt

@@ -1,6 +1,5 @@
 package org.mjdev.desktop.main
 package org.mjdev.desktop.main
 
 
-import Notify
 import org.mjdev.desktop.components.main.MainWindow
 import org.mjdev.desktop.components.main.MainWindow
 import org.mjdev.desktop.helpers.application.application
 import org.mjdev.desktop.helpers.application.application
 
 
@@ -11,8 +10,8 @@ fun main(
     exitProcessOnExit = true
     exitProcessOnExit = true
 ) {
 ) {
     MainWindow()
     MainWindow()
-    Notify(
-        message= "Hello World!",
-        duration=NotificationDuration.LONG
-    )
+//    Notify(
+//        message = "Hello World!",
+//        duration = NotificationDuration.LONG
+//    )
 }
 }

+ 6 - 2
composeApp/src/desktopMain/kotlin/org/mjdev/desktop/managers/apps/AppsManager.kt

@@ -165,8 +165,12 @@ class AppsManager(
         }.toList()
         }.toList()
 
 
     override val favoriteApps: List<App>
     override val favoriteApps: List<App>
-        get() = Shell.executeAndRead("gsettings", "get", "org.gnome.shell", "favorite-apps")
-            .replace("'", "\"") // todo ?
+        get() = Shell.executeAndRead(
+            "gsettings",
+            "get",
+            "org.gnome.shell",
+            "favorite-apps"
+        ).replace("'", "\"") // todo ?
             .jsonToList<String>()
             .jsonToList<String>()
             .flatMap { deskFileName ->
             .flatMap { deskFileName ->
                 findDesktopFileByName(deskFileName).map { deskFile ->
                 findDesktopFileByName(deskFileName).map { deskFile ->

+ 6 - 5
composeApp/src/desktopMain/kotlin/org/mjdev/desktop/managers/theme/linux/ThemeManagerLinux.kt

@@ -28,7 +28,6 @@ import org.mjdev.desktop.managers.theme.base.ThemeManagerStub
 import org.mjdev.desktop.extensions.PathExt.exists
 import org.mjdev.desktop.extensions.PathExt.exists
 import org.mjdev.desktop.extensions.StringExt.hexRgb
 import org.mjdev.desktop.extensions.StringExt.hexRgb
 import org.mjdev.desktop.context.IDesktopContext
 import org.mjdev.desktop.context.IDesktopContext
-import java.util.concurrent.CompletableFuture
 import java.util.concurrent.CompletableFuture.runAsync
 import java.util.concurrent.CompletableFuture.runAsync
 
 
 @Suppress("unused", "MemberVisibilityCanBePrivate")
 @Suppress("unused", "MemberVisibilityCanBePrivate")
@@ -54,14 +53,16 @@ class ThemeManagerLinux(
 
 
     override fun clearSystemTheme() {
     override fun clearSystemTheme() {
         runCatching {
         runCatching {
-            Log.i("Deleting : file:///${systemGtk3CssFile.absolutePath}")
+//            Log.i("Deleting : file:///${systemGtk3CssFile.absolutePath}")
             systemGtk3CssFile.delete()
             systemGtk3CssFile.delete()
-            Log.i("Deleting : file:///${systemGtk4CssFile.absolutePath}")
+//            Log.i("Deleting : file:///${systemGtk4CssFile.absolutePath}")
             systemGtk4CssFile.delete()
             systemGtk4CssFile.delete()
-            Log.i("Deleting theme : file:///${themeDesktopFile.parentFile.absolutePath}")
+//            Log.i("Deleting theme : file:///${themeDesktopFile.parentFile.absolutePath}")
             themeDesktopFile.parentFile.delete()
             themeDesktopFile.parentFile.delete()
         }.onFailure { e ->
         }.onFailure { e ->
             Log.e(e)
             Log.e(e)
+        }.onSuccess {
+            Log.d("Custom system theme cleared.")
         }
         }
     }
     }
 
 
@@ -77,7 +78,7 @@ class ThemeManagerLinux(
         }
         }
     }
     }
 
 
-    private fun createDesktopFile() = runAsync{
+    private fun createDesktopFile() = runAsync {
         runCatching {
         runCatching {
             desktopFile(themeDesktopFile) {
             desktopFile(themeDesktopFile) {
                 mkDirs()
                 mkDirs()

+ 1 - 1
gradle.properties

@@ -4,7 +4,7 @@ kotlin.code.style=official
 # do not check or build disabled
 # do not check or build disabled
 kotlin.native.ignoreDisabledTargets=true
 kotlin.native.ignoreDisabledTargets=true
 # gradle
 # gradle
-org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M"
+org.gradle.jvmargs=--enable-preview -Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M"
 org.gradle.parallel=true
 org.gradle.parallel=true
 # gradle build cache
 # gradle build cache
 org.gradle.configuration-cache=true
 org.gradle.configuration-cache=true

+ 33 - 7
gradle/libs.versions.toml

@@ -19,14 +19,14 @@ android-min-sdk = "24"
 vlc-version = "3.0.21-2"
 vlc-version = "3.0.21-2"
 vlc-dir = "composeApp/src/commonMain/resources/vlc/"
 vlc-dir = "composeApp/src/commonMain/resources/vlc/"
 ### lib versions ###################################################################################
 ### lib versions ###################################################################################
-gradle = "8.10.1"
+gradle = "8.11.0"
 #gradle-kotlinter = "4.3.0"
 #gradle-kotlinter = "4.3.0"
 androidx-activity-compose = "1.10.1"
 androidx-activity-compose = "1.10.1"
-androidx-lifecycle = "2.9.0"
-androidx-ui-tooling = "1.8.2"
+androidx-lifecycle = "2.9.1"
+androidx-ui-tooling = "1.8.3"
 app-icon = "1.2.6"
 app-icon = "1.2.6"
 coil = "3.2.0"
 coil = "3.2.0"
-compose-plugin = "1.8.1"
+compose-plugin = "1.8.2"
 core-splash-screen = "1.0.1"
 core-splash-screen = "1.0.1"
 generative-ai = "0.9.0-1.1.0"
 generative-ai = "0.9.0-1.1.0"
 gettext-lib = "1.11.0"
 gettext-lib = "1.11.0"
@@ -66,7 +66,11 @@ vlcj = "4.11.0"
 jna = "5.17.0"
 jna = "5.17.0"
 image-comparison = "4.4.0"
 image-comparison = "4.4.0"
 haze = "1.6.4"
 haze = "1.6.4"
-kotlinx-serialization-json= "1.8.1"
+kotlinx-serialization-json = "1.8.1"
+ktor = "3.2.0"
+flock = "0.1.0"
+markwon = "4.6.2"
+html2text = "-SNAPSHOT"
 ### libs ###########################################################################################
 ### libs ###########################################################################################
 [libraries]
 [libraries]
 ####################################################################################################
 ####################################################################################################
@@ -96,7 +100,7 @@ ychat = { module = "co.yml:ychat", version.ref = "ychat" }
 # date time
 # date time
 kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-date-time" }
 kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-date-time" }
 # json
 # json
-kotlinx-serialization-json = { module="org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref="kotlinx-serialization-json"}
+kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization-json" }
 # okhttp
 # okhttp
 okhttp3-client = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp3" }
 okhttp3-client = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp3" }
 # coil
 # coil
@@ -139,7 +143,29 @@ jna-platform-jpms = { module = "net.java.dev.jna:jna-platform-jpms", version.ref
 # image comparer
 # image comparer
 imageComparison = { module = "com.github.romankh3:image-comparison", version.ref = "image-comparison" }
 imageComparison = { module = "com.github.romankh3:image-comparison", version.ref = "image-comparison" }
 # blur
 # blur
-haze = { module= "dev.chrisbanes.haze:haze", version.ref="haze" }
+haze = { module = "dev.chrisbanes.haze:haze", version.ref = "haze" }
+# network
+ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
+ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
+ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
+ktor-client-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" }
+ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
+okhttp3-logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp3" }
+okhttp3-urlconnection = { module = "com.squareup.okhttp3:okhttp-urlconnection", version.ref = "okhttp3" }
+okhttp3-dnsoverhttps = { module = "com.squareup.okhttp3:okhttp-dnsoverhttps", version.ref = "okhttp3" }
+okhttp3-tls = { module = "com.squareup.okhttp3:okhttp-tls", version.ref = "okhttp3" }
+# ai agents
+flock-aigentic-core = { module = "community.flock.aigentic:core", version.ref = "flock" }
+flock-aigentic-openai = { module = "community.flock.aigentic:openai", version.ref = "flock" }
+flock-aigentic-gemini = { module = "community.flock.aigentic:gemini", version.ref = "flock" }
+flock-aigentic-ollama = { module = "community.flock.aigentic:ollama", version.ref = "flock" }
+flock-aigentic-vertexai = { module = "community.flock.aigentic:vertexai", version.ref = "flock" }
+flock-aigentic-http = { module = "community.flock.aigentic:http", version.ref = "flock" }
+flock-aigentic-openapi = { module = "community.flock.aigentic:openapi", version.ref = "flock" }
+# markdown
+markwon = { module = "io.noties.markwon:core", version.ref = "markwon" }
+# html 2 text
+html2text = { module = "com.github.BartoszJarocki:android-boilerpipe", version.ref = "html2text" }
 ### plugins ########################################################################################
 ### plugins ########################################################################################
 [plugins]
 [plugins]
 ####################################################################################################
 ####################################################################################################

+ 17 - 15
settings.gradle.kts

@@ -28,13 +28,14 @@ pluginManagement {
         maven("https://plugins.gradle.org/m2/")
         maven("https://plugins.gradle.org/m2/")
         maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
         maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
         maven("https://dl.bintray.com/kotlin/ktor")
         maven("https://dl.bintray.com/kotlin/ktor")
-        google {
-            mavenContent {
-                includeGroupAndSubgroups("androidx")
-                includeGroupAndSubgroups("com.android")
-                includeGroupAndSubgroups("com.google")
-            }
-        }
+        maven("https://central.sonatype.com/repository/maven-snapshots")
+//        google {
+//            mavenContent {
+//                includeGroupAndSubgroups("androidx")
+//                includeGroupAndSubgroups("com.android")
+//                includeGroupAndSubgroups("com.google")
+//            }
+//        }
         google()
         google()
     }
     }
 }
 }
@@ -60,13 +61,14 @@ dependencyResolutionManagement {
         maven("https://plugins.gradle.org/m2/")
         maven("https://plugins.gradle.org/m2/")
         maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
         maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
         maven("https://dl.bintray.com/kotlin/ktor")
         maven("https://dl.bintray.com/kotlin/ktor")
-        google {
-            mavenContent {
-                includeGroupAndSubgroups("androidx")
-                includeGroupAndSubgroups("com.android")
-                includeGroupAndSubgroups("com.google")
-            }
-        }
+        maven("https://central.sonatype.com/repository/maven-snapshots")
+//        google {
+//            mavenContent {
+//                includeGroupAndSubgroups("androidx")
+//                includeGroupAndSubgroups("com.android")
+//                includeGroupAndSubgroups("com.google")
+//            }
+//        }
         google()
         google()
     }
     }
 }
 }
@@ -84,7 +86,7 @@ include(":composeApp")
 rootProject.children.forEach { project ->
 rootProject.children.forEach { project ->
     fun configureProject(project: ProjectDescriptor) {
     fun configureProject(project: ProjectDescriptor) {
         project.buildFileName = "${project.name}.gradle.kts"
         project.buildFileName = "${project.name}.gradle.kts"
-        project.children.forEach { child->
+        project.children.forEach { child ->
             configureProject(child)
             configureProject(child)
         }
         }
     }
     }