mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Save remembered tabs per user (#57)
If the remember tab setting is enabled, tabs will be remembered per user profile now
This commit is contained in:
parent
f5ee5eceab
commit
b5771db54e
6 changed files with 98 additions and 39 deletions
|
|
@ -3,13 +3,23 @@ package com.github.damontecres.wholphin.hilt
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
|
import androidx.datastore.core.DataStore
|
||||||
import com.github.damontecres.wholphin.BuildConfig
|
import com.github.damontecres.wholphin.BuildConfig
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
|
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||||
|
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||||
|
import com.github.damontecres.wholphin.preferences.updateInterfacePreferences
|
||||||
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
|
import com.github.damontecres.wholphin.util.RememberTabManager
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import org.jellyfin.sdk.Jellyfin
|
import org.jellyfin.sdk.Jellyfin
|
||||||
import org.jellyfin.sdk.api.client.util.AuthorizationHeaderBuilder
|
import org.jellyfin.sdk.api.client.util.AuthorizationHeaderBuilder
|
||||||
|
|
@ -17,6 +27,7 @@ import org.jellyfin.sdk.api.okhttp.OkHttpFactory
|
||||||
import org.jellyfin.sdk.createJellyfin
|
import org.jellyfin.sdk.createJellyfin
|
||||||
import org.jellyfin.sdk.model.ClientInfo
|
import org.jellyfin.sdk.model.ClientInfo
|
||||||
import org.jellyfin.sdk.model.DeviceInfo
|
import org.jellyfin.sdk.model.DeviceInfo
|
||||||
|
import java.util.UUID
|
||||||
import javax.inject.Qualifier
|
import javax.inject.Qualifier
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
|
@ -28,6 +39,10 @@ annotation class AuthOkHttpClient
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
annotation class StandardOkHttpClient
|
annotation class StandardOkHttpClient
|
||||||
|
|
||||||
|
@Qualifier
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
annotation class IoCoroutineScope
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
object AppModule {
|
object AppModule {
|
||||||
|
|
@ -118,4 +133,51 @@ object AppModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun apiClient(jellyfin: Jellyfin) = jellyfin.createApi()
|
fun apiClient(jellyfin: Jellyfin) = jellyfin.createApi()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of [RememberTabManager] which remembers by server, user, & item
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun rememberTabManager(
|
||||||
|
serverRepository: ServerRepository,
|
||||||
|
appPreference: DataStore<AppPreferences>,
|
||||||
|
@IoCoroutineScope scope: CoroutineScope,
|
||||||
|
) = object : RememberTabManager {
|
||||||
|
fun key(itemId: UUID) = "${serverRepository.currentServer?.id}_${serverRepository.currentUser?.id}_$itemId"
|
||||||
|
|
||||||
|
override fun getRememberedTab(
|
||||||
|
preferences: UserPreferences,
|
||||||
|
itemId: UUID,
|
||||||
|
defaultTab: Int,
|
||||||
|
): Int {
|
||||||
|
if (preferences.appPreferences.interfacePreferences.rememberSelectedTab) {
|
||||||
|
return preferences.appPreferences.interfacePreferences
|
||||||
|
.getRememberedTabsOrDefault(key(itemId), defaultTab)
|
||||||
|
} else {
|
||||||
|
return defaultTab
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun saveRememberedTab(
|
||||||
|
preferences: UserPreferences,
|
||||||
|
itemId: UUID,
|
||||||
|
tabIndex: Int,
|
||||||
|
) {
|
||||||
|
if (preferences.appPreferences.interfacePreferences.rememberSelectedTab) {
|
||||||
|
scope.launch(ExceptionHandler()) {
|
||||||
|
appPreference.updateData {
|
||||||
|
preferences.appPreferences.updateInterfacePreferences {
|
||||||
|
putRememberedTabs(key(itemId), tabIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@IoCoroutineScope
|
||||||
|
fun ioCoroutineScope(): CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,8 @@ package com.github.damontecres.wholphin.preferences
|
||||||
import androidx.datastore.core.CorruptionException
|
import androidx.datastore.core.CorruptionException
|
||||||
import androidx.datastore.core.Serializer
|
import androidx.datastore.core.Serializer
|
||||||
import com.google.protobuf.InvalidProtocolBufferException
|
import com.google.protobuf.InvalidProtocolBufferException
|
||||||
import timber.log.Timber
|
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import java.util.UUID
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.time.Duration.Companion.hours
|
import kotlin.time.Duration.Companion.hours
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
@ -108,13 +106,3 @@ inline fun AppPreferences.updateInterfacePreferences(block: InterfacePreferences
|
||||||
update {
|
update {
|
||||||
interfacePreferences = interfacePreferences.toBuilder().apply(block).build()
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ import androidx.tv.material3.Text
|
||||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||||
import com.github.damontecres.wholphin.data.model.GetItemsFilter
|
import com.github.damontecres.wholphin.data.model.GetItemsFilter
|
||||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.rememberTab
|
|
||||||
import com.github.damontecres.wholphin.ui.components.CollectionFolderGrid
|
import com.github.damontecres.wholphin.ui.components.CollectionFolderGrid
|
||||||
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
||||||
import com.github.damontecres.wholphin.ui.components.GenreCardGrid
|
import com.github.damontecres.wholphin.ui.components.GenreCardGrid
|
||||||
|
|
@ -50,13 +49,8 @@ fun CollectionFolderMovie(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
preferencesViewModel: PreferencesViewModel = hiltViewModel(),
|
preferencesViewModel: PreferencesViewModel = hiltViewModel(),
|
||||||
) {
|
) {
|
||||||
val uiPrefs = preferences.appPreferences.interfacePreferences
|
|
||||||
val rememberedTabIndex =
|
val rememberedTabIndex =
|
||||||
if (uiPrefs.rememberSelectedTab) {
|
remember { preferencesViewModel.getRememberedTab(preferences, destination.itemId, 0) }
|
||||||
uiPrefs.getRememberedTabsOrDefault(destination.itemId.toString(), 0)
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
val tabs = listOf("Recommended", "Library", "Genres")
|
val tabs = listOf("Recommended", "Library", "Genres")
|
||||||
var focusTabIndex by rememberSaveable { mutableIntStateOf(rememberedTabIndex) }
|
var focusTabIndex by rememberSaveable { mutableIntStateOf(rememberedTabIndex) }
|
||||||
|
|
@ -66,13 +60,10 @@ fun CollectionFolderMovie(
|
||||||
val firstTabFocusRequester = remember { FocusRequester() }
|
val firstTabFocusRequester = remember { FocusRequester() }
|
||||||
LaunchedEffect(Unit) { firstTabFocusRequester.tryRequestFocus() }
|
LaunchedEffect(Unit) { firstTabFocusRequester.tryRequestFocus() }
|
||||||
|
|
||||||
if (uiPrefs.rememberSelectedTab) {
|
|
||||||
LaunchedEffect(selectedTabIndex) {
|
LaunchedEffect(selectedTabIndex) {
|
||||||
preferencesViewModel.preferenceDataStore.updateData {
|
preferencesViewModel.saveRememberedTab(preferences, destination.itemId, selectedTabIndex)
|
||||||
preferences.appPreferences.rememberTab(destination.itemId, selectedTabIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var showHeader by rememberSaveable { mutableStateOf(true) }
|
var showHeader by rememberSaveable { mutableStateOf(true) }
|
||||||
|
|
||||||
val onClickItem = { item: BaseItem ->
|
val onClickItem = { item: BaseItem ->
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ import androidx.tv.material3.Text
|
||||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||||
import com.github.damontecres.wholphin.data.model.GetItemsFilter
|
import com.github.damontecres.wholphin.data.model.GetItemsFilter
|
||||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.rememberTab
|
|
||||||
import com.github.damontecres.wholphin.ui.components.CollectionFolderGrid
|
import com.github.damontecres.wholphin.ui.components.CollectionFolderGrid
|
||||||
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
||||||
import com.github.damontecres.wholphin.ui.components.GenreCardGrid
|
import com.github.damontecres.wholphin.ui.components.GenreCardGrid
|
||||||
|
|
@ -50,13 +49,8 @@ fun CollectionFolderTv(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
preferencesViewModel: PreferencesViewModel = hiltViewModel(),
|
preferencesViewModel: PreferencesViewModel = hiltViewModel(),
|
||||||
) {
|
) {
|
||||||
val uiPrefs = preferences.appPreferences.interfacePreferences
|
|
||||||
val rememberedTabIndex =
|
val rememberedTabIndex =
|
||||||
if (uiPrefs.rememberSelectedTab) {
|
remember { preferencesViewModel.getRememberedTab(preferences, destination.itemId, 0) }
|
||||||
uiPrefs.getRememberedTabsOrDefault(destination.itemId.toString(), 0)
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
val tabs = listOf("Recommended", "Library", "Genres")
|
val tabs = listOf("Recommended", "Library", "Genres")
|
||||||
var focusTabIndex by rememberSaveable { mutableIntStateOf(rememberedTabIndex) }
|
var focusTabIndex by rememberSaveable { mutableIntStateOf(rememberedTabIndex) }
|
||||||
|
|
@ -66,13 +60,10 @@ fun CollectionFolderTv(
|
||||||
val firstTabFocusRequester = remember { FocusRequester() }
|
val firstTabFocusRequester = remember { FocusRequester() }
|
||||||
LaunchedEffect(Unit) { firstTabFocusRequester.tryRequestFocus() }
|
LaunchedEffect(Unit) { firstTabFocusRequester.tryRequestFocus() }
|
||||||
|
|
||||||
if (uiPrefs.rememberSelectedTab) {
|
|
||||||
LaunchedEffect(selectedTabIndex) {
|
LaunchedEffect(selectedTabIndex) {
|
||||||
preferencesViewModel.preferenceDataStore.updateData {
|
preferencesViewModel.saveRememberedTab(preferences, destination.itemId, selectedTabIndex)
|
||||||
preferences.appPreferences.rememberTab(destination.itemId, selectedTabIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val onClickItem = { item: BaseItem ->
|
val onClickItem = { item: BaseItem ->
|
||||||
preferencesViewModel.navigationManager.navigateTo(item.destination())
|
preferencesViewModel.navigationManager.navigateTo(item.destination())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import androidx.datastore.core.DataStore
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||||
import com.github.damontecres.wholphin.ui.nav.NavigationManager
|
import com.github.damontecres.wholphin.ui.nav.NavigationManager
|
||||||
|
import com.github.damontecres.wholphin.util.RememberTabManager
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -13,4 +14,6 @@ class PreferencesViewModel
|
||||||
constructor(
|
constructor(
|
||||||
val preferenceDataStore: DataStore<AppPreferences>,
|
val preferenceDataStore: DataStore<AppPreferences>,
|
||||||
val navigationManager: NavigationManager,
|
val navigationManager: NavigationManager,
|
||||||
) : ViewModel()
|
val rememberTabManager: RememberTabManager,
|
||||||
|
) : ViewModel(),
|
||||||
|
RememberTabManager by rememberTabManager
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.github.damontecres.wholphin.util
|
||||||
|
|
||||||
|
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
interface RememberTabManager {
|
||||||
|
/**
|
||||||
|
* If enabled, get the remembered tab index for the given item
|
||||||
|
*/
|
||||||
|
fun getRememberedTab(
|
||||||
|
preferences: UserPreferences,
|
||||||
|
itemId: UUID,
|
||||||
|
defaultTab: Int,
|
||||||
|
): Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If enabled, save the remembered tab index for the given item
|
||||||
|
*/
|
||||||
|
fun saveRememberedTab(
|
||||||
|
preferences: UserPreferences,
|
||||||
|
itemId: UUID,
|
||||||
|
tabIndex: Int,
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue