milan jurkulák vor 2 Jahren
Ursprung
Commit
ff8f5bfe0e
32 geänderte Dateien mit 527 neuen und 607 gelöschten Zeilen
  1. 21 0
      annotations/build.gradle.kts
  2. 12 0
      annotations/src/main/kotlin/org/mjdev/annotations/CreateAndroidUnitTest.kt
  3. 12 0
      annotations/src/main/kotlin/org/mjdev/annotations/CreateScreenShot.kt
  4. 12 0
      annotations/src/main/kotlin/org/mjdev/annotations/CreateUnitTest.kt
  5. 3 3
      app/src/main/kotlin/org/mjdev/tvapp/activity/IPTVActivity.kt
  6. 1 1
      app/src/main/kotlin/org/mjdev/tvapp/activity/MainActivity.kt
  7. 1 1
      app/src/main/kotlin/org/mjdev/tvapp/activity/WebActivity.kt
  8. 1 1
      app/src/main/kotlin/org/mjdev/tvapp/ui/pages/AboutPage.kt
  9. 8 8
      app/src/main/kotlin/org/mjdev/tvapp/ui/pages/MainPage.kt
  10. 1 1
      app/src/main/kotlin/org/mjdev/tvapp/ui/pages/PluginsPage.kt
  11. 1 1
      app/src/main/kotlin/org/mjdev/tvapp/ui/pages/SubscriptionPage.kt
  12. 1 1
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/GalleryScreen.kt
  13. 3 5
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/IPTVScreen.kt
  14. 1 1
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/MainScreen.kt
  15. 1 1
      build.gradle.kts
  16. 5 0
      buildSrc/build.gradle.kts
  17. 6 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/extensions/DependencyHandlerScopeExt.kt
  18. 31 25
      buildSrc/src/main/kotlin/org/mjdev/gradle/plugin/AppPlugin.kt
  19. 16 10
      buildSrc/src/main/kotlin/org/mjdev/gradle/plugin/LibPlugin.kt
  20. 4 5
      buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/ReleaseNotesCreateTask.kt
  21. 63 45
      buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/TestClassesGeneratorTask.kt
  22. 0 488
      documentation/release-notes-1.3.1.md
  23. 2 0
      gradle.properties
  24. 14 8
      gradle/libs.versions.toml
  25. 23 0
      processor/build.gradle.kts
  26. 76 0
      processor/src/main/kotlin/org/mjdev/processor/Processor.kt
  27. 25 0
      processor/src/main/kotlin/org/mjdev/processor/ProcessorProvider.kt
  28. 31 0
      processor/src/main/kotlin/org/mjdev/processor/base/ITestBuilder.kt
  29. 93 0
      processor/src/main/kotlin/org/mjdev/processor/builders/PaparazziTestBuilder.kt
  30. 9 0
      processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider
  31. 6 2
      settings.gradle.kts
  32. 44 0
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/indicators/DashedProgressIndicator.kt

+ 21 - 0
annotations/build.gradle.kts

@@ -0,0 +1,21 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+plugins {
+    id("org.jetbrains.kotlin.jvm")
+    id("kotlin")
+}
+
+java {
+    sourceCompatibility = JavaVersion.VERSION_17
+    targetCompatibility = JavaVersion.VERSION_17
+}
+
+dependencies {
+    implementation(libs.kotlin.stdlib.jdk8)
+}

+ 12 - 0
annotations/src/main/kotlin/org/mjdev/annotations/CreateAndroidUnitTest.kt

@@ -0,0 +1,12 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.annotations
+
+@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
+annotation class CreateAndroidUnitTest

+ 12 - 0
annotations/src/main/kotlin/org/mjdev/annotations/CreateScreenShot.kt

@@ -0,0 +1,12 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.annotations
+
+@Target(AnnotationTarget.FUNCTION)
+annotation class CreateScreenShot

+ 12 - 0
annotations/src/main/kotlin/org/mjdev/annotations/CreateUnitTest.kt

@@ -0,0 +1,12 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.annotations
+
+@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
+annotation class CreateUnitTest

+ 3 - 3
app/src/main/kotlin/org/mjdev/tvapp/activity/IPTVActivity.kt

@@ -14,17 +14,17 @@ import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.Color
 import org.mjdev.tvapp.data.local.Media
 import org.mjdev.tvapp.ui.screens.GalleryScreen
-import org.mjdev.tvlib.extensions.NavGraphBuilderExt.screen
-import org.mjdev.tvlib.navigation.NavGraphBuilderEx
 import org.mjdev.tvapp.ui.screens.IPTVScreen
 import org.mjdev.tvapp.ui.screens.LoadingScreen
 import org.mjdev.tvlib.activity.TvActivity
 import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.NavControllerExt.openAsTop
+import org.mjdev.tvlib.extensions.NavGraphBuilderExt.screen
 import org.mjdev.tvlib.extensions.NavGraphBuilderExt.startScreen
 import org.mjdev.tvlib.interfaces.ItemAudio
 import org.mjdev.tvlib.interfaces.ItemPhoto
 import org.mjdev.tvlib.interfaces.ItemVideo
+import org.mjdev.tvlib.navigation.NavGraphBuilderEx
 import org.mjdev.tvlib.navigation.NavHostControllerEx
 import java.net.URL
 
@@ -64,4 +64,4 @@ class IPTVActivity : TvActivity() {
         const val IPTV_DATA = "IPTV_DATA"
     }
 
-}
+}

+ 1 - 1
app/src/main/kotlin/org/mjdev/tvapp/activity/MainActivity.kt

@@ -9,13 +9,13 @@
 package org.mjdev.tvapp.activity
 
 import androidx.compose.runtime.Composable
-import org.mjdev.tvlib.navigation.NavGraphBuilderEx
 import org.mjdev.tvapp.ui.screens.MainScreen
 import org.mjdev.tvapp.ui.screens.SplashScreen
 import org.mjdev.tvlib.activity.TvActivity
 import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.NavGraphBuilderExt.homeScreen
 import org.mjdev.tvlib.extensions.NavGraphBuilderExt.startScreen
+import org.mjdev.tvlib.navigation.NavGraphBuilderEx
 
 @Suppress("PreviewShouldNotBeCalledRecursively")
 class MainActivity : TvActivity() {

+ 1 - 1
app/src/main/kotlin/org/mjdev/tvapp/activity/WebActivity.kt

@@ -11,13 +11,13 @@ package org.mjdev.tvapp.activity
 import android.content.Intent
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.Color
-import org.mjdev.tvlib.navigation.NavGraphBuilderEx
 import org.mjdev.tvapp.ui.screens.WebScreen
 import org.mjdev.tvlib.activity.TvActivity
 import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.NavControllerExt.openAsTop
 import org.mjdev.tvlib.extensions.NavGraphBuilderExt.startScreen
 import org.mjdev.tvlib.extensions.StringExt.parseUri
+import org.mjdev.tvlib.navigation.NavGraphBuilderEx
 import org.mjdev.tvlib.navigation.NavHostControllerEx
 
 @Suppress("PreviewShouldNotBeCalledRecursively")

+ 1 - 1
app/src/main/kotlin/org/mjdev/tvapp/ui/pages/AboutPage.kt

@@ -27,9 +27,9 @@ import androidx.tv.material3.CardDefaults
 import org.mjdev.tvapp.R
 import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.card.Card
-import org.mjdev.tvlib.ui.components.page.Page
 import org.mjdev.tvlib.ui.components.card.CardContent
 import org.mjdev.tvlib.ui.components.image.CircleImage
+import org.mjdev.tvlib.ui.components.page.Page
 import org.mjdev.tvlib.ui.components.text.TextAny
 
 class AboutPage : Page() {

+ 8 - 8
app/src/main/kotlin/org/mjdev/tvapp/ui/pages/MainPage.kt

@@ -34,22 +34,22 @@ import org.mjdev.tvapp.activity.MainActivity
 import org.mjdev.tvapp.app.Application
 import org.mjdev.tvapp.data.events.SyncEvent
 import org.mjdev.tvapp.sync.SyncAdapter.Companion.pauseSync
-import org.mjdev.tvlib.data.local.User
-import org.mjdev.tvlib.auth.AuthManager.Companion.rememberAuthManager
-import org.mjdev.tvlib.ui.components.page.Page
-import org.mjdev.tvlib.ui.components.tv.AppsRow
-import org.mjdev.tvlib.ui.components.tv.BrowseView
-import org.mjdev.tvlib.ui.components.tv.LocalAudioRow
-import org.mjdev.tvlib.ui.components.tv.LocalPhotosRow
-import org.mjdev.tvlib.ui.components.tv.LocalVideoRow
 import org.mjdev.tvapp.viewmodel.MainViewModel
 import org.mjdev.tvlib.annotations.Previews
+import org.mjdev.tvlib.auth.AuthManager.Companion.rememberAuthManager
+import org.mjdev.tvlib.data.local.User
 import org.mjdev.tvlib.extensions.ComposeExt.observedEvents
 import org.mjdev.tvlib.extensions.KodeinExt.rememberInstance
 import org.mjdev.tvlib.extensions.NavExt.rememberNavControllerEx
 import org.mjdev.tvlib.interfaces.ItemPhoto
 import org.mjdev.tvlib.interfaces.ItemWithBackground
 import org.mjdev.tvlib.interfaces.ItemWithImage
+import org.mjdev.tvlib.ui.components.page.Page
+import org.mjdev.tvlib.ui.components.tv.AppsRow
+import org.mjdev.tvlib.ui.components.tv.BrowseView
+import org.mjdev.tvlib.ui.components.tv.LocalAudioRow
+import org.mjdev.tvlib.ui.components.tv.LocalPhotosRow
+import org.mjdev.tvlib.ui.components.tv.LocalVideoRow
 import java.io.Serializable
 import java.net.URL
 

+ 1 - 1
app/src/main/kotlin/org/mjdev/tvapp/ui/pages/PluginsPage.kt

@@ -25,10 +25,10 @@ import androidx.compose.ui.unit.dp
 import androidx.tv.material3.CardDefaults
 import org.mjdev.tvapp.R
 import org.mjdev.tvlib.annotations.Previews
+import org.mjdev.tvlib.ui.components.card.Card
 import org.mjdev.tvlib.ui.components.card.CardContent
 import org.mjdev.tvlib.ui.components.page.Page
 import org.mjdev.tvlib.ui.components.text.TextAny
-import org.mjdev.tvlib.ui.components.card.Card
 
 class PluginsPage : Page() {
     override val title: Int = R.string.title_plugins

+ 1 - 1
app/src/main/kotlin/org/mjdev/tvapp/ui/pages/SubscriptionPage.kt

@@ -26,8 +26,8 @@ import androidx.tv.material3.CardDefaults
 import org.mjdev.tvapp.R
 import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.card.Card
-import org.mjdev.tvlib.ui.components.page.Page
 import org.mjdev.tvlib.ui.components.card.CardContent
+import org.mjdev.tvlib.ui.components.page.Page
 import org.mjdev.tvlib.ui.components.text.TextAny
 
 class SubscriptionPage : Page() {

+ 1 - 1
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/GalleryScreen.kt

@@ -19,12 +19,12 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.platform.LocalContext
 import androidx.navigation.navArgument
-import org.mjdev.tvlib.extensions.KodeinExt.rememberInstance
 import org.mjdev.tvapp.R
 import org.mjdev.tvapp.app.Application
 import org.mjdev.tvapp.sync.SyncAdapter.Companion.pauseSyncUntilGone
 import org.mjdev.tvapp.viewmodel.DetailViewModel
 import org.mjdev.tvlib.annotations.Previews
+import org.mjdev.tvlib.extensions.KodeinExt.rememberInstance
 import org.mjdev.tvlib.extensions.ListExt.indexOf
 import org.mjdev.tvlib.extensions.MediaItemExt.uri
 import org.mjdev.tvlib.navigation.AnyType

+ 3 - 5
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/IPTVScreen.kt

@@ -20,17 +20,17 @@ import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.platform.LocalContext
 import androidx.media3.common.MediaItem
 import androidx.navigation.navArgument
-import org.mjdev.tvlib.extensions.KodeinExt.rememberInstance
 import org.mjdev.tvapp.R
 import org.mjdev.tvapp.app.Application
 import org.mjdev.tvapp.sync.SyncAdapter.Companion.pauseSyncUntilGone
 import org.mjdev.tvapp.viewmodel.IPTVViewModel
 import org.mjdev.tvlib.annotations.Previews
+import org.mjdev.tvlib.extensions.KodeinExt.rememberInstance
+import org.mjdev.tvlib.extensions.ListExt.indexOf
+import org.mjdev.tvlib.extensions.MediaItemExt.uri
 import org.mjdev.tvlib.navigation.AnyType
 import org.mjdev.tvlib.screen.Screen
 import org.mjdev.tvlib.ui.components.media.MediaPlayerContainer
-import org.mjdev.tvlib.extensions.MediaItemExt.uri
-import org.mjdev.tvlib.extensions.ListExt.indexOf
 import org.mjdev.tvlib.ui.components.media.MediaPlayerState.Companion.rememberMediaPlayerState
 import timber.log.Timber
 
@@ -93,5 +93,3 @@ class IPTVScreen : Screen() {
     }
 
 }
-
-

+ 1 - 1
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/MainScreen.kt

@@ -41,6 +41,6 @@ class MainScreen : ScreenWithPages() {
 
     @Previews
     @Composable
-    override fun Content()  = super.Content()
+    override fun Content() = super.Content()
 
 }

+ 1 - 1
build.gradle.kts

@@ -15,10 +15,10 @@ plugins {
 
 buildscript {
     repositories {
+        google()
         mavenCentral()
         maven("https://storage.googleapis.com/r8-releases/raw")
         maven("https://mvn.dailymotion.com/repository/releases/")
-        google()
     }
 
     dependencies {

+ 5 - 0
buildSrc/build.gradle.kts

@@ -16,10 +16,12 @@ repositories {
     maven(url = "https://plugins.gradle.org/m2/")
     maven(url = "https://oss.sonatype.org/content/repositories/public")
     maven(url = "https://oss.sonatype.org/content/repositories/snapshots")
+    maven(url = uri("https://packages.jetbrains.team/maven/p/reflekt/reflekt"))
 }
 
 plugins {
     `kotlin-dsl`
+//    id("org.jetbrains.reflekt") version "1.5.30"
 }
 
 dependencies {
@@ -45,6 +47,9 @@ dependencies {
     implementation(libs.kotlin.mockito)
     implementation(libs.junit)
     implementation(libs.kotlin.compose.compiler)
+    implementation(libs.symbol.processing.api)
+//    implementation(libs.kotlin.reflekt.dsl)
+//    implementation(libs.symbol.processing.embeddable)
 //    implementation(libs.apk.parser)
 //    implementation(libs.gradle.docker.plugin)
 //    implementation(libs.korim.jvm)

+ 6 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/extensions/DependencyHandlerScopeExt.kt

@@ -61,3 +61,9 @@ fun DependencyHandlerScope.ksp(
 ) {
     add(KSP_IMPLEMENTATION, dependency.get())
 }
+
+fun DependencyHandlerScope.ksp(
+    dependency: Dependency
+) {
+    add(KSP_IMPLEMENTATION, dependency)
+}

+ 31 - 25
buildSrc/src/main/kotlin/org/mjdev/gradle/plugin/AppPlugin.kt

@@ -16,49 +16,50 @@ import org.gradle.api.Project
 import org.gradle.api.artifacts.dsl.LockMode
 import org.gradle.kotlin.dsl.configure
 import org.gradle.kotlin.dsl.dependencies
+import org.gradle.kotlin.dsl.project
 import org.jetbrains.dokka.Platform
 import org.jmailen.gradle.kotlinter.KotlinterExtension
 import org.jmailen.gradle.kotlinter.KotlinterPlugin
+import org.kordamp.gradle.plugin.markdown.MarkdownPlugin
 import org.mjdev.gradle.base.BasePlugin
 import org.mjdev.gradle.extensions.addSyncProviderAuthString
+import org.mjdev.gradle.extensions.androidTestImplementation
+import org.mjdev.gradle.extensions.applicationId
+import org.mjdev.gradle.extensions.applyPlugin
 import org.mjdev.gradle.extensions.asInt
-import org.mjdev.gradle.extensions.registerTask
-import org.mjdev.gradle.extensions.runAfterAssembleTask
+import org.mjdev.gradle.extensions.assembleTasks
 import org.mjdev.gradle.extensions.buildConfigString
+import org.mjdev.gradle.extensions.cleanProjectTask
+import org.mjdev.gradle.extensions.debugImplementation
+import org.mjdev.gradle.extensions.detektTask
+import org.mjdev.gradle.extensions.dokkaTask
 import org.mjdev.gradle.extensions.extension
-import org.mjdev.gradle.extensions.libs
-import org.mjdev.gradle.extensions.manifestPlaceholders
+import org.mjdev.gradle.extensions.fromBuildPropertiesFile
 import org.mjdev.gradle.extensions.implementation
-import org.mjdev.gradle.extensions.debugImplementation
-import org.mjdev.gradle.extensions.testImplementation
-import org.mjdev.gradle.extensions.androidTestImplementation
-import org.mjdev.gradle.extensions.applicationId
+import org.mjdev.gradle.extensions.kotlinCompileOptions
 import org.mjdev.gradle.extensions.ksp
+import org.mjdev.gradle.extensions.libs
+import org.mjdev.gradle.extensions.loadRootPropertiesFile
+import org.mjdev.gradle.extensions.manifestPlaceholders
+import org.mjdev.gradle.extensions.markDownToHtmlTask
+import org.mjdev.gradle.extensions.projectName
+import org.mjdev.gradle.extensions.registerTask
+import org.mjdev.gradle.extensions.releaseNotesCreateTask
+import org.mjdev.gradle.extensions.runAfterAssembleTask
 import org.mjdev.gradle.extensions.setSigningConfigs
 import org.mjdev.gradle.extensions.stringRes
+import org.mjdev.gradle.extensions.testImplementation
+import org.mjdev.gradle.extensions.variants
 import org.mjdev.gradle.extensions.versionCode
 import org.mjdev.gradle.extensions.versionName
-import org.mjdev.gradle.extensions.kotlinCompileOptions
-import org.mjdev.gradle.extensions.detektTask
-import org.mjdev.gradle.extensions.dokkaTask
-import org.mjdev.gradle.extensions.releaseNotesCreateTask
-import org.mjdev.gradle.extensions.applyPlugin
-import org.mjdev.gradle.extensions.projectName
 import org.mjdev.gradle.extensions.webServiceCreateTask
-import org.mjdev.gradle.extensions.loadRootPropertiesFile
-import org.mjdev.gradle.extensions.fromBuildPropertiesFile
+import org.mjdev.gradle.extensions.zipReleaseCreateTask
 import org.mjdev.gradle.plugin.config.AppConfig
-import org.mjdev.gradle.tasks.ReleaseNotesCreateTask
-import org.mjdev.gradle.tasks.WebServiceCreateTask
-import org.mjdev.gradle.tasks.CreatePropsTask
 import org.mjdev.gradle.tasks.CheckNewLibsTask
 import org.mjdev.gradle.tasks.CleanProjectTask
-import org.kordamp.gradle.plugin.markdown.MarkdownPlugin
-import org.mjdev.gradle.extensions.assembleTasks
-import org.mjdev.gradle.extensions.cleanProjectTask
-import org.mjdev.gradle.extensions.markDownToHtmlTask
-import org.mjdev.gradle.extensions.variants
-import org.mjdev.gradle.extensions.zipReleaseCreateTask
+import org.mjdev.gradle.tasks.CreatePropsTask
+import org.mjdev.gradle.tasks.ReleaseNotesCreateTask
+import org.mjdev.gradle.tasks.WebServiceCreateTask
 import org.mjdev.gradle.tasks.ZipReleaseCreateTask
 
 @Suppress("UnstableApiUsage")
@@ -74,6 +75,8 @@ class AppPlugin : BasePlugin() {
         applyPlugin(libs.plugins.objectbox)
         applyPlugin(libs.plugins.gradle.dokka)
         applyPlugin(libs.plugins.kotlin.compose.compiler)
+        applyPlugin(libs.plugins.gradle.paparazzi.plugin)
+//        applyPlugin(libs.plugins.kotlin.reflekt)
         applyPlugin<MarkdownPlugin>()
         applyPlugin<DetektPlugin>()
         applyPlugin<KotlinterPlugin>()
@@ -407,6 +410,9 @@ class AppPlugin : BasePlugin() {
             androidTestImplementation(libs.androidx.espresso.core)
             // anr
             implementation(libs.anrwatchdog)
+            // own ksp
+            implementation(project(":annotations"))
+            ksp(project(":processor"))
             // oauth
 //            implementation(libs.auth0)
 //            implementation(libs.android.jwtdecode)

+ 16 - 10
buildSrc/src/main/kotlin/org/mjdev/gradle/plugin/LibPlugin.kt

@@ -15,29 +15,30 @@ import org.gradle.api.Project
 import org.gradle.api.artifacts.dsl.LockMode
 import org.gradle.kotlin.dsl.configure
 import org.gradle.kotlin.dsl.dependencies
+import org.gradle.kotlin.dsl.project
 import org.jetbrains.dokka.Platform
 import org.jmailen.gradle.kotlinter.KotlinterExtension
 import org.jmailen.gradle.kotlinter.KotlinterPlugin
 import org.mjdev.gradle.base.BasePlugin
-import org.mjdev.gradle.plugin.config.LibConfig
+import org.mjdev.gradle.extensions.androidTestImplementation
+import org.mjdev.gradle.extensions.applyPlugin
 import org.mjdev.gradle.extensions.asInt
-import org.mjdev.gradle.extensions.runAfterAssembleTask
-import org.mjdev.gradle.extensions.extension
-import org.mjdev.gradle.extensions.libs
-import org.mjdev.gradle.extensions.implementation
 import org.mjdev.gradle.extensions.debugImplementation
-import org.mjdev.gradle.extensions.testImplementation
-import org.mjdev.gradle.extensions.androidTestImplementation
-import org.mjdev.gradle.extensions.ksp
-import org.mjdev.gradle.extensions.kotlinCompileOptions
 import org.mjdev.gradle.extensions.detektTask
 import org.mjdev.gradle.extensions.dokkaTask
+import org.mjdev.gradle.extensions.extension
 import org.mjdev.gradle.extensions.fromBuildPropertiesFile
+import org.mjdev.gradle.extensions.implementation
+import org.mjdev.gradle.extensions.kotlinCompileOptions
+import org.mjdev.gradle.extensions.ksp
+import org.mjdev.gradle.extensions.libs
 import org.mjdev.gradle.extensions.loadRootPropertiesFile
 import org.mjdev.gradle.extensions.projectName
 import org.mjdev.gradle.extensions.registerTask
+import org.mjdev.gradle.extensions.runAfterAssembleTask
+import org.mjdev.gradle.extensions.testImplementation
+import org.mjdev.gradle.plugin.config.LibConfig
 import org.mjdev.gradle.tasks.CreatePropsTask
-import org.mjdev.gradle.extensions.applyPlugin
 
 @Suppress("UnstableApiUsage")
 class LibPlugin : BasePlugin() {
@@ -53,6 +54,8 @@ class LibPlugin : BasePlugin() {
         applyPlugin(libs.plugins.objectbox)
         applyPlugin(libs.plugins.gradle.dokka)
         applyPlugin(libs.plugins.kotlin.compose.compiler)
+        applyPlugin(libs.plugins.gradle.paparazzi.plugin)
+//        applyPlugin(libs.plugins.kotlin.reflekt)
         applyPlugin<DetektPlugin>()
         applyPlugin<KotlinterPlugin>()
         registerTask<CreatePropsTask> {
@@ -272,6 +275,9 @@ class LibPlugin : BasePlugin() {
             androidTestImplementation(libs.androidx.espresso.core)
             // anr
             implementation(libs.anrwatchdog)
+            // own ksp
+            implementation(project(":annotations"))
+            ksp(project(":processor"))
             // oauth
 //            implementation(libs.auth0)
 //            implementation(libs.android.jwtdecode)

+ 4 - 5
buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/ReleaseNotesCreateTask.kt

@@ -10,14 +10,14 @@ package org.mjdev.gradle.tasks
 
 import org.gradle.internal.impldep.org.eclipse.jgit.api.Git
 import org.gradle.internal.impldep.org.eclipse.jgit.internal.storage.file.FileRepository
+import org.mjdev.gradle.base.BaseTask
+import org.mjdev.gradle.extensions.file
+import org.mjdev.gradle.extensions.projectVersion
 import org.mjdev.gradle.extensions.toDateString
+import org.mjdev.gradle.extensions.writeText
 import java.io.File
 import java.util.Date
 import java.util.Locale
-import org.mjdev.gradle.extensions.file
-import org.mjdev.gradle.extensions.writeText
-import org.mjdev.gradle.extensions.projectVersion
-import org.mjdev.gradle.base.BaseTask
 
 open class ReleaseNotesCreateTask : BaseTask() {
 
@@ -53,7 +53,6 @@ open class ReleaseNotesCreateTask : BaseTask() {
     }
 
     override fun onAssemble() {
-        println("Creating release notes")
         StringBuilder().apply {
             @Suppress("DEPRECATION")
             append("## Release notes $projectVersion - ${Date().toLocaleString()}\n")

+ 63 - 45
buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/TestClassesGeneratorTask.kt

@@ -8,19 +8,34 @@
 
 package org.mjdev.gradle.tasks
 
-import com.squareup.kotlinpoet.FileSpec
-import org.gradle.api.Project
+//import com.google.devtools.ksp.impl.CommandLineKSPLogger
+//import com.google.devtools.ksp.impl.KotlinSymbolProcessing
+//import com.google.devtools.ksp.processing.KSPJvmConfig
+//import com.google.devtools.ksp.processor.AbstractTestProcessor
+//import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
+//import org.jetbrains.kotlin.cli.jvm.config.javaSourceRoots
+//import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
+//import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots
+//import org.jetbrains.kotlin.config.JVMConfigurationKeys
+//import org.jetbrains.kotlin.config.languageVersionSettings
+//import org.jetbrains.kotlin.test.compileJavaFiles
+//import org.jetbrains.kotlin.test.kotlinPathsForDistDirectoryForTests
+//import org.jetbrains.kotlin.test.model.FrontendKinds
+//import org.jetbrains.kotlin.test.model.TestModule
+//import org.jetbrains.kotlin.test.services.JUnit5Assertions
+//import org.jetbrains.kotlin.test.services.TestServices
+//import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
+//import org.jetbrains.kotlin.test.services.isKtFile
+//import org.jetbrains.kotlin.test.util.KtTestUtil
+//import org.jetbrains.kotlin.utils.PathUtil
 import org.mjdev.gradle.base.BaseTask
-import org.mjdev.gradle.extensions.file
 import org.mjdev.gradle.extensions.allFiles
-import org.mjdev.gradle.extensions.unitTestDir
-import org.mjdev.gradle.extensions.asTestFile
-import java.io.File
+import org.mjdev.gradle.extensions.file
 
-@Suppress("unused", "PrivatePropertyName")
+@Suppress("unused")
 open class TestClassesGeneratorTask : BaseTask() {
-    private val GH_API_KEY = "0f2d28811bd14776b5c6fd4a84798d5b.96b1d61fc593b1ba"
-    private val GH_API_URL = "https://api-beta.copilot.com"
+//    private val GH_API_KEY = "0f2d28811bd14776b5c6fd4a84798d5b.96b1d61fc593b1ba"
+//    private val GH_API_URL = "https://api-beta.copilot.com"
 
     //curl \
     //  -X POST \
@@ -35,8 +50,7 @@ open class TestClassesGeneratorTask : BaseTask() {
         p.file("src").file("main").allFiles("kt")
     }
 
-    private val worker = GithubClassWorker()
-
+//    private val worker = GithubClassWorker()
 
     init {
         group = "mjdev"
@@ -44,48 +58,52 @@ open class TestClassesGeneratorTask : BaseTask() {
         outputs.upToDateWhen { false }
     }
 
-    private fun createTestFile(
-        project: Project,
-        file: File
-    ) {
-        makeTestFile(
-            file,
-            File(project.unitTestDir, file.asTestFile.name)
-        )
-    }
-
-    @Suppress("SpellCheckingInspection")
-    private fun makeTestFile(
-        srcFile: File,
-        destfile: File
-    ) {
-        worker.makeTestClass(srcFile).also { createdClass ->
-            createdClass?.writeTo(destfile)
-        }
-    }
-
-    interface ClassWorker {
-        fun makeTestClass(file: File): FileSpec?
-    }
+//    private fun createTestFile(
+//        project: Project,
+//        file: File
+//    ) {
+//        makeTestFile(
+//            file,
+//            File(project.unitTestDir, file.asTestFile.name)
+//        )
+//    }
+
+//    @Suppress("SpellCheckingInspection")
+//    private fun makeTestFile(
+//        srcFile: File,
+//        destfile: File
+//    ) {
+//        worker.makeTestClass(srcFile).also { createdClass ->
+//            createdClass?.writeTo(destfile)
+//        }
+//    }
+
+//    interface ClassWorker {
+//        fun makeTestClass(file: File): FileSpec?
+//    }
 
     // todo
 
-    class GithubClassWorker : ClassWorker {
-        override fun makeTestClass(file: File): FileSpec? = null
-    }
+//    class GithubClassWorker : ClassWorker {
+//        override fun makeTestClass(file: File): FileSpec? = null
+//    }
 
     override fun onClean() {
     }
 
     override fun onAssemble() {
-        println("> Got files:")
-        fileMap.keys.forEach { project ->
-            val files = fileMap[project] ?: emptyList()
-            files.forEach { file ->
-                println("> ${project.name} > $file")
-                createTestFile(project, file)
-            }
-        }
+//        val kspConfig = KSPJvmConfig.Builder().apply {
+//             All configurations happen here.
+//        }.build()
+//        val exitCode = KotlinSymbolProcessing(kspConfig, listOfProcessors, kspLoggerImpl).execute()
+//        println("> Got files:")
+//        fileMap.keys.forEach { project ->
+//            val files = fileMap[project] ?: emptyList()
+//            files.forEach { file ->
+//                println("> ${project.name} > $file")
+//                createTestFile(project, file)
+//            }
+//        }
     }
 
 }

+ 0 - 488
documentation/release-notes-1.3.1.md

@@ -1,488 +0,0 @@
-## Release notes 1.0.0 - 14. 6. 2024, 13:21:36
-
-* 14.06.2024
-
-* [milan jurkulák] : kodein improvements 
-* [milan jurkulák] : kodein improvements 
-* [milan jurkulák] : kodein improvements 
-* [milan jurkulák] : code cleanup 
-* [milan jurkulák] : code cleanup 
-
-* 13.06.2024
-
-* [milan jurkulák] : tv lib update 
-* [milan jurkulák] : dagger removal, kodein pre-implementation  
-
-* 22.05.2024
-
-* [milan jurkulák] : update libs  update libs 
-
-* 20.05.2024
-
-* [milan jurkulák] : kapt removal 
-* [milan jurkulák] : new compose & kotlin 2 
-
-* 02.05.2024
-
-* [milan jurkulák] : documentation update 
-* [milan jurkulák] : documentation update 
-* [milan jurkulák] : documentation update 
-* [milan jurkulák] : build script update 
-* [milan jurkulák] : download button 
-* [milan jurkulák] : download button 
-* [milan jurkulák] : update documentations 
-* [milan jurkulák] : update documentations 
-* [milan jurkulák] : update documentations 
-* [milan jurkulák] : update documentations 
-* [milan jurkulák] : update actions 
-* [milan jurkulák] : update actions 
-* [milan jurkulák] : documentation 
-* [milan jurkulák] : documentation 
-* [milan jurkulák] : documentation 
-* [milan jurkulák] : documentation 
-* [milan jurkulák] : dockerfile 
-* [milan jurkulák] : action update  
-* [milan jurkulák] : dockerfile 
-* [milan jurkulák] : dockerfile 
-* [milan jurkulák] : dockerfile 
-* [milan jurkulák] : dockerfile 
-* [milan jurkulák] : dockerfile 
-* [milan jurkulák] : dockerfile 
-* [milan jurkulák] : dockerfile 
-* [milan jurkulák] : dockerfile 
-* [milan jurkulák] : dockerfile 
-* [milan jurkulák] : dockerfile 
-* [milan jurkulák] : dockerfile 
-* [milan jurkulák] : generated files removal 
-* [milan jurkulák] : generated files removal 
-* [milan jurkulák] : generated files removal 
-* [milan jurkulák] : generated files removal 
-* [milan jurkulák] : generated files removal 
-* [milan jurkulák] : code improvements 
-
-* 01.05.2024
-
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-
-* 30.04.2024
-
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-
-* 29.04.2024
-
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulak] : code improvements  code improvements  code improvements  code improvements  code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-
-* 28.04.2024
-
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements 
-* [milan jurkulák] : code improvements  code improvements  code improvements 
-
-* 15.02.2024
-
-* [milan jurkulak] : code improvements 
-
-* 08.02.2024
-
-* [milan jurkulak] : code improvements 
-
-* 07.02.2024
-
-* [milan jurkulak] : code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements 
-
-* 09.01.2024
-
-* [milan jurkulak] : number digits 
-* [milan jurkulak] : code improvements 
-* [milan jurkulak] : code improvements 
-* [milan jurkulak] : background changes 
-
-* 05.01.2024
-
-* [milan jurkulak] : code improvements  
-* [milan jurkulak] : webview fetcher  web scrapper webview  web scrapper webview 
-
-* 27.12.2023
-
-* [milan jurkulak] : build release fix 
-* [milan jurkulak] : scrapper improvements 
-* [milan jurkulak] : scrapper improvements  scrapper improvements  scrapper improvements  scrapper improvements 
-
-* 26.12.2023
-
-* [milan jurkulak] : config field fix / proguard fix 
-* [milan jurkulak] : build improvements 
-
-* 21.12.2023
-
-* [milan jurkulak] : scrapper base  scrapper base 
-* [milan jurkulak] : navigation improvements 
-
-* 19.12.2023
-
-* [milan jurkulak] : navigation improvements / need more improvements 
-
-* 06.12.2023
-
-* [milan jurkulak] : code improvements 
-* [milan jurkulak] : code improvements 
-
-* 05.12.2023
-
-* [milan jurkulak] : scroll improvements 
-* [milan jurkulak] : update fix 
-* [milan jurkulak] : update fix 
-
-* 04.12.2023
-
-* [milan jurkulak] : update fix 
-* [milan jurkulak] : update fix 
-* [milan jurkulak] : app bump 
-* [milan jurkulak] : merge remote-tracking branch 'origin/main' 
-* [milan jurkulák] : delete .github/workflows/codeql.yml
-* [milan jurkulak] : code improvements 
-* [milan jurkulak] : code improvements  code improvements  code improvements  code improvements  code improvements 
-* [milan jurkulak] : glide album art 
-* [milan jurkulak] : web scrapper pre-implement  web scrapper pre-implement 
-
-* 16.10.2023
-
-* [milan jurkulak] : images glide 
-
-* 12.10.2023
-
-* [milan jurkulak] : libraries versions bump 
-* [milan jurkulak] : theme dynamic & payments preimplementation 
-
-* 06.10.2023
-
-* [milan jurkulak] : image caching improvement 
-
-* 05.10.2023
-
-* [milan jurkulak] : minify temporary removal 
-* [milan jurkulak] : 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 
-
-* 30.09.2023
-
-* [milan jurkulak] : merge remote-tracking branch 'origin/main' 
-* [milan jurkulak] : code cleanup 
-* [milan jurkulak] : image loader improvements 
-
-* 29.09.2023
-
-* [milan jurkulák] : codeql.yml
-* [milan jurkulak] : remembers 
-
-* 27.09.2023
-
-* [milan jurkulak] : test component 
-* [milan jurkulak] : app updater 
-* [milan jurkulak] : html scrapper 
-* [milan jurkulak] : design improvement 
-
-* 21.08.2023
-
-* [milan jurkulak] : sync improvement 
-
-* 20.08.2023
-
-* [milan jurkulak] : play next on error preimplementation 
-* [milan jurkulak] : sync improvement 
-* [milan jurkulak] : network check improvement 
-* [milan jurkulak] : mobile apps fix 
-* [milan jurkulak] : app updater preimplement  app updater  app updater  app updater 
-* [milan jurkulak] : messages, resources 
-* [milan jurkulak] : code coments 
-
-* 19.08.2023
-
-* [milan jurkulak] : mediaitem uri fix 
-* [milan jurkulak] : mediaitem uri fix 
-* [milan jurkulak] : design improvements  design improvements  design improvements 
-* [milan jurkulak] : media player improvements 
-* [milan jurkulak] : nav controller fix 
-* [milan jurkulak] : lifecycle fix 
-
-* 18.08.2023
-
-* [milan jurkulak] : caching cursor fixes 
-
-* 11.08.2023
-
-* [milan jurkulak] : code improvements 
-* [milan jurkulak] : code improvements 
-* [milan jurkulak] : notification importance change 
-* [milan jurkulak] : player improvements  player improvements 
-
-* 10.08.2023
-
-* [milan jurkulak] : gridviews preimplementation  
-* [milan jurkulak] : media session  media session 
-* [milan jurkulak] : audio focus 
-* [milan jurkulak] : graphic resources & widget prepare 
-* [milan jurkulak] : mediaplayer widget preimplementation 
-* [milan jurkulak] : mediaplayer lifecycle / performance 
-* [milan jurkulak] : media state fixes 
-* [milan jurkulak] : audio preview fixes 
-
-* 09.08.2023
-
-* [milan jurkulak] : playernotificationmanager preimplementation (mobile) 
-* [milan jurkulak] : code cleanup 
-* [milan jurkulak] : sync improvements 
-* [milan jurkulak] : code improvements 
-* [milan jurkulak] : design fixes 
-* [milan jurkulak] : performance improvements  
-* [milan jurkulak] : sanwitch lib for removing bpt 
-
-* 08.08.2023
-
-* [milan jurkulak] : audio player preview dailymotion 
-* [milan jurkulak] : config changes preparation 
-* [milan jurkulak] : exoplayer transparency 
-* [milan jurkulak] : padding fix main screen 
-* [milan jurkulak] : download video for audio files, preimplementation 
-* [milan jurkulak] : design improvements  design improvements  design improvements  design improvements  design improvements  design improvements 
-
-* 07.08.2023
-
-* [milan jurkulak] : navigation padding 
-* [milan jurkulak] : gallery double tap 
-* [milan jurkulak] : gallery selection fix 
-* [milan jurkulak] : code cleanup & improvements 
-* [milan jurkulak] : page improvements 
-* [milan jurkulak] : focus fixes  
-* [milan jurkulak] : design fixes  design fixes 
-* [milan jurkulak] : carousel reimplementation 
-* [milan jurkulak] : carousel reimplementation 
-* [milan jurkulak] : activity lifecycle improvements 
-* [milan jurkulak] : image cache improvements 
-* [milan jurkulak] : manifest fixes 
-* [milan jurkulak] : cursor improvements 
-* [milan jurkulak] : anr fixes 
-
-* 06.08.2023
-
-* [milan jurkulak] : code fixes 
-* [milan jurkulak] : coil improvements 
-* [milan jurkulak] : caching album art data 
-* [milan jurkulak] : placeholder improvement 
-* [milan jurkulak] : webview fixes 
-* [milan jurkulak] : album art downloader cover art improvement 
-* [milan jurkulak] : album art downloader cover art 
-* [milan jurkulak] : gallery custom overlay support 
-* [milan jurkulak] : web client user agent 
-* [milan jurkulak] : carousel fixes 
-* [milan jurkulak] : swipe gestures for big carousel & gallery 
-* [milan jurkulak] : swipe gestures for big carousel & gallery 
-* [milan jurkulak] : code cleanup 
-* [milan jurkulak] : icon change 
-* [milan jurkulak] : item info improvement 
-* [milan jurkulak] : item info improvement 
-* [milan jurkulak] : code clean 
-* [milan jurkulak] : storage permissions fix 
-* [milan jurkulak] : detail improvements  detail improvements  detail improvements  detail improvements  detail improvements  detail improvements  detail improvements  detail improvements  detail improvements 
-
-* 04.08.2023
-
-* [milan jurkulak] : library update post fixes 
-* [milan jurkulak] : agp upgrade  agp upgrade 
-
-* 03.08.2023
-
-* [milan jurkulak] : oauth preimplementation 
-* [milan jurkulak] : library update 
-
-* 02.08.2023
-
-* [milan jurkulak] : detail screen improvements  detail screen improvements  detail screen improvements 
-* [milan jurkulak] : player improvements 
-* [milan jurkulak] : settings preimlplementation 
-* [milan jurkulak] : album art for coil 
-* [milan jurkulak] : mobile navigation modal 
-
-* 01.08.2023
-
-* [milan jurkulak] : player improvements & detail improvements 
-* [milan jurkulak] : code improvements  code improvements  code improvements 
-* [milan jurkulak] : better navigation prepare  better navigation prepare 
-* [milan jurkulak] : main page improvements 
-* [milan jurkulak] : portrait / landscape mode 
-
-* 23.07.2023
-
-* [milan jurkulak] : code improvements for preview 
-* [milan jurkulak] : repos refactor 
-
-* 22.07.2023
-
-* [milan jurkulak] : data fixes 
-* [milan jurkulak] : design improvements 
-* [milan jurkulak] : iptv categories 
-* [milan jurkulak] : iptv 
-* [milan jurkulak] : media player controls  media player controls 
-
-* 21.07.2023
-
-* [milan jurkulak] : pages improvement 
-* [milan jurkulak] : lottie support 
-
-* 18.07.2023
-
-* [milan jurkulak] : code move / anr reporting 
-* [milan jurkulak] : libs update 
-* [milan jurkulak] : new screenshots 
-* [milan jurkulak] : libs ver. upgrade 
-* [milan jurkulak] : media player controls 
-* [milan jurkulak] : xml layout component 
-* [milan jurkulak] : anr spy 
-* [milan jurkulak] : photo improvements 
-
-* 12.07.2023
-
-* [milan jurkulak] : photo improvements 
-* [milan jurkulak] : photo detail fix 
-* [milan jurkulak] : launcher add 
-* [milan jurkulak] : performance fix 
-* [milan jurkulak] : app manager fix / removal of itself from list 
-* [milan jurkulak] : photo item tablet fix 
-* [milan jurkulak] : card text focus background 
-* [milan jurkulak] : fading background 
-* [milan jurkulak] : readme update 
-* [milan jurkulak] : temporary dokka disablement & code cleanup 
-* [milan jurkulak] : items improve 
-* [milan jurkulak] : library pre-implementation 
-* [milan jurkulak] : tablet photos cursor fix 
-* [milan jurkulak] : tablet screen padding fix 
-* [milan jurkulak] : tablet background fix 
-* [milan jurkulak] : cursor sort order  cursor sort order 
-* [milan jurkulak] : carousel finalization 
-* [milan jurkulak] : featured items #1 
-* [milan jurkulak] : tv pager fix #1 
-* [milan jurkulak] : performance improvements 
-
-* 11.07.2023
-
-* [milan jurkulak] : pager animation 
-* [milan jurkulak] : image load improvement 
-* [milan jurkulak] : cursor row scroll improvement 
-* [milan jurkulak] : cursor row scroll improvement 
-* [milan jurkulak] : cursor improvement  cursor improvement 
-* [milan jurkulak] : permissions pre-implementation  permissions fix 
-
-* 10.07.2023
-
-* [milan jurkulak] : code cleanup 
-* [milan jurkulak] : lifecycle preimplementation 
-* [milan jurkulak] : net state improvements 
-* [milan jurkulak] : gui improvements 
-* [milan jurkulak] : cursor rows improvement 
-* [milan jurkulak] : columns fix for older devices 
-* [milan jurkulak] : one line text in cards 
-* [milan jurkulak] : recompose fixes  recompose fixes #2  recompose fixes #4 
-* [milan jurkulak] : recompose debugging 
-* [milan jurkulak] : custom adapter and custom rows  custom adapter and custom rows  coil more sources  scroll horizontal lists  scroll horizontal lists  scroll horizontal lists  scroll horizontal lists  details  details  details 
-
-* 07.07.2023
-
-* [milan jurkulak] : themes preimplementation 
-* [milan jurkulak] : paging preimplementation 
-* [milan jurkulak] : design improvements 
-
-* 02.07.2023
-
-* [milan jurkulak] : design improvements 
-* [milan jurkulak] : design improvements 
-* [milan jurkulak] : responsive design improvements 
-* [milan jurkulak] : contentpadding badge fix 
-* [milan jurkulak] : touch event fix 
-* [milan jurkulak] : card aspect fix 
-* [milan jurkulak] : page focus 
-* [milan jurkulak] : focusing fix, final 
-* [milan jurkulak] : carousel fix 
-* [milan jurkulak] : focusing fix 
-
-* 01.07.2023
-
-* [milan jurkulak] : gui improvements 
-* [milan jurkulak] : navigation code cleanup 
-* [milan jurkulak] : ui improvements 
-
-* 30.06.2023
-
-* [milan jurkulak] : touch handling  
-* [milan jurkulak] : navigation improvements 
-* [milan jurkulak] : ui improvements ui improvements ui improvements #1 
-* [milan jurkulak] : code cleanup 
-* [milan jurkulak] : pager preimplementation 
-* [milan jurkulak] : merge branch 'page1' into main
-
-* 29.06.2023
-
-* [milan jurkulak] : ui improvements 
-* [milan jurkulak] : code improvements 
-* [milan jurkulak] : code improvements 
-
-* 28.06.2023
-
-* [milan jurkulak] : caching fix 
-* [milan jurkulak] : pager implementation 
-* [milan jurkulak] : merge branch 'old_working' into main
-* [milan jurkulak] : previews improvement/components 
-
-* 27.06.2023
-
-* [milan jurkulak] : screens improvement 
-* [milan jurkulak] : network state fixes 
-* [milan jurkulak] : design fixes tabs  design fixes tabs 
-* [milan jurkulak] : design fixes header 
-* [milan jurkulak] : pager preimplementation 
-
-* 26.06.2023
-
-* [milan jurkulak] : repo clean 
-* [milan jurkulak] : ignore update 
-* [milan jurkulak] : ignore update 
-* [milan jurkulak] : documentation index  ignore update 
-* [milan jurkulak] : carousel touchable implementation 
-* [milan jurkulak] : code clean / icons for screens  media player fix  splash screen menu removal  delete .gradle directory delete .idea directory create security.md design improvements  git ignore items update  git ignore items update 
-* [milan] : create security.md
-* [milan] : delete .idea directory
-* [milan] : delete .gradle directory
-* [milan jurkulak] : splash screen menu removal 
-* [milan jurkulak] : media player fix 
-
-* 25.06.2023
-
-* [milan jurkulak] : code clean / icons for screens 
-* [milan jurkulak] : initial commit 

+ 2 - 0
gradle.properties

@@ -21,5 +21,7 @@ systemProp.javax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal
 kapt.use.worker.api=false
 kapt.incremental.apt=false
 android.enableJetifier=true
+android.jetifier.ignorelist=android-base-common,common
 #org.gradle.warning.mode=all
 #kotlin.experimental.tryK2=true
+ksp.useKSP2=true

+ 14 - 8
gradle/libs.versions.toml

@@ -1,6 +1,6 @@
 # versions #########################################################################################
 [versions]
-#
+####################################################################################################
 accompanist-permissions = "0.34.0"
 aescrypt = "0.0.1"
 #android-material = "1.12.0"
@@ -47,10 +47,10 @@ jsoup = "1.17.2"
 junit = "4.13.2"
 #jwtdecode = "2.0.2"
 korim-jvm = "4.0.2"
-kotlin = "2.0.0-RC3"
+kotlin = "2.0.0"
 kotlinpoet = "1.16.0"
 kotlinter-gradle = "4.3.0"
-kotlinx-coroutines-android = "1.8.0"
+kotlinx-coroutines-android = "1.8.1"
 landscapist-glide = "2.3.3"
 lottie-compose = "6.4.0"
 #
@@ -64,7 +64,7 @@ okhttp3-bom = "5.0.0-alpha.14"
 okhttp3-integration = "4.16.0"
 okhttp3-logging-interceptor = "5.0.0-alpha.14"
 org-eclipse-jgit = "4.8.0.201706111038-r"
-paparazzi-gradle-plugin = "1.3.2"
+paparazzi-gradle-plugin = "1.3.4"
 photofilter = "2.0.2"
 r8 = "8.3.37"
 retrofit2-kotlin-coroutines-adapter = "0.9.2"
@@ -75,10 +75,10 @@ kodein-di = "7.22.0"
 gradle-catalogs-update = "0.8.4"
 gradle-versions = "0.51.0"
 ktlint = "11.3.2"
-gradle-devtools-google-ksp = "2.0.0-RC3-1.0.20"
-
+gradle-devtools-google-ksp = "2.0.0-1.0.21"
 # libraries ########################################################################################
 [libraries]
+####################################################################################################
 # common
 accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist-permissions" }
 aescrypt = { module = "com.scottyab:aescrypt", version.ref = "aescrypt" }
@@ -170,7 +170,6 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
 junit = { module = "junit:junit", version.ref = "junit" }
 korim-jvm = { module = "com.soywiz.korlibs.korim:korim-jvm", version.ref = "korim-jvm" }
 kotlin-mockito = { module = "org.mockito.kotlin:mockito-kotlin", version.ref = "mockito-kotlin" }
-kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
 # kotlin
 kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" }
 # kotlinx
@@ -197,9 +196,13 @@ retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "converte
 retrofit2-kotlin-coroutines-adapter = { module = "com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter", version.ref = "retrofit2-kotlin-coroutines-adapter" }
 sandwich = { module = "com.github.skydoves:sandwich", version.ref = "sandwich" }
 sandwich-retrofit = { module = "com.github.skydoves:sandwich-retrofit", version.ref = "sandwich" }
+symbol-processing-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "gradle-devtools-google-ksp" }
+#symbol-processing-embeddable = { module = "com.google.devtools.ksp:symbol-processing-aa-embeddable", version.ref = "gradle-devtools-google-ksp" }
 timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
 zxing-core = { module = "com.google.zxing:core", version.ref = "zxing-core" }
 kotlin-compose-compiler = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" }
+kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
+kotlin-reflekt-dsl = { module = "org.jetbrains.reflekt:reflekt-dsl", version.ref = "kotlin" }
 #
 #classpath("org.jetbrains.kotlin:kotlin-scripting-jsr223:1.9.22")
 #classpath("org.jetbrains.kotlin:kotlin-scripting-common:1.9.22")
@@ -209,9 +212,9 @@ kotlin-compose-compiler = { module = "org.jetbrains.kotlin:compose-compiler-grad
 #classpath("com.bmuschko:gradle-docker-plugin:9.4.0")
 #classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1")
 #classpath("com.newrelic.agent.android:agent-gradle-plugin:5.9.0")
-
 ## plugins #########################################################################################
 [plugins]
+####################################################################################################
 android-application = { id = "com.android.application", version.ref = "gradle" }
 android-library = { id = "com.android.library", version.ref = "gradle" }
 gradle-catalogs-update = { id = "nl.littlerobots.version-catalog-update", version.ref = "gradle-catalogs-update" }
@@ -224,6 +227,9 @@ gradle-versions = { id = "com.github.ben-manes.versions", version.ref = "gradle-
 kotlin-compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
 kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
 kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
+kotlin-reflekt = { id = "org.jetbrains.reflekt", version.ref = "kotlin" }
 gradle-dokka = { id = "org.jetbrains.dokka" }
 objectbox = { id = "io.objectbox" }
 google-devtools-ksp = { id = "com.google.devtools.ksp" }
+gradle-paparazzi-plugin = { id = "app.cash.paparazzi" }
+####################################################################################################

+ 23 - 0
processor/build.gradle.kts

@@ -0,0 +1,23 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+plugins {
+    id("org.jetbrains.kotlin.jvm")
+    id("kotlin")
+}
+
+java {
+    sourceCompatibility = JavaVersion.VERSION_17
+    targetCompatibility = JavaVersion.VERSION_17
+}
+
+dependencies {
+    implementation(project(":annotations"))
+    implementation(libs.kotlin.stdlib.jdk8)
+    implementation(libs.symbol.processing.api)
+}

+ 76 - 0
processor/src/main/kotlin/org/mjdev/processor/Processor.kt

@@ -0,0 +1,76 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.processor
+
+import com.google.devtools.ksp.processing.CodeGenerator
+import com.google.devtools.ksp.processing.KSPLogger
+import com.google.devtools.ksp.processing.Resolver
+import com.google.devtools.ksp.processing.SymbolProcessor
+import com.google.devtools.ksp.symbol.KSAnnotated
+import com.google.devtools.ksp.symbol.KSFile
+import com.google.devtools.ksp.symbol.KSFunctionDeclaration
+import com.google.devtools.ksp.symbol.KSVisitorVoid
+import com.google.devtools.ksp.validate
+import org.mjdev.annotations.CreateScreenShot
+import org.mjdev.processor.base.ITestBuilder
+import org.mjdev.processor.builders.PaparazziTestBuilder
+import java.io.File
+
+@Suppress("unused")
+class Processor(
+    private val codeGenerator: CodeGenerator,
+    private val logger: KSPLogger,
+    private val options: Map<String, String>
+) : SymbolProcessor {
+
+    private val builders = mutableListOf<ITestBuilder>()
+
+    fun addBuilder(builder: ITestBuilder) {
+        builders.add(builder)
+    }
+
+    override fun process(resolver: Resolver): List<KSAnnotated> {
+        val screenshots = resolver.getSymbolsWithAnnotation(CreateScreenShot::class.qualifiedName!!)
+        if (!screenshots.iterator().hasNext()) {
+            return emptyList()
+        }
+        screenshots.forEach {
+            it.accept(ScreenShotsVisitor(), Unit)
+        }
+        val unableToProcess = screenshots.filterNot {
+            it.validate()
+        }.toList()
+        builders.forEach { builder ->
+            builder.build(codeGenerator)
+        }
+        return unableToProcess
+    }
+
+    inner class ScreenShotsVisitor : KSVisitorVoid() {
+
+        override fun visitFunctionDeclaration(function: KSFunctionDeclaration, data: Unit) {
+            val file = function.containingFile
+            if (file != null) {
+                PaparazziTestBuilder(file.projectDir).fileName(file.fileName)
+                    .packageName(file.packageName.asString()).function(function).also {
+                        addBuilder(it)
+                    }
+            }
+        }
+
+        private val KSFile.projectDir: File
+            get() = File(filePath).let {
+                var ff = it
+                while (ff.name != "src") ff = ff.parentFile
+                ff.parentFile
+            }
+
+    }
+
+}

+ 25 - 0
processor/src/main/kotlin/org/mjdev/processor/ProcessorProvider.kt

@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.processor
+
+import com.google.devtools.ksp.processing.SymbolProcessor
+import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
+import com.google.devtools.ksp.processing.SymbolProcessorProvider
+
+class ProcessorProvider : SymbolProcessorProvider {
+
+    override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
+        return Processor(
+            environment.codeGenerator,
+            environment.logger,
+            environment.options
+        )
+    }
+
+}

+ 31 - 0
processor/src/main/kotlin/org/mjdev/processor/base/ITestBuilder.kt

@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.processor.base
+
+import com.google.devtools.ksp.processing.CodeGenerator
+import java.io.File
+
+interface ITestBuilder {
+    fun build(codeGenerator: CodeGenerator)
+
+    companion object {
+        fun File.file(name: String) = File(this, name)
+
+        fun File.file(name: String, ext: String) = File(this, "$name.$ext")
+
+        fun File.fileFromPackageName(packageName: String): File {
+            val subFolders = packageName.split(".")
+            var root = this
+            for (subfolder in subFolders) {
+                root = root.file(subfolder)
+            }
+            return root
+        }
+    }
+}

+ 93 - 0
processor/src/main/kotlin/org/mjdev/processor/builders/PaparazziTestBuilder.kt

@@ -0,0 +1,93 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.processor.builders
+
+import com.google.devtools.ksp.processing.CodeGenerator
+import com.google.devtools.ksp.symbol.KSClassDeclaration
+import com.google.devtools.ksp.symbol.KSFunctionDeclaration
+import org.mjdev.processor.base.ITestBuilder
+import org.mjdev.processor.base.ITestBuilder.Companion.file
+import org.mjdev.processor.base.ITestBuilder.Companion.fileFromPackageName
+import java.io.File
+
+class PaparazziTestBuilder(
+    private val projectDir: File
+) : ITestBuilder {
+
+    private var packageName: String? = null
+    private var fileName: String? = null
+    private var fncName: String? = null
+
+    private val unitTestDir: File
+        get() = projectDir
+            .file("src")
+            .file("test")
+            .file("kotlin")
+            .fileFromPackageName(packageName ?: "")
+
+    private val normalizedFileName: String
+        get() = File(fileName!!).nameWithoutExtension + "Screenshot"
+
+    private val unitTestFile: File
+        get() = unitTestDir.file(normalizedFileName, "kt")
+
+    fun packageName(name: String?): PaparazziTestBuilder {
+        this.packageName = name
+        return this
+    }
+
+    fun fileName(name: String?): PaparazziTestBuilder {
+        this.fileName = name
+        return this
+    }
+
+    fun function(function: KSFunctionDeclaration): PaparazziTestBuilder {
+        val fncParent = function.parent
+        this.fncName = if (fncParent is KSClassDeclaration) {
+            "${fncParent.simpleName.asString()}().${function.simpleName.asString()}"
+        } else {
+            "${function.simpleName.asString()}()"
+        }
+        return this
+    }
+
+    private fun createContent(): String = StringBuilder().apply {
+        appendLine("package $packageName")
+        appendLine()
+        appendLine("import app.cash.paparazzi.Paparazzi")
+        appendLine("import org.junit.Rule")
+        appendLine("import org.junit.Test")
+        appendLine()
+        appendLine("class $normalizedFileName {")
+        appendLine("    @get:Rule")
+        appendLine("    val paparazzi = Paparazzi()")
+        appendLine()
+        appendLine("    @Test")
+        appendLine("    fun makeScreenshot() {")
+        appendLine("        try {")
+        appendLine("            paparazzi.snapshot {")
+        appendLine("                $fncName()")
+        appendLine("            }")
+        appendLine("        } catch (_: Throwable) {")
+        appendLine("        }")
+        appendLine("    }")
+        appendLine("}")
+    }.toString()
+
+    override fun build(codeGenerator: CodeGenerator) {
+        if (packageName != null && fileName != null) {
+            unitTestFile.apply {
+                parentFile.mkdirs()
+                createNewFile()
+                writeText(createContent())
+            }
+        }
+    }
+
+}

+ 9 - 0
processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider

@@ -0,0 +1,9 @@
+#
+#  Copyright (c) Milan Jurkulák 2024.
+#  Contact:
+#  e: mimoccc@gmail.com
+#  e: mj@mjdev.org
+#  w: https://mjdev.org
+#
+
+org.mjdev.processor.ProcessorProvider

+ 6 - 2
settings.gradle.kts

@@ -11,9 +11,9 @@ pluginManagement {
         google()
         mavenCentral()
         gradlePluginPortal()
-        maven(url = "https://www.jitpack.io")
         @Suppress("JcenterRepositoryObsolete", "DEPRECATION")
         jcenter()
+        maven(url = "https://www.jitpack.io")
         maven(url = "https://plugins.gradle.org/m2/")
         maven(url = "https://mvn.dailymotion.com/repository/releases/")
         maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
@@ -28,9 +28,9 @@ dependencyResolutionManagement {
         google()
         mavenCentral()
         gradlePluginPortal()
-        maven(url = "https://www.jitpack.io")
         @Suppress("JcenterRepositoryObsolete", "DEPRECATION")
         jcenter()
+        maven(url = "https://www.jitpack.io")
         maven(url = "https://plugins.gradle.org/m2/")
         maven(url = "https://mvn.dailymotion.com/repository/releases/")
         maven(url = "https://dl.bintray.com/kotlin/ktor")
@@ -38,5 +38,9 @@ dependencyResolutionManagement {
 }
 
 rootProject.name = "TvApp"
+
+include(":annotations")
+include(":processor")
+
 include(":app")
 include(":tvlib")

+ 44 - 0
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/indicators/DashedProgressIndicator.kt

@@ -0,0 +1,44 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.tvlib.ui.components.indicators
+
+import androidx.compose.foundation.Canvas
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.StrokeCap
+import androidx.compose.ui.unit.dp
+
+@Composable
+fun DashedProgressIndicator(
+    modifier: Modifier = Modifier,
+    progress: Int = 3,
+    totalNumberOfBars: Int = 10,
+    dashColor: Color = Color.LightGray,
+    strokeWidth: Float = 13f
+) = Canvas(modifier = modifier) {
+    val barArea = size.width / totalNumberOfBars
+    val barLength = barArea - 10.dp.toPx()
+    var nextBarStartPosition = 0F
+    for (i in 0..totalNumberOfBars) {
+        val barStartPosition = nextBarStartPosition + 5.dp.toPx()
+        val barEndPosition = barStartPosition + barLength
+        val start = Offset(x = barStartPosition, y = size.height / 2)
+        val end = Offset(x = barEndPosition, y = size.height / 2)
+        drawLine(
+            cap = StrokeCap.Round,
+            color = if (i < progress) dashColor else dashColor.copy(alpha = .5F),
+            start = start,
+            end = end,
+            strokeWidth = strokeWidth
+        )
+        nextBarStartPosition = barEndPosition + 5.dp.toPx()
+    }
+}