mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-12-22 12:47:54 +01:00
Scrollbars and various Bug Fixes
This commit is contained in:
parent
d90469d0fd
commit
603314fcd2
@ -48,6 +48,7 @@
|
||||
android:usesCleartextTraffic="true"
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:largeHeap="true"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:configChanges="orientation|screenSize"
|
||||
|
@ -236,7 +236,13 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
||||
ContextCompat.startForegroundService(this@MainActivity, serviceIntent)
|
||||
}
|
||||
|
||||
override fun giveDonation() = startPayment(this@MainActivity)
|
||||
override fun giveDonation() {
|
||||
try {
|
||||
startPayment(this@MainActivity)
|
||||
}catch (e:Exception) {
|
||||
openPlatform("",platformLink = "https://razorpay.com/payment-button/pl_GnKuuDBdBu0ank/view/?utm_source=payment_button&utm_medium=button&utm_campaign=payment_button")
|
||||
}
|
||||
}
|
||||
|
||||
override fun shareApp() {
|
||||
val sendIntent: Intent = Intent().apply {
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
object Versions {
|
||||
// App's Version (To be bumped at each update)
|
||||
const val versionName = "2.3.0"
|
||||
const val versionName = "2.3.5"
|
||||
|
||||
// Kotlin
|
||||
const val kotlinVersion = "1.4.32"
|
||||
@ -45,7 +45,7 @@ object Versions {
|
||||
const val slf4j = "1.7.30"
|
||||
|
||||
// Android
|
||||
const val versionCode = 17
|
||||
const val versionCode = 18
|
||||
const val minSdkVersion = 21
|
||||
const val compileSdkVersion = 29
|
||||
const val targetSdkVersion = 29
|
||||
@ -142,7 +142,7 @@ object Extras {
|
||||
const val jaudioTagger = "com.github.Shabinder:JAudioTagger-Android:1.0"
|
||||
const val kermit = "co.touchlab:kermit:${Versions.kermit}"
|
||||
object Android {
|
||||
val razorpay = "com.razorpay:checkout:1.6.5"
|
||||
val razorpay = "com.razorpay:checkout:1.6.7"
|
||||
val fetch = "androidx.tonyodev.fetch2:xfetch2:3.1.6"
|
||||
val appUpdator = "com.github.amitbd1508:AppUpdater:4.1.0"
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
package com.shabinder.common.uikit
|
||||
|
||||
import androidx.compose.foundation.ScrollState
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
actual val MARGIN_SCROLLBAR: Dp = 0.dp
|
||||
|
||||
actual interface ScrollbarAdapter
|
||||
|
||||
@Composable
|
||||
actual fun rememberScrollbarAdapter(
|
||||
scrollState: ScrollState
|
||||
): ScrollbarAdapter = object : ScrollbarAdapter {}
|
||||
|
||||
@Composable
|
||||
actual fun rememberScrollbarAdapter(
|
||||
scrollState: LazyListState,
|
||||
itemCount: Int,
|
||||
averageItemSize: Dp
|
||||
): ScrollbarAdapter =
|
||||
object : ScrollbarAdapter {}
|
||||
|
||||
@Composable
|
||||
actual fun VerticalScrollbar(
|
||||
modifier: Modifier,
|
||||
adapter: ScrollbarAdapter
|
||||
) {
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.shabinder.common.uikit
|
||||
|
||||
import androidx.compose.foundation.ScrollState
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
|
||||
expect val MARGIN_SCROLLBAR: Dp
|
||||
|
||||
expect interface ScrollbarAdapter
|
||||
|
||||
@Composable
|
||||
expect fun rememberScrollbarAdapter(
|
||||
scrollState: LazyListState,
|
||||
itemCount: Int,
|
||||
averageItemSize: Dp
|
||||
): ScrollbarAdapter
|
||||
|
||||
@Composable
|
||||
expect fun rememberScrollbarAdapter(
|
||||
scrollState: ScrollState
|
||||
): ScrollbarAdapter
|
||||
|
||||
@Composable
|
||||
expect fun VerticalScrollbar(
|
||||
modifier: Modifier,
|
||||
adapter: ScrollbarAdapter
|
||||
)
|
@ -22,6 +22,7 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
@ -29,6 +30,7 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.CircularProgressIndicator
|
||||
import androidx.compose.material.ExtendedFloatingActionButton
|
||||
import androidx.compose.material.Icon
|
||||
@ -77,6 +79,9 @@ fun SpotiFlyerListContent(
|
||||
Text("Loading..", style = appNameStyle, color = colorPrimary)
|
||||
}
|
||||
} else {
|
||||
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
LazyColumn(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
content = {
|
||||
@ -91,12 +96,23 @@ fun SpotiFlyerListContent(
|
||||
)
|
||||
}
|
||||
},
|
||||
state = listState,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
|
||||
DownloadAllButton(
|
||||
onClick = { component.onDownloadAllClicked(model.trackList) },
|
||||
modifier = Modifier.padding(bottom = 24.dp).align(Alignment.BottomCenter)
|
||||
)
|
||||
|
||||
VerticalScrollbar(
|
||||
modifier = Modifier.padding(end = 2.dp).align(Alignment.CenterEnd).fillMaxHeight(),
|
||||
adapter = rememberScrollbarAdapter(
|
||||
scrollState = listState,
|
||||
itemCount = model.trackList.size,
|
||||
averageItemSize = 72.dp
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,11 @@ import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
@ -35,6 +37,7 @@ import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
@ -125,7 +128,7 @@ fun HomeTabBar(
|
||||
|
||||
TabRow(
|
||||
selectedTabIndex = selectedIndex,
|
||||
indicator = indicator,
|
||||
indicator = indicator as @Composable (List<TabPosition>) -> Unit,
|
||||
modifier = modifier,
|
||||
) {
|
||||
categories.forEachIndexed { index, category ->
|
||||
@ -219,160 +222,169 @@ fun SearchPanel(
|
||||
|
||||
@Composable
|
||||
fun AboutColumn(modifier: Modifier = Modifier) {
|
||||
// TODO Make Scrollable
|
||||
Column(modifier.fillMaxSize().padding(8.dp).verticalScroll(rememberScrollState())) {
|
||||
Card(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
border = BorderStroke(1.dp, Color.Gray)
|
||||
) {
|
||||
Column(modifier.padding(12.dp)) {
|
||||
Text(
|
||||
text = "Supported Platforms",
|
||||
style = SpotiFlyerTypography.body1,
|
||||
color = colorAccent
|
||||
)
|
||||
Spacer(modifier = Modifier.padding(top = 12.dp))
|
||||
Row(horizontalArrangement = Arrangement.Center, modifier = modifier.fillMaxWidth()) {
|
||||
Icon(
|
||||
SpotifyLogo(),
|
||||
"Open Spotify",
|
||||
tint = Color.Unspecified,
|
||||
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
||||
onClick = { methods.value.openPlatform("com.spotify.music", "http://open.spotify.com") }
|
||||
)
|
||||
)
|
||||
Spacer(modifier = modifier.padding(start = 16.dp))
|
||||
Icon(
|
||||
GaanaLogo(),
|
||||
"Open Gaana",
|
||||
tint = Color.Unspecified,
|
||||
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
||||
onClick = { methods.value.openPlatform("com.gaana", "http://gaana.com") }
|
||||
)
|
||||
)
|
||||
Spacer(modifier = modifier.padding(start = 16.dp))
|
||||
Icon(
|
||||
YoutubeLogo(),
|
||||
"Open Youtube",
|
||||
tint = Color.Unspecified,
|
||||
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
||||
onClick = { methods.value.openPlatform("com.google.android.youtube", "http://m.youtube.com") }
|
||||
)
|
||||
)
|
||||
Spacer(modifier = modifier.padding(start = 12.dp))
|
||||
Icon(
|
||||
YoutubeMusicLogo(),
|
||||
"Open Youtube Music",
|
||||
tint = Color.Unspecified,
|
||||
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
||||
onClick = { methods.value.openPlatform("com.google.android.apps.youtube.music", "https://music.youtube.com/") }
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.padding(top = 8.dp))
|
||||
Card(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
border = BorderStroke(1.dp, Color.Gray) // Gray
|
||||
) {
|
||||
Column(modifier.padding(12.dp)) {
|
||||
Text(
|
||||
text = "Support Development",
|
||||
style = SpotiFlyerTypography.body1,
|
||||
color = colorAccent
|
||||
)
|
||||
Spacer(modifier = Modifier.padding(top = 6.dp))
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth().clickable(
|
||||
onClick = { methods.value.openPlatform("", "http://github.com/Shabinder/SpotiFlyer") }
|
||||
)
|
||||
.padding(vertical = 6.dp)
|
||||
) {
|
||||
Icon(GithubLogo(), "Open Project Repo", tint = Color(0xFFCCCCCC))
|
||||
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||
Column {
|
||||
Text(
|
||||
text = "GitHub",
|
||||
style = SpotiFlyerTypography.h6
|
||||
)
|
||||
Text(
|
||||
text = "Star / Fork the project on Github.",
|
||||
style = SpotiFlyerTypography.subtitle2
|
||||
)
|
||||
}
|
||||
}
|
||||
Row(
|
||||
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||
.clickable(onClick = { methods.value.openPlatform("", "http://github.com/Shabinder/SpotiFlyer") }),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(Icons.Rounded.Flag, "Help Translate", Modifier.size(32.dp))
|
||||
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||
Column {
|
||||
Text(
|
||||
text = "Translate",
|
||||
style = SpotiFlyerTypography.h6
|
||||
)
|
||||
Text(
|
||||
text = "Help us translate this app in your local language.",
|
||||
style = SpotiFlyerTypography.subtitle2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var isDonationDialogVisible by remember { mutableStateOf(false) }
|
||||
Box {
|
||||
val stateVertical = rememberScrollState(0)
|
||||
|
||||
DonationDialog(
|
||||
isDonationDialogVisible
|
||||
) {
|
||||
isDonationDialogVisible = false
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||
.clickable(onClick = { isDonationDialogVisible = true }),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(Icons.Rounded.CardGiftcard, "Support Developer")
|
||||
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||
Column {
|
||||
Text(
|
||||
text = "Donate",
|
||||
style = SpotiFlyerTypography.h6
|
||||
Column(modifier.fillMaxSize().padding(8.dp).verticalScroll(stateVertical)) {
|
||||
Card(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
border = BorderStroke(1.dp, Color.Gray)
|
||||
) {
|
||||
Column(modifier.padding(12.dp)) {
|
||||
Text(
|
||||
text = "Supported Platforms",
|
||||
style = SpotiFlyerTypography.body1,
|
||||
color = colorAccent
|
||||
)
|
||||
Spacer(modifier = Modifier.padding(top = 12.dp))
|
||||
Row(horizontalArrangement = Arrangement.Center, modifier = modifier.fillMaxWidth()) {
|
||||
Icon(
|
||||
SpotifyLogo(),
|
||||
"Open Spotify",
|
||||
tint = Color.Unspecified,
|
||||
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
||||
onClick = { methods.value.openPlatform("com.spotify.music", "http://open.spotify.com") }
|
||||
)
|
||||
)
|
||||
Text(
|
||||
text = "If you think I deserve to get paid for my work, you can support me here.",
|
||||
//text = "SpotiFlyer will always be, Free and Open-Source. You can however show us that you care by sending a small donation.",
|
||||
style = SpotiFlyerTypography.subtitle2
|
||||
Spacer(modifier = modifier.padding(start = 16.dp))
|
||||
Icon(
|
||||
GaanaLogo(),
|
||||
"Open Gaana",
|
||||
tint = Color.Unspecified,
|
||||
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
||||
onClick = { methods.value.openPlatform("com.gaana", "http://gaana.com") }
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
Row(
|
||||
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||
.clickable(
|
||||
onClick = {
|
||||
methods.value.shareApp()
|
||||
}
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(Icons.Rounded.Share, "Share SpotiFlyer App")
|
||||
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||
Column {
|
||||
Text(
|
||||
text = "Share",
|
||||
style = SpotiFlyerTypography.h6
|
||||
Spacer(modifier = modifier.padding(start = 16.dp))
|
||||
Icon(
|
||||
YoutubeLogo(),
|
||||
"Open Youtube",
|
||||
tint = Color.Unspecified,
|
||||
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
||||
onClick = { methods.value.openPlatform("com.google.android.youtube", "http://m.youtube.com") }
|
||||
)
|
||||
)
|
||||
Text(
|
||||
text = "Share this app with your friends and family.",
|
||||
style = SpotiFlyerTypography.subtitle2
|
||||
Spacer(modifier = modifier.padding(start = 12.dp))
|
||||
Icon(
|
||||
YoutubeMusicLogo(),
|
||||
"Open Youtube Music",
|
||||
tint = Color.Unspecified,
|
||||
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
||||
onClick = { methods.value.openPlatform("com.google.android.apps.youtube.music", "https://music.youtube.com/") }
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.padding(top = 8.dp))
|
||||
Card(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
border = BorderStroke(1.dp, Color.Gray) // Gray
|
||||
) {
|
||||
Column(modifier.padding(12.dp)) {
|
||||
Text(
|
||||
text = "Support Development",
|
||||
style = SpotiFlyerTypography.body1,
|
||||
color = colorAccent
|
||||
)
|
||||
Spacer(modifier = Modifier.padding(top = 6.dp))
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth().clickable(
|
||||
onClick = { methods.value.openPlatform("", "http://github.com/Shabinder/SpotiFlyer") }
|
||||
)
|
||||
.padding(vertical = 6.dp)
|
||||
) {
|
||||
Icon(GithubLogo(), "Open Project Repo", tint = Color(0xFFCCCCCC))
|
||||
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||
Column {
|
||||
Text(
|
||||
text = "GitHub",
|
||||
style = SpotiFlyerTypography.h6
|
||||
)
|
||||
Text(
|
||||
text = "Star / Fork the project on Github.",
|
||||
style = SpotiFlyerTypography.subtitle2
|
||||
)
|
||||
}
|
||||
}
|
||||
Row(
|
||||
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||
.clickable(onClick = { methods.value.openPlatform("", "http://github.com/Shabinder/SpotiFlyer") }),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(Icons.Rounded.Flag, "Help Translate", Modifier.size(32.dp))
|
||||
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||
Column {
|
||||
Text(
|
||||
text = "Translate",
|
||||
style = SpotiFlyerTypography.h6
|
||||
)
|
||||
Text(
|
||||
text = "Help us translate this app in your local language.",
|
||||
style = SpotiFlyerTypography.subtitle2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var isDonationDialogVisible by remember { mutableStateOf(false) }
|
||||
|
||||
DonationDialog(
|
||||
isDonationDialogVisible
|
||||
) {
|
||||
isDonationDialogVisible = false
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||
.clickable(onClick = { isDonationDialogVisible = true }),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(Icons.Rounded.CardGiftcard, "Support Developer")
|
||||
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||
Column {
|
||||
Text(
|
||||
text = "Donate",
|
||||
style = SpotiFlyerTypography.h6
|
||||
)
|
||||
Text(
|
||||
text = "If you think I deserve to get paid for my work, you can support me here.",
|
||||
//text = "SpotiFlyer will always be, Free and Open-Source. You can however show us that you care by sending a small donation.",
|
||||
style = SpotiFlyerTypography.subtitle2
|
||||
)
|
||||
}
|
||||
}
|
||||
Row(
|
||||
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||
.clickable(
|
||||
onClick = {
|
||||
methods.value.shareApp()
|
||||
}
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(Icons.Rounded.Share, "Share SpotiFlyer App")
|
||||
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||
Column {
|
||||
Text(
|
||||
text = "Share",
|
||||
style = SpotiFlyerTypography.h6
|
||||
)
|
||||
Text(
|
||||
text = "Share this app with your friends and family.",
|
||||
style = SpotiFlyerTypography.subtitle2
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VerticalScrollbar(
|
||||
modifier = Modifier.padding(end = 2.dp).align(Alignment.CenterEnd).fillMaxHeight(),
|
||||
adapter = rememberScrollbarAdapter(stateVertical)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -392,19 +404,35 @@ fun HistoryColumn(
|
||||
Text("No History Available", style = SpotiFlyerTypography.h4.copy(fontWeight = FontWeight.Light), textAlign = TextAlign.Center)
|
||||
}
|
||||
} else {
|
||||
LazyColumn(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
content = {
|
||||
items(it.distinctBy { record -> record.coverUrl }) { record ->
|
||||
DownloadRecordItem(
|
||||
item = record,
|
||||
loadImage,
|
||||
onItemClicked
|
||||
)
|
||||
}
|
||||
},
|
||||
modifier = Modifier.padding(top = 8.dp).fillMaxSize()
|
||||
)
|
||||
Box {
|
||||
|
||||
val listState = rememberLazyListState()
|
||||
val itemList = it.distinctBy { record -> record.coverUrl }
|
||||
|
||||
LazyColumn(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
content = {
|
||||
items(itemList) { record ->
|
||||
DownloadRecordItem(
|
||||
item = record,
|
||||
loadImage,
|
||||
onItemClicked
|
||||
)
|
||||
}
|
||||
},
|
||||
state = listState,
|
||||
modifier = Modifier.padding(top = 8.dp).fillMaxSize()
|
||||
)
|
||||
|
||||
VerticalScrollbar(
|
||||
modifier = Modifier.padding(end = 2.dp).align(Alignment.CenterEnd).fillMaxHeight(),
|
||||
adapter = rememberScrollbarAdapter(
|
||||
scrollState = listState,
|
||||
itemCount = itemList.size,
|
||||
averageItemSize = 70.dp
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,14 +67,6 @@ actual fun DownloadImageTick() {
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun DonationDialog(
|
||||
isVisible:Boolean,
|
||||
onDismiss:()->Unit
|
||||
){
|
||||
|
||||
}
|
||||
|
||||
actual fun montserratFont() = FontFamily(
|
||||
Font("font/montserrat_light.ttf", FontWeight.Light),
|
||||
Font("font/montserrat_regular.ttf", FontWeight.Normal),
|
||||
|
@ -0,0 +1,46 @@
|
||||
package com.shabinder.common.uikit
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.ScrollState
|
||||
import androidx.compose.foundation.ScrollbarAdapter
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
actual val MARGIN_SCROLLBAR: Dp = 8.dp
|
||||
|
||||
actual typealias ScrollbarAdapter = androidx.compose.foundation.ScrollbarAdapter
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
actual fun rememberScrollbarAdapter(
|
||||
scrollState: LazyListState,
|
||||
itemCount: Int,
|
||||
averageItemSize: Dp
|
||||
): ScrollbarAdapter =
|
||||
androidx.compose.foundation.rememberScrollbarAdapter(
|
||||
scrollState = scrollState,
|
||||
itemCount = itemCount,
|
||||
averageItemSize = averageItemSize
|
||||
)
|
||||
|
||||
@Composable
|
||||
actual fun rememberScrollbarAdapter(
|
||||
scrollState: ScrollState
|
||||
): ScrollbarAdapter = remember(scrollState) {
|
||||
ScrollbarAdapter(scrollState)
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun VerticalScrollbar(
|
||||
modifier: Modifier,
|
||||
adapter: ScrollbarAdapter
|
||||
) {
|
||||
androidx.compose.foundation.VerticalScrollbar(
|
||||
modifier = modifier,
|
||||
adapter = adapter
|
||||
)
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
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.Dialog
|
||||
import com.shabinder.common.models.methods
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
actual fun DonationDialog(
|
||||
isVisible:Boolean,
|
||||
onDismiss:()->Unit
|
||||
){
|
||||
AnimatedVisibility(
|
||||
isVisible
|
||||
) {
|
||||
|
||||
Dialog(onDismiss) {
|
||||
Card(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
border = BorderStroke(1.dp, Color.Gray) // Gray
|
||||
) {
|
||||
Column(Modifier.padding(16.dp)) {
|
||||
Text(
|
||||
"Support Us",
|
||||
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 = "International Donations (Outside India).",
|
||||
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 = "Indian Donations (UPI / PayTM / PhonePe / Cards).",
|
||||
style = SpotiFlyerTypography.subtitle2
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -21,8 +21,8 @@ plugins {
|
||||
kotlin("plugin.serialization")
|
||||
}
|
||||
|
||||
val statelyVersion = "1.1.6"
|
||||
val statelyIsoVersion = "1.1.6-a1"
|
||||
val statelyVersion = "1.1.7"
|
||||
val statelyIsoVersion = "1.1.7-a1"
|
||||
|
||||
kotlin {
|
||||
sourceSets {
|
||||
|
@ -161,6 +161,9 @@ actual class Dir actual constructor(
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
} catch (e: OutOfMemoryError) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,10 +212,10 @@ class ForegroundService : Service(), CoroutineScope {
|
||||
is DownloadResult.Error -> {
|
||||
launch {
|
||||
logger.d(tag) { it.message }
|
||||
logger.d(tag) { "${track.title} Requesting Download thru Android DM" }
|
||||
downloadUsingDM(url, track.outputFilePath, track)
|
||||
/*logger.d(tag) { "${track.title} Requesting Download thru Android DM" }
|
||||
downloadUsingDM(url, track.outputFilePath, track)*/
|
||||
removeFromNotification("Downloading ${track.title}")
|
||||
downloaded++
|
||||
failed++
|
||||
}
|
||||
updateNotification()
|
||||
sendTrackBroadcast(Status.FAILED.name,track)
|
||||
@ -247,15 +247,16 @@ class ForegroundService : Service(), CoroutineScope {
|
||||
removeFromNotification("Processing ${track.title}")
|
||||
}
|
||||
logger.d(tag) { "${track.title} Download Completed" }
|
||||
downloaded++
|
||||
} catch (
|
||||
e: KotlinNullPointerException
|
||||
e: Exception
|
||||
) {
|
||||
// Try downloading using android DM
|
||||
logger.d(tag) { "${track.title} Download Failed! Error:Fetch!!!!" }
|
||||
logger.d(tag) { "${track.title} Requesting Download thru Android DM" }
|
||||
downloadUsingDM(url, track.outputFilePath, track)
|
||||
failed++
|
||||
/*logger.d(tag) { "${track.title} Requesting Download thru Android DM" }
|
||||
downloadUsingDM(url, track.outputFilePath, track)*/
|
||||
}
|
||||
downloaded++
|
||||
removeFromNotification("Downloading ${track.title}")
|
||||
}
|
||||
}
|
||||
@ -263,7 +264,7 @@ class ForegroundService : Service(), CoroutineScope {
|
||||
}
|
||||
|
||||
/**
|
||||
* If fetch Fails , Android Download Manager To RESCUE!!
|
||||
* If Custom Downloader Fails , Android Download Manager To RESCUE!!
|
||||
**/
|
||||
private fun downloadUsingDM(url: String, outputDir: String, track: TrackDetails) {
|
||||
launch {
|
||||
|
@ -61,9 +61,21 @@ compose.desktop {
|
||||
mainClass = "MainKt"
|
||||
description = "Music Downloader for Spotify, Gaana, Youtube Music."
|
||||
nativeDistributions {
|
||||
modules("java.sql", "java.security.jgss")
|
||||
modules("java.sql", "java.security.jgss", "jdk.crypto.ec")
|
||||
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
|
||||
packageName = "SpotiFlyer"
|
||||
copyright = "© 2021 Shabinder. All rights reserved."
|
||||
vendor = "Shabinder"
|
||||
val iconsRoot = project.file("src/jvmMain/resources/drawable")
|
||||
macOS {
|
||||
iconFile.set(iconsRoot.resolve("spotiflyer.icns"))
|
||||
}
|
||||
windows {
|
||||
iconFile.set(iconsRoot.resolve("spotiflyer.ico"))
|
||||
}
|
||||
linux {
|
||||
iconFile.set(iconsRoot.resolve("spotiflyer.png"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -14,12 +14,14 @@
|
||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import androidx.compose.desktop.AppManager
|
||||
import androidx.compose.desktop.DesktopMaterialTheme
|
||||
import androidx.compose.desktop.Window
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.IntSize
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import com.arkivanov.decompose.extensions.compose.jetbrains.rememberRootComponent
|
||||
import com.arkivanov.mvikotlin.core.lifecycle.LifecycleRegistry
|
||||
@ -31,7 +33,6 @@ import com.shabinder.common.di.FetchPlatformQueryResult
|
||||
import com.shabinder.common.di.initKoin
|
||||
import com.shabinder.common.di.isInternetAccessible
|
||||
import com.shabinder.common.models.Actions
|
||||
import com.shabinder.common.models.AllPlatforms
|
||||
import com.shabinder.common.models.PlatformActions
|
||||
import com.shabinder.common.models.TrackDetails
|
||||
import com.shabinder.common.root.SpotiFlyerRoot
|
||||
@ -41,8 +42,12 @@ import com.shabinder.common.uikit.SpotiFlyerShapes
|
||||
import com.shabinder.common.uikit.SpotiFlyerTypography
|
||||
import com.shabinder.common.uikit.colorOffWhite
|
||||
import com.shabinder.database.Database
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.awt.Desktop
|
||||
import java.net.URI
|
||||
import javax.swing.JFileChooser
|
||||
import javax.swing.JFileChooser.APPROVE_OPTION
|
||||
import javax.swing.JFileChooser.CANCEL_OPTION
|
||||
|
||||
private val koin = initKoin(enableNetworkLogs = true).koin
|
||||
private lateinit var showToast: (String)->Unit
|
||||
@ -52,7 +57,7 @@ fun main() {
|
||||
val lifecycle = LifecycleRegistry()
|
||||
lifecycle.resume()
|
||||
|
||||
Window("SpotiFlyer") {
|
||||
Window("SpotiFlyer",size = IntSize(450,800)) {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = Color.Black,
|
||||
@ -89,19 +94,39 @@ private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot =
|
||||
}
|
||||
|
||||
override fun setDownloadDirectoryAction() {
|
||||
showToast("TODO: Still needs to be Implemented")
|
||||
val fileChooser = JFileChooser().apply {
|
||||
fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
|
||||
}
|
||||
when (fileChooser.showOpenDialog(AppManager.focusedWindow?.window)) {
|
||||
APPROVE_OPTION -> {
|
||||
val directory = fileChooser.selectedFile
|
||||
if(directory.canWrite()){
|
||||
directories.setDownloadDirectory(directory.absolutePath)
|
||||
showPopUpMessage("Set New Download Directory:\n${directory.absolutePath}")
|
||||
} else {
|
||||
showPopUpMessage("Cant Write to Selected Directory!")
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
showPopUpMessage("No Directory Selected")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun queryActiveTracks() {}
|
||||
override fun queryActiveTracks() {/**/}
|
||||
|
||||
override fun giveDonation() {
|
||||
|
||||
openLink("https://razorpay.com/payment-button/pl_GnKuuDBdBu0ank/view/?utm_source=payment_button&utm_medium=button&utm_campaign=payment_button")
|
||||
}
|
||||
|
||||
override fun shareApp() {}
|
||||
override fun shareApp() = openLink("https://github.com/Shabinder/SpotiFlyer")
|
||||
|
||||
override fun openPlatform(packageID: String, platformLink: String) {
|
||||
showToast("TODO: Still needs to be Implemented")
|
||||
override fun openPlatform(packageID: String, platformLink: String) = openLink(platformLink)
|
||||
|
||||
fun openLink(link:String) {
|
||||
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
|
||||
Desktop.getDesktop().browse(URI(link))
|
||||
}
|
||||
}
|
||||
|
||||
override fun writeMp3Tags(trackDetails: TrackDetails) {/*IMPLEMENTED*/}
|
||||
|
@ -0,0 +1,6 @@
|
||||
<vector android:height="24dp" android:viewportHeight="456"
|
||||
android:viewportWidth="456" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M61.179,282h-41.2c-6,0 -10.9,4.9 -10.9,10.9v152.2c0,6 4.9,10.9 10.9,10.9h41.2c6,0 10.9,-4.9 10.9,-10.9V292.9C72.079,286.9 67.179,282 61.179,282z"/>
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M443.179,294.4c-0.3,-0.4 -0.6,-0.8 -0.8,-1.2c-6.1,-6.8 -16.4,-7.7 -23.6,-2.1c-20,16.3 -49.2,39.8 -68.1,55.1c-16.7,13.3 -37.3,21 -58.7,21.8l-51.2,1.7c-9.4,0.3 -18.2,-4.5 -23,-12.6l-5.7,-9.7c-1.5,-2.5 -2.5,-5.3 -3.1,-8.2c-2.6,-13.9 6.5,-27.4 20.4,-30l52.9,-10c8.5,-1.7 14.3,-9.7 13.3,-18.3c-1,-8.2 -8,-14.3 -16.2,-14.4c-0.3,0 -0.7,0 -0.8,0c-0.4,0 -0.9,0 -1.3,0l-71.2,-2.9c-24.7,-0.9 -46,3.9 -71.2,16.1l-42.8,20.7v114l35.9,-6.6c0.1,-0.1 0.2,-0.1 0.3,-0.1c13.9,-2 23.1,-2.9 38.2,-2.2l107.5,5c33.7,1.4 66.8,-9.7 92.7,-31.3l74.4,-61.7C447.979,311.7 448.879,301.3 443.179,294.4z"/>
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M307.379,0c-61.2,0.1 -110.7,49.7 -110.8,110.8c0,0.1 0,0.1 0,0.1c0,61.2 49.7,110.8 110.9,110.8s110.8,-49.7 110.8,-110.9S368.579,0 307.379,0zM333.079,80h13.4c5.5,0 10,4.5 10,10s-4.5,10 -10,10h-13.4c-2,7.8 -6,14.9 -11.7,20.6c-7.5,7.5 -17.5,11.9 -28.1,12.5l37.7,35.7c4,3.8 4.2,10.1 0.4,14.1s-10.1,4.2 -14.1,0.4l-55.9,-52.9c-1.9,-1.9 -3.1,-4.5 -3.1,-7.2c-0.1,-5.6 4.4,-10.1 10,-10.2h22.4c6.2,0.1 12.2,-2.3 16.7,-6.7c1.8,-1.9 3.3,-4 4.6,-6.3h-43.7c-5.5,0 -10,-4.5 -10,-10s4.5,-10 10,-10h43.7c-3.7,-8 -11.9,-14 -21.3,-14h-22.4c-5.5,0 -10,-4.5 -10,-10s4.5,-10 10,-10h78.2c5.5,0 10,4.5 10,10s-4.5,10 -10,10h-19.2C330.079,70.3 331.979,75 333.079,80z"/>
|
||||
</vector>
|
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:viewportHeight="435.505"
|
||||
android:viewportWidth="435.505" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M403.496,101.917c-4.104,-5.073 -8.877,-9.705 -14.166,-13.839c0.707,13.117 -0.508,27.092 -3.668,41.884c-8.627,40.413 -29.256,74.754 -59.656,99.304c-30.375,24.533 -68.305,37.502 -109.686,37.502h-60.344l-19.533,91.512c-3.836,17.959 -19.943,30.99 -38.303,30.99H70.938l-4.898,22.484c-1.258,5.79 0.17,11.839 3.887,16.453c3.715,4.614 9.324,7.298 15.25,7.298h66.498c9.24,0 17.225,-6.459 19.152,-15.495L193.667,313h76.188c36.854,0 70.527,-11.464 97.384,-33.152c26.869,-21.697 45.129,-52.186 52.807,-88.162C427.822,155.309 422.253,125.106 403.496,101.917z"/>
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M117.292,354.191l22.84,-107.008h76.188c36.852,0 70.527,-11.465 97.383,-33.154c26.867,-21.697 45.129,-52.186 52.809,-88.161c7.773,-36.378 2.207,-66.58 -16.553,-89.769C331.952,13.832 301.17,0 269.633,0H103.639c-9.209,0 -17.174,6.417 -19.135,15.414L12.505,345.938c-1.26,5.789 0.168,11.838 3.887,16.453c3.713,4.613 9.32,7.296 15.248,7.296h66.5C107.38,369.687 115.36,363.229 117.292,354.191zM178.235,75.291h52.229c12.287,0 23.274,5.149 30.145,14.129c7.297,9.539 9.431,22.729 5.853,36.188c-0.047,0.171 -0.088,0.342 -0.131,0.516c-6.57,27.73 -33.892,50.291 -60.898,50.291h-50.05L178.235,75.291z"/>
|
||||
</vector>
|
BIN
desktop/src/jvmMain/resources/drawable/spotiflyer.icns
Normal file
BIN
desktop/src/jvmMain/resources/drawable/spotiflyer.icns
Normal file
Binary file not shown.
BIN
desktop/src/jvmMain/resources/drawable/spotiflyer.ico
Normal file
BIN
desktop/src/jvmMain/resources/drawable/spotiflyer.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
BIN
desktop/src/jvmMain/resources/drawable/spotiflyer.png
Normal file
BIN
desktop/src/jvmMain/resources/drawable/spotiflyer.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 95 KiB |
Loading…
Reference in New Issue
Block a user