mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Better tab UI & remember tab setting
This commit is contained in:
parent
c642636da7
commit
88038bfcfd
7 changed files with 139 additions and 15 deletions
|
|
@ -254,6 +254,18 @@ sealed interface AppPreference<T> {
|
|||
},
|
||||
)
|
||||
|
||||
val RememberSelectedTab =
|
||||
AppSwitchPreference(
|
||||
title = R.string.remember_selected_tab,
|
||||
defaultValue = false,
|
||||
getter = { it.interfacePreferences.rememberSelectedTab },
|
||||
setter = { prefs, value ->
|
||||
prefs.updateInterfacePreferences { rememberSelectedTab = value }
|
||||
},
|
||||
summaryOn = R.string.enabled,
|
||||
summaryOff = R.string.disabled,
|
||||
)
|
||||
|
||||
val InstalledVersion =
|
||||
AppClickablePreference(
|
||||
title = R.string.installed_version,
|
||||
|
|
@ -301,6 +313,7 @@ val basicPreferences =
|
|||
AppPreference.HomePageItems,
|
||||
AppPreference.RewatchNextUp,
|
||||
AppPreference.PlayThemeMusic,
|
||||
AppPreference.RememberSelectedTab,
|
||||
),
|
||||
),
|
||||
PreferenceGroup(
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ package com.github.damontecres.dolphin.preferences
|
|||
import androidx.datastore.core.CorruptionException
|
||||
import androidx.datastore.core.Serializer
|
||||
import com.google.protobuf.InvalidProtocolBufferException
|
||||
import timber.log.Timber
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
|
|
@ -77,3 +79,13 @@ inline fun AppPreferences.updateInterfacePreferences(block: InterfacePreferences
|
|||
update {
|
||||
interfacePreferences = interfacePreferences.toBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
fun AppPreferences.rememberTab(
|
||||
itemId: UUID,
|
||||
index: Int,
|
||||
): AppPreferences {
|
||||
Timber.v("Updating $itemId tab to $index")
|
||||
return updateInterfacePreferences {
|
||||
putRememberedTabs(itemId.toString(), index)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,17 +14,23 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.focus.focusRestorer
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Tab
|
||||
import androidx.tv.material3.TabDefaults
|
||||
import androidx.tv.material3.TabRow
|
||||
import androidx.tv.material3.TabRowDefaults
|
||||
import androidx.tv.material3.Text
|
||||
import com.github.damontecres.dolphin.preferences.UserPreferences
|
||||
import com.github.damontecres.dolphin.preferences.rememberTab
|
||||
import com.github.damontecres.dolphin.ui.components.ErrorMessage
|
||||
import com.github.damontecres.dolphin.ui.components.RecommendedMovie
|
||||
import com.github.damontecres.dolphin.ui.ifElse
|
||||
import com.github.damontecres.dolphin.ui.nav.Destination
|
||||
import com.github.damontecres.dolphin.ui.nav.NavigationManager
|
||||
import com.github.damontecres.dolphin.ui.preferences.PreferencesViewModel
|
||||
import com.github.damontecres.dolphin.ui.tryRequestFocus
|
||||
|
||||
@Composable
|
||||
|
|
@ -33,29 +39,71 @@ fun CollectionFolderMovie(
|
|||
navigationManager: NavigationManager,
|
||||
destination: Destination.MediaItem,
|
||||
modifier: Modifier = Modifier,
|
||||
preferencesViewModel: PreferencesViewModel = hiltViewModel(),
|
||||
) {
|
||||
val uiPrefs = preferences.appPreferences.interfacePreferences
|
||||
val rememberedTabIndex =
|
||||
if (uiPrefs.rememberSelectedTab) {
|
||||
uiPrefs.getRememberedTabsOrDefault(destination.itemId.toString(), 0)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
val tabs = listOf("Recommended", "Library")
|
||||
var selectedTabIndex by rememberSaveable { mutableIntStateOf(0) }
|
||||
var focusTabIndex by rememberSaveable { mutableIntStateOf(rememberedTabIndex) }
|
||||
var selectedTabIndex by rememberSaveable { mutableIntStateOf(rememberedTabIndex) }
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
|
||||
val firstTabFocusRequester = remember { FocusRequester() }
|
||||
LaunchedEffect(Unit) { firstTabFocusRequester.tryRequestFocus() }
|
||||
|
||||
if (uiPrefs.rememberSelectedTab) {
|
||||
LaunchedEffect(selectedTabIndex) {
|
||||
preferencesViewModel.preferenceDataStore.updateData {
|
||||
preferences.appPreferences.rememberTab(destination.itemId, selectedTabIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) { focusRequester.tryRequestFocus() }
|
||||
Column(
|
||||
modifier = modifier,
|
||||
) {
|
||||
TabRow(
|
||||
selectedTabIndex = selectedTabIndex,
|
||||
selectedTabIndex = focusTabIndex,
|
||||
modifier =
|
||||
Modifier
|
||||
.padding(start = 32.dp, top = 16.dp)
|
||||
.focusRestorer(firstTabFocusRequester),
|
||||
.padding(start = 32.dp, top = 16.dp, bottom = 16.dp)
|
||||
.focusRestorer(firstTabFocusRequester)
|
||||
.onFocusChanged {
|
||||
if (!it.isFocused) {
|
||||
focusTabIndex = selectedTabIndex
|
||||
}
|
||||
},
|
||||
indicator =
|
||||
@Composable { tabPositions, doesTabRowHaveFocus ->
|
||||
tabPositions.getOrNull(focusTabIndex)?.let { currentTabPosition ->
|
||||
// TabRowDefaults.PillIndicator(
|
||||
// currentTabPosition = currentTabPosition,
|
||||
// doesTabRowHaveFocus = doesTabRowHaveFocus,
|
||||
// )
|
||||
TabRowDefaults.UnderlinedIndicator(
|
||||
currentTabPosition = currentTabPosition,
|
||||
doesTabRowHaveFocus = doesTabRowHaveFocus,
|
||||
activeColor = MaterialTheme.colorScheme.border,
|
||||
)
|
||||
}
|
||||
},
|
||||
tabs = {
|
||||
tabs.forEachIndexed { index, title ->
|
||||
Tab(
|
||||
selected = selectedTabIndex == index,
|
||||
selected = focusTabIndex == index,
|
||||
onClick = { selectedTabIndex = index },
|
||||
onFocus = {},
|
||||
onFocus = { focusTabIndex = index },
|
||||
colors =
|
||||
TabDefaults.pillIndicatorTabColors(
|
||||
focusedContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
|
|
@ -64,7 +112,7 @@ fun CollectionFolderMovie(
|
|||
Modifier
|
||||
.padding(8.dp)
|
||||
.ifElse(
|
||||
index == 0,
|
||||
index == selectedTabIndex,
|
||||
Modifier.focusRequester(firstTabFocusRequester),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -14,17 +14,23 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.focus.focusRestorer
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Tab
|
||||
import androidx.tv.material3.TabDefaults
|
||||
import androidx.tv.material3.TabRow
|
||||
import androidx.tv.material3.TabRowDefaults
|
||||
import androidx.tv.material3.Text
|
||||
import com.github.damontecres.dolphin.preferences.UserPreferences
|
||||
import com.github.damontecres.dolphin.preferences.rememberTab
|
||||
import com.github.damontecres.dolphin.ui.components.ErrorMessage
|
||||
import com.github.damontecres.dolphin.ui.components.RecommendedTvShow
|
||||
import com.github.damontecres.dolphin.ui.ifElse
|
||||
import com.github.damontecres.dolphin.ui.nav.Destination
|
||||
import com.github.damontecres.dolphin.ui.nav.NavigationManager
|
||||
import com.github.damontecres.dolphin.ui.preferences.PreferencesViewModel
|
||||
import com.github.damontecres.dolphin.ui.tryRequestFocus
|
||||
|
||||
@Composable
|
||||
|
|
@ -33,29 +39,71 @@ fun CollectionFolderTv(
|
|||
navigationManager: NavigationManager,
|
||||
destination: Destination.MediaItem,
|
||||
modifier: Modifier = Modifier,
|
||||
preferencesViewModel: PreferencesViewModel = hiltViewModel(),
|
||||
) {
|
||||
val uiPrefs = preferences.appPreferences.interfacePreferences
|
||||
val rememberedTabIndex =
|
||||
if (uiPrefs.rememberSelectedTab) {
|
||||
uiPrefs.getRememberedTabsOrDefault(destination.itemId.toString(), 0)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
val tabs = listOf("Recommended", "Library")
|
||||
var selectedTabIndex by rememberSaveable { mutableIntStateOf(0) }
|
||||
var focusTabIndex by rememberSaveable { mutableIntStateOf(rememberedTabIndex) }
|
||||
var selectedTabIndex by rememberSaveable { mutableIntStateOf(rememberedTabIndex) }
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
|
||||
val firstTabFocusRequester = remember { FocusRequester() }
|
||||
LaunchedEffect(Unit) { firstTabFocusRequester.tryRequestFocus() }
|
||||
|
||||
if (uiPrefs.rememberSelectedTab) {
|
||||
LaunchedEffect(selectedTabIndex) {
|
||||
preferencesViewModel.preferenceDataStore.updateData {
|
||||
preferences.appPreferences.rememberTab(destination.itemId, selectedTabIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) { focusRequester.tryRequestFocus() }
|
||||
Column(
|
||||
modifier = modifier,
|
||||
) {
|
||||
TabRow(
|
||||
selectedTabIndex = selectedTabIndex,
|
||||
selectedTabIndex = focusTabIndex,
|
||||
modifier =
|
||||
Modifier
|
||||
.padding(start = 32.dp, top = 16.dp)
|
||||
.focusRestorer(firstTabFocusRequester),
|
||||
.padding(start = 32.dp, top = 16.dp, bottom = 16.dp)
|
||||
.focusRestorer(firstTabFocusRequester)
|
||||
.onFocusChanged {
|
||||
if (!it.isFocused) {
|
||||
focusTabIndex = selectedTabIndex
|
||||
}
|
||||
},
|
||||
indicator =
|
||||
@Composable { tabPositions, doesTabRowHaveFocus ->
|
||||
tabPositions.getOrNull(focusTabIndex)?.let { currentTabPosition ->
|
||||
// TabRowDefaults.PillIndicator(
|
||||
// currentTabPosition = currentTabPosition,
|
||||
// doesTabRowHaveFocus = doesTabRowHaveFocus,
|
||||
// )
|
||||
TabRowDefaults.UnderlinedIndicator(
|
||||
currentTabPosition = currentTabPosition,
|
||||
doesTabRowHaveFocus = doesTabRowHaveFocus,
|
||||
activeColor = MaterialTheme.colorScheme.border,
|
||||
)
|
||||
}
|
||||
},
|
||||
tabs = {
|
||||
tabs.forEachIndexed { index, title ->
|
||||
Tab(
|
||||
selected = selectedTabIndex == index,
|
||||
selected = focusTabIndex == index,
|
||||
onClick = { selectedTabIndex = index },
|
||||
onFocus = {},
|
||||
onFocus = { focusTabIndex = index },
|
||||
colors =
|
||||
TabDefaults.pillIndicatorTabColors(
|
||||
focusedContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
|
|
@ -64,7 +112,7 @@ fun CollectionFolderTv(
|
|||
Modifier
|
||||
.padding(8.dp)
|
||||
.ifElse(
|
||||
index == 0,
|
||||
index == selectedTabIndex,
|
||||
Modifier.focusRequester(firstTabFocusRequester),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ data class HomeRow(
|
|||
fun HomePage(
|
||||
preferences: UserPreferences,
|
||||
navigationManager: NavigationManager,
|
||||
modifier: Modifier,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: HomeViewModel = hiltViewModel(),
|
||||
) {
|
||||
OneTimeLaunchedEffect {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ enum ThemeSongVolume {
|
|||
|
||||
message InterfacePreferences {
|
||||
ThemeSongVolume play_theme_songs = 1;
|
||||
bool remember_selected_tab = 2;
|
||||
map<string, int32> remembered_tabs = 3;
|
||||
}
|
||||
|
||||
message AppPreferences {
|
||||
|
|
|
|||
|
|
@ -59,5 +59,6 @@
|
|||
<string name="pref_key_update_last_check_threshold">preference.update.threshold</string>
|
||||
<string name="pref_key_update_last_check">preference.update.lastTimestamp</string>
|
||||
<string name="confirm">Confirm</string>
|
||||
<string name="remember_selected_tab">Remember selected tabs</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue