diff --git a/app/src/main/java/pl/lambada/songsync/data/remote/UserSettingsController.kt b/app/src/main/java/pl/lambada/songsync/data/remote/UserSettingsController.kt index c3900c8..8da3b83 100644 --- a/app/src/main/java/pl/lambada/songsync/data/remote/UserSettingsController.kt +++ b/app/src/main/java/pl/lambada/songsync/data/remote/UserSettingsController.kt @@ -52,6 +52,9 @@ class UserSettingsController(private val dataStore: DataStore) { var showPath by mutableStateOf(dataStore.get(showPathKey, false)) private set + var directlyModifyTimestamps by mutableStateOf(dataStore.get(directlyModifyTimestampsKey, false)) + private set + var sortOrder by mutableStateOf( SortOrders.entries .find { it.queryName == dataStore.get(sortOrderKey, SortOrders.ASCENDING.queryName) }!! @@ -119,6 +122,11 @@ class UserSettingsController(private val dataStore: DataStore) { showPath = to } + fun updateDirectlyModifyTimestamps(to: Boolean) { + dataStore.set(directlyModifyTimestampsKey, to) + directlyModifyTimestamps = to + } + fun updateSortOrder(to: SortOrders) { dataStore.set(sortOrderKey, to.queryName) sortOrder = to @@ -142,4 +150,5 @@ private val pureBlackKey = booleanPreferencesKey("pure_black") private val sdCardPathKey = stringPreferencesKey("sd_card_path") private val showPathKey = booleanPreferencesKey("show_path") private val sortOrderKey = stringPreferencesKey("sort_order") -private val sortByKey = stringPreferencesKey("sort_by") \ No newline at end of file +private val sortByKey = stringPreferencesKey("sort_by") +private val directlyModifyTimestampsKey = booleanPreferencesKey("directly_modify_timestamps") \ No newline at end of file diff --git a/app/src/main/java/pl/lambada/songsync/ui/screens/lyricsFetch/LyricsFetchScreen.kt b/app/src/main/java/pl/lambada/songsync/ui/screens/lyricsFetch/LyricsFetchScreen.kt index d22ea08..82fade2 100644 --- a/app/src/main/java/pl/lambada/songsync/ui/screens/lyricsFetch/LyricsFetchScreen.kt +++ b/app/src/main/java/pl/lambada/songsync/ui/screens/lyricsFetch/LyricsFetchScreen.kt @@ -152,6 +152,7 @@ fun SharedTransitionScope.LyricsFetchScreen( viewModel.lrcOffset = 0 viewModel.queryState = QueryStatus.NotSubmitted }, + directOffset = viewModel.userSettingsController.directlyModifyTimestamps, offset = viewModel.lrcOffset, onSetOffset = { viewModel.lrcOffset = it }, onSaveLyrics = { diff --git a/app/src/main/java/pl/lambada/songsync/ui/screens/lyricsFetch/LyricsFetchViewModel.kt b/app/src/main/java/pl/lambada/songsync/ui/screens/lyricsFetch/LyricsFetchViewModel.kt index 0a77815..d37098d 100644 --- a/app/src/main/java/pl/lambada/songsync/ui/screens/lyricsFetch/LyricsFetchViewModel.kt +++ b/app/src/main/java/pl/lambada/songsync/ui/screens/lyricsFetch/LyricsFetchViewModel.kt @@ -86,7 +86,7 @@ class LyricsFetchViewModel( context: Context, generatedUsingString: String ) { - val lrcContent = generateLrcContent(song, lyrics, generatedUsingString, lrcOffset) + val lrcContent = generateLrcContent(song, lyrics, generatedUsingString, lrcOffset, userSettingsController.directlyModifyTimestamps) val file = newLyricsFilePath(filePath, song) if (!isLegacyFileAccessRequired(filePath)) { @@ -127,7 +127,7 @@ class LyricsFetchViewModel( context: Context, song: SongInfo ) { - val lrcContent = generateLrcContent(song, lyrics, context.getString(R.string.generated_using), lrcOffset) + val lrcContent = generateLrcContent(song, lyrics, context.getString(R.string.generated_using), lrcOffset, userSettingsController.directlyModifyTimestamps) runCatching { embedLyricsInFile( diff --git a/app/src/main/java/pl/lambada/songsync/ui/screens/lyricsFetch/components/SuccessContent.kt b/app/src/main/java/pl/lambada/songsync/ui/screens/lyricsFetch/components/SuccessContent.kt index b324cce..29077cf 100644 --- a/app/src/main/java/pl/lambada/songsync/ui/screens/lyricsFetch/components/SuccessContent.kt +++ b/app/src/main/java/pl/lambada/songsync/ui/screens/lyricsFetch/components/SuccessContent.kt @@ -38,6 +38,7 @@ fun SharedTransitionScope.SuccessContent( result: SongInfo, onTryAgain: () -> Unit, onEdit: () -> Unit, + directOffset: Boolean, offset: Int, onSetOffset: (Int) -> Unit, onSaveLyrics: (String) -> Unit, @@ -103,7 +104,13 @@ fun SharedTransitionScope.SuccessContent( LyricsFetchState.NotSubmitted -> { /* nothing */ } is LyricsFetchState.Success -> LyricsSuccessContent( - lyrics = applyOffsetToLyrics(it.lyrics, offset), + lyrics = it.lyrics.let { + if (offset != 0 && directOffset) { + applyOffsetToLyrics(it, offset) + } else { + it + } + }, offset = offset, onSetOffset = onSetOffset, onSaveLyrics = { onSaveLyrics(it.lyrics) }, diff --git a/app/src/main/java/pl/lambada/songsync/ui/screens/settings/SettingsScreen.kt b/app/src/main/java/pl/lambada/songsync/ui/screens/settings/SettingsScreen.kt index 40ad607..f2d370c 100644 --- a/app/src/main/java/pl/lambada/songsync/ui/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/pl/lambada/songsync/ui/screens/settings/SettingsScreen.kt @@ -19,6 +19,7 @@ import androidx.navigation.NavController import pl.lambada.songsync.R import pl.lambada.songsync.data.remote.UpdateState import pl.lambada.songsync.data.remote.UserSettingsController +import pl.lambada.songsync.ui.screens.about.components.OffsetModeSwitch import pl.lambada.songsync.ui.screens.settings.components.SettingsScreenTopBar import pl.lambada.songsync.ui.screens.settings.components.AppInfoSection import pl.lambada.songsync.ui.screens.settings.components.ContributorsSection @@ -105,6 +106,13 @@ fun SettingsScreen( ) } + item { + OffsetModeSwitch( + selected = userSettingsController.directlyModifyTimestamps, + onToggle = { userSettingsController.updateDirectlyModifyTimestamps(it) } + ) + } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { item { SdCardPathSetting( diff --git a/app/src/main/java/pl/lambada/songsync/ui/screens/settings/components/OffsetModeSwitch.kt b/app/src/main/java/pl/lambada/songsync/ui/screens/settings/components/OffsetModeSwitch.kt new file mode 100644 index 0000000..b418ba4 --- /dev/null +++ b/app/src/main/java/pl/lambada/songsync/ui/screens/settings/components/OffsetModeSwitch.kt @@ -0,0 +1,21 @@ +package pl.lambada.songsync.ui.screens.about.components + +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import pl.lambada.songsync.R +import pl.lambada.songsync.ui.components.SettingsItem +import pl.lambada.songsync.ui.components.SwitchItem + +@Composable +fun OffsetModeSwitch( + selected: Boolean, + onToggle: (Boolean) -> Unit +) { + SettingsItem(label = stringResource(R.string.offset_mode)) { + SwitchItem( + label = stringResource(R.string.offset_mode_summary), + selected = selected, + onClick = { onToggle(!selected) } + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/pl/lambada/songsync/util/LyricsUtils.kt b/app/src/main/java/pl/lambada/songsync/util/LyricsUtils.kt index 22a5853..212cf16 100644 --- a/app/src/main/java/pl/lambada/songsync/util/LyricsUtils.kt +++ b/app/src/main/java/pl/lambada/songsync/util/LyricsUtils.kt @@ -26,12 +26,17 @@ fun generateLrcContent( lyrics: String, generatedUsingString: String, offset: Int = 0, + directOffset: Boolean ): String { - return ("[ti:${song.songName}]\n" + + val offsetSign = if (offset >= 0) "+" else "" + val offsetStr = if (!directOffset) "[offset:${offsetSign}${offset}]\n" else "" + val lyrics = if (directOffset && offset != 0) applyOffsetToLyrics(lyrics, offset) else lyrics + + return "[ti:${song.songName}]\n" + "[ar:${song.artistName}]\n" + - "[by:$generatedUsingString]\n" + lyrics).let { - if (offset != 0) applyOffsetToLyrics(it, offset) else it - } + offsetStr + + "[by:$generatedUsingString]\n" + + lyrics } fun newLyricsFilePath(filePath: String?, song: SongInfo): File { @@ -251,7 +256,8 @@ private suspend fun downloadLyricsForSong( context, viewModel.userSettingsController.sdCardPath, songInfo, - it + it, + viewModel.userSettingsController.directlyModifyTimestamps ) onLyricsSaved() @@ -265,13 +271,15 @@ private fun formatAndSaveLyricsForSong( sdCardPath: String?, songInfo: SongInfo, lyrics: String, + directOffset: Boolean ) { val targetFile = song.filePath.toLrcFile() val lrcContent = generateLrcContent( songInfo, lyrics, - context.getString(R.string.generated_using) + context.getString(R.string.generated_using), + directOffset = directOffset ) writeLyricsToFile(targetFile, lrcContent, context, song, sdCardPath) @@ -316,7 +324,7 @@ fun applyOffsetToLyrics(lyrics: String, offset: Int): String { fun applyOffset(minute: Int, second: Int, millisecond: Int): String { val totalMilliseconds = (minute * 60 * 1000) + (second * 1000) + (millisecond * 10) + offset - if (totalMilliseconds < 0) return "[00:00.000]" // Prevent negative times + if (totalMilliseconds < 0) return "00:00.000" // Prevent negative times val newMinutes = (totalMilliseconds / 60000) % 60 val newSeconds = (totalMilliseconds / 1000) % 60 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fc8ad93..f88c203 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -138,5 +138,7 @@ Ascending Descending Sort + Offset mode + Directly modify the lyrics timestamps instead of using offset LRC tag Settings