Skip to content

Commit 1925c0f

Browse files
authored
Merge pull request #1184 from maxrave-dev/v0.2.20/SIM-265/spotify-login-helper
v0.2.20: Option to show all cookies for Spotify Log in
2 parents 00810e0 + 4232de1 commit 1925c0f

4 files changed

Lines changed: 168 additions & 0 deletions

File tree

app/src/main/java/com/maxrave/simpmusic/ui/component/ModalBottomSheet.kt

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.maxrave.simpmusic.ui.component
22

33
import android.app.Activity
4+
import android.content.ClipData
45
import android.content.Context
56
import android.content.Intent
67
import android.os.Build
@@ -46,7 +47,10 @@ import androidx.compose.foundation.rememberScrollState
4647
import androidx.compose.foundation.shape.CircleShape
4748
import androidx.compose.foundation.shape.RoundedCornerShape
4849
import androidx.compose.foundation.text.KeyboardOptions
50+
import androidx.compose.foundation.text.selection.SelectionContainer
4951
import androidx.compose.foundation.verticalScroll
52+
import androidx.compose.material.icons.Icons
53+
import androidx.compose.material.icons.filled.ContentCopy
5054
import androidx.compose.material3.AlertDialog
5155
import androidx.compose.material3.AlertDialogDefaults
5256
import androidx.compose.material3.BasicAlertDialog
@@ -94,6 +98,8 @@ import androidx.compose.ui.graphics.painter.Painter
9498
import androidx.compose.ui.input.nestedscroll.nestedScroll
9599
import androidx.compose.ui.input.pointer.pointerInput
96100
import androidx.compose.ui.layout.ContentScale
101+
import androidx.compose.ui.platform.ClipEntry
102+
import androidx.compose.ui.platform.LocalClipboard
97103
import androidx.compose.ui.platform.LocalContext
98104
import androidx.compose.ui.platform.LocalDensity
99105
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
@@ -2763,6 +2769,99 @@ fun DevLogInBottomSheet(
27632769
}
27642770
}
27652771

2772+
@OptIn(ExperimentalMaterial3Api::class)
2773+
@Composable
2774+
fun DevCookieLogInBottomSheet(
2775+
onDismiss: () -> Unit,
2776+
type: DevLogInType,
2777+
cookies: List<Pair<String, String?>>,
2778+
) {
2779+
val clipboardManager = LocalClipboard.current
2780+
val context = LocalContext.current
2781+
val coroutineScope = rememberCoroutineScope()
2782+
val modelBottomSheetState =
2783+
rememberModalBottomSheetState(
2784+
skipPartiallyExpanded = true,
2785+
)
2786+
2787+
ModalBottomSheet(
2788+
onDismissRequest = onDismiss,
2789+
sheetState = modelBottomSheetState,
2790+
containerColor = Color.Transparent,
2791+
contentColor = Color.Transparent,
2792+
dragHandle = null,
2793+
scrimColor = Color.Black.copy(alpha = .5f),
2794+
contentWindowInsets = { WindowInsets(0, 0, 0, 0) },
2795+
) {
2796+
Card(
2797+
modifier =
2798+
Modifier
2799+
.fillMaxWidth()
2800+
.wrapContentHeight(),
2801+
shape = RoundedCornerShape(topStart = 8.dp, topEnd = 8.dp),
2802+
colors = CardDefaults.cardColors().copy(containerColor = Color(0xFF242424)),
2803+
) {
2804+
Column(
2805+
horizontalAlignment = Alignment.CenterHorizontally,
2806+
) {
2807+
Spacer(modifier = Modifier.height(5.dp))
2808+
Card(
2809+
modifier =
2810+
Modifier
2811+
.width(60.dp)
2812+
.height(4.dp),
2813+
colors =
2814+
CardDefaults.cardColors().copy(
2815+
containerColor = Color(0xFF474545),
2816+
),
2817+
shape = RoundedCornerShape(50),
2818+
) {}
2819+
Spacer(modifier = Modifier.height(10.dp))
2820+
Text(text = stringResource(R.string.list_all_cookies_of_this_page), style = typo.labelSmall)
2821+
cookies.forEach { cookie ->
2822+
Row(
2823+
verticalAlignment = Alignment.CenterVertically,
2824+
horizontalArrangement = Arrangement.spacedBy(12.dp),
2825+
modifier = Modifier.padding(12.dp),
2826+
) {
2827+
Text(
2828+
text = cookie.first,
2829+
style = typo.bodyMedium,
2830+
modifier = Modifier.weight(1f),
2831+
)
2832+
SelectionContainer(
2833+
modifier = Modifier.weight(2f),
2834+
) {
2835+
Text(
2836+
text = cookie.second ?: "",
2837+
style = typo.bodyMedium,
2838+
)
2839+
}
2840+
IconButton(
2841+
onClick = {
2842+
coroutineScope.launch {
2843+
clipboardManager.setClipEntry(
2844+
ClipEntry(
2845+
clipData = ClipData.newPlainText(cookie.first, cookie.second ?: ""),
2846+
),
2847+
)
2848+
Toast.makeText(context, context.getString(R.string.copied_to_clipboard), Toast.LENGTH_SHORT).show()
2849+
}
2850+
},
2851+
) {
2852+
Icon(
2853+
imageVector = Icons.Default.ContentCopy,
2854+
contentDescription = "Copy",
2855+
)
2856+
}
2857+
}
2858+
}
2859+
EndOfModalBottomSheet()
2860+
}
2861+
}
2862+
}
2863+
}
2864+
27662865
@Composable
27672866
fun EndOfModalBottomSheet() {
27682867
Box(

app/src/main/java/com/maxrave/simpmusic/ui/screen/login/SpotifyLoginScreen.kt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ import androidx.compose.foundation.layout.fillMaxSize
1515
import androidx.compose.foundation.layout.padding
1616
import androidx.compose.foundation.layout.size
1717
import androidx.compose.material.icons.Icons
18+
import androidx.compose.material.icons.filled.Cookie
1819
import androidx.compose.material.icons.filled.LogoDev
1920
import androidx.compose.material3.ExperimentalMaterial3Api
21+
import androidx.compose.material3.FloatingActionButton
2022
import androidx.compose.material3.Icon
2123
import androidx.compose.material3.IconButton
2224
import androidx.compose.material3.Text
@@ -41,6 +43,7 @@ import androidx.media3.common.util.UnstableApi
4143
import androidx.navigation.NavController
4244
import com.maxrave.simpmusic.R
4345
import com.maxrave.simpmusic.common.Config
46+
import com.maxrave.simpmusic.ui.component.DevCookieLogInBottomSheet
4447
import com.maxrave.simpmusic.ui.component.DevLogInBottomSheet
4548
import com.maxrave.simpmusic.ui.component.DevLogInType
4649
import com.maxrave.simpmusic.ui.component.RippleIconButton
@@ -69,10 +72,17 @@ fun SpotifyLoginScreen(
6972
val context = LocalContext.current
7073
val hazeState = rememberHazeState()
7174
val spotifyStatus by viewModel.spotifyStatus.collectAsStateWithLifecycle()
75+
76+
val fullSpotifyCookies by viewModel.fullSpotifyCookies.collectAsStateWithLifecycle()
77+
7278
var devLoginSheet by rememberSaveable {
7379
mutableStateOf(false)
7480
}
7581

82+
var showCookiesBottomSheet by rememberSaveable {
83+
mutableStateOf(false)
84+
}
85+
7686
// Hide bottom navigation when entering this screen
7787
LaunchedEffect(Unit) {
7888
hideBottomNavigation()
@@ -122,6 +132,14 @@ fun SpotifyLoginScreen(
122132
view: WebView?,
123133
url: String?,
124134
) {
135+
CookieManager.getInstance().getCookie(url)?.let { cookie ->
136+
val cookies =
137+
cookie.split("; ").map {
138+
val (key, value) = it.split("=")
139+
key to value
140+
}
141+
viewModel.setFullSpotifyCookies(cookies)
142+
}
125143
if (url == Config.SPOTIFY_ACCOUNT_URL) {
126144
CookieManager.getInstance().getCookie(url)?.let {
127145
viewModel.saveSpotifySpdc(it)
@@ -190,6 +208,26 @@ fun SpotifyLoginScreen(
190208
containerColor = Color.Transparent,
191209
),
192210
)
211+
212+
FloatingActionButton(
213+
onClick = {
214+
showCookiesBottomSheet = true
215+
},
216+
containerColor = Color(0xFF40D96A),
217+
modifier =
218+
Modifier
219+
.align(
220+
Alignment.BottomStart,
221+
).padding(innerPadding)
222+
.padding(
223+
25.dp,
224+
),
225+
) {
226+
Icon(
227+
Icons.Default.Cookie,
228+
"Cookies",
229+
)
230+
}
193231
}
194232
if (devLoginSheet) {
195233
DevLogInBottomSheet(
@@ -211,4 +249,14 @@ fun SpotifyLoginScreen(
211249
type = DevLogInType.Spotify,
212250
)
213251
}
252+
253+
if (showCookiesBottomSheet) {
254+
DevCookieLogInBottomSheet(
255+
onDismiss = {
256+
showCookiesBottomSheet = false
257+
},
258+
type = DevLogInType.Spotify,
259+
cookies = fullSpotifyCookies,
260+
)
261+
}
214262
}

app/src/main/java/com/maxrave/simpmusic/viewModel/LogInViewModel.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import androidx.media3.common.util.UnstableApi
66
import com.maxrave.simpmusic.viewModel.base.BaseViewModel
77
import kotlinx.coroutines.flow.MutableStateFlow
88
import kotlinx.coroutines.flow.StateFlow
9+
import kotlinx.coroutines.flow.asStateFlow
910
import kotlinx.coroutines.launch
1011

1112
@UnstableApi
@@ -15,6 +16,12 @@ class LogInViewModel(
1516
private val _spotifyStatus: MutableStateFlow<Boolean> = MutableStateFlow(false)
1617
val spotifyStatus: StateFlow<Boolean> get() = _spotifyStatus
1718

19+
private val _fullSpotifyCookies: MutableStateFlow<List<Pair<String, String?>>> = MutableStateFlow(emptyList())
20+
val fullSpotifyCookies: StateFlow<List<Pair<String, String?>>> get() = _fullSpotifyCookies.asStateFlow()
21+
22+
private val _fullYouTubeCookies: MutableStateFlow<List<Pair<String, String?>>> = MutableStateFlow(emptyList())
23+
val fullYouTubeCookies: StateFlow<List<Pair<String, String?>>> get() = _fullYouTubeCookies.asStateFlow()
24+
1825
fun saveSpotifySpdc(cookie: String) {
1926
viewModelScope.launch {
2027
cookie
@@ -41,4 +48,16 @@ class LogInViewModel(
4148
dataStoreManager.setDataSyncId(dataSyncId)
4249
}
4350
}
51+
52+
fun setFullSpotifyCookies(cookies: List<Pair<String, String?>>) {
53+
viewModelScope.launch {
54+
_fullSpotifyCookies.value = cookies
55+
}
56+
}
57+
58+
fun setFullYouTubeCookies(cookies: List<Pair<String, String?>>) {
59+
viewModelScope.launch {
60+
_fullYouTubeCookies.value = cookies
61+
}
62+
}
4463
}

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,4 +455,6 @@
455455
<string name="backup_downloaded">Backup downloaded data</string>
456456
<string name="backup_downloaded_description">Backup all downloaded songs\'s data</string>
457457
<string name="no_playlist_found">No local playlists found, please create one first</string>
458+
<string name="list_all_cookies_of_this_page">List all cookies of this page</string>
459+
<string name="copied_to_clipboard">Copied to clipboard</string>
458460
</resources>

0 commit comments

Comments
 (0)