diff --git a/build-number.properties b/build-number.properties
index b21fb84..18a7270 100644
--- a/build-number.properties
+++ b/build-number.properties
@@ -15,4 +15,4 @@
# You should have received a copy of the GNU General Public License along
# with Fhraise. If not, see .
#
-buildNumber=17
+buildNumber=18
diff --git a/composeApp/src/androidMain/kotlin/ui/composables/Scrollbars.android.kt b/composeApp/src/androidMain/kotlin/ui/composables/Scrollbars.android.kt
new file mode 100644
index 0000000..5313852
--- /dev/null
+++ b/composeApp/src/androidMain/kotlin/ui/composables/Scrollbars.android.kt
@@ -0,0 +1,27 @@
+/*
+ * This file is part of Fhraise.
+ * Copyright (c) 2024 HSAS Foodies. All Rights Reserved.
+ *
+ * Fhraise is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Fhraise is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Fhraise. If not, see .
+ */
+
+package ui.composables
+
+import androidx.compose.foundation.ScrollState
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+
+@Composable
+actual fun VerticalScrollbar(scrollState: ScrollState, modifier: Modifier) {
+}
diff --git a/composeApp/src/commonMain/kotlin/ui/composables/Scrollbars.kt b/composeApp/src/commonMain/kotlin/ui/composables/Scrollbars.kt
new file mode 100644
index 0000000..9211e20
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/ui/composables/Scrollbars.kt
@@ -0,0 +1,26 @@
+/*
+ * This file is part of Fhraise.
+ * Copyright (c) 2024 HSAS Foodies. All Rights Reserved.
+ *
+ * Fhraise is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Fhraise is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Fhraise. If not, see .
+ */
+
+package ui.composables
+
+import androidx.compose.foundation.ScrollState
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+
+@Composable
+expect fun VerticalScrollbar(scrollState: ScrollState, modifier: Modifier = Modifier)
diff --git a/composeApp/src/commonMain/kotlin/ui/pages/root/SignIn.kt b/composeApp/src/commonMain/kotlin/ui/pages/root/SignIn.kt
index d6b241e..6ba69a7 100644
--- a/composeApp/src/commonMain/kotlin/ui/pages/root/SignIn.kt
+++ b/composeApp/src/commonMain/kotlin/ui/pages/root/SignIn.kt
@@ -55,6 +55,7 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
import ui.WindowSizeClass
import ui.WindowWidthSizeClass
+import ui.composables.VerticalScrollbar
import ui.modifiers.applyBrush
import kotlin.math.max
import kotlin.math.roundToInt
@@ -197,6 +198,8 @@ fun SignInLayout(
targetValue = if (animation == null) 0f else 1f, animationSpec = spring(stiffness = Spring.StiffnessLow)
)
+ val scrollState = rememberScrollState()
+
SubcomposeLayout(
modifier = Modifier.alpha(firstPrintAnimation).offset(y = 32.dp * (1f - firstPrintAnimation)).then(modifier)
) { constraints ->
@@ -248,16 +251,19 @@ fun SignInLayout(
val additionalContentPlaceable = additionalContentMeasurable.measure(additionalContentConstraints)
// == Measure main ==
+ val mainBottomSpace =
+ ((additionalContentPlaceable.height + additionalContentPaddingBottom) * animationSecondStageReversed)
+
val mainMeasurable = subcompose("main") {
SignInMainLayout(
animation = animation,
animationSecondStage = animationSecondStage,
- scrollState = rememberScrollState(),
+ scrollState = scrollState,
contentPaddingLeft = contentPaddingLeft,
contentPaddingTop = contentPaddingTop,
contentPaddingRight = contentPaddingRight,
contentPaddingBottom = contentPaddingBottom,
- bottomSpace = ((additionalContentPlaceable.height + additionalContentPaddingBottom) * animationSecondStageReversed).roundToInt(),
+ bottomSpace = mainBottomSpace.roundToInt(),
header = header,
mainContent = content,
)
@@ -265,11 +271,24 @@ fun SignInLayout(
val mainCompatWidth = width.toFloat()
val mainMediumExpandedWidth = width * 7f / 9f
- val mainWidth = mainCompatWidth + (mainMediumExpandedWidth - mainCompatWidth) * animationSecondStage
+ val mainWidth =
+ (mainCompatWidth + (mainMediumExpandedWidth - mainCompatWidth) * animationSecondStage).coerceAtLeast(0f)
+ .roundToInt()
- val mainConstraints = Constraints.fixed(width = mainWidth.roundToInt().coerceAtLeast(0), height = height)
+ val mainConstraints = Constraints.fixed(width = mainWidth, height = height)
val mainPlaceable = mainMeasurable.measure(mainConstraints)
+ // == Scrollbar ==
+ val scrollbarHeight = (safeHeight - mainBottomSpace).roundToInt()
+
+ val scrollbarPlaceable = subcompose("scrollBar") {
+ VerticalScrollbar(scrollState = scrollState)
+ }.firstOrNull()
+ ?.measure(Constraints(maxWidth = mainWidth, minHeight = scrollbarHeight, maxHeight = scrollbarHeight))
+
+ val scrollbarX = scrollbarPlaceable?.let { mainWidth - scrollbarPlaceable.width }
+ val scrollbarY = contentPaddingTop.roundToInt()
+
// == Place ==
val additionalContentCompatMediumX = 0f
val additionalContentX =
@@ -305,6 +324,7 @@ fun SignInLayout(
layout(width, height) {
mainPlaceable.placeRelative(0, 0)
+ scrollbarX?.let { scrollbarPlaceable.placeRelative(scrollbarX, scrollbarY) }
additionalContentBackgroundPlaceable.placeRelative(0, additionalContentBackgroundY.roundToInt())
additionalContentPlaceable.placeRelative(additionalContentX.roundToInt(), additionalContentY.roundToInt())
}
diff --git a/composeApp/src/desktopMain/kotlin/ui/composables/Scrollbars.desktop.kt b/composeApp/src/desktopMain/kotlin/ui/composables/Scrollbars.desktop.kt
new file mode 100644
index 0000000..ce544d7
--- /dev/null
+++ b/composeApp/src/desktopMain/kotlin/ui/composables/Scrollbars.desktop.kt
@@ -0,0 +1,31 @@
+/*
+ * This file is part of Fhraise.
+ * Copyright (c) 2024 HSAS Foodies. All Rights Reserved.
+ *
+ * Fhraise is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Fhraise is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Fhraise. If not, see .
+ */
+
+package ui.composables
+
+import androidx.compose.foundation.ScrollState
+import androidx.compose.foundation.rememberScrollbarAdapter
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+
+@Composable
+actual fun VerticalScrollbar(scrollState: ScrollState, modifier: Modifier) {
+ androidx.compose.foundation.VerticalScrollbar(
+ adapter = rememberScrollbarAdapter(scrollState = scrollState), modifier = modifier
+ )
+}
diff --git a/composeApp/src/wasmJsMain/kotlin/ui/composables/Scrollbars.wasmJs.kt b/composeApp/src/wasmJsMain/kotlin/ui/composables/Scrollbars.wasmJs.kt
new file mode 100644
index 0000000..5313852
--- /dev/null
+++ b/composeApp/src/wasmJsMain/kotlin/ui/composables/Scrollbars.wasmJs.kt
@@ -0,0 +1,27 @@
+/*
+ * This file is part of Fhraise.
+ * Copyright (c) 2024 HSAS Foodies. All Rights Reserved.
+ *
+ * Fhraise is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Fhraise is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Fhraise. If not, see .
+ */
+
+package ui.composables
+
+import androidx.compose.foundation.ScrollState
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+
+@Composable
+actual fun VerticalScrollbar(scrollState: ScrollState, modifier: Modifier) {
+}