diff --git a/README.md b/README.md
index 4ef945e..8ac3a02 100644
--- a/README.md
+++ b/README.md
@@ -8,17 +8,5 @@ App that listens to your notifications and provides lyrics for the currently pla
## Supported players
Any player that uses the MediaSession API _should_ be supported
-## Using Spotify for lyrics
-If you plan on using the "Use Spotify for lyrics" feature you will need to create a Spotify developer app.
-You can do so [here](https://developer.spotify.com/dashboard/applications), and you should follow these steps:
-- Click on "Create app" in your developer dashboard
-- Name your app whatever you'd like and give it a description
-- Add the following redirect URI: `lyricsgrabbr://spotify-auth`
-- Select `Android` under "Which API/SDKs are you planning to use?"
-- Save your newly created app
-- You will be redirected to your app page where you can click on "Settings" and find your Client ID under the "Basic Information" tab
-
-You can then use the Client ID of your app inside LyricsGrabbr to authenticate with Spotify.
-
## License
The project is licensed under the GPL3 license while the assets (icon) are licensed under the creative commons license.
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 99ad3aa..23269ab 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -107,31 +107,30 @@ android {
dependencies {
- implementation("androidx.core:core-ktx:1.12.0")
- implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
- implementation("androidx.lifecycle:lifecycle-runtime-compose:2.7.0")
- implementation("androidx.activity:activity-compose:1.8.2")
- implementation(platform("androidx.compose:compose-bom:2023.10.01"))
+ implementation("androidx.core:core-ktx:1.13.1")
+ implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.3")
+ implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.3")
+ implementation("androidx.activity:activity-compose:1.9.0")
+ implementation(platform("androidx.compose:compose-bom:2024.06.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
- implementation("androidx.compose.material3:material3:1.1.2")
- implementation("com.google.android.material:material:1.11.0")
- implementation("androidx.compose.material:material-icons-extended:1.5.4")
+ implementation("androidx.compose.material3:material3:1.2.1")
+ implementation("com.google.android.material:material:1.12.0")
+ implementation("androidx.compose.material:material-icons-extended:1.6.8")
implementation("androidx.core:core-splashscreen:1.0.1")
- implementation("androidx.navigation:navigation-compose:2.7.6")
- implementation("androidx.datastore:datastore-preferences:1.0.0")
+ implementation("androidx.navigation:navigation-compose:2.7.7")
+ implementation("androidx.datastore:datastore-preferences:1.1.1")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
- implementation("io.coil-kt:coil:2.5.0")
- implementation("io.coil-kt:coil-compose:2.5.0")
+ implementation("io.coil-kt:coil:2.6.0")
+ implementation("io.coil-kt:coil-compose:2.6.0")
implementation("org.jsoup:jsoup:1.17.2")
- implementation("com.adamratzman:spotify-api-kotlin-core:4.0.2")
testImplementation("junit:junit:4.13.2")
- androidTestImplementation("androidx.test.ext:junit:1.1.5")
- androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
- androidTestImplementation(platform("androidx.compose:compose-bom:2023.10.01"))
+ androidTestImplementation("androidx.test.ext:junit:1.2.1")
+ androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
+ androidTestImplementation(platform("androidx.compose:compose-bom:2024.06.00"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 841a497..4783888 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -31,19 +31,6 @@
-
-
-
-
-
-
-
-
-
by preferencesDataStore(
name = PREFERENCES_NAME
)
-const val SPOTIFY_REDIRECT_URI = "lyricsgrabbr://spotify-auth"
-
class LGApp: Application() {
lateinit var settingsPreferencesRepository: SettingsPreferencesRepository
lateinit var homeRepository: HomeRepository
lateinit var lyricsRepository: LyricsRepository
- val credentialStore by lazy {
- SpotifyDefaultCredentialStore(
- clientId = "",
- redirectUri = SPOTIFY_REDIRECT_URI,
- applicationContext = applicationContext
- )
- }
override fun onCreate() {
super.onCreate()
settingsPreferencesRepository = SettingsPreferencesRepository(dataStore)
homeRepository = HomeRepository(applicationContext)
- lyricsRepository = LyricsRepository(applicationContext)
+ lyricsRepository = LyricsRepository()
}
}
diff --git a/app/src/main/java/com/illusionman1212/lyricsgrabbr/MainActivity.kt b/app/src/main/java/com/illusionman1212/lyricsgrabbr/MainActivity.kt
index 9a842dd..3540200 100644
--- a/app/src/main/java/com/illusionman1212/lyricsgrabbr/MainActivity.kt
+++ b/app/src/main/java/com/illusionman1212/lyricsgrabbr/MainActivity.kt
@@ -1,6 +1,5 @@
package com.illusionman1212.lyricsgrabbr
-import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
@@ -22,7 +21,6 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
@@ -60,10 +58,6 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
- val context = LocalContext.current
- val activity = context as Activity
- val application = activity.application as LGApp
-
val settingsViewModel: SettingsViewModel = viewModel(
factory = SettingsViewModel.Factory
)
@@ -83,7 +77,6 @@ class MainActivity : ComponentActivity() {
}
runBlocking {
- settingsViewModel.updateSpotifyAuthStatus(application.credentialStore.spotifyToken?.refreshToken != null)
appTheme.intValue = settingsViewModel.getAppTheme()
}
diff --git a/app/src/main/java/com/illusionman1212/lyricsgrabbr/SpotifyPkceLoginActivityImpl.kt b/app/src/main/java/com/illusionman1212/lyricsgrabbr/SpotifyPkceLoginActivityImpl.kt
deleted file mode 100644
index 1d4cee6..0000000
--- a/app/src/main/java/com/illusionman1212/lyricsgrabbr/SpotifyPkceLoginActivityImpl.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.illusionman1212.lyricsgrabbr
-
-import android.widget.Toast
-import com.adamratzman.spotify.SpotifyClientApi
-import com.adamratzman.spotify.SpotifyScope
-import com.adamratzman.spotify.auth.pkce.AbstractSpotifyPkceLoginActivity
-import com.illusionman1212.lyricsgrabbr.viewmodels.SettingsViewModel
-
-class SpotifyPkceLoginActivityImpl: AbstractSpotifyPkceLoginActivity() {
- override val clientId: String = CLIENT_ID
- override val redirectUri: String = SPOTIFY_REDIRECT_URI
- override val scopes: List = listOf(SpotifyScope.UserReadCurrentlyPlaying)
-
- override fun onFailure(exception: Exception) {
- Toast.makeText(this, "Failed to authenticate", Toast.LENGTH_SHORT).show()
- settingsViewModel?.updateSpotifyAuthStatus(false)
- }
-
- override fun onSuccess(api: SpotifyClientApi) {
- (application as LGApp).credentialStore.setSpotifyApi(api)
- Toast.makeText(this, "Successfully authenticated", Toast.LENGTH_SHORT).show()
- settingsViewModel?.updateSpotifyAuthStatus(true)
- }
-
- companion object {
- var CLIENT_ID = ""
- var settingsViewModel: SettingsViewModel? = null
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/illusionman1212/lyricsgrabbr/data/LyricsRepository.kt b/app/src/main/java/com/illusionman1212/lyricsgrabbr/data/LyricsRepository.kt
index e60b454..3eb4dbf 100644
--- a/app/src/main/java/com/illusionman1212/lyricsgrabbr/data/LyricsRepository.kt
+++ b/app/src/main/java/com/illusionman1212/lyricsgrabbr/data/LyricsRepository.kt
@@ -1,13 +1,6 @@
package com.illusionman1212.lyricsgrabbr.data
-import android.content.Context
import android.net.Uri
-import com.illusionman1212.lyricsgrabbr.R
-import com.illusionman1212.lyricsgrabbr.data.network.GET
-import com.illusionman1212.lyricsgrabbr.data.network.NetworkHelper
-import com.illusionman1212.lyricsgrabbr.utils.await
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.json.Json
import org.jsoup.Jsoup
import org.jsoup.internal.StringUtil
import org.jsoup.nodes.Element
@@ -15,58 +8,7 @@ import org.jsoup.nodes.Node
import org.jsoup.nodes.TextNode
import org.jsoup.select.NodeVisitor
-@Serializable
-data class LyricLine(
- val startTimeMs: ULong,
- val words: String,
-)
-
-@Serializable
-data class Lyrics(
- val syncType: String,
- val lines: List,
- val language: String,
-)
-
-@Serializable
-data class SuccessResponse(
- val lyrics: Lyrics,
-)
-
-class LyricsRepository(private val context: Context) {
- private val networkHelper = NetworkHelper(context)
- private val json = Json {
- ignoreUnknownKeys = true
- }
-
- suspend fun fetchLyricsFromSpotify(trackId: String): Pair {
- val builder = Uri.Builder()
- val url = builder.scheme("https")
- .authority("api.lyricstify.vercel.app")
- .appendPath("v1")
- .appendPath("lyrics")
- .appendPath(trackId)
- .build()
-
- val res = networkHelper.client.newCall(
- GET(url.toString())
- ).await()
-
- val body = res.body?.string()
-
- if (res.isSuccessful) {
- return Pair(json.decodeFromString(SuccessResponse.serializer(), body!!)
- .lyrics
- .lines.joinToString(separator = "\n") { it.words }, true)
- } else {
- if (res.code == 404) {
- return Pair(context.resources.getString(R.string.spotify_no_lyrics_error), false)
- }
-
- return Pair(context.resources.getString(R.string.generic_error), false)
- }
- }
-
+class LyricsRepository {
fun fetchLyricsFromGenius(url: Uri): String {
val doc = Jsoup.connect(url.toString()).userAgent(USER_AGENT).get()
val divs = doc.select("div[data-lyrics-container]")
diff --git a/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/components/LGIconButton.kt b/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/components/LGIconButton.kt
index 2116a96..f8922da 100644
--- a/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/components/LGIconButton.kt
+++ b/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/components/LGIconButton.kt
@@ -2,17 +2,16 @@ package com.illusionman1212.lyricsgrabbr.ui.components
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
-import androidx.compose.foundation.layout.RowScope
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.IconButton
-import androidx.compose.material3.PlainTooltipBox
import androidx.compose.material3.Text
+import androidx.compose.material3.TooltipBox
+import androidx.compose.material3.TooltipDefaults
+import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.layout.ModifierInfo
import androidx.compose.ui.layout.layoutId
-import com.illusionman1212.lyricsgrabbr.utils.mirror
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -22,16 +21,19 @@ fun LGIconButton(
badge: (@Composable BoxScope.() -> Unit)? = null,
content: @Composable () -> Unit
) {
+ val tooltipState = rememberTooltipState()
+
Layout(
content = {
- PlainTooltipBox(
+ TooltipBox(
+ positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
tooltip = {
Text(text = tooltip)
},
+ state = tooltipState,
) {
IconButton(
onClick = onClick,
- Modifier.tooltipAnchor(),
content = content
)
}
@@ -73,4 +75,4 @@ fun LGIconButton(
// }
// }
// }
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/screens/Home.kt b/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/screens/Home.kt
index 302d4fd..161407f 100644
--- a/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/screens/Home.kt
+++ b/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/screens/Home.kt
@@ -90,7 +90,6 @@ import com.illusionman1212.lyricsgrabbr.LGApp
import com.illusionman1212.lyricsgrabbr.ui.components.forwardingPainter
import com.illusionman1212.lyricsgrabbr.utils.annotatedStringResource
import com.illusionman1212.lyricsgrabbr.viewmodels.LyricsViewModel
-import com.illusionman1212.lyricsgrabbr.viewmodels.SettingsViewModel
import kotlinx.coroutines.launch
@@ -125,7 +124,7 @@ fun HomePage(
) }
var shouldShowNotificationPermissionRationale by remember { mutableStateOf(
ActivityCompat.shouldShowRequestPermissionRationale(
- context as android.app.Activity,
+ context,
POST_NOTIFICATIONS
)
)}
@@ -141,7 +140,6 @@ fun HomePage(
val song = lastNotification.collectAsStateWithLifecycle().value
val uiState = homeViewModel.uiState.collectAsStateWithLifecycle().value
- var getLyricsFromSpotify by rememberSaveable { mutableStateOf(false)}
LaunchedEffect(Unit) {
if (!shouldShowNotificationPermissionRationale)
@@ -159,17 +157,9 @@ fun HomePage(
LaunchedEffect(song) {
if (song != null && song.title != uiState.notification?.title && song.artist != uiState.notification?.artist) {
- val spotifyApi = application.credentialStore.getSpotifyClientPkceApi()
- val useSpotifyApi = song.packageName == "com.spotify.music" && spotifyApi != null
- getLyricsFromSpotify = useSpotifyApi
-
homeViewModel.setSong(song)
- if (useSpotifyApi) {
- homeViewModel.makeRequestToSpotify(spotifyApi!!)
- } else {
- homeViewModel.makeRequestToGenius(song.title, song.artist)
- }
+ homeViewModel.makeRequestToGenius(song.title, song.artist)
}
}
@@ -335,7 +325,7 @@ fun HomePage(
},
navigateToLyrics = navigateToLyrics,
setLyricsTitle = { id, title, subtitle, url ->
- lyricsViewModel.onSongChange(id, title, subtitle, url, getLyricsFromSpotify)
+ lyricsViewModel.onSongChange(id, title, subtitle, url)
},
)
}
diff --git a/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/screens/Lyrics.kt b/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/screens/Lyrics.kt
index d69b821..5a01609 100644
--- a/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/screens/Lyrics.kt
+++ b/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/screens/Lyrics.kt
@@ -54,11 +54,7 @@ fun LyricsPage(
val uiState = lyricsViewModel.uiState.collectAsStateWithLifecycle().value
LaunchedEffect(uiState.song, uiState.artist, uiState.url) {
- if (uiState.useSpotifyApi) {
- lyricsViewModel.fetchLyricsFromSpotify()
- } else {
- lyricsViewModel.fetchLyricsFromGenius()
- }
+ lyricsViewModel.fetchLyricsFromGenius()
}
Scaffold(
diff --git a/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/screens/Settings.kt b/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/screens/Settings.kt
index 10a1620..3b47751 100644
--- a/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/screens/Settings.kt
+++ b/app/src/main/java/com/illusionman1212/lyricsgrabbr/ui/screens/Settings.kt
@@ -1,6 +1,5 @@
package com.illusionman1212.lyricsgrabbr.ui.screens
-import android.app.Activity
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -13,19 +12,16 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.text.ClickableText
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.outlined.Palette
import androidx.compose.material3.Icon
-import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
-import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -36,35 +32,20 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.platform.LocalUriHandler
-import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.SpanStyle
-import androidx.compose.ui.text.font.FontStyle
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.input.PasswordVisualTransformation
-import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.adamratzman.spotify.SpotifyClientApi
-import com.adamratzman.spotify.SpotifyException
-import com.adamratzman.spotify.auth.pkce.startSpotifyClientPkceLoginActivity
-import com.illusionman1212.lyricsgrabbr.LGApp
import com.illusionman1212.lyricsgrabbr.R
-import com.illusionman1212.lyricsgrabbr.SpotifyPkceLoginActivityImpl
import com.illusionman1212.lyricsgrabbr.ui.components.LGAlertDialog
import com.illusionman1212.lyricsgrabbr.ui.components.LGRadioButton
import com.illusionman1212.lyricsgrabbr.ui.theme.ColorSecondaryLight
import com.illusionman1212.lyricsgrabbr.data.Theme
import com.illusionman1212.lyricsgrabbr.ui.components.LGIconButton
-import com.illusionman1212.lyricsgrabbr.utils.annotatedStringResource
import com.illusionman1212.lyricsgrabbr.utils.mirror
import com.illusionman1212.lyricsgrabbr.viewmodels.SettingsState
import com.illusionman1212.lyricsgrabbr.viewmodels.SettingsViewModel
-import kotlinx.coroutines.runBlocking
private val Themes = hashMapOf(
Theme.LIGHT.ordinal to R.string.theme_light,
@@ -72,56 +53,6 @@ private val Themes = hashMapOf(
Theme.SYSTEM.ordinal to R.string.theme_system
)
-// TODO: this is here as a reference because I think I will need a guard in the future
-fun Activity.guardValidSpotifyApi(
- classBackTo: Class,
- alreadyTriedToReauthenticate: Boolean = false,
- block: suspend (api: SpotifyClientApi) -> T
-): T? {
- return runBlocking {
- val app = (application as LGApp)
-
- try {
- val token = app.credentialStore.spotifyToken
- ?: throw SpotifyException.ReAuthenticationNeededException()
- val usesPkceAuth = token.refreshToken != null
- val api = (if (usesPkceAuth) app.credentialStore.getSpotifyClientPkceApi()
- else app.credentialStore.getSpotifyImplicitGrantApi())
- ?: throw SpotifyException.ReAuthenticationNeededException()
-
- block(api)
- } catch (e: SpotifyException) {
- e.printStackTrace()
- val api = app.credentialStore.getSpotifyClientPkceApi()!!
- if (!alreadyTriedToReauthenticate) {
- try {
- api.refreshToken()
- app.credentialStore.spotifyToken = api.token
- block(api)
- } catch (e: SpotifyException.ReAuthenticationNeededException) {
- e.printStackTrace()
- return@runBlocking guardValidSpotifyApi(
- classBackTo = classBackTo,
- alreadyTriedToReauthenticate = true,
- block = block
- )
- } catch (e: IllegalArgumentException) {
- e.printStackTrace()
- return@runBlocking guardValidSpotifyApi(
- classBackTo = classBackTo,
- alreadyTriedToReauthenticate = true,
- block = block
- )
- }
- } else {
- //pkceClassBackTo = classBackTo
- startSpotifyClientPkceLoginActivity(SpotifyPkceLoginActivityImpl::class.java)
- null
- }
- }
- }
-}
-
@Composable
fun SettingsPage(
goBack: () -> Unit,
@@ -159,7 +90,6 @@ fun SettingsPage(
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Appearance(viewModel, uiState)
- Lyrics(viewModel, uiState)
}
}
}
@@ -229,84 +159,6 @@ fun ThemeDialog(
}
}
-@Composable
-fun Lyrics(viewModel: SettingsViewModel, uiState: SettingsState) {
- val context = LocalContext.current
- val activity = context as Activity
- val application = activity.application as LGApp
-
- var isDialogOpen by remember { mutableStateOf(false) }
- var spotifyIdValue by remember { mutableStateOf("") }
-
- SettingGroup(stringResource(id = R.string.lyrics)) {
- ToggleSetting(
- title = stringResource(id = R.string.use_spotify_api),
- checked = uiState.isSpotifyAuthed,
- icon = painterResource(id = R.drawable.spotify),
- onClick = {
- if (uiState.isSpotifyAuthed) {
- application.credentialStore.clear()
- viewModel.updateSpotifyAuthStatus(false)
- } else {
- isDialogOpen = true
- }
- },
- )
- }
-
- if (isDialogOpen) {
- LGAlertDialog(
- onDismiss = { isDialogOpen = false },
- title = stringResource(id = R.string.spotify_client_id),
- buttons = {
- TextButton(onClick = { isDialogOpen = false }) {
- Text(stringResource(id = R.string.cancel))
- }
- TextButton(onClick = {
- SpotifyPkceLoginActivityImpl.CLIENT_ID = spotifyIdValue
- SpotifyPkceLoginActivityImpl.settingsViewModel = viewModel
- activity.startSpotifyClientPkceLoginActivity(SpotifyPkceLoginActivityImpl::class.java)
- isDialogOpen = false
- }) {
- Text(stringResource(id = R.string.confirm))
- }
- }
- ) {
- val linkColor = MaterialTheme.colorScheme.surfaceTint
- val spotifyDesc = annotatedStringResource(R.string.spotify_client_id_desc) {
- when (it.key) {
- "href" -> SpanStyle(color = linkColor, textDecoration = TextDecoration.Underline)
- "weight" -> SpanStyle(fontWeight = FontWeight.Bold, fontStyle = FontStyle.Italic)
- else -> null
- }
- }
- val textColor = LocalContentColor.current
- val uriHandler = LocalUriHandler.current
-
- ClickableText(
- spotifyDesc,
- onClick = { offset ->
- spotifyDesc.getStringAnnotations(tag = "href", start = offset, end = offset)
- .firstOrNull()
- ?.let {
- uriHandler.openUri(it.item)
- }
- },
- style = MaterialTheme.typography.bodyMedium.copy(color = textColor),
- )
-
- TextField(
- value = spotifyIdValue,
- onValueChange = { spotifyIdValue = it },
- placeholder = {
- Text(stringResource(id = R.string.not_set))
- },
- visualTransformation = PasswordVisualTransformation(),
- )
- }
- }
-}
-
@Composable
fun SettingGroup(title: String, content: @Composable () -> Unit) {
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
diff --git a/app/src/main/java/com/illusionman1212/lyricsgrabbr/viewmodels/HomeViewModel.kt b/app/src/main/java/com/illusionman1212/lyricsgrabbr/viewmodels/HomeViewModel.kt
index 8a0de9e..c91a989 100644
--- a/app/src/main/java/com/illusionman1212/lyricsgrabbr/viewmodels/HomeViewModel.kt
+++ b/app/src/main/java/com/illusionman1212/lyricsgrabbr/viewmodels/HomeViewModel.kt
@@ -2,17 +2,14 @@ package com.illusionman1212.lyricsgrabbr.viewmodels
import android.content.Context
import android.net.Uri
-import androidx.core.net.toUri
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
-import com.adamratzman.spotify.SpotifyClientApi
import com.illusionman1212.lyricsgrabbr.LGApp
import com.illusionman1212.lyricsgrabbr.NotificationEvent
-import com.illusionman1212.lyricsgrabbr.R
import com.illusionman1212.lyricsgrabbr.data.HomeRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
@@ -103,32 +100,6 @@ class HomeViewModel(private val context: Context, private val homeRepository: Ho
_uiState.value = _uiState.value.copy(isLoading = true, notification = song, error = null)
}
- fun makeRequestToSpotify(spotifyApi: SpotifyClientApi) {
- viewModelScope.launch {
- val track = spotifyApi.player.getCurrentlyPlaying()?.item
-
- if (track?.id == null) {
- _uiState.value = _uiState.value.copy(
- isLoading = false,
- error = context.resources.getString(R.string.no_spotify_song_playing)
- )
- } else {
- _uiState.value = _uiState.value.copy(
- isLoading = false,
- error = null,
- results = listOf(SearchResult(
- title = _uiState.value.notification!!.title,
- artist = _uiState.value.notification!!.artist,
- url = track.asTrack?.externalUrls?.spotify?.toUri() ?: Uri.EMPTY,
- artistUrl = track.asTrack?.artists?.get(0)?.externalUrls?.spotify?.toUri() ?: Uri.EMPTY,
- thumbnail = track.asTrack?.album?.images?.get(0)?.url?.toUri() ?: Uri.EMPTY,
- id = track.id!!,
- ))
- )
- }
- }
- }
-
fun makeRequestToGenius(song: String, artist: String) {
viewModelScope.launch {
_uiState.update { HomeState(true, uiState.value.results, uiState.value.notification, null) }
diff --git a/app/src/main/java/com/illusionman1212/lyricsgrabbr/viewmodels/LyricsViewModel.kt b/app/src/main/java/com/illusionman1212/lyricsgrabbr/viewmodels/LyricsViewModel.kt
index 678230e..46eb853 100644
--- a/app/src/main/java/com/illusionman1212/lyricsgrabbr/viewmodels/LyricsViewModel.kt
+++ b/app/src/main/java/com/illusionman1212/lyricsgrabbr/viewmodels/LyricsViewModel.kt
@@ -22,7 +22,6 @@ data class LyricsState(
val artist: String = "",
val url: Uri = Uri.EMPTY,
val trackId: String = "",
- val useSpotifyApi: Boolean = false,
// set by Lyrics screen
val lyrics: String = "",
@@ -35,24 +34,9 @@ class LyricsViewModel(private val lyricsRepository: LyricsRepository): ViewModel
private val _uiState = MutableStateFlow(LyricsState())
val uiState = _uiState.asStateFlow()
- fun onSongChange(trackId: String, title: String, subtitle: String, url: Uri, useSpotifyApi: Boolean) {
+ fun onSongChange(trackId: String, title: String, subtitle: String, url: Uri) {
_uiState.update {
- it.copy(song = title, artist = subtitle, url = url, useSpotifyApi = useSpotifyApi, trackId = trackId)
- }
- }
-
- fun fetchLyricsFromSpotify() {
- _uiState.value = _uiState.value.copy(isLoading = true, lyrics = "")
-
- viewModelScope.launch {
- withContext(Dispatchers.IO) {
- val (lyrics, isSuccess) = lyricsRepository.fetchLyricsFromSpotify(uiState.value.trackId)
- if (isSuccess) {
- _uiState.value = _uiState.value.copy(isLoading = false, lyrics = lyrics)
- } else {
- _uiState.value = _uiState.value.copy(isLoading = false, error = lyrics, lyrics = "")
- }
- }
+ it.copy(song = title, artist = subtitle, url = url, trackId = trackId)
}
}
diff --git a/app/src/main/java/com/illusionman1212/lyricsgrabbr/viewmodels/SettingsViewModel.kt b/app/src/main/java/com/illusionman1212/lyricsgrabbr/viewmodels/SettingsViewModel.kt
index 4402d73..8473710 100644
--- a/app/src/main/java/com/illusionman1212/lyricsgrabbr/viewmodels/SettingsViewModel.kt
+++ b/app/src/main/java/com/illusionman1212/lyricsgrabbr/viewmodels/SettingsViewModel.kt
@@ -18,7 +18,6 @@ import kotlinx.coroutines.launch
data class SettingsState(
val appTheme: Int = Theme.SYSTEM.ordinal,
- val isSpotifyAuthed: Boolean = false,
)
class SettingsViewModel(private val settingsPrefsRepo: SettingsPreferencesRepository): ViewModel() {
@@ -35,10 +34,6 @@ class SettingsViewModel(private val settingsPrefsRepo: SettingsPreferencesReposi
}
}
- fun updateSpotifyAuthStatus(isAuthed: Boolean) {
- _uiState.value = _uiState.value.copy(isSpotifyAuthed = isAuthed)
- }
-
init {
viewModelScope.launch {
settingsPrefsRepo.preferences.collectLatest {
diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml
index 226cb4a..02277b2 100644
--- a/app/src/main/res/values-ar/strings.xml
+++ b/app/src/main/res/values-ar/strings.xml
@@ -9,7 +9,6 @@
لقد انتهت مهلة الطلب، حاول مرة أخرى لاحقًا
لقد حدث خطأ، حاول مرة أخرى لاحقاً
أعد المحاولة
- عذرًا، لا يحتوي Spotify على كلمات لهذه الأغنية
لا يوجد مشغل مدعوم قيد التشغيل
@@ -25,7 +24,6 @@
يتطلب هذا التطبيق أذونات الإشعارات لبدء خدمة مقدمة بغرض الاستماع إلى إشعارات الموسيقى، ولا يمكن أن يعمل بدونها.
لم يتم منح إذن الإشعارات، لن يعمل التطبيق بشكل صحيح
منح الإذن
- No song is playing on Spotify
الإعدادات
@@ -34,10 +32,6 @@
نهار
ليلي
استخدم مظهر النظام
- استخدم Spotify للكلمات
- Spotify Client ID
- خالي
- يمكن لهذا التطبيق استخدام واجهة برمجة تطبيقات الويب الخاصة بـ Spotify للحصول على كلمات الأغاني. تحتاج إلى تقديم Spotify Client ID لاستخدام هذه الميزة. يمكنك الحصول على واحدة من هنا.\nلا يعمل هذا إلا إذا كنت تقوم بتشغيل الموسيقى من مشغل Spotify.
كلمات الأغنية
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9935d3c..2c7ba71 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -8,7 +8,6 @@
Request has timed out, try again later
An error has occurred, try again later
Retry
- Sorry, Spotify doesn\'t have lyrics for this song
No supported player is running
@@ -24,7 +23,6 @@
LyricsGrabbr requires notification permissions to start a foreground service for the purpose of listening to music notifications, and cannot function without it.
Notification permission is not granted, the app will not function properly
Grant Permission
- No song is playing on Spotify
Settings
@@ -33,10 +31,6 @@
Light
Dark
Use System Theme
- Use Spotify for lyrics
- Spotify Client ID
- Not Set
- This app can use Spotify\'s Web API to get lyrics. You need to provide a Spotify Client ID to use this feature. You can get one from here.\nThis only works if you\'re playing music from the Spotify player.
Lyrics