From d655c3e09ae2c1dd1333dbe7e1f4e2f9abb3e48f Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Tue, 7 Jan 2025 07:36:00 +0700 Subject: [PATCH] chore: WIP compose library page --- .../base/controller/BaseComposeController.kt | 4 +- .../ui/base/controller/BaseController.kt | 6 ++ .../base/controller/BaseLegacyController.kt | 4 +- .../ui/library/LibraryComposeController.kt | 23 ++++++++ .../kanade/tachiyomi/ui/main/MainActivity.kt | 3 +- .../controllers/SettingsAdvancedController.kt | 4 ++ .../java/yokai/domain/base/BasePreferences.kt | 2 + .../main/java/yokai/presentation/Scaffold.kt | 3 + .../presentation/library/LibraryScreen.kt | 33 +++++++++++ .../library/components/CommonMangaItem.kt | 11 ++++ .../library/components/LazyLibraryGrid.kt | 28 +++++++++ .../moko-resources/base/strings.xml | 2 + .../presentation/core/components/LazyGrid.kt | 58 +++++++++++++++++++ .../presentation/core/util/PaddingValues.kt | 22 +++++++ 14 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryComposeController.kt create mode 100644 app/src/main/java/yokai/presentation/library/LibraryScreen.kt create mode 100644 app/src/main/java/yokai/presentation/library/components/CommonMangaItem.kt create mode 100644 app/src/main/java/yokai/presentation/library/components/LazyLibraryGrid.kt create mode 100644 presentation/core/src/main/java/yokai/presentation/core/components/LazyGrid.kt create mode 100644 presentation/core/src/main/java/yokai/presentation/core/util/PaddingValues.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseComposeController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseComposeController.kt index 7f2fed8f1f..4ecd065463 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseComposeController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseComposeController.kt @@ -17,12 +17,14 @@ import yokai.presentation.theme.YokaiTheme abstract class BaseComposeController(bundle: Bundle? = null) : BaseController(bundle) { + override val shouldHideLegacyAppBar = true + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup, savedViewState: Bundle? ): View { - hideLegacyAppBar() + setAppBarVisibility() return ComposeView(container.context).apply { layoutParams = ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseController.kt index f378bed539..b1fcea81e2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseController.kt @@ -25,6 +25,8 @@ import kotlinx.coroutines.cancel abstract class BaseController(bundle: Bundle? = null) : Controller(bundle), BackHandlerControllerInterface, BaseControllerPreferenceControllerCommonInterface { + abstract val shouldHideLegacyAppBar: Boolean + lateinit var viewScope: CoroutineScope var isDragging = false @@ -58,6 +60,10 @@ abstract class BaseController(bundle: Bundle? = null) : open fun onViewCreated(view: View) { } + internal fun setAppBarVisibility() { + if (shouldHideLegacyAppBar) hideLegacyAppBar() else showLegacyAppBar() + } + override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) { if (type.isEnter && !isControllerVisible) { view?.alpha = 0f diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseLegacyController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseLegacyController.kt index 996074df6f..e710deaf8d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseLegacyController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseLegacyController.kt @@ -20,11 +20,13 @@ import eu.kanade.tachiyomi.util.view.isControllerVisible abstract class BaseLegacyController(bundle: Bundle? = null) : BaseController(bundle) { + override val shouldHideLegacyAppBar = false + lateinit var binding: VB val isBindingInitialized get() = this::binding.isInitialized override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedViewState: Bundle?): View { - showLegacyAppBar() + setAppBarVisibility() binding = createBinding(inflater) binding.root.backgroundColor = binding.root.context.getResourceColor(R.attr.background) return binding.root diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryComposeController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryComposeController.kt new file mode 100644 index 0000000000..a67ecad114 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryComposeController.kt @@ -0,0 +1,23 @@ +package eu.kanade.tachiyomi.ui.library + +import android.os.Bundle +import androidx.compose.runtime.Composable +import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.ui.base.controller.BaseComposeController +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get +import yokai.domain.ui.UiPreferences +import yokai.presentation.library.LibraryScreen + +class LibraryComposeController( + bundle: Bundle? = null, + val uiPreferences: UiPreferences = Injekt.get(), + val preferences: PreferencesHelper = Injekt.get(), +) : BaseComposeController(bundle) { + override val shouldHideLegacyAppBar = false + + @Composable + override fun ScreenContent() { + LibraryScreen() + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index cc0ecb6cc5..bed1662cda 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -85,6 +85,7 @@ import eu.kanade.tachiyomi.ui.base.SmallToolbarInterface import eu.kanade.tachiyomi.ui.base.activity.BaseActivity import eu.kanade.tachiyomi.ui.base.controller.BaseLegacyController import eu.kanade.tachiyomi.ui.base.controller.DialogController +import eu.kanade.tachiyomi.ui.library.LibraryComposeController import eu.kanade.tachiyomi.ui.library.LibraryController import eu.kanade.tachiyomi.ui.manga.MangaDetailsController import eu.kanade.tachiyomi.ui.more.AboutController @@ -538,7 +539,7 @@ open class MainActivity : BaseActivity() { if (currentRoot?.tag()?.toIntOrNull() != id) { setRoot( when (id) { - R.id.nav_library -> LibraryController() + R.id.nav_library -> if (basePreferences.composeLibrary().get()) LibraryComposeController() else LibraryController() R.id.nav_recents -> RecentsController() else -> BrowseController() }, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/controllers/SettingsAdvancedController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/controllers/SettingsAdvancedController.kt index 6f01d01dc4..c1e7143314 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/controllers/SettingsAdvancedController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/controllers/SettingsAdvancedController.kt @@ -394,6 +394,10 @@ class SettingsAdvancedController : SettingsLegacyController() { onClick { LibraryUpdateJob.startNow(context, target = Target.TRACKING) } } + switchPreference { + bindTo(basePreferences.composeLibrary()) + title = context.getString(MR.strings.pref_use_compose_library).addBetaTag(context) + } } preferenceCategory { diff --git a/app/src/main/java/yokai/domain/base/BasePreferences.kt b/app/src/main/java/yokai/domain/base/BasePreferences.kt index 5e450ee513..ca8e21ded1 100644 --- a/app/src/main/java/yokai/domain/base/BasePreferences.kt +++ b/app/src/main/java/yokai/domain/base/BasePreferences.kt @@ -49,4 +49,6 @@ class BasePreferences(private val preferenceStore: PreferenceStore) { } fun hardwareBitmapThreshold() = preferenceStore.getInt("pref_hardware_bitmap_threshold", GLUtil.SAFE_TEXTURE_LIMIT) + + fun composeLibrary() = preferenceStore.getBoolean("pref_use_compose_library", false) } diff --git a/app/src/main/java/yokai/presentation/Scaffold.kt b/app/src/main/java/yokai/presentation/Scaffold.kt index 7122df5f38..4c63800a1e 100644 --- a/app/src/main/java/yokai/presentation/Scaffold.kt +++ b/app/src/main/java/yokai/presentation/Scaffold.kt @@ -99,6 +99,7 @@ fun YokaiScaffold( scrollBehavior = scrollBehaviorOrDefault, actions = actions, ) + AppBarType.NONE -> {} } }, snackbarHost = snackbarHost, @@ -115,6 +116,8 @@ fun getTopAppBarColor(title: String): Pair { } enum class AppBarType { + // FIXME: Delete "NONE" later + NONE, SMALL, LARGE, } diff --git a/app/src/main/java/yokai/presentation/library/LibraryScreen.kt b/app/src/main/java/yokai/presentation/library/LibraryScreen.kt new file mode 100644 index 0000000000..4e1abf5fad --- /dev/null +++ b/app/src/main/java/yokai/presentation/library/LibraryScreen.kt @@ -0,0 +1,33 @@ +package yokai.presentation.library + +import androidx.compose.foundation.lazy.grid.items +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import yokai.presentation.AppBarType +import yokai.presentation.YokaiScaffold +import yokai.presentation.library.components.LazyLibraryGrid +import yokai.util.Screen + +class LibraryScreen : Screen() { + @Composable + override fun Content() { + val columns = 3 // FIXME: Retrieve from preferences + val items = (0..100).toList() + YokaiScaffold( + onNavigationIconClicked = {}, + appBarType = AppBarType.NONE, + ) { contentPadding -> + LazyLibraryGrid( + columns = columns, + contentPadding = contentPadding, + ) { + items( + items = items, + contentType = { "library_grid_item" } + ) { + Text("Hello world! ($it)") + } + } + } + } +} diff --git a/app/src/main/java/yokai/presentation/library/components/CommonMangaItem.kt b/app/src/main/java/yokai/presentation/library/components/CommonMangaItem.kt new file mode 100644 index 0000000000..cec16949c2 --- /dev/null +++ b/app/src/main/java/yokai/presentation/library/components/CommonMangaItem.kt @@ -0,0 +1,11 @@ +package yokai.presentation.library.components + +import androidx.compose.ui.unit.dp + +object CommonMangaItemDefaults { + val GridHorizontalSpacer = 4.dp + val GridVerticalSpacer = 4.dp + + @Suppress("ConstPropertyName") + const val BrowseFavoriteCoverAlpha = 0.34f +} diff --git a/app/src/main/java/yokai/presentation/library/components/LazyLibraryGrid.kt b/app/src/main/java/yokai/presentation/library/components/LazyLibraryGrid.kt new file mode 100644 index 0000000000..ae4541db99 --- /dev/null +++ b/app/src/main/java/yokai/presentation/library/components/LazyLibraryGrid.kt @@ -0,0 +1,28 @@ +package yokai.presentation.library.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyGridScope +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import yokai.presentation.core.components.FastScrollLazyVerticalGrid +import yokai.presentation.core.util.plus + +@Composable +internal fun LazyLibraryGrid( + modifier: Modifier = Modifier, + columns: Int, + contentPadding: PaddingValues, + content: LazyGridScope.() -> Unit, +) { + FastScrollLazyVerticalGrid( + columns = if (columns == 0) GridCells.Adaptive(128.dp) else GridCells.Fixed(columns), + modifier = modifier, + contentPadding = contentPadding + PaddingValues(8.dp), + verticalArrangement = Arrangement.spacedBy(CommonMangaItemDefaults.GridVerticalSpacer), + horizontalArrangement = Arrangement.spacedBy(CommonMangaItemDefaults.GridHorizontalSpacer), + content = content, + ) +} diff --git a/i18n/src/commonMain/moko-resources/base/strings.xml b/i18n/src/commonMain/moko-resources/base/strings.xml index 303e9324fa..7b5c85b035 100644 --- a/i18n/src/commonMain/moko-resources/base/strings.xml +++ b/i18n/src/commonMain/moko-resources/base/strings.xml @@ -166,6 +166,8 @@ Tracking status Ungrouped + Use experimental compose library + Sort by Total chapters diff --git a/presentation/core/src/main/java/yokai/presentation/core/components/LazyGrid.kt b/presentation/core/src/main/java/yokai/presentation/core/components/LazyGrid.kt new file mode 100644 index 0000000000..1532c990cc --- /dev/null +++ b/presentation/core/src/main/java/yokai/presentation/core/components/LazyGrid.kt @@ -0,0 +1,58 @@ +package yokai.presentation.core.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyGridScope +import androidx.compose.foundation.lazy.grid.LazyGridState +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.rememberLazyGridState +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +@Composable +fun FastScrollLazyVerticalGrid( + columns: GridCells, + modifier: Modifier = Modifier, + state: LazyGridState = rememberLazyGridState(), + thumbAllowed: () -> Boolean = { true }, + thumbColor: Color = MaterialTheme.colorScheme.primary, + contentPadding: PaddingValues = PaddingValues(0.dp), + topContentPadding: Dp = Dp.Hairline, + bottomContentPadding: Dp = Dp.Hairline, + endContentPadding: Dp = Dp.Hairline, + reverseLayout: Boolean = false, + verticalArrangement: Arrangement.Vertical = + if (!reverseLayout) Arrangement.Top else Arrangement.Bottom, + horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, + userScrollEnabled: Boolean = true, + content: LazyGridScope.() -> Unit, +) { + VerticalGridFastScroller( + state = state, + columns = columns, + arrangement = horizontalArrangement, + contentPadding = contentPadding, + modifier = modifier, + thumbAllowed = thumbAllowed, + thumbColor = thumbColor, + topContentPadding = topContentPadding, + bottomContentPadding = bottomContentPadding, + endContentPadding = endContentPadding, + ) { + LazyVerticalGrid( + columns = columns, + state = state, + contentPadding = contentPadding, + reverseLayout = reverseLayout, + verticalArrangement = verticalArrangement, + horizontalArrangement = horizontalArrangement, + userScrollEnabled = userScrollEnabled, + content = content, + ) + } +} diff --git a/presentation/core/src/main/java/yokai/presentation/core/util/PaddingValues.kt b/presentation/core/src/main/java/yokai/presentation/core/util/PaddingValues.kt new file mode 100644 index 0000000000..8422a88ec4 --- /dev/null +++ b/presentation/core/src/main/java/yokai/presentation/core/util/PaddingValues.kt @@ -0,0 +1,22 @@ +package yokai.presentation.core.util + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.calculateEndPadding +import androidx.compose.foundation.layout.calculateStartPadding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.ui.platform.LocalLayoutDirection + +@Composable +@ReadOnlyComposable +operator fun PaddingValues.plus(other: PaddingValues): PaddingValues { + val layoutDirection = LocalLayoutDirection.current + return PaddingValues( + start = calculateStartPadding(layoutDirection) + + other.calculateStartPadding(layoutDirection), + end = calculateEndPadding(layoutDirection) + + other.calculateEndPadding(layoutDirection), + top = calculateTopPadding() + other.calculateTopPadding(), + bottom = calculateBottomPadding() + other.calculateBottomPadding(), + ) +}