Initial migration of general reader settings to Compose

This commit is contained in:
arkon
2023-07-10 18:42:35 -04:00
parent 87bdee5990
commit 710ebfb7a5
16 changed files with 373 additions and 354 deletions

View File

@@ -0,0 +1,158 @@
package eu.kanade.presentation.reader.settings
import android.os.Build
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.res.stringResource
import androidx.core.graphics.alpha
import androidx.core.graphics.blue
import androidx.core.graphics.green
import androidx.core.graphics.red
import eu.kanade.presentation.util.collectAsState
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
import tachiyomi.core.preference.getAndSet
import tachiyomi.presentation.core.components.CheckboxItem
import tachiyomi.presentation.core.components.SelectItem
import tachiyomi.presentation.core.components.SliderItem
@Composable
internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) {
val colorFilterModes = buildList {
addAll(
listOf(
R.string.label_default,
R.string.filter_mode_multiply,
R.string.filter_mode_screen,
),
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
addAll(
listOf(
R.string.filter_mode_overlay,
R.string.filter_mode_lighten,
R.string.filter_mode_darken,
),
)
}
}.map { stringResource(it) }
val customBrightness by screenModel.preferences.customBrightness().collectAsState()
CheckboxItem(
label = stringResource(R.string.pref_custom_brightness),
checked = customBrightness,
onClick = {
screenModel.togglePreference(ReaderPreferences::customBrightness)
},
)
/**
* Sets the brightness of the screen. Range is [-75, 100].
* From -75 to -1 a semi-transparent black view is shown at the top with the minimum brightness.
* From 1 to 100 it sets that value as brightness.
* 0 sets system brightness and hides the overlay.
*/
if (customBrightness) {
val customBrightnessValue by screenModel.preferences.customBrightnessValue().collectAsState()
SliderItem(
label = stringResource(R.string.pref_custom_brightness),
min = -75,
max = 100,
value = customBrightnessValue,
valueText = customBrightnessValue.toString(),
onChange = { screenModel.preferences.customBrightnessValue().set(it) },
)
}
val colorFilter by screenModel.preferences.colorFilter().collectAsState()
CheckboxItem(
label = stringResource(R.string.pref_custom_color_filter),
checked = colorFilter,
onClick = {
screenModel.togglePreference(ReaderPreferences::colorFilter)
},
)
if (colorFilter) {
val colorFilterValue by screenModel.preferences.colorFilterValue().collectAsState()
SliderItem(
label = stringResource(R.string.color_filter_r_value),
max = 255,
value = colorFilterValue.red,
valueText = colorFilterValue.red.toString(),
onChange = { newRValue ->
screenModel.preferences.colorFilterValue().getAndSet {
getColorValue(it, newRValue, RED_MASK, 16)
}
},
)
SliderItem(
label = stringResource(R.string.color_filter_g_value),
max = 255,
value = colorFilterValue.green,
valueText = colorFilterValue.green.toString(),
onChange = { newGValue ->
screenModel.preferences.colorFilterValue().getAndSet {
getColorValue(it, newGValue, GREEN_MASK, 8)
}
},
)
SliderItem(
label = stringResource(R.string.color_filter_b_value),
max = 255,
value = colorFilterValue.blue,
valueText = colorFilterValue.blue.toString(),
onChange = { newBValue ->
screenModel.preferences.colorFilterValue().getAndSet {
getColorValue(it, newBValue, BLUE_MASK, 0)
}
},
)
SliderItem(
label = stringResource(R.string.color_filter_a_value),
max = 255,
value = colorFilterValue.alpha,
valueText = colorFilterValue.alpha.toString(),
onChange = { newAValue ->
screenModel.preferences.colorFilterValue().getAndSet {
getColorValue(it, newAValue, ALPHA_MASK, 24)
}
},
)
val colorFilterMode by screenModel.preferences.colorFilterMode().collectAsState()
SelectItem(
label = stringResource(R.string.pref_color_filter_mode),
options = colorFilterModes.toTypedArray(),
selectedIndex = colorFilterMode,
) {
screenModel.preferences.colorFilterMode().set(it)
}
}
val grayscale by screenModel.preferences.grayscale().collectAsState()
CheckboxItem(
label = stringResource(R.string.pref_grayscale),
checked = grayscale,
onClick = {
screenModel.togglePreference(ReaderPreferences::grayscale)
},
)
val invertedColors by screenModel.preferences.invertedColors().collectAsState()
CheckboxItem(
label = stringResource(R.string.pref_inverted_colors),
checked = invertedColors,
onClick = {
screenModel.togglePreference(ReaderPreferences::invertedColors)
},
)
}
private fun getColorValue(currentColor: Int, color: Int, mask: Long, bitShift: Int): Int {
return (color shl bitShift) or (currentColor and mask.inv().toInt())
}
private const val ALPHA_MASK: Long = 0xFF000000
private const val RED_MASK: Long = 0x00FF0000
private const val GREEN_MASK: Long = 0x0000FF00
private const val BLUE_MASK: Long = 0x000000FF

View File

@@ -0,0 +1,96 @@
package eu.kanade.presentation.reader.settings
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.res.stringResource
import eu.kanade.presentation.util.collectAsState
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
import tachiyomi.presentation.core.components.CheckboxItem
import tachiyomi.presentation.core.components.HeadingItem
import tachiyomi.presentation.core.components.RadioItem
@Composable
internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) {
// TODO: show this in a nicer way
HeadingItem(stringResource(R.string.pref_reader_theme))
val readerTheme by screenModel.preferences.readerTheme().collectAsState()
listOf(
R.string.black_background to 1,
R.string.gray_background to 2,
R.string.white_background to 0,
R.string.automatic_background to 3,
).map { (titleRes, theme) ->
RadioItem(
label = stringResource(titleRes),
selected = readerTheme == theme,
onClick = { screenModel.preferences.readerTheme().set(theme) },
)
}
val showPageNumber by screenModel.preferences.showPageNumber().collectAsState()
CheckboxItem(
label = stringResource(R.string.pref_show_page_number),
checked = showPageNumber,
onClick = {
screenModel.togglePreference(ReaderPreferences::showPageNumber)
},
)
val fullscreen by screenModel.preferences.fullscreen().collectAsState()
CheckboxItem(
label = stringResource(R.string.pref_fullscreen),
checked = fullscreen,
onClick = {
screenModel.togglePreference(ReaderPreferences::fullscreen)
},
)
// TODO: hide if there's no cutout
val cutoutShort by screenModel.preferences.cutoutShort().collectAsState()
CheckboxItem(
label = stringResource(R.string.pref_cutout_short),
checked = cutoutShort,
onClick = {
screenModel.togglePreference(ReaderPreferences::cutoutShort)
},
)
val keepScreenOn by screenModel.preferences.keepScreenOn().collectAsState()
CheckboxItem(
label = stringResource(R.string.pref_keep_screen_on),
checked = keepScreenOn,
onClick = {
screenModel.togglePreference(ReaderPreferences::keepScreenOn)
},
)
val readWithLongTap by screenModel.preferences.readWithLongTap().collectAsState()
CheckboxItem(
label = stringResource(R.string.pref_read_with_long_tap),
checked = readWithLongTap,
onClick = {
screenModel.togglePreference(ReaderPreferences::readWithLongTap)
},
)
val alwaysShowChapterTransition by screenModel.preferences.alwaysShowChapterTransition().collectAsState()
CheckboxItem(
label = stringResource(R.string.pref_always_show_chapter_transition),
checked = alwaysShowChapterTransition,
onClick = {
screenModel.togglePreference(ReaderPreferences::alwaysShowChapterTransition)
},
)
val pageTransitions by screenModel.preferences.pageTransitions().collectAsState()
CheckboxItem(
label = stringResource(R.string.pref_page_transitions),
checked = pageTransitions,
onClick = {
screenModel.togglePreference(ReaderPreferences::pageTransitions)
},
)
}

View File

@@ -0,0 +1,66 @@
package eu.kanade.presentation.reader.settings
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.window.DialogWindowProvider
import eu.kanade.presentation.components.TabbedDialog
import eu.kanade.presentation.components.TabbedDialogPaddings
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
@Composable
fun ReaderSettingsDialog(
onDismissRequest: () -> Unit,
onShowMenus: () -> Unit,
onHideMenus: () -> Unit,
screenModel: ReaderSettingsScreenModel,
) {
// TODO: undimming doesn't seem to work
val window = (LocalView.current.parent as? DialogWindowProvider)?.window
val tabTitles = listOf(
stringResource(R.string.pref_category_reading_mode),
stringResource(R.string.pref_category_general),
stringResource(R.string.custom_filter),
)
val pagerState = rememberPagerState { tabTitles.size }
LaunchedEffect(pagerState.currentPage) {
if (pagerState.currentPage == 2) {
window?.setDimAmount(0f)
onHideMenus()
} else {
window?.setDimAmount(0.75f)
onShowMenus()
}
}
TabbedDialog(
onDismissRequest = {
onDismissRequest()
onShowMenus()
},
tabTitles = tabTitles,
pagerState = pagerState,
) { page ->
Column(
modifier = Modifier
.padding(vertical = TabbedDialogPaddings.Vertical)
.verticalScroll(rememberScrollState()),
) {
when (page) {
0 -> ReadingModePage(screenModel)
1 -> GeneralPage(screenModel)
2 -> ColorFilterPage(screenModel)
}
}
}
}

View File

@@ -0,0 +1,10 @@
package eu.kanade.presentation.reader.settings
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.runtime.Composable
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
@Composable
internal fun ColumnScope.ReadingModePage(screenModel: ReaderSettingsScreenModel) {
// TODO
}