diff --git a/composeApp/src/commonMain/composeResources/drawable/mouse_left_button_16.svg b/composeApp/src/commonMain/composeResources/drawable/mouse_left_button_16.svg
new file mode 100644
index 000000000..2f58c2f8a
--- /dev/null
+++ b/composeApp/src/commonMain/composeResources/drawable/mouse_left_button_16.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/composeApp/src/commonMain/composeResources/drawable/mouse_m4_button_16.svg b/composeApp/src/commonMain/composeResources/drawable/mouse_m4_button_16.svg
new file mode 100644
index 000000000..4e418198b
--- /dev/null
+++ b/composeApp/src/commonMain/composeResources/drawable/mouse_m4_button_16.svg
@@ -0,0 +1 @@
+
diff --git a/composeApp/src/commonMain/composeResources/drawable/mouse_m5_button_16.svg b/composeApp/src/commonMain/composeResources/drawable/mouse_m5_button_16.svg
new file mode 100644
index 000000000..aa9be7f4f
--- /dev/null
+++ b/composeApp/src/commonMain/composeResources/drawable/mouse_m5_button_16.svg
@@ -0,0 +1 @@
+
diff --git a/composeApp/src/commonMain/composeResources/drawable/mouse_middle_button_16.svg b/composeApp/src/commonMain/composeResources/drawable/mouse_middle_button_16.svg
new file mode 100644
index 000000000..37eab1d78
--- /dev/null
+++ b/composeApp/src/commonMain/composeResources/drawable/mouse_middle_button_16.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/composeApp/src/commonMain/composeResources/drawable/mouse_right_button_16.svg b/composeApp/src/commonMain/composeResources/drawable/mouse_right_button_16.svg
new file mode 100644
index 000000000..e48d5def4
--- /dev/null
+++ b/composeApp/src/commonMain/composeResources/drawable/mouse_right_button_16.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml
index d5262ee13..092944f4c 100644
--- a/composeApp/src/commonMain/composeResources/values/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values/strings.xml
@@ -1,9 +1,4 @@
- Gold
- Jade
- Rose Gold
- Arctic Blue
- Graphite
Choose Profile Background
Custom background URLs can be configured from the Nuvio web panel.
Normal
@@ -1391,6 +1386,23 @@
Rose
Violet
White
+ Custom
+ Your custom gradient
+ Choose three colors for your theme. Select a color to edit it.
+ Edit custom theme
+ Your custom color
+ Choose a color for your theme.
+ Gradient
+ Single color
+ Color %1$d
+ Hue
+ Saturation
+ Brightness
+ Hex color
+ Enter six characters (0–9, A–F), with or without #.
+ Save theme
+ Preview
+ Your accent
Next Episode
Finding source…
Playing via %1$s in %2$d…
@@ -1675,6 +1687,51 @@
Downloading update...
No updates found.
A new version is ready to install.
+ Shortcuts
+ Keyboard and mouse shortcuts.
+ GENERAL & NAVIGATION
+ PLAYER – PLAYBACK
+ Go back / previous screen
+ Show options
+ Switch to home
+ Switch to search
+ Switch to library
+ Switch to settings
+ Activate search box
+ Play / Pause
+ Sequential switch audio track
+ Toggle enable / disable subtitle
+ Toggle mute state
+ Seek forward or backward
+ Volume up / down
+ Toggle app fullscreen
+ Skip intro
+ Open audio selector window
+ Open subtitle selector window
+ Open source list window
+ Open episode list window
+ Move focus and options
+ Play next episode
+ Hold to speed up playback
+ Open playback speed panel
+ Playback speed control
+ Reset playback speed to 1x
+ Decrease / increase subtitle delay
+ Turn on / off sub opacity
+ Increase / reduce opacity of subs
+ or
+ Esc
+ Space
+ Enter
+ Shift
+ Hold Space
+ Left
+ Hold Left
+ Right
+ Forward
+ Backward
+ Scroll Up
+ Scroll Down
In-app updates are not available on this build.
No release notes were provided.
Preparing download
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsModels.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsModels.kt
index c0061f999..f9bd976e1 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsModels.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsModels.kt
@@ -4,6 +4,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.AccountCircle
import androidx.compose.material.icons.rounded.Info
import androidx.compose.material.icons.rounded.Notifications
+import androidx.compose.material.icons.rounded.Keyboard
import androidx.compose.material.icons.rounded.Settings
import androidx.compose.material.icons.rounded.Tune
import androidx.compose.ui.graphics.vector.ImageVector
@@ -28,6 +29,7 @@ import nuvio.composeapp.generated.resources.compose_settings_page_playback
import nuvio.composeapp.generated.resources.compose_settings_page_plugins
import nuvio.composeapp.generated.resources.compose_settings_page_poster_customization
import nuvio.composeapp.generated.resources.compose_settings_page_root
+import nuvio.composeapp.generated.resources.compose_settings_page_shortcuts
import nuvio.composeapp.generated.resources.compose_settings_page_streams
import nuvio.composeapp.generated.resources.compose_settings_page_supporters_contributors
import nuvio.composeapp.generated.resources.compose_settings_page_tmdb_enrichment
@@ -43,6 +45,7 @@ internal enum class SettingsCategory(
Account(Res.string.settings_account, Icons.Rounded.AccountCircle),
General(Res.string.compose_settings_category_general, Icons.Rounded.Settings),
About(Res.string.compose_settings_category_about, Icons.Rounded.Info),
+ Shortcuts(Res.string.compose_settings_page_shortcuts, Icons.Rounded.Keyboard),
Advanced(Res.string.compose_settings_page_advanced, Icons.Rounded.Tune),
}
@@ -162,6 +165,11 @@ internal enum class SettingsPage(
category = SettingsCategory.Account,
parentPage = Root,
),
+ Shortcuts(
+ titleRes = Res.string.compose_settings_page_shortcuts,
+ category = SettingsCategory.Shortcuts,
+ parentPage = Root,
+ ),
}
internal val SettingsPage.opensInlineOnTablet: Boolean
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsRootPage.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsRootPage.kt
index d6d5dcc1d..282237ec4 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsRootPage.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsRootPage.kt
@@ -12,6 +12,7 @@ import androidx.compose.material.icons.rounded.CloudDownload
import androidx.compose.material.icons.rounded.Extension
import androidx.compose.material.icons.rounded.Favorite
import androidx.compose.material.icons.rounded.Info
+import androidx.compose.material.icons.rounded.Keyboard
import androidx.compose.material.icons.rounded.Link
import androidx.compose.material.icons.rounded.Notifications
import androidx.compose.material.icons.rounded.Palette
@@ -39,8 +40,10 @@ import nuvio.composeapp.generated.resources.compose_settings_page_licenses_attri
import nuvio.composeapp.generated.resources.compose_settings_page_notifications
import nuvio.composeapp.generated.resources.compose_settings_page_playback
import nuvio.composeapp.generated.resources.compose_settings_page_privacy_policy
+import nuvio.composeapp.generated.resources.compose_settings_page_shortcuts
import nuvio.composeapp.generated.resources.compose_settings_page_supporters_contributors
import nuvio.composeapp.generated.resources.compose_settings_root_account_description
+import nuvio.composeapp.generated.resources.compose_settings_root_shortcuts_description
import nuvio.composeapp.generated.resources.compose_settings_root_appearance_description
import nuvio.composeapp.generated.resources.compose_settings_root_check_updates_description
import nuvio.composeapp.generated.resources.compose_settings_root_check_updates_title
@@ -74,6 +77,7 @@ internal fun LazyListScope.settingsRootContent(
onPlaybackClick: () -> Unit,
onAppearanceClick: () -> Unit,
onAdvancedClick: () -> Unit,
+ onShortcutsClick: () -> Unit,
onNotificationsClick: () -> Unit,
onContentDiscoveryClick: () -> Unit,
onIntegrationsClick: () -> Unit,
@@ -91,6 +95,7 @@ internal fun LazyListScope.settingsRootContent(
showGeneralSection: Boolean = true,
showAboutSection: Boolean = true,
showAdvancedSection: Boolean = true,
+ showShortcutsSection: Boolean = true,
showSupportersContributorsPage: Boolean = true,
) {
if (showAccountSection) {
@@ -266,6 +271,24 @@ internal fun LazyListScope.settingsRootContent(
}
}
}
+ if (showShortcutsSection) {
+ item {
+ SettingsSection(
+ title = stringResource(Res.string.compose_settings_page_shortcuts),
+ isTablet = isTablet,
+ ) {
+ SettingsGroup(isTablet = isTablet) {
+ SettingsNavigationRow(
+ title = stringResource(Res.string.compose_settings_page_shortcuts),
+ description = stringResource(Res.string.compose_settings_root_shortcuts_description),
+ icon = Icons.Rounded.Keyboard,
+ isTablet = isTablet,
+ onClick = onShortcutsClick,
+ )
+ }
+ }
+ }
+ }
item {
androidx.compose.foundation.layout.Column(
modifier = Modifier
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsScreen.kt
index 31ee628e1..2bf62c53d 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsScreen.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsScreen.kt
@@ -614,6 +614,7 @@ private fun MobileSettingsScreen(
onPlaybackClick = { onPageChange(SettingsPage.Playback) },
onAppearanceClick = { onPageChange(SettingsPage.Appearance) },
onAdvancedClick = { onPageChange(SettingsPage.Advanced) },
+ onShortcutsClick = { onPageChange(SettingsPage.Shortcuts) },
onNotificationsClick = { onPageChange(SettingsPage.Notifications) },
onContentDiscoveryClick = { onPageChange(SettingsPage.ContentDiscovery) },
onIntegrationsClick = { onPageChange(SettingsPage.Integrations) },
@@ -699,6 +700,9 @@ private fun MobileSettingsScreen(
isTablet = false,
rememberLastProfileEnabled = rememberLastProfileEnabled,
)
+ SettingsPage.Shortcuts -> shortcutsSettingsContent(
+ isTablet = false,
+ )
SettingsPage.Notifications -> if (AppFeaturePolicy.notificationsEnabled) {
notificationsSettingsContent(
isTablet = false,
@@ -930,10 +934,12 @@ private fun TabletSettingsScreen(
icon = category.icon,
selected = category == activeCategory,
onClick = {
- if (category != activeCategory || page != SettingsPage.Root) {
+ if (category != activeCategory || (category != SettingsCategory.Shortcuts && page != SettingsPage.Root) || (category == SettingsCategory.Shortcuts && page != SettingsPage.Shortcuts)) {
selectedCategory = category.name
navBarScrollState?.expand()
- if (page != SettingsPage.Root) {
+ if (category == SettingsCategory.Shortcuts) {
+ onPageChange(SettingsPage.Shortcuts)
+ } else {
onPageChange(SettingsPage.Root)
}
}
@@ -1042,7 +1048,7 @@ private fun TabletSettingsScreen(
} else {
stringResource(page.titleRes)
},
- showBack = previousPage != null,
+ showBack = previousPage != null && page != SettingsPage.Shortcuts,
onBack = { previousPage?.let(onPageChange) },
)
}
@@ -1063,6 +1069,7 @@ private fun TabletSettingsScreen(
onPlaybackClick = { openInlinePage(SettingsPage.Playback) },
onAppearanceClick = { openInlinePage(SettingsPage.Appearance) },
onAdvancedClick = { openInlinePage(SettingsPage.Advanced) },
+ onShortcutsClick = { openInlinePage(SettingsPage.Shortcuts) },
onNotificationsClick = { openInlinePage(SettingsPage.Notifications) },
onContentDiscoveryClick = { openInlinePage(SettingsPage.ContentDiscovery) },
onIntegrationsClick = { openInlinePage(SettingsPage.Integrations) },
@@ -1080,10 +1087,14 @@ private fun TabletSettingsScreen(
showGeneralSection = activeCategory == SettingsCategory.General,
showAboutSection = activeCategory == SettingsCategory.About,
showAdvancedSection = activeCategory == SettingsCategory.Advanced,
+ showShortcutsSection = activeCategory == SettingsCategory.Shortcuts,
showSupportersContributorsPage = AppFeaturePolicy.supportersContributorsPageEnabled,
)
}
}
+ SettingsPage.Shortcuts -> shortcutsSettingsContent(
+ isTablet = true,
+ )
SettingsPage.Account -> accountSettingsContent(
isTablet = true,
)
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/ShortcutsSettingsPage.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/ShortcutsSettingsPage.kt
new file mode 100644
index 000000000..96f707048
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/ShortcutsSettingsPage.kt
@@ -0,0 +1,365 @@
+package com.nuvio.app.features.settings
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyListScope
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.KeyboardArrowDown
+import androidx.compose.material.icons.filled.KeyboardArrowLeft
+import androidx.compose.material.icons.filled.KeyboardArrowRight
+import androidx.compose.material.icons.filled.KeyboardArrowUp
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import com.nuvio.app.core.ui.nuvio
+import nuvio.composeapp.generated.resources.*
+import org.jetbrains.compose.resources.stringResource
+
+internal fun LazyListScope.shortcutsSettingsContent(
+ isTablet: Boolean,
+) {
+ item {
+ SettingsSection(
+ title = stringResource(Res.string.compose_settings_shortcuts_section_general),
+ isTablet = isTablet,
+ ) {
+ SettingsGroup(isTablet = isTablet) {
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_back), isTablet) {
+ ShortcutKey(stringResource(Res.string.compose_settings_shortcuts_key_esc))
+ ShortcutOrText()
+ ShortcutMouseKey(MouseButton.Backward, stringResource(Res.string.compose_settings_shortcuts_mouse_backward))
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_options), isTablet) {
+ ShortcutMouseKey(MouseButton.Right, stringResource(Res.string.compose_settings_shortcuts_mouse_right))
+ ShortcutOrText()
+ ShortcutMouseKey(MouseButton.Left, stringResource(Res.string.compose_settings_shortcuts_mouse_hold_left))
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_home), isTablet) {
+ ShortcutKey("1")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_search), isTablet) {
+ ShortcutKey("2")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_library), isTablet) {
+ ShortcutKey("3")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_settings), isTablet) {
+ ShortcutKey("4")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_search_box), isTablet) {
+ ShortcutKey("/")
+ ShortcutOrText()
+ ShortcutKey("0")
+ }
+ }
+ }
+ }
+
+ item {
+ SettingsSection(
+ title = stringResource(Res.string.compose_settings_shortcuts_section_player),
+ isTablet = isTablet,
+ ) {
+ SettingsGroup(isTablet = isTablet) {
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_play_pause), isTablet) {
+ ShortcutKey(stringResource(Res.string.compose_settings_shortcuts_key_space))
+ ShortcutOrText()
+ ShortcutKey("K")
+ ShortcutOrText()
+ ShortcutMouseKey(MouseButton.Left, stringResource(Res.string.compose_settings_shortcuts_mouse_left))
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_audio_track), isTablet) {
+ ShortcutKey("B")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_subtitle_toggle), isTablet) {
+ ShortcutKey("V")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_mute), isTablet) {
+ ShortcutKey("M")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_seek), isTablet) {
+ ShortcutIconKey(Icons.Default.KeyboardArrowLeft)
+ ShortcutOrText()
+ ShortcutIconKey(Icons.Default.KeyboardArrowRight)
+ ShortcutOrText()
+ ShortcutMouseKey(MouseButton.Forward, stringResource(Res.string.compose_settings_shortcuts_mouse_forward))
+ ShortcutOrText()
+ ShortcutMouseKey(MouseButton.Backward, stringResource(Res.string.compose_settings_shortcuts_mouse_backward))
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_volume), isTablet) {
+ ShortcutIconKey(Icons.Default.KeyboardArrowUp)
+ ShortcutOrText()
+ ShortcutIconKey(Icons.Default.KeyboardArrowDown)
+ ShortcutOrText()
+ ShortcutMouseKey(MouseButton.ScrollUp, stringResource(Res.string.compose_settings_shortcuts_mouse_scroll_up))
+ ShortcutOrText()
+ ShortcutMouseKey(MouseButton.ScrollDown, stringResource(Res.string.compose_settings_shortcuts_mouse_scroll_down))
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_fullscreen), isTablet) {
+ ShortcutKey("F11")
+ ShortcutOrText()
+ ShortcutKey("F")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_skip_intro), isTablet) {
+ ShortcutKey(stringResource(Res.string.compose_settings_shortcuts_key_enter))
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_audio_selector), isTablet) {
+ ShortcutKey("A")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_subtitle_selector), isTablet) {
+ ShortcutKey("S")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_source_list), isTablet) {
+ ShortcutKey("Q")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_episode_list), isTablet) {
+ ShortcutKey("E")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_focus_options), isTablet) {
+ ShortcutIconKey(Icons.Default.KeyboardArrowUp)
+ ShortcutOrText()
+ ShortcutIconKey(Icons.Default.KeyboardArrowDown)
+ ShortcutOrText()
+ ShortcutIconKey(Icons.Default.KeyboardArrowLeft)
+ ShortcutOrText()
+ ShortcutIconKey(Icons.Default.KeyboardArrowRight)
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_next_episode), isTablet) {
+ ShortcutKey(stringResource(Res.string.compose_settings_shortcuts_key_shift))
+ ShortcutPlusText()
+ ShortcutKey("N")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_speed_hold), isTablet) {
+ ShortcutKey(stringResource(Res.string.compose_settings_shortcuts_key_hold_space))
+ ShortcutOrText()
+ ShortcutMouseKey(MouseButton.Left, stringResource(Res.string.compose_settings_shortcuts_mouse_hold_left))
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_speed_panel), isTablet) {
+ ShortcutKey("`")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_speed_control), isTablet) {
+ ShortcutKey(stringResource(Res.string.compose_settings_shortcuts_key_shift))
+ ShortcutPlusText()
+ ShortcutKey("<")
+ ShortcutOrText()
+ ShortcutKey(stringResource(Res.string.compose_settings_shortcuts_key_shift))
+ ShortcutPlusText()
+ ShortcutKey(">")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_speed_reset), isTablet) {
+ ShortcutKey("/")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_subtitle_delay), isTablet) {
+ ShortcutKey("G")
+ ShortcutOrText()
+ ShortcutKey("H")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_sub_opacity_toggle), isTablet) {
+ ShortcutKey("O")
+ }
+ SettingsGroupDivider(isTablet = isTablet)
+ ShortcutRow(stringResource(Res.string.compose_settings_shortcuts_row_sub_opacity_adjust), isTablet) {
+ ShortcutKey("I")
+ ShortcutOrText()
+ ShortcutKey("P")
+ }
+ }
+ }
+ }
+}
+
+@Composable
+private fun ShortcutRow(
+ title: String,
+ isTablet: Boolean,
+ keys: @Composable RowScope.() -> Unit,
+) {
+ val tokens = MaterialTheme.nuvio
+ val verticalPadding = if (isTablet) 16.dp else 14.dp
+ val horizontalPadding = if (isTablet) 20.dp else 16.dp
+
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = horizontalPadding, vertical = verticalPadding),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.SpaceBetween,
+ ) {
+ Text(
+ text = title,
+ style = MaterialTheme.typography.bodyLarge,
+ color = tokens.colors.textPrimary,
+ )
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
+ ) {
+ keys()
+ }
+ }
+}
+
+@Composable
+private fun ShortcutKey(label: String) {
+ val tokens = MaterialTheme.nuvio
+ Box(
+ modifier = Modifier
+ .background(
+ color = tokens.colors.surfaceCard,
+ shape = RoundedCornerShape(6.dp)
+ )
+ .border(
+ width = 1.dp,
+ color = tokens.colors.borderSubtle,
+ shape = RoundedCornerShape(6.dp)
+ )
+ .padding(horizontal = 8.dp, vertical = 4.dp),
+ contentAlignment = Alignment.Center,
+ ) {
+ Text(
+ text = label,
+ style = MaterialTheme.typography.labelLarge,
+ color = tokens.colors.textPrimary,
+ fontWeight = FontWeight.Bold,
+ fontFamily = FontFamily.Monospace,
+ )
+ }
+}
+
+@Composable
+private fun ShortcutIconKey(icon: androidx.compose.ui.graphics.vector.ImageVector) {
+ val tokens = MaterialTheme.nuvio
+ Box(
+ modifier = Modifier
+ .background(
+ color = tokens.colors.surfaceCard,
+ shape = RoundedCornerShape(6.dp)
+ )
+ .border(
+ width = 1.dp,
+ color = tokens.colors.borderSubtle,
+ shape = RoundedCornerShape(6.dp)
+ )
+ .padding(horizontal = 4.dp, vertical = 2.dp),
+ contentAlignment = Alignment.Center,
+ ) {
+ Icon(
+ imageVector = icon,
+ contentDescription = null,
+ tint = tokens.colors.textPrimary,
+ modifier = Modifier.size(18.dp)
+ )
+ }
+}
+
+enum class MouseButton { Left, Right, Middle, ScrollUp, ScrollDown, Forward, Backward, None }
+
+@Composable
+private fun ShortcutMouseKey(button: MouseButton, label: String, modifier: Modifier = Modifier) {
+ Box(
+ modifier = modifier
+ .border(
+ width = 1.dp,
+ color = MaterialTheme.nuvio.colors.borderSubtle,
+ shape = RoundedCornerShape(6.dp)
+ )
+ .background(
+ color = MaterialTheme.nuvio.colors.surfaceCard,
+ shape = RoundedCornerShape(6.dp)
+ )
+ .padding(horizontal = 6.dp, vertical = 4.dp),
+ contentAlignment = Alignment.Center
+ ) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.spacedBy(6.dp)
+ ) {
+ val iconRes = when (button) {
+ MouseButton.Left -> Res.drawable.mouse_left_button_16
+ MouseButton.Right -> Res.drawable.mouse_right_button_16
+ MouseButton.Middle, MouseButton.ScrollUp, MouseButton.ScrollDown -> Res.drawable.mouse_middle_button_16
+ MouseButton.Forward -> Res.drawable.mouse_m4_button_16
+ MouseButton.Backward -> Res.drawable.mouse_m5_button_16
+ MouseButton.None -> null
+ }
+
+ if (iconRes != null) {
+ Icon(
+ painter = org.jetbrains.compose.resources.painterResource(iconRes),
+ contentDescription = null,
+ tint = MaterialTheme.nuvio.colors.textPrimary,
+ modifier = Modifier.size(16.dp)
+ )
+ } else {
+ Box(modifier = Modifier.size(16.dp))
+ }
+
+ Text(
+ text = label,
+ color = MaterialTheme.nuvio.colors.textPrimary,
+ fontFamily = FontFamily.Monospace,
+ style = MaterialTheme.typography.bodyMedium,
+ fontWeight = FontWeight.Bold
+ )
+ }
+ }
+}
+
+@Composable
+private fun ShortcutOrText() {
+ Text(
+ text = stringResource(Res.string.compose_settings_shortcuts_or),
+ style = MaterialTheme.typography.bodyMedium,
+ color = MaterialTheme.nuvio.colors.textSecondary,
+ modifier = Modifier.padding(horizontal = 2.dp)
+ )
+}
+
+@Composable
+private fun ShortcutPlusText() {
+ Text(
+ text = "+",
+ style = MaterialTheme.typography.bodyMedium,
+ color = MaterialTheme.nuvio.colors.textSecondary,
+ modifier = Modifier.padding(horizontal = 2.dp)
+ )
+}