diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 04d4f636..3375b220 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -49,7 +49,7 @@ android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:icon="@mipmap/ic_launcher" android:largeHeap="true" - android:label="@string/app_name" + android:label="SpotiFlyer" android:roundIcon="@mipmap/ic_launcher_round" android:configChanges="orientation|screenSize" android:forceDarkAllowed="true" @@ -57,7 +57,7 @@ tools:targetApi="q"> diff --git a/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt b/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt index 4647f8c1..e5a69bc3 100644 --- a/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt +++ b/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt @@ -17,6 +17,8 @@ package com.shabinder.spotiflyer import android.annotation.SuppressLint +import android.content.ClipData +import android.content.ClipboardManager import android.content.ComponentName import android.content.Context import android.content.Intent @@ -31,11 +33,20 @@ import android.os.PowerManager import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.animation.* +import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* -import androidx.compose.material.* -import androidx.compose.runtime.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.State +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalView import androidx.core.content.ContextCompat @@ -51,7 +62,10 @@ import com.google.accompanist.insets.ProvideWindowInsets import com.google.accompanist.insets.navigationBarsPadding import com.google.accompanist.insets.statusBarsHeight import com.google.accompanist.insets.statusBarsPadding -import com.shabinder.common.di.* +import com.shabinder.common.di.ConnectionLiveData +import com.shabinder.common.di.Dir +import com.shabinder.common.di.FetchPlatformQueryResult +import com.shabinder.common.di.observeAsState import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.models.Actions import com.shabinder.common.models.DownloadStatus @@ -63,18 +77,28 @@ import com.shabinder.common.root.SpotiFlyerRoot import com.shabinder.common.root.SpotiFlyerRoot.Analytics import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks import com.shabinder.common.translations.Strings -import com.shabinder.common.uikit.* +import com.shabinder.common.uikit.configurations.SpotiFlyerTheme +import com.shabinder.common.uikit.configurations.colorOffWhite +import com.shabinder.common.uikit.screens.SpotiFlyerRootContent import com.shabinder.spotiflyer.service.ForegroundService import com.shabinder.spotiflyer.ui.AnalyticsDialog import com.shabinder.spotiflyer.ui.NetworkDialog import com.shabinder.spotiflyer.ui.PermissionDialog -import com.shabinder.spotiflyer.utils.* -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.* +import com.shabinder.spotiflyer.utils.checkAppSignature +import com.shabinder.spotiflyer.utils.checkIfLatestVersion +import com.shabinder.spotiflyer.utils.checkPermissions +import com.shabinder.spotiflyer.utils.disableDozeMode +import com.shabinder.spotiflyer.utils.requestStoragePermission +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.conflate +import kotlinx.coroutines.flow.emitAll +import kotlinx.coroutines.launch import org.koin.android.ext.android.inject import org.matomo.sdk.extra.TrackHelper import java.io.File + @ExperimentalAnimationApi class MainActivity : ComponentActivity() { @@ -295,6 +319,14 @@ class MainActivity : ComponentActivity() { startActivity(shareIntent) } + override fun copyToClipboard(text: String) { + val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager + val clip = ClipData.newPlainText("SpotiFlyer Selection", text) + clipboard.setPrimaryClip(clip) + + showPopUpMessage("StackTrace Copied to Clipboard.") + } + override fun openPlatform(packageID: String, platformLink: String) { val manager: PackageManager = applicationContext.packageManager try { diff --git a/android/src/main/java/com/shabinder/spotiflyer/ui/AnalyticsDialog.kt b/android/src/main/java/com/shabinder/spotiflyer/ui/AnalyticsDialog.kt index 2bbc0847..63bed6b6 100644 --- a/android/src/main/java/com/shabinder/spotiflyer/ui/AnalyticsDialog.kt +++ b/android/src/main/java/com/shabinder/spotiflyer/ui/AnalyticsDialog.kt @@ -27,9 +27,9 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.DialogProperties import com.shabinder.common.translations.Strings -import com.shabinder.common.uikit.SpotiFlyerShapes -import com.shabinder.common.uikit.SpotiFlyerTypography -import com.shabinder.common.uikit.colorPrimary +import com.shabinder.common.uikit.configurations.SpotiFlyerShapes +import com.shabinder.common.uikit.configurations.SpotiFlyerTypography +import com.shabinder.common.uikit.configurations.colorPrimary @ExperimentalAnimationApi @Composable diff --git a/android/src/main/java/com/shabinder/spotiflyer/ui/NetworkDialog.kt b/android/src/main/java/com/shabinder/spotiflyer/ui/NetworkDialog.kt index a204e959..c5f2b7ff 100644 --- a/android/src/main/java/com/shabinder/spotiflyer/ui/NetworkDialog.kt +++ b/android/src/main/java/com/shabinder/spotiflyer/ui/NetworkDialog.kt @@ -44,9 +44,9 @@ import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.shabinder.common.translations.Strings -import com.shabinder.common.uikit.SpotiFlyerShapes -import com.shabinder.common.uikit.SpotiFlyerTypography -import com.shabinder.common.uikit.colorOffWhite +import com.shabinder.common.uikit.configurations.SpotiFlyerShapes +import com.shabinder.common.uikit.configurations.SpotiFlyerTypography +import com.shabinder.common.uikit.configurations.colorOffWhite import kotlinx.coroutines.delay @ExperimentalAnimationApi @@ -88,7 +88,8 @@ fun NetworkDialog( ) { Image(Icons.Rounded.CloudOff, Strings.noInternetConnection(),Modifier.size(42.dp),colorFilter = ColorFilter.tint( - colorOffWhite)) + colorOffWhite + )) Spacer(modifier = Modifier.padding(start = 16.dp)) Text( text = Strings.checkInternetConnection(), diff --git a/android/src/main/java/com/shabinder/spotiflyer/ui/PermissionDialog.kt b/android/src/main/java/com/shabinder/spotiflyer/ui/PermissionDialog.kt index 8b55781e..4412d644 100644 --- a/android/src/main/java/com/shabinder/spotiflyer/ui/PermissionDialog.kt +++ b/android/src/main/java/com/shabinder/spotiflyer/ui/PermissionDialog.kt @@ -29,9 +29,9 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.shabinder.common.translations.Strings -import com.shabinder.common.uikit.SpotiFlyerShapes -import com.shabinder.common.uikit.SpotiFlyerTypography -import com.shabinder.common.uikit.colorPrimary +import com.shabinder.common.uikit.configurations.SpotiFlyerShapes +import com.shabinder.common.uikit.configurations.SpotiFlyerTypography +import com.shabinder.common.uikit.configurations.colorPrimary import kotlinx.coroutines.delay @ExperimentalAnimationApi diff --git a/build.gradle.kts b/build.gradle.kts index c4f0b7fc..da71da60 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,14 +33,14 @@ allprojects { tasks.withType().configureEach { kotlinOptions { jvmTarget = "1.8" - freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn" } } afterEvaluate { project.extensions.findByType()?.let { kmpExt -> kmpExt.sourceSets.run { all { - languageSettings.useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi") + languageSettings.useExperimentalAnnotation("kotlin.RequiresOptIn") + languageSettings.useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi") } removeAll { it.name == "androidAndroidTestRelease" } } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 6a9fa555..33d0caf4 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -30,13 +30,14 @@ repositories { } dependencies { - implementation("com.android.tools.build:gradle:4.1.1") + implementation(Androidx.gradlePlugin) implementation(JetBrains.Compose.gradlePlugin) implementation(JetBrains.Kotlin.gradlePlugin) implementation(JetBrains.Kotlin.serialization) implementation(SqlDelight.gradlePlugin) - implementation("org.jlleitschuh.gradle:ktlint-gradle:${Versions.ktLint}") - implementation("de.comahe.i18n4k:i18n4k-gradle-plugin:0.1.1") + implementation(KTLint.gradlePlugin) + implementation(Internationalization.gradlePlugin) + implementation(Mosaic.gradlePlugin) } kotlin { diff --git a/buildSrc/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/buildSrc/src/main/kotlin/Versions.kt index 6e64166a..afb068fb 100644 --- a/buildSrc/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/buildSrc/src/main/kotlin/Versions.kt @@ -19,17 +19,21 @@ object Versions { // App's Version (To be bumped at each update) const val versionName = "3.1.0" - const val versionCode = 20 + const val versionCode = 20 // Kotlin const val kotlinVersion = "1.5.10" + const val coroutinesVersion = "1.5.0" // Code Formatting const val ktLint = "10.1.0" + // Console-App UI + const val mosaic = "0.1.0" + // DI - const val koin = "3.1.0" + const val koin = "3.1.2" // Logger const val kermit = "0.1.9" @@ -45,6 +49,9 @@ object Versions { const val sqliteJdbcDriver = "3.34.0" const val slf4j = "1.7.31" + // Internationalisation + const val i18n4k = "0.1.2" + // Android const val minSdkVersion = 21 const val compileSdkVersion = 29 @@ -80,15 +87,11 @@ object Androidx { const val junit = "androidx.test.ext:junit:1.1.2" const val expresso = "androidx.test.espresso:espresso-core:3.3.0" - /*object Compose{ - const val materialIcon = "androidx.compose.material:material-icons-extended:${Versions.compose}" - const val ui = "androidx.compose.ui:ui:${Versions.compose}" - const val uiGraphics = "androidx.compose.ui:ui-graphics:${Versions.compose}" - const val uiTooling = "androidx.compose.ui:ui-tooling:${Versions.compose}" - const val foundationLayout = "androidx.compose.foundation:foundation-layout:${Versions.compose}" - const val material = "androidx.compose.material:material:${Versions.compose}" - const val runtimeLiveData = "androidx.compose.runtime:runtime-livedata:${Versions.compose}" - }*/ + const val gradlePlugin = "com.android.tools.build:gradle:4.1.1" +} + +object KTLint { + const val gradlePlugin = "org.jlleitschuh.gradle:ktlint-gradle:${Versions.ktLint}" } object JetBrains { @@ -106,7 +109,9 @@ object JetBrains { 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.2.6" const val decompose = "com.arkivanov.decompose:decompose:$VERSION" @@ -146,7 +151,8 @@ object Ktor { } object Internationalization { - const val dep = "de.comahe.i18n4k:i18n4k-core:0.1.1" + const val dep = "de.comahe.i18n4k:i18n4k-core:${Versions.i18n4k}" + const val gradlePlugin = "de.comahe.i18n4k:i18n4k-gradle-plugin:${Versions.i18n4k}" } object Extras { diff --git a/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidDialog.kt b/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidDialog.kt new file mode 100644 index 00000000..db9d5a46 --- /dev/null +++ b/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidDialog.kt @@ -0,0 +1,19 @@ +package com.shabinder.common.uikit + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.runtime.Composable + +@OptIn(ExperimentalAnimationApi::class) +@Composable +actual fun Dialog( + isVisible: Boolean, + onDismiss: () -> Unit, + content: @Composable () -> Unit +) { + AnimatedVisibility(isVisible) { + androidx.compose.ui.window.Dialog(onDismiss) { + content() + } + } +} \ No newline at end of file diff --git a/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImageLoad.kt b/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImageLoad.kt index ec019e31..ae308b4b 100644 --- a/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImageLoad.kt +++ b/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImageLoad.kt @@ -20,7 +20,7 @@ actual fun ImageLoad( link: String, loader: suspend () -> Picture, desc: String, - modifier: Modifier, + modifier: Modifier // placeholder: ImageVector ) { var pic by remember(link) { mutableStateOf(null) } diff --git a/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImages.kt b/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImages.kt index 10ea5bf5..744c52e2 100644 --- a/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImages.kt +++ b/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImages.kt @@ -22,24 +22,10 @@ import androidx.compose.foundation.Image import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight import com.shabinder.common.database.R import com.shabinder.common.translations.Strings import kotlinx.coroutines.flow.MutableStateFlow -actual fun montserratFont() = FontFamily( - Font(R.font.montserrat_light, FontWeight.Light), - Font(R.font.montserrat_regular, FontWeight.Normal), - Font(R.font.montserrat_medium, FontWeight.Medium), - Font(R.font.montserrat_semibold, FontWeight.SemiBold), -) - -actual fun pristineFont() = FontFamily( - Font(R.font.pristine_script, FontWeight.Bold) -) - @Composable actual fun DownloadImageTick() { Image( @@ -49,10 +35,11 @@ actual fun DownloadImageTick() { } @Composable -actual fun DownloadImageError() { +actual fun DownloadImageError(modifier: Modifier) { Image( painterResource(R.drawable.ic_error), - Strings.downloadError() + Strings.downloadError(), + modifier = modifier ) } diff --git a/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/DonationDialog.kt b/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/DonationDialog.kt deleted file mode 100644 index ceae4b23..00000000 --- a/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/DonationDialog.kt +++ /dev/null @@ -1,141 +0,0 @@ -package com.shabinder.common.uikit - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material.ButtonDefaults -import androidx.compose.material.Card -import androidx.compose.material.Icon -import androidx.compose.material.OutlinedButton -import androidx.compose.material.Text -import androidx.compose.material.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog -import com.shabinder.common.models.methods -import com.shabinder.common.translations.Strings - -@OptIn(ExperimentalAnimationApi::class) -@Composable -actual fun DonationDialog( - isVisible: Boolean, - onDismiss: () -> Unit, - onSnooze: () -> Unit -) { - AnimatedVisibility( - isVisible - ) { - - Dialog(onDismiss) { - Card( - modifier = Modifier.fillMaxWidth(), - border = BorderStroke(1.dp, Color.Gray) // Gray - ) { - Column(Modifier.padding(16.dp)) { - Text( - Strings.supportUs(), - style = SpotiFlyerTypography.h5, - textAlign = TextAlign.Center, - color = colorAccent, - modifier = Modifier - ) - Spacer(modifier = Modifier.padding(vertical = 4.dp)) - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth().clickable( - onClick = { - onDismiss() - methods.value.openPlatform("", "https://opencollective.com/spotiflyer/donate") - } - ) - .padding(vertical = 6.dp) - ) { - Icon(OpenCollectiveLogo(), "Open Collective Logo", Modifier.size(24.dp), tint = Color(0xFFCCCCCC)) - Spacer(modifier = Modifier.padding(start = 16.dp)) - Column { - Text( - text = "Open Collective", - style = SpotiFlyerTypography.h6 - ) - Text( - text = Strings.worldWideDonations(), - style = SpotiFlyerTypography.subtitle2 - ) - } - } - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth().clickable( - onClick = { - onDismiss() - methods.value.openPlatform("", "https://www.paypal.com/paypalme/shabinder") - } - ) - .padding(vertical = 6.dp) - ) { - Icon(PaypalLogo(), "Paypal Logo", Modifier.size(24.dp), tint = Color(0xFFCCCCCC)) - Spacer(modifier = Modifier.padding(start = 16.dp)) - Column { - Text( - text = "Paypal", - style = SpotiFlyerTypography.h6 - ) - Text( - text = Strings.worldWideDonations(), - style = SpotiFlyerTypography.subtitle2 - ) - } - } - Row( - modifier = Modifier.fillMaxWidth().padding(top = 6.dp) - .clickable( - onClick = { - onDismiss() - methods.value.giveDonation() - } - ), - verticalAlignment = Alignment.CenterVertically - ) { - Icon(RazorPay(), "Indian Rupee Logo", Modifier.size(24.dp), tint = Color(0xFFCCCCCC)) - Spacer(modifier = Modifier.padding(start = 16.dp)) - Column { - Text( - text = "RazorPay", - style = SpotiFlyerTypography.h6 - ) - Text( - text = "${Strings.indianDonations()} (UPI / PayTM / PhonePe / Cards).", - style = SpotiFlyerTypography.subtitle2 - ) - } - } - Spacer(modifier = Modifier.padding(vertical = 16.dp)) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly, - modifier = Modifier.padding(horizontal = 4.dp).fillMaxWidth() - ) { - OutlinedButton(onClick = onDismiss) { - Text(Strings.dismiss()) - } - TextButton(onClick = onSnooze, colors = ButtonDefaults.buttonColors()) { - Text(Strings.remindLater()) - } - } - } - } - } - } -} diff --git a/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/configurations/AndroidTypography.kt b/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/configurations/AndroidTypography.kt new file mode 100644 index 00000000..c20dd9c7 --- /dev/null +++ b/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/configurations/AndroidTypography.kt @@ -0,0 +1,17 @@ +package com.shabinder.common.uikit.configurations + +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import com.shabinder.common.database.R + +actual fun montserratFont() = FontFamily( + Font(R.font.montserrat_light, FontWeight.Light), + Font(R.font.montserrat_regular, FontWeight.Normal), + Font(R.font.montserrat_medium, FontWeight.Medium), + Font(R.font.montserrat_semibold, FontWeight.SemiBold), +) + +actual fun pristineFont() = FontFamily( + Font(R.font.pristine_script, FontWeight.Bold) +) \ No newline at end of file diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectDialog.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectDialog.kt new file mode 100644 index 00000000..88d406ef --- /dev/null +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectDialog.kt @@ -0,0 +1,10 @@ +package com.shabinder.common.uikit + +import androidx.compose.runtime.Composable + +@Composable +expect fun Dialog( + isVisible: Boolean, + onDismiss: () -> Unit, + content: @Composable () -> Unit +) \ No newline at end of file diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImageLoad.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImageLoad.kt index 9c8cce2d..35e4ba46 100644 --- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImageLoad.kt +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImageLoad.kt @@ -8,7 +8,7 @@ import com.shabinder.common.di.Picture expect fun ImageLoad( link: String, loader: suspend () -> Picture, - desc: String = "Album Art", - modifier: Modifier = Modifier, + desc: String, + modifier: Modifier // placeholder:Painter = PlaceHolderImage() ) diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImages.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImages.kt index 2bdf26b0..0a3a410e 100644 --- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImages.kt +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImages.kt @@ -67,14 +67,7 @@ expect fun RazorPay(): Painter expect fun HeartIcon(): Painter @Composable -expect fun DownloadImageError() +expect fun DownloadImageError(modifier: Modifier) @Composable -expect fun DownloadImageArrow(modifier: Modifier) - -@Composable -expect fun DonationDialog( - isVisible: Boolean, - onDismiss: () -> Unit, - onSnooze: () -> Unit -) +expect fun DownloadImageArrow(modifier: Modifier) \ No newline at end of file diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/Color.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/configurations/Color.kt similarity index 97% rename from common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/Color.kt rename to common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/configurations/Color.kt index edef2cb4..41500af1 100644 --- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/Color.kt +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/configurations/Color.kt @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -package com.shabinder.common.uikit +package com.shabinder.common.uikit.configurations import androidx.compose.material.darkColors import androidx.compose.ui.graphics.Color diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/Shape.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/configurations/Shape.kt similarity index 95% rename from common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/Shape.kt rename to common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/configurations/Shape.kt index d37cbc51..726ed5bd 100644 --- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/Shape.kt +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/configurations/Shape.kt @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -package com.shabinder.common.uikit +package com.shabinder.common.uikit.configurations import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Shapes diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/Theme.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/configurations/Theme.kt similarity index 95% rename from common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/Theme.kt rename to common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/configurations/Theme.kt index fdf13ddf..77ef86ab 100644 --- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/Theme.kt +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/configurations/Theme.kt @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -package com.shabinder.common.uikit +package com.shabinder.common.uikit.configurations import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/Type.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/configurations/Type.kt similarity index 98% rename from common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/Type.kt rename to common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/configurations/Type.kt index b4140437..0159d15d 100644 --- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/Type.kt +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/configurations/Type.kt @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -package com.shabinder.common.uikit +package com.shabinder.common.uikit.configurations import androidx.compose.material.Typography import androidx.compose.ui.graphics.Color diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/dialogs/Donation.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/dialogs/Donation.kt index 7b7f3db7..a4c5f64a 100644 --- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/dialogs/Donation.kt +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/dialogs/Donation.kt @@ -1,17 +1,46 @@ package com.shabinder.common.uikit.dialogs +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.Card +import androidx.compose.material.Icon +import androidx.compose.material.OutlinedButton +import androidx.compose.material.Text +import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import com.shabinder.common.uikit.DonationDialog +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.shabinder.common.models.methods +import com.shabinder.common.translations.Strings +import com.shabinder.common.uikit.Dialog +import com.shabinder.common.uikit.OpenCollectiveLogo +import com.shabinder.common.uikit.PaypalLogo +import com.shabinder.common.uikit.RazorPay +import com.shabinder.common.uikit.configurations.SpotiFlyerTypography +import com.shabinder.common.uikit.configurations.colorAccent typealias DonationDialogCallBacks = Triple -private typealias openAction = () -> Unit -private typealias dismissAction = () -> Unit +internal typealias openAction = () -> Unit +internal typealias dismissAction = () -> Unit private typealias snoozeAction = () -> Unit +@OptIn(ExperimentalAnimationApi::class) @Composable fun DonationDialogComponent(onDismissExtra: () -> Unit): DonationDialogCallBacks { var isDonationDialogVisible by remember { mutableStateOf(false) } @@ -30,4 +59,112 @@ fun DonationDialogComponent(onDismissExtra: () -> Unit): DonationDialogCallBacks isDonationDialogVisible = false } return DonationDialogCallBacks(openDonationDialog,dismissDonationDialog,snoozeDonationDialog) -} \ No newline at end of file +} + +@ExperimentalAnimationApi +@Composable +fun DonationDialog( + isVisible: Boolean, + onDismiss: () -> Unit, + onSnooze: () -> Unit +) { + Dialog(isVisible,onDismiss) { + Card( + modifier = Modifier.fillMaxWidth(), + border = BorderStroke(1.dp, Color.Gray) // Gray + ) { + Column(Modifier.padding(16.dp)) { + Text( + Strings.supportUs(), + style = SpotiFlyerTypography.h5, + textAlign = TextAlign.Center, + color = colorAccent, + modifier = Modifier + ) + Spacer(modifier = Modifier.padding(vertical = 4.dp)) + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth().clickable( + onClick = { + onDismiss() + methods.value.openPlatform("", "https://opencollective.com/spotiflyer/donate") + } + ) + .padding(vertical = 6.dp) + ) { + Icon(OpenCollectiveLogo(), "Open Collective Logo", Modifier.size(24.dp), tint = Color(0xFFCCCCCC)) + Spacer(modifier = Modifier.padding(start = 16.dp)) + Column { + Text( + text = "Open Collective", + style = SpotiFlyerTypography.h6 + ) + Text( + text = Strings.worldWideDonations(), + style = SpotiFlyerTypography.subtitle2 + ) + } + } + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth().clickable( + onClick = { + onDismiss() + methods.value.openPlatform("", "https://www.paypal.com/paypalme/shabinder") + } + ) + .padding(vertical = 6.dp) + ) { + Icon(PaypalLogo(), "Paypal Logo", Modifier.size(24.dp), tint = Color(0xFFCCCCCC)) + Spacer(modifier = Modifier.padding(start = 16.dp)) + Column { + Text( + text = "Paypal", + style = SpotiFlyerTypography.h6 + ) + Text( + text = Strings.worldWideDonations(), + style = SpotiFlyerTypography.subtitle2 + ) + } + } + Row( + modifier = Modifier.fillMaxWidth().padding(top = 6.dp) + .clickable( + onClick = { + onDismiss() + methods.value.giveDonation() + } + ), + verticalAlignment = Alignment.CenterVertically + ) { + Icon(RazorPay(), "Indian Rupee Logo", Modifier.size(24.dp), tint = Color(0xFFCCCCCC)) + Spacer(modifier = Modifier.padding(start = 16.dp)) + Column { + Text( + text = "RazorPay", + style = SpotiFlyerTypography.h6 + ) + Text( + text = "${Strings.indianDonations()} (UPI / PayTM / PhonePe / Cards).", + style = SpotiFlyerTypography.subtitle2 + ) + } + } + Spacer(modifier = Modifier.padding(vertical = 16.dp)) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + modifier = Modifier.padding(horizontal = 4.dp).fillMaxWidth() + ) { + OutlinedButton(onClick = onDismiss) { + Text(Strings.dismiss()) + } + TextButton(onClick = onSnooze, colors = ButtonDefaults.buttonColors()) { + Text(Strings.remindLater()) + } + } + } + } + } +} diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/dialogs/ErrorInfoDialog.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/dialogs/ErrorInfoDialog.kt new file mode 100644 index 00000000..6e2a164e --- /dev/null +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/dialogs/ErrorInfoDialog.kt @@ -0,0 +1,79 @@ +package com.shabinder.common.uikit.dialogs + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.Card +import androidx.compose.material.Text +import androidx.compose.material.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.shabinder.common.models.methods +import com.shabinder.common.translations.Strings +import com.shabinder.common.uikit.Dialog +import com.shabinder.common.uikit.configurations.SpotiFlyerTypography +import com.shabinder.common.uikit.configurations.colorAccent + +typealias ErrorInfoDialogCallBacks = Pair + +@Composable +fun ErrorInfoDialog(error: Throwable): ErrorInfoDialogCallBacks { + var isErrorDialogVisible by remember { mutableStateOf(false) } + val onDismissDialog = { isErrorDialogVisible = false } + val openErrorDialog = { isErrorDialogVisible = true } + + Dialog(isErrorDialogVisible, onDismissDialog) { + Card( + modifier = Modifier.fillMaxWidth(), + border = BorderStroke(1.dp, Color.Gray) // Gray + ) { + Column(Modifier.padding(16.dp)) { + Text( + Strings.whatWentWrong(), + style = SpotiFlyerTypography.h5, + textAlign = TextAlign.Center, + color = colorAccent, + modifier = Modifier.padding(vertical = 4.dp).fillMaxWidth() + ) + + Spacer(Modifier.padding(top = 4.dp)) + Text(Strings.copyCodeInGithubIssue(), fontWeight = FontWeight.SemiBold) + + SelectionContainer(Modifier.padding(vertical = 8.dp).verticalScroll(rememberScrollState()).weight(1f)) { + Text(error.stackTraceToString(), fontWeight = FontWeight.Light) + } + Row( + Modifier.padding(top = 8.dp).fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly + ) { + TextButton(onClick = onDismissDialog, colors = ButtonDefaults.buttonColors()) { + Text(Strings.dismiss()) + } + TextButton(onClick = { methods.value.copyToClipboard(error.stackTraceToString()) }, colors = ButtonDefaults.buttonColors()) { + Text(Strings.copyToClipboard()) + } + } + } + } + } + + return ErrorInfoDialogCallBacks(openErrorDialog,onDismissDialog) +} \ No newline at end of file diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/SpotiFlyerListUi.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/SpotiFlyerListUi.kt similarity index 85% rename from common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/SpotiFlyerListUi.kt rename to common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/SpotiFlyerListUi.kt index 006d2054..366b9e13 100644 --- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/SpotiFlyerListUi.kt +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/SpotiFlyerListUi.kt @@ -14,8 +14,9 @@ * * along with this program. If not, see . */ -package com.shabinder.common.uikit +package com.shabinder.common.uikit.screens +import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -27,6 +28,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed @@ -37,6 +39,8 @@ import androidx.compose.material.ExtendedFloatingActionButton import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.Info import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -55,7 +59,20 @@ import com.shabinder.common.models.DownloadStatus import com.shabinder.common.models.TrackDetails import com.shabinder.common.models.methods import com.shabinder.common.translations.Strings +import com.shabinder.common.uikit.DownloadAllImage +import com.shabinder.common.uikit.DownloadImageArrow +import com.shabinder.common.uikit.DownloadImageError +import com.shabinder.common.uikit.DownloadImageTick +import com.shabinder.common.uikit.ImageLoad +import com.shabinder.common.uikit.VerticalScrollbar +import com.shabinder.common.uikit.configurations.SpotiFlyerTypography +import com.shabinder.common.uikit.configurations.appNameStyle +import com.shabinder.common.uikit.configurations.colorAccent +import com.shabinder.common.uikit.configurations.colorPrimary +import com.shabinder.common.uikit.configurations.lightGray import com.shabinder.common.uikit.dialogs.DonationDialogComponent +import com.shabinder.common.uikit.dialogs.ErrorInfoDialog +import com.shabinder.common.uikit.rememberScrollbarAdapter @OptIn(ExperimentalMaterialApi::class) @Composable @@ -133,6 +150,7 @@ fun SpotiFlyerListContent( } } +@OptIn(ExperimentalAnimationApi::class) @Composable fun TrackCard( track: TrackDetails, @@ -168,7 +186,19 @@ fun TrackCard( CircularProgressIndicator() } is DownloadStatus.Failed -> { - DownloadImageError() + val (openErrorDialog,dismissErrorDialog) = ErrorInfoDialog((track.downloaded as DownloadStatus.Failed).error) + + Icon(Icons.Rounded.Info,Strings.downloadError(),tint = lightGray,modifier = Modifier.size(42.dp).clickable { + openErrorDialog() + }.padding(start = 4.dp,end = 12.dp)) + + DownloadImageError( + Modifier.clickable( + onClick = { + downloadTrack() + } + ) + ) } is DownloadStatus.Downloading -> { CircularProgressIndicator(progress = (track.downloaded as DownloadStatus.Downloading).progress.toFloat() / 100f) diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/SpotiFlyerMainUi.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/SpotiFlyerMainUi.kt similarity index 96% rename from common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/SpotiFlyerMainUi.kt rename to common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/SpotiFlyerMainUi.kt index 76ee29f5..e227afec 100644 --- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/SpotiFlyerMainUi.kt +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/SpotiFlyerMainUi.kt @@ -14,7 +14,7 @@ * * along with this program. If not, see . */ -package com.shabinder.common.uikit +package com.shabinder.common.uikit.screens import androidx.compose.animation.Crossfade import androidx.compose.foundation.BorderStroke @@ -84,7 +84,23 @@ import com.shabinder.common.main.SpotiFlyerMain.HomeCategory import com.shabinder.common.models.DownloadRecord import com.shabinder.common.models.methods import com.shabinder.common.translations.Strings +import com.shabinder.common.uikit.GaanaLogo +import com.shabinder.common.uikit.GithubLogo +import com.shabinder.common.uikit.ImageLoad +import com.shabinder.common.uikit.SaavnLogo +import com.shabinder.common.uikit.ShareImage +import com.shabinder.common.uikit.SpotifyLogo +import com.shabinder.common.uikit.VerticalScrollbar +import com.shabinder.common.uikit.YoutubeLogo +import com.shabinder.common.uikit.YoutubeMusicLogo +import com.shabinder.common.uikit.configurations.SpotiFlyerShapes +import com.shabinder.common.uikit.configurations.SpotiFlyerTypography +import com.shabinder.common.uikit.configurations.colorAccent +import com.shabinder.common.uikit.configurations.colorOffWhite +import com.shabinder.common.uikit.configurations.colorPrimary +import com.shabinder.common.uikit.configurations.transparent import com.shabinder.common.uikit.dialogs.DonationDialogComponent +import com.shabinder.common.uikit.rememberScrollbarAdapter @Composable fun SpotiFlyerMainContent(component: SpotiFlyerMain) { diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/SpotiFlyerRootUi.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/SpotiFlyerRootUi.kt similarity index 94% rename from common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/SpotiFlyerRootUi.kt rename to common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/SpotiFlyerRootUi.kt index ad0112b6..6b842b48 100644 --- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/SpotiFlyerRootUi.kt +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/SpotiFlyerRootUi.kt @@ -16,7 +16,7 @@ @file:Suppress("EXPERIMENTAL_API_USAGE") -package com.shabinder.common.uikit +package com.shabinder.common.uikit.screens import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.ExperimentalAnimationApi @@ -60,8 +60,13 @@ import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState import com.shabinder.common.root.SpotiFlyerRoot import com.shabinder.common.root.SpotiFlyerRoot.Child import com.shabinder.common.translations.Strings -import com.shabinder.common.uikit.splash.Splash -import com.shabinder.common.uikit.splash.SplashState +import com.shabinder.common.uikit.SpotiFlyerLogo +import com.shabinder.common.uikit.Toast +import com.shabinder.common.uikit.ToastDuration +import com.shabinder.common.uikit.configurations.appNameStyle +import com.shabinder.common.uikit.configurations.colorPrimaryDark +import com.shabinder.common.uikit.screens.splash.Splash +import com.shabinder.common.uikit.screens.splash.SplashState import com.shabinder.common.uikit.utils.verticalGradientScrim // To Not Show Splash Again After Configuration Change in Android diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/splash/Splash.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/splash/Splash.kt similarity index 93% rename from common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/splash/Splash.kt rename to common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/splash/Splash.kt index 6632031e..40aaace5 100644 --- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/splash/Splash.kt +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/splash/Splash.kt @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -package com.shabinder.common.uikit.splash +package com.shabinder.common.uikit.screens.splash import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement @@ -38,9 +38,9 @@ import androidx.compose.ui.unit.sp import com.shabinder.common.translations.Strings import com.shabinder.common.uikit.HeartIcon import com.shabinder.common.uikit.SpotiFlyerLogo -import com.shabinder.common.uikit.SpotiFlyerTypography -import com.shabinder.common.uikit.colorAccent -import com.shabinder.common.uikit.colorPrimary +import com.shabinder.common.uikit.configurations.SpotiFlyerTypography +import com.shabinder.common.uikit.configurations.colorAccent +import com.shabinder.common.uikit.configurations.colorPrimary import kotlinx.coroutines.delay private const val SplashWaitTime: Long = 2000 diff --git a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopDialog.kt b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopDialog.kt new file mode 100644 index 00000000..6a90d3db --- /dev/null +++ b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopDialog.kt @@ -0,0 +1,19 @@ +package com.shabinder.common.uikit + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.runtime.Composable + +@OptIn(ExperimentalAnimationApi::class) +@Composable +actual fun Dialog( + isVisible: Boolean, + onDismiss: () -> Unit, + content: @Composable () -> Unit +) { + AnimatedVisibility(isVisible) { + androidx.compose.ui.window.v1.Dialog(onDismiss) { + content() + } + } +} \ No newline at end of file diff --git a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImageLoad.kt b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImageLoad.kt index 045da16d..9823c627 100644 --- a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImageLoad.kt +++ b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImageLoad.kt @@ -20,7 +20,7 @@ actual fun ImageLoad( link: String, loader: suspend () -> Picture, desc: String, - modifier: Modifier, + modifier: Modifier // placeholder: ImageVector ) { var pic by remember(link) { mutableStateOf(null) } diff --git a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImages.kt b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImages.kt index d5e9625d..b0403d07 100644 --- a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImages.kt +++ b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImages.kt @@ -19,15 +19,10 @@ package com.shabinder.common.uikit import androidx.compose.foundation.Image import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.res.vectorXmlResource -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.platform.Font @Composable actual fun DownloadImageTick() { @@ -37,22 +32,12 @@ actual fun DownloadImageTick() { ) } -actual fun montserratFont() = FontFamily( - Font("font/montserrat_light.ttf", FontWeight.Light), - Font("font/montserrat_regular.ttf", FontWeight.Normal), - Font("font/montserrat_medium.ttf", FontWeight.Medium), - Font("font/montserrat_semibold.ttf", FontWeight.SemiBold), -) - -actual fun pristineFont() = FontFamily( - Font("font/pristine_script.ttf", FontWeight.Bold) -) - @Composable -actual fun DownloadImageError() { +actual fun DownloadImageError(modifier: Modifier) { Image( vectorXmlResource("drawable/ic_error.xml"), - "Can't Download" + "Can't Download", + modifier = modifier ) } diff --git a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopToast.kt b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopToast.kt index f766237f..1b575d5d 100644 --- a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopToast.kt +++ b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopToast.kt @@ -39,6 +39,8 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import com.shabinder.common.uikit.configurations.SpotiFlyerTypography +import com.shabinder.common.uikit.configurations.colorOffWhite import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow diff --git a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DonationDialog.kt b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DonationDialog.kt deleted file mode 100644 index e0e692e2..00000000 --- a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DonationDialog.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.shabinder.common.uikit - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material.Card -import androidx.compose.material.Icon -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.v1.Dialog -import com.shabinder.common.models.methods -import com.shabinder.common.translations.Strings - -@OptIn(ExperimentalAnimationApi::class, androidx.compose.ui.ExperimentalComposeUiApi::class) -@Composable -actual fun DonationDialog( - isVisible: Boolean, - onDismiss: () -> Unit, - onSnooze: () -> Unit -) { - AnimatedVisibility( - isVisible - ) { - - Dialog(onDismiss) { - Card( - modifier = Modifier.fillMaxSize(), - border = BorderStroke(1.dp, Color.Gray) // Gray - ) { - Column(Modifier.padding(16.dp)) { - Text( - Strings.supportUs(), - style = SpotiFlyerTypography.h5, - textAlign = TextAlign.Center, - color = colorAccent, - modifier = Modifier - ) - Spacer(modifier = Modifier.padding(vertical = 4.dp)) - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth().clickable( - onClick = { - onDismiss() - methods.value.openPlatform("", "https://www.paypal.com/paypalme/shabinder") - } - ) - .padding(vertical = 6.dp) - ) { - Icon(PaypalLogo(), "Paypal Logo", tint = Color(0xFFCCCCCC)) - Spacer(modifier = Modifier.padding(start = 16.dp)) - Column { - Text( - text = "Paypal", - style = SpotiFlyerTypography.h6 - ) - Text( - text = Strings.worldWideDonations(), - style = SpotiFlyerTypography.subtitle2 - ) - } - } - Row( - modifier = Modifier.fillMaxWidth().padding(top = 6.dp) - .clickable( - onClick = { - onDismiss() - methods.value.giveDonation() - } - ), - verticalAlignment = Alignment.CenterVertically - ) { - Icon(RazorPay(), "Indian Rupee Logo", Modifier.size(32.dp), tint = Color(0xFFCCCCCC)) - Spacer(modifier = Modifier.padding(start = 16.dp)) - Column { - Text( - text = "RazorPay", - style = SpotiFlyerTypography.h6 - ) - Text( - text = "${Strings.indianDonations()} (UPI / PayTM / PhonePe / Cards).", - style = SpotiFlyerTypography.subtitle2 - ) - } - } - } - } - } - } -} diff --git a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/configurations/DesktopTypography.kt b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/configurations/DesktopTypography.kt new file mode 100644 index 00000000..9928136b --- /dev/null +++ b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/configurations/DesktopTypography.kt @@ -0,0 +1,17 @@ +package com.shabinder.common.uikit.configurations + +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.platform.Font + + +actual fun montserratFont() = FontFamily( + Font("font/montserrat_light.ttf", FontWeight.Light), + Font("font/montserrat_regular.ttf", FontWeight.Normal), + Font("font/montserrat_medium.ttf", FontWeight.Medium), + Font("font/montserrat_semibold.ttf", FontWeight.SemiBold), +) + +actual fun pristineFont() = FontFamily( + Font("font/pristine_script.ttf", FontWeight.Bold) +) \ No newline at end of file diff --git a/common/data-models/build.gradle.kts b/common/data-models/build.gradle.kts index 2499b0ad..1abae967 100644 --- a/common/data-models/build.gradle.kts +++ b/common/data-models/build.gradle.kts @@ -31,7 +31,7 @@ val statelyIsoVersion = "1.1.7-a1" i18n4k { inputDirectory = "../../translations" packageName = "com.shabinder.common.translations" - // sourceCodeLocales = listOf("en", "de") + // sourceCodeLocales = listOf("en", "de", "es", "fr", "id", "pt", "ru", "uk") } kotlin { diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/Actions.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/Actions.kt index 016d0d4b..6a9d8988 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/Actions.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/Actions.kt @@ -36,6 +36,9 @@ interface Actions { // Share SpotiFlyer App fun shareApp() + // Copy to Clipboard + fun copyToClipboard(text: String) + // Open / Redirect to another Platform fun openPlatform(packageID: String, platformLink: String) fun writeMp3Tags(trackDetails: TrackDetails) @@ -48,6 +51,8 @@ private fun stubActions(): Actions = object : Actions { override fun queryActiveTracks() {} override fun giveDonation() {} override fun shareApp() {} + override fun copyToClipboard(text: String) {} + override fun openPlatform(packageID: String, platformLink: String) {} override fun writeMp3Tags(trackDetails: TrackDetails) {} diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/SpotiFlyerException.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/SpotiFlyerException.kt index 2af34bd1..19167089 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/SpotiFlyerException.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/SpotiFlyerException.kt @@ -32,8 +32,8 @@ sealed class SpotiFlyerException(override val message: String): Exception(messag val jioSaavnError: Throwable, val ytMusicError: Throwable, override val message: String = "${Strings.noLinkFound()}: $trackName," + - " \n JioSaavn Error's StackTrace: ${jioSaavnError.stackTraceToString()} \n " + - " \n YtMusic Error's StackTrace: ${ytMusicError.stackTraceToString()} \n " + " \n YtMusic Error's StackTrace: ${ytMusicError.stackTraceToString()} \n " + + " \n JioSaavn Error's StackTrace: ${jioSaavnError.stackTraceToString()} \n " ): SpotiFlyerException(message) data class LinkInvalid( diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/event/coroutines/SuspendableEvent.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/event/coroutines/SuspendableEvent.kt index bd6485b2..13f62b0d 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/event/coroutines/SuspendableEvent.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/event/coroutines/SuspendableEvent.kt @@ -1,3 +1,5 @@ +@file:Suppress("UNCHECKED_CAST") + package com.shabinder.common.models.event.coroutines import kotlin.properties.ReadOnlyProperty diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/FetchPlatformQueryResult.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/FetchPlatformQueryResult.kt index b7eabb08..2729639c 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/FetchPlatformQueryResult.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/FetchPlatformQueryResult.kt @@ -101,6 +101,7 @@ class FetchPlatformQueryResult( } Source.YouTube -> { youtubeMp3.getMp3DownloadLink(track.videoID.requireNotNull()).flatMapError { + logger.e("Yt1sMp3 Failed") { it.message ?: "couldn't fetch link for ${track.videoID} ,trying manual extraction" } youtubeProvider.ytDownloader.getVideo(track.videoID!!).get()?.url?.let { m4aLink -> audioToMp3.convertToMp3(m4aLink) } ?: throw SpotiFlyerException.YoutubeLinkNotFound(track.videoID) @@ -130,8 +131,8 @@ class FetchPlatformQueryResult( SuspendableEvent.error( SpotiFlyerException.DownloadLinkFetchFailed( trackName = track.title, - jioSaavnError = saavnError, - ytMusicError = ytMusicError + ytMusicError = ytMusicError, + jioSaavnError = saavnError ) ) } diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/YoutubeMusic.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/YoutubeMusic.kt index 0949226e..ac311a1b 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/YoutubeMusic.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/YoutubeMusic.kt @@ -303,7 +303,7 @@ class YoutubeMusic constructor( } // logger.d("YT Api Result"){"$trackName - $linksWithMatchValue"} return linksWithMatchValue.toList().sortedByDescending { it.second }.toMap().also { - logger.d(tag) { "Match Found for $trackName - ${!it.isNullOrEmpty()}" } + logger.d(tag) { "Match Found for $trackName - ${!it.isNullOrEmpty()} ${it.keys.firstOrNull() ?: ""}" } } } diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/saavn/JioSaavnRequests.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/saavn/JioSaavnRequests.kt index b3b59ecf..b445a923 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/saavn/JioSaavnRequests.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/saavn/JioSaavnRequests.kt @@ -243,7 +243,7 @@ interface JioSaavnRequests { // Skip this Result if No Word is Common in Name if (!hasCommonWord) { - logger.i("Saavn Removing Common Word") { result.toString() } + // logger.i("Saavn Removing Common Word") { result.toString() } continue } @@ -264,7 +264,7 @@ interface JioSaavnRequests { } if (artistMatchNumber == 0) { - logger.i("Artist Match Saavn Removing") { result.toString() } + // logger.i("Artist Match Saavn Removing") { result.toString() } continue } val artistMatch: Float = (artistMatchNumber.toFloat() / trackArtists.size) * 100 @@ -274,11 +274,12 @@ interface JioSaavnRequests { linksWithMatchValue[result.id] = avgMatch } return linksWithMatchValue.toList().sortedByDescending { it.second }.toMap().also { - logger.i { "Match Found for $trackName - ${!it.isNullOrEmpty()}" } + logger.i(TAG) { "Match Found for $trackName - ${!it.isNullOrEmpty()} ${it.keys.firstOrNull() ?: ""}" } } } companion object { + const val TAG = "Saavn Request" // EndPoints val search_base_url = "${corsApi}https://www.jiosaavn.com/api.php?__call=autocomplete.get&_format=json&_marker=0&cc=in&includeMetaTags=1&query=" val song_details_base_url = "${corsApi}https://www.jiosaavn.com/api.php?__call=song.getDetails&cc=in&_marker=0%3F_marker%3D0&_format=json&pids=" diff --git a/common/root/src/commonMain/kotlin/com/shabinder/common/root/integration/SpotiFlyerRootImpl.kt b/common/root/src/commonMain/kotlin/com/shabinder/common/root/integration/SpotiFlyerRootImpl.kt index 96ea55ac..bc062ff7 100644 --- a/common/root/src/commonMain/kotlin/com/shabinder/common/root/integration/SpotiFlyerRootImpl.kt +++ b/common/root/src/commonMain/kotlin/com/shabinder/common/root/integration/SpotiFlyerRootImpl.kt @@ -76,6 +76,7 @@ internal class SpotiFlyerRootImpl( ) { instanceKeeper.ensureNeverFrozen() methods.value = dependencies.actions.freeze() + /*Init App Launch & Authenticate Spotify Client*/ initAppLaunchAndAuthenticateSpotify(dependencies.fetchQuery::authenticateSpotifyClient) } diff --git a/console-app/build.gradle.kts b/console-app/build.gradle.kts index ec9a4d43..48966a03 100644 --- a/console-app/build.gradle.kts +++ b/console-app/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - kotlin("jvm")// version "1.4.32" + kotlin("jvm") kotlin("plugin.serialization") id("ktlint-setup") id("com.jakewharton.mosaic") diff --git a/console-app/src/main/java/main.kt b/console-app/src/main/java/main.kt index 62c5bdea..0e018cd8 100644 --- a/console-app/src/main/java/main.kt +++ b/console-app/src/main/java/main.kt @@ -5,7 +5,7 @@ import com.jakewharton.mosaic.Text import com.jakewharton.mosaic.runMosaic import kotlinx.coroutines.delay -fun main(/*args: Array*/) = runMosaic { +fun main() = runMosaic { // TODO https://github.com/JakeWharton/mosaic/issues/3 var count by mutableStateOf(0) diff --git a/desktop/src/jvmMain/kotlin/Main.kt b/desktop/src/jvmMain/kotlin/Main.kt index 684b635b..227a996f 100644 --- a/desktop/src/jvmMain/kotlin/Main.kt +++ b/desktop/src/jvmMain/kotlin/Main.kt @@ -37,21 +37,25 @@ 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.common.uikit.SpotiFlyerColors -import com.shabinder.common.uikit.SpotiFlyerRootContent -import com.shabinder.common.uikit.SpotiFlyerShapes -import com.shabinder.common.uikit.SpotiFlyerTypography -import com.shabinder.common.uikit.colorOffWhite +import com.shabinder.common.uikit.configurations.SpotiFlyerColors +import com.shabinder.common.uikit.configurations.SpotiFlyerShapes +import com.shabinder.common.uikit.configurations.SpotiFlyerTypography +import com.shabinder.common.uikit.configurations.colorOffWhite +import com.shabinder.common.uikit.screens.SpotiFlyerRootContent import com.shabinder.database.Database import kotlinx.coroutines.runBlocking import org.piwik.java.tracking.PiwikTracker import utils.trackAsync import utils.trackScreenAsync import java.awt.Desktop +import java.awt.Toolkit +import java.awt.datatransfer.Clipboard +import java.awt.datatransfer.StringSelection import java.net.URI import javax.swing.JFileChooser import javax.swing.JFileChooser.APPROVE_OPTION + private val koin = initKoin(enableNetworkLogs = true).koin private lateinit var showToast: (String)->Unit private val tracker: PiwikTracker by lazy { @@ -129,6 +133,11 @@ private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot = } override fun shareApp() = openLink("https://github.com/Shabinder/SpotiFlyer") + override fun copyToClipboard(text: String) { + val data = StringSelection(text) + val cb: Clipboard = Toolkit.getDefaultToolkit().systemClipboard + cb.setContents(data, data) + } override fun openPlatform(packageID: String, platformLink: String) = openLink(platformLink) diff --git a/settings.gradle.kts b/settings.gradle.kts index a8b58618..c2cd3240 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -31,11 +31,3 @@ include( ":console-app", ":maintenance-tasks" ) - -includeBuild("mosaic/mosaic") { - dependencySubstitution { - substitute(module("com.jakewharton.mosaic:mosaic-gradle-plugin")).with(project(":mosaic-gradle-plugin")) - substitute(module("com.jakewharton.mosaic:mosaic-runtime")).with(project(":mosaic-runtime")) - substitute(module("com.jakewharton.mosaic:compose-compiler")).with(project(":compose:compiler")) - } -} diff --git a/translations/Strings_de.properties b/translations/Strings_de.properties index 54e4354a..427e4d02 100644 --- a/translations/Strings_de.properties +++ b/translations/Strings_de.properties @@ -15,6 +15,9 @@ supportDeveloper = Entwickler untestützen donateDescription = Wenn du denkst, dass ich verdiene für meine Arbeit bezahlt zu werden, können sie mich hier unterstützen.If you think I deserve to get paid for my work, you can support me here. share = Teilen shareDescription = Teile diese App mit deiner Familie und deinen Freunden. +whatWentWrong = Was schief gelaufen ist... +copyToClipboard = In die Zwischenablage kopieren +copyCodeInGithubIssue = Kopieren Sie Einfügen unterhalb des Codes, während Sie ein Github-Problem erstellen / Dieses Problem melden, um bessere Hilfe zu erhalten. status = Status analytics = Analyse analyticsDescription = Deine Daten sind Anonym und werden nie mit Drittanbietern geteilt. diff --git a/translations/Strings_en.properties b/translations/Strings_en.properties index 18f4ef15..234f616c 100644 --- a/translations/Strings_en.properties +++ b/translations/Strings_en.properties @@ -15,6 +15,9 @@ supportDeveloper = Support Developer donateDescription = If you think I deserve to get paid for my work, you can support me here. share = Share shareDescription = Share this app with your friends and family. +whatWentWrong = What Went Wrong... +copyToClipboard = Copy to Clipboard +copyCodeInGithubIssue = Copy Paste Below Code while creating Github Issue / Reporting this issue for better help. status = Status analytics = Analytics analyticsDescription = Your Data is Anonymized and never shared with 3rd party service. diff --git a/translations/Strings_es.properties b/translations/Strings_es.properties index b6c5daf2..f769b11a 100644 --- a/translations/Strings_es.properties +++ b/translations/Strings_es.properties @@ -15,6 +15,9 @@ supportDeveloper = Apoya al desarollador donateDescription = Si crees que merezco una paga por mi trabajo, aquí puedes apoyarme. share = Comparte shareDescription = Comparte esta aplicación con tus familiares y amigos. +whatWentWrong = Qué salió mal... +copyToClipboard = Copiar al portapapeles +copyCodeInGithubIssue = Copie Pegar debajo del código mientras crea Github Issue / Reportando este problema para obtener una mejor ayuda. status = Estatus analytics = Analiticos analyticsDescription = Tus datos son anonimizados y nunca se compartiran con servicios de terceros. diff --git a/translations/Strings_fr.properties b/translations/Strings_fr.properties index d7ba5a18..e7fcee10 100644 --- a/translations/Strings_fr.properties +++ b/translations/Strings_fr.properties @@ -15,6 +15,9 @@ supportDeveloper = Soutenir le Développeur donateDescription = Si vous pensez que je mérite d'être payé pour mon travail, vous pouvez me soutenir ici. share = Partager shareDescription = Partagez cette application avec vos amis et votre famille. +whatWentWrong = Qu'est ce qui ne s'est pas bien passé... +copyToClipboard = Copier dans le presse-papier +copyCodeInGithubIssue = Copiez et collez le code ci-dessous lors de la création d'un problème Github / Signalement de ce problème pour une meilleure aide. status = Statut analytics = Analyses analyticsDescription = Vos données sont anonymes et ne sont jamais partagées avec des services tiers. diff --git a/translations/Strings_id.properties b/translations/Strings_id.properties index 1b64db5e..de000ca0 100644 --- a/translations/Strings_id.properties +++ b/translations/Strings_id.properties @@ -15,6 +15,9 @@ supportDeveloper = Dukung Developer donateDescription = Jika Anda ingin memberi donasi ke developer apl. ini, Anda bisa donasi disini. share = Bagikan shareDescription = Bagikan aplikasi ini kepada teman / keluarga anda. +whatWentWrong = Apa yang salah... +copyToClipboard = Menyalin ke clipboard +copyCodeInGithubIssue = Salin Tempel Kode Di Bawah Saat membuat Masalah Github / Melaporkan masalah ini untuk bantuan yang lebih baik. status = Status analytics = Analytics analyticsDescription = Data Anda tidak dapat dilihat oleh orang lain dan TIDAK akan dibagikan ke pihak ketiga. diff --git a/translations/Strings_pt.properties b/translations/Strings_pt.properties index 72c0291b..a544fc6e 100644 --- a/translations/Strings_pt.properties +++ b/translations/Strings_pt.properties @@ -15,6 +15,9 @@ supportDeveloper = Ajude o Desenvolvedor donateDescription = Se você acha que mereço ser pago pelo meu trabalho, você pode me ajudar aqui. share = Compartilhar shareDescription = Compartilhe este app com seus amigos e família. +whatWentWrong = O que deu errado... +copyToClipboard = Copiar para área de transferência +copyCodeInGithubIssue = Copiar e colar abaixo do código ao criar o problema no Github / relatar esse problema para obter ajuda melhor. status = Status analytics = Estatísticas analyticsDescription = Seus dados serão tornados anônimos e nunca serão compartilhados com serviços de terceiros. diff --git a/translations/Strings_ru.properties b/translations/Strings_ru.properties index d359a77b..e62a697b 100644 --- a/translations/Strings_ru.properties +++ b/translations/Strings_ru.properties @@ -15,6 +15,9 @@ supportDeveloper = Поддержи разработчика donateDescription = Если считаешь, что я заслуживаю этого, ты можешь поддержать меня здесь. share = Поделиться shareDescription = Расскажи об этом приложении знакомым - поделись полезным инструментом. +whatWentWrong = Что пошло не так... +copyToClipboard = Скопировать в буфер обмена +copyCodeInGithubIssue = Скопируйте вставьте ниже код при создании проблемы Github / Сообщите об этой проблеме для лучшей помощи. status = Статус analytics = Аналитика analyticsDescription = Предоставить анонимные данные для улучшения приложения. Они не будут переданы третьим лицам. diff --git a/translations/Strings_uk.properties b/translations/Strings_uk.properties index ede0af19..a6a11aa4 100644 --- a/translations/Strings_uk.properties +++ b/translations/Strings_uk.properties @@ -15,6 +15,9 @@ supportDeveloper = Підтримати розробника donateDescription = Якщо ви вважаєте, що я заслуговую на отримання грошей за свою роботу, ви можете підтримати мене тут. share = Поділитися shareDescription = Поділися цією програмою зі своїми друзями та родиною. +whatWentWrong = Що пішло не так... +copyToClipboard = Копіювати в буфер обміну +copyCodeInGithubIssue = Скопіюйте вставку нижче коду під час створення випуску Github / звітування про цю проблему, щоб отримати кращу допомогу. status = Статус analytics = Аналіз analyticsDescription = Ваші дані анонімні та ніколи не передаються стороннім сервісам. diff --git a/web-app/src/main/kotlin/App.kt b/web-app/src/main/kotlin/App.kt index 785c1785..42c46f28 100644 --- a/web-app/src/main/kotlin/App.kt +++ b/web-app/src/main/kotlin/App.kt @@ -71,6 +71,8 @@ class App(props: AppProps): RComponent(props) { /*TODO("Not yet implemented")*/ } + override fun copyToClipboard(text: String) {} + override fun setDownloadDirectoryAction() {} override fun queryActiveTracks() {}