Skip to content

Commit eda2dcc

Browse files
committed
feat(settings): Add blur fullscreen lyrics setting
This commit introduces a new setting to blur the background of the fullscreen lyrics screen. The setting is added to the app's settings screen and affects the appearance of the fullscreen lyrics. A new library `haze` is added to implement the blur effect.
1 parent 8990537 commit eda2dcc

File tree

9 files changed

+518
-564
lines changed

9 files changed

+518
-564
lines changed

app/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,10 @@ dependencies {
321321

322322
// Jetbrains Markdown
323323
api(libs.markdown)
324+
325+
// Blur Haze
326+
implementation(libs.haze)
327+
implementation(libs.haze.material)
324328
}
325329
aboutLibraries {
326330
prettyPrint = true

app/src/main/java/com/maxrave/simpmusic/data/dataStore/DataStoreManager.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,25 @@ class DataStoreManager(
707707
}
708708
}
709709

710+
val blurFullscreenLyrics =
711+
settingsDataStore.data.map { preferences ->
712+
preferences[BLUR_FULLSCREEN_LYRICS] ?: FALSE
713+
}
714+
715+
suspend fun setBlurFullscreenLyrics(blur: Boolean) {
716+
withContext(Dispatchers.IO) {
717+
if (blur) {
718+
settingsDataStore.edit { settings ->
719+
settings[BLUR_FULLSCREEN_LYRICS] = TRUE
720+
}
721+
} else {
722+
settingsDataStore.edit { settings ->
723+
settings[BLUR_FULLSCREEN_LYRICS] = FALSE
724+
}
725+
}
726+
}
727+
}
728+
710729
companion object Settings {
711730
val COOKIE = stringPreferencesKey("cookie")
712731
val LOGGED_IN = stringPreferencesKey("logged_in")
@@ -751,6 +770,7 @@ class DataStoreManager(
751770
val ENDLESS_QUEUE = stringPreferencesKey("endless_queue")
752771
val SHOULD_SHOW_LOG_IN_REQUIRED_ALERT = stringPreferencesKey("should_show_log_in_required_alert")
753772
val AUTO_CHECK_FOR_UPDATES = stringPreferencesKey("auto_check_for_updates")
773+
val BLUR_FULLSCREEN_LYRICS = stringPreferencesKey("blur_fullscreen_lyrics")
754774
const val REPEAT_MODE_OFF = "REPEAT_MODE_OFF"
755775
const val REPEAT_ONE = "REPEAT_ONE"
756776
const val REPEAT_ALL = "REPEAT_ALL"

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

Lines changed: 461 additions & 414 deletions
Large diffs are not rendered by default.

app/src/main/java/com/maxrave/simpmusic/ui/screen/home/SettingScreen.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ fun SettingScreen(
189189
val proxyHost by viewModel.proxyHost.collectAsStateWithLifecycle()
190190
val proxyPort by viewModel.proxyPort.collectAsStateWithLifecycle()
191191
val autoCheckUpdate by viewModel.autoCheckUpdate.collectAsStateWithLifecycle()
192+
val blurFullscreenLyrics by viewModel.blurFullscreenLyrics.collectAsStateWithLifecycle()
192193
var checkForUpdateSubtitle by rememberSaveable {
193194
mutableStateOf("")
194195
}
@@ -269,6 +270,12 @@ fun SettingScreen(
269270
smallSubtitle = true,
270271
switch = (enableTranslucentNavBar to { viewModel.setTranslucentBottomBar(it) }),
271272
)
273+
SettingItem(
274+
title = stringResource(R.string.blur_fullscreen_lyrics),
275+
subtitle = stringResource(R.string.blur_fullscreen_lyrics_description),
276+
smallSubtitle = true,
277+
switch = (blurFullscreenLyrics to { viewModel.setBlurFullscreenLyrics(it) }),
278+
)
272279
}
273280
}
274281
item(key = "content") {

app/src/main/java/com/maxrave/simpmusic/ui/screen/player/NowPlayingScreen.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ fun NowPlayingScreen(
378378
sharedViewModel = sharedViewModel,
379379
color = startColor.value,
380380
navController = navController,
381+
shouldHaze = sharedViewModel.blurFullscreenLyrics(),
381382
) {
382383
showFullscreenLyrics = false
383384
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ class SettingsViewModel(
123123
val proxyPort: StateFlow<Int> = _proxyPort
124124
private var _autoCheckUpdate = MutableStateFlow(false)
125125
val autoCheckUpdate: StateFlow<Boolean> = _autoCheckUpdate
126+
private var _blurFullscreenLyrics = MutableStateFlow(false)
127+
val blurFullscreenLyrics: StateFlow<Boolean> = _blurFullscreenLyrics
126128

127129
private var _alertData: MutableStateFlow<SettingAlertState?> = MutableStateFlow(null)
128130
val alertData: StateFlow<SettingAlertState?> = _alertData
@@ -170,11 +172,27 @@ class SettingsViewModel(
170172
getCanvasCache()
171173
getTranslucentBottomBar()
172174
getAutoCheckUpdate()
175+
getBlurFullscreenLyrics()
173176
viewModelScope.launch {
174177
calculateDataFraction()
175178
}
176179
}
177180

181+
private fun getBlurFullscreenLyrics() {
182+
viewModelScope.launch {
183+
dataStoreManager.blurFullscreenLyrics.collect { blurFullscreenLyrics ->
184+
_blurFullscreenLyrics.value = blurFullscreenLyrics == DataStoreManager.TRUE
185+
}
186+
}
187+
}
188+
189+
fun setBlurFullscreenLyrics(blurFullscreenLyrics: Boolean) {
190+
viewModelScope.launch {
191+
dataStoreManager.setBlurFullscreenLyrics(blurFullscreenLyrics)
192+
getBlurFullscreenLyrics()
193+
}
194+
}
195+
178196
private fun getAutoCheckUpdate() {
179197
viewModelScope.launch {
180198
dataStoreManager.autoCheckForUpdates.collect { autoCheckUpdate ->

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

Lines changed: 2 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -380,119 +380,6 @@ class SharedViewModel(
380380
}
381381
}
382382
}
383-
// val job2 =
384-
// launch {
385-
// handler.nowPlaying.collectLatest { nowPlaying ->
386-
// Log.w("MainActivity", "nowPlaying collect $nowPlaying")
387-
// nowPlaying?.let { now ->
388-
// _format.value = null
389-
// _songInfo.value = null
390-
// _canvas.value = null
391-
// canvasJob?.cancel()
392-
// getSongInfo(now.mediaId)
393-
// getSkipSegments(now.mediaId)
394-
// basicWidget.performUpdate(
395-
// context,
396-
// simpleMediaServiceHandler!!,
397-
// null,
398-
// )
399-
// downloadImageForWidgetJob?.cancel()
400-
// downloadImageForWidgetJob =
401-
// viewModelScope.launch {
402-
// val p = getScreenSize(context)
403-
// val widgetImageSize = p.x.coerceAtMost(p.y)
404-
// val imageRequest =
405-
// ImageRequest.Builder(context)
406-
// .data(nowPlaying.mediaMetadata.artworkUri)
407-
// .size(widgetImageSize)
408-
// .placeholder(R.drawable.holder_video)
409-
// .target(
410-
// onSuccess = { drawable ->
411-
// basicWidget.updateImage(
412-
// context,
413-
// drawable.toBitmap(
414-
// widgetImageSize,
415-
// widgetImageSize,
416-
// ),
417-
// )
418-
// },
419-
// onStart = { holder ->
420-
// if (holder != null) {
421-
// basicWidget.updateImage(
422-
// context,
423-
// holder.toBitmap(
424-
// widgetImageSize,
425-
// widgetImageSize,
426-
// ),
427-
// )
428-
// }
429-
// },
430-
// onError = {
431-
// AppCompatResources.getDrawable(
432-
// context,
433-
// R.drawable.holder_video,
434-
// )
435-
// ?.let { it1 ->
436-
// basicWidget.updateImage(
437-
// context,
438-
// it1.toBitmap(
439-
// widgetImageSize,
440-
// widgetImageSize,
441-
// ),
442-
// )
443-
// }
444-
// },
445-
// ).build()
446-
// ImageLoader(context).execute(imageRequest)
447-
// }
448-
// }
449-
// if (nowPlaying != null) {
450-
// transformEmit(nowPlaying)
451-
// val tempSong =
452-
// simpleMediaServiceHandler!!.queueData.first()?.listTracks?.getOrNull(
453-
// getCurrentMediaItemIndex(),
454-
// )
455-
// if (tempSong != null) {
456-
// Log.d("Check tempSong", tempSong.toString())
457-
// mainRepository.insertSong(
458-
// tempSong.toSongEntity(),
459-
// ).first()
460-
// .let { id ->
461-
// Log.d("Check insertSong", id.toString())
462-
// }
463-
// mainRepository.getSongById(tempSong.videoId)
464-
// .collectLatest { songEntity ->
465-
// _songDB.value = songEntity
466-
// if (songEntity != null) {
467-
// Log.w(
468-
// "Check like",
469-
// "SharedViewModel nowPlaying collect ${songEntity.liked}",
470-
// )
471-
// _liked.value = songEntity.liked
472-
// }
473-
// }
474-
// mainRepository.updateSongInLibrary(
475-
// LocalDateTime.now(),
476-
// tempSong.videoId,
477-
// )
478-
// mainRepository.updateListenCount(tempSong.videoId)
479-
// tempSong.durationSeconds?.let {
480-
// mainRepository.updateDurationSeconds(
481-
// it,
482-
// tempSong.videoId,
483-
// )
484-
// }
485-
// videoId.postValue(tempSong.videoId)
486-
// transformEmit(nowPlaying)
487-
// }
488-
// val index = getCurrentMediaItemIndex() + 1
489-
// Log.w("Check index", index.toString())
490-
// val size = simpleMediaServiceHandler!!.queueData.first()?.listTracks?.size ?: 0
491-
// Log.w("Check size", size.toString())
492-
// Log.w("Check loadingMore", loadingMore.toString())
493-
// }
494-
// }
495-
// }
496383
val controllerJob =
497384
launch {
498385
Log.w(tag, "ControllerJob is running")
@@ -515,53 +402,18 @@ class SharedViewModel(
515402
}
516403
}
517404
}
518-
// val getDurationJob = launch {
519-
// combine(nowPlayingState, mediaState){ nowPlayingState, mediaState ->
520-
// Pair(nowPlayingState, mediaState)
521-
// }.collectLatest {
522-
// val nowPlaying = it.first
523-
// val media = it.second
524-
// if (media is SimpleMediaState.Ready && nowPlaying?.mediaItem != null) {
525-
// if (nowPlaying.mediaItem.isSong()) {
526-
// Log.w(tag, "Duration is ${media.duration}")
527-
// getCanvas(nowPlaying.mediaItem.mediaId, media.duration.toInt())
528-
// }
529-
// getLyricsFromFormat(nowPlaying.mediaItem.mediaId, media.duration.toInt())
530-
// }
531-
// }
532-
// }
533-
// getDurationJob.join()
534-
// val job3 =
535-
// launch {
536-
// handler.controlState.collectLatest { controlState ->
537-
// _shuffleModeEnabled.value = controlState.isShuffle
538-
// _repeatMode.value = controlState.repeatState
539-
// isPlaying.value = controlState.isPlaying
540-
// }
541-
// }
542-
// val job10 =
543-
// launch {
544-
// nowPlayingMediaItem.collectLatest { now ->
545-
// Log.d(
546-
// "Now Playing",
547-
// now?.mediaId + now?.mediaMetadata?.title
548-
// )
549-
// }
550-
// }
551405
job1.join()
552406
controllerJob.join()
553407
sleepTimerJob.join()
554408
playlistNameJob.join()
555-
// job2.join()
556-
// job3.join()
557-
// nowPlayingJob.join()
558-
// job10.join()
559409
}
560410
if (runBlocking { dataStoreManager.loggedIn.first() } == TRUE) {
561411
getYouTubeLiked()
562412
}
563413
}
564414

415+
fun blurFullscreenLyrics(): Boolean = runBlocking { dataStoreManager.blurFullscreenLyrics.first() == TRUE }
416+
565417
private fun getLikeStatus(videoId: String?) {
566418
viewModelScope.launch {
567419
if (videoId != null) {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,4 +382,6 @@
382382
<string name="do_not_show_again">Do not show again</string>
383383
<string name="auto_check_for_update">Automatic check for update</string>
384384
<string name="auto_check_for_update_description">Checking for update when you open app</string>
385+
<string name="blur_fullscreen_lyrics">Blur fullscreen lyrics effect</string>
386+
<string name="blur_fullscreen_lyrics_description">Blurring the background of the Fullscreen lyrics screen effect</string>
385387
</resources>

gradle/libs.versions.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ koin-bom = "4.0.0-RC1"
6060
md = "0.7.3"
6161
store = "5.1.0-alpha05"
6262
ui-text-android = "1.7.7"
63+
haze = "1.3.0"
6364

6465
[libraries]
6566
desugaring = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "desugaring"}
@@ -147,6 +148,8 @@ kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect" }
147148
ksoup-html = { group = "com.mohamedrejeb.ksoup", name = "ksoup-html", version.ref = "ksoup" }
148149
ksoup-entities = { group = "com.mohamedrejeb.ksoup", name = "ksoup-entities", version.ref = "ksoup" }
149150
markdown = { module = "org.jetbrains:markdown", version.ref = "md" }
151+
haze = { module = "dev.chrisbanes.haze:haze", version.ref = "haze" }
152+
haze-material = { module = "dev.chrisbanes.haze:haze-materials", version.ref = "haze" }
150153
store = { module = "org.mobilenativefoundation.store:store5", version.ref = "store" }
151154
# Use NewPipeExtractor from the Outertune project (Thanks to @DD3Boh)
152155
newpipe-extractor = { module = "com.github.gechoto:NewPipeExtractor", version = "00cf7dad9e49933c7faaa382c9c7b1e7afb28a7d" }

0 commit comments

Comments
 (0)