Gradle Deps Catalog, Gradle Script Cleanup, Compose, WebApp Updated

This commit is contained in:
Shabinder Singh 2021-09-30 22:46:43 +05:30
parent f403ca63f2
commit 13471d4a28
50 changed files with 725 additions and 634 deletions

View File

@ -16,7 +16,6 @@
import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import org.jetbrains.compose.compose
import org.jetbrains.kotlin.kapt.cli.main
plugins {
id("com.android.application")
@ -79,6 +78,9 @@ android {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
packagingOptions {
exclude("META-INF/*")
}
configurations {
"implementation" {
exclude(group = "androidx.compose.animation")
@ -92,7 +94,7 @@ android {
dependencies {
implementation(compose.material)
implementation(compose.materialIconsExtended)
implementation(Androidx.androidxActivity)
implementation(deps.androidx.activity)
// Project's SubModules
implementation(project(":common:database"))
@ -103,43 +105,39 @@ dependencies {
implementation(project(":common:core-components"))
implementation(project(":common:providers"))
// Koin
implementation(Koin.android)
implementation(Koin.compose)
with(deps) {
// DECOMPOSE
implementation(Decompose.decompose)
implementation(Decompose.extensionsCompose)
// Koin
with(koin) {
implementation(androidx.compose)
implementation(android)
}
// MVI
implementation(MVIKotlin.mvikotlin)
implementation(MVIKotlin.mvikotlinMain)
implementation(MVIKotlin.mvikotlinLogging)
implementation(MVIKotlin.mvikotlinTimeTravel)
// DECOMPOSE
with(decompose) {
implementation(dep)
implementation(extensions.compose)
}
// Extras
with(Extras.Android) {
implementation(countly)
implementation(appUpdator)
implementation(countly.android)
implementation(android.app.notifier)
implementation(storage.chooser)
with(bundles) {
implementation(androidx.lifecycle)
implementation(mviKotlin)
implementation(accompanist.inset)
}
// Test
testImplementation(junit)
androidTestImplementation(androidx.junit)
androidTestImplementation(androidx.expresso)
// Desugar
coreLibraryDesugaring(androidx.desugar)
// Debug
debugImplementation(leak.canary)
}
with(Versions.androidxLifecycle) {
implementation("androidx.lifecycle:lifecycle-service:$this")
implementation("androidx.lifecycle:lifecycle-common-java8:$this")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:$this")
}
implementation(Extras.kermit)
// implementation("com.jakewharton.timber:timber:4.7.1")
implementation("dev.icerock.moko:parcelize:${Versions.mokoParcelize}")
implementation("com.github.shabinder:storage-chooser:2.0.4.45")
implementation("com.google.accompanist:accompanist-insets:0.16.1")
// Test
testImplementation("junit:junit:4.13.2")
androidTestImplementation(Androidx.junit)
androidTestImplementation(Androidx.expresso)
// Desugaring
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5")
}

View File

@ -38,22 +38,32 @@ allprojects {
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>>().configureEach {
dependsOn(":common:data-models:generateI18n4kFiles")
kotlinOptions {
if(this is org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions) {
if (this is org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions) {
jvmTarget = "1.8"
}
freeCompilerArgs = (freeCompilerArgs + listOf("-Xopt-in=kotlin.RequiresOptIn"))
}
}
afterEvaluate {
project.extensions.findByType<org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension>()?.let { kmpExt ->
kmpExt.sourceSets.run {
all {
languageSettings.useExperimentalAnnotation("kotlin.RequiresOptIn")
languageSettings.useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi")
configurations.all {
resolutionStrategy {
eachDependency {
if (requested.group == "org.jetbrains.kotlin") {
@Suppress("UnstableApiUsage")
useVersion(deps.kotlin.kotlinGradlePlugin.get().versionConstraint.requiredVersion)
}
removeAll { it.name == "androidAndroidTestRelease" }
}
}
}
afterEvaluate {
project.extensions.findByType<org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension>()
?.let { kmpExt ->
kmpExt.sourceSets.run {
all {
languageSettings.useExperimentalAnnotation("kotlin.RequiresOptIn")
languageSettings.useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi")
}
removeAll { it.name == "androidAndroidTestRelease" }
}
}
}
}

View File

@ -30,17 +30,20 @@ repositories {
}
dependencies {
implementation(Androidx.gradlePlugin)
implementation(JetBrains.Compose.gradlePlugin)
implementation(JetBrains.Kotlin.gradlePlugin)
implementation(JetBrains.Kotlin.serialization)
implementation(SqlDelight.gradlePlugin)
implementation(KTLint.gradlePlugin)
implementation(Internationalization.gradlePlugin)
implementation(Mosaic.gradlePlugin)
with(deps) {
implementation(androidx.gradle.plugin)
implementation(kotlin.compose.gradle)
implementation(ktlint.gradle)
implementation(mosaic.gradle)
implementation(kotlin.kotlinGradlePlugin)
implementation(sqldelight.gradle.plugin)
implementation(i18n4k.gradle.plugin)
implementation(kotlin.serialization)
}
}
kotlin {
// Add Deps to compilation, so it will become available in main project
sourceSets.getByName("main").kotlin.srcDir("buildSrc/src/main/kotlin")
}

View File

@ -14,11 +14,15 @@
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
@file:Suppress("MayBeConstant", "SpellCheckingInspection")
@file:Suppress("MayBeConstant", "SpellCheckingInspection", "UnstableApiUsage")
import org.gradle.api.Project
import org.gradle.api.artifacts.ExternalModuleDependency
import org.gradle.api.artifacts.VersionCatalog
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.kotlin.dsl.accessors.runtime.addDependencyTo
import org.gradle.kotlin.dsl.getByType
object Versions {
// App's Version (To be bumped at each update)
@ -26,44 +30,10 @@ object Versions {
const val versionCode = 26
// Kotlin
const val kotlinVersion = "1.5.21"
const val coroutinesVersion = "1.5.1"
// Code Formatting
const val ktLint = "10.1.0"
// Console-App UI
const val mosaic = "0.1.0"
// DI
const val koin = "3.1.2"
// Logger
const val kermit = "0.1.9"
const val mokoParcelize = "0.7.1"
// Internet
const val ktor = "1.6.2"
const val kotlinxSerialization = "1.2.2"
// Database
const val sqlDelight = "1.5.1"
const val sqliteJdbcDriver = "3.34.0"
const val slf4j = "1.7.31"
// Internationalisation
const val i18n4k = "0.1.3"
// Android
const val minSdkVersion = 21
const val compileSdkVersion = 30
const val compileSdkVersion = 31
const val targetSdkVersion = 29
const val androidxLifecycle = "2.4.0-alpha03"
}
object HostOS {
@ -74,143 +44,46 @@ object HostOS {
val isLinux = hostOs.startsWith("Linux", true)
}
object MultiPlatformSettings {
const val dep = "com.russhwolf:multiplatform-settings-no-arg:0.7.7"
}
val Project.Deps: VersionCatalog get() = project.extensions.getByType<VersionCatalogsExtension>().named("deps")
object KotlinJSWrappers {
private const val bomVersion = "0.0.1-pre.235-kotlin-1.5.21"
val bom = "org.jetbrains.kotlin-wrappers:kotlin-wrappers-bom:${bomVersion}"
const val kotlinReact = "org.jetbrains.kotlin-wrappers:kotlin-react"
const val kotlinReactDom = "org.jetbrains.kotlin-wrappers:kotlin-react-dom"
const val kotlinStyled = "org.jetbrains.kotlin-wrappers:kotlin-styled"
}
val VersionCatalog.ktorBundle get() = findBundle("ktor").get()
val VersionCatalog.statelyBundle get() = findBundle("stately").get()
val VersionCatalog.androidXLifecycleBundle get() = findBundle("androidx-lifecycle").get()
val VersionCatalog.androidXCommonBundle get() = findBundle("androidx-common").get()
val VersionCatalog.kotlinTestBundle get() = findBundle("kotlin-test").get()
val VersionCatalog.sqldelightBundle get() = findBundle("sqldelight").get()
val VersionCatalog.mviKotlinBundle get() = findBundle("mviKotlin").get()
val VersionCatalog.essentyBundle get() = findBundle("essenty").get()
val VersionCatalog.koinAndroidBundle get() = findBundle("koin-android").get()
val VersionCatalog.kotlinJSWrappers get() = findBundle("kotlin-js-wrappers").get()
object Koin {
val core = "io.insert-koin:koin-core:${Versions.koin}"
val test = "io.insert-koin:koin-test:${Versions.koin}"
val android = "io.insert-koin:koin-android:${Versions.koin}"
val compose = "io.insert-koin:koin-androidx-compose:${Versions.koin}"
}
val VersionCatalog.kotlinJunitTest get() = findDependency("kotlin-kotlinTestJunit").get()
val VersionCatalog.kotlinJSTest get() = findDependency("kotlin-kotlinTestJs").get()
val VersionCatalog.kermit get() = findDependency("kermit").get()
val VersionCatalog.decompose get() = findDependency("decompose-dep").get()
val VersionCatalog.decomposeComposeExt get() = findDependency("decompose-extensions-compose").get()
val VersionCatalog.jaffree get() = findDependency("jaffree").get()
object Androidx {
const val androidxActivity = "androidx.activity:activity-compose:1.3.1"
const val core = "androidx.core:core-ktx:1.6.0"
const val palette = "androidx.palette:palette-ktx:1.0.0"
const val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.coroutinesVersion}"
val VersionCatalog.ktlintGradle get() = findDependency("ktlint-gradle").get()
val VersionCatalog.androidGradle get() = findDependency("androidx-gradle-plugin").get()
val VersionCatalog.mosaicGradle get() = findDependency("mosaic-gradle").get()
val VersionCatalog.kotlinComposeGradle get() = findDependency("kotlin-compose-gradle").get()
val VersionCatalog.kotlinGradle get() = findDependency("kotlin-kotlinGradlePlugin").get()
val VersionCatalog.i18n4kGradle get() = findDependency("i18n4k-gradle-plugin").get()
val VersionCatalog.sqlDelightGradle get() = findDependency("sqldelight-gradle-plugin").get()
val VersionCatalog.kotlinSerializationPlugin get() = findDependency("kotlin-serialization").get()
const val junit = "androidx.test.ext:junit:1.1.2"
const val expresso = "androidx.test.espresso:espresso-core:3.3.0"
val VersionCatalog.koinCore get() = findDependency("koin-core").get()
val VersionCatalog.kotlinCoroutines get() = findDependency("kotlin-coroutines").get()
val VersionCatalog.kotlinxSerialization get() = findDependency("kotlinx-serialization-json").get()
val VersionCatalog.ktorClientIOS get() = findDependency("ktor-client-ios").get()
val VersionCatalog.ktorClientAndroid get() = findDependency("ktor-client-android").get()
val VersionCatalog.ktorClientApache get() = findDependency("ktor-client-apache").get()
val VersionCatalog.ktorClientJS get() = findDependency("ktor-client-js").get()
val VersionCatalog.ktorClientCIO get() = findDependency("ktor-client-cio").get()
val VersionCatalog.slf4j get() = findDependency("slf4j-simple").get()
const val gradlePlugin = "com.android.tools.build:gradle:7.0.1"
}
object KTLint {
const val gradlePlugin = "org.jlleitschuh.gradle:ktlint-gradle:${Versions.ktLint}"
}
object JetBrains {
object Kotlin {
const val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1-native-mt"
const val gradlePlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlinVersion}"
const val serialization = "org.jetbrains.kotlin:kotlin-serialization:${Versions.kotlinVersion}"
const val testCommon = "org.jetbrains.kotlin:kotlin-test-common:${Versions.kotlinVersion}"
const val testJunit = "org.jetbrains.kotlin:kotlin-test-junit:${Versions.kotlinVersion}"
const val testAnnotationsCommon =
"org.jetbrains.kotlin:kotlin-test-annotations-common:${Versions.kotlinVersion}"
}
object Compose {
// __LATEST_COMPOSE_RELEASE_VERSION__
private const val VERSION = "1.0.0-alpha3"
const val gradlePlugin = "org.jetbrains.compose:compose-gradle-plugin:$VERSION"
}
}
object Mosaic {
const val gradlePlugin = "com.jakewharton.mosaic:mosaic-gradle-plugin:${Versions.mosaic}"
}
object Decompose {
private const val VERSION = "0.3.1"
const val decompose = "com.arkivanov.decompose:decompose:$VERSION"
const val decomposeIosX64 = "com.arkivanov.decompose:decompose-iosx64:$VERSION"
const val decomposeIosArm64 = "com.arkivanov.decompose:decompose-iosarm64:$VERSION"
const val extensionsCompose = "com.arkivanov.decompose:extensions-compose-jetbrains:$VERSION"
}
object MVIKotlin {
private const val VERSION = "2.0.4"
const val rx = "com.arkivanov.mvikotlin:rx:$VERSION"
const val mvikotlin = "com.arkivanov.mvikotlin:mvikotlin:$VERSION"
const val mvikotlinMain = "com.arkivanov.mvikotlin:mvikotlin-main:$VERSION"
const val coroutines = "com.arkivanov.mvikotlin:mvikotlin-extensions-coroutines:$VERSION"
const val keepers = "com.arkivanov.mvikotlin:keepers:$VERSION"
const val mvikotlinMainIosX64 = "com.arkivanov.mvikotlin:mvikotlin-main-iosx64:$VERSION"
const val mvikotlinMainIosArm64 = "com.arkivanov.mvikotlin:mvikotlin-main-iosarm64:$VERSION"
const val mvikotlinLogging = "com.arkivanov.mvikotlin:mvikotlin-logging:$VERSION"
const val mvikotlinTimeTravel = "com.arkivanov.mvikotlin:mvikotlin-timetravel:$VERSION"
const val mvikotlinExtensionsReaktive = "com.arkivanov.mvikotlin:mvikotlin-extensions-reaktive:$VERSION"
}
object Ktor {
val clientCore = "io.ktor:ktor-client-core:${Versions.ktor}"
val clientJson = "io.ktor:ktor-client-json:${Versions.ktor}"
val clientLogging = "io.ktor:ktor-client-logging:${Versions.ktor}"
val clientSerialization = "io.ktor:ktor-client-serialization:${Versions.ktor}"
val auth = "io.ktor:ktor-client-auth:${Versions.ktor}"
val clientAndroid = "io.ktor:ktor-client-android:${Versions.ktor}"
val clientCurl = "io.ktor:ktor-client-curl:${Versions.ktor}"
val clientApache = "io.ktor:ktor-client-apache:${Versions.ktor}"
val slf4j = "org.slf4j:slf4j-simple:${Versions.slf4j}"
val clientIos = "io.ktor:ktor-client-ios:${Versions.ktor}"
val clientCio = "io.ktor:ktor-client-cio:${Versions.ktor}"
val clientJs = "io.ktor:ktor-client-js:${Versions.ktor}"
}
object Internationalization {
const val dep = "de.comahe.i18n4k:i18n4k-core:${Versions.i18n4k}"
const val gradlePlugin = "de.comahe.i18n4k:i18n4k-gradle-plugin:${Versions.i18n4k}"
}
object Extras {
const val youtubeDownloader = "io.github.shabinder:youtube-api-dl:1.3"
const val fuzzyWuzzy = "io.github.shabinder:fuzzywuzzy:1.1"
const val mp3agic = "com.mpatric:mp3agic:0.9.0"
const val jaudioTagger = "com.github.Shabinder:JAudioTagger-Android:1.0"
const val kermit = "co.touchlab:kermit:${Versions.kermit}"
object Android {
// Self Hosted Analytics & Crashlytics (FOSS)
val countly = "ly.count.android:sdk:20.11.8"
val appUpdator = "com.github.amitbd1508:AppUpdater:4.1.0"
}
object Desktop {
val countly = "ly.count.sdk:java:20.11.0"
}
}
object Serialization {
val json = "org.jetbrains.kotlinx:kotlinx-serialization-json:${Versions.kotlinxSerialization}"
}
object SqlDelight {
val runtime = "com.squareup.sqldelight:runtime:${Versions.sqlDelight}"
val coroutineExtensions = "com.squareup.sqldelight:coroutines-extensions:${Versions.sqlDelight}"
const val gradlePlugin = "com.squareup.sqldelight:gradle-plugin:${Versions.sqlDelight}"
const val androidDriver = "com.squareup.sqldelight:android-driver:${Versions.sqlDelight}"
const val sqliteDriver = "com.squareup.sqldelight:sqlite-driver:${Versions.sqlDelight}"
const val nativeDriver = "com.squareup.sqldelight:native-driver:${Versions.sqlDelight}"
val nativeDriverMacos = "com.squareup.sqldelight:native-driver-macosx64:${Versions.sqlDelight}"
val jdbcDriver = "org.xerial:sqlite-jdbc:${Versions.sqliteJdbcDriver}"
}
fun DependencyHandler.`implementation`(
dependencyNotation: String,
dependencyConfiguration: ExternalModuleDependency.() -> Unit
): ExternalModuleDependency = addDependencyTo(
this, "implementation", dependencyNotation
) { dependencyConfiguration() }
val VersionCatalog.sqlDelightJDBC get() = findDependency("sqlite-jdbc-driver").get()
val VersionCatalog.sqlDelightNative get() = findDependency("sqldelight-native-driver").get()
val VersionCatalog.sqlDelightAndroid get() = findDependency("sqldelight-android-driver").get()
val VersionCatalog.sqlDelightDriver get() = findDependency("sqldelight-driver").get()

135
buildSrc/deps.versions.toml Normal file
View File

@ -0,0 +1,135 @@
[versions]
kotlin = "1.5.31"
androidCoroutines = "1.5.1"
ktLint = "10.1.0"
mosaic = "0.1.0"
koin = "3.1.2"
kermit = "0.1.9"
mokoParcelize = "0.7.1"
ktor = "1.6.3"
kotlinxSerialization = "1.2.2"
sqlDelight = "1.5.1"
sqliteJdbcDriver = "3.34.0"
slf4j = "1.7.31"
i18n4k = "0.1.3"
essenty = "0.1.3"
multiplatformSettings = "0.7.7"
decompose = "0.3.1"
mviKotlin = "2.0.4"
accompanist = "0.18.0"
statelyVersion = "1.1.10"
statelyIsoVersion = "1.2.0-nmm"
androidxLifecycle = "2.4.0-alpha03"
[libraries]
kotlin-kotlinGradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
kotlin-serialization = { group = "org.jetbrains.kotlin", name = "kotlin-serialization", version.ref = "kotlin" }
kotlin-kotlinTestCommon = { group = "org.jetbrains.kotlin", name = "kotlin-test-common", version.ref = "kotlin" }
kotlin-kotlinTestJs = { group = "org.jetbrains.kotlin", name = "kotlin-test-js", version.ref = "kotlin" }
kotlin-kotlinTestJunit = { group = "org.jetbrains.kotlin", name = "kotlin-test-junit", version.ref = "kotlin" }
kotlin-kotlinTestAnnotationsCommon = { group = "org.jetbrains.kotlin", name = "kotlin-test-annotations-common", version.ref = "kotlin" }
kotlin-coroutines = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version = "1.5.2-native-mt" }
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerialization" }
kotlinx-atomicfu = { group = "org.jetbrains.kotlinx", name = "atomicfu", version = "0.16.3" }
kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version = "0.2.1" }
kotlin-compose-gradle = { group = "org.jetbrains.compose", name = "compose-gradle-plugin", version = "1.0.0-alpha4-build366" }
mosaic-gradle = { group = "com.jakewharton.mosaic", name = "mosaic-gradle-plugin", version.ref = "mosaic" }
essenty-lifecycle = { group = "com.arkivanov.essenty", name = "lifecycle", version.ref = "essenty" }
essenty-instanceKeeper = { group = "com.arkivanov.essenty", name = "instance-keeper", version.ref = "essenty" }
decompose-dep = { group = "com.arkivanov.decompose", name = "decompose", version.ref = "decompose" }
decompose-extensions-compose = { group = "com.arkivanov.decompose", name = "extensions-compose-jetbrains", version.ref = "decompose" }
mviKotlin-dep = { group = "com.arkivanov.mvikotlin", name = "mvikotlin", version.ref = "mviKotlin" }
mviKotlin-rx = { group = "com.arkivanov.mvikotlin", name = "rx", version.ref = "mviKotlin" }
mviKotlin-main = { group = "com.arkivanov.mvikotlin", name = "mvikotlin-main", version.ref = "mviKotlin" }
mviKotlin-coroutines = { group = "com.arkivanov.mvikotlin", name = "mvikotlin-extensions-coroutines", version.ref = "mviKotlin" }
mviKotlin-keepers = { group = "com.arkivanov.mvikotlin", name = "keepers", version.ref = "mviKotlin" }
mviKotlin-logging = { group = "com.arkivanov.mvikotlin", name = "mvikotlin-logging", version.ref = "mviKotlin" }
mviKotlin-timetravel = { group = "com.arkivanov.mvikotlin", name = "mvikotlin-timetravel", version.ref = "mviKotlin" }
mviKotlin-extensions-reaktive = { group = "com.arkivanov.mvikotlin", name = "mvikotlin-extensions-reaktive", version.ref = "mviKotlin" }
ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" }
ktor-client-json = { group = "io.ktor", name = "ktor-client-json", version.ref = "ktor" }
ktor-client-logging = { group = "io.ktor", name = "ktor-client-logging", version.ref = "ktor" }
ktor-client-serialization = { group = "io.ktor", name = "ktor-client-serialization", version.ref = "ktor" }
ktor-client-auth = { group = "io.ktor", name = "ktor-client-auth", version.ref = "ktor" }
ktor-client-android = { group = "io.ktor", name = "ktor-client-android", version.ref = "ktor" }
ktor-client-curl = { group = "io.ktor", name = "ktor-client-curl", version.ref = "ktor" }
ktor-client-apache = { group = "io.ktor", name = "ktor-client-apache", version.ref = "ktor" }
ktor-client-ios = { group = "io.ktor", name = "ktor-client-ios", version.ref = "ktor" }
ktor-client-cio = { group = "io.ktor", name = "ktor-client-cio", version.ref = "ktor" }
ktor-client-js = { group = "io.ktor", name = "ktor-client-js", version.ref = "ktor" }
slf4j-simple = { group = "org.slf4j", name = "slf4j-simple", version.ref = "slf4j" }
i18n4k-core = { group = "de.comahe.i18n4k", name = "i18n4k-core", version.ref = "i18n4k" }
i18n4k-gradle-plugin = { group = "de.comahe.i18n4k", name = "i18n4k-gradle-plugin", version.ref = "i18n4k" }
youtube-downloader = { group = "io.github.shabinder", name = "youtube-api-dl", version = "1.3" }
fuzzy-wuzzy = { group = "io.github.shabinder", name = "fuzzywuzzy", version = "1.1" }
mp3agic = { group = "com.mpatric", name = "mp3agic", version = "0.9.0" }
kermit = { group = "co.touchlab", name = "kermit", version.ref = "kermit" }
storage-chooser = { group = "com.github.shabinder", name = "storage-chooser", version = "2.0.4.45" }
accompanist-inset = { group = "com.google.accompanist", name = "accompanist-insets", version.ref = "accompanist" }
android-app-notifier = { group = "com.github.amitbd1508", name = "AppUpdater", version = "4.1.0" }
moko-parcelize = { group = "dev.icerock.moko", name = "parcelize", version.ref = "mokoParcelize" }
jaffree = { group = "com.github.kokorin.jaffree", name = "jaffree", version = "2021.08.16" }
multiplatform-settings = { group = "com.russhwolf", name = "multiplatform-settings-no-arg", version.ref = "multiplatformSettings" }
countly-android = { group = "ly.count.android", name = "sdk", version = "20.11.8" }
countly-desktop = { group = "ly.count.sdk", name = "java", version = "20.11.0" }
stately-common = { group = "co.touchlab", name = "stately-common", version.ref = "statelyVersion" }
stately-concurrency = { group = "co.touchlab", name = "stately-concurrency", version.ref = "statelyVersion" }
stately-isolate = { group = "co.touchlab", name = "stately-isolate", version.ref = "statelyIsoVersion" }
stately-iso-collections = { group = "co.touchlab", name = "stately-iso-collections", version.ref = "statelyIsoVersion" }
sqldelight-runtime = { group = "com.squareup.sqldelight", name = "runtime", version.ref = "sqlDelight" }
sqldelight-coroutines-extension = { group = "com.squareup.sqldelight", name = "coroutines-extensions", version.ref = "sqlDelight" }
sqldelight-gradle-plugin = { group = "com.squareup.sqldelight", name = "gradle-plugin", version.ref = "sqlDelight" }
sqldelight-driver = { group = "com.squareup.sqldelight", name = "sqlite-driver", version.ref = "sqlDelight" }
sqldelight-android-driver = { group = "com.squareup.sqldelight", name = "android-driver", version.ref = "sqlDelight" }
sqldelight-native-driver = { group = "com.squareup.sqldelight", name = "native-driver", version.ref = "sqlDelight" }
sqlite-jdbc-driver = { group = "org.xerial", name = "sqlite-jdbc", version.ref = "sqliteJdbcDriver" }
koin-core = { group = "io.insert-koin", name = "koin-core", version.ref = "koin" }
koin-test = { group = "io.insert-koin", name = "koin-test", version.ref = "koin" }
koin-android = { group = "io.insert-koin", name = "koin-android", version.ref = "koin" }
koin-androidx-compose = { group = "io.insert-koin", name = "koin-androidx-compose", version.ref = "koin" }
kotlin-js-wrappers-react = { group = "org.jetbrains.kotlin-wrappers", name = "kotlin-react", version = "17.0.2-pre.251-kotlin-1.5.31" }
kotlin-js-wrappers-reactDom = { group = "org.jetbrains.kotlin-wrappers", name = "kotlin-react-dom", version = "17.0.2-pre.251-kotlin-1.5.31" }
kotlin-js-wrappers-styled = { group = "org.jetbrains.kotlin-wrappers", name = "kotlin-styled", version = "5.3.1-pre.250-kotlin-1.5.31" }
kotlin-js-wrappers-ext = { group = "org.jetbrains.kotlin-wrappers", name = "kotlin-extensions", version = "1.0.1-pre.251-kotlin-1.5.31" }
androidx-activity = { group = "androidx.activity", name = "activity-compose", version = "1.3.1" }
androidx-core = { group = "androidx.core", name = "core-ktx", version = "1.6.0" }
androidx-palette = { group = "androidx.palette", name = "palette-ktx", version = "1.0.0" }
androidx-coroutines = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "androidCoroutines" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version = "1.1.2" }
androidx-expresso = { group = "androidx.test.espresso", name = "espresso-core", version = "3.3.0" }
androidx-gradle-plugin = { group = "com.android.tools.build", name = "gradle", version = "4.2.2" }
androidx-lifecycle-service = { group = "androidx.lifecycle", name = "lifecycle-service", version.ref = "androidxLifecycle" }
androidx-lifecycle-common = { group = "androidx.lifecycle", name = "lifecycle-common-java8", version.ref = "androidxLifecycle" }
androidx-lifecycle-runtime = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "androidxLifecycle" }
androidx-desugar = { group = "com.android.tools", name = "desugar_jdk_libs", version = "1.1.5" }
leak-canary = { group = "com.squareup.leakcanary", name = "leakcanary-android", version = "2.7" }
junit = { group = "junit", name = "junit", version = "4.13.2" }
ktlint-gradle = { group = "org.jlleitschuh.gradle", name = "ktlint-gradle", version.ref = "ktLint" }
[bundles]
ktor = ["ktor-client-core","ktor-client-json","ktor-client-auth","ktor-client-logging","ktor-client-serialization"]
stately = ["stately-common","stately-concurrency","stately-isolate","stately-iso-collections"]
androidx-lifecycle = ["androidx-lifecycle-service","androidx-lifecycle-common","androidx-lifecycle-runtime"]
androidx-common = ["androidx-activity","androidx-core"]
kotlin-test = ["kotlin-kotlinTestCommon","kotlin-kotlinTestAnnotationsCommon"]
sqldelight = ["sqldelight-runtime","sqldelight-coroutines-extension","sqldelight-driver"]
mviKotlin = ["mviKotlin-dep","mviKotlin-main","mviKotlin-coroutines","mviKotlin-logging","mviKotlin-timetravel"]
kotlinCommon = ["kotlin-coroutines", "kotlin-serialization", "kotlinx-serialization-json", "kotlinx-atomicfu"]
essenty = ["essenty-lifecycle","essenty-instanceKeeper"]
koin-android = ["koin-androidx-compose","koin-android"]
kotlin-js-wrappers = ["kotlin-js-wrappers-react","kotlin-js-wrappers-reactDom","kotlin-js-wrappers-styled","kotlin-js-wrappers-ext"]

View File

@ -0,0 +1,12 @@
enableFeaturePreview("VERSION_CATALOGS")
dependencyResolutionManagement {
@Suppress("UnstableApiUsage")
versionCatalogs {
create("deps") {
from(files("deps.versions.toml"))
}
}
}
rootProject.name = "spotiflyer-build"

View File

@ -6,10 +6,10 @@ kotlin {
sourceSets {
all {
languageSettings.apply {
useExperimentalAnnotation("kotlin.RequiresOptIn")
useExperimentalAnnotation("kotlin.Experimental")
useExperimentalAnnotation("kotlin.time.ExperimentalTime")
useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi")
optIn("kotlin.RequiresOptIn")
optIn("kotlin.Experimental")
optIn("kotlin.time.ExperimentalTime")
optIn("kotlinx.serialization.ExperimentalSerializationApi")
}
}
}

View File

@ -29,36 +29,23 @@ kotlin {
sourceSets {
all {
languageSettings.apply {
useExperimentalAnnotation("androidx.compose.animation")
optIn("androidx.compose.animation")
}
}
named("commonMain") {
dependencies {
// Decompose
implementation(Decompose.decompose)
// MVI
implementation(MVIKotlin.coroutines)
implementation(MVIKotlin.mvikotlin)
implementation(compose.ui)
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material)
implementation(compose.animation)
implementation(Extras.kermit)
implementation("dev.icerock.moko:parcelize:${Versions.mokoParcelize}")
implementation(JetBrains.Kotlin.coroutines) {
@Suppress("DEPRECATION")
isForce = true
}
implementation(Deps.kotlinCoroutines)
implementation(Deps.decompose)
}
}
named("androidMain") {
dependencies {
implementation(Androidx.androidxActivity)
implementation(Androidx.core)
implementation(Deps.androidXCommonBundle)
}
}
named("desktopMain") {

View File

@ -42,23 +42,24 @@ kotlin {
sourceSets {
named("commonTest") {
dependencies {
implementation(JetBrains.Kotlin.testCommon)
implementation(JetBrains.Kotlin.testAnnotationsCommon)
implementation(Deps.kotlinTestBundle)
}
}
named("androidTest") {
dependencies {
implementation(JetBrains.Kotlin.testJunit)
implementation(Deps.kotlinJunitTest)
}
}
named("desktopTest") {
dependencies {
implementation(JetBrains.Kotlin.testJunit)
implementation(Deps.kotlinJunitTest)
}
}
named("jsTest") {
dependencies {}
dependencies {
implementation(Deps.kotlinJSTest)
}
}
}
}

View File

@ -25,7 +25,7 @@ plugins {
kotlin {
/*IOS Target Can be only built on Mac*/
if(HostOS.isMac){
if (HostOS.isMac) {
val sdkName: String? = System.getenv("SDK_NAME")
val isiOSDevice = sdkName.orEmpty().startsWith("iphoneos")
if (isiOSDevice) {
@ -50,45 +50,25 @@ kotlin {
sourceSets {
named("commonMain") {
dependencies {
// Decompose
implementation(Decompose.decompose)
// MVI
implementation(MVIKotlin.coroutines)
implementation(MVIKotlin.mvikotlin)
// Koin
implementation(Koin.core)
implementation(Ktor.auth)
implementation(Ktor.clientJson)
implementation(Ktor.clientCore)
implementation(Ktor.clientLogging)
implementation(Ktor.clientSerialization)
// Extras
implementation(Extras.kermit)
implementation(Serialization.json)
implementation("co.touchlab:stately-common:1.1.7")
implementation("dev.icerock.moko:parcelize:${Versions.mokoParcelize}")
implementation(JetBrains.Kotlin.coroutines) {
@Suppress("DEPRECATION")
isForce = true
}
implementation(Deps.ktorBundle)
implementation(Deps.kotlinxSerialization)
implementation(Deps.kotlinCoroutines)
implementation(Deps.mviKotlinBundle)
implementation(Deps.decompose)
implementation(Deps.koinCore)
}
}
named("androidMain") {
dependencies {
implementation(Androidx.androidxActivity)
implementation(Androidx.core)
implementation(compose.runtime)
implementation(compose.material)
implementation(compose.foundation)
implementation(compose.materialIconsExtended)
implementation(Decompose.extensionsCompose)
implementation(Ktor.clientAndroid)
implementation(Koin.android)
implementation(Deps.androidXCommonBundle)
implementation(Deps.decomposeComposeExt)
implementation(Deps.ktorClientAndroid)
implementation(Deps.koinAndroidBundle)
}
}
@ -99,27 +79,20 @@ kotlin {
implementation(compose.material)
implementation(compose.desktop.common)
implementation(compose.materialIconsExtended)
implementation(Decompose.extensionsCompose)
implementation(Ktor.clientApache)
implementation(Ktor.slf4j)
implementation(Deps.decomposeComposeExt)
implementation(Deps.ktorClientApache)
implementation(Deps.slf4j)
}
}
named("jsMain") {
dependencies {
implementation(Ktor.clientJs)
/*with(KotlinJSWrappers) {
implementation(enforcedPlatform(bom))
implementation(kotlinReact)
implementation(kotlinReactDom)
implementation(kotlinStyled)
}*/
implementation(Deps.ktorClientJS)
}
}
if(HostOS.isMac){
named("iosMain"){
if (HostOS.isMac) {
named("iosMain") {
dependencies {
implementation(Ktor.clientIos)
implementation(Deps.ktorClientIOS)
}
}
}

View File

@ -40,7 +40,7 @@ kotlin {
implementation(project(":common:database"))
implementation(project(":common:data-models"))
implementation(project(":common:dependency-injection"))
implementation(Decompose.extensionsCompose)
implementation(deps.decompose.extensions.compose)
}
}
}

View File

@ -21,15 +21,19 @@ package com.shabinder.common.uikit
import androidx.compose.foundation.Image
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.loadXmlImageVector
import androidx.compose.ui.res.vectorXmlResource
import androidx.compose.ui.res.useResource
import org.xml.sax.InputSource
@Composable
internal actual fun <T> imageVectorResource(id: T): ImageVector =
vectorXmlResource(id as String)
internal actual fun <T> imageVectorResource(id: T): ImageVector {
val density = LocalDensity.current
return useResource(id as String) {
loadXmlImageVector(InputSource(it), density)
}
}
@Composable
actual fun DownloadImageTick() {

View File

@ -12,7 +12,7 @@ import androidx.compose.ui.unit.dp
actual val MARGIN_SCROLLBAR: Dp = 8.dp
actual typealias ScrollbarAdapter = androidx.compose.foundation.ScrollbarAdapter
actual typealias ScrollbarAdapter = ScrollbarAdapter
@OptIn(ExperimentalFoundationApi::class)
@Composable
@ -23,8 +23,6 @@ actual fun rememberScrollbarAdapter(
): ScrollbarAdapter =
androidx.compose.foundation.rememberScrollbarAdapter(
scrollState = scrollState,
itemCount = itemCount,
averageItemSize = averageItemSize
)
@Composable

View File

@ -10,29 +10,37 @@ kotlin {
dependencies {
implementation(project(":common:data-models"))
implementation(project(":common:database"))
api("org.jetbrains.kotlinx:atomicfu:0.16.2")
api(MultiPlatformSettings.dep)
implementation(MVIKotlin.rx)
with(deps) {
api(multiplatform.settings)
api(kotlinx.atomicfu)
implementation(mviKotlin.rx)
implementation(decompose.dep)
}
}
}
androidMain {
dependencies {
implementation(Extras.mp3agic)
implementation(Extras.Android.countly)
with(deps) {
implementation(mp3agic)
implementation(countly.android)
}
implementation(project(":ffmpeg:android-ffmpeg"))
}
}
desktopMain {
dependencies {
implementation(Extras.mp3agic)
implementation(Extras.Desktop.countly)
implementation("com.github.kokorin.jaffree:jaffree:2021.08.16")
with(deps) {
implementation(mp3agic)
implementation(countly.desktop)
implementation(jaffree)
}
}
}
jsMain {
dependencies {
implementation(npm("browser-id3-writer", "4.4.0"))
implementation(npm("file-saver", "2.0.4"))
implementation(deps.kotlin.js.wrappers.ext)
}
}
}

View File

@ -30,17 +30,20 @@ import com.shabinder.common.core_components.removeAllTags
import com.shabinder.common.core_components.setId3v1Tags
import com.shabinder.common.core_components.setId3v2TagsAndSaveFile
import com.shabinder.common.database.SpotiFlyerDatabase
import com.shabinder.common.models.Actions
import com.shabinder.common.models.DownloadStatus
import com.shabinder.common.models.TrackDetails
import com.shabinder.common.models.dispatcherIO
import com.shabinder.common.models.event.coroutines.SuspendableEvent
import com.shabinder.common.models.event.coroutines.failure
import com.shabinder.common.models.event.coroutines.map
import com.shabinder.common.models.Actions
import com.shabinder.database.Database
import kotlinx.coroutines.*
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.MutableSharedFlow
import org.jetbrains.skija.Image
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jetbrains.skia.Image
import org.koin.dsl.bind
import org.koin.dsl.module
import java.awt.image.BufferedImage
@ -165,7 +168,7 @@ class DesktopFileManager(
}
SuspendableEvent.success(trackDetails.outputFilePath)
} catch (e: Throwable) {
if(e is JaffreeException) Actions.instance.showPopUpMessage("No FFmpeg found at path.")
if (e is JaffreeException) Actions.instance.showPopUpMessage("No FFmpeg found at path.")
if (songFile.exists()) songFile.delete()
logger.e { "${songFile.absolutePath} could not be created" }
SuspendableEvent.error(e)

View File

@ -25,9 +25,6 @@ plugins {
id("de.comahe.i18n4k")
}
val statelyVersion = "1.1.7"
val statelyIsoVersion = "1.1.7-a1"
i18n4k {
inputDirectory = "../../translations"
packageName = "com.shabinder.common.translations"
@ -50,11 +47,13 @@ kotlin {
}
commonMain {
dependencies {
api("co.touchlab:stately-concurrency:$statelyVersion")
api("co.touchlab:stately-isolate:$statelyIsoVersion")
api("co.touchlab:stately-iso-collections:$statelyIsoVersion")
implementation(Extras.youtubeDownloader)
api(Internationalization.dep)
with(deps) {
api(bundles.stately)
api(i18n4k.core)
api(kermit)
api(moko.parcelize)
implementation(youtube.downloader)
}
}
}
}

View File

@ -34,31 +34,32 @@ kotlin {
implementation(project(":common:data-models"))
// SQL Delight
implementation(SqlDelight.runtime)
implementation(SqlDelight.coroutineExtensions)
// koin
implementation(Koin.test)
with(deps.sqldelight) {
implementation(runtime)
api(coroutines.extension)
}
}
}
androidMain {
dependencies {
implementation(SqlDelight.androidDriver)
implementation(deps.sqldelight.android.driver)
}
}
desktopMain {
dependencies {
implementation(SqlDelight.sqliteDriver)
implementation(SqlDelight.jdbcDriver)
with(deps) {
implementation(sqldelight.driver)
implementation(sqlite.jdbc.driver)
}
}
}
if (HostOS.isMac) {
val iosMain by getting {
dependencies {
implementation(SqlDelight.nativeDriver)
implementation(deps.sqldelight.native.driver)
}
}
}

View File

@ -14,8 +14,6 @@
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import org.jetbrains.compose.compose
plugins {
id("android-setup")
id("multiplatform-setup")

View File

@ -30,7 +30,6 @@ kotlin {
implementation(project(":common:database"))
implementation(project(":common:providers"))
implementation(project(":common:core-components"))
implementation(SqlDelight.coroutineExtensions)
}
}
}

View File

@ -30,7 +30,6 @@ kotlin {
implementation(project(":common:database"))
implementation(project(":common:providers"))
implementation(project(":common:core-components"))
implementation(SqlDelight.coroutineExtensions)
}
}
}

View File

@ -30,7 +30,6 @@ kotlin {
implementation(project(":common:database"))
implementation(project(":common:core-components"))
implementation(project(":common:providers"))
implementation(SqlDelight.coroutineExtensions)
}
}
}

View File

@ -12,23 +12,25 @@ kotlin {
sourceSets {
commonMain {
dependencies {
implementation(project(":common:data-models"))
implementation(project(":common:database"))
implementation(project(":common:core-components"))
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.2.1")
implementation(Extras.youtubeDownloader)
implementation(Extras.fuzzyWuzzy)
with(deps) {
implementation(project(":common:data-models"))
implementation(project(":common:database"))
implementation(project(":common:core-components"))
implementation(youtube.downloader)
implementation(fuzzy.wuzzy)
implementation(kotlinx.datetime)
}
}
}
androidMain {
dependencies {
implementation(Extras.mp3agic)
implementation(deps.mp3agic)
}
}
desktopMain {
dependencies {
implementation(Extras.mp3agic)
implementation("com.github.kokorin.jaffree:jaffree:2021.08.16")
implementation(deps.mp3agic)
implementation(deps.jaffree)
}
}
jsMain {

View File

@ -32,7 +32,7 @@ interface SoundCloudRequests {
}
@Suppress("NAME_SHADOWING")
suspend fun getTrack(track: JsonObject): TrackDetails {
suspend fun getTrack(track: JsonObject): TrackDetails? {
val track = getTrackInfo(track)
val title = track.getString("title")
@ -42,7 +42,7 @@ interface SoundCloudRequests {
if (track.getBoolean("streamable") == false)
throw SpotiFlyerException.LinkInvalid("\nSound Cloud Reports that $title is not streamable !\n")
return null
}

View File

@ -33,9 +33,10 @@ fun org.jetbrains.kotlin.gradle.dsl.KotlinNativeBinaryContainer.generateFramewor
export(project(":common:providers"))
export(project(":common:list"))
export(project(":common:preference"))
export(Decompose.decompose)
export(MVIKotlin.mvikotlinMain)
export(MVIKotlin.mvikotlinLogging)
with(deps) {
export(decompose.dep)
export(bundles.mviKotlin)
}
}
}
@ -71,7 +72,6 @@ kotlin {
implementation(project(":common:providers"))
implementation(project(":common:core-components"))
implementation(project(":common:preference"))
implementation(SqlDelight.coroutineExtensions)
}
}
}
@ -86,9 +86,10 @@ kotlin {
api(project(":common:list"))
api(project(":common:main"))
api(project(":common:preference"))
api(Decompose.decompose)
api(MVIKotlin.mvikotlinMain)
api(MVIKotlin.mvikotlinLogging)
with(deps) {
api(decompose.dep)
api(bundles.mviKotlin)
}
}
}
}
@ -100,8 +101,11 @@ val packForXcode by tasks.creating(Sync::class) {
group = "build"
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val targetName = "ios"
val framework = kotlin.targets.getByName<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>(targetName)
.binaries.getFramework(mode)
val framework =
kotlin.targets.getByName<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>(
targetName
)
.binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
val targetDir = File(buildDir, "xcode-frameworks")

View File

@ -19,38 +19,39 @@ application {
}
dependencies {
implementation(Koin.core)
implementation(project(":common:database"))
implementation(project(":common:data-models"))
implementation(project(":common:dependency-injection"))
implementation(project(":common:root"))
implementation(project(":common:main"))
implementation(project(":common:list"))
implementation(project(":common:list"))
with(deps) {
implementation(Koin.core)
implementation(project(":common:database"))
implementation(project(":common:data-models"))
implementation(project(":common:dependency-injection"))
implementation(project(":common:root"))
implementation(project(":common:main"))
implementation(project(":common:list"))
implementation(project(":common:list"))
// Decompose
implementation(Decompose.decompose)
implementation(Decompose.extensionsCompose)
// Decompose
implementation(Decompose.decompose)
implementation(Decompose.extensionsCompose)
// MVI
implementation(MVIKotlin.mvikotlin)
implementation(MVIKotlin.mvikotlinMain)
// MVI
implementation(MVIKotlin.mvikotlin)
implementation(MVIKotlin.mvikotlinMain)
// Koin
implementation(Koin.core)
// Koin
implementation(Koin.core)
// Matomo
implementation("org.piwik.java.tracking:matomo-java-tracker:1.6")
// Matomo
implementation(Ktor.slf4j)
implementation(Ktor.clientCore)
implementation(Ktor.clientJson)
implementation(Ktor.clientApache)
implementation(Ktor.clientLogging)
implementation(Ktor.clientSerialization)
implementation(Serialization.json)
// testDeps
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:1.5.21")
implementation(Ktor.slf4j)
implementation(Ktor.clientCore)
implementation(Ktor.clientJson)
implementation(Ktor.clientApache)
implementation(Ktor.clientLogging)
implementation(Ktor.clientSerialization)
implementation(Serialization.json)
// testDeps
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:1.5.21")
}
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {

View File

@ -44,19 +44,21 @@ kotlin {
implementation(project(":common:compose"))
implementation(project(":common:providers"))
implementation(project(":common:root"))
implementation("com.github.kokorin.jaffree:jaffree:2021.08.16")
// Decompose
implementation(Decompose.decompose)
implementation(Decompose.extensionsCompose)
with(deps) {
implementation(jaffree)
// MVI
implementation(MVIKotlin.mvikotlin)
implementation(MVIKotlin.mvikotlinMain)
// Koin
implementation(Koin.core)
with(decompose) {
implementation(dep)
implementation(extensions.compose)
}
with(mviKotlin) {
implementation(dep)
implementation(main)
}
implementation(koin.core)
}
}
}
val jvmTest by getting

View File

@ -13,8 +13,6 @@ android {
minSdk = Versions.minSdkVersion
targetSdk = Versions.targetSdkVersion
// versionCode = Versions.versionCode
// versionName = Versions.versionName
/*ndk {
abiFilters.addAll(setOf("x86", "x86_64", "armeabi-v7a", "arm64-v8a"))

View File

@ -2,6 +2,7 @@ package nl.bravobit.ffmpeg;
import android.os.Build;
@SuppressWarnings("deprecation")
public class CpuArchHelper {
public static final String X86_CPU = "x86";
public static final String X86_64_CPU = "x86_64";

View File

@ -1,7 +1,6 @@
package nl.bravobit.ffmpeg;
import android.os.AsyncTask;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@ -9,10 +8,12 @@ import java.io.OutputStream;
import java.util.Map;
import java.util.concurrent.TimeoutException;
@SuppressWarnings("deprecation")
class FFcommandExecuteAsyncTask extends AsyncTask<Void, String, CommandResult> implements FFtask {
private final String[] cmd;
private Map<String, String> environment;
private final Map<String, String> environment;
private final StringBuilder outputStringBuilder = new StringBuilder();
private final FFcommandExecuteResponseHandler ffmpegExecuteResponseHandler;
private final ShellCommand shellCommand;
private final long timeout;
@ -39,6 +40,7 @@ class FFcommandExecuteAsyncTask extends AsyncTask<Void, String, CommandResult> i
@Override
protected CommandResult doInBackground(Void... params) {
CommandResult ret = CommandResult.getDummyFailureResponse();
try {
process = shellCommand.run(cmd, environment);
if (process == null) {
@ -46,16 +48,19 @@ class FFcommandExecuteAsyncTask extends AsyncTask<Void, String, CommandResult> i
}
Log.d("Running publishing updates method");
checkAndUpdateProcess();
return CommandResult.getOutputFromProcess(process);
ret = CommandResult.getOutputFromProcess(process);
outputStringBuilder.append(ret.output);
} catch (TimeoutException e) {
Log.e("FFmpeg binary timed out", e);
return new CommandResult(false, e.getMessage());
ret = new CommandResult(false, e.getMessage());
outputStringBuilder.append(ret.output);
} catch (Exception e) {
Log.e("Error running FFmpeg binary", e);
} finally {
Util.destroyProcess(process);
}
return CommandResult.getDummyFailureResponse();
output = outputStringBuilder.toString();
return ret;
}
@Override
@ -68,7 +73,6 @@ class FFcommandExecuteAsyncTask extends AsyncTask<Void, String, CommandResult> i
@Override
protected void onPostExecute(CommandResult commandResult) {
if (ffmpegExecuteResponseHandler != null) {
output += commandResult.output;
if (commandResult.success) {
ffmpegExecuteResponseHandler.onSuccess(output);
} else {
@ -107,7 +111,7 @@ class FFcommandExecuteAsyncTask extends AsyncTask<Void, String, CommandResult> i
return;
}
output += line + "\n";
outputStringBuilder.append(line); outputStringBuilder.append("\n");
publishProgress(line);
}
} catch (IOException e) {
@ -139,4 +143,4 @@ class FFcommandExecuteAsyncTask extends AsyncTask<Void, String, CommandResult> i
e.printStackTrace();
}
}
}
}

View File

@ -6,6 +6,7 @@ import android.os.AsyncTask;
import java.io.File;
import java.util.Map;
@SuppressWarnings("deprecation")
public class FFprobe implements FFbinaryInterface {
private final FFbinaryContextProvider context;
@ -22,12 +23,7 @@ public class FFprobe implements FFbinaryInterface {
public static FFprobe getInstance(final Context context) {
if (instance == null) {
instance = new FFprobe(new FFbinaryContextProvider() {
@Override
public Context provide() {
return context;
}
});
instance = new FFprobe(() -> context);
}
return instance;
}

View File

@ -22,7 +22,7 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m
org.gradle.jvmargs=-Xmx2048m -XX:+UseParallelGC
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects

View File

@ -18,16 +18,15 @@ application {
}
dependencies {
implementation(Ktor.slf4j)
implementation(Ktor.clientCore)
implementation(Ktor.clientJson)
implementation(Ktor.clientApache)
implementation(Ktor.clientLogging)
implementation(Ktor.clientSerialization)
implementation(Serialization.json)
with(deps) {
implementation(slf4j.simple)
implementation(bundles.ktor)
implementation(ktor.client.apache)
implementation(kotlinx.serialization.json)
// testDeps
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:1.5.21")
// testDep
testImplementation(kotlin.kotlinTestJunit)
}
}
tasks.test {

View File

@ -14,6 +14,16 @@
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
enableFeaturePreview("VERSION_CATALOGS")
dependencyResolutionManagement {
@Suppress("UnstableApiUsage")
versionCatalogs {
create("deps") {
from(files("buildSrc/deps.versions.toml"))
}
}
}
rootProject.name = "spotiflyer"
include(
@ -32,5 +42,5 @@ include(
":desktop",
":web-app",
//":console-app",
":maintenance-tasks"
":maintenance-tasks",
)

View File

@ -21,20 +21,17 @@ plugins {
group = "com.shabinder"
version = "0.1"
repositories {
mavenCentral()
//maven(url = "https://dl.bintray.com/kotlin/kotlin-js-wrappers")
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-js:1.5.21")
implementation(Koin.core)
implementation(Extras.kermit)
implementation(Decompose.decompose)
implementation(MVIKotlin.mvikotlin)
implementation(MVIKotlin.coroutines)
implementation(MVIKotlin.mvikotlinMain)
implementation(MVIKotlin.mvikotlinLogging)
with(deps) {
implementation(koin.core)
implementation(decompose.dep)
implementation(ktor.client.js)
with(bundles) {
implementation(mviKotlin)
implementation(ktor)
implementation(kotlin.js.wrappers)
}
}
implementation(project(":common:root"))
implementation(project(":common:main"))
implementation(project(":common:list"))
@ -43,27 +40,7 @@ dependencies {
implementation(project(":common:providers"))
implementation(project(":common:core-components"))
implementation(project(":common:dependency-injection"))
implementation("co.touchlab:stately-common:1.1.7")
implementation("dev.icerock.moko:parcelize:${Versions.mokoParcelize}")
// implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.1")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2") {
// https://youtrack.jetbrains.com/issue/KTOR-2670
@Suppress("DEPRECATION")
isForce = true
}
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1-native-mt") {
@Suppress("DEPRECATION")
isForce = true
}
with(KotlinJSWrappers) {
implementation(enforcedPlatform(bom))
implementation(kotlinReact)
implementation(kotlinReactDom)
implementation(kotlinStyled)
}
implementation("org.jetbrains.kotlin:kotlin-stdlib-js:${deps.kotlin.kotlinGradlePlugin.get().versionConstraint.requiredVersion}")
}
kotlin {

View File

@ -23,21 +23,25 @@ import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory
import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory
import com.shabinder.common.core_components.file_manager.DownloadProgressFlow
import com.shabinder.common.core_components.preference_manager.PreferenceManager
import com.shabinder.common.di.ApplicationInit
import com.shabinder.common.models.Actions
import com.shabinder.common.models.PlatformActions
import com.shabinder.common.models.TrackDetails
import com.shabinder.common.root.SpotiFlyerRoot
import com.shabinder.database.Database
import extras.renderableChild
import react.*
import react.PropsWithChildren
import react.RBuilder
import react.RComponent
import react.State
import root.RootR
external interface AppProps : RProps {
external interface AppProps : PropsWithChildren {
var dependencies: AppDependencies
}
@Suppress("FunctionName")
fun RBuilder.App(attrs: AppProps.() -> Unit): ReactElement {
fun RBuilder.App(attrs: AppProps.() -> Unit) {
return child(App::class) {
this.attrs(attrs)
}
@ -46,7 +50,7 @@ fun RBuilder.App(attrs: AppProps.() -> Unit): ReactElement {
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED", "NON_EXPORTABLE_TYPE")
@OptIn(ExperimentalJsExport::class)
@JsExport
class App(props: AppProps) : RComponent<AppProps, RState>(props) {
class App(props: AppProps) : RComponent<AppProps, State>(props) {
private val lifecycle = LifecycleRegistry()
private val ctx = DefaultComponentContext(lifecycle = lifecycle)
@ -62,6 +66,7 @@ class App(props: AppProps) : RComponent<AppProps, RState>(props) {
override val fetchQuery = dependencies.fetchPlatformQueryResult
override val fileManager = dependencies.fileManager
override val analyticsManager = dependencies.analyticsManager
override val appInit: ApplicationInit = dependencies.appInit
override val preferenceManager: PreferenceManager = dependencies.preferenceManager
override val database: Database? = fileManager.db
override val downloadProgressFlow = DownloadProgressFlow

View File

@ -18,6 +18,7 @@ import co.touchlab.kermit.Kermit
import com.shabinder.common.core_components.analytics.AnalyticsManager
import com.shabinder.common.core_components.file_manager.FileManager
import com.shabinder.common.core_components.preference_manager.PreferenceManager
import com.shabinder.common.di.ApplicationInit
import com.shabinder.common.di.initKoin
import com.shabinder.common.providers.FetchPlatformQueryResult
import kotlinx.browser.document
@ -42,6 +43,7 @@ object AppDependencies : KoinComponent {
val fetchPlatformQueryResult: FetchPlatformQueryResult
val preferenceManager: PreferenceManager
val analyticsManager: AnalyticsManager
val appInit: ApplicationInit
init {
initKoin()
fileManager = get()
@ -49,5 +51,6 @@ object AppDependencies : KoinComponent {
fetchPlatformQueryResult = get()
preferenceManager = get()
analyticsManager = get()
appInit = get()
}
}

View File

@ -18,16 +18,16 @@ package extras
import com.arkivanov.decompose.value.Value
import com.arkivanov.decompose.value.ValueObserver
import react.PropsWithChildren
import react.RComponent
import react.RProps
import react.RState
import react.State
import react.setState
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED", "NON_EXPORTABLE_TYPE")
@OptIn(ExperimentalJsExport::class)
@JsExport
abstract class RenderableComponent<T: Any, S: RState>(
abstract class RenderableComponent<T : Any, S : State>(
props: Props<T>,
initialState: S
) : RComponent<Props<T>, S>(props) {
@ -60,7 +60,6 @@ abstract class RenderableComponent<T: Any, S: RState>(
}
protected class Subscription<T : Any>(
val value: Value<T>,
val observer: ValueObserver<T>
@ -72,8 +71,8 @@ abstract class RenderableComponent<T: Any, S: RState>(
@JsExport
class RStateWrapper<T>(
var model: T
) : RState
) : State
external interface Props<T : Any> : RProps {
external interface Props<T : Any> : PropsWithChildren {
var component: T
}

View File

@ -17,39 +17,49 @@
package home
import Styles
import kotlinx.css.*
import kotlinx.css.borderRadius
import kotlinx.css.height
import kotlinx.css.margin
import kotlinx.css.px
import kotlinx.css.width
import kotlinx.html.id
import react.*
import react.PropsWithChildren
import react.RBuilder
import react.dom.attrs
import styled.*
import react.functionComponent
import styled.css
import styled.styledA
import styled.styledDiv
import styled.styledForm
import styled.styledImg
external interface IconListProps : RProps {
var iconsAndPlatforms: Map<String,String>
var isBadge:Boolean
external interface IconListProps : PropsWithChildren {
var iconsAndPlatforms: Map<String, String>
var isBadge: Boolean
}
@Suppress("FunctionName")
fun RBuilder.IconList(handler:IconListProps.() -> Unit): ReactElement {
return child(iconList){
fun RBuilder.IconList(handler: IconListProps.() -> Unit) {
return child(iconList) {
attrs {
handler()
}
}
}
private val iconList = functionalComponent<IconListProps>("IconList") { props ->
private val iconList = functionComponent<IconListProps>("IconList") { props ->
styledDiv {
css {
margin(18.px)
if(props.isBadge) {
classes = mutableListOf("info-banners")
if (props.isBadge) {
classes.add("info-banners")
}
+ Styles.makeRow
+Styles.makeRow
}
val firstElem = props.iconsAndPlatforms.keys.elementAt(1)
for((icon,platformLink) in props.iconsAndPlatforms){
if(icon == firstElem && props.isBadge){
for ((icon, platformLink) in props.iconsAndPlatforms) {
if (icon == firstElem && props.isBadge) {
//<form><script src="https://checkout.razorpay.com/v1/payment-button.js" data-payment_button_id="pl_GnKuuDBdBu0ank" async> </script> </form>
styledForm {
attrs {
@ -57,13 +67,13 @@ private val iconList = functionalComponent<IconListProps>("IconList") { props ->
}
}
}
styledA(href = platformLink,target="_blank"){
styledA(href = platformLink, target = "_blank") {
styledImg {
attrs {
src = icon
}
css {
classes = mutableListOf("glow-button")
classes.add("glow-button")
margin(8.px)
if (!props.isBadge) {
height = 42.px

View File

@ -18,34 +18,32 @@ package home
import kotlinx.css.em
import kotlinx.css.fontSize
import react.PropsWithChildren
import react.RBuilder
import react.RProps
import react.ReactElement
import react.child
import react.functionalComponent
import react.functionComponent
import styled.css
import styled.styledDiv
import styled.styledH1
external interface MessageProps : RProps {
external interface MessageProps : PropsWithChildren {
var text: String
}
@Suppress("FunctionName")
fun RBuilder.Message(handler:MessageProps.() -> Unit): ReactElement {
return child(message){
fun RBuilder.Message(handler: MessageProps.() -> Unit) {
return child(message) {
attrs {
handler()
}
}
}
private val message = functionalComponent<MessageProps>("Message") { props->
private val message = functionComponent<MessageProps>("Message") { props ->
styledDiv {
styledH1 {
+ props.text
+props.text
css {
classes = mutableListOf("headingTitle")
classes.add("headingTitle")
fontSize = 2.6.em
}
}

View File

@ -22,32 +22,35 @@ import kotlinx.html.js.onChangeFunction
import kotlinx.html.js.onClickFunction
import kotlinx.html.js.onKeyDownFunction
import org.w3c.dom.HTMLInputElement
import react.PropsWithChildren
import react.RBuilder
import react.RProps
import react.child
import react.dom.attrs
import react.functionalComponent
import styled.*
import react.functionComponent
import styled.css
import styled.styledButton
import styled.styledDiv
import styled.styledImg
import styled.styledInput
external interface SearchbarProps : RProps {
external interface SearchbarProps : PropsWithChildren {
var link: String
var search:(String)->Unit
var onLinkChange:(String)->Unit
var search: (String) -> Unit
var onLinkChange: (String) -> Unit
}
@Suppress("FunctionName")
fun RBuilder.SearchBar(handler:SearchbarProps.() -> Unit) = child(searchbar){
fun RBuilder.SearchBar(handler: SearchbarProps.() -> Unit) = child(searchbar) {
attrs {
handler()
}
}
val searchbar = functionalComponent<SearchbarProps>("SearchBar"){ props ->
styledDiv{
val searchbar = functionComponent<SearchbarProps>("SearchBar") { props ->
styledDiv {
css {
classes = mutableListOf("searchBox")
classes.add("searchBox")
}
styledInput(type = InputType.url){
styledInput(type = InputType.url) {
attrs {
placeholder = "Search"
onChangeFunction = {
@ -55,30 +58,30 @@ val searchbar = functionalComponent<SearchbarProps>("SearchBar"){ props ->
props.onLinkChange(target.value)
}
this.onKeyDownFunction = {
if(it.asDynamic().key == "Enter") {
if(props.link.isEmpty()) window.alert("Enter a Link from Supported Platforms")
if (it.asDynamic().key == "Enter") {
if (props.link.isEmpty()) window.alert("Enter a Link from Supported Platforms")
else props.search(props.link)
}
}
value = props.link
}
css {
classes = mutableListOf("searchInput")
classes.add("searchInput")
}
}
styledButton {
attrs {
onClickFunction = {
if(props.link.isEmpty()) window.alert("Enter a Link from Supported Platforms")
if (props.link.isEmpty()) window.alert("Enter a Link from Supported Platforms")
else props.search(props.link)
}
}
css {
classes = mutableListOf("searchButton")
classes.add("searchButton")
}
styledImg(src = "search.svg") {
css {
classes = mutableListOf("search-icon")
classes.add("search-icon")
}
}
}

View File

@ -23,42 +23,44 @@ import kotlinx.css.justifyContent
import kotlinx.css.marginBottom
import kotlinx.css.px
import kotlinx.css.width
import react.PropsWithChildren
import react.RBuilder
import react.RProps
import react.ReactElement
import react.child
import react.functionalComponent
import react.functionComponent
import styled.css
import styled.styledDiv
import styled.styledSpan
@Suppress("FunctionName")
fun RBuilder.CircularProgressBar(handler: CircularProgressBarProps.() -> Unit): ReactElement {
return child(circularProgressBar){
fun RBuilder.CircularProgressBar(handler: CircularProgressBarProps.() -> Unit) {
return child(circularProgressBar) {
attrs {
handler()
}
}
}
external interface CircularProgressBarProps : RProps {
var progress:Int
external interface CircularProgressBarProps : PropsWithChildren {
var progress: Int
}
private val circularProgressBar = functionalComponent<CircularProgressBarProps>("Circular-Progress-Bar") { props->
private val circularProgressBar = functionComponent<CircularProgressBarProps>("Circular-Progress-Bar") { props ->
styledDiv {
styledSpan { +"${props.progress}%" }
styledDiv{
styledDiv {
css {
classes = mutableListOf("left-half-clipper")
classes.add("left-half-clipper")
}
styledDiv{ css { classes = mutableListOf("first50-bar") } }
styledDiv{ css { classes = mutableListOf("value-bar") } }
styledDiv { css { classes.add("first50-bar") } }
styledDiv { css { classes.add("value-bar") } }
}
css{
css {
display = Display.flex
justifyContent = JustifyContent.center
classes = mutableListOf("progress-circle","p${props.progress}").apply { if(props.progress>50) add("over50") }
classes.addAll(
mutableListOf(
"progress-circle",
"p${props.progress}"
).apply { if (props.progress > 50) add("over50") })
width = 50.px
marginBottom = 65.px
}

View File

@ -16,32 +16,45 @@
package list
import kotlinx.css.*
import kotlinx.css.Align
import kotlinx.css.Display
import kotlinx.css.FlexDirection
import kotlinx.css.TextAlign
import kotlinx.css.alignItems
import kotlinx.css.display
import kotlinx.css.flexDirection
import kotlinx.css.height
import kotlinx.css.marginTop
import kotlinx.css.px
import kotlinx.css.textAlign
import kotlinx.css.width
import kotlinx.html.id
import react.*
import react.PropsWithChildren
import react.RBuilder
import react.dom.attrs
import react.functionComponent
import styled.css
import styled.styledDiv
import styled.styledH1
import styled.styledImg
external interface CoverImageProps : RProps {
external interface CoverImageProps : PropsWithChildren {
var coverImageURL: String
var coverName: String
}
@Suppress("FunctionName")
fun RBuilder.CoverImage(handler: CoverImageProps.() -> Unit): ReactElement {
return child(coverImage){
fun RBuilder.CoverImage(handler: CoverImageProps.() -> Unit) {
return child(coverImage) {
attrs {
handler()
}
}
}
private val coverImage = functionalComponent<CoverImageProps>("CoverImage"){ props ->
private val coverImage = functionComponent<CoverImageProps>("CoverImage") { props ->
styledDiv {
styledImg(src= props.coverImageURL){
styledImg(src = props.coverImageURL) {
css {
height = 220.px
width = 220.px

View File

@ -16,52 +16,65 @@
package list
import kotlinx.css.*
import kotlinx.css.Align
import kotlinx.css.Display
import kotlinx.css.JustifyContent
import kotlinx.css.WhiteSpace
import kotlinx.css.alignItems
import kotlinx.css.display
import kotlinx.css.fontSize
import kotlinx.css.height
import kotlinx.css.justifyContent
import kotlinx.css.px
import kotlinx.css.whiteSpace
import kotlinx.html.id
import kotlinx.html.js.onClickFunction
import react.*
import react.PropsWithChildren
import react.RBuilder
import react.dom.attrs
import react.functionComponent
import react.useEffect
import react.useState
import styled.css
import styled.styledDiv
import styled.styledH5
import styled.styledImg
external interface DownloadAllButtonProps : RProps {
var isActive:Boolean
var link : String
var downloadAll:()->Unit
external interface DownloadAllButtonProps : PropsWithChildren {
var isActive: Boolean
var link: String
var downloadAll: () -> Unit
}
@Suppress("FunctionName")
fun RBuilder.DownloadAllButton(handler: DownloadAllButtonProps.() -> Unit): ReactElement {
return child(downloadAllButton){
fun RBuilder.DownloadAllButton(handler: DownloadAllButtonProps.() -> Unit) {
return child(downloadAllButton) {
attrs {
handler()
}
}
}
private val downloadAllButton = functionalComponent<DownloadAllButtonProps>("DownloadAllButton") { props->
private val downloadAllButton = functionComponent<DownloadAllButtonProps>("DownloadAllButton") { props ->
val (isClicked,setClicked) = useState(false)
val (isClicked, setClicked) = useState(false)
useEffect(mutableListOf(props.link)){
useEffect(mutableListOf(props.link)) {
setClicked(false)
}
if(props.isActive){
if(isClicked) {
styledDiv{
if (props.isActive) {
if (isClicked) {
styledDiv {
css {
display = Display.flex
alignItems = Align.center
justifyContent = JustifyContent.center
height = 52.px
}
LoadingSpinner { }
LoadingSpinner { }
}
}
else{
} else {
styledDiv {
attrs {
onClickFunction = {
@ -71,9 +84,9 @@ private val downloadAllButton = functionalComponent<DownloadAllButtonProps>("Dow
}
styledDiv {
styledImg(src = "download.svg",alt = "Download All Button") {
styledImg(src = "download.svg", alt = "Download All Button") {
css {
classes = mutableListOf("download-all-icon")
classes.add("download-all-icon")
height = 32.px
}
}
@ -82,7 +95,7 @@ private val downloadAllButton = functionalComponent<DownloadAllButtonProps>("Dow
attrs {
id = "download-all-text"
}
+ "Download All"
+"Download All"
css {
whiteSpace = WhiteSpace.nowrap
fontSize = 15.px
@ -90,13 +103,13 @@ private val downloadAllButton = functionalComponent<DownloadAllButtonProps>("Dow
}
css {
classes = mutableListOf("download-icon")
classes.add("download-icon")
display = Display.flex
alignItems = Align.center
}
}
css {
classes = mutableListOf("download-button")
classes.add("download-button")
display = Display.flex
alignItems = Align.center
}

View File

@ -17,31 +17,37 @@
package list
import com.shabinder.common.models.DownloadStatus
import kotlinx.css.*
import kotlinx.css.borderRadius
import kotlinx.css.em
import kotlinx.css.margin
import kotlinx.css.px
import kotlinx.css.width
import kotlinx.html.js.onClickFunction
import react.*
import react.PropsWithChildren
import react.RBuilder
import react.dom.attrs
import react.functionComponent
import styled.css
import styled.styledDiv
import styled.styledImg
@Suppress("FunctionName")
fun RBuilder.DownloadButton(handler: DownloadButtonProps.() -> Unit): ReactElement {
return child(downloadButton){
fun RBuilder.DownloadButton(handler: DownloadButtonProps.() -> Unit) {
return child(downloadButton) {
attrs {
handler()
}
}
}
external interface DownloadButtonProps : RProps {
var onClick:()->Unit
var status :DownloadStatus
external interface DownloadButtonProps : PropsWithChildren {
var onClick: () -> Unit
var status: DownloadStatus
}
private val downloadButton = functionalComponent<DownloadButtonProps>("Circular-Progress-Bar") { props->
private val downloadButton = functionComponent<DownloadButtonProps>("Circular-Progress-Bar") { props ->
styledDiv {
val src = when(props.status){
val src = when (props.status) {
is DownloadStatus.NotDownloaded -> "download-gradient.svg"
is DownloadStatus.Downloaded -> "check.svg"
is DownloadStatus.Failed -> "error.svg"
@ -59,7 +65,7 @@ private val downloadButton = functionalComponent<DownloadButtonProps>("Circular-
}
}
css {
classes = mutableListOf("glow-button")
classes.add("glow-button")
borderRadius = 100.px
}
}

View File

@ -84,7 +84,7 @@ class ListScreen(
}
css {
classes = mutableListOf("list-screen")
classes.add("list-screen")
display = Display.flex
padding(8.px)
flexDirection = FlexDirection.column

View File

@ -24,43 +24,41 @@ import kotlinx.css.flexGrow
import kotlinx.css.height
import kotlinx.css.px
import kotlinx.css.width
import react.PropsWithChildren
import react.RBuilder
import react.RProps
import react.ReactElement
import react.child
import react.functionalComponent
import react.functionComponent
import styled.css
import styled.styledDiv
@Suppress("FunctionName")
fun RBuilder.LoadingAnim(handler: RProps.() -> Unit): ReactElement {
return child(loadingAnim){
fun RBuilder.LoadingAnim(handler: PropsWithChildren.() -> Unit) {
return child(loadingAnim) {
attrs {
handler()
}
}
}
private val loadingAnim = functionalComponent<RProps>("Loading Animation") {
styledDiv{
private val loadingAnim = functionComponent<PropsWithChildren>("Loading Animation") {
styledDiv {
css {
flexGrow = 1.0
display = Display.flex
alignItems = Align.center
}
styledDiv {
styledDiv { css { classes = mutableListOf("sk-cube sk-cube1") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube2") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube3") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube4") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube5") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube6") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube7") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube8") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube9") } }
styledDiv { css { classes.add("sk-cube sk-cube1") } }
styledDiv { css { classes.add("sk-cube sk-cube2") } }
styledDiv { css { classes.add("sk-cube sk-cube3") } }
styledDiv { css { classes.add("sk-cube sk-cube4") } }
styledDiv { css { classes.add("sk-cube sk-cube5") } }
styledDiv { css { classes.add("sk-cube sk-cube6") } }
styledDiv { css { classes.add("sk-cube sk-cube7") } }
styledDiv { css { classes.add("sk-cube sk-cube8") } }
styledDiv { css { classes.add("sk-cube sk-cube9") } }
css {
classes = mutableListOf("sk-cube-grid")
classes.add("sk-cube-grid")
height = 60.px
width = 60.px
}

View File

@ -19,31 +19,29 @@ package list
import kotlinx.css.marginRight
import kotlinx.css.px
import kotlinx.css.width
import react.PropsWithChildren
import react.RBuilder
import react.RProps
import react.ReactElement
import react.child
import react.functionalComponent
import react.functionComponent
import styled.css
import styled.styledDiv
@Suppress("FunctionName")
fun RBuilder.LoadingSpinner(handler: RProps.() -> Unit): ReactElement {
return child(loadingSpinner){
fun RBuilder.LoadingSpinner(handler: PropsWithChildren.() -> Unit) {
return child(loadingSpinner) {
attrs {
handler()
}
}
}
private val loadingSpinner = functionalComponent<RProps>("Loading-Spinner") {
private val loadingSpinner = functionComponent<PropsWithChildren>("Loading-Spinner") {
styledDiv {
styledDiv{}
styledDiv{}
styledDiv{}
styledDiv{}
css{
classes = mutableListOf("lds-ring")
styledDiv {}
styledDiv {}
styledDiv {}
styledDiv {}
css {
classes.add("lds-ring")
width = 50.px
marginRight = 8.px
}

View File

@ -18,30 +18,61 @@ package list
import com.shabinder.common.models.DownloadStatus
import com.shabinder.common.models.TrackDetails
import kotlinx.css.*
import kotlinx.css.Align
import kotlinx.css.Display
import kotlinx.css.FlexDirection
import kotlinx.css.Overflow
import kotlinx.css.TextAlign
import kotlinx.css.TextOverflow
import kotlinx.css.WhiteSpace
import kotlinx.css.alignItems
import kotlinx.css.display
import kotlinx.css.em
import kotlinx.css.flexDirection
import kotlinx.css.flexGrow
import kotlinx.css.fontSize
import kotlinx.css.height
import kotlinx.css.margin
import kotlinx.css.minWidth
import kotlinx.css.overflow
import kotlinx.css.padding
import kotlinx.css.paddingRight
import kotlinx.css.px
import kotlinx.css.textAlign
import kotlinx.css.textOverflow
import kotlinx.css.whiteSpace
import kotlinx.css.width
import kotlinx.html.id
import react.*
import react.PropsWithChildren
import react.RBuilder
import react.dom.attrs
import styled.*
import react.functionComponent
import react.useEffect
import react.useState
import styled.css
import styled.styledDiv
import styled.styledH3
import styled.styledH4
import styled.styledImg
external interface TrackItemProps : RProps {
var details:TrackDetails
var downloadTrack:(TrackDetails)->Unit
external interface TrackItemProps : PropsWithChildren {
var details: TrackDetails
var downloadTrack: (TrackDetails) -> Unit
}
@Suppress("FunctionName")
fun RBuilder.TrackItem(handler: TrackItemProps.() -> Unit): ReactElement {
return child(trackItem){
fun RBuilder.TrackItem(handler: TrackItemProps.() -> Unit) {
return child(trackItem) {
attrs {
handler()
}
}
}
private val trackItem = functionalComponent<TrackItemProps>("Track-Item"){ props ->
val (downloadStatus,setDownloadStatus) = useState(props.details.downloaded)
private val trackItem = functionComponent<TrackItemProps>("Track-Item") { props ->
val (downloadStatus, setDownloadStatus) = useState(props.details.downloaded)
val details = props.details
useEffect(listOf(props.details)){
useEffect(listOf(props.details)) {
setDownloadStatus(props.details.downloaded)
}
styledDiv {
@ -63,14 +94,14 @@ private val trackItem = functionalComponent<TrackItemProps>("Track-Item"){ props
flexDirection = FlexDirection.column
margin(8.px)
}
styledDiv{
styledDiv {
css {
height = 40.px
alignItems = Align.center
display = Display.flex
}
styledH3 {
+ details.title
+details.title
css {
padding(8.px)
fontSize = 1.3.em
@ -87,7 +118,7 @@ private val trackItem = functionalComponent<TrackItemProps>("Track-Item"){ props
display = Display.flex
}
styledH4 {
+ details.artists.joinToString(",")
+details.artists.joinToString(",")
css {
flexGrow = 1.0
padding(8.px)
@ -109,12 +140,12 @@ private val trackItem = functionalComponent<TrackItemProps>("Track-Item"){ props
whiteSpace = WhiteSpace.nowrap
overflow = Overflow.hidden
}
+ "${details.durationSec/60} min, ${details.durationSec%60} sec"
+"${details.durationSec / 60} min, ${details.durationSec % 60} sec"
}
}
}
when(downloadStatus){
is DownloadStatus.NotDownloaded ->{
when (downloadStatus) {
is DownloadStatus.NotDownloaded -> {
DownloadButton {
onClick = {
setDownloadStatus(DownloadStatus.Queued)
@ -152,7 +183,7 @@ private val trackItem = functionalComponent<TrackItemProps>("Track-Item"){ props
css {
alignItems = Align.center
display =Display.flex
display = Display.flex
paddingRight = 16.px
}
}

View File

@ -16,36 +16,55 @@
package navbar
import kotlinx.css.*
import kotlinx.css.Align
import kotlinx.css.Display
import kotlinx.css.LinearDimension
import kotlinx.css.alignItems
import kotlinx.css.display
import kotlinx.css.filter
import kotlinx.css.fontSize
import kotlinx.css.height
import kotlinx.css.margin
import kotlinx.css.marginLeft
import kotlinx.css.marginRight
import kotlinx.css.px
import kotlinx.css.width
import kotlinx.html.id
import kotlinx.html.js.onBlurFunction
import kotlinx.html.js.onClickFunction
import react.*
import react.RBuilder
import react.RProps
import react.dom.attrs
import styled.*
import react.functionComponent
import styled.css
import styled.styledA
import styled.styledDiv
import styled.styledH1
import styled.styledImg
import styled.styledNav
@Suppress("FunctionName")
fun RBuilder.NavBar(handler: NavBarProps.() -> Unit): ReactElement{
return child(navBar){
fun RBuilder.NavBar(handler: NavBarProps.() -> Unit) {
return child(navBar) {
attrs {
handler()
}
}
}
external interface NavBarProps:RProps{
external interface NavBarProps : RProps {
var isBackVisible: Boolean
var popBackToHomeScreen: () -> Unit
}
private val navBar = functionalComponent<NavBarProps>("NavBar") { props ->
private val navBar = functionComponent<NavBarProps>("NavBar") { props ->
styledNav {
css {
+NavBarStyles.nav
}
styledDiv{
styledDiv {
attrs {
onClickFunction = {
props.popBackToHomeScreen()
@ -54,22 +73,22 @@ private val navBar = functionalComponent<NavBarProps>("NavBar") { props ->
props.popBackToHomeScreen()
}
}
styledImg(src = "left-arrow.svg",alt = "Back Arrow"){
styledImg(src = "left-arrow.svg", alt = "Back Arrow") {
css {
height = 42.px
width = 42.px
display = if(props.isBackVisible) Display.inline else Display.none
display = if (props.isBackVisible) Display.inline else Display.none
filter = "invert(100)"
marginRight = 12.px
}
}
}
styledA(href = "https://shabinder.github.io/SpotiFlyer/",target="_blank") {
styledA(href = "https://shabinder.github.io/SpotiFlyer/", target = "_blank") {
css {
display = Display.flex
alignItems = Align.center
}
styledImg(src = "spotiflyer.svg",alt = "Logo") {
styledImg(src = "spotiflyer.svg", alt = "Logo") {
css {
height = 42.px
width = 42.px
@ -80,7 +99,7 @@ private val navBar = functionalComponent<NavBarProps>("NavBar") { props ->
attrs {
id = "appName"
}
css{
css {
fontSize = 46.px
margin(horizontal = 14.px)
}
@ -93,7 +112,7 @@ private val navBar = functionalComponent<NavBarProps>("NavBar") { props ->
setCorsMode(corsProxy)
}*/
styledDiv{
styledDiv {
/*styledH4 { + "Extension" }
@ -125,8 +144,8 @@ private val navBar = functionalComponent<NavBarProps>("NavBar") { props ->
}
}*/
styledA(href = "https://github.com/Shabinder/SpotiFlyer/"){
styledImg(src = "github.svg"){
styledA(href = "https://github.com/Shabinder/SpotiFlyer/") {
styledImg(src = "github.svg") {
css {
height = 42.px
width = 42.px

View File

@ -26,7 +26,6 @@ import home.HomeScreen
import list.ListScreen
import navbar.NavBar
import react.RBuilder
import react.RState
class RootR(props: Props<SpotiFlyerRoot>) : RenderableComponent<SpotiFlyerRoot, State>(
props = props,
@ -58,4 +57,4 @@ class RootR(props: Props<SpotiFlyerRoot>) : RenderableComponent<SpotiFlyerRoot,
@JsExport
class State(
var routerState: RouterState<*, Child>
) : RState
) : react.State