Add scrollbars everywhere! Closes #35

This commit is contained in:
Syer10
2021-12-19 13:54:21 -05:00
parent b9503e7fe0
commit 89caae3681
27 changed files with 1038 additions and 593 deletions

View File

@@ -20,6 +20,7 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
@@ -32,6 +33,7 @@ import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
@@ -41,6 +43,8 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.Checkbox
import androidx.compose.material.ContentAlpha
@@ -242,7 +246,8 @@ fun <T> ChoiceDialog(
buttons = buttons,
title = title
) {
LazyColumn(Modifier.fillMaxSize()) {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
items(items) { (value, text) ->
Row(
modifier = Modifier.requiredHeight(48.dp).fillMaxWidth().clickable(
@@ -264,6 +269,12 @@ fun <T> ChoiceDialog(
}
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
@@ -283,28 +294,37 @@ fun <T> MultiSelectDialog(
}
) {
val checked by checkedFlow.collectAsState()
LazyColumn(Modifier.fillMaxSize()) {
items(items) { (value, text) ->
Row(
modifier = Modifier.requiredHeight(48.dp).fillMaxWidth().clickable(
onClick = {
if (value in checked) {
checkedFlow.value -= value
} else {
checkedFlow.value += value
val state = rememberLazyListState()
Box {
LazyColumn(Modifier.fillMaxSize(), state) {
items(items) { (value, text) ->
Row(
modifier = Modifier.requiredHeight(48.dp).fillMaxWidth().clickable(
onClick = {
if (value in checked) {
checkedFlow.value -= value
} else {
checkedFlow.value += value
}
}
}
),
verticalAlignment = Alignment.CenterVertically
) {
Checkbox(
checked = value in checked,
onCheckedChange = null,
)
Text(text = text, modifier = Modifier.padding(start = 24.dp))
),
verticalAlignment = Alignment.CenterVertically
) {
Checkbox(
checked = value in checked,
onCheckedChange = null,
)
Text(text = text, modifier = Modifier.padding(start = 24.dp))
}
}
item { Spacer(Modifier.height(80.dp)) }
}
item { Spacer(Modifier.height(80.dp)) }
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -48,8 +48,8 @@ fun AppTheme(content: @Composable () -> Unit) {
thickness = 8.dp,
shape = MaterialTheme.shapes.small,
hoverDurationMillis = 300,
unhoverColor = MaterialTheme.colors.onSurface.copy(alpha = 0.12f),
hoverColor = MaterialTheme.colors.onSurface.copy(alpha = 0.50f)
unhoverColor = MaterialTheme.colors.onSurface.copy(alpha = 0.30f),
hoverColor = MaterialTheme.colors.onSurface.copy(alpha = 0.70f)
),
content = content
)

View File

@@ -6,16 +6,20 @@
package ca.gosyer.ui.categories
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.Card
import androidx.compose.material.ContentAlpha
import androidx.compose.material.ExtendedFloatingActionButton
@@ -84,7 +88,8 @@ fun CategoriesMenu(notifyFinished: (() -> Unit)? = null) {
Surface {
Box {
LazyColumn(modifier = Modifier.fillMaxSize()) {
val state = rememberLazyListState()
LazyColumn(modifier = Modifier.fillMaxSize(), state = state,) {
itemsIndexed(categories) { i, category ->
CategoryRow(
category = category,
@@ -118,6 +123,12 @@ fun CategoriesMenu(notifyFinished: (() -> Unit)? = null) {
}
}
)
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -7,7 +7,9 @@
package ca.gosyer.ui.downloads
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
@@ -19,6 +21,8 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.Icon
import androidx.compose.material.LinearProgressIndicator
@@ -34,6 +38,7 @@ import androidx.compose.material.icons.rounded.PlayArrow
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.FilterQuality
@@ -90,15 +95,24 @@ fun DownloadsMenu(onMangaClick: (Long) -> Unit) {
ActionIcon(onClick = vm::clear, stringResource("action_clear_queue"), Icons.Rounded.ClearAll)
}
)
LazyColumn(Modifier.fillMaxSize()) {
items(downloadQueue) {
DownloadsItem(
it,
{ onMangaClick(it.mangaId) },
vm::stopDownload,
vm::moveToBottom
)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
items(downloadQueue) {
DownloadsItem(
it,
{ onMangaClick(it.mangaId) },
vm::stopDownload,
vm::moveToBottom
)
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,7 +6,6 @@
package ca.gosyer.ui.extensions
import androidx.compose.foundation.ScrollbarAdapter
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
@@ -129,7 +128,9 @@ fun ExtensionsMenu() {
}
}
VerticalScrollbar(
modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
modifier = Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp),
adapter = rememberScrollbarAdapter(state)
)
}
@@ -244,7 +245,12 @@ fun LanguageDialog(enabledLangsFlow: MutableStateFlow<Set<String>>, availableLan
}
item { Spacer(Modifier.height(70.dp)) }
}
VerticalScrollbar(ScrollbarAdapter(state), Modifier.align(Alignment.CenterEnd).padding(8.dp))
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -7,14 +7,18 @@
package ca.gosyer.ui.library
import androidx.compose.foundation.ContextMenuItem
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio
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.rememberScrollbarAdapter
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
@@ -43,22 +47,32 @@ fun LibraryMangaCompactGrid(
onClickManga: (Long) -> Unit = {},
onRemoveMangaClicked: (Long) -> Unit = {}
) {
LazyVerticalGrid(
cells = GridCells.Adaptive(160.dp),
modifier = Modifier.fillMaxSize().padding(4.dp)
) {
items(library) { manga ->
LibraryMangaCompactGridItem(
manga = manga,
unread = manga.unreadCount,
downloaded = manga.downloadCount,
onClick = { onClickManga(manga.id) }
) {
listOf(
ContextMenuItem("Unfavorite") { onRemoveMangaClicked(manga.id) }
)
Box {
val state = rememberLazyListState()
LazyVerticalGrid(
cells = GridCells.Adaptive(160.dp),
state = state,
modifier = Modifier.fillMaxSize().padding(4.dp)
) {
items(library) { manga ->
LibraryMangaCompactGridItem(
manga = manga,
unread = manga.unreadCount,
downloaded = manga.downloadCount,
onClick = { onClickManga(manga.id) }
) {
listOf(
ContextMenuItem("Unfavorite") { onRemoveMangaClicked(manga.id) }
)
}
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}

View File

@@ -164,7 +164,9 @@ fun MangaMenu(mangaId: Long, menuController: MenuController? = LocalMenuControll
}
}
VerticalScrollbar(
modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
modifier = Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp),
adapter = rememberScrollbarAdapter(state)
)
}
@@ -262,26 +264,35 @@ fun openCategorySelectDialog(
onPositiveButton = { onPositiveClick(enabledCategoriesFlow.value, oldCategories) }
) {
val enabledCategories by enabledCategoriesFlow.collectAsState()
LazyColumn {
items(categories) { category ->
Row(
Modifier.fillMaxWidth().padding(8.dp)
.clickable {
if (category in enabledCategories) {
enabledCategoriesFlow.value -= category
} else {
enabledCategoriesFlow.value += category
}
},
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(category.name, style = MaterialTheme.typography.subtitle1)
Checkbox(
category in enabledCategories,
onCheckedChange = null
)
val state = rememberLazyListState()
Box {
LazyColumn(state = state) {
items(categories) { category ->
Row(
Modifier.fillMaxWidth().padding(8.dp)
.clickable {
if (category in enabledCategories) {
enabledCategoriesFlow.value -= category
} else {
enabledCategoriesFlow.value += category
}
},
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(category.name, style = MaterialTheme.typography.subtitle1)
Checkbox(
category in enabledCategories,
onCheckedChange = null
)
}
}
}
VerticalScrollbar(
modifier = Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp),
adapter = rememberScrollbarAdapter(state)
)
}
}
}

View File

@@ -6,6 +6,8 @@
package ca.gosyer.ui.reader.viewer
import androidx.compose.foundation.HorizontalScrollbar
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.gestures.animateScrollBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
@@ -21,6 +23,7 @@ import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
@@ -124,6 +127,13 @@ fun ContinuousReader(
progress
)
}
VerticalScrollbar(
modifier = Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp),
adapter = rememberScrollbarAdapter(state),
reverseLayout = direction == Direction.Up
)
}
Direction.Left, Direction.Right -> {
LazyRow(
@@ -145,6 +155,13 @@ fun ContinuousReader(
progress
)
}
HorizontalScrollbar(
modifier = Modifier.align(Alignment.BottomCenter)
.fillMaxWidth()
.padding(horizontal = 8.dp, vertical = 4.dp),
adapter = rememberScrollbarAdapter(state),
reverseLayout = direction == Direction.Left
)
}
}
}

View File

@@ -6,9 +6,19 @@
package ca.gosyer.ui.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.data.update.UpdatePreferences
import ca.gosyer.ui.base.components.MenuController
import ca.gosyer.ui.base.components.Toolbar
@@ -29,10 +39,19 @@ fun SettingsAdvancedScreen(menuController: MenuController) {
val vm = viewModel<SettingsAdvancedViewModel>()
Column {
Toolbar(stringResource("settings_advanced_screen"), menuController, true)
LazyColumn {
item {
SwitchPreference(preference = vm.updatesEnabled, title = stringResource("update_checker"))
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
SwitchPreference(preference = vm.updatesEnabled, title = stringResource("update_checker"))
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,16 +6,21 @@
package ca.gosyer.ui.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
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.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
@@ -77,59 +82,68 @@ fun SettingsAppearance(menuController: MenuController) {
Column {
Toolbar(stringResource("settings_appearance_screen"), menuController, true)
LazyColumn {
item {
ChoicePreference(
preference = vm.themeMode,
choices = mapOf(
ThemeMode.System to stringResource("theme_follow_system"),
ThemeMode.Light to stringResource("theme_light"),
ThemeMode.Dark to stringResource("theme_dark")
),
title = stringResource("theme")
)
}
item {
Text(
stringResource("preset_themes"),
modifier = Modifier.padding(start = 16.dp, top = 16.dp, bottom = 4.dp)
)
LazyRow(modifier = Modifier.padding(horizontal = 8.dp)) {
items(themesForCurrentMode) { theme ->
ThemeItem(
theme,
onClick = {
(if (isLight) vm.lightTheme else vm.darkTheme).value = it.id
activeColors.primaryStateFlow.value = it.colors.primary
activeColors.secondaryStateFlow.value = it.colors.secondary
}
)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
ChoicePreference(
preference = vm.themeMode,
choices = mapOf(
ThemeMode.System to stringResource("theme_follow_system"),
ThemeMode.Light to stringResource("theme_light"),
ThemeMode.Dark to stringResource("theme_dark")
),
title = stringResource("theme")
)
}
item {
Text(
stringResource("preset_themes"),
modifier = Modifier.padding(start = 16.dp, top = 16.dp, bottom = 4.dp)
)
LazyRow(modifier = Modifier.padding(horizontal = 8.dp)) {
items(themesForCurrentMode) { theme ->
ThemeItem(
theme,
onClick = {
(if (isLight) vm.lightTheme else vm.darkTheme).value = it.id
activeColors.primaryStateFlow.value = it.colors.primary
activeColors.secondaryStateFlow.value = it.colors.secondary
}
)
}
}
}
item {
ColorPreference(
preference = activeColors.primaryStateFlow,
title = stringResource("color_primary"),
subtitle = stringResource("color_primary_sub"),
unsetColor = MaterialTheme.colors.primary
)
}
item {
ColorPreference(
preference = activeColors.secondaryStateFlow,
title = stringResource("color_secondary"),
subtitle = stringResource("color_secondary_sub"),
unsetColor = MaterialTheme.colors.secondary
)
}
item {
SwitchPreference(
vm.windowDecorations,
stringResource("window_decorations"),
stringResource("window_decorations_sub")
)
}
}
item {
ColorPreference(
preference = activeColors.primaryStateFlow,
title = stringResource("color_primary"),
subtitle = stringResource("color_primary_sub"),
unsetColor = MaterialTheme.colors.primary
)
}
item {
ColorPreference(
preference = activeColors.secondaryStateFlow,
title = stringResource("color_secondary"),
subtitle = stringResource("color_secondary_sub"),
unsetColor = MaterialTheme.colors.secondary
)
}
item {
SwitchPreference(
vm.windowDecorations,
stringResource("window_decorations"),
stringResource("window_decorations_sub")
)
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,10 +6,17 @@
package ca.gosyer.ui.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
@@ -200,28 +207,37 @@ fun SettingsBackupScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("settings_backup_screen"), menuController, true)
LazyColumn {
item {
PreferenceFile(
stringResource("backup_restore"),
stringResource("backup_restore_sub"),
restoring,
restoringProgress,
restoreStatus
) {
filePicker("gz") {
vm.restoreFile(it.selectedFile.toPath())
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
PreferenceFile(
stringResource("backup_restore"),
stringResource("backup_restore_sub"),
restoring,
restoringProgress,
restoreStatus
) {
filePicker("gz") {
vm.restoreFile(it.selectedFile.toPath())
}
}
PreferenceFile(
stringResource("backup_create"),
stringResource("backup_create_sub"),
creating,
creatingProgress,
creatingStatus,
vm::exportBackup
)
}
PreferenceFile(
stringResource("backup_create"),
stringResource("backup_create_sub"),
creating,
creatingProgress,
creatingStatus,
vm::exportBackup
)
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,9 +6,19 @@
package ca.gosyer.ui.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.ui.base.components.MenuController
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.resources.stringResource
@@ -17,7 +27,16 @@ import ca.gosyer.ui.base.resources.stringResource
fun SettingsBrowseScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("settings_browse_screen"), menuController, true)
LazyColumn {
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,9 +6,19 @@
package ca.gosyer.ui.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.ui.base.components.MenuController
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.resources.stringResource
@@ -17,7 +27,16 @@ import ca.gosyer.ui.base.resources.stringResource
fun SettingsDownloadsScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("settings_download_screen"), menuController, true)
LazyColumn {
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,10 +6,20 @@
package ca.gosyer.ui.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.Divider
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.build.BuildResources
import ca.gosyer.data.ui.UiPreferences
import ca.gosyer.data.ui.model.StartScreen
@@ -82,34 +92,46 @@ fun SettingsGeneralScreen(menuController: MenuController) {
val vm = viewModel<SettingsGeneralViewModel>()
Column {
Toolbar(stringResource("settings_general_screen"), menuController, closable = true)
LazyColumn {
item {
ChoicePreference(
preference = vm.startScreen,
title = stringResource("start_screen"),
choices = vm.getStartScreenChoices()
)
}
item {
SwitchPreference(preference = vm.confirmExit, title = stringResource("confirm_exit"))
}
item {
Divider()
}
item {
ChoicePreference(
preference = vm.language,
title = stringResource("language"),
choices = vm.getLanguageChoices(),
)
}
item {
ChoicePreference(
preference = vm.dateFormat,
title = stringResource("date_format"),
choices = vm.getDateChoices()
)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
ChoicePreference(
preference = vm.startScreen,
title = stringResource("start_screen"),
choices = vm.getStartScreenChoices()
)
}
item {
SwitchPreference(
preference = vm.confirmExit,
title = stringResource("confirm_exit")
)
}
item {
Divider()
}
item {
ChoicePreference(
preference = vm.language,
title = stringResource("language"),
choices = vm.getLanguageChoices(),
)
}
item {
ChoicePreference(
preference = vm.dateFormat,
title = stringResource("date_format"),
choices = vm.getDateChoices()
)
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,10 +6,20 @@
package ca.gosyer.ui.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.data.library.LibraryPreferences
import ca.gosyer.data.server.interactions.CategoryInteractionHandler
import ca.gosyer.ui.base.components.MenuController
@@ -51,17 +61,29 @@ fun SettingsLibraryScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("settings_library_screen"), menuController, true)
LazyColumn {
item {
SwitchPreference(preference = vm.showAllCategory, title = stringResource("show_all_category"))
}
item {
PreferenceRow(
stringResource("location_categories"),
onClick = { openCategoriesMenu(vm::refreshCategoryCount) },
subtitle = vm.categories.collectAsState().value.toString()
)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
SwitchPreference(
preference = vm.showAllCategory,
title = stringResource("show_all_category")
)
}
item {
PreferenceRow(
stringResource("location_categories"),
onClick = { openCategoriesMenu(vm::refreshCategoryCount) },
subtitle = vm.categories.collectAsState().value.toString()
)
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,9 +6,19 @@
package ca.gosyer.ui.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.ui.base.components.MenuController
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.resources.stringResource
@@ -17,7 +27,16 @@ import ca.gosyer.ui.base.resources.stringResource
fun SettingsParentalControlsScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("settings_parental_control_screen"), menuController, true)
LazyColumn {
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,12 +6,22 @@
package ca.gosyer.ui.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.Divider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach
import ca.gosyer.data.reader.ReaderModePreferences
import ca.gosyer.data.reader.ReaderPreferences
@@ -121,80 +131,95 @@ fun SettingsReaderScreen(menuController: MenuController) {
val modeSettings by vm.modeSettings.collectAsState()
Column {
Toolbar(stringResource("settings_reader"), menuController, true)
LazyColumn {
item {
ChoicePreference(
vm.selectedMode,
vm.modes.collectAsState().value.associateWith { it },
stringResource("reader_mode")
)
}
item {
Divider()
}
modeSettings.fastForEach {
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
ExpandablePreference(it.mode) {
ChoicePreference(
it.direction,
vm.getDirectionChoices(),
stringResource("direction"),
enabled = !it.defaultMode
)
SwitchPreference(
it.continuous,
stringResource("continuous"),
stringResource("continuous_sub"),
enabled = !it.defaultMode
)
val continuous by it.continuous.collectAsState()
if (continuous) {
ChoicePreference(
it.padding,
vm.getPaddingChoices(),
stringResource("page_padding")
)
val direction by it.direction.collectAsState()
val (title, subtitle) = if (direction == Direction.Up || direction == Direction.Down) {
stringResource("force_fit_width") to stringResource("force_fit_width_sub")
} else {
stringResource("force_fit_height") to stringResource("force_fit_height_sub")
}
SwitchPreference(
it.fitSize,
title,
subtitle
)
val maxSize by it.maxSize.collectAsState()
val (maxSizeTitle, maxSizeSubtitle) = if (direction == Direction.Up || direction == Direction.Down) {
stringResource("max_width") to stringResource("max_width_sub", maxSize)
} else {
stringResource("max_height") to stringResource("max_height_sub", maxSize)
}
ChoicePreference(
it.maxSize,
vm.getMaxSizeChoices(direction),
maxSizeTitle,
maxSizeSubtitle
)
} else {
ChoicePreference(
it.imageScale,
vm.getImageScaleChoices(),
stringResource("image_scale")
)
}
ChoicePreference(
it.navigationMode,
vm.getNavigationModeChoices(),
stringResource("navigation_mode")
)
}
ChoicePreference(
vm.selectedMode,
vm.modes.collectAsState().value.associateWith { it },
stringResource("reader_mode")
)
}
item {
Divider()
}
modeSettings.fastForEach {
item {
ExpandablePreference(it.mode) {
ChoicePreference(
it.direction,
vm.getDirectionChoices(),
stringResource("direction"),
enabled = !it.defaultMode
)
SwitchPreference(
it.continuous,
stringResource("continuous"),
stringResource("continuous_sub"),
enabled = !it.defaultMode
)
val continuous by it.continuous.collectAsState()
if (continuous) {
ChoicePreference(
it.padding,
vm.getPaddingChoices(),
stringResource("page_padding")
)
val direction by it.direction.collectAsState()
val (title, subtitle) = if (direction == Direction.Up || direction == Direction.Down) {
stringResource("force_fit_width") to stringResource("force_fit_width_sub")
} else {
stringResource("force_fit_height") to stringResource("force_fit_height_sub")
}
SwitchPreference(
it.fitSize,
title,
subtitle
)
val maxSize by it.maxSize.collectAsState()
val (maxSizeTitle, maxSizeSubtitle) = if (direction == Direction.Up || direction == Direction.Down) {
stringResource("max_width") to stringResource(
"max_width_sub",
maxSize
)
} else {
stringResource("max_height") to stringResource(
"max_height_sub",
maxSize
)
}
ChoicePreference(
it.maxSize,
vm.getMaxSizeChoices(direction),
maxSizeTitle,
maxSizeSubtitle
)
} else {
ChoicePreference(
it.imageScale,
vm.getImageScaleChoices(),
stringResource("image_scale")
)
}
ChoicePreference(
it.navigationMode,
vm.getNavigationModeChoices(),
stringResource("navigation_mode")
)
}
}
item {
Divider()
}
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,8 +6,15 @@
package ca.gosyer.ui.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Backup
import androidx.compose.material.icons.rounded.ChromeReaderMode
@@ -18,6 +25,9 @@ import androidx.compose.material.icons.rounded.Explore
import androidx.compose.material.icons.rounded.Palette
import androidx.compose.material.icons.rounded.Tune
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.ui.base.components.MenuController
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.prefs.PreferenceRow
@@ -28,91 +38,100 @@ import ca.gosyer.ui.main.Routes
fun SettingsScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("location_settings"), closable = false)
LazyColumn {
item {
PreferenceRow(
title = stringResource("settings_general"),
icon = Icons.Rounded.Tune,
onClick = { menuController.push(Routes.SettingsGeneral) }
)
}
item {
PreferenceRow(
title = stringResource("settings_appearance"),
icon = Icons.Rounded.Palette,
onClick = { menuController.push(Routes.SettingsAppearance) }
)
}
item {
PreferenceRow(
title = stringResource("settings_server"),
icon = Icons.Rounded.Computer,
onClick = { menuController.push(Routes.SettingsServer) }
)
}
item {
PreferenceRow(
title = stringResource("settings_library"),
icon = Icons.Rounded.CollectionsBookmark,
onClick = { menuController.push(Routes.SettingsLibrary) }
)
}
item {
PreferenceRow(
title = stringResource("settings_reader"),
icon = Icons.Rounded.ChromeReaderMode,
onClick = { menuController.push(Routes.SettingsReader) }
)
}
/*item {
Pref(
title = stringResource("settings_download"),
icon = Icons.Rounded.GetApp,
onClick = { navController.push(Route.SettingsDownloads) }
)
}
item {
Pref(
title = stringResource("settings_tracking"),
icon = Icons.Rounded.Sync,
onClick = { navController.push(Route.SettingsTracking) }
)
}*/
item {
PreferenceRow(
title = stringResource("settings_browse"),
icon = Icons.Rounded.Explore,
onClick = { menuController.push(Routes.SettingsBrowse) }
)
}
item {
PreferenceRow(
title = stringResource("settings_backup"),
icon = Icons.Rounded.Backup,
onClick = { menuController.push(Routes.SettingsBackup) }
)
}
/*item {
Pref(
title = stringResource("settings_security"),
icon = Icons.Rounded.Security,
onClick = { navController.push(Route.SettingsSecurity) }
)
}
item {
Pref(
title = stringResource("settings_parental_controls"),
icon = Icons.Rounded.PeopleOutline,
onClick = { navController.push(Route.SettingsParentalControls) }
)
}*/
item {
PreferenceRow(
title = stringResource("settings_advanced"),
icon = Icons.Rounded.Code,
onClick = { menuController.push(Routes.SettingsAdvanced) }
)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
PreferenceRow(
title = stringResource("settings_general"),
icon = Icons.Rounded.Tune,
onClick = { menuController.push(Routes.SettingsGeneral) }
)
}
item {
PreferenceRow(
title = stringResource("settings_appearance"),
icon = Icons.Rounded.Palette,
onClick = { menuController.push(Routes.SettingsAppearance) }
)
}
item {
PreferenceRow(
title = stringResource("settings_server"),
icon = Icons.Rounded.Computer,
onClick = { menuController.push(Routes.SettingsServer) }
)
}
item {
PreferenceRow(
title = stringResource("settings_library"),
icon = Icons.Rounded.CollectionsBookmark,
onClick = { menuController.push(Routes.SettingsLibrary) }
)
}
item {
PreferenceRow(
title = stringResource("settings_reader"),
icon = Icons.Rounded.ChromeReaderMode,
onClick = { menuController.push(Routes.SettingsReader) }
)
}
/*item {
Pref(
title = stringResource("settings_download"),
icon = Icons.Rounded.GetApp,
onClick = { navController.push(Route.SettingsDownloads) }
)
}
item {
Pref(
title = stringResource("settings_tracking"),
icon = Icons.Rounded.Sync,
onClick = { navController.push(Route.SettingsTracking) }
)
}*/
item {
PreferenceRow(
title = stringResource("settings_browse"),
icon = Icons.Rounded.Explore,
onClick = { menuController.push(Routes.SettingsBrowse) }
)
}
item {
PreferenceRow(
title = stringResource("settings_backup"),
icon = Icons.Rounded.Backup,
onClick = { menuController.push(Routes.SettingsBackup) }
)
}
/*item {
Pref(
title = stringResource("settings_security"),
icon = Icons.Rounded.Security,
onClick = { navController.push(Route.SettingsSecurity) }
)
}
item {
Pref(
title = stringResource("settings_parental_controls"),
icon = Icons.Rounded.PeopleOutline,
onClick = { navController.push(Route.SettingsParentalControls) }
)
}*/
item {
PreferenceRow(
title = stringResource("settings_advanced"),
icon = Icons.Rounded.Code,
onClick = { menuController.push(Routes.SettingsAdvanced) }
)
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,9 +6,19 @@
package ca.gosyer.ui.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.ui.base.components.MenuController
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.resources.stringResource
@@ -17,7 +27,16 @@ import ca.gosyer.ui.base.resources.stringResource
fun SettingsSecurityScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("settings_security_screen"), menuController, true)
LazyColumn {
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,8 +6,15 @@
package ca.gosyer.ui.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.Divider
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Info
@@ -16,7 +23,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import ca.gosyer.data.server.ServerHostPreferences
import ca.gosyer.data.server.ServerPreferences
import ca.gosyer.data.server.ServerService
@@ -138,171 +148,208 @@ fun SettingsServerScreen(menuController: MenuController) {
}
Column {
Toolbar(stringResource("settings_server_screen"), menuController, true)
LazyColumn {
item {
SwitchPreference(preference = vm.host, title = stringResource("host_server"))
}
if (host) {
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
SwitchPreference(preference = vm.host, title = stringResource("host_server"))
}
if (host) {
item {
PreferenceRow(
stringResource("host_settings"),
Icons.Rounded.Info,
subtitle = stringResource("host_settings_sub")
)
}
item {
val ip by vm.ip.collectAsState()
EditTextPreference(
preference = vm.ip,
title = stringResource("host_ip"),
subtitle = stringResource("host_ip_sub", ip),
changeListener = vm::serverSettingChanged
)
}
item {
val port by vm.port.collectAsState()
EditTextPreference(
preference = vm.port,
title = stringResource("host_port"),
subtitle = stringResource("host_port_sub", port),
changeListener = vm::serverSettingChanged
)
}
item {
SwitchPreference(
preference = vm.socksProxyEnabled,
title = stringResource("host_socks_enabled"),
changeListener = vm::serverSettingChanged
)
}
item {
val proxyHost by vm.socksProxyHost.collectAsState()
EditTextPreference(
preference = vm.socksProxyHost,
title = stringResource("host_socks_host"),
subtitle = stringResource("host_socks_host_sub", proxyHost),
changeListener = vm::serverSettingChanged
)
}
item {
val proxyPort by vm.socksProxyPort.collectAsState()
EditTextPreference(
preference = vm.socksProxyPort,
title = stringResource("host_socks_port"),
subtitle = stringResource("host_socks_port_sub", proxyPort),
changeListener = vm::serverSettingChanged
)
}
item {
SwitchPreference(
preference = vm.debugLogsEnabled,
title = stringResource("host_debug_logging"),
subtitle = stringResource("host_debug_logging_sub"),
changeListener = vm::serverSettingChanged
)
}
item {
SwitchPreference(
preference = vm.systemTrayEnabled,
title = stringResource("host_system_tray"),
subtitle = stringResource("host_system_tray_sub"),
changeListener = vm::serverSettingChanged
)
}
item {
SwitchPreference(
preference = vm.webUIEnabled,
title = stringResource("host_webui"),
subtitle = stringResource("host_webui_sub"),
changeListener = vm::serverSettingChanged
)
}
item {
val webUIEnabled by vm.webUIEnabled.collectAsState()
SwitchPreference(
preference = vm.openInBrowserEnabled,
title = stringResource("host_open_in_browser"),
subtitle = stringResource("host_open_in_browser_sub"),
changeListener = vm::serverSettingChanged,
enabled = webUIEnabled
)
}
item {
SwitchPreference(
preference = vm.basicAuthEnabled,
title = stringResource("basic_auth"),
subtitle = stringResource("host_basic_auth_sub"),
changeListener = vm::serverSettingChanged
)
}
item {
EditTextPreference(
preference = vm.basicAuthUsername,
title = stringResource("host_basic_auth_username"),
changeListener = vm::serverSettingChanged,
enabled = basicAuthEnabled
)
}
item {
EditTextPreference(
preference = vm.basicAuthPassword,
title = stringResource("host_basic_auth_password"),
changeListener = vm::serverSettingChanged,
visualTransformation = PasswordVisualTransformation(),
enabled = basicAuthEnabled
)
}
}
item {
Divider()
}
item {
EditTextPreference(
vm.serverUrl,
stringResource("server_url"),
subtitle = vm.serverUrl.collectAsState().value
)
}
item {
EditTextPreference(
vm.serverPort,
stringResource("server_port"),
subtitle = vm.serverPort.collectAsState().value
)
}
item {
PreferenceRow(
stringResource("host_settings"),
Icons.Rounded.Info,
subtitle = stringResource("host_settings_sub")
stringResource("server_preference_warning"),
Icons.Rounded.Warning,
subtitle = stringResource("server_preference_warning_sub")
)
}
item {
val ip by vm.ip.collectAsState()
EditTextPreference(
preference = vm.ip,
title = stringResource("host_ip"),
subtitle = stringResource("host_ip_sub", ip),
changeListener = vm::serverSettingChanged
)
ChoicePreference(vm.proxy, vm.getProxyChoices(), stringResource("server_proxy"))
}
item {
val port by vm.port.collectAsState()
EditTextPreference(
preference = vm.port,
title = stringResource("host_port"),
subtitle = stringResource("host_port_sub", port),
changeListener = vm::serverSettingChanged
)
}
item {
SwitchPreference(
preference = vm.socksProxyEnabled,
title = stringResource("host_socks_enabled"),
changeListener = vm::serverSettingChanged
)
}
item {
val proxyHost by vm.socksProxyHost.collectAsState()
EditTextPreference(
preference = vm.socksProxyHost,
title = stringResource("host_socks_host"),
subtitle = stringResource("host_socks_host_sub", proxyHost),
changeListener = vm::serverSettingChanged
)
}
item {
val proxyPort by vm.socksProxyPort.collectAsState()
EditTextPreference(
preference = vm.socksProxyPort,
title = stringResource("host_socks_port"),
subtitle = stringResource("host_socks_port_sub", proxyPort),
changeListener = vm::serverSettingChanged
)
}
item {
SwitchPreference(
preference = vm.debugLogsEnabled,
title = stringResource("host_debug_logging"),
subtitle = stringResource("host_debug_logging_sub"),
changeListener = vm::serverSettingChanged
)
}
item {
SwitchPreference(
preference = vm.systemTrayEnabled,
title = stringResource("host_system_tray"),
subtitle = stringResource("host_system_tray_sub"),
changeListener = vm::serverSettingChanged
)
}
item {
SwitchPreference(
preference = vm.webUIEnabled,
title = stringResource("host_webui"),
subtitle = stringResource("host_webui_sub"),
changeListener = vm::serverSettingChanged
)
}
item {
val webUIEnabled by vm.webUIEnabled.collectAsState()
SwitchPreference(
preference = vm.openInBrowserEnabled,
title = stringResource("host_open_in_browser"),
subtitle = stringResource("host_open_in_browser_sub"),
changeListener = vm::serverSettingChanged,
enabled = webUIEnabled
)
}
item {
SwitchPreference(
preference = vm.basicAuthEnabled,
title = stringResource("basic_auth"),
subtitle = stringResource("host_basic_auth_sub"),
changeListener = vm::serverSettingChanged
)
}
item {
EditTextPreference(
preference = vm.basicAuthUsername,
title = stringResource("host_basic_auth_username"),
changeListener = vm::serverSettingChanged,
enabled = basicAuthEnabled
)
}
item {
EditTextPreference(
preference = vm.basicAuthPassword,
title = stringResource("host_basic_auth_password"),
changeListener = vm::serverSettingChanged,
visualTransformation = PasswordVisualTransformation(),
enabled = basicAuthEnabled
)
}
}
item {
Divider()
}
item {
EditTextPreference(vm.serverUrl, stringResource("server_url"), subtitle = vm.serverUrl.collectAsState().value)
}
item {
EditTextPreference(vm.serverPort, stringResource("server_port"), subtitle = vm.serverPort.collectAsState().value)
}
item {
PreferenceRow(
stringResource("server_preference_warning"),
Icons.Rounded.Warning,
subtitle = stringResource("server_preference_warning_sub")
)
}
item {
ChoicePreference(vm.proxy, vm.getProxyChoices(), stringResource("server_proxy"))
}
when (proxy) {
Proxy.NO_PROXY -> Unit
Proxy.HTTP_PROXY -> {
item {
EditTextPreference(vm.httpHost, stringResource("http_proxy"), vm.httpHost.collectAsState().value)
when (proxy) {
Proxy.NO_PROXY -> Unit
Proxy.HTTP_PROXY -> {
item {
EditTextPreference(
vm.httpHost,
stringResource("http_proxy"),
vm.httpHost.collectAsState().value
)
}
item {
EditTextPreference(
vm.httpPort,
stringResource("http_port"),
vm.httpPort.collectAsState().value
)
}
}
item {
EditTextPreference(vm.httpPort, stringResource("http_port"), vm.httpPort.collectAsState().value)
Proxy.SOCKS_PROXY -> {
item {
EditTextPreference(
vm.socksHost,
stringResource("socks_proxy"),
vm.socksHost.collectAsState().value
)
}
item {
EditTextPreference(
vm.socksPort,
stringResource("socks_port"),
vm.socksPort.collectAsState().value
)
}
}
}
Proxy.SOCKS_PROXY -> {
item {
ChoicePreference(vm.auth, vm.getAuthChoices(), stringResource("authentication"))
}
if (auth != Auth.NONE) {
item {
EditTextPreference(vm.socksHost, stringResource("socks_proxy"), vm.socksHost.collectAsState().value)
EditTextPreference(vm.authUsername, stringResource("auth_username"))
}
item {
EditTextPreference(vm.socksPort, stringResource("socks_port"), vm.socksPort.collectAsState().value)
EditTextPreference(
vm.authPassword,
stringResource("auth_password"),
visualTransformation = PasswordVisualTransformation()
)
}
}
}
item {
ChoicePreference(vm.auth, vm.getAuthChoices(), stringResource("authentication"))
}
if (auth != Auth.NONE) {
item {
EditTextPreference(vm.authUsername, stringResource("auth_username"))
}
item {
EditTextPreference(vm.authPassword, stringResource("auth_password"), visualTransformation = PasswordVisualTransformation())
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,9 +6,19 @@
package ca.gosyer.ui.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.ui.base.components.MenuController
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.resources.stringResource
@@ -17,7 +27,16 @@ import ca.gosyer.ui.base.resources.stringResource
fun SettingsTrackingScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("settings_tracking_screen"), menuController, true)
LazyColumn {
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -9,6 +9,7 @@ package ca.gosyer.ui.sources
import androidx.compose.animation.Crossfade
import androidx.compose.foundation.TooltipArea
import androidx.compose.foundation.TooltipPlacement
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
@@ -19,6 +20,8 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Icon
import androidx.compose.material.Surface
@@ -108,51 +111,60 @@ fun SourcesSideMenu(
onCloseSourceTabClick: (Source) -> Unit
) {
Surface(elevation = 1.dp) {
LazyColumn(Modifier.fillMaxHeight().width(64.dp)) {
items(sourceTabs) { source ->
TooltipArea(
{
Surface(
modifier = Modifier.shadow(4.dp),
shape = RoundedCornerShape(4.dp),
elevation = 4.dp
) {
Text(source?.name ?: stringResource("sources_home"), modifier = Modifier.padding(10.dp))
}
},
modifier = Modifier.size(64.dp),
tooltipPlacement = TooltipPlacement.CursorPoint(
offset = DpOffset(0.dp, 16.dp)
)
) {
Box(Modifier.fillMaxSize()) {
val modifier = Modifier
.combinedMouseClickable(
onClick = {
onSourceTabClick(source)
},
onMiddleClick = {
if (source != null) {
onCloseSourceTabClick(source)
}
}
)
.requiredSize(50.dp)
.align(Alignment.Center)
if (source != null) {
Box(Modifier.align(Alignment.Center)) {
KamelImage(
lazyPainterResource(source, filterQuality = FilterQuality.Medium),
source.displayName,
modifier
)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxHeight().width(64.dp), state) {
items(sourceTabs) { source ->
TooltipArea(
{
Surface(
modifier = Modifier.shadow(4.dp),
shape = RoundedCornerShape(4.dp),
elevation = 4.dp
) {
Text(source?.name ?: stringResource("sources_home"), modifier = Modifier.padding(10.dp))
}
},
modifier = Modifier.size(64.dp),
tooltipPlacement = TooltipPlacement.CursorPoint(
offset = DpOffset(0.dp, 16.dp)
)
) {
Box(Modifier.fillMaxSize()) {
val modifier = Modifier
.combinedMouseClickable(
onClick = {
onSourceTabClick(source)
},
onMiddleClick = {
if (source != null) {
onCloseSourceTabClick(source)
}
}
)
.requiredSize(50.dp)
.align(Alignment.Center)
if (source != null) {
Box(Modifier.align(Alignment.Center)) {
KamelImage(
lazyPainterResource(source, filterQuality = FilterQuality.Medium),
source.displayName,
modifier
)
}
} else {
Icon(Icons.Rounded.Home, stringResource("sources_home"), modifier = modifier)
}
} else {
Icon(Icons.Rounded.Home, stringResource("sources_home"), modifier = modifier)
}
}
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -96,7 +96,9 @@ fun SourceHomeScreen(
}*/
VerticalScrollbar(
modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
modifier = Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp),
adapter = rememberScrollbarAdapter(state)
)
}

View File

@@ -6,11 +6,15 @@
package ca.gosyer.ui.sources.components
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
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.rememberScrollbarAdapter
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Explore
import androidx.compose.material.icons.rounded.FilterList
@@ -35,6 +39,7 @@ import ca.gosyer.ui.base.vm.viewModel
import ca.gosyer.ui.sources.components.filter.SourceFiltersMenu
import ca.gosyer.util.compose.persistentLazyListState
import com.github.zsoltk.compose.savedinstancestate.Bundle
import com.github.zsoltk.compose.savedinstancestate.BundleScope
import io.kamel.image.lazyPainterResource
@Composable
@@ -85,23 +90,25 @@ fun SourceScreen(
onLoadNextPage = vm::loadNextPage,
onMangaClick = onMangaClick,
)
SourceFiltersMenu(
bundle = bundle,
modifier = Modifier.align(Alignment.TopEnd),
sourceId = source.id,
showFilters = showingFilters && !isLatest,
onSearchClicked = {
vm.setUsingFilters(true)
vm.showingFilters(false)
vm.submitSearch()
},
onResetClicked = {
vm.setUsingFilters(false)
vm.showingFilters(false)
vm.submitSearch()
},
showFiltersButton = vm::enableFilters
)
BundleScope("filters", autoDispose = false) {
SourceFiltersMenu(
bundle = bundle,
modifier = Modifier.align(Alignment.TopEnd),
sourceId = source.id,
showFilters = showingFilters && !isLatest,
onSearchClicked = {
vm.setUsingFilters(true)
vm.showingFilters(false)
vm.submitSearch()
},
onResetClicked = {
vm.setUsingFilters(false)
vm.showingFilters(false)
vm.submitSearch()
},
showFiltersButton = vm::enableFilters
)
}
}
}
}
@@ -186,19 +193,27 @@ private fun MangaTable(
LoadingScreen(isLoading)
} else {
val persistentState = persistentLazyListState(bundle)
LazyVerticalGrid(GridCells.Adaptive(160.dp), state = persistentState) {
itemsIndexed(mangas) { index, manga ->
if (hasNextPage && index == mangas.lastIndex) {
LaunchedEffect(Unit) { onLoadNextPage() }
}
MangaGridItem(
title = manga.title,
cover = lazyPainterResource(manga, filterQuality = FilterQuality.Medium),
onClick = {
onMangaClick(manga.id)
Box {
LazyVerticalGrid(GridCells.Adaptive(160.dp), state = persistentState) {
itemsIndexed(mangas) { index, manga ->
if (hasNextPage && index == mangas.lastIndex) {
LaunchedEffect(Unit) { onLoadNextPage() }
}
)
MangaGridItem(
title = manga.title,
cover = lazyPainterResource(manga, filterQuality = FilterQuality.Medium),
onClick = {
onMangaClick(manga.id)
}
)
}
}
VerticalScrollbar(
rememberScrollbarAdapter(persistentState),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -14,6 +14,7 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.FocusInteraction
import androidx.compose.foundation.interaction.MutableInteractionSource
@@ -31,6 +32,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.Button
import androidx.compose.material.Checkbox
import androidx.compose.material.ContentAlpha
@@ -68,6 +70,7 @@ import ca.gosyer.ui.base.prefs.ExpandablePreference
import ca.gosyer.ui.base.resources.stringResource
import ca.gosyer.ui.base.vm.viewModel
import ca.gosyer.ui.sources.components.filter.model.SourceFiltersView
import ca.gosyer.util.compose.persistentLazyListState
import com.github.zsoltk.compose.savedinstancestate.Bundle
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filterIsInstance
@@ -105,8 +108,8 @@ fun SourceFiltersMenu(
exit = fadeOut() + slideOutHorizontally(targetOffsetX = { it * 2 }),
modifier = modifier
) {
Surface(elevation = 1.dp) {
Column(Modifier.width(360.dp).fillMaxHeight()) {
Surface(elevation = 1.dp, modifier = Modifier.width(360.dp).fillMaxHeight()) {
Column(Modifier.fillMaxSize()) {
Surface(elevation = 4.dp) {
Row(
Modifier.height(56.dp).fillMaxWidth().padding(horizontal = 16.dp),
@@ -122,19 +125,28 @@ fun SourceFiltersMenu(
}
}
val expandedGroups = remember { mutableStateListOf<Int>() }
LazyColumn(Modifier.fillMaxSize()) {
items(
items = filters,
key = { it.filter.hashCode() }
) { item ->
item.toView(startExpanded = item.index in expandedGroups) { expanded, index ->
if (expanded) {
expandedGroups += index
} else {
expandedGroups -= index
Box {
val lazyListState = persistentLazyListState()
LazyColumn(Modifier.fillMaxSize(), lazyListState) {
items(
items = filters,
key = { it.filter.hashCode() }
) { item ->
item.toView(startExpanded = item.index in expandedGroups) { expanded, index ->
if (expanded) {
expandedGroups += index
} else {
expandedGroups -= index
}
}
}
}
VerticalScrollbar(
rememberScrollbarAdapter(lazyListState),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,11 +6,18 @@
package ca.gosyer.ui.sources.settings
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.Checkbox
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Switch
@@ -19,6 +26,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
@@ -61,23 +69,32 @@ fun SourceSettingsMenu(sourceId: Long, menuController: MenuController? = LocalMe
Column {
Toolbar(stringResource("location_settings"), menuController, menuController != null)
LazyColumn {
items(settings, { it.props.hashCode() }) {
when (it) {
is CheckBox, is Switch -> {
TwoStatePreference(it as TwoState, it is CheckBox)
}
is List -> {
ListPreference(it)
}
is EditText -> {
EditTextPreference(it)
}
is MultiSelect -> {
MultiSelectPreference(it)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
items(settings, { it.props.hashCode() }) {
when (it) {
is CheckBox, is Switch -> {
TwoStatePreference(it as TwoState, it is CheckBox)
}
is List -> {
ListPreference(it)
}
is EditText -> {
EditTextPreference(it)
}
is MultiSelect -> {
MultiSelectPreference(it)
}
}
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}

View File

@@ -6,20 +6,26 @@
package ca.gosyer.ui.updates
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
@@ -54,24 +60,33 @@ fun UpdatesMenu(
if (isLoading || updates.isEmpty()) {
LoadingScreen(isLoading)
} else {
LazyColumn {
itemsIndexed(updates) { index, item ->
LaunchedEffect(Unit) {
if (index == updates.lastIndex) {
vm.loadNextPage()
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
itemsIndexed(updates) { index, item ->
LaunchedEffect(Unit) {
if (index == updates.lastIndex) {
vm.loadNextPage()
}
}
val manga = item.manga!!
val chapter = item.chapter
UpdatesItem(
item,
onClickItem = { openChapter(chapter.index, chapter.mangaId) },
onClickCover = { openManga(manga.id) },
onClickDownload = vm::downloadChapter,
onClickDeleteDownload = vm::deleteDownloadedChapter,
onClickStopDownload = vm::stopDownloadingChapter
)
}
val manga = item.manga!!
val chapter = item.chapter
UpdatesItem(
item,
onClickItem = { openChapter(chapter.index, chapter.mangaId) },
onClickCover = { openManga(manga.id) },
onClickDownload = vm::downloadChapter,
onClickDeleteDownload = vm::deleteDownloadedChapter,
onClickStopDownload = vm::stopDownloadingChapter
)
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
}