diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index 847dc6dc..00bda4ce 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -23,6 +23,7 @@
+
diff --git a/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImages.kt b/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImages.kt
index e56a099e..a9eb45ce 100644
--- a/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImages.kt
+++ b/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImages.kt
@@ -81,6 +81,9 @@ actual fun SpotifyLogo() = getCachedPainter(R.drawable.ic_spotify_logo)
@Composable
actual fun SaavnLogo() = getCachedPainter(R.drawable.ic_jio_saavn_logo)
+@Composable
+actual fun SoundCloudLogo() = getCachedPainter(R.drawable.ic_soundcloud)
+
@Composable
actual fun GaanaLogo() = getCachedPainter(R.drawable.ic_gaana)
diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImages.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImages.kt
index 6be14625..557bfb49 100644
--- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImages.kt
+++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImages.kt
@@ -58,6 +58,9 @@ expect fun SpotifyLogo(): Painter
@Composable
expect fun SaavnLogo(): Painter
+@Composable
+expect fun SoundCloudLogo(): Painter
+
@Composable
expect fun YoutubeLogo(): Painter
diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/SpotiFlyerMainUi.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/SpotiFlyerMainUi.kt
index 670106fb..eab0877b 100644
--- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/SpotiFlyerMainUi.kt
+++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/screens/SpotiFlyerMainUi.kt
@@ -83,12 +83,14 @@ import com.shabinder.common.main.SpotiFlyerMain
import com.shabinder.common.main.SpotiFlyerMain.HomeCategory
import com.shabinder.common.models.DownloadRecord
import com.shabinder.common.models.Actions
+import com.shabinder.common.models.spotify.Source
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.SoundCloudLogo
import com.shabinder.common.uikit.SpotifyLogo
import com.shabinder.common.uikit.VerticalScrollbar
import com.shabinder.common.uikit.YoutubeLogo
@@ -319,6 +321,17 @@ fun AboutColumn(
)
)
}
+ Spacer(modifier = Modifier.padding(top = 8.dp))
+ Row(horizontalArrangement = Arrangement.Center, modifier = modifier.fillMaxWidth()) {
+ Icon(
+ SoundCloudLogo(),
+ "${Strings.open()} Sound Cloud",
+ tint = Color.Unspecified,
+ modifier = Modifier.clip(SpotiFlyerShapes.medium).clickable(
+ onClick = { Actions.instance.openPlatform("com.soundcloud.android", "https://soundcloud.com/") }
+ )
+ )
+ }
}
}
Spacer(modifier = Modifier.padding(top = 8.dp))
diff --git a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImages.kt b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImages.kt
index 859ce01b..125a1763 100644
--- a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImages.kt
+++ b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImages.kt
@@ -86,6 +86,10 @@ actual fun SpotifyLogo() =
actual fun SaavnLogo() =
getCachedPainter("drawable/ic_jio_saavn_logo.xml")
+@Composable
+actual fun SoundCloudLogo() =
+ getCachedPainter("drawable/ic_soundcloud.xml")
+
@Composable
actual fun YoutubeLogo() =
getCachedPainter("drawable/ic_youtube.xml")
diff --git a/common/core-components/src/desktopMain/kotlin/com.shabinder.common.core_components/file_manager/DesktopFileManager.kt b/common/core-components/src/desktopMain/kotlin/com.shabinder.common.core_components/file_manager/DesktopFileManager.kt
index a355f89e..6ef248dd 100644
--- a/common/core-components/src/desktopMain/kotlin/com.shabinder.common.core_components/file_manager/DesktopFileManager.kt
+++ b/common/core-components/src/desktopMain/kotlin/com.shabinder.common.core_components/file_manager/DesktopFileManager.kt
@@ -107,9 +107,11 @@ class DesktopFileManager(
override suspend fun cacheImage(image: Any, path: String): Unit = withContext(dispatcherIO) {
try {
+ val file = File(path)
+ if(!file.parentFile.exists()) createDirectories()
(image as? BufferedImage)?.let {
- ImageIO.write(it, "jpeg", File(path))
- }
+ ImageIO.write(it, "jpeg", file)
+ }
} catch (e: IOException) {
e.printStackTrace()
}
diff --git a/common/data-models/src/main/res/drawable/ic_soundcloud.xml b/common/data-models/src/main/res/drawable/ic_soundcloud.xml
new file mode 100644
index 00000000..faaf1945
--- /dev/null
+++ b/common/data-models/src/main/res/drawable/ic_soundcloud.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/common/providers/src/commonMain/kotlin/com.shabinder.common.providers/saavn/SaavnProvider.kt b/common/providers/src/commonMain/kotlin/com.shabinder.common.providers/saavn/SaavnProvider.kt
index 5568238a..a6c7e836 100644
--- a/common/providers/src/commonMain/kotlin/com.shabinder.common.providers/saavn/SaavnProvider.kt
+++ b/common/providers/src/commonMain/kotlin/com.shabinder.common.providers/saavn/SaavnProvider.kt
@@ -29,7 +29,7 @@ class SaavnProvider(
).apply {
val pageLink = fullLink.substringAfter("saavn.com/").substringBefore("?")
when {
- pageLink.contains("/song/", true) -> {
+ pageLink.contains("song/", true) -> {
getSong(fullLink).value.let {
folderType = "Tracks"
subFolder = ""
@@ -38,7 +38,7 @@ class SaavnProvider(
coverUrl = it.image.replace("http:", "https:")
}
}
- pageLink.contains("/album/", true) -> {
+ pageLink.contains("album/", true) -> {
getAlbum(fullLink).value.let {
folderType = "Albums"
subFolder = removeIllegalChars(it.title)
@@ -47,7 +47,7 @@ class SaavnProvider(
coverUrl = it.image.replace("http:", "https:")
}
}
- pageLink.contains("/featured/", true) -> { // Playlist
+ pageLink.contains("featured/", true) -> { // Playlist
getPlaylist(fullLink).value.let {
folderType = "Playlists"
subFolder = removeIllegalChars(it.listname)
diff --git a/common/providers/src/commonMain/kotlin/com.shabinder.common.providers/saavn/requests/JioSaavnRequests.kt b/common/providers/src/commonMain/kotlin/com.shabinder.common.providers/saavn/requests/JioSaavnRequests.kt
index a9d6faec..ca914ab7 100644
--- a/common/providers/src/commonMain/kotlin/com.shabinder.common.providers/saavn/requests/JioSaavnRequests.kt
+++ b/common/providers/src/commonMain/kotlin/com.shabinder.common.providers/saavn/requests/JioSaavnRequests.kt
@@ -18,9 +18,16 @@ import io.github.shabinder.utils.getBoolean
import io.github.shabinder.utils.getJsonArray
import io.github.shabinder.utils.getJsonObject
import io.github.shabinder.utils.getString
-import io.ktor.client.*
-import io.ktor.client.request.*
-import kotlinx.serialization.json.*
+import io.ktor.client.HttpClient
+import io.ktor.client.request.get
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.JsonArray
+import kotlinx.serialization.json.JsonObject
+import kotlinx.serialization.json.JsonPrimitive
+import kotlinx.serialization.json.buildJsonArray
+import kotlinx.serialization.json.buildJsonObject
+import kotlinx.serialization.json.jsonPrimitive
+import kotlinx.serialization.json.put
import kotlin.collections.set
interface JioSaavnRequests {
@@ -32,9 +39,9 @@ interface JioSaavnRequests {
trackName: String,
trackArtists: List,
preferredQuality: AudioQuality
- ): SuspendableEvent, Throwable> = searchForSong(trackName).map { songs ->
- val bestMatch = sortByBestMatch(songs, trackName, trackArtists).keys.firstOrNull() ?:
- throw SpotiFlyerException.DownloadLinkFetchFailed("No SAAVN Match Found for $trackName")
+ ): SuspendableEvent, Throwable> = searchForSong(trackName).map { songs ->
+ val bestMatch = sortByBestMatch(songs, trackName, trackArtists).keys.firstOrNull()
+ ?: throw SpotiFlyerException.DownloadLinkFetchFailed("No SAAVN Match Found for $trackName")
var audioQuality: AudioQuality = AudioQuality.KBPS160
val m4aLink: String by getSongFromID(bestMatch).map { song ->
@@ -46,7 +53,7 @@ interface JioSaavnRequests {
song.media_url.requireNotNull().replaceAfterLast("_", "${optimalQuality.kbps}.mp4")
}
- Pair(m4aLink,audioQuality)
+ Pair(m4aLink, audioQuality)
}
suspend fun searchForSong(
@@ -235,8 +242,8 @@ interface JioSaavnRequests {
for (result in tracks) {
var hasCommonWord = false
- val resultName = result.title.lowercase().replace("/", " ")
- val trackNameWords = trackName.lowercase().split(" ")
+ val resultName = result.title.toLowerCase().replace("/", " ")
+ val trackNameWords = trackName.toLowerCase().split(" ")
for (nameWord in trackNameWords) {
if (nameWord.isNotBlank() && FuzzySearch.partialRatio(nameWord, resultName) > 85) hasCommonWord = true
@@ -256,11 +263,11 @@ interface JioSaavnRequests {
// String Containing All Artist Names from JioSaavn Search Result
val artistListString = mutableSetOf().apply {
result.more_info?.singers?.split(",")?.let { addAll(it) }
- result.more_info?.primary_artists?.lowercase()?.split(",")?.let { addAll(it) }
+ result.more_info?.primary_artists?.toLowerCase()?.split(",")?.let { addAll(it) }
}.joinToString(" , ")
for (artist in trackArtists) {
- if (FuzzySearch.partialRatio(artist.lowercase(), artistListString) > 85)
+ if (FuzzySearch.partialRatio(artist.toLowerCase(), artistListString) > 85)
artistMatchNumber++
}