Tweak tablet UI mode setting (#8262)
This commit is contained in:
parent
b3557e844c
commit
d558f9e1d6
@ -166,7 +166,6 @@ dependencies {
|
|||||||
implementation(compose.activity)
|
implementation(compose.activity)
|
||||||
implementation(compose.foundation)
|
implementation(compose.foundation)
|
||||||
implementation(compose.material3.core)
|
implementation(compose.material3.core)
|
||||||
implementation(compose.material3.windowsizeclass)
|
|
||||||
implementation(compose.material3.adapter)
|
implementation(compose.material3.adapter)
|
||||||
implementation(compose.material.icons)
|
implementation(compose.material.icons)
|
||||||
implementation(compose.animation)
|
implementation(compose.animation)
|
||||||
@ -324,7 +323,6 @@ tasks {
|
|||||||
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
|
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
|
||||||
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
|
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
|
||||||
"-opt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi",
|
"-opt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi",
|
||||||
"-opt-in=androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi",
|
|
||||||
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||||
"-opt-in=kotlinx.coroutines.FlowPreview",
|
"-opt-in=kotlinx.coroutines.FlowPreview",
|
||||||
"-opt-in=kotlinx.coroutines.InternalCoroutinesApi",
|
"-opt-in=kotlinx.coroutines.InternalCoroutinesApi",
|
||||||
|
@ -30,7 +30,6 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@ -72,7 +71,7 @@ import eu.kanade.tachiyomi.ui.manga.MangaScreenState
|
|||||||
fun MangaScreen(
|
fun MangaScreen(
|
||||||
state: MangaScreenState.Success,
|
state: MangaScreenState.Success,
|
||||||
snackbarHostState: SnackbarHostState,
|
snackbarHostState: SnackbarHostState,
|
||||||
windowWidthSizeClass: WindowWidthSizeClass,
|
isTabletUi: Boolean,
|
||||||
onBackClicked: () -> Unit,
|
onBackClicked: () -> Unit,
|
||||||
onChapterClicked: (Chapter) -> Unit,
|
onChapterClicked: (Chapter) -> Unit,
|
||||||
onDownloadChapter: ((List<ChapterItem>, ChapterDownloadAction) -> Unit)?,
|
onDownloadChapter: ((List<ChapterItem>, ChapterDownloadAction) -> Unit)?,
|
||||||
@ -105,7 +104,7 @@ fun MangaScreen(
|
|||||||
onAllChapterSelected: (Boolean) -> Unit,
|
onAllChapterSelected: (Boolean) -> Unit,
|
||||||
onInvertSelection: () -> Unit,
|
onInvertSelection: () -> Unit,
|
||||||
) {
|
) {
|
||||||
if (windowWidthSizeClass == WindowWidthSizeClass.Compact) {
|
if (!isTabletUi) {
|
||||||
MangaScreenSmallImpl(
|
MangaScreenSmallImpl(
|
||||||
state = state,
|
state = state,
|
||||||
snackbarHostState = snackbarHostState,
|
snackbarHostState = snackbarHostState,
|
||||||
@ -136,7 +135,6 @@ fun MangaScreen(
|
|||||||
} else {
|
} else {
|
||||||
MangaScreenLargeImpl(
|
MangaScreenLargeImpl(
|
||||||
state = state,
|
state = state,
|
||||||
windowWidthSizeClass = windowWidthSizeClass,
|
|
||||||
snackbarHostState = snackbarHostState,
|
snackbarHostState = snackbarHostState,
|
||||||
onBackClicked = onBackClicked,
|
onBackClicked = onBackClicked,
|
||||||
onChapterClicked = onChapterClicked,
|
onChapterClicked = onChapterClicked,
|
||||||
@ -308,7 +306,7 @@ private fun MangaScreenSmallImpl(
|
|||||||
contentType = MangaScreenItem.INFO_BOX,
|
contentType = MangaScreenItem.INFO_BOX,
|
||||||
) {
|
) {
|
||||||
MangaInfoBox(
|
MangaInfoBox(
|
||||||
windowWidthSizeClass = WindowWidthSizeClass.Compact,
|
isTabletUi = false,
|
||||||
appBarPadding = topPadding,
|
appBarPadding = topPadding,
|
||||||
title = state.manga.title,
|
title = state.manga.title,
|
||||||
author = state.manga.author,
|
author = state.manga.author,
|
||||||
@ -373,7 +371,6 @@ private fun MangaScreenSmallImpl(
|
|||||||
@Composable
|
@Composable
|
||||||
fun MangaScreenLargeImpl(
|
fun MangaScreenLargeImpl(
|
||||||
state: MangaScreenState.Success,
|
state: MangaScreenState.Success,
|
||||||
windowWidthSizeClass: WindowWidthSizeClass,
|
|
||||||
snackbarHostState: SnackbarHostState,
|
snackbarHostState: SnackbarHostState,
|
||||||
onBackClicked: () -> Unit,
|
onBackClicked: () -> Unit,
|
||||||
onChapterClicked: (Chapter) -> Unit,
|
onChapterClicked: (Chapter) -> Unit,
|
||||||
@ -505,7 +502,7 @@ fun MangaScreenLargeImpl(
|
|||||||
.verticalScroll(rememberScrollState()),
|
.verticalScroll(rememberScrollState()),
|
||||||
) {
|
) {
|
||||||
MangaInfoBox(
|
MangaInfoBox(
|
||||||
windowWidthSizeClass = windowWidthSizeClass,
|
isTabletUi = true,
|
||||||
appBarPadding = contentPadding.calculateTopPadding(),
|
appBarPadding = contentPadding.calculateTopPadding(),
|
||||||
title = state.manga.title,
|
title = state.manga.title,
|
||||||
author = state.manga.author,
|
author = state.manga.author,
|
||||||
|
@ -43,7 +43,6 @@ import androidx.compose.material3.ProvideTextStyle
|
|||||||
import androidx.compose.material3.SuggestionChip
|
import androidx.compose.material3.SuggestionChip
|
||||||
import androidx.compose.material3.SuggestionChipDefaults
|
import androidx.compose.material3.SuggestionChipDefaults
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@ -88,7 +87,7 @@ private val whitespaceLineRegex = Regex("[\\r\\n]{2,}", setOf(RegexOption.MULTIL
|
|||||||
@Composable
|
@Composable
|
||||||
fun MangaInfoBox(
|
fun MangaInfoBox(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
windowWidthSizeClass: WindowWidthSizeClass,
|
isTabletUi: Boolean,
|
||||||
appBarPadding: Dp,
|
appBarPadding: Dp,
|
||||||
title: String,
|
title: String,
|
||||||
author: String?,
|
author: String?,
|
||||||
@ -123,7 +122,7 @@ fun MangaInfoBox(
|
|||||||
|
|
||||||
// Manga & source info
|
// Manga & source info
|
||||||
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) {
|
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) {
|
||||||
if (windowWidthSizeClass == WindowWidthSizeClass.Compact) {
|
if (!isTabletUi) {
|
||||||
MangaAndSourceTitlesSmall(
|
MangaAndSourceTitlesSmall(
|
||||||
appBarPadding = appBarPadding,
|
appBarPadding = appBarPadding,
|
||||||
coverDataProvider = coverDataProvider,
|
coverDataProvider = coverDataProvider,
|
||||||
|
@ -27,8 +27,6 @@ import cafe.adriel.voyager.navigator.currentOrThrow
|
|||||||
import eu.kanade.domain.base.BasePreferences
|
import eu.kanade.domain.base.BasePreferences
|
||||||
import eu.kanade.domain.library.service.LibraryPreferences
|
import eu.kanade.domain.library.service.LibraryPreferences
|
||||||
import eu.kanade.domain.manga.repository.MangaRepository
|
import eu.kanade.domain.manga.repository.MangaRepository
|
||||||
import eu.kanade.domain.ui.UiPreferences
|
|
||||||
import eu.kanade.domain.ui.model.TabletUiMode
|
|
||||||
import eu.kanade.presentation.more.settings.Preference
|
import eu.kanade.presentation.more.settings.Preference
|
||||||
import eu.kanade.presentation.util.collectAsState
|
import eu.kanade.presentation.util.collectAsState
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
@ -110,7 +108,6 @@ class SettingsAdvancedScreen : SearchableSettings {
|
|||||||
getNetworkGroup(networkPreferences = networkPreferences),
|
getNetworkGroup(networkPreferences = networkPreferences),
|
||||||
getLibraryGroup(),
|
getLibraryGroup(),
|
||||||
getExtensionsGroup(basePreferences = basePreferences),
|
getExtensionsGroup(basePreferences = basePreferences),
|
||||||
getDisplayGroup(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,24 +387,4 @@ class SettingsAdvancedScreen : SearchableSettings {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun getDisplayGroup(): Preference.PreferenceGroup {
|
|
||||||
val context = LocalContext.current
|
|
||||||
val uiPreferences = remember { Injekt.get<UiPreferences>() }
|
|
||||||
return Preference.PreferenceGroup(
|
|
||||||
title = stringResource(R.string.pref_category_display),
|
|
||||||
preferenceItems = listOf(
|
|
||||||
Preference.PreferenceItem.ListPreference(
|
|
||||||
pref = uiPreferences.tabletUiMode(),
|
|
||||||
title = stringResource(R.string.pref_tablet_ui_mode),
|
|
||||||
entries = TabletUiMode.values().associateWith { stringResource(it.titleResId) },
|
|
||||||
onValueChanged = {
|
|
||||||
context.toast(R.string.requires_app_restart)
|
|
||||||
true
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -13,12 +13,14 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import eu.kanade.domain.ui.UiPreferences
|
import eu.kanade.domain.ui.UiPreferences
|
||||||
|
import eu.kanade.domain.ui.model.TabletUiMode
|
||||||
import eu.kanade.domain.ui.model.ThemeMode
|
import eu.kanade.domain.ui.model.ThemeMode
|
||||||
import eu.kanade.domain.ui.model.setAppCompatDelegateThemeMode
|
import eu.kanade.domain.ui.model.setAppCompatDelegateThemeMode
|
||||||
import eu.kanade.presentation.more.settings.Preference
|
import eu.kanade.presentation.more.settings.Preference
|
||||||
import eu.kanade.presentation.util.collectAsState
|
import eu.kanade.presentation.util.collectAsState
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.util.system.isTablet
|
import eu.kanade.tachiyomi.util.system.isAutoTabletUiAvailable
|
||||||
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.flow.drop
|
import kotlinx.coroutines.flow.drop
|
||||||
import kotlinx.coroutines.flow.merge
|
import kotlinx.coroutines.flow.merge
|
||||||
@ -40,7 +42,7 @@ class SettingsAppearanceScreen : SearchableSettings {
|
|||||||
|
|
||||||
return listOf(
|
return listOf(
|
||||||
getThemeGroup(context = context, uiPreferences = uiPreferences),
|
getThemeGroup(context = context, uiPreferences = uiPreferences),
|
||||||
getNavigationGroup(context = context, uiPreferences = uiPreferences),
|
getDisplayGroup(context = context, uiPreferences = uiPreferences),
|
||||||
getTimestampGroup(uiPreferences = uiPreferences),
|
getTimestampGroup(uiPreferences = uiPreferences),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -99,18 +101,38 @@ class SettingsAppearanceScreen : SearchableSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun getNavigationGroup(
|
private fun getDisplayGroup(
|
||||||
context: Context,
|
context: Context,
|
||||||
uiPreferences: UiPreferences,
|
uiPreferences: UiPreferences,
|
||||||
): Preference.PreferenceGroup {
|
): Preference.PreferenceGroup {
|
||||||
|
val tabletUiModePref = uiPreferences.tabletUiMode()
|
||||||
|
val tabletUiMode by tabletUiModePref.collectAsState()
|
||||||
|
|
||||||
|
val isTabletUiAvailable = remember(tabletUiMode) { // won't survive config change
|
||||||
|
when (tabletUiMode) {
|
||||||
|
TabletUiMode.AUTOMATIC -> context.resources.configuration.isAutoTabletUiAvailable()
|
||||||
|
TabletUiMode.NEVER -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Preference.PreferenceGroup(
|
return Preference.PreferenceGroup(
|
||||||
title = stringResource(R.string.pref_category_navigation),
|
title = stringResource(R.string.pref_category_display),
|
||||||
enabled = remember(context) { context.isTablet() },
|
|
||||||
preferenceItems = listOf(
|
preferenceItems = listOf(
|
||||||
|
Preference.PreferenceItem.ListPreference(
|
||||||
|
pref = tabletUiModePref,
|
||||||
|
title = stringResource(R.string.pref_tablet_ui_mode),
|
||||||
|
entries = TabletUiMode.values().associateWith { stringResource(it.titleResId) },
|
||||||
|
onValueChanged = {
|
||||||
|
context.toast(R.string.requires_app_restart)
|
||||||
|
true
|
||||||
|
},
|
||||||
|
),
|
||||||
Preference.PreferenceItem.ListPreference(
|
Preference.PreferenceItem.ListPreference(
|
||||||
pref = uiPreferences.sideNavIconAlignment(),
|
pref = uiPreferences.sideNavIconAlignment(),
|
||||||
title = stringResource(R.string.pref_side_nav_icon_alignment),
|
title = stringResource(R.string.pref_side_nav_icon_alignment),
|
||||||
subtitle = "%s",
|
subtitle = "%s",
|
||||||
|
enabled = isTabletUiAvailable,
|
||||||
entries = mapOf(
|
entries = mapOf(
|
||||||
0 to stringResource(R.string.alignment_top),
|
0 to stringResource(R.string.alignment_top),
|
||||||
1 to stringResource(R.string.alignment_center),
|
1 to stringResource(R.string.alignment_center),
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
package eu.kanade.presentation.util
|
|
||||||
|
|
||||||
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.ReadOnlyComposable
|
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
|
||||||
import androidx.compose.ui.unit.Dp
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
@ReadOnlyComposable
|
|
||||||
fun calculateWindowWidthSizeClass(): WindowWidthSizeClass {
|
|
||||||
val configuration = LocalConfiguration.current
|
|
||||||
return fromWidth(configuration.smallestScreenWidthDp.dp)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fromWidth(width: Dp): WindowWidthSizeClass {
|
|
||||||
require(width >= 0.dp) { "Width must not be negative" }
|
|
||||||
return when {
|
|
||||||
width < 720.dp -> WindowWidthSizeClass.Compact // Was 600
|
|
||||||
width < 840.dp -> WindowWidthSizeClass.Medium
|
|
||||||
else -> WindowWidthSizeClass.Expanded
|
|
||||||
}
|
|
||||||
}
|
|
@ -65,7 +65,7 @@ import eu.kanade.tachiyomi.util.lang.launchUI
|
|||||||
import eu.kanade.tachiyomi.util.preference.asHotFlow
|
import eu.kanade.tachiyomi.util.preference.asHotFlow
|
||||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||||
import eu.kanade.tachiyomi.util.system.getThemeColor
|
import eu.kanade.tachiyomi.util.system.getThemeColor
|
||||||
import eu.kanade.tachiyomi.util.system.isTablet
|
import eu.kanade.tachiyomi.util.system.isTabletUi
|
||||||
import eu.kanade.tachiyomi.util.system.logcat
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat
|
import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat
|
||||||
@ -610,7 +610,7 @@ class MainActivity : BaseActivity() {
|
|||||||
binding.appbar.isVisible = !isComposeController
|
binding.appbar.isVisible = !isComposeController
|
||||||
binding.controllerContainer.enableScrollingBehavior(!isComposeController)
|
binding.controllerContainer.enableScrollingBehavior(!isComposeController)
|
||||||
|
|
||||||
if (!isTablet()) {
|
if (!isTabletUi()) {
|
||||||
// Save lift state
|
// Save lift state
|
||||||
if (isPush) {
|
if (isPush) {
|
||||||
if (router.backstackSize > 1) {
|
if (router.backstackSize > 1) {
|
||||||
|
@ -13,6 +13,7 @@ import androidx.compose.runtime.collectAsState
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||||
import com.bluelinelabs.conductor.ControllerChangeType
|
import com.bluelinelabs.conductor.ControllerChangeType
|
||||||
@ -25,7 +26,6 @@ import eu.kanade.presentation.manga.DownloadAction
|
|||||||
import eu.kanade.presentation.manga.MangaScreen
|
import eu.kanade.presentation.manga.MangaScreen
|
||||||
import eu.kanade.presentation.manga.components.DeleteChaptersDialog
|
import eu.kanade.presentation.manga.components.DeleteChaptersDialog
|
||||||
import eu.kanade.presentation.manga.components.DownloadCustomAmountDialog
|
import eu.kanade.presentation.manga.components.DownloadCustomAmountDialog
|
||||||
import eu.kanade.presentation.util.calculateWindowWidthSizeClass
|
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadService
|
import eu.kanade.tachiyomi.data.download.DownloadService
|
||||||
import eu.kanade.tachiyomi.data.download.model.Download
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
@ -52,6 +52,7 @@ import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
|||||||
import eu.kanade.tachiyomi.ui.recent.history.HistoryController
|
import eu.kanade.tachiyomi.ui.recent.history.HistoryController
|
||||||
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
|
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
|
||||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||||
|
import eu.kanade.tachiyomi.util.system.isTabletUi
|
||||||
import eu.kanade.tachiyomi.util.system.logcat
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -112,10 +113,13 @@ class MangaController : FullComposeController<MangaPresenter> {
|
|||||||
val isHttpSource = remember { successState.source is HttpSource }
|
val isHttpSource = remember { successState.source is HttpSource }
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
val configuration = LocalConfiguration.current
|
||||||
|
val isTabletUi = remember { configuration.isTabletUi() } // won't survive config change
|
||||||
|
|
||||||
MangaScreen(
|
MangaScreen(
|
||||||
state = successState,
|
state = successState,
|
||||||
snackbarHostState = snackbarHostState,
|
snackbarHostState = snackbarHostState,
|
||||||
windowWidthSizeClass = calculateWindowWidthSizeClass(),
|
isTabletUi = isTabletUi,
|
||||||
onBackClicked = router::popCurrentController,
|
onBackClicked = router::popCurrentController,
|
||||||
onChapterClicked = this::openChapter,
|
onChapterClicked = this::openChapter,
|
||||||
onDownloadChapter = this::onDownloadChapters.takeIf { !successState.source.isLocalOrStub() },
|
onDownloadChapter = this::onDownloadChapters.takeIf { !successState.source.isLocalOrStub() },
|
||||||
|
@ -6,9 +6,10 @@ import androidx.compose.animation.core.LinearEasing
|
|||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
import androidx.compose.animation.with
|
import androidx.compose.animation.with
|
||||||
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import cafe.adriel.voyager.navigator.Navigator
|
import cafe.adriel.voyager.navigator.Navigator
|
||||||
import cafe.adriel.voyager.transitions.ScreenTransition
|
import cafe.adriel.voyager.transitions.ScreenTransition
|
||||||
@ -19,8 +20,8 @@ import eu.kanade.presentation.more.settings.screen.SettingsGeneralScreen
|
|||||||
import eu.kanade.presentation.more.settings.screen.SettingsMainScreen
|
import eu.kanade.presentation.more.settings.screen.SettingsMainScreen
|
||||||
import eu.kanade.presentation.util.LocalBackPress
|
import eu.kanade.presentation.util.LocalBackPress
|
||||||
import eu.kanade.presentation.util.LocalRouter
|
import eu.kanade.presentation.util.LocalRouter
|
||||||
import eu.kanade.presentation.util.calculateWindowWidthSizeClass
|
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.BasicFullComposeController
|
import eu.kanade.tachiyomi.ui.base.controller.BasicFullComposeController
|
||||||
|
import eu.kanade.tachiyomi.util.system.isTabletUi
|
||||||
|
|
||||||
class SettingsMainController(bundle: Bundle = bundleOf()) : BasicFullComposeController(bundle) {
|
class SettingsMainController(bundle: Bundle = bundleOf()) : BasicFullComposeController(bundle) {
|
||||||
|
|
||||||
@ -39,8 +40,9 @@ class SettingsMainController(bundle: Bundle = bundleOf()) : BasicFullComposeCont
|
|||||||
@Composable
|
@Composable
|
||||||
override fun ComposeContent() {
|
override fun ComposeContent() {
|
||||||
CompositionLocalProvider(LocalRouter provides router) {
|
CompositionLocalProvider(LocalRouter provides router) {
|
||||||
val widthSizeClass = calculateWindowWidthSizeClass()
|
val configuration = LocalConfiguration.current
|
||||||
if (widthSizeClass == WindowWidthSizeClass.Compact) {
|
val isTabletUi = remember { configuration.isTabletUi() } // won't survive config change
|
||||||
|
if (!isTabletUi) {
|
||||||
Navigator(
|
Navigator(
|
||||||
screen = if (toBackupScreen) {
|
screen = if (toBackupScreen) {
|
||||||
SettingsBackupScreen()
|
SettingsBackupScreen()
|
||||||
|
@ -50,8 +50,6 @@ import java.io.File
|
|||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
private const val TABLET_UI_MIN_SCREEN_WIDTH_DP = 720
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies a string to clipboard
|
* Copies a string to clipboard
|
||||||
*
|
*
|
||||||
@ -263,28 +261,46 @@ fun Context.createFileInCacheDir(name: String): File {
|
|||||||
return file
|
return file
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private const val TABLET_UI_REQUIRED_SCREEN_WIDTH_DP = 720
|
||||||
* We consider anything with a width of >= 720dp as a tablet, i.e. with layouts in layout-sw720dp.
|
|
||||||
*/
|
// some tablets have screen width like 711dp = 1600px / 2.25
|
||||||
fun Context.isTablet(): Boolean {
|
private const val TABLET_UI_MIN_SCREEN_WIDTH_PORTRAIT_DP = 700
|
||||||
return resources.configuration.smallestScreenWidthDp >= TABLET_UI_MIN_SCREEN_WIDTH_DP
|
|
||||||
|
// make sure icons on the nav rail fit
|
||||||
|
private const val TABLET_UI_MIN_SCREEN_WIDTH_LANDSCAPE_DP = 600
|
||||||
|
|
||||||
|
fun Context.isTabletUi(): Boolean {
|
||||||
|
return resources.configuration.isTabletUi()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Configuration.isTabletUi(): Boolean {
|
||||||
|
return smallestScreenWidthDp >= TABLET_UI_REQUIRED_SCREEN_WIDTH_DP
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Configuration.isAutoTabletUiAvailable(): Boolean {
|
||||||
|
return smallestScreenWidthDp >= TABLET_UI_MIN_SCREEN_WIDTH_LANDSCAPE_DP
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: move the logic to `isTabletUi()` when main activity is rewritten in Compose
|
||||||
fun Context.prepareTabletUiContext(): Context {
|
fun Context.prepareTabletUiContext(): Context {
|
||||||
val configuration = resources.configuration
|
val configuration = resources.configuration
|
||||||
val expected = when (Injekt.get<UiPreferences>().tabletUiMode().get()) {
|
val expected = when (Injekt.get<UiPreferences>().tabletUiMode().get()) {
|
||||||
TabletUiMode.AUTOMATIC -> isTablet()
|
TabletUiMode.AUTOMATIC ->
|
||||||
|
configuration.smallestScreenWidthDp >= when (configuration.orientation) {
|
||||||
|
Configuration.ORIENTATION_PORTRAIT -> TABLET_UI_MIN_SCREEN_WIDTH_PORTRAIT_DP
|
||||||
|
else -> TABLET_UI_MIN_SCREEN_WIDTH_LANDSCAPE_DP
|
||||||
|
}
|
||||||
TabletUiMode.ALWAYS -> true
|
TabletUiMode.ALWAYS -> true
|
||||||
TabletUiMode.LANDSCAPE -> configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
TabletUiMode.LANDSCAPE -> configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
TabletUiMode.NEVER -> false
|
TabletUiMode.NEVER -> false
|
||||||
}
|
}
|
||||||
if (configuration.smallestScreenWidthDp >= TABLET_UI_MIN_SCREEN_WIDTH_DP != expected) {
|
if (configuration.isTabletUi() != expected) {
|
||||||
val overrideConf = Configuration()
|
val overrideConf = Configuration()
|
||||||
overrideConf.setTo(configuration)
|
overrideConf.setTo(configuration)
|
||||||
overrideConf.smallestScreenWidthDp = if (expected) {
|
overrideConf.smallestScreenWidthDp = if (expected) {
|
||||||
overrideConf.smallestScreenWidthDp.coerceAtLeast(TABLET_UI_MIN_SCREEN_WIDTH_DP)
|
overrideConf.smallestScreenWidthDp.coerceAtLeast(TABLET_UI_REQUIRED_SCREEN_WIDTH_DP)
|
||||||
} else {
|
} else {
|
||||||
overrideConf.smallestScreenWidthDp.coerceAtMost(TABLET_UI_MIN_SCREEN_WIDTH_DP - 1)
|
overrideConf.smallestScreenWidthDp.coerceAtMost(TABLET_UI_REQUIRED_SCREEN_WIDTH_DP - 1)
|
||||||
}
|
}
|
||||||
return createConfigurationContext(overrideConf)
|
return createConfigurationContext(overrideConf)
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import androidx.core.view.isVisible
|
|||||||
import androidx.customview.view.AbsSavedState
|
import androidx.customview.view.AbsSavedState
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
import eu.kanade.tachiyomi.util.system.isTablet
|
import eu.kanade.tachiyomi.util.system.isTabletUi
|
||||||
import eu.kanade.tachiyomi.util.view.findChild
|
import eu.kanade.tachiyomi.util.view.findChild
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,7 +48,7 @@ class TachiyomiCoordinatorLayout @JvmOverloads constructor(
|
|||||||
) {
|
) {
|
||||||
super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type, consumed)
|
super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type, consumed)
|
||||||
// Disable elevation overlay when tabs are visible
|
// Disable elevation overlay when tabs are visible
|
||||||
if (context.isTablet().not()) {
|
if (context.isTabletUi().not()) {
|
||||||
if (target is ComposeView) {
|
if (target is ComposeView) {
|
||||||
val scrollCondition = if (type == ViewCompat.TYPE_NON_TOUCH) {
|
val scrollCondition = if (type == ViewCompat.TYPE_NON_TOUCH) {
|
||||||
dyUnconsumed >= 0
|
dyUnconsumed >= 0
|
||||||
|
@ -13,7 +13,6 @@ ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose
|
|||||||
ui-util = { module = "androidx.compose.ui:ui-util", version.ref = "compose" }
|
ui-util = { module = "androidx.compose.ui:ui-util", version.ref = "compose" }
|
||||||
|
|
||||||
material3-core = { module = "androidx.compose.material3:material3", version.ref = "material3" }
|
material3-core = { module = "androidx.compose.material3:material3", version.ref = "material3" }
|
||||||
material3-windowsizeclass = { module = "androidx.compose.material3:material3-window-size-class", version.ref = "material3" }
|
|
||||||
material3-adapter = "com.google.android.material:compose-theme-adapter-3:1.0.20"
|
material3-adapter = "com.google.android.material:compose-theme-adapter-3:1.0.20"
|
||||||
material-icons = { module = "androidx.compose.material:material-icons-extended", version.ref = "compose" }
|
material-icons = { module = "androidx.compose.material:material-icons-extended", version.ref = "compose" }
|
||||||
|
|
||||||
|
@ -187,7 +187,6 @@
|
|||||||
<string name="theme_yotsuba">Yotsuba</string>
|
<string name="theme_yotsuba">Yotsuba</string>
|
||||||
<string name="theme_tidalwave">Tidal Wave</string>
|
<string name="theme_tidalwave">Tidal Wave</string>
|
||||||
<string name="pref_dark_theme_pure_black">Pure black dark mode</string>
|
<string name="pref_dark_theme_pure_black">Pure black dark mode</string>
|
||||||
<string name="pref_category_navigation">Navigation</string>
|
|
||||||
<string name="pref_side_nav_icon_alignment">Side navigation icon alignment</string>
|
<string name="pref_side_nav_icon_alignment">Side navigation icon alignment</string>
|
||||||
<string name="alignment_top">Top</string>
|
<string name="alignment_top">Top</string>
|
||||||
<string name="alignment_center">Center</string>
|
<string name="alignment_center">Center</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user