mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-11-27 19:04:32 +01:00
Some more translations, ErrorInfoDialog and Refactoring
This commit is contained in:
parent
fc9355269a
commit
9881cc55aa
@ -49,7 +49,7 @@
|
|||||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:largeHeap="true"
|
android:largeHeap="true"
|
||||||
android:label="@string/app_name"
|
android:label="SpotiFlyer"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:forceDarkAllowed="true"
|
android:forceDarkAllowed="true"
|
||||||
@ -57,7 +57,7 @@
|
|||||||
tools:targetApi="q">
|
tools:targetApi="q">
|
||||||
<activity android:name=".MainActivity"
|
<activity android:name=".MainActivity"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:label="@string/app_name"
|
android:label="SpotiFlyer"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:theme="@style/Theme.SpotiFlyer"
|
android:theme="@style/Theme.SpotiFlyer"
|
||||||
>
|
>
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
package com.shabinder.spotiflyer
|
package com.shabinder.spotiflyer
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@ -31,11 +33,20 @@ import android.os.PowerManager
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.compose.animation.*
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.material.*
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.runtime.*
|
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.Modifier
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.core.content.ContextCompat
|
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.navigationBarsPadding
|
||||||
import com.google.accompanist.insets.statusBarsHeight
|
import com.google.accompanist.insets.statusBarsHeight
|
||||||
import com.google.accompanist.insets.statusBarsPadding
|
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.di.preference.PreferenceManager
|
||||||
import com.shabinder.common.models.Actions
|
import com.shabinder.common.models.Actions
|
||||||
import com.shabinder.common.models.DownloadStatus
|
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.SpotiFlyerRoot.Analytics
|
||||||
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
||||||
import com.shabinder.common.translations.Strings
|
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.service.ForegroundService
|
||||||
import com.shabinder.spotiflyer.ui.AnalyticsDialog
|
import com.shabinder.spotiflyer.ui.AnalyticsDialog
|
||||||
import com.shabinder.spotiflyer.ui.NetworkDialog
|
import com.shabinder.spotiflyer.ui.NetworkDialog
|
||||||
import com.shabinder.spotiflyer.ui.PermissionDialog
|
import com.shabinder.spotiflyer.ui.PermissionDialog
|
||||||
import com.shabinder.spotiflyer.utils.*
|
import com.shabinder.spotiflyer.utils.checkAppSignature
|
||||||
import kotlinx.coroutines.*
|
import com.shabinder.spotiflyer.utils.checkIfLatestVersion
|
||||||
import kotlinx.coroutines.flow.*
|
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.koin.android.ext.android.inject
|
||||||
import org.matomo.sdk.extra.TrackHelper
|
import org.matomo.sdk.extra.TrackHelper
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
@ExperimentalAnimationApi
|
@ExperimentalAnimationApi
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
@ -295,6 +319,14 @@ class MainActivity : ComponentActivity() {
|
|||||||
startActivity(shareIntent)
|
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) {
|
override fun openPlatform(packageID: String, platformLink: String) {
|
||||||
val manager: PackageManager = applicationContext.packageManager
|
val manager: PackageManager = applicationContext.packageManager
|
||||||
try {
|
try {
|
||||||
|
@ -27,9 +27,9 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import com.shabinder.common.translations.Strings
|
import com.shabinder.common.translations.Strings
|
||||||
import com.shabinder.common.uikit.SpotiFlyerShapes
|
import com.shabinder.common.uikit.configurations.SpotiFlyerShapes
|
||||||
import com.shabinder.common.uikit.SpotiFlyerTypography
|
import com.shabinder.common.uikit.configurations.SpotiFlyerTypography
|
||||||
import com.shabinder.common.uikit.colorPrimary
|
import com.shabinder.common.uikit.configurations.colorPrimary
|
||||||
|
|
||||||
@ExperimentalAnimationApi
|
@ExperimentalAnimationApi
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -44,9 +44,9 @@ import androidx.compose.ui.graphics.ColorFilter
|
|||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.shabinder.common.translations.Strings
|
import com.shabinder.common.translations.Strings
|
||||||
import com.shabinder.common.uikit.SpotiFlyerShapes
|
import com.shabinder.common.uikit.configurations.SpotiFlyerShapes
|
||||||
import com.shabinder.common.uikit.SpotiFlyerTypography
|
import com.shabinder.common.uikit.configurations.SpotiFlyerTypography
|
||||||
import com.shabinder.common.uikit.colorOffWhite
|
import com.shabinder.common.uikit.configurations.colorOffWhite
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
@ExperimentalAnimationApi
|
@ExperimentalAnimationApi
|
||||||
@ -88,7 +88,8 @@ fun NetworkDialog(
|
|||||||
) {
|
) {
|
||||||
Image(Icons.Rounded.CloudOff,
|
Image(Icons.Rounded.CloudOff,
|
||||||
Strings.noInternetConnection(),Modifier.size(42.dp),colorFilter = ColorFilter.tint(
|
Strings.noInternetConnection(),Modifier.size(42.dp),colorFilter = ColorFilter.tint(
|
||||||
colorOffWhite))
|
colorOffWhite
|
||||||
|
))
|
||||||
Spacer(modifier = Modifier.padding(start = 16.dp))
|
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||||
Text(
|
Text(
|
||||||
text = Strings.checkInternetConnection(),
|
text = Strings.checkInternetConnection(),
|
||||||
|
@ -29,9 +29,9 @@ import androidx.compose.ui.text.style.TextAlign
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.shabinder.common.translations.Strings
|
import com.shabinder.common.translations.Strings
|
||||||
import com.shabinder.common.uikit.SpotiFlyerShapes
|
import com.shabinder.common.uikit.configurations.SpotiFlyerShapes
|
||||||
import com.shabinder.common.uikit.SpotiFlyerTypography
|
import com.shabinder.common.uikit.configurations.SpotiFlyerTypography
|
||||||
import com.shabinder.common.uikit.colorPrimary
|
import com.shabinder.common.uikit.configurations.colorPrimary
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
@ExperimentalAnimationApi
|
@ExperimentalAnimationApi
|
||||||
|
@ -33,14 +33,14 @@ allprojects {
|
|||||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
|
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "1.8"
|
||||||
freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
project.extensions.findByType<org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension>()?.let { kmpExt ->
|
project.extensions.findByType<org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension>()?.let { kmpExt ->
|
||||||
kmpExt.sourceSets.run {
|
kmpExt.sourceSets.run {
|
||||||
all {
|
all {
|
||||||
languageSettings.useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi")
|
languageSettings.useExperimentalAnnotation("kotlin.RequiresOptIn")
|
||||||
|
languageSettings.useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi")
|
||||||
}
|
}
|
||||||
removeAll { it.name == "androidAndroidTestRelease" }
|
removeAll { it.name == "androidAndroidTestRelease" }
|
||||||
}
|
}
|
||||||
|
@ -30,13 +30,14 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.android.tools.build:gradle:4.1.1")
|
implementation(Androidx.gradlePlugin)
|
||||||
implementation(JetBrains.Compose.gradlePlugin)
|
implementation(JetBrains.Compose.gradlePlugin)
|
||||||
implementation(JetBrains.Kotlin.gradlePlugin)
|
implementation(JetBrains.Kotlin.gradlePlugin)
|
||||||
implementation(JetBrains.Kotlin.serialization)
|
implementation(JetBrains.Kotlin.serialization)
|
||||||
implementation(SqlDelight.gradlePlugin)
|
implementation(SqlDelight.gradlePlugin)
|
||||||
implementation("org.jlleitschuh.gradle:ktlint-gradle:${Versions.ktLint}")
|
implementation(KTLint.gradlePlugin)
|
||||||
implementation("de.comahe.i18n4k:i18n4k-gradle-plugin:0.1.1")
|
implementation(Internationalization.gradlePlugin)
|
||||||
|
implementation(Mosaic.gradlePlugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
@ -19,17 +19,21 @@
|
|||||||
object Versions {
|
object Versions {
|
||||||
// App's Version (To be bumped at each update)
|
// App's Version (To be bumped at each update)
|
||||||
const val versionName = "3.1.0"
|
const val versionName = "3.1.0"
|
||||||
const val versionCode = 20
|
|
||||||
|
|
||||||
|
const val versionCode = 20
|
||||||
// Kotlin
|
// Kotlin
|
||||||
const val kotlinVersion = "1.5.10"
|
const val kotlinVersion = "1.5.10"
|
||||||
|
|
||||||
const val coroutinesVersion = "1.5.0"
|
const val coroutinesVersion = "1.5.0"
|
||||||
|
|
||||||
// Code Formatting
|
// Code Formatting
|
||||||
const val ktLint = "10.1.0"
|
const val ktLint = "10.1.0"
|
||||||
|
|
||||||
|
// Console-App UI
|
||||||
|
const val mosaic = "0.1.0"
|
||||||
|
|
||||||
// DI
|
// DI
|
||||||
const val koin = "3.1.0"
|
const val koin = "3.1.2"
|
||||||
|
|
||||||
// Logger
|
// Logger
|
||||||
const val kermit = "0.1.9"
|
const val kermit = "0.1.9"
|
||||||
@ -45,6 +49,9 @@ object Versions {
|
|||||||
const val sqliteJdbcDriver = "3.34.0"
|
const val sqliteJdbcDriver = "3.34.0"
|
||||||
const val slf4j = "1.7.31"
|
const val slf4j = "1.7.31"
|
||||||
|
|
||||||
|
// Internationalisation
|
||||||
|
const val i18n4k = "0.1.2"
|
||||||
|
|
||||||
// Android
|
// Android
|
||||||
const val minSdkVersion = 21
|
const val minSdkVersion = 21
|
||||||
const val compileSdkVersion = 29
|
const val compileSdkVersion = 29
|
||||||
@ -80,15 +87,11 @@ object Androidx {
|
|||||||
const val junit = "androidx.test.ext:junit:1.1.2"
|
const val junit = "androidx.test.ext:junit:1.1.2"
|
||||||
const val expresso = "androidx.test.espresso:espresso-core:3.3.0"
|
const val expresso = "androidx.test.espresso:espresso-core:3.3.0"
|
||||||
|
|
||||||
/*object Compose{
|
const val gradlePlugin = "com.android.tools.build:gradle:4.1.1"
|
||||||
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}"
|
object KTLint {
|
||||||
const val uiTooling = "androidx.compose.ui:ui-tooling:${Versions.compose}"
|
const val gradlePlugin = "org.jlleitschuh.gradle:ktlint-gradle:${Versions.ktLint}"
|
||||||
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}"
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object JetBrains {
|
object JetBrains {
|
||||||
@ -106,7 +109,9 @@ object JetBrains {
|
|||||||
const val gradlePlugin = "org.jetbrains.compose:compose-gradle-plugin:$VERSION"
|
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 {
|
object Decompose {
|
||||||
private const val VERSION = "0.2.6"
|
private const val VERSION = "0.2.6"
|
||||||
const val decompose = "com.arkivanov.decompose:decompose:$VERSION"
|
const val decompose = "com.arkivanov.decompose:decompose:$VERSION"
|
||||||
@ -146,7 +151,8 @@ object Ktor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Internationalization {
|
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 {
|
object Extras {
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,7 +20,7 @@ actual fun ImageLoad(
|
|||||||
link: String,
|
link: String,
|
||||||
loader: suspend () -> Picture,
|
loader: suspend () -> Picture,
|
||||||
desc: String,
|
desc: String,
|
||||||
modifier: Modifier,
|
modifier: Modifier
|
||||||
// placeholder: ImageVector
|
// placeholder: ImageVector
|
||||||
) {
|
) {
|
||||||
var pic by remember(link) { mutableStateOf<ImageBitmap?>(null) }
|
var pic by remember(link) { mutableStateOf<ImageBitmap?>(null) }
|
||||||
|
@ -22,24 +22,10 @@ import androidx.compose.foundation.Image
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.painterResource
|
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.database.R
|
||||||
import com.shabinder.common.translations.Strings
|
import com.shabinder.common.translations.Strings
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
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
|
@Composable
|
||||||
actual fun DownloadImageTick() {
|
actual fun DownloadImageTick() {
|
||||||
Image(
|
Image(
|
||||||
@ -49,10 +35,11 @@ actual fun DownloadImageTick() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
actual fun DownloadImageError() {
|
actual fun DownloadImageError(modifier: Modifier) {
|
||||||
Image(
|
Image(
|
||||||
painterResource(R.drawable.ic_error),
|
painterResource(R.drawable.ic_error),
|
||||||
Strings.downloadError()
|
Strings.downloadError(),
|
||||||
|
modifier = modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)
|
||||||
|
)
|
@ -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
|
||||||
|
)
|
@ -8,7 +8,7 @@ import com.shabinder.common.di.Picture
|
|||||||
expect fun ImageLoad(
|
expect fun ImageLoad(
|
||||||
link: String,
|
link: String,
|
||||||
loader: suspend () -> Picture,
|
loader: suspend () -> Picture,
|
||||||
desc: String = "Album Art",
|
desc: String,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier
|
||||||
// placeholder:Painter = PlaceHolderImage()
|
// placeholder:Painter = PlaceHolderImage()
|
||||||
)
|
)
|
||||||
|
@ -67,14 +67,7 @@ expect fun RazorPay(): Painter
|
|||||||
expect fun HeartIcon(): Painter
|
expect fun HeartIcon(): Painter
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
expect fun DownloadImageError()
|
expect fun DownloadImageError(modifier: Modifier)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
expect fun DownloadImageArrow(modifier: Modifier)
|
expect fun DownloadImageArrow(modifier: Modifier)
|
||||||
|
|
||||||
@Composable
|
|
||||||
expect fun DonationDialog(
|
|
||||||
isVisible: Boolean,
|
|
||||||
onDismiss: () -> Unit,
|
|
||||||
onSnooze: () -> Unit
|
|
||||||
)
|
|
@ -14,7 +14,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.shabinder.common.uikit
|
package com.shabinder.common.uikit.configurations
|
||||||
|
|
||||||
import androidx.compose.material.darkColors
|
import androidx.compose.material.darkColors
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
@ -14,7 +14,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.shabinder.common.uikit
|
package com.shabinder.common.uikit.configurations
|
||||||
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.Shapes
|
import androidx.compose.material.Shapes
|
@ -14,7 +14,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.shabinder.common.uikit
|
package com.shabinder.common.uikit.configurations
|
||||||
|
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
@ -14,7 +14,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.shabinder.common.uikit
|
package com.shabinder.common.uikit.configurations
|
||||||
|
|
||||||
import androidx.compose.material.Typography
|
import androidx.compose.material.Typography
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
@ -1,17 +1,46 @@
|
|||||||
package com.shabinder.common.uikit.dialogs
|
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.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
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<openAction,dismissAction,snoozeAction>
|
typealias DonationDialogCallBacks = Triple<openAction,dismissAction,snoozeAction>
|
||||||
private typealias openAction = () -> Unit
|
internal typealias openAction = () -> Unit
|
||||||
private typealias dismissAction = () -> Unit
|
internal typealias dismissAction = () -> Unit
|
||||||
private typealias snoozeAction = () -> Unit
|
private typealias snoozeAction = () -> Unit
|
||||||
|
|
||||||
|
@OptIn(ExperimentalAnimationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun DonationDialogComponent(onDismissExtra: () -> Unit): DonationDialogCallBacks {
|
fun DonationDialogComponent(onDismissExtra: () -> Unit): DonationDialogCallBacks {
|
||||||
var isDonationDialogVisible by remember { mutableStateOf(false) }
|
var isDonationDialogVisible by remember { mutableStateOf(false) }
|
||||||
@ -30,4 +59,112 @@ fun DonationDialogComponent(onDismissExtra: () -> Unit): DonationDialogCallBacks
|
|||||||
isDonationDialogVisible = false
|
isDonationDialogVisible = false
|
||||||
}
|
}
|
||||||
return DonationDialogCallBacks(openDonationDialog,dismissDonationDialog,snoozeDonationDialog)
|
return DonationDialogCallBacks(openDonationDialog,dismissDonationDialog,snoozeDonationDialog)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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<openAction,dismissAction>
|
||||||
|
|
||||||
|
@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)
|
||||||
|
}
|
@ -14,8 +14,9 @@
|
|||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
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.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
@ -37,6 +39,8 @@ import androidx.compose.material.ExtendedFloatingActionButton
|
|||||||
import androidx.compose.material.Icon
|
import androidx.compose.material.Icon
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Text
|
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.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
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.TrackDetails
|
||||||
import com.shabinder.common.models.methods
|
import com.shabinder.common.models.methods
|
||||||
import com.shabinder.common.translations.Strings
|
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.DonationDialogComponent
|
||||||
|
import com.shabinder.common.uikit.dialogs.ErrorInfoDialog
|
||||||
|
import com.shabinder.common.uikit.rememberScrollbarAdapter
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@ -133,6 +150,7 @@ fun SpotiFlyerListContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalAnimationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun TrackCard(
|
fun TrackCard(
|
||||||
track: TrackDetails,
|
track: TrackDetails,
|
||||||
@ -168,7 +186,19 @@ fun TrackCard(
|
|||||||
CircularProgressIndicator()
|
CircularProgressIndicator()
|
||||||
}
|
}
|
||||||
is DownloadStatus.Failed -> {
|
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 -> {
|
is DownloadStatus.Downloading -> {
|
||||||
CircularProgressIndicator(progress = (track.downloaded as DownloadStatus.Downloading).progress.toFloat() / 100f)
|
CircularProgressIndicator(progress = (track.downloaded as DownloadStatus.Downloading).progress.toFloat() / 100f)
|
@ -14,7 +14,7 @@
|
|||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.shabinder.common.uikit
|
package com.shabinder.common.uikit.screens
|
||||||
|
|
||||||
import androidx.compose.animation.Crossfade
|
import androidx.compose.animation.Crossfade
|
||||||
import androidx.compose.foundation.BorderStroke
|
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.DownloadRecord
|
||||||
import com.shabinder.common.models.methods
|
import com.shabinder.common.models.methods
|
||||||
import com.shabinder.common.translations.Strings
|
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.dialogs.DonationDialogComponent
|
||||||
|
import com.shabinder.common.uikit.rememberScrollbarAdapter
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SpotiFlyerMainContent(component: SpotiFlyerMain) {
|
fun SpotiFlyerMainContent(component: SpotiFlyerMain) {
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
@file:Suppress("EXPERIMENTAL_API_USAGE")
|
@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.AnimatedVisibility
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
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
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot.Child
|
import com.shabinder.common.root.SpotiFlyerRoot.Child
|
||||||
import com.shabinder.common.translations.Strings
|
import com.shabinder.common.translations.Strings
|
||||||
import com.shabinder.common.uikit.splash.Splash
|
import com.shabinder.common.uikit.SpotiFlyerLogo
|
||||||
import com.shabinder.common.uikit.splash.SplashState
|
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
|
import com.shabinder.common.uikit.utils.verticalGradientScrim
|
||||||
|
|
||||||
// To Not Show Splash Again After Configuration Change in Android
|
// To Not Show Splash Again After Configuration Change in Android
|
@ -14,7 +14,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.shabinder.common.uikit.splash
|
package com.shabinder.common.uikit.screens.splash
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
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.translations.Strings
|
||||||
import com.shabinder.common.uikit.HeartIcon
|
import com.shabinder.common.uikit.HeartIcon
|
||||||
import com.shabinder.common.uikit.SpotiFlyerLogo
|
import com.shabinder.common.uikit.SpotiFlyerLogo
|
||||||
import com.shabinder.common.uikit.SpotiFlyerTypography
|
import com.shabinder.common.uikit.configurations.SpotiFlyerTypography
|
||||||
import com.shabinder.common.uikit.colorAccent
|
import com.shabinder.common.uikit.configurations.colorAccent
|
||||||
import com.shabinder.common.uikit.colorPrimary
|
import com.shabinder.common.uikit.configurations.colorPrimary
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
private const val SplashWaitTime: Long = 2000
|
private const val SplashWaitTime: Long = 2000
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,7 +20,7 @@ actual fun ImageLoad(
|
|||||||
link: String,
|
link: String,
|
||||||
loader: suspend () -> Picture,
|
loader: suspend () -> Picture,
|
||||||
desc: String,
|
desc: String,
|
||||||
modifier: Modifier,
|
modifier: Modifier
|
||||||
// placeholder: ImageVector
|
// placeholder: ImageVector
|
||||||
) {
|
) {
|
||||||
var pic by remember(link) { mutableStateOf<ImageBitmap?>(null) }
|
var pic by remember(link) { mutableStateOf<ImageBitmap?>(null) }
|
||||||
|
@ -19,15 +19,10 @@ package com.shabinder.common.uikit
|
|||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||||
import androidx.compose.ui.res.vectorXmlResource
|
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
|
@Composable
|
||||||
actual fun DownloadImageTick() {
|
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
|
@Composable
|
||||||
actual fun DownloadImageError() {
|
actual fun DownloadImageError(modifier: Modifier) {
|
||||||
Image(
|
Image(
|
||||||
vectorXmlResource("drawable/ic_error.xml"),
|
vectorXmlResource("drawable/ic_error.xml"),
|
||||||
"Can't Download"
|
"Can't Download",
|
||||||
|
modifier = modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
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.GlobalScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
@ -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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)
|
||||||
|
)
|
@ -31,7 +31,7 @@ val statelyIsoVersion = "1.1.7-a1"
|
|||||||
i18n4k {
|
i18n4k {
|
||||||
inputDirectory = "../../translations"
|
inputDirectory = "../../translations"
|
||||||
packageName = "com.shabinder.common.translations"
|
packageName = "com.shabinder.common.translations"
|
||||||
// sourceCodeLocales = listOf("en", "de")
|
// sourceCodeLocales = listOf("en", "de", "es", "fr", "id", "pt", "ru", "uk")
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
@ -36,6 +36,9 @@ interface Actions {
|
|||||||
// Share SpotiFlyer App
|
// Share SpotiFlyer App
|
||||||
fun shareApp()
|
fun shareApp()
|
||||||
|
|
||||||
|
// Copy to Clipboard
|
||||||
|
fun copyToClipboard(text: String)
|
||||||
|
|
||||||
// Open / Redirect to another Platform
|
// Open / Redirect to another Platform
|
||||||
fun openPlatform(packageID: String, platformLink: String)
|
fun openPlatform(packageID: String, platformLink: String)
|
||||||
fun writeMp3Tags(trackDetails: TrackDetails)
|
fun writeMp3Tags(trackDetails: TrackDetails)
|
||||||
@ -48,6 +51,8 @@ private fun stubActions(): Actions = object : Actions {
|
|||||||
override fun queryActiveTracks() {}
|
override fun queryActiveTracks() {}
|
||||||
override fun giveDonation() {}
|
override fun giveDonation() {}
|
||||||
override fun shareApp() {}
|
override fun shareApp() {}
|
||||||
|
override fun copyToClipboard(text: String) {}
|
||||||
|
|
||||||
override fun openPlatform(packageID: String, platformLink: String) {}
|
override fun openPlatform(packageID: String, platformLink: String) {}
|
||||||
override fun writeMp3Tags(trackDetails: TrackDetails) {}
|
override fun writeMp3Tags(trackDetails: TrackDetails) {}
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ sealed class SpotiFlyerException(override val message: String): Exception(messag
|
|||||||
val jioSaavnError: Throwable,
|
val jioSaavnError: Throwable,
|
||||||
val ytMusicError: Throwable,
|
val ytMusicError: Throwable,
|
||||||
override val message: String = "${Strings.noLinkFound()}: $trackName," +
|
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)
|
): SpotiFlyerException(message)
|
||||||
|
|
||||||
data class LinkInvalid(
|
data class LinkInvalid(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
@file:Suppress("UNCHECKED_CAST")
|
||||||
|
|
||||||
package com.shabinder.common.models.event.coroutines
|
package com.shabinder.common.models.event.coroutines
|
||||||
|
|
||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadOnlyProperty
|
||||||
|
@ -101,6 +101,7 @@ class FetchPlatformQueryResult(
|
|||||||
}
|
}
|
||||||
Source.YouTube -> {
|
Source.YouTube -> {
|
||||||
youtubeMp3.getMp3DownloadLink(track.videoID.requireNotNull()).flatMapError {
|
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 ->
|
youtubeProvider.ytDownloader.getVideo(track.videoID!!).get()?.url?.let { m4aLink ->
|
||||||
audioToMp3.convertToMp3(m4aLink)
|
audioToMp3.convertToMp3(m4aLink)
|
||||||
} ?: throw SpotiFlyerException.YoutubeLinkNotFound(track.videoID)
|
} ?: throw SpotiFlyerException.YoutubeLinkNotFound(track.videoID)
|
||||||
@ -130,8 +131,8 @@ class FetchPlatformQueryResult(
|
|||||||
SuspendableEvent.error(
|
SuspendableEvent.error(
|
||||||
SpotiFlyerException.DownloadLinkFetchFailed(
|
SpotiFlyerException.DownloadLinkFetchFailed(
|
||||||
trackName = track.title,
|
trackName = track.title,
|
||||||
jioSaavnError = saavnError,
|
ytMusicError = ytMusicError,
|
||||||
ytMusicError = ytMusicError
|
jioSaavnError = saavnError
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -303,7 +303,7 @@ class YoutubeMusic constructor(
|
|||||||
}
|
}
|
||||||
// logger.d("YT Api Result"){"$trackName - $linksWithMatchValue"}
|
// logger.d("YT Api Result"){"$trackName - $linksWithMatchValue"}
|
||||||
return linksWithMatchValue.toList().sortedByDescending { it.second }.toMap().also {
|
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() ?: ""}" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ interface JioSaavnRequests {
|
|||||||
|
|
||||||
// Skip this Result if No Word is Common in Name
|
// Skip this Result if No Word is Common in Name
|
||||||
if (!hasCommonWord) {
|
if (!hasCommonWord) {
|
||||||
logger.i("Saavn Removing Common Word") { result.toString() }
|
// logger.i("Saavn Removing Common Word") { result.toString() }
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +264,7 @@ interface JioSaavnRequests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (artistMatchNumber == 0) {
|
if (artistMatchNumber == 0) {
|
||||||
logger.i("Artist Match Saavn Removing") { result.toString() }
|
// logger.i("Artist Match Saavn Removing") { result.toString() }
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val artistMatch: Float = (artistMatchNumber.toFloat() / trackArtists.size) * 100
|
val artistMatch: Float = (artistMatchNumber.toFloat() / trackArtists.size) * 100
|
||||||
@ -274,11 +274,12 @@ interface JioSaavnRequests {
|
|||||||
linksWithMatchValue[result.id] = avgMatch
|
linksWithMatchValue[result.id] = avgMatch
|
||||||
}
|
}
|
||||||
return linksWithMatchValue.toList().sortedByDescending { it.second }.toMap().also {
|
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 {
|
companion object {
|
||||||
|
const val TAG = "Saavn Request"
|
||||||
// EndPoints
|
// 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 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="
|
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="
|
||||||
|
@ -76,6 +76,7 @@ internal class SpotiFlyerRootImpl(
|
|||||||
) {
|
) {
|
||||||
instanceKeeper.ensureNeverFrozen()
|
instanceKeeper.ensureNeverFrozen()
|
||||||
methods.value = dependencies.actions.freeze()
|
methods.value = dependencies.actions.freeze()
|
||||||
|
|
||||||
/*Init App Launch & Authenticate Spotify Client*/
|
/*Init App Launch & Authenticate Spotify Client*/
|
||||||
initAppLaunchAndAuthenticateSpotify(dependencies.fetchQuery::authenticateSpotifyClient)
|
initAppLaunchAndAuthenticateSpotify(dependencies.fetchQuery::authenticateSpotifyClient)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm")// version "1.4.32"
|
kotlin("jvm")
|
||||||
kotlin("plugin.serialization")
|
kotlin("plugin.serialization")
|
||||||
id("ktlint-setup")
|
id("ktlint-setup")
|
||||||
id("com.jakewharton.mosaic")
|
id("com.jakewharton.mosaic")
|
||||||
|
@ -5,7 +5,7 @@ import com.jakewharton.mosaic.Text
|
|||||||
import com.jakewharton.mosaic.runMosaic
|
import com.jakewharton.mosaic.runMosaic
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
fun main(/*args: Array<String>*/) = runMosaic {
|
fun main() = runMosaic {
|
||||||
// TODO https://github.com/JakeWharton/mosaic/issues/3
|
// TODO https://github.com/JakeWharton/mosaic/issues/3
|
||||||
var count by mutableStateOf(0)
|
var count by mutableStateOf(0)
|
||||||
|
|
||||||
|
@ -37,21 +37,25 @@ import com.shabinder.common.models.Actions
|
|||||||
import com.shabinder.common.models.PlatformActions
|
import com.shabinder.common.models.PlatformActions
|
||||||
import com.shabinder.common.models.TrackDetails
|
import com.shabinder.common.models.TrackDetails
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot
|
import com.shabinder.common.root.SpotiFlyerRoot
|
||||||
import com.shabinder.common.uikit.SpotiFlyerColors
|
import com.shabinder.common.uikit.configurations.SpotiFlyerColors
|
||||||
import com.shabinder.common.uikit.SpotiFlyerRootContent
|
import com.shabinder.common.uikit.configurations.SpotiFlyerShapes
|
||||||
import com.shabinder.common.uikit.SpotiFlyerShapes
|
import com.shabinder.common.uikit.configurations.SpotiFlyerTypography
|
||||||
import com.shabinder.common.uikit.SpotiFlyerTypography
|
import com.shabinder.common.uikit.configurations.colorOffWhite
|
||||||
import com.shabinder.common.uikit.colorOffWhite
|
import com.shabinder.common.uikit.screens.SpotiFlyerRootContent
|
||||||
import com.shabinder.database.Database
|
import com.shabinder.database.Database
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.piwik.java.tracking.PiwikTracker
|
import org.piwik.java.tracking.PiwikTracker
|
||||||
import utils.trackAsync
|
import utils.trackAsync
|
||||||
import utils.trackScreenAsync
|
import utils.trackScreenAsync
|
||||||
import java.awt.Desktop
|
import java.awt.Desktop
|
||||||
|
import java.awt.Toolkit
|
||||||
|
import java.awt.datatransfer.Clipboard
|
||||||
|
import java.awt.datatransfer.StringSelection
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import javax.swing.JFileChooser
|
import javax.swing.JFileChooser
|
||||||
import javax.swing.JFileChooser.APPROVE_OPTION
|
import javax.swing.JFileChooser.APPROVE_OPTION
|
||||||
|
|
||||||
|
|
||||||
private val koin = initKoin(enableNetworkLogs = true).koin
|
private val koin = initKoin(enableNetworkLogs = true).koin
|
||||||
private lateinit var showToast: (String)->Unit
|
private lateinit var showToast: (String)->Unit
|
||||||
private val tracker: PiwikTracker by lazy {
|
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 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)
|
override fun openPlatform(packageID: String, platformLink: String) = openLink(platformLink)
|
||||||
|
|
||||||
|
@ -31,11 +31,3 @@ include(
|
|||||||
":console-app",
|
":console-app",
|
||||||
":maintenance-tasks"
|
":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"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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.
|
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
|
share = Teilen
|
||||||
shareDescription = Teile diese App mit deiner Familie und deinen Freunden.
|
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
|
status = Status
|
||||||
analytics = Analyse
|
analytics = Analyse
|
||||||
analyticsDescription = Deine Daten sind Anonym und werden nie mit Drittanbietern geteilt.
|
analyticsDescription = Deine Daten sind Anonym und werden nie mit Drittanbietern geteilt.
|
||||||
|
@ -15,6 +15,9 @@ supportDeveloper = Support Developer
|
|||||||
donateDescription = If you think I deserve to get paid for my work, you can support me here.
|
donateDescription = If you think I deserve to get paid for my work, you can support me here.
|
||||||
share = Share
|
share = Share
|
||||||
shareDescription = Share this app with your friends and family.
|
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
|
status = Status
|
||||||
analytics = Analytics
|
analytics = Analytics
|
||||||
analyticsDescription = Your Data is Anonymized and never shared with 3rd party service.
|
analyticsDescription = Your Data is Anonymized and never shared with 3rd party service.
|
||||||
|
@ -15,6 +15,9 @@ supportDeveloper = Apoya al desarollador
|
|||||||
donateDescription = Si crees que merezco una paga por mi trabajo, aquí puedes apoyarme.
|
donateDescription = Si crees que merezco una paga por mi trabajo, aquí puedes apoyarme.
|
||||||
share = Comparte
|
share = Comparte
|
||||||
shareDescription = Comparte esta aplicación con tus familiares y amigos.
|
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
|
status = Estatus
|
||||||
analytics = Analiticos
|
analytics = Analiticos
|
||||||
analyticsDescription = Tus datos son anonimizados y nunca se compartiran con servicios de terceros.
|
analyticsDescription = Tus datos son anonimizados y nunca se compartiran con servicios de terceros.
|
||||||
|
@ -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.
|
donateDescription = Si vous pensez que je mérite d'être payé pour mon travail, vous pouvez me soutenir ici.
|
||||||
share = Partager
|
share = Partager
|
||||||
shareDescription = Partagez cette application avec vos amis et votre famille.
|
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
|
status = Statut
|
||||||
analytics = Analyses
|
analytics = Analyses
|
||||||
analyticsDescription = Vos données sont anonymes et ne sont jamais partagées avec des services tiers.
|
analyticsDescription = Vos données sont anonymes et ne sont jamais partagées avec des services tiers.
|
||||||
|
@ -15,6 +15,9 @@ supportDeveloper = Dukung Developer
|
|||||||
donateDescription = Jika Anda ingin memberi donasi ke developer apl. ini, Anda bisa donasi disini.
|
donateDescription = Jika Anda ingin memberi donasi ke developer apl. ini, Anda bisa donasi disini.
|
||||||
share = Bagikan
|
share = Bagikan
|
||||||
shareDescription = Bagikan aplikasi ini kepada teman / keluarga anda.
|
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
|
status = Status
|
||||||
analytics = Analytics
|
analytics = Analytics
|
||||||
analyticsDescription = Data Anda tidak dapat dilihat oleh orang lain dan TIDAK akan dibagikan ke pihak ketiga.
|
analyticsDescription = Data Anda tidak dapat dilihat oleh orang lain dan TIDAK akan dibagikan ke pihak ketiga.
|
||||||
|
@ -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.
|
donateDescription = Se você acha que mereço ser pago pelo meu trabalho, você pode me ajudar aqui.
|
||||||
share = Compartilhar
|
share = Compartilhar
|
||||||
shareDescription = Compartilhe este app com seus amigos e família.
|
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
|
status = Status
|
||||||
analytics = Estatísticas
|
analytics = Estatísticas
|
||||||
analyticsDescription = Seus dados serão tornados anônimos e nunca serão compartilhados com serviços de terceiros.
|
analyticsDescription = Seus dados serão tornados anônimos e nunca serão compartilhados com serviços de terceiros.
|
||||||
|
@ -15,6 +15,9 @@ supportDeveloper = Поддержи разработчика
|
|||||||
donateDescription = Если считаешь, что я заслуживаю этого, ты можешь поддержать меня здесь.
|
donateDescription = Если считаешь, что я заслуживаю этого, ты можешь поддержать меня здесь.
|
||||||
share = Поделиться
|
share = Поделиться
|
||||||
shareDescription = Расскажи об этом приложении знакомым - поделись полезным инструментом.
|
shareDescription = Расскажи об этом приложении знакомым - поделись полезным инструментом.
|
||||||
|
whatWentWrong = Что пошло не так...
|
||||||
|
copyToClipboard = Скопировать в буфер обмена
|
||||||
|
copyCodeInGithubIssue = Скопируйте вставьте ниже код при создании проблемы Github / Сообщите об этой проблеме для лучшей помощи.
|
||||||
status = Статус
|
status = Статус
|
||||||
analytics = Аналитика
|
analytics = Аналитика
|
||||||
analyticsDescription = Предоставить анонимные данные для улучшения приложения. Они не будут переданы третьим лицам.
|
analyticsDescription = Предоставить анонимные данные для улучшения приложения. Они не будут переданы третьим лицам.
|
||||||
|
@ -15,6 +15,9 @@ supportDeveloper = Підтримати розробника
|
|||||||
donateDescription = Якщо ви вважаєте, що я заслуговую на отримання грошей за свою роботу, ви можете підтримати мене тут.
|
donateDescription = Якщо ви вважаєте, що я заслуговую на отримання грошей за свою роботу, ви можете підтримати мене тут.
|
||||||
share = Поділитися
|
share = Поділитися
|
||||||
shareDescription = Поділися цією програмою зі своїми друзями та родиною.
|
shareDescription = Поділися цією програмою зі своїми друзями та родиною.
|
||||||
|
whatWentWrong = Що пішло не так...
|
||||||
|
copyToClipboard = Копіювати в буфер обміну
|
||||||
|
copyCodeInGithubIssue = Скопіюйте вставку нижче коду під час створення випуску Github / звітування про цю проблему, щоб отримати кращу допомогу.
|
||||||
status = Статус
|
status = Статус
|
||||||
analytics = Аналіз
|
analytics = Аналіз
|
||||||
analyticsDescription = Ваші дані анонімні та ніколи не передаються стороннім сервісам.
|
analyticsDescription = Ваші дані анонімні та ніколи не передаються стороннім сервісам.
|
||||||
|
@ -71,6 +71,8 @@ class App(props: AppProps): RComponent<AppProps, RState>(props) {
|
|||||||
/*TODO("Not yet implemented")*/
|
/*TODO("Not yet implemented")*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun copyToClipboard(text: String) {}
|
||||||
|
|
||||||
override fun setDownloadDirectoryAction() {}
|
override fun setDownloadDirectoryAction() {}
|
||||||
|
|
||||||
override fun queryActiveTracks() {}
|
override fun queryActiveTracks() {}
|
||||||
|
Loading…
Reference in New Issue
Block a user