From ddba5682b9502b12a5d489f9d5548a9d10e4fb2b Mon Sep 17 00:00:00 2001 From: Hepolise Date: Sun, 23 Nov 2025 15:29:23 +0300 Subject: [PATCH] feat: add configurable long press actions with quick settings tile - Add rewind functionality as an alternative to track change on long press - Implement segmented button control for choosing between track change/rewind - Add animated rewind duration slider that appears when rewind is selected - Create Quick Settings tile for toggling between track change/rewind modes - Improve volume key handling to properly route through media session API - Add seek functionality for precise media navigation - Support multiple languages (English, Russian, Chinese) - Maintain backward compatibility with existing settings New features: - Long press action selection (track change or rewind) - Configurable rewind duration (1-60 seconds) - Quick Settings tile for easy mode switching --- app/src/main/AndroidManifest.xml | 11 ++ .../module/VolumeKeyControlModuleHandlers.kt | 75 ++++++++-- .../service/RewindActionTileService.kt | 65 +++++++++ .../ui/component/LongPressSetting.kt | 133 +++++++++++++++++- .../ui/screen/SettingsScreen.kt | 37 ++++- .../util/AppFilterType.kt | 7 +- .../util/RewindActionType.kt | 5 + .../util/SharedPreferencesUtil.kt | 16 +++ .../res/drawable/ic_fast_forward_48dp.xml | 10 ++ .../main/res/drawable/ic_skip_next_48dp.xml | 10 ++ app/src/main/res/values-ru-rRU/strings.xml | 7 + app/src/main/res/values-zh-rCN/strings.xml | 7 + app/src/main/res/values-zh-rTW/strings.xml | 7 + app/src/main/res/values/strings.xml | 7 + 14 files changed, 375 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/ru/hepolise/volumekeytrackcontrol/service/RewindActionTileService.kt create mode 100644 app/src/main/java/ru/hepolise/volumekeytrackcontrol/util/RewindActionType.kt create mode 100644 app/src/main/res/drawable/ic_fast_forward_48dp.xml create mode 100644 app/src/main/res/drawable/ic_skip_next_48dp.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dc8fccb..0c8485c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -44,6 +44,17 @@ + + + + + + controls.skipToNext() - MediaEvent.Prev -> controls.skipToPrevious() + MediaEvent.Next -> { + if (prefs.getRewindActionType() == RewindActionType.TRACK_CHANGE) { + controls.skipToNext() + } else { + val currentPosition = controller.playbackState?.position ?: 0 + val duration = + controller.metadata?.getLong(MediaMetadata.METADATA_KEY_DURATION) + ?: Long.MAX_VALUE + val newPosition = + min(currentPosition + prefs.getRewindDuration() * 1000, duration) + controls.seekTo(newPosition) + } + } + + MediaEvent.Prev -> { + if (prefs.getRewindActionType() == RewindActionType.TRACK_CHANGE) { + controls.skipToPrevious() + } else { + val currentPosition = controller.playbackState?.position ?: 0 + val newPosition = max(currentPosition - prefs.getRewindDuration() * 1000, 0) + controls.seekTo(newPosition) + } + } } vibrator.triggerVibration() } @@ -339,11 +371,32 @@ object VolumeKeyControlModuleHandlers { } fun adjustStreamVolume(audioManager: AudioManager) { - val direction = when (origKey) { - Key.UP -> AudioManager.ADJUST_RAISE - Key.DOWN -> AudioManager.ADJUST_LOWER + try { + val direction = when (origKey) { + Key.UP -> KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_UP) + Key.DOWN -> KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_DOWN) + } + + XposedHelpers.callMethod( + sessionHelper, + "sendVolumeKeyEvent", + arrayOf( + KeyEvent::class.java, + Int::class.javaPrimitiveType, + Boolean::class.javaPrimitiveType + ), + direction, AudioManager.USE_DEFAULT_STREAM_TYPE, false + ) + } catch (e: Exception) { + log("Failed to adjust stream volume: ${e.message}") + log("Falling back to adjustStreamVolume") + + val direction = when (origKey) { + Key.UP -> AudioManager.ADJUST_RAISE + Key.DOWN -> AudioManager.ADJUST_LOWER + } + audioManager.adjustStreamVolume(AudioManager.USE_DEFAULT_STREAM_TYPE, direction, 0) } - audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, direction, 0) } private companion object { diff --git a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/service/RewindActionTileService.kt b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/service/RewindActionTileService.kt new file mode 100644 index 0000000..e369b15 --- /dev/null +++ b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/service/RewindActionTileService.kt @@ -0,0 +1,65 @@ +package ru.hepolise.volumekeytrackcontrol.service + +import android.graphics.drawable.Icon +import android.service.quicksettings.Tile +import android.service.quicksettings.TileService +import androidx.core.content.edit +import ru.hepolise.volumekeytrackcontrol.util.RewindActionType +import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.REWIND_ACTION_TYPE +import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.getRewindActionType +import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.getSettingsSharedPreferences +import ru.hepolise.volumekeytrackcontrolmodule.R + +class RewindActionTileService : TileService() { + + override fun onStartListening() { + super.onStartListening() + updateTile() + } + + override fun onClick() { + super.onClick() + toggleActionType() + } + + private fun toggleActionType() { + val prefs = getSettingsSharedPreferences() + val currentType = prefs.getRewindActionType() + + val newType = when (currentType) { + RewindActionType.TRACK_CHANGE -> RewindActionType.REWIND + RewindActionType.REWIND -> RewindActionType.TRACK_CHANGE + } + + prefs?.edit { + putString(REWIND_ACTION_TYPE, newType.name) + } + + updateTile() + } + + private fun updateTile() { + val prefs = getSettingsSharedPreferences() + val currentType = prefs.getRewindActionType() + + val tile = qsTile ?: return + + when (currentType) { + RewindActionType.TRACK_CHANGE -> { + tile.label = getString(R.string.track_change) + tile.contentDescription = getString(R.string.track_change) + tile.icon = Icon.createWithResource(this, R.drawable.ic_skip_next_48dp) + tile.state = Tile.STATE_ACTIVE + } + + RewindActionType.REWIND -> { + tile.label = getString(R.string.rewind) + tile.contentDescription = getString(R.string.rewind) + tile.icon = Icon.createWithResource(this, R.drawable.ic_fast_forward_48dp) + tile.state = Tile.STATE_ACTIVE + } + } + + tile.updateTile() + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/ui/component/LongPressSetting.kt b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/ui/component/LongPressSetting.kt index b757d0c..f1ef797 100644 --- a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/ui/component/LongPressSetting.kt +++ b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/ui/component/LongPressSetting.kt @@ -1,12 +1,24 @@ package ru.hepolise.volumekeytrackcontrol.ui.component import android.content.SharedPreferences +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Edit import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.SegmentedButton +import androidx.compose.material3.SegmentedButtonDefaults +import androidx.compose.material3.SingleChoiceSegmentedButtonRow import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -16,25 +28,42 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp import androidx.core.content.edit +import ru.hepolise.volumekeytrackcontrol.util.RewindActionType import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.LONG_PRESS_DURATION +import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.REWIND_ACTION_TYPE +import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.REWIND_DURATION import ru.hepolise.volumekeytrackcontrolmodule.R +data class LongPressSettingData( + val longPressDuration: Int, + val rewindActionType: RewindActionType, + val rewindDuration: Int +) + @Composable fun LongPressSetting( - longPressDuration: Int, + data: LongPressSettingData, sharedPreferences: SharedPreferences, - onValueChange: (Int) -> Unit + onValueChange: (LongPressSettingData) -> Unit ) { + val longPressDuration = data.longPressDuration + val rewindActionType = data.rewindActionType + val rewindDuration = data.rewindDuration + + var showLongPressTimeoutDialog by remember { mutableStateOf(false) } + var showRewindDurationDialog by remember { mutableStateOf(false) } + PrefsSlider( value = longPressDuration, - onValueChange = { onValueChange(it) }, + onValueChange = { onValueChange(data.copy(longPressDuration = it)) }, valueRange = 100f..1000f, prefKey = LONG_PRESS_DURATION, sharedPreferences = sharedPreferences ) - var showLongPressTimeoutDialog by remember { mutableStateOf(false) } Row(verticalAlignment = Alignment.CenterVertically) { Text( text = stringResource(R.string.long_press_duration, longPressDuration), @@ -52,6 +81,85 @@ fun LongPressSetting( } } + Row(verticalAlignment = Alignment.CenterVertically) { + Text( + text = stringResource(R.string.long_press_action), + ) + } + + Row(verticalAlignment = Alignment.CenterVertically) { + SingleChoiceSegmentedButtonRow { + RewindActionType.entries.forEachIndexed { index, actionType -> + SegmentedButton( + selected = rewindActionType == actionType, + onClick = { + onValueChange(data.copy(rewindActionType = actionType)) + sharedPreferences.edit { + putString(REWIND_ACTION_TYPE, actionType.name) + } + }, + shape = SegmentedButtonDefaults.itemShape( + index = index, + count = RewindActionType.entries.size + ), + modifier = Modifier + .defaultMinSize(minWidth = 140.dp) + .weight(1f) + ) { + Text( + text = when (actionType) { + RewindActionType.TRACK_CHANGE -> stringResource(R.string.track_change) + RewindActionType.REWIND -> stringResource(R.string.rewind) + }, + maxLines = 1, + overflow = TextOverflow.Visible, + softWrap = false + ) + } + } + } + } + + Box { + AnimatedVisibility( + visible = rewindActionType == RewindActionType.REWIND, + enter = fadeIn() + expandVertically(expandFrom = Alignment.Top), + exit = fadeOut() + shrinkVertically(shrinkTowards = Alignment.Top), + modifier = Modifier.fillMaxWidth() + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + ) { + PrefsSlider( + value = rewindDuration, + onValueChange = { + onValueChange(data.copy(rewindDuration = it)) + }, + valueRange = 1f..60f, + prefKey = REWIND_DURATION, + sharedPreferences = sharedPreferences + ) + + Row(verticalAlignment = Alignment.CenterVertically) { + Text( + text = stringResource(R.string.rewind_duration, rewindDuration), + modifier = Modifier.clickable { showRewindDurationDialog = true } + ) + IconButton( + onClick = { + showRewindDurationDialog = true + } + ) { + Icon( + imageVector = Icons.Default.Edit, + contentDescription = stringResource(R.string.edit_rewind_duration) + ) + } + } + } + } + } + if (showLongPressTimeoutDialog) { NumberAlertDialog( title = stringResource(R.string.long_press_duration_dialog_title), @@ -60,10 +168,25 @@ fun LongPressSetting( maxValue = 1000, onDismissRequest = { showLongPressTimeoutDialog = false }, onConfirm = { - onValueChange(it) + onValueChange(data.copy(longPressDuration = it)) sharedPreferences.edit { putInt(LONG_PRESS_DURATION, it) } showLongPressTimeoutDialog = false } ) } + + if (showRewindDurationDialog) { + NumberAlertDialog( + title = stringResource(R.string.rewind_duration_dialog_title), + defaultValue = rewindDuration, + minValue = 1, + maxValue = 60, + onDismissRequest = { showRewindDurationDialog = false }, + onConfirm = { + onValueChange(data.copy(rewindDuration = it)) + sharedPreferences.edit { putInt(REWIND_DURATION, it) } + showRewindDurationDialog = false + } + ) + } } \ No newline at end of file diff --git a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/ui/screen/SettingsScreen.kt b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/ui/screen/SettingsScreen.kt index a35de31..bb4b8cd 100644 --- a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/ui/screen/SettingsScreen.kt +++ b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/ui/screen/SettingsScreen.kt @@ -93,6 +93,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import ru.hepolise.volumekeytrackcontrol.ui.component.AppFilterSetting import ru.hepolise.volumekeytrackcontrol.ui.component.LongPressSetting +import ru.hepolise.volumekeytrackcontrol.ui.component.LongPressSettingData import ru.hepolise.volumekeytrackcontrol.ui.component.SwapButtonsSetting import ru.hepolise.volumekeytrackcontrol.ui.component.VibrationEffectSetting import ru.hepolise.volumekeytrackcontrol.ui.component.VibrationSettingData @@ -103,12 +104,17 @@ import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.APP_FILTER_T import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.EFFECT_DEFAULT_VALUE import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.IS_SWAP_BUTTONS_DEFAULT_VALUE import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.LONG_PRESS_DURATION_DEFAULT_VALUE +import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.REWIND_ACTION_TYPE +import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.REWIND_ACTION_TYPE_DEFAULT_VALUE +import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.REWIND_DURATION_DEFAULT_VALUE import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.SETTINGS_PREFS import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.VIBRATION_AMPLITUDE_DEFAULT_VALUE import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.VIBRATION_LENGTH_DEFAULT_VALUE import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.getAppFilterType import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.getLaunchedCount import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.getLongPressDuration +import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.getRewindActionType +import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.getRewindDuration import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.getStatusSharedPreferences import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.getVibrationAmplitude import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.getVibrationLength @@ -140,6 +146,9 @@ fun SettingsScreen( val isLoading by bootViewModel.isLoading.collectAsState() var longPressDuration by remember { mutableIntStateOf(settingsPrefs.getLongPressDuration()) } + var rewindActionType by remember { mutableStateOf(settingsPrefs.getRewindActionType()) } + var rewindDuration by remember { mutableIntStateOf(settingsPrefs.getRewindDuration()) } + var vibrationType by remember { mutableStateOf(settingsPrefs.getVibrationType()) } var vibrationLength by remember { mutableIntStateOf(settingsPrefs.getVibrationLength()) } var vibrationAmplitude by remember { mutableIntStateOf(settingsPrefs.getVibrationAmplitude()) } @@ -166,6 +175,20 @@ fun SettingsScreen( } } + settingsPrefs?.also { + DisposableEffect(Unit) { + val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, key -> + if (key == REWIND_ACTION_TYPE) { + rewindActionType = settingsPrefs.getRewindActionType() + } + } + settingsPrefs.registerOnSharedPreferenceChangeListener(listener) + onDispose { + settingsPrefs.unregisterOnSharedPreferenceChangeListener(listener) + } + } + } + val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() Scaffold( @@ -239,8 +262,16 @@ fun SettingsScreen( icon = Icons.Default.Settings, title = stringResource(R.string.long_press_settings) ) { - LongPressSetting(longPressDuration, settingsPrefs) { - longPressDuration = it + LongPressSetting( + LongPressSettingData( + longPressDuration, + rewindActionType, + rewindDuration + ), settingsPrefs + ) { + longPressDuration = it.longPressDuration + rewindActionType = it.rewindActionType + rewindDuration = it.rewindDuration } SwapButtonsSetting( isSwapButtons = isSwapButtons, @@ -294,6 +325,8 @@ fun SettingsScreen( vibrationLength = VIBRATION_LENGTH_DEFAULT_VALUE vibrationAmplitude = VIBRATION_AMPLITUDE_DEFAULT_VALUE longPressDuration = LONG_PRESS_DURATION_DEFAULT_VALUE + rewindActionType = REWIND_ACTION_TYPE_DEFAULT_VALUE + rewindDuration = REWIND_DURATION_DEFAULT_VALUE isSwapButtons = IS_SWAP_BUTTONS_DEFAULT_VALUE appFilterType = AppFilterType.fromKey( APP_FILTER_TYPE_DEFAULT_VALUE diff --git a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/util/AppFilterType.kt b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/util/AppFilterType.kt index 87dbcde..215f0d4 100644 --- a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/util/AppFilterType.kt +++ b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/util/AppFilterType.kt @@ -3,13 +3,12 @@ package ru.hepolise.volumekeytrackcontrol.util import ru.hepolise.volumekeytrackcontrolmodule.R enum class AppFilterType( - val value: Int, val key: String, val resourceId: Int ) { - DISABLED(0, "disabled", R.string.app_filter_disabled), - WHITE_LIST(1, "whitelist", R.string.app_filter_white_list), - BLACK_LIST(2, "blacklist", R.string.app_filter_black_list); + DISABLED("disabled", R.string.app_filter_disabled), + WHITE_LIST("whitelist", R.string.app_filter_white_list), + BLACK_LIST("blacklist", R.string.app_filter_black_list); companion object { fun fromKey(key: String?) = entries.find { it.key == key } ?: DISABLED diff --git a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/util/RewindActionType.kt b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/util/RewindActionType.kt new file mode 100644 index 0000000..28abed0 --- /dev/null +++ b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/util/RewindActionType.kt @@ -0,0 +1,5 @@ +package ru.hepolise.volumekeytrackcontrol.util + +enum class RewindActionType { + TRACK_CHANGE, REWIND; +} \ No newline at end of file diff --git a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/util/SharedPreferencesUtil.kt b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/util/SharedPreferencesUtil.kt index 5aae451..e4ff625 100644 --- a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/util/SharedPreferencesUtil.kt +++ b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/util/SharedPreferencesUtil.kt @@ -19,6 +19,8 @@ object SharedPreferencesUtil { const val VIBRATION_LENGTH = "vibrationLength" const val VIBRATION_AMPLITUDE = "vibrationAmplitude" const val LONG_PRESS_DURATION = "longPressDuration" + const val REWIND_ACTION_TYPE = "rewindActionType" + const val REWIND_DURATION = "rewindDuration" const val IS_SWAP_BUTTONS = "isSwapButtons" const val APP_FILTER_TYPE = "appFilterType" const val WHITE_LIST_APPS = "whiteListApps" @@ -33,6 +35,8 @@ object SharedPreferencesUtil { const val VIBRATION_LENGTH_DEFAULT_VALUE = 50 const val VIBRATION_AMPLITUDE_DEFAULT_VALUE = 128 val LONG_PRESS_DURATION_DEFAULT_VALUE = ViewConfiguration.getLongPressTimeout() + val REWIND_ACTION_TYPE_DEFAULT_VALUE = RewindActionType.TRACK_CHANGE + const val REWIND_DURATION_DEFAULT_VALUE = 5 const val IS_SWAP_BUTTONS_DEFAULT_VALUE = false val APP_FILTER_TYPE_DEFAULT_VALUE = AppFilterType.DISABLED.key @@ -58,6 +62,18 @@ object SharedPreferencesUtil { return this?.getInt(LONG_PRESS_DURATION, defaultValue) ?: defaultValue } + fun SharedPreferences?.getRewindActionType(): RewindActionType { + val defaultValue = REWIND_ACTION_TYPE_DEFAULT_VALUE.name + return RewindActionType.valueOf( + this?.getString(REWIND_ACTION_TYPE, defaultValue) ?: defaultValue + ) + } + + fun SharedPreferences?.getRewindDuration(): Int { + val defaultValue = REWIND_DURATION_DEFAULT_VALUE + return this?.getInt(REWIND_DURATION, defaultValue) ?: defaultValue + } + fun SharedPreferences?.isSwapButtons(): Boolean { val defaultValue = IS_SWAP_BUTTONS_DEFAULT_VALUE return this?.getBoolean(IS_SWAP_BUTTONS, defaultValue) ?: defaultValue diff --git a/app/src/main/res/drawable/ic_fast_forward_48dp.xml b/app/src/main/res/drawable/ic_fast_forward_48dp.xml new file mode 100644 index 0000000..222d62c --- /dev/null +++ b/app/src/main/res/drawable/ic_fast_forward_48dp.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_skip_next_48dp.xml b/app/src/main/res/drawable/ic_skip_next_48dp.xml new file mode 100644 index 0000000..c91c460 --- /dev/null +++ b/app/src/main/res/drawable/ic_skip_next_48dp.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values-ru-rRU/strings.xml b/app/src/main/res/values-ru-rRU/strings.xml index 4522e2c..a6232c4 100644 --- a/app/src/main/res/values-ru-rRU/strings.xml +++ b/app/src/main/res/values-ru-rRU/strings.xml @@ -52,6 +52,13 @@ Поменять кнопки Вверх/Вниз для переключения + Переключение трека + Действие при долгом нажатии + Перемотка + Длительность перемотки: %d сек + Установить длительность перемотки + Изменить длительность перемотки + Сбросить настройки Вы уверены, что хотите сбросить настройки? Настройки сброшены по умолчанию diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 242a509..3752a4a 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -47,6 +47,13 @@ 交换上下曲按钮 + 切换曲目 + 长按动作 + 快退 + 快退时长:%d 秒 + 设置快退时长 + 编辑快退时长 + 重置设置 确定要重置设置吗? 设置已恢复默认 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 5be2304..b57c0ed 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -47,6 +47,13 @@ 交換上下曲按鈕 + 切換曲目 + 長按動作 + 倒轉 + 倒轉時長:%d 秒 + 設定倒轉時長 + 編輯倒轉時長 + 重設設定 確定要重設設定嗎? 設定已恢復預設 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 03fc7a1..fc55336 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -50,6 +50,13 @@ Swap Up/Down buttons for skipping + Long press action + Track change + Rewind + Rewind duration: %d sec + Set rewind duration + Edit rewind duration + Reset settings Are you sure you want to reset settings? Settings are reset to default