From b255023d07dacbd353defa7cad7e1be0cf57d727 Mon Sep 17 00:00:00 2001 From: Syer10 Date: Fri, 29 Jul 2022 09:56:42 -0400 Subject: [PATCH] Update to Mpp Compose 1.2.0 dev builds(with Android 1.2.0 release) --- .../ca/gosyer/jui/android/ReaderActivity.kt | 2 +- build.gradle.kts | 6 +- .../core/prefs/AndroidPreferenceAdapters.kt | 2 +- .../jui/core/prefs/JvmPreferenceAdapters.kt | 4 +- .../jui/desktop/logging/LoggingSetup.kt | 7 +- gradle/libs.versions.toml | 28 ++--- i18n/build.gradle.kts | 5 + .../jui/ui/base/prefs/ColorPickerDialog.kt | 10 +- .../components/MangaComfortableGrid.kt | 14 +-- .../ui/library/components/MangaCompactGrid.kt | 14 +-- .../library/components/MangaCoverOnlyGrid.kt | 14 +-- .../components/SourceMangaComfortableGrid.kt | 14 +-- .../components/SourceMangaCompactGrid.kt | 14 +-- .../components/SourceHomeScreenContent.kt | 91 +++++++--------- .../jui/uicore/components/AndroidScrollbar.kt | 62 +++++++++++ .../jui/uicore/components/DropDownMenu.kt | 3 +- .../gosyer/jui/uicore/components/Scrollbar.kt | 8 ++ .../jui/uicore/components/DesktopScrollbar.kt | 103 ++++++++++++++++++ 18 files changed, 281 insertions(+), 120 deletions(-) diff --git a/android/src/main/kotlin/ca/gosyer/jui/android/ReaderActivity.kt b/android/src/main/kotlin/ca/gosyer/jui/android/ReaderActivity.kt index 417791be..652a3913 100644 --- a/android/src/main/kotlin/ca/gosyer/jui/android/ReaderActivity.kt +++ b/android/src/main/kotlin/ca/gosyer/jui/android/ReaderActivity.kt @@ -53,7 +53,7 @@ class ReaderActivity : AppCompatActivity() { chapterIndex = chapterIndex, mangaId = mangaId, hotkeyFlow = hotkeyFlow, - onCloseRequest = ::onBackPressed + onCloseRequest = onBackPressedDispatcher::onBackPressed ) } } diff --git a/build.gradle.kts b/build.gradle.kts index 4ccf9537..4c1436de 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -48,9 +48,9 @@ tasks.withType { kotlinOptions { - freeCompilerArgs = freeCompilerArgs + listOf( + /*freeCompilerArgs = freeCompilerArgs + listOf( "-Xjvm-default=compatibility", - ) + )*/ } } tasks.withType { @@ -64,7 +64,7 @@ subprojects { plugins.withType { configure { // 32 requires a higher android plugin version - compileSdkVersion(31) + compileSdkVersion(33) defaultConfig { minSdk = 21 targetSdk = 31 diff --git a/core/src/androidMain/kotlin/ca/gosyer/jui/core/prefs/AndroidPreferenceAdapters.kt b/core/src/androidMain/kotlin/ca/gosyer/jui/core/prefs/AndroidPreferenceAdapters.kt index 731c6302..b338e4e2 100644 --- a/core/src/androidMain/kotlin/ca/gosyer/jui/core/prefs/AndroidPreferenceAdapters.kt +++ b/core/src/androidMain/kotlin/ca/gosyer/jui/core/prefs/AndroidPreferenceAdapters.kt @@ -96,7 +96,7 @@ internal class ObjectAdapter( ) : AndroidPreference.Adapter { override fun get(key: String, preferences: ObservableSettings): T { - return deserializer(preferences.getString(key)) // Not called unless key is present. + return deserializer(preferences.getString(key, "")) // Not called unless key is present. } override fun set(key: String, value: T, editor: ObservableSettings) { diff --git a/core/src/desktopMain/kotlin/ca/gosyer/jui/core/prefs/JvmPreferenceAdapters.kt b/core/src/desktopMain/kotlin/ca/gosyer/jui/core/prefs/JvmPreferenceAdapters.kt index 204abed5..f8236f88 100644 --- a/core/src/desktopMain/kotlin/ca/gosyer/jui/core/prefs/JvmPreferenceAdapters.kt +++ b/core/src/desktopMain/kotlin/ca/gosyer/jui/core/prefs/JvmPreferenceAdapters.kt @@ -17,7 +17,7 @@ import kotlinx.serialization.modules.SerializersModule internal object StringAdapter : JvmPreference.Adapter { override fun get(key: String, preferences: ObservableSettings): String { - return preferences.getString(key) // Not called unless key is present. + return preferences.getString(key, "") // Not called unless key is present. } override fun set(key: String, value: String, editor: ObservableSettings) { @@ -96,7 +96,7 @@ internal class ObjectAdapter( ) : JvmPreference.Adapter { override fun get(key: String, preferences: ObservableSettings): T { - return deserializer(preferences.getString(key)) // Not called unless key is present. + return deserializer(preferences.getString(key, "")) // Not called unless key is present. } override fun set(key: String, value: T, editor: ObservableSettings) { diff --git a/desktop/src/main/kotlin/ca/gosyer/jui/desktop/logging/LoggingSetup.kt b/desktop/src/main/kotlin/ca/gosyer/jui/desktop/logging/LoggingSetup.kt index 3d4be392..e3b256e8 100644 --- a/desktop/src/main/kotlin/ca/gosyer/jui/desktop/logging/LoggingSetup.kt +++ b/desktop/src/main/kotlin/ca/gosyer/jui/desktop/logging/LoggingSetup.kt @@ -13,7 +13,6 @@ import org.apache.logging.log4j.Level import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.core.LoggerContext import org.apache.logging.log4j.core.appender.ConsoleAppender -import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory import org.lighthousegames.logging.KmLogging import org.lighthousegames.logging.logging @@ -71,14 +70,14 @@ fun initializeLogger(loggingLocation: Path) { .addAttribute("pattern", filePattern) ) .addComponent( - newComponent>("Policies") + newComponent<_>("Policies") .addComponent( - newComponent>("CronTriggeringPolicy") + newComponent<_>("CronTriggeringPolicy") .addAttribute("schedule", "0 0 0 * * ?") .addAttribute("evaluateOnStartup", "true") ) .addComponent( - newComponent>("SizeBasedTriggeringPolicy") + newComponent<_>("SizeBasedTriggeringPolicy") .addAttribute("size", "100M") ) ) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b3558462..73a7b71a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,34 +1,34 @@ [versions] # Kotlin -kotlin = "1.6.10" -coroutines = "1.6.3" +kotlin = "1.7.0" +coroutines = "1.6.4" # Serialization json = "1.3.3" # Compose -composeGradle = "1.1.1" -composeAndroid = "1.1.1" +composeGradle = "1.2.0-alpha01-dev753" +composeAndroid = "1.2.0" voyager = "1.0.0-beta16" accompanist = "0.24.4" -kamel = "0.3.0" +kamel = "0.4.0" materialDialogs = "0.7.1" # Android -androidGradle = "7.0.4" +androidGradle = "7.3.0-beta05" core = "1.8.0" -appCompat = "1.6.0-alpha04" # alpha5+ requires android 32 +appCompat = "1.6.0-alpha05" activityCompose = "1.5.0" work = "2.7.1" # Android Lifecycle -lifecycle = "2.5.0" # 2.6.0 alpha+ requires android 32 +lifecycle = "2.6.0-alpha01" # Swing darklaf = "3.0.0" # Dependency Injection -ksp = "1.6.10-1.0.4" +ksp = "1.7.0-1.0.6" kotlinInject = "0.4.1" # Network @@ -41,27 +41,27 @@ log4j = "2.18.0" kmlogging = "1.2.0" # Storage -okio = "3.0.0" # 3.1.0+ requires Kotlin 1.6.21+ +okio = "3.2.0" appDirs = "1.2.1" # Preferences -multiplatformSettings = "0.8.1" # 0.9+ requires Kotlin 1.6.21+ +multiplatformSettings = "1.0.0-alpha01" # Utility kroki = "1.22" desugarJdkLibs = "1.1.6" # 1.2.0+ requires Android plugin 7.3 alpha aboutLibraries = "10.3.1" -dateTime = "0.3.2" +dateTime = "0.4.0" # Localization moko = "0.20.1" # BuildConfigs buildconfig = "3.0.3" -buildkonfig = "0.11.0" # 0.11.0+ requires Kotlin 1.7.0+ +buildkonfig = "0.12.0" # Linter -kotlinter = "3.9.0" # 3.10.0+ requires Kotlin 1.7.0+ +kotlinter = "3.11.1" # Version updates versions = "0.42.0" diff --git a/i18n/build.gradle.kts b/i18n/build.gradle.kts index be986735..8226d26a 100644 --- a/i18n/build.gradle.kts +++ b/i18n/build.gradle.kts @@ -49,4 +49,9 @@ android { lint { disable += "MissingTranslation" } + + sourceSets.getByName("main") { + assets.srcDir(File(buildDir, "generated/moko/androidMain/assets")) + res.srcDir(File(buildDir, "generated/moko/androidMain/res")) + } } \ No newline at end of file diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/prefs/ColorPickerDialog.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/prefs/ColorPickerDialog.kt index 62e5cb8a..27461c40 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/prefs/ColorPickerDialog.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/prefs/ColorPickerDialog.kt @@ -26,9 +26,9 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredHeight import androidx.compose.foundation.layout.requiredWidth import androidx.compose.foundation.layout.size -import androidx.compose.foundation.lazy.GridCells -import androidx.compose.foundation.lazy.LazyVerticalGrid -import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme @@ -139,7 +139,7 @@ private fun ColorPresets( val borderColor = MaterialTheme.colors.onBackground.copy(alpha = 0.54f) Column { - LazyVerticalGrid(cells = GridCells.Fixed(5)) { + LazyVerticalGrid(columns = GridCells.Fixed(5)) { items(presets) { color -> ColorPresetItem( color = color, @@ -158,7 +158,7 @@ private fun ColorPresets( .background(MaterialTheme.colors.onBackground.copy(alpha = 0.2f)) ) - LazyVerticalGrid(cells = GridCells.Fixed(5)) { + LazyVerticalGrid(columns = GridCells.Fixed(5)) { items(shades) { color -> ColorPresetItem( color = color, diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/MangaComfortableGrid.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/MangaComfortableGrid.kt index 15acd382..74976320 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/MangaComfortableGrid.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/MangaComfortableGrid.kt @@ -13,10 +13,10 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.GridCells -import androidx.compose.foundation.lazy.LazyVerticalGrid -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items +import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.material.LocalTextStyle import androidx.compose.material.MaterialTheme import androidx.compose.material.Text @@ -51,14 +51,14 @@ fun LibraryMangaComfortableGrid( showLocal: Boolean ) { Box { - val state = rememberLazyListState() + val state = rememberLazyGridState() val cells = if (gridColumns < 1) { GridCells.Adaptive(gridSize.dp) } else { GridCells.Fixed(gridColumns) } LazyVerticalGrid( - cells = cells, + columns = cells, state = state, modifier = Modifier.fillMaxSize().padding(4.dp) ) { @@ -77,7 +77,7 @@ fun LibraryMangaComfortableGrid( } } VerticalScrollbar( - rememberScrollbarAdapter(state), + rememberScrollbarAdapter(state, cells), Modifier.align(Alignment.CenterEnd) .fillMaxHeight() .scrollbarPadding() diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/MangaCompactGrid.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/MangaCompactGrid.kt index 90714cb2..80294db9 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/MangaCompactGrid.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/MangaCompactGrid.kt @@ -12,10 +12,10 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.GridCells -import androidx.compose.foundation.lazy.LazyVerticalGrid -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items +import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.material.LocalTextStyle import androidx.compose.material.MaterialTheme import androidx.compose.material.Text @@ -59,14 +59,14 @@ fun LibraryMangaCompactGrid( showLocal: Boolean ) { Box { - val state = rememberLazyListState() + val state = rememberLazyGridState() val cells = if (gridColumns < 1) { GridCells.Adaptive(gridSize.dp) } else { GridCells.Fixed(gridColumns) } LazyVerticalGrid( - cells = cells, + columns = cells, state = state, modifier = Modifier.fillMaxSize().padding(4.dp) ) { @@ -85,7 +85,7 @@ fun LibraryMangaCompactGrid( } } VerticalScrollbar( - rememberScrollbarAdapter(state), + rememberScrollbarAdapter(state, cells), Modifier.align(Alignment.CenterEnd) .fillMaxHeight() .scrollbarPadding() diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/MangaCoverOnlyGrid.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/MangaCoverOnlyGrid.kt index e67e26eb..6735c665 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/MangaCoverOnlyGrid.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/MangaCoverOnlyGrid.kt @@ -12,10 +12,10 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.GridCells -import androidx.compose.foundation.lazy.LazyVerticalGrid -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items +import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -45,14 +45,14 @@ fun LibraryMangaCoverOnlyGrid( showLocal: Boolean ) { Box { - val state = rememberLazyListState() + val state = rememberLazyGridState() val cells = if (gridColumns < 1) { GridCells.Adaptive(gridSize.dp) } else { GridCells.Fixed(gridColumns) } LazyVerticalGrid( - cells = cells, + columns = cells, state = state, modifier = Modifier.fillMaxSize().padding(4.dp) ) { @@ -71,7 +71,7 @@ fun LibraryMangaCoverOnlyGrid( } } VerticalScrollbar( - rememberScrollbarAdapter(state), + rememberScrollbarAdapter(state, cells), Modifier.align(Alignment.CenterEnd) .fillMaxHeight() .scrollbarPadding() diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/browse/components/SourceMangaComfortableGrid.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/browse/components/SourceMangaComfortableGrid.kt index fc284708..8f900b1f 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/browse/components/SourceMangaComfortableGrid.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/browse/components/SourceMangaComfortableGrid.kt @@ -14,10 +14,10 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.GridCells -import androidx.compose.foundation.lazy.LazyVerticalGrid -import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.itemsIndexed +import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.material.LocalTextStyle import androidx.compose.material.MaterialTheme import androidx.compose.material.Text @@ -50,14 +50,14 @@ fun SourceMangaComfortableGrid( onLoadNextPage: () -> Unit, ) { Box { - val state = rememberLazyListState() + val state = rememberLazyGridState() val cells = if (gridColumns < 1) { GridCells.Adaptive(gridSize.dp) } else { GridCells.Fixed(gridColumns) } LazyVerticalGrid( - cells = cells, + columns = cells, state = state, modifier = Modifier.fillMaxSize().padding(4.dp) ) { @@ -75,7 +75,7 @@ fun SourceMangaComfortableGrid( } } VerticalScrollbar( - rememberScrollbarAdapter(state), + rememberScrollbarAdapter(state, cells), Modifier.align(Alignment.CenterEnd) .fillMaxHeight() .scrollbarPadding() diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/browse/components/SourceMangaCompactGrid.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/browse/components/SourceMangaCompactGrid.kt index b5e1b58b..911ab08a 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/browse/components/SourceMangaCompactGrid.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/browse/components/SourceMangaCompactGrid.kt @@ -13,10 +13,10 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.GridCells -import androidx.compose.foundation.lazy.LazyVerticalGrid -import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.itemsIndexed +import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.material.LocalTextStyle import androidx.compose.material.MaterialTheme import androidx.compose.material.Text @@ -53,14 +53,14 @@ fun SourceMangaCompactGrid( onLoadNextPage: () -> Unit, ) { Box { - val state = rememberLazyListState() + val state = rememberLazyGridState() val cells = if (gridColumns < 1) { GridCells.Adaptive(gridSize.dp) } else { GridCells.Fixed(gridColumns) } LazyVerticalGrid( - cells = cells, + columns = cells, state = state, modifier = Modifier.fillMaxSize().padding(4.dp) ) { @@ -78,7 +78,7 @@ fun SourceMangaCompactGrid( } } VerticalScrollbar( - rememberScrollbarAdapter(state), + rememberScrollbarAdapter(state, cells), Modifier.align(Alignment.CenterEnd) .fillMaxHeight() .scrollbarPadding() diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/home/components/SourceHomeScreenContent.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/home/components/SourceHomeScreenContent.kt index f79f9631..7890c2cf 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/home/components/SourceHomeScreenContent.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/home/components/SourceHomeScreenContent.kt @@ -7,7 +7,6 @@ package ca.gosyer.jui.ui.sources.home.components import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -20,10 +19,11 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.GridCells import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items +import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.RoundedCornerShape @@ -86,27 +86,41 @@ fun SourceHomeScreenContent( if (sources.isEmpty()) { LoadingScreen(isLoading) } else { - Box(Modifier.fillMaxSize().padding(it), Alignment.TopCenter) { - val state = rememberLazyListState() - SourceCategory(sources, onAddSource, state) - /*val sourcesByLang = sources.groupBy { it.lang.toLowerCase() }.toList() - LazyColumn(state = state) { - items(sourcesByLang) { (lang, sources) -> - SourceCategory( - lang, - sources, - onSourceClicked = sourceClicked - ) - Spacer(Modifier.height(8.dp)) + BoxWithConstraints(Modifier.fillMaxSize().padding(it), Alignment.TopCenter) { + if (maxWidth > 720.dp) { + val state = rememberLazyGridState() + val cells = GridCells.Adaptive(120.dp) + LazyVerticalGrid(cells, state = state) { + items(sources) { source -> + WideSourceItem( + source, + onSourceClicked = onAddSource + ) + } } - }*/ - - VerticalScrollbar( - modifier = Modifier.align(Alignment.CenterEnd) - .fillMaxHeight() - .scrollbarPadding(), - adapter = rememberScrollbarAdapter(state) - ) + VerticalScrollbar( + modifier = Modifier.align(Alignment.CenterEnd) + .fillMaxHeight() + .scrollbarPadding(), + adapter = rememberScrollbarAdapter(state, cells) + ) + } else { + val state = rememberLazyListState() + LazyColumn(state = state) { + items(sources) { source -> + ThinSourceItem( + source, + onSourceClicked = onAddSource + ) + } + } + VerticalScrollbar( + modifier = Modifier.align(Alignment.CenterEnd) + .fillMaxHeight() + .scrollbarPadding(), + adapter = rememberScrollbarAdapter(state) + ) + } } } } @@ -137,35 +151,6 @@ fun SourceHomeScreenToolbar( ) } -@Composable -fun SourceCategory( - sources: List, - onSourceClicked: (Source) -> Unit, - state: LazyListState -) { - BoxWithConstraints { - if (maxWidth > 720.dp) { - LazyVerticalGrid(GridCells.Adaptive(120.dp), state = state) { - items(sources) { source -> - WideSourceItem( - source, - onSourceClicked = onSourceClicked - ) - } - } - } else { - LazyColumn(state = state) { - items(sources) { source -> - ThinSourceItem( - source, - onSourceClicked = onSourceClicked - ) - } - } - } - } -} - @Composable fun WideSourceItem( source: Source, diff --git a/ui-core/src/androidMain/kotlin/ca/gosyer/jui/uicore/components/AndroidScrollbar.kt b/ui-core/src/androidMain/kotlin/ca/gosyer/jui/uicore/components/AndroidScrollbar.kt index 302ecd4d..e46521d8 100644 --- a/ui-core/src/androidMain/kotlin/ca/gosyer/jui/uicore/components/AndroidScrollbar.kt +++ b/ui-core/src/androidMain/kotlin/ca/gosyer/jui/uicore/components/AndroidScrollbar.kt @@ -15,6 +15,8 @@ import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable @@ -38,6 +40,7 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp +import androidx.compose.ui.util.fastMaxBy import androidx.compose.ui.util.fastSumBy import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow @@ -48,6 +51,8 @@ class ScrollStateScrollbarAdapter(val scrollState: ScrollState) : ScrollbarAdapt class LazyListStateScrollbarAdapter(val lazyListState: LazyListState) : ScrollbarAdapter +class LazyGridStateScrollbarAdapter(val lazyGridState: LazyGridState, val gridCells: GridCells) : ScrollbarAdapter + @Immutable actual class ScrollbarStyle @@ -70,6 +75,9 @@ internal actual fun RealVerticalScrollbar( is LazyListStateScrollbarAdapter -> { Modifier.drawScrollbar(adapter.lazyListState, Orientation.Vertical, reverseLayout) } + is LazyGridStateScrollbarAdapter -> { + Modifier.drawScrollbar(adapter.lazyGridState, adapter.gridCells, Orientation.Vertical, reverseLayout) + } else -> Modifier } Box(modifier then Modifier.fillMaxSize() then scrollbarModifier) @@ -113,6 +121,16 @@ actual fun rememberScrollbarAdapter( } } +@Composable +actual fun rememberScrollbarAdapter( + scrollState: LazyGridState, + gridCells: GridCells, +): ScrollbarAdapter { + return remember(scrollState, gridCells) { + LazyGridStateScrollbarAdapter(scrollState, gridCells) + } +} + actual fun Modifier.scrollbarPadding() = this // Based on https://gist.github.com/mxalbert1996/33a360fcab2105a31e5355af98216f5a @@ -186,6 +204,50 @@ private fun Modifier.drawScrollbar( } } +private fun Modifier.drawScrollbar( + state: LazyGridState, + gridCells: GridCells, + orientation: Orientation, + reverseScrolling: Boolean +): Modifier = drawScrollbar( + orientation, reverseScrolling, snapshotFlow { state.isScrollInProgress } +) { reverseDirection, atEnd, thickness, color, alpha -> + val layoutInfo = state.layoutInfo + val viewportSize = layoutInfo.viewportEndOffset - layoutInfo.viewportStartOffset + val items = layoutInfo.visibleItemsInfo + // TODO Fix spacing + val itemsSize = items.chunked( + with(gridCells) { + calculateCrossAxisCellSizes(viewportSize, 0).size + } + ).sumOf { it.fastMaxBy { it.size.height }?.size?.height ?: 0 } + val showScrollbar = items.size < layoutInfo.totalItemsCount || itemsSize > viewportSize + val estimatedItemSize = if (items.isEmpty()) 0f else itemsSize.toFloat() / items.size + val totalSize = estimatedItemSize * layoutInfo.totalItemsCount + val canvasSize = if (orientation == Orientation.Horizontal) size.width else size.height + val thumbSize = viewportSize / totalSize * canvasSize + val startOffset = if (items.isEmpty()) 0f else items + .first() + .run { + (estimatedItemSize * index - if (orientation == Orientation.Vertical) offset.y else offset.x) / totalSize * canvasSize + } + val drawScrollbar = onDrawScrollbar( + orientation = orientation, + reverseDirection = reverseDirection, + atEnd = atEnd, + showScrollbar = showScrollbar, + thickness = thickness, + color = color, + alpha = alpha, + thumbSize = thumbSize, + startOffset = startOffset + ) + onDrawWithContent { + drawContent() + drawScrollbar() + } +} + private fun CacheDrawScope.onDrawScrollbar( orientation: Orientation, reverseDirection: Boolean, diff --git a/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/components/DropDownMenu.kt b/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/components/DropDownMenu.kt index cc567688..3df65f05 100644 --- a/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/components/DropDownMenu.kt +++ b/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/components/DropDownMenu.kt @@ -50,8 +50,7 @@ data class PopupProperties @ExperimentalComposeUiApi constructor( val securePolicy: SecureFlagPolicy = SecureFlagPolicy.Inherit, val excludeFromSystemGesture: Boolean = true, val clippingEnabled: Boolean = true, - @Suppress("EXPERIMENTAL_ANNOTATION_ON_WRONG_TARGET") - @get:ExperimentalComposeUiApi + @property:ExperimentalComposeUiApi val usePlatformDefaultWidth: Boolean = false ) diff --git a/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/components/Scrollbar.kt b/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/components/Scrollbar.kt index 19fb012d..b406e62d 100644 --- a/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/components/Scrollbar.kt +++ b/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/components/Scrollbar.kt @@ -9,6 +9,8 @@ package ca.gosyer.jui.uicore.components import androidx.compose.foundation.ScrollState import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.runtime.Composable import androidx.compose.runtime.ProvidableCompositionLocal import androidx.compose.runtime.remember @@ -66,4 +68,10 @@ expect fun rememberScrollbarAdapter( scrollState: LazyListState, ): ScrollbarAdapter +@Composable +expect fun rememberScrollbarAdapter( + scrollState: LazyGridState, + gridCells: GridCells, +): ScrollbarAdapter + expect fun Modifier.scrollbarPadding(): Modifier diff --git a/ui-core/src/desktopMain/kotlin/ca/gosyer/jui/uicore/components/DesktopScrollbar.kt b/ui-core/src/desktopMain/kotlin/ca/gosyer/jui/uicore/components/DesktopScrollbar.kt index dda1e426..ec994a49 100644 --- a/ui-core/src/desktopMain/kotlin/ca/gosyer/jui/uicore/components/DesktopScrollbar.kt +++ b/ui-core/src/desktopMain/kotlin/ca/gosyer/jui/uicore/components/DesktopScrollbar.kt @@ -7,13 +7,22 @@ package ca.gosyer.jui.uicore.components import androidx.compose.foundation.ScrollState +import androidx.compose.foundation.gestures.scrollBy import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.runtime.Composable import androidx.compose.runtime.ProvidableCompositionLocal +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.dp +import kotlin.math.abs actual typealias ScrollbarAdapter = androidx.compose.foundation.ScrollbarAdapter @@ -58,4 +67,98 @@ actual fun rememberScrollbarAdapter( return androidx.compose.foundation.rememberScrollbarAdapter(scrollState) } +@Composable +actual fun rememberScrollbarAdapter( + scrollState: LazyGridState, + gridCells: GridCells, +): ScrollbarAdapter { + val density = LocalDensity.current + return remember(scrollState, gridCells, density) { GridScrollbarAdapter(scrollState, gridCells, density) } +} + +// TODO deal with item spacing +class GridScrollbarAdapter( + private val scrollState: LazyGridState, + private val gridCells: GridCells, + private val density: Density, +) : ScrollbarAdapter { + override val scrollOffset: Float + get() = (scrollState.firstVisibleItemIndex / itemsPerRow).coerceAtLeast(0) * averageItemSize + scrollState.firstVisibleItemScrollOffset + + + override fun maxScrollOffset(containerSize: Int): Float { + val size = with(gridCells) { + density.calculateCrossAxisCellSizes(containerSize, 0).size + } + return (averageItemSize * (itemCount / size) - containerSize).coerceAtLeast(0f) + } + + + override suspend fun scrollTo(containerSize: Int, scrollOffset: Float) { + val distance = scrollOffset - this@GridScrollbarAdapter.scrollOffset + + // if we scroll less than containerSize we need to use scrollBy function to avoid + // undesirable scroll jumps (when an item size is different) + // + // if we scroll more than containerSize we should immediately jump to this position + // without recreating all items between the current and the new position + if (abs(distance) <= containerSize) { + scrollState.scrollBy(distance) + } else { + snapTo(containerSize, scrollOffset) + } + } + + private suspend fun snapTo(containerSize: Int, scrollOffset: Float) { + // In case of very big values, we can catch an overflow, so convert values to double and + // coerce them +// val averageItemSize = 26.000002f +// val scrollOffsetCoerced = 2.54490608E8.toFloat() +// val index = (scrollOffsetCoerced / averageItemSize).toInt() // 9788100 +// val offset = (scrollOffsetCoerced - index * averageItemSize) // -16.0 +// println(offset) + + val maximumValue = maxScrollOffset(containerSize).toDouble() + val scrollOffsetCoerced = scrollOffset.toDouble().coerceIn(0.0, maximumValue) + val averageItemSize = averageItemSize.toDouble() + + val index = (scrollOffsetCoerced / averageItemSize) + .toInt() + .div( + with(gridCells) { + density.calculateCrossAxisCellSizes(containerSize, 0).size + } + ) + .coerceAtLeast(0) + .coerceAtMost(itemCount - 1) + + val offset = (scrollOffsetCoerced - index * averageItemSize) + .toInt() + .coerceAtLeast(0) + + scrollState.scrollToItem(index = index, scrollOffset = offset) + } + + private val itemCount get() = scrollState.layoutInfo.totalItemsCount + + private val averageItemSize: Float by derivedStateOf { + scrollState + .layoutInfo + .visibleItemsInfo + .asSequence() + .map { it.size.height } + .average() + .toFloat() + } + + private val itemsPerRow + get() = with(gridCells) { + density.calculateCrossAxisCellSizes( + (scrollState.layoutInfo.viewportEndOffset - scrollState.layoutInfo.viewportStartOffset) + .coerceAtLeast(0), + 0 + ).size + } +} + actual fun Modifier.scrollbarPadding() = padding(horizontal = 4.dp, vertical = 8.dp)