Migrate More screen to full Compose
Cette révision appartient à :
Parent
e2510c144a
révision
4d9d587366
6 fichiers modifiés avec 105 ajouts et 122 suppressions
|
@ -3,6 +3,7 @@ package eu.kanade.presentation.more
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.asPaddingValues
|
import androidx.compose.foundation.layout.asPaddingValues
|
||||||
import androidx.compose.foundation.layout.navigationBars
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
|
import androidx.compose.foundation.layout.statusBarsPadding
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.CloudOff
|
import androidx.compose.material.icons.outlined.CloudOff
|
||||||
import androidx.compose.material.icons.outlined.GetApp
|
import androidx.compose.material.icons.outlined.GetApp
|
||||||
|
@ -16,15 +17,16 @@ import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
|
||||||
import androidx.compose.ui.platform.LocalUriHandler
|
import androidx.compose.ui.platform.LocalUriHandler
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import eu.kanade.presentation.components.AppBar
|
||||||
import eu.kanade.presentation.components.Divider
|
import eu.kanade.presentation.components.Divider
|
||||||
import eu.kanade.presentation.components.PreferenceRow
|
import eu.kanade.presentation.components.PreferenceRow
|
||||||
|
import eu.kanade.presentation.components.Scaffold
|
||||||
import eu.kanade.presentation.components.ScrollbarLazyColumn
|
import eu.kanade.presentation.components.ScrollbarLazyColumn
|
||||||
import eu.kanade.presentation.components.SwitchPreference
|
import eu.kanade.presentation.components.SwitchPreference
|
||||||
|
import eu.kanade.presentation.util.plus
|
||||||
import eu.kanade.presentation.util.quantityStringResource
|
import eu.kanade.presentation.util.quantityStringResource
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.ui.more.DownloadQueueState
|
import eu.kanade.tachiyomi.ui.more.DownloadQueueState
|
||||||
|
@ -33,7 +35,6 @@ import eu.kanade.tachiyomi.ui.more.MorePresenter
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MoreScreen(
|
fun MoreScreen(
|
||||||
nestedScrollInterop: NestedScrollConnection,
|
|
||||||
presenter: MorePresenter,
|
presenter: MorePresenter,
|
||||||
onClickDownloadQueue: () -> Unit,
|
onClickDownloadQueue: () -> Unit,
|
||||||
onClickCategories: () -> Unit,
|
onClickCategories: () -> Unit,
|
||||||
|
@ -44,92 +45,108 @@ fun MoreScreen(
|
||||||
val uriHandler = LocalUriHandler.current
|
val uriHandler = LocalUriHandler.current
|
||||||
val downloadQueueState by presenter.downloadQueueState.collectAsState()
|
val downloadQueueState by presenter.downloadQueueState.collectAsState()
|
||||||
|
|
||||||
ScrollbarLazyColumn(
|
Scaffold(
|
||||||
modifier = Modifier.nestedScroll(nestedScrollInterop),
|
modifier = Modifier.statusBarsPadding(),
|
||||||
contentPadding = WindowInsets.navigationBars.asPaddingValues(),
|
topBar = {
|
||||||
) {
|
AppBar(
|
||||||
item {
|
title = stringResource(R.string.label_more),
|
||||||
LogoHeader()
|
downloadedOnlyMode = presenter.downloadedOnly.value,
|
||||||
}
|
incognitoMode = presenter.incognitoMode.value,
|
||||||
|
|
||||||
item {
|
|
||||||
SwitchPreference(
|
|
||||||
preference = presenter.downloadedOnly,
|
|
||||||
title = stringResource(R.string.label_downloaded_only),
|
|
||||||
subtitle = stringResource(R.string.downloaded_only_summary),
|
|
||||||
painter = rememberVectorPainter(Icons.Outlined.CloudOff),
|
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
item {
|
) { paddingValues ->
|
||||||
SwitchPreference(
|
ScrollbarLazyColumn(
|
||||||
preference = presenter.incognitoMode,
|
contentPadding = paddingValues + WindowInsets.navigationBars.asPaddingValues(),
|
||||||
title = stringResource(R.string.pref_incognito_mode),
|
) {
|
||||||
subtitle = stringResource(R.string.pref_incognito_mode_summary),
|
item {
|
||||||
painter = painterResource(R.drawable.ic_glasses_24dp),
|
LogoHeader()
|
||||||
)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
item { Divider() }
|
item {
|
||||||
|
SwitchPreference(
|
||||||
|
preference = presenter.downloadedOnly,
|
||||||
|
title = stringResource(R.string.label_downloaded_only),
|
||||||
|
subtitle = stringResource(R.string.downloaded_only_summary),
|
||||||
|
painter = rememberVectorPainter(Icons.Outlined.CloudOff),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
item {
|
||||||
|
SwitchPreference(
|
||||||
|
preference = presenter.incognitoMode,
|
||||||
|
title = stringResource(R.string.pref_incognito_mode),
|
||||||
|
subtitle = stringResource(R.string.pref_incognito_mode_summary),
|
||||||
|
painter = painterResource(R.drawable.ic_glasses_24dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
item {
|
item { Divider() }
|
||||||
PreferenceRow(
|
|
||||||
title = stringResource(R.string.label_download_queue),
|
item {
|
||||||
subtitle = when (downloadQueueState) {
|
PreferenceRow(
|
||||||
DownloadQueueState.Stopped -> null
|
title = stringResource(R.string.label_download_queue),
|
||||||
is DownloadQueueState.Paused -> {
|
subtitle = when (downloadQueueState) {
|
||||||
val pending = (downloadQueueState as DownloadQueueState.Paused).pending
|
DownloadQueueState.Stopped -> null
|
||||||
if (pending == 0) {
|
is DownloadQueueState.Paused -> {
|
||||||
stringResource(R.string.paused)
|
val pending = (downloadQueueState as DownloadQueueState.Paused).pending
|
||||||
} else {
|
if (pending == 0) {
|
||||||
"${stringResource(R.string.paused)} • ${quantityStringResource(R.plurals.download_queue_summary, pending, pending)}"
|
stringResource(R.string.paused)
|
||||||
|
} else {
|
||||||
|
"${stringResource(R.string.paused)} • ${
|
||||||
|
quantityStringResource(
|
||||||
|
R.plurals.download_queue_summary,
|
||||||
|
pending,
|
||||||
|
pending,
|
||||||
|
)
|
||||||
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
is DownloadQueueState.Downloading -> {
|
||||||
is DownloadQueueState.Downloading -> {
|
val pending = (downloadQueueState as DownloadQueueState.Downloading).pending
|
||||||
val pending = (downloadQueueState as DownloadQueueState.Downloading).pending
|
quantityStringResource(R.plurals.download_queue_summary, pending, pending)
|
||||||
quantityStringResource(R.plurals.download_queue_summary, pending, pending)
|
}
|
||||||
}
|
},
|
||||||
},
|
painter = rememberVectorPainter(Icons.Outlined.GetApp),
|
||||||
painter = rememberVectorPainter(Icons.Outlined.GetApp),
|
onClick = onClickDownloadQueue,
|
||||||
onClick = onClickDownloadQueue,
|
)
|
||||||
)
|
}
|
||||||
}
|
item {
|
||||||
item {
|
PreferenceRow(
|
||||||
PreferenceRow(
|
title = stringResource(R.string.categories),
|
||||||
title = stringResource(R.string.categories),
|
painter = rememberVectorPainter(Icons.Outlined.Label),
|
||||||
painter = rememberVectorPainter(Icons.Outlined.Label),
|
onClick = onClickCategories,
|
||||||
onClick = onClickCategories,
|
)
|
||||||
)
|
}
|
||||||
}
|
item {
|
||||||
item {
|
PreferenceRow(
|
||||||
PreferenceRow(
|
title = stringResource(R.string.label_backup),
|
||||||
title = stringResource(R.string.label_backup),
|
painter = rememberVectorPainter(Icons.Outlined.SettingsBackupRestore),
|
||||||
painter = rememberVectorPainter(Icons.Outlined.SettingsBackupRestore),
|
onClick = onClickBackupAndRestore,
|
||||||
onClick = onClickBackupAndRestore,
|
)
|
||||||
)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
item { Divider() }
|
item { Divider() }
|
||||||
|
|
||||||
item {
|
item {
|
||||||
PreferenceRow(
|
PreferenceRow(
|
||||||
title = stringResource(R.string.label_settings),
|
title = stringResource(R.string.label_settings),
|
||||||
painter = rememberVectorPainter(Icons.Outlined.Settings),
|
painter = rememberVectorPainter(Icons.Outlined.Settings),
|
||||||
onClick = onClickSettings,
|
onClick = onClickSettings,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
PreferenceRow(
|
PreferenceRow(
|
||||||
title = stringResource(R.string.pref_category_about),
|
title = stringResource(R.string.pref_category_about),
|
||||||
painter = rememberVectorPainter(Icons.Outlined.Info),
|
painter = rememberVectorPainter(Icons.Outlined.Info),
|
||||||
onClick = onClickAbout,
|
onClick = onClickAbout,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
PreferenceRow(
|
PreferenceRow(
|
||||||
title = stringResource(R.string.label_help),
|
title = stringResource(R.string.label_help),
|
||||||
painter = rememberVectorPainter(Icons.Outlined.HelpOutline),
|
painter = rememberVectorPainter(Icons.Outlined.HelpOutline),
|
||||||
onClick = { uriHandler.openUri(MoreController.URL_HELP) },
|
onClick = { uriHandler.openUri(MoreController.URL_HELP) },
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import androidx.core.net.toUri
|
||||||
import com.bluelinelabs.conductor.Controller
|
import com.bluelinelabs.conductor.Controller
|
||||||
import com.bluelinelabs.conductor.Router
|
import com.bluelinelabs.conductor.Router
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
import com.bluelinelabs.conductor.RouterTransaction
|
||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
|
||||||
import eu.kanade.tachiyomi.util.system.openInBrowser
|
import eu.kanade.tachiyomi.util.system.openInBrowser
|
||||||
|
|
||||||
fun Router.setRoot(controller: Controller, id: Int) {
|
fun Router.setRoot(controller: Controller, id: Int) {
|
||||||
|
@ -44,10 +43,3 @@ fun Controller.withFadeTransaction(): RouterTransaction {
|
||||||
fun Controller.openInBrowser(url: String) {
|
fun Controller.openInBrowser(url: String) {
|
||||||
activity?.openInBrowser(url.toUri())
|
activity?.openInBrowser(url.toUri())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns [MainActivity]'s app bar height
|
|
||||||
*/
|
|
||||||
fun Controller.getMainAppBarHeight(): Int {
|
|
||||||
return (activity as? MainActivity)?.binding?.appbar?.measuredHeight ?: 0
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.ui.base.controller
|
|
||||||
|
|
||||||
interface NoAppBarElevationController
|
|
|
@ -44,7 +44,6 @@ import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.FabController
|
import eu.kanade.tachiyomi.ui.base.controller.FabController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.FullComposeContentController
|
import eu.kanade.tachiyomi.ui.base.controller.FullComposeContentController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.NoAppBarElevationController
|
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.RootController
|
import eu.kanade.tachiyomi.ui.base.controller.RootController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.TabbedController
|
import eu.kanade.tachiyomi.ui.base.controller.TabbedController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||||
|
@ -639,8 +638,6 @@ class MainActivity : BaseActivity() {
|
||||||
backstackLiftState.remove(it.instanceId)
|
backstackLiftState.remove(it.instanceId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.root.isLiftAppBarOnScroll = internalTo !is NoAppBarElevationController
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
package eu.kanade.tachiyomi.ui.more
|
package eu.kanade.tachiyomi.ui.more
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
|
||||||
import eu.kanade.presentation.more.MoreScreen
|
import eu.kanade.presentation.more.MoreScreen
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.ComposeController
|
import eu.kanade.tachiyomi.ui.base.controller.FullComposeController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.NoAppBarElevationController
|
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.RootController
|
import eu.kanade.tachiyomi.ui.base.controller.RootController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||||
import eu.kanade.tachiyomi.ui.category.CategoryController
|
import eu.kanade.tachiyomi.ui.category.CategoryController
|
||||||
|
@ -14,18 +12,16 @@ import eu.kanade.tachiyomi.ui.setting.SettingsBackupController
|
||||||
import eu.kanade.tachiyomi.ui.setting.SettingsMainController
|
import eu.kanade.tachiyomi.ui.setting.SettingsMainController
|
||||||
|
|
||||||
class MoreController :
|
class MoreController :
|
||||||
ComposeController<MorePresenter>(),
|
FullComposeController<MorePresenter>(),
|
||||||
RootController,
|
RootController {
|
||||||
NoAppBarElevationController {
|
|
||||||
|
|
||||||
override fun getTitle() = resources?.getString(R.string.label_more)
|
override fun getTitle() = resources?.getString(R.string.label_more)
|
||||||
|
|
||||||
override fun createPresenter() = MorePresenter()
|
override fun createPresenter() = MorePresenter()
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun ComposeContent(nestedScrollInterop: NestedScrollConnection) {
|
override fun ComposeContent() {
|
||||||
MoreScreen(
|
MoreScreen(
|
||||||
nestedScrollInterop = nestedScrollInterop,
|
|
||||||
presenter = presenter,
|
presenter = presenter,
|
||||||
onClickDownloadQueue = { router.pushController(DownloadController()) },
|
onClickDownloadQueue = { router.pushController(DownloadController()) },
|
||||||
onClickCategories = { router.pushController(CategoryController()) },
|
onClickCategories = { router.pushController(CategoryController()) },
|
||||||
|
|
|
@ -34,25 +34,9 @@ class TachiyomiCoordinatorLayout @JvmOverloads constructor(
|
||||||
defStyleAttr: Int = R.attr.coordinatorLayoutStyle,
|
defStyleAttr: Int = R.attr.coordinatorLayoutStyle,
|
||||||
) : CoordinatorLayout(context, attrs, defStyleAttr) {
|
) : CoordinatorLayout(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
/**
|
|
||||||
* Keep lifted state and do nothing on tablet UI
|
|
||||||
*/
|
|
||||||
private val isTablet = context.isTablet()
|
|
||||||
|
|
||||||
private var appBarLayout: AppBarLayout? = null
|
private var appBarLayout: AppBarLayout? = null
|
||||||
private var tabLayout: TabLayout? = null
|
private var tabLayout: TabLayout? = null
|
||||||
|
|
||||||
/**
|
|
||||||
* If true, [AppBarLayout] child will be lifted on nested scroll.
|
|
||||||
*/
|
|
||||||
var isLiftAppBarOnScroll = true
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal check
|
|
||||||
*/
|
|
||||||
private val canLiftAppBarOnScroll
|
|
||||||
get() = !isTablet && isLiftAppBarOnScroll
|
|
||||||
|
|
||||||
override fun onNestedScroll(
|
override fun onNestedScroll(
|
||||||
target: View,
|
target: View,
|
||||||
dxConsumed: Int,
|
dxConsumed: Int,
|
||||||
|
@ -64,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 (canLiftAppBarOnScroll) {
|
if (context.isTablet().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
|
||||||
|
|
Référencer dans un nouveau ticket