From 4a728072e7035532a5130eae1b9d817fd5ab6995 Mon Sep 17 00:00:00 2001 From: hemanth-thirdi Date: Fri, 2 Jan 2026 19:40:56 +0530 Subject: [PATCH 1/3] Fix submodule MediaServiceCore initialization --- .../ui/component/PlayerControlLayout.kt | 71 +++++++++++++++++++ .../simpmusic/viewModel/SharedViewModel.kt | 28 ++++++++ 2 files changed, 99 insertions(+) diff --git a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/component/PlayerControlLayout.kt b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/component/PlayerControlLayout.kt index 98f928fd2..6fb21272b 100644 --- a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/component/PlayerControlLayout.kt +++ b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/component/PlayerControlLayout.kt @@ -13,10 +13,12 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.Forward5 import androidx.compose.material.icons.rounded.PauseCircle import androidx.compose.material.icons.rounded.PlayCircle import androidx.compose.material.icons.rounded.Repeat import androidx.compose.material.icons.rounded.RepeatOne +import androidx.compose.material.icons.rounded.Replay5 import androidx.compose.material.icons.rounded.Shuffle import androidx.compose.material.icons.rounded.SkipNext import androidx.compose.material.icons.rounded.SkipPrevious @@ -86,6 +88,29 @@ fun PlayerControlLayout( } } } + Box(Modifier.weight(1f), contentAlignment = Alignment.Center) { + Box( + modifier = + Modifier + .background(transparent) + .size(smallIcon.second) + .aspectRatio(1f) + .clip( + CircleShape, + ) + .clickable { + onUIEvent(UIEvent.Backward5) + }, + contentAlignment = Alignment.Center, + ) { + Icon( + imageVector = Icons.Rounded.Replay5, + tint = Color.White, + contentDescription = "", + modifier = Modifier.size(smallIcon.first), + ) + } + } Box(Modifier.weight(1f), contentAlignment = Alignment.Center) { Box( modifier = @@ -111,6 +136,29 @@ fun PlayerControlLayout( ) } } + Box(Modifier.weight(1f), contentAlignment = Alignment.Center) { + Box( + modifier = + Modifier + .background(transparent) + .size(mediumIcon.second) + .aspectRatio(1f) + .clip( + CircleShape, + ) + .clickable { + onUIEvent(UIEvent.Backward) + }, + contentAlignment = Alignment.Center, + ) { + Icon( + imageVector = Icons.Rounded.Replay10, + tint = Color.White, + contentDescription = "", + modifier = Modifier.size(mediumIcon.first), + ) + } + } Box(Modifier.weight(1f), contentAlignment = Alignment.Center) { Box( modifier = @@ -145,6 +193,29 @@ fun PlayerControlLayout( } } } + Box(Modifier.weight(1f), contentAlignment = Alignment.Center) { + Box( + modifier = + Modifier + .background(transparent) + .size(mediumIcon.second) + .aspectRatio(1f) + .clip( + CircleShape, + ) + .clickable { + onUIEvent(UIEvent.Forward5) + }, + contentAlignment = Alignment.Center, + ) { + Icon( + imageVector = Icons.Rounded.Forward5, + tint = Color.White, + contentDescription = "", + modifier = Modifier.size(mediumIcon.first), + ) + } + } Box(Modifier.weight(1f), contentAlignment = Alignment.Center) { Box( modifier = diff --git a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SharedViewModel.kt b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SharedViewModel.kt index 64ff2744e..052ad58c9 100644 --- a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SharedViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SharedViewModel.kt @@ -770,6 +770,30 @@ class SharedViewModel( dataStoreManager.setPlayerVolume(newVolume) mediaPlayerHandler.onPlayerEvent(PlayerEvent.UpdateVolume(newVolume)) } + + UIEvent.Forward5 -> { + val current = timeline.value.current + val total = timeline.value.total + if (total > 0) { + val newProgress = (current + 5000).coerceAtMost(total) + val progressPercent = (newProgress.toFloat() / total.toFloat()) * 100f + mediaPlayerHandler.onPlayerEvent( + PlayerEvent.UpdateProgress(progressPercent), + ) + } + } + + UIEvent.Backward5 -> { + val current = timeline.value.current + val total = timeline.value.total + if (total > 0) { + val newProgress = (current - 5000).coerceAtLeast(0) + val progressPercent = (newProgress.toFloat() / total.toFloat()) * 100f + mediaPlayerHandler.onPlayerEvent( + PlayerEvent.UpdateProgress(progressPercent), + ) + } + } } } @@ -1626,6 +1650,10 @@ sealed class UIEvent { ) : UIEvent() data object ToggleLike : UIEvent() + + data object Forward5 : UIEvent() + + data object Backward5 : UIEvent() } enum class LyricsProvider { From c5ce19e7ec06c6a124f386d1ecbc00dcc1c906cf Mon Sep 17 00:00:00 2001 From: Hemanth K R <80522401+Hemanth2332@users.noreply.github.com> Date: Tue, 23 Jun 2026 23:05:58 +0530 Subject: [PATCH 2/3] =?UTF-8?q?added=20=C2=B15=20when=20tapped=20on=20imag?= =?UTF-8?q?e.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../composeResources/values/strings.xml | 2 + .../ui/component/PlayerControlLayout.kt | 33 +---- .../simpmusic/ui/screen/home/SettingScreen.kt | 8 ++ .../ui/screen/player/FullscreenPlayer.kt | 66 +++++----- .../ui/screen/player/NowPlayingScreen.kt | 121 +++++++++++++++++- .../simpmusic/viewModel/SettingsViewModel.kt | 18 +++ .../simpmusic/viewModel/SharedViewModel.kt | 1 + gradle/libs.versions.toml | 4 +- 8 files changed, 186 insertions(+), 67 deletions(-) diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml index 3fadddd9a..dc53b1371 100644 --- a/composeApp/src/commonMain/composeResources/values/strings.xml +++ b/composeApp/src/commonMain/composeResources/values/strings.xml @@ -172,6 +172,8 @@ Playback Save Playback State Save shuffle and repeat mode + Double press on image to ±5sec + Double tap on left/right of the image to seek back/forward 5 seconds Skip Silent Skip no music part Time out, check internet connection (%1$s) diff --git a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/component/PlayerControlLayout.kt b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/component/PlayerControlLayout.kt index 6fb21272b..562a4daa7 100644 --- a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/component/PlayerControlLayout.kt +++ b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/component/PlayerControlLayout.kt @@ -88,29 +88,6 @@ fun PlayerControlLayout( } } } - Box(Modifier.weight(1f), contentAlignment = Alignment.Center) { - Box( - modifier = - Modifier - .background(transparent) - .size(smallIcon.second) - .aspectRatio(1f) - .clip( - CircleShape, - ) - .clickable { - onUIEvent(UIEvent.Backward5) - }, - contentAlignment = Alignment.Center, - ) { - Icon( - imageVector = Icons.Rounded.Replay5, - tint = Color.White, - contentDescription = "", - modifier = Modifier.size(smallIcon.first), - ) - } - } Box(Modifier.weight(1f), contentAlignment = Alignment.Center) { Box( modifier = @@ -141,21 +118,21 @@ fun PlayerControlLayout( modifier = Modifier .background(transparent) - .size(mediumIcon.second) + .size(smallIcon.second) .aspectRatio(1f) .clip( CircleShape, ) .clickable { - onUIEvent(UIEvent.Backward) + onUIEvent(UIEvent.Backward5) }, contentAlignment = Alignment.Center, ) { Icon( - imageVector = Icons.Rounded.Replay10, + imageVector = Icons.Rounded.Replay5, tint = Color.White, contentDescription = "", - modifier = Modifier.size(mediumIcon.first), + modifier = Modifier.size(smallIcon.first), ) } } @@ -288,4 +265,4 @@ fun PlayerControlLayout( } } } -} \ No newline at end of file +} diff --git a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/screen/home/SettingScreen.kt b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/screen/home/SettingScreen.kt index 202d6b803..b35dd0d60 100644 --- a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/screen/home/SettingScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/screen/home/SettingScreen.kt @@ -267,6 +267,8 @@ import simpmusic.composeapp.generated.resources.save_all_your_playlist_data import simpmusic.composeapp.generated.resources.save_last_played import simpmusic.composeapp.generated.resources.save_last_played_track_and_queue import simpmusic.composeapp.generated.resources.save_playback_state +import simpmusic.composeapp.generated.resources.double_press_to_seek +import simpmusic.composeapp.generated.resources.double_press_to_seek_description import simpmusic.composeapp.generated.resources.save_shuffle_and_repeat_mode import simpmusic.composeapp.generated.resources.send_back_listening_data_to_google import simpmusic.composeapp.generated.resources.set @@ -382,6 +384,7 @@ fun SettingScreen( val normalizeVolume by viewModel.normalizeVolume.map { it == TRUE }.collectAsStateWithLifecycle(initialValue = false) val skipSilent by viewModel.skipSilent.map { it == TRUE }.collectAsStateWithLifecycle(initialValue = false) val savePlaybackState by viewModel.savedPlaybackState.map { it == TRUE }.collectAsStateWithLifecycle(initialValue = false) + val doublePressToSeek by viewModel.doublePressToSeek.map { it == TRUE }.collectAsStateWithLifecycle(initialValue = false) val saveLastPlayed by viewModel.saveRecentSongAndQueue.map { it == TRUE }.collectAsStateWithLifecycle(initialValue = false) val killServiceOnExit by viewModel.killServiceOnExit.map { it == TRUE }.collectAsStateWithLifecycle(initialValue = true) val mainLyricsProvider by viewModel.mainLyricsProvider.collectAsStateWithLifecycle() @@ -870,6 +873,11 @@ fun SettingScreen( subtitle = stringResource(Res.string.save_shuffle_and_repeat_mode), switch = (savePlaybackState to { viewModel.setSavedPlaybackState(it) }), ) + SettingItem( + title = stringResource(Res.string.double_press_to_seek), + subtitle = stringResource(Res.string.double_press_to_seek_description), + switch = (doublePressToSeek to { viewModel.setDoublePressToSeek(it) }), + ) SettingItem( title = stringResource(Res.string.save_last_played), subtitle = stringResource(Res.string.save_last_played_track_and_queue), diff --git a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/screen/player/FullscreenPlayer.kt b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/screen/player/FullscreenPlayer.kt index ef336cc9e..8873fafdd 100644 --- a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/screen/player/FullscreenPlayer.kt +++ b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/screen/player/FullscreenPlayer.kt @@ -31,8 +31,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Forward5 import androidx.compose.material.icons.filled.FullscreenExit -import androidx.compose.material.icons.filled.KeyboardDoubleArrowLeft -import androidx.compose.material.icons.filled.KeyboardDoubleArrowRight import androidx.compose.material.icons.filled.Pause import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.Replay5 @@ -91,7 +89,6 @@ import org.koin.compose.koinInject import simpmusic.composeapp.generated.resources.Res import simpmusic.composeapp.generated.resources.baseline_arrow_back_ios_new_24 import simpmusic.composeapp.generated.resources.baseline_more_vert_24 -import simpmusic.composeapp.generated.resources.five_seconds import kotlin.math.roundToLong @OptIn(ExperimentalMaterial3Api::class) @@ -121,6 +118,7 @@ fun FullscreenPlayer( val nowPlayingState by sharedViewModel.nowPlayingScreenData.collectAsStateWithLifecycle() val controllerState by sharedViewModel.controllerState.collectAsStateWithLifecycle() val timelineState by sharedViewModel.timeline.collectAsStateWithLifecycle() + val doublePressToSeek by sharedViewModel.doublePressToSeek.collectAsStateWithLifecycle() var showBottom by rememberSaveable { mutableStateOf(false) } var isSliding by rememberSaveable { @@ -154,10 +152,8 @@ fun FullscreenPlayer( // For double tap effect val coroutineScope = rememberCoroutineScope() - var doubleBackwardTapped by remember { mutableStateOf(false) } val interactionSourceBackward = remember { MutableInteractionSource() } - var doubleForwardTapped by remember { mutableStateOf(false) } val interactionSourceForward = remember { MutableInteractionSource() } var showBackwardText by remember { mutableStateOf(false) } @@ -216,14 +212,14 @@ fun FullscreenPlayer( showHideFullscreenOverlay = !showHideFullscreenOverlay }, onDoubleTap = { offset -> - coroutineScope.launch { - doubleBackwardTapped = true - val press = PressInteraction.Press(offset) - interactionSourceBackward.emit(press) - sharedViewModel.onUIEvent(UIEvent.Backward) - showBackwardText = true - interactionSourceBackward.emit(PressInteraction.Release(press)) - doubleBackwardTapped = false + if (doublePressToSeek) { + coroutineScope.launch { + val press = PressInteraction.Press(offset) + interactionSourceBackward.emit(press) + sharedViewModel.onUIEvent(UIEvent.Backward5) + showBackwardText = true + interactionSourceBackward.emit(PressInteraction.Release(press)) + } } }, ) @@ -234,17 +230,16 @@ fun FullscreenPlayer( if (it) { Row( verticalAlignment = Alignment.CenterVertically, + modifier = + Modifier + .background(Color.Black.copy(alpha = 0.5f), RoundedCornerShape(16.dp)) + .padding(horizontal = 14.dp, vertical = 8.dp), ) { Icon( - Icons.Filled.KeyboardDoubleArrowLeft, + Icons.Filled.Replay5, "", tint = Color.White, - ) - Spacer(Modifier.width(4.dp)) - Text( - stringResource(Res.string.five_seconds), - color = Color.White, - style = typo().bodyMedium, + modifier = Modifier.size(36.dp), ) } } @@ -268,14 +263,14 @@ fun FullscreenPlayer( showHideFullscreenOverlay = !showHideFullscreenOverlay }, onDoubleTap = { offset -> - coroutineScope.launch { - doubleForwardTapped = true - val press = PressInteraction.Press(offset) - interactionSourceForward.emit(press) - sharedViewModel.onUIEvent(UIEvent.Forward) - showForwardText = true - interactionSourceForward.emit(PressInteraction.Release(press)) - doubleForwardTapped = false + if (doublePressToSeek) { + coroutineScope.launch { + val press = PressInteraction.Press(offset) + interactionSourceForward.emit(press) + sharedViewModel.onUIEvent(UIEvent.Forward5) + showForwardText = true + interactionSourceForward.emit(PressInteraction.Release(press)) + } } }, ) @@ -286,17 +281,16 @@ fun FullscreenPlayer( if (it) { Row( verticalAlignment = Alignment.CenterVertically, + modifier = + Modifier + .background(Color.Black.copy(alpha = 0.5f), RoundedCornerShape(16.dp)) + .padding(horizontal = 14.dp, vertical = 8.dp), ) { - Text( - stringResource(Res.string.five_seconds), - color = Color.White, - style = typo().bodyMedium, - ) - Spacer(Modifier.width(4.dp)) Icon( - Icons.Filled.KeyboardDoubleArrowRight, + Icons.Filled.Forward5, "", tint = Color.White, + modifier = Modifier.size(36.dp), ) } } @@ -765,4 +759,4 @@ fun FullscreenPlayer( expect fun FullScreenRotationImmersive( onLaunch: () -> Unit = {}, onDispose: () -> Unit = {}, -) \ No newline at end of file +) diff --git a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/screen/player/NowPlayingScreen.kt b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/screen/player/NowPlayingScreen.kt index 4fc7c94e6..277374568 100644 --- a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/screen/player/NowPlayingScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/screen/player/NowPlayingScreen.kt @@ -22,7 +22,11 @@ import androidx.compose.foundation.basicMarquee import androidx.compose.foundation.clickable import androidx.compose.foundation.focusable import androidx.compose.foundation.gestures.detectHorizontalDragGestures +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.indication import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.PressInteraction +import androidx.compose.material3.ripple import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -264,6 +268,7 @@ fun NowPlayingScreenContent( onSwipeEnabledChange: (Boolean) -> Unit = {}, onDismiss: () -> Unit = {}, ) { + val coroutineScope = rememberCoroutineScope() val screenInfo = getScreenSizeInfo() val localDensity = LocalDensity.current @@ -279,6 +284,27 @@ fun NowPlayingScreenContent( // State val isInPipMode = rememberIsInPipMode() + val doublePressToSeek by sharedViewModel.doublePressToSeek.collectAsStateWithLifecycle() + + val interactionSourceBackward = remember { MutableInteractionSource() } + val interactionSourceForward = remember { MutableInteractionSource() } + + var showBackwardText by remember { mutableStateOf(false) } + var showForwardText by remember { mutableStateOf(false) } + + LaunchedEffect(key1 = showBackwardText) { + if (showBackwardText) { + delay(1000) + showBackwardText = false + } + } + LaunchedEffect(key1 = showForwardText) { + if (showForwardText) { + delay(1000) + showForwardText = false + } + } + val mainScrollState = rememberScrollState() var showHideMiddleLayout by rememberSaveable { @@ -831,6 +857,99 @@ fun NowPlayingScreenContent( if (!screenDataState.isVideo || !shouldShowVideo) 1f else 0f, ), ) + if (doublePressToSeek && (!screenDataState.isVideo || !shouldShowVideo)) { + Row( + modifier = Modifier + .matchParentSize() + .padding(3.dp) + .clip(RoundedCornerShape(8.dp)) + ) { + // Left side (Seek backward) + Box( + modifier = Modifier + .fillMaxHeight() + .weight(1f) + .indication( + interactionSource = interactionSourceBackward, + indication = ripple(), + ) + .pointerInput(Unit) { + detectTapGestures( + onDoubleTap = { offset -> + coroutineScope.launch { + val press = PressInteraction.Press(offset) + interactionSourceBackward.emit(press) + sharedViewModel.onUIEvent(UIEvent.Backward5) + showBackwardText = true + interactionSourceBackward.emit(PressInteraction.Release(press)) + } + } + ) + }, + contentAlignment = Alignment.Center + ) { + Crossfade(showBackwardText) { + if (it) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .background(Color.Black.copy(alpha = 0.5f), RoundedCornerShape(16.dp)) + .padding(horizontal = 14.dp, vertical = 8.dp) + ) { + Icon( + Icons.Rounded.Replay5, + "", + tint = Color.White, + modifier = Modifier.size(36.dp) + ) + } + } + } + } + // Right side (Seek forward) + Box( + modifier = Modifier + .fillMaxHeight() + .weight(1f) + .indication( + interactionSource = interactionSourceForward, + indication = ripple(), + ) + .pointerInput(Unit) { + detectTapGestures( + onDoubleTap = { offset -> + coroutineScope.launch { + val press = PressInteraction.Press(offset) + interactionSourceForward.emit(press) + sharedViewModel.onUIEvent(UIEvent.Forward5) + showForwardText = true + interactionSourceForward.emit(PressInteraction.Release(press)) + } + } + ) + }, + contentAlignment = Alignment.Center + ) { + Crossfade(showForwardText) { + if (it) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .background(Color.Black.copy(alpha = 0.5f), RoundedCornerShape(16.dp)) + .padding(horizontal = 14.dp, vertical = 8.dp) + ) { + Icon( + Icons.Rounded.Forward5, + "", + tint = Color.White, + modifier = Modifier.size(36.dp) + ) + } + } + } + } + } + } } // IS VIDEO => Show Video @@ -1873,4 +1992,4 @@ fun NowPlayingScreenContent( } } } -} \ No newline at end of file +} diff --git a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SettingsViewModel.kt b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SettingsViewModel.kt index 969c8e0d2..e2347c442 100644 --- a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SettingsViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SettingsViewModel.kt @@ -70,6 +70,8 @@ class SettingsViewModel( val normalizeVolume: StateFlow = _normalizeVolume private var _skipSilent: MutableStateFlow = MutableStateFlow(null) val skipSilent: StateFlow = _skipSilent + private var _doublePressToSeek: MutableStateFlow = MutableStateFlow(null) + val doublePressToSeek: StateFlow = _doublePressToSeek private var _savedPlaybackState: MutableStateFlow = MutableStateFlow(null) val savedPlaybackState: StateFlow = _savedPlaybackState private var _saveRecentSongAndQueue: MutableStateFlow = MutableStateFlow(null) @@ -209,6 +211,7 @@ class SettingsViewModel( getLoggedIn() getNormalizeVolume() getSkipSilent() + getDoublePressToSeek() getSavedPlaybackState() getSendBackToGoogle() getSaveRecentSongAndQueue() @@ -1010,6 +1013,21 @@ class SettingsViewModel( } } + fun getDoublePressToSeek() { + viewModelScope.launch { + dataStoreManager.doublePressToSeek.collect { doublePressToSeek -> + _doublePressToSeek.emit(doublePressToSeek) + } + } + } + + fun setDoublePressToSeek(enable: Boolean) { + viewModelScope.launch { + dataStoreManager.setDoublePressToSeek(enable) + getDoublePressToSeek() + } + } + fun getSavedPlaybackState() { viewModelScope.launch { dataStoreManager.saveStateOfPlayback.collect { savedPlaybackState -> diff --git a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SharedViewModel.kt b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SharedViewModel.kt index 052ad58c9..c58a80c83 100644 --- a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SharedViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SharedViewModel.kt @@ -202,6 +202,7 @@ class SharedViewModel( val likeStatus: StateFlow = _likeStatus val openAppTime: StateFlow = dataStoreManager.openAppTime.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000L), 0) + val doublePressToSeek: StateFlow = dataStoreManager.doublePressToSeek.map { it == TRUE }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000L), false) private val _shareSavedLyrics: MutableStateFlow = MutableStateFlow(true) val shareSavedLyrics: StateFlow get() = _shareSavedLyrics diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 941f91d1c..590eed042 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -50,7 +50,7 @@ slf4j = "1.7.36" sentry-android = "8.28.0" sentry-gradle-android = "5.12.2" sentry-jvm = "8.28.0" -newpipe = "31edd9f7ad2b8e309442e86d5318cc2779480674" +newpipe = "0.24.8" webkit = "1.14.0" kermit = "2.0.8" paging-common = "3.3.6" @@ -244,4 +244,4 @@ jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" build-config = { id = "com.codingfeline.buildkonfig", version.ref = "buildkonfig" } # JVM -osdetector = { id = "com.google.osdetector", version.ref = "osdetector" } \ No newline at end of file +osdetector = { id = "com.google.osdetector", version.ref = "osdetector" } From bd641ee52ff4c471f1fdcabc671c6afb3d9fc3ae Mon Sep 17 00:00:00 2001 From: Hemanth K R <80522401+Hemanth2332@users.noreply.github.com> Date: Tue, 23 Jun 2026 23:43:42 +0530 Subject: [PATCH 3/3] added +-5sec rewind feature through image tap --- .../maxrave/simpmusic/viewModel/SettingsViewModel.kt | 10 +++++++--- .../com/maxrave/simpmusic/viewModel/SharedViewModel.kt | 10 ++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SettingsViewModel.kt b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SettingsViewModel.kt index e2347c442..252db04f5 100644 --- a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SettingsViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SettingsViewModel.kt @@ -13,6 +13,8 @@ import com.maxrave.domain.data.entities.DownloadState import com.maxrave.domain.data.entities.GoogleAccountEntity import com.maxrave.domain.extension.toNetScapeString import com.maxrave.domain.manager.DataStoreManager +import com.maxrave.domain.manager.DataStoreManager.Values.FALSE +import com.maxrave.domain.manager.DataStoreManager.Values.TRUE import com.maxrave.domain.mediaservice.handler.DownloadHandler import com.maxrave.domain.repository.AccountRepository import com.maxrave.domain.repository.CacheRepository @@ -50,6 +52,8 @@ import simpmusic.composeapp.generated.resources.clear_thumbnail_cache import simpmusic.composeapp.generated.resources.restore_failed import simpmusic.composeapp.generated.resources.restore_in_progress +private const val DOUBLE_PRESS_TO_SEEK_KEY = "double_press_to_seek" + class SettingsViewModel( private val dataStoreManager: DataStoreManager, private val commonRepository: CommonRepository, @@ -1015,7 +1019,7 @@ class SettingsViewModel( fun getDoublePressToSeek() { viewModelScope.launch { - dataStoreManager.doublePressToSeek.collect { doublePressToSeek -> + dataStoreManager.getString(DOUBLE_PRESS_TO_SEEK_KEY).collect { doublePressToSeek -> _doublePressToSeek.emit(doublePressToSeek) } } @@ -1023,7 +1027,7 @@ class SettingsViewModel( fun setDoublePressToSeek(enable: Boolean) { viewModelScope.launch { - dataStoreManager.setDoublePressToSeek(enable) + dataStoreManager.putString(DOUBLE_PRESS_TO_SEEK_KEY, if (enable) TRUE else FALSE) getDoublePressToSeek() } } @@ -1498,4 +1502,4 @@ expect fun getPackageName(): String expect fun getFileDir(): String -expect fun changeLanguageNative(code: String) \ No newline at end of file +expect fun changeLanguageNative(code: String) diff --git a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SharedViewModel.kt b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SharedViewModel.kt index c58a80c83..47c916d3b 100644 --- a/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SharedViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/SharedViewModel.kt @@ -101,6 +101,8 @@ import java.io.FileOutputStream import kotlin.math.abs import kotlin.reflect.KClass +private const val DOUBLE_PRESS_TO_SEEK_KEY = "double_press_to_seek" + @OptIn(ExperimentalCoroutinesApi::class) class SharedViewModel( private val dataStoreManager: DataStoreManager, @@ -202,7 +204,11 @@ class SharedViewModel( val likeStatus: StateFlow = _likeStatus val openAppTime: StateFlow = dataStoreManager.openAppTime.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000L), 0) - val doublePressToSeek: StateFlow = dataStoreManager.doublePressToSeek.map { it == TRUE }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000L), false) + val doublePressToSeek: StateFlow = + dataStoreManager + .getString(DOUBLE_PRESS_TO_SEEK_KEY) + .map { it == TRUE } + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000L), false) private val _shareSavedLyrics: MutableStateFlow = MutableStateFlow(true) val shareSavedLyrics: StateFlow get() = _shareSavedLyrics @@ -1702,4 +1708,4 @@ data class NowPlayingScreenData( playlistName = "", ) } -} \ No newline at end of file +}