(feat) transparency schemes
This commit is contained in:
parent
68874f1d87
commit
167be6e34d
@ -1,6 +1,10 @@
|
|||||||
package de.mm20.launcher2.ui.base
|
package de.mm20.launcher2.ui.base
|
||||||
|
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import de.mm20.launcher2.preferences.IconShape
|
import de.mm20.launcher2.preferences.IconShape
|
||||||
import de.mm20.launcher2.preferences.ui.CardStyle
|
import de.mm20.launcher2.preferences.ui.CardStyle
|
||||||
import de.mm20.launcher2.preferences.ui.GridSettings
|
import de.mm20.launcher2.preferences.ui.GridSettings
|
||||||
@ -9,8 +13,6 @@ import de.mm20.launcher2.ui.component.ProvideIconShape
|
|||||||
import de.mm20.launcher2.ui.locals.LocalCardStyle
|
import de.mm20.launcher2.ui.locals.LocalCardStyle
|
||||||
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
|
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
|
||||||
import de.mm20.launcher2.ui.locals.LocalGridSettings
|
import de.mm20.launcher2.ui.locals.LocalGridSettings
|
||||||
import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme
|
|
||||||
import de.mm20.launcher2.ui.theme.transparency.TransparencyScheme
|
|
||||||
import de.mm20.launcher2.widgets.FavoritesWidget
|
import de.mm20.launcher2.widgets.FavoritesWidget
|
||||||
import de.mm20.launcher2.widgets.WidgetRepository
|
import de.mm20.launcher2.widgets.WidgetRepository
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
@ -48,10 +50,6 @@ fun ProvideSettings(
|
|||||||
LocalCardStyle provides cardStyle,
|
LocalCardStyle provides cardStyle,
|
||||||
LocalFavoritesEnabled provides favoritesEnabled,
|
LocalFavoritesEnabled provides favoritesEnabled,
|
||||||
LocalGridSettings provides gridSettings,
|
LocalGridSettings provides gridSettings,
|
||||||
LocalTransparencyScheme provides TransparencyScheme(
|
|
||||||
background = cardStyle.opacity * 0.85f,
|
|
||||||
surface = cardStyle.opacity,
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
ProvideIconShape(iconShape) {
|
ProvideIconShape(iconShape) {
|
||||||
content()
|
content()
|
||||||
|
|||||||
@ -40,7 +40,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import de.mm20.launcher2.themes.Colors
|
import de.mm20.launcher2.themes.colors.Colors
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
||||||
import de.mm20.launcher2.ui.component.LargeMessage
|
import de.mm20.launcher2.ui.component.LargeMessage
|
||||||
|
|||||||
@ -5,9 +5,8 @@ import android.net.Uri
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import de.mm20.launcher2.preferences.ColorsDescriptor
|
|
||||||
import de.mm20.launcher2.preferences.ui.UiSettings
|
import de.mm20.launcher2.preferences.ui.UiSettings
|
||||||
import de.mm20.launcher2.themes.Colors
|
import de.mm20.launcher2.themes.colors.Colors
|
||||||
import de.mm20.launcher2.themes.ThemeRepository
|
import de.mm20.launcher2.themes.ThemeRepository
|
||||||
import de.mm20.launcher2.themes.fromLegacyJson
|
import de.mm20.launcher2.themes.fromLegacyJson
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -58,9 +57,9 @@ class ImportThemeSheetVM : ViewModel(), KoinComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun importTheme(colors: Colors, apply: Boolean) {
|
private fun importTheme(colors: Colors, apply: Boolean) {
|
||||||
themeRepository.createColors(colors)
|
themeRepository.colors.create(colors)
|
||||||
if (apply) {
|
if (apply) {
|
||||||
uiSettings.setColors(ColorsDescriptor.Custom(colors.id.toString()))
|
uiSettings.setColorsId(colors.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,39 +1,29 @@
|
|||||||
package de.mm20.launcher2.ui.component
|
package de.mm20.launcher2.ui.component
|
||||||
|
|
||||||
import androidx.compose.foundation.BorderStroke
|
import androidx.compose.foundation.BorderStroke
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.shape.CornerSize
|
|
||||||
import androidx.compose.material3.LocalAbsoluteTonalElevation
|
|
||||||
import androidx.compose.material3.LocalContentColor
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.drawBehind
|
|
||||||
import androidx.compose.ui.draw.drawWithCache
|
|
||||||
import androidx.compose.ui.draw.shadow
|
|
||||||
import androidx.compose.ui.geometry.Offset
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.RectangleShape
|
|
||||||
import androidx.compose.ui.graphics.Shape
|
import androidx.compose.ui.graphics.Shape
|
||||||
import androidx.compose.ui.graphics.drawOutline
|
|
||||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
|
||||||
import androidx.compose.ui.graphics.drawscope.withTransform
|
|
||||||
import androidx.compose.ui.unit.Density
|
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import de.mm20.launcher2.ui.locals.LocalCardStyle
|
import de.mm20.launcher2.ui.locals.LocalCardStyle
|
||||||
import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme
|
import de.mm20.launcher2.ui.theme.transparency.transparency
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LauncherCard(
|
fun LauncherCard(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
elevation: Dp = 2.dp,
|
elevation: Dp = 2.dp,
|
||||||
backgroundOpacity: Float = LocalTransparencyScheme.current.surface,
|
backgroundOpacity: Float = MaterialTheme.transparency.surface,
|
||||||
shape: Shape = MaterialTheme.shapes.medium,
|
shape: Shape = MaterialTheme.shapes.medium,
|
||||||
color: Color = MaterialTheme.colorScheme.surface.copy(alpha = backgroundOpacity.coerceIn(0f, 1f)),
|
color: Color = MaterialTheme.colorScheme.surface.copy(
|
||||||
|
alpha = backgroundOpacity.coerceIn(
|
||||||
|
0f,
|
||||||
|
1f
|
||||||
|
)
|
||||||
|
),
|
||||||
border: BorderStroke? = LocalCardStyle.current.borderWidth.takeIf { it > 0 }
|
border: BorderStroke? = LocalCardStyle.current.borderWidth.takeIf { it > 0 }
|
||||||
?.let { BorderStroke(it.dp, MaterialTheme.colorScheme.surface) },
|
?.let { BorderStroke(it.dp, MaterialTheme.colorScheme.surface) },
|
||||||
content: @Composable () -> Unit = {}
|
content: @Composable () -> Unit = {}
|
||||||
@ -49,149 +39,3 @@ fun LauncherCard(
|
|||||||
tonalElevation = elevation,
|
tonalElevation = elevation,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun PartialLauncherCard(
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
isTop: Boolean = false,
|
|
||||||
isBottom: Boolean = false,
|
|
||||||
elevation: Dp = 2.dp,
|
|
||||||
backgroundOpacity: Float = LocalTransparencyScheme.current.surface,
|
|
||||||
content: @Composable () -> Unit
|
|
||||||
) {
|
|
||||||
|
|
||||||
if (isTop && isBottom) {
|
|
||||||
LauncherCard(modifier = modifier, content = content)
|
|
||||||
} else if (!isTop && !isBottom) {
|
|
||||||
CardMiddlePiece(modifier = modifier, elevation = elevation, content = content)
|
|
||||||
} else {
|
|
||||||
CardEndPiece(
|
|
||||||
modifier = modifier,
|
|
||||||
isTop = isTop,
|
|
||||||
isBottom = isBottom,
|
|
||||||
elevation = elevation,
|
|
||||||
backgroundOpacity = backgroundOpacity,
|
|
||||||
content = content
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun CardMiddlePiece(
|
|
||||||
modifier: Modifier,
|
|
||||||
elevation: Dp,
|
|
||||||
backgroundOpacity: Float = LocalTransparencyScheme.current.surface,
|
|
||||||
content: @Composable () -> Unit
|
|
||||||
) {
|
|
||||||
val borderWidth = LocalCardStyle.current.borderWidth.dp
|
|
||||||
val borderColor = MaterialTheme.colorScheme.surface
|
|
||||||
|
|
||||||
val absoluteElevation = LocalAbsoluteTonalElevation.current + elevation
|
|
||||||
Box(
|
|
||||||
modifier = modifier
|
|
||||||
.shadow(if (backgroundOpacity < 1f) 0.dp else elevation, RectangleShape, true)
|
|
||||||
.background(
|
|
||||||
if (backgroundOpacity == 1f) {
|
|
||||||
MaterialTheme.colorScheme.surfaceColorAtElevation(absoluteElevation)
|
|
||||||
} else {
|
|
||||||
MaterialTheme.colorScheme.surface.copy(
|
|
||||||
alpha = backgroundOpacity.coerceIn(
|
|
||||||
0f,
|
|
||||||
1f
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.drawBehind {
|
|
||||||
if (borderWidth == 0.dp) return@drawBehind
|
|
||||||
val border = borderWidth.toPx()
|
|
||||||
drawRect(
|
|
||||||
color = borderColor,
|
|
||||||
topLeft = Offset.Zero,
|
|
||||||
size = size.copy(width = border)
|
|
||||||
)
|
|
||||||
drawRect(
|
|
||||||
color = borderColor,
|
|
||||||
topLeft = Offset(size.width - border, 0f),
|
|
||||||
size = size.copy(width = border)
|
|
||||||
)
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
CompositionLocalProvider(
|
|
||||||
LocalContentColor provides MaterialTheme.colorScheme.onSurface,
|
|
||||||
LocalAbsoluteTonalElevation provides absoluteElevation,
|
|
||||||
) {
|
|
||||||
content()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun CardEndPiece(
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
isTop: Boolean,
|
|
||||||
isBottom: Boolean,
|
|
||||||
elevation: Dp,
|
|
||||||
backgroundOpacity: Float,
|
|
||||||
content: @Composable () -> Unit,
|
|
||||||
) {
|
|
||||||
val shape = when {
|
|
||||||
isTop -> MaterialTheme.shapes.medium.copy(
|
|
||||||
bottomEnd = CornerSize(0),
|
|
||||||
bottomStart = CornerSize(0),
|
|
||||||
)
|
|
||||||
isBottom -> MaterialTheme.shapes.medium.copy(
|
|
||||||
topEnd = CornerSize(0),
|
|
||||||
topStart = CornerSize(0),
|
|
||||||
)
|
|
||||||
else -> RectangleShape
|
|
||||||
}
|
|
||||||
|
|
||||||
val borderWidth = LocalCardStyle.current.borderWidth.dp
|
|
||||||
val borderColor = MaterialTheme.colorScheme.surface
|
|
||||||
|
|
||||||
val absoluteElevation = LocalAbsoluteTonalElevation.current + elevation
|
|
||||||
Box(
|
|
||||||
modifier = modifier
|
|
||||||
.shadow(if (backgroundOpacity < 1f) 0.dp else elevation, shape, true)
|
|
||||||
.background(
|
|
||||||
if (backgroundOpacity == 1f) {
|
|
||||||
MaterialTheme.colorScheme.surfaceColorAtElevation(absoluteElevation)
|
|
||||||
} else {
|
|
||||||
MaterialTheme.colorScheme.surface.copy(
|
|
||||||
alpha = backgroundOpacity.coerceIn(
|
|
||||||
0f,
|
|
||||||
1f
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.drawWithCache {
|
|
||||||
val border = borderWidth.toPx()
|
|
||||||
val outline = shape.createOutline(
|
|
||||||
size.copy(height = size.height + border),
|
|
||||||
layoutDirection,
|
|
||||||
Density(density, fontScale)
|
|
||||||
)
|
|
||||||
onDrawBehind {
|
|
||||||
if (borderWidth == 0.dp) return@onDrawBehind
|
|
||||||
withTransform({
|
|
||||||
translate(0f, if (isBottom) -border else 0f)
|
|
||||||
}) {
|
|
||||||
drawOutline(
|
|
||||||
outline,
|
|
||||||
borderColor,
|
|
||||||
style = Stroke(width = border * 2)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
CompositionLocalProvider(
|
|
||||||
LocalContentColor provides MaterialTheme.colorScheme.onSurface,
|
|
||||||
LocalAbsoluteTonalElevation provides absoluteElevation,
|
|
||||||
) {
|
|
||||||
content()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -45,7 +45,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import de.mm20.launcher2.preferences.SearchBarStyle
|
import de.mm20.launcher2.preferences.SearchBarStyle
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.layout.BottomReversed
|
import de.mm20.launcher2.ui.layout.BottomReversed
|
||||||
import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme
|
import de.mm20.launcher2.ui.theme.transparency.transparency
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SearchBar(
|
fun SearchBar(
|
||||||
@ -102,7 +102,7 @@ fun SearchBar(
|
|||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
when {
|
when {
|
||||||
it == SearchBarLevel.Active -> LocalTransparencyScheme.current.surface
|
it == SearchBarLevel.Active -> MaterialTheme.transparency.surface
|
||||||
style != SearchBarStyle.Transparent -> 1f
|
style != SearchBarStyle.Transparent -> 1f
|
||||||
it == SearchBarLevel.Resting -> 0f
|
it == SearchBarLevel.Resting -> 0f
|
||||||
else -> 1f
|
else -> 1f
|
||||||
|
|||||||
@ -100,7 +100,7 @@ import de.mm20.launcher2.ui.launcher.helper.WallpaperBlur
|
|||||||
import de.mm20.launcher2.ui.launcher.search.SearchVM
|
import de.mm20.launcher2.ui.launcher.search.SearchVM
|
||||||
import de.mm20.launcher2.ui.launcher.search.filters.KeyboardFilterBar
|
import de.mm20.launcher2.ui.launcher.search.filters.KeyboardFilterBar
|
||||||
import de.mm20.launcher2.ui.launcher.searchbar.LauncherSearchBar
|
import de.mm20.launcher2.ui.launcher.searchbar.LauncherSearchBar
|
||||||
import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme
|
import de.mm20.launcher2.ui.theme.transparency.transparency
|
||||||
import dev.chrisbanes.haze.hazeEffect
|
import dev.chrisbanes.haze.hazeEffect
|
||||||
import dev.chrisbanes.haze.hazeSource
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import dev.chrisbanes.haze.rememberHazeState
|
import dev.chrisbanes.haze.rememberHazeState
|
||||||
@ -1416,7 +1416,7 @@ internal fun LauncherScaffold(
|
|||||||
.homePageAnimation(
|
.homePageAnimation(
|
||||||
state,
|
state,
|
||||||
if (config.homeComponent.drawBackground) {
|
if (config.homeComponent.drawBackground) {
|
||||||
config.backgroundColor.copy(alpha = LocalTransparencyScheme.current.background)
|
config.backgroundColor.copy(alpha = MaterialTheme.transparency.background)
|
||||||
} else {
|
} else {
|
||||||
Color.Transparent
|
Color.Transparent
|
||||||
}
|
}
|
||||||
@ -1516,7 +1516,7 @@ internal fun LauncherScaffold(
|
|||||||
blurRadius = 4.dp
|
blurRadius = 4.dp
|
||||||
}
|
}
|
||||||
.background(
|
.background(
|
||||||
MaterialTheme.colorScheme.surfaceContainer.copy(alpha = LocalTransparencyScheme.current.background)
|
MaterialTheme.colorScheme.surfaceContainer.copy(alpha = MaterialTheme.transparency.background)
|
||||||
)
|
)
|
||||||
.statusBarsPadding()
|
.statusBarsPadding()
|
||||||
)
|
)
|
||||||
@ -1536,7 +1536,7 @@ internal fun LauncherScaffold(
|
|||||||
blurRadius = 4.dp
|
blurRadius = 4.dp
|
||||||
}
|
}
|
||||||
.background(
|
.background(
|
||||||
MaterialTheme.colorScheme.surfaceContainer.copy(alpha = LocalTransparencyScheme.current.background)
|
MaterialTheme.colorScheme.surfaceContainer.copy(alpha = MaterialTheme.transparency.background)
|
||||||
)
|
)
|
||||||
.navigationBarsPadding()
|
.navigationBarsPadding()
|
||||||
)
|
)
|
||||||
@ -1583,7 +1583,7 @@ private fun SecondaryPage(
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.secondaryPageAnimation(
|
.secondaryPageAnimation(
|
||||||
state,
|
state,
|
||||||
config.backgroundColor.copy(alpha = LocalTransparencyScheme.current.background),
|
config.backgroundColor.copy(alpha = MaterialTheme.transparency.background),
|
||||||
)
|
)
|
||||||
val composable = composables[component]
|
val composable = composables[component]
|
||||||
|
|
||||||
|
|||||||
@ -53,7 +53,7 @@ import de.mm20.launcher2.ui.launcher.sheets.HiddenItemsSheet
|
|||||||
import de.mm20.launcher2.ui.launcher.sheets.LocalBottomSheetManager
|
import de.mm20.launcher2.ui.launcher.sheets.LocalBottomSheetManager
|
||||||
import de.mm20.launcher2.ui.locals.LocalCardStyle
|
import de.mm20.launcher2.ui.locals.LocalCardStyle
|
||||||
import de.mm20.launcher2.ui.locals.LocalGridSettings
|
import de.mm20.launcher2.ui.locals.LocalGridSettings
|
||||||
import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme
|
import de.mm20.launcher2.ui.theme.transparency.transparency
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SearchColumn(
|
fun SearchColumn(
|
||||||
@ -370,7 +370,7 @@ fun LazyListScope.SingleResult(
|
|||||||
vertical = 4.dp,
|
vertical = 4.dp,
|
||||||
),
|
),
|
||||||
color = if (highlight) MaterialTheme.colorScheme.secondaryContainer
|
color = if (highlight) MaterialTheme.colorScheme.secondaryContainer
|
||||||
else MaterialTheme.colorScheme.surface.copy(LocalTransparencyScheme.current.surface)
|
else MaterialTheme.colorScheme.surface.copy(MaterialTheme.transparency.surface)
|
||||||
) {
|
) {
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,6 +78,7 @@ import de.mm20.launcher2.ui.launcher.transitions.HandleEnterHomeTransition
|
|||||||
import de.mm20.launcher2.ui.locals.LocalGridSettings
|
import de.mm20.launcher2.ui.locals.LocalGridSettings
|
||||||
import de.mm20.launcher2.ui.locals.LocalWindowSize
|
import de.mm20.launcher2.ui.locals.LocalWindowSize
|
||||||
import de.mm20.launcher2.ui.overlays.Overlay
|
import de.mm20.launcher2.ui.overlays.Overlay
|
||||||
|
import de.mm20.launcher2.ui.theme.transparency.transparency
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
|
||||||
@ -266,7 +267,7 @@ fun ItemPopup(origin: IntRect, searchable: Searchable, onDismissRequest: () -> U
|
|||||||
) {
|
) {
|
||||||
LauncherCard(
|
LauncherCard(
|
||||||
elevation = 8.dp * animationProgress.value,
|
elevation = 8.dp * animationProgress.value,
|
||||||
backgroundOpacity = 1f,
|
backgroundOpacity = MaterialTheme.transparency.elevatedSurface,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.placeOverlay(
|
.placeOverlay(
|
||||||
origin.translate(
|
origin.translate(
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import de.mm20.launcher2.search.SavableSearchable
|
import de.mm20.launcher2.search.SavableSearchable
|
||||||
import de.mm20.launcher2.ui.ktx.withCorners
|
import de.mm20.launcher2.ui.ktx.withCorners
|
||||||
import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme
|
import de.mm20.launcher2.ui.theme.transparency.transparency
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
|
|
||||||
fun <T : SavableSearchable> LazyListScope.GridResults(
|
fun <T : SavableSearchable> LazyListScope.GridResults(
|
||||||
@ -39,7 +39,7 @@ fun <T : SavableSearchable> LazyListScope.GridResults(
|
|||||||
bottom = if (!reverse && isBottom) 8.dp else 0.dp,
|
bottom = if (!reverse && isBottom) 8.dp else 0.dp,
|
||||||
)
|
)
|
||||||
.background(
|
.background(
|
||||||
MaterialTheme.colorScheme.surface.copy(alpha = LocalTransparencyScheme.current.surface),
|
MaterialTheme.colorScheme.surface.copy(alpha = MaterialTheme.transparency.surface),
|
||||||
MaterialTheme.shapes.medium.withCorners(
|
MaterialTheme.shapes.medium.withCorners(
|
||||||
topStart = isTop,
|
topStart = isTop,
|
||||||
topEnd = isTop,
|
topEnd = isTop,
|
||||||
@ -72,7 +72,7 @@ fun <T : SavableSearchable> LazyListScope.GridResults(
|
|||||||
bottom = if (!reverse && isLast) 8.dp else 0.dp,
|
bottom = if (!reverse && isLast) 8.dp else 0.dp,
|
||||||
)
|
)
|
||||||
.background(
|
.background(
|
||||||
MaterialTheme.colorScheme.surface.copy(alpha = LocalTransparencyScheme.current.surface),
|
MaterialTheme.colorScheme.surface.copy(alpha = MaterialTheme.transparency.surface),
|
||||||
MaterialTheme.shapes.medium.withCorners(
|
MaterialTheme.shapes.medium.withCorners(
|
||||||
topStart = isFirst && !reverse || isLast && reverse,
|
topStart = isFirst && !reverse || isLast && reverse,
|
||||||
topEnd = isFirst && !reverse || isLast && reverse,
|
topEnd = isFirst && !reverse || isLast && reverse,
|
||||||
@ -120,7 +120,7 @@ fun <T : SavableSearchable> LazyListScope.GridResults(
|
|||||||
bottom = if (!reverse) 8.dp else 0.dp,
|
bottom = if (!reverse) 8.dp else 0.dp,
|
||||||
)
|
)
|
||||||
.background(
|
.background(
|
||||||
MaterialTheme.colorScheme.surface.copy(alpha = LocalTransparencyScheme.current.surface),
|
MaterialTheme.colorScheme.surface.copy(alpha = MaterialTheme.transparency.surface),
|
||||||
MaterialTheme.shapes.medium.withCorners(
|
MaterialTheme.shapes.medium.withCorners(
|
||||||
topStart = isTop,
|
topStart = isTop,
|
||||||
topEnd = isTop,
|
topEnd = isTop,
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package de.mm20.launcher2.ui.launcher.search.common.list
|
package de.mm20.launcher2.ui.launcher.search.common.list
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
|
||||||
import androidx.compose.animation.core.animateDp
|
import androidx.compose.animation.core.animateDp
|
||||||
import androidx.compose.animation.core.animateFloat
|
import androidx.compose.animation.core.animateFloat
|
||||||
import androidx.compose.animation.core.updateTransition
|
import androidx.compose.animation.core.updateTransition
|
||||||
@ -12,7 +11,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyItemScope
|
import androidx.compose.foundation.lazy.LazyItemScope
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.material3.HorizontalDivider
|
|
||||||
import androidx.compose.material3.LocalContentColor
|
import androidx.compose.material3.LocalContentColor
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@ -22,10 +20,9 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import de.mm20.launcher2.search.SavableSearchable
|
import de.mm20.launcher2.search.SavableSearchable
|
||||||
import de.mm20.launcher2.ui.ktx.animateCorners
|
|
||||||
import de.mm20.launcher2.ui.ktx.animateShapeAsState
|
import de.mm20.launcher2.ui.ktx.animateShapeAsState
|
||||||
import de.mm20.launcher2.ui.layout.BottomReversed
|
import de.mm20.launcher2.ui.layout.BottomReversed
|
||||||
import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme
|
import de.mm20.launcher2.ui.theme.transparency.transparency
|
||||||
|
|
||||||
fun <T : SavableSearchable> LazyListScope.ListResults(
|
fun <T : SavableSearchable> LazyListScope.ListResults(
|
||||||
key: String,
|
key: String,
|
||||||
@ -101,12 +98,13 @@ fun LazyItemScope.ListItemSurface(
|
|||||||
content: @Composable ColumnScope.() -> Unit,
|
content: @Composable ColumnScope.() -> Unit,
|
||||||
) {
|
) {
|
||||||
val transition = updateTransition(isExpanded)
|
val transition = updateTransition(isExpanded)
|
||||||
val elevation by transition.animateDp {
|
|
||||||
if (it) 2.dp else 0.dp
|
|
||||||
}
|
|
||||||
val backgroundAlpha by transition.animateFloat {
|
val backgroundAlpha by transition.animateFloat {
|
||||||
if (it) 1f else LocalTransparencyScheme.current.surface
|
if (it) MaterialTheme.transparency.elevatedSurface else MaterialTheme.transparency.surface
|
||||||
}
|
}
|
||||||
|
val elevation by transition.animateDp {
|
||||||
|
if (it && backgroundAlpha == 1f) 2.dp else 0.dp
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val padding by transition.animateDp {
|
val padding by transition.animateDp {
|
||||||
if (it) 8.dp else 1.dp
|
if (it) 8.dp else 1.dp
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import de.mm20.launcher2.ui.common.FavoritesTagSelector
|
|||||||
import de.mm20.launcher2.ui.component.Banner
|
import de.mm20.launcher2.ui.component.Banner
|
||||||
import de.mm20.launcher2.ui.launcher.search.common.grid.SearchResultGrid
|
import de.mm20.launcher2.ui.launcher.search.common.grid.SearchResultGrid
|
||||||
import de.mm20.launcher2.ui.layout.BottomReversed
|
import de.mm20.launcher2.ui.layout.BottomReversed
|
||||||
import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme
|
import de.mm20.launcher2.ui.theme.transparency.transparency
|
||||||
|
|
||||||
fun LazyListScope.SearchFavorites(
|
fun LazyListScope.SearchFavorites(
|
||||||
favorites: List<SavableSearchable>,
|
favorites: List<SavableSearchable>,
|
||||||
@ -47,7 +47,7 @@ fun LazyListScope.SearchFavorites(
|
|||||||
)
|
)
|
||||||
.background(
|
.background(
|
||||||
MaterialTheme.colorScheme.surface.copy(
|
MaterialTheme.colorScheme.surface.copy(
|
||||||
LocalTransparencyScheme.current.surface
|
MaterialTheme.transparency.surface
|
||||||
),
|
),
|
||||||
MaterialTheme.shapes.medium
|
MaterialTheme.shapes.medium
|
||||||
)
|
)
|
||||||
|
|||||||
@ -72,7 +72,7 @@ import de.mm20.launcher2.permissions.PermissionsManager
|
|||||||
import de.mm20.launcher2.plugin.PluginRepository
|
import de.mm20.launcher2.plugin.PluginRepository
|
||||||
import de.mm20.launcher2.plugin.PluginType
|
import de.mm20.launcher2.plugin.PluginType
|
||||||
import de.mm20.launcher2.search.calendar.CalendarListType
|
import de.mm20.launcher2.search.calendar.CalendarListType
|
||||||
import de.mm20.launcher2.themes.atTone
|
import de.mm20.launcher2.themes.colors.atTone
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.base.LocalAppWidgetHost
|
import de.mm20.launcher2.ui.base.LocalAppWidgetHost
|
||||||
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
||||||
@ -95,7 +95,6 @@ import de.mm20.launcher2.widgets.NotesWidget
|
|||||||
import de.mm20.launcher2.widgets.WeatherWidget
|
import de.mm20.launcher2.widgets.WeatherWidget
|
||||||
import de.mm20.launcher2.widgets.Widget
|
import de.mm20.launcher2.widgets.Widget
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import org.koin.androidx.compose.get
|
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
import java.time.ZonedDateTime
|
import java.time.ZonedDateTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|||||||
@ -41,7 +41,7 @@ import de.mm20.launcher2.ui.launcher.widgets.favorites.FavoritesWidget
|
|||||||
import de.mm20.launcher2.ui.launcher.widgets.music.MusicWidget
|
import de.mm20.launcher2.ui.launcher.widgets.music.MusicWidget
|
||||||
import de.mm20.launcher2.ui.launcher.widgets.notes.NotesWidget
|
import de.mm20.launcher2.ui.launcher.widgets.notes.NotesWidget
|
||||||
import de.mm20.launcher2.ui.launcher.widgets.weather.WeatherWidget
|
import de.mm20.launcher2.ui.launcher.widgets.weather.WeatherWidget
|
||||||
import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme
|
import de.mm20.launcher2.ui.theme.transparency.transparency
|
||||||
import de.mm20.launcher2.widgets.AppWidget
|
import de.mm20.launcher2.widgets.AppWidget
|
||||||
import de.mm20.launcher2.widgets.CalendarWidget
|
import de.mm20.launcher2.widgets.CalendarWidget
|
||||||
import de.mm20.launcher2.widgets.FavoritesWidget
|
import de.mm20.launcher2.widgets.FavoritesWidget
|
||||||
@ -73,7 +73,7 @@ fun WidgetItem(
|
|||||||
} else null
|
} else null
|
||||||
|
|
||||||
val backgroundOpacity by animateFloatAsState(
|
val backgroundOpacity by animateFloatAsState(
|
||||||
if (widget is AppWidget && !widget.config.background && !editMode) 0f else LocalTransparencyScheme.current.surface,
|
if (widget is AppWidget && !widget.config.background && !editMode) 0f else MaterialTheme.transparency.surface,
|
||||||
label = "widgetCardBackgroundOpacity",
|
label = "widgetCardBackgroundOpacity",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -87,7 +87,7 @@ import de.mm20.launcher2.ui.ktx.conditional
|
|||||||
import de.mm20.launcher2.ui.launcher.transitions.EnterHomeTransitionParams
|
import de.mm20.launcher2.ui.launcher.transitions.EnterHomeTransitionParams
|
||||||
import de.mm20.launcher2.ui.launcher.transitions.HandleEnterHomeTransition
|
import de.mm20.launcher2.ui.launcher.transitions.HandleEnterHomeTransition
|
||||||
import de.mm20.launcher2.ui.locals.LocalWindowSize
|
import de.mm20.launcher2.ui.locals.LocalWindowSize
|
||||||
import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme
|
import de.mm20.launcher2.ui.theme.transparency.transparency
|
||||||
import de.mm20.launcher2.widgets.MusicWidget
|
import de.mm20.launcher2.widgets.MusicWidget
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
@ -352,7 +352,7 @@ fun MusicWidget(widget: MusicWidget) {
|
|||||||
) {
|
) {
|
||||||
FilledTonalIconButton(
|
FilledTonalIconButton(
|
||||||
colors = IconButtonDefaults.filledTonalIconButtonColors(
|
colors = IconButtonDefaults.filledTonalIconButtonColors(
|
||||||
containerColor = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = LocalTransparencyScheme.current.surface),
|
containerColor = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = MaterialTheme.transparency.surface),
|
||||||
),
|
),
|
||||||
onClick = { viewModel.togglePause() },
|
onClick = { viewModel.togglePause() },
|
||||||
) {
|
) {
|
||||||
|
|||||||
@ -86,7 +86,7 @@ import de.mm20.launcher2.ui.component.MissingPermissionBanner
|
|||||||
import de.mm20.launcher2.ui.component.Tooltip
|
import de.mm20.launcher2.ui.component.Tooltip
|
||||||
import de.mm20.launcher2.ui.component.weather.AnimatedWeatherIcon
|
import de.mm20.launcher2.ui.component.weather.AnimatedWeatherIcon
|
||||||
import de.mm20.launcher2.ui.component.weather.WeatherIcon
|
import de.mm20.launcher2.ui.component.weather.WeatherIcon
|
||||||
import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme
|
import de.mm20.launcher2.ui.theme.transparency.transparency
|
||||||
import de.mm20.launcher2.weather.DailyForecast
|
import de.mm20.launcher2.weather.DailyForecast
|
||||||
import de.mm20.launcher2.weather.Forecast
|
import de.mm20.launcher2.weather.Forecast
|
||||||
import de.mm20.launcher2.widgets.WeatherWidget
|
import de.mm20.launcher2.widgets.WeatherWidget
|
||||||
@ -187,7 +187,7 @@ fun WeatherWidget(widget: WeatherWidget) {
|
|||||||
val currentDayForecasts by viewModel.currentDayForecasts
|
val currentDayForecasts by viewModel.currentDayForecasts
|
||||||
|
|
||||||
Surface(
|
Surface(
|
||||||
color = MaterialTheme.colorScheme.surfaceContainer.copy(alpha = LocalTransparencyScheme.current.surface),
|
color = MaterialTheme.colorScheme.surfaceContainer.copy(alpha = MaterialTheme.transparency.surface),
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
@ -299,7 +299,7 @@ fun CurrentWeather(forecast: Forecast, imperialUnits: Boolean) {
|
|||||||
topEnd = CornerSize(0),
|
topEnd = CornerSize(0),
|
||||||
bottomEnd = CornerSize(0)
|
bottomEnd = CornerSize(0)
|
||||||
),
|
),
|
||||||
color = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = LocalTransparencyScheme.current.surface),
|
color = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = MaterialTheme.transparency.surface),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "${forecast.provider} (${
|
text = "${forecast.provider} (${
|
||||||
|
|||||||
@ -80,6 +80,10 @@ import de.mm20.launcher2.ui.settings.shapes.ShapeSchemeSettingsScreen
|
|||||||
import de.mm20.launcher2.ui.settings.shapes.ShapeSchemesSettingsScreen
|
import de.mm20.launcher2.ui.settings.shapes.ShapeSchemesSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.tags.TagsSettingsScreen
|
import de.mm20.launcher2.ui.settings.tags.TagsSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.tasks.TasksIntegrationSettingsScreen
|
import de.mm20.launcher2.ui.settings.tasks.TasksIntegrationSettingsScreen
|
||||||
|
import de.mm20.launcher2.ui.settings.transparencies.TransparencySchemeSettingsRoute
|
||||||
|
import de.mm20.launcher2.ui.settings.transparencies.TransparencySchemeSettingsScreen
|
||||||
|
import de.mm20.launcher2.ui.settings.transparencies.TransparencySchemesSettingsRoute
|
||||||
|
import de.mm20.launcher2.ui.settings.transparencies.TransparencySchemesSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.unitconverter.UnitConverterHelpSettingsScreen
|
import de.mm20.launcher2.ui.settings.unitconverter.UnitConverterHelpSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.unitconverter.UnitConverterSettingsScreen
|
import de.mm20.launcher2.ui.settings.unitconverter.UnitConverterSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.weather.WeatherIntegrationSettingsScreen
|
import de.mm20.launcher2.ui.settings.weather.WeatherIntegrationSettingsScreen
|
||||||
@ -206,6 +210,14 @@ class SettingsActivity : BaseActivity() {
|
|||||||
} ?: return@composable
|
} ?: return@composable
|
||||||
ShapeSchemeSettingsScreen(id)
|
ShapeSchemeSettingsScreen(id)
|
||||||
}
|
}
|
||||||
|
composable<TransparencySchemesSettingsRoute> {
|
||||||
|
TransparencySchemesSettingsScreen()
|
||||||
|
}
|
||||||
|
composable<TransparencySchemeSettingsRoute> {
|
||||||
|
val route: TransparencySchemeSettingsRoute = it.toRoute()
|
||||||
|
?: return@composable
|
||||||
|
TransparencySchemeSettingsScreen(UUID.fromString(route.id))
|
||||||
|
}
|
||||||
composable("settings/appearance/cards") {
|
composable("settings/appearance/cards") {
|
||||||
CardsSettingsScreen()
|
CardsSettingsScreen()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import androidx.compose.material.icons.Icons
|
|||||||
import androidx.compose.material.icons.rounded.ArrowCircleDown
|
import androidx.compose.material.icons.rounded.ArrowCircleDown
|
||||||
import androidx.compose.material.icons.rounded.ArrowCircleUp
|
import androidx.compose.material.icons.rounded.ArrowCircleUp
|
||||||
import androidx.compose.material.icons.rounded.CropSquare
|
import androidx.compose.material.icons.rounded.CropSquare
|
||||||
|
import androidx.compose.material.icons.rounded.Opacity
|
||||||
import androidx.compose.material.icons.rounded.Palette
|
import androidx.compose.material.icons.rounded.Palette
|
||||||
import androidx.compose.material.icons.rounded.TextFields
|
import androidx.compose.material.icons.rounded.TextFields
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@ -27,6 +28,7 @@ import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
|||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
||||||
import de.mm20.launcher2.ui.component.preferences.value
|
import de.mm20.launcher2.ui.component.preferences.value
|
||||||
import de.mm20.launcher2.ui.locals.LocalNavController
|
import de.mm20.launcher2.ui.locals.LocalNavController
|
||||||
|
import de.mm20.launcher2.ui.settings.transparencies.TransparencySchemesSettingsRoute
|
||||||
import de.mm20.launcher2.ui.theme.getTypography
|
import de.mm20.launcher2.ui.theme.getTypography
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -36,6 +38,7 @@ fun AppearanceSettingsScreen() {
|
|||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
val colorThemeName by viewModel.colorThemeName.collectAsStateWithLifecycle(null)
|
val colorThemeName by viewModel.colorThemeName.collectAsStateWithLifecycle(null)
|
||||||
val shapeThemeName by viewModel.shapeThemeName.collectAsStateWithLifecycle(null)
|
val shapeThemeName by viewModel.shapeThemeName.collectAsStateWithLifecycle(null)
|
||||||
|
val transparencyThemeName by viewModel.transparencyThemeName.collectAsStateWithLifecycle(null)
|
||||||
val compatModeColors by viewModel.compatModeColors.collectAsState()
|
val compatModeColors by viewModel.compatModeColors.collectAsState()
|
||||||
|
|
||||||
val importLauncher = rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) {
|
val importLauncher = rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) {
|
||||||
@ -101,6 +104,14 @@ fun AppearanceSettingsScreen() {
|
|||||||
},
|
},
|
||||||
icon = Icons.Rounded.CropSquare,
|
icon = Icons.Rounded.CropSquare,
|
||||||
)
|
)
|
||||||
|
Preference(
|
||||||
|
title = stringResource(id = R.string.preference_screen_transparencies),
|
||||||
|
summary = transparencyThemeName,
|
||||||
|
onClick = {
|
||||||
|
navController?.navigate(TransparencySchemesSettingsRoute)
|
||||||
|
},
|
||||||
|
icon = Icons.Rounded.Opacity,
|
||||||
|
)
|
||||||
|
|
||||||
Preference(
|
Preference(
|
||||||
title = stringResource(R.string.preference_cards),
|
title = stringResource(R.string.preference_cards),
|
||||||
|
|||||||
@ -25,15 +25,22 @@ class AppearanceSettingsScreenVM : ViewModel(), KoinComponent {
|
|||||||
uiSettings.setColorScheme(colorScheme)
|
uiSettings.setColorScheme(colorScheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
val colorThemeName = uiSettings.colors.flatMapLatest {
|
val colorThemeName = uiSettings.colorsId.flatMapLatest {
|
||||||
themeRepository.getColorsOrDefault(it)
|
themeRepository.colors.getOrDefault(it)
|
||||||
}.map {
|
}.map {
|
||||||
it.name
|
it.name
|
||||||
}
|
}
|
||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||||
|
|
||||||
val shapeThemeName = uiSettings.shapes.flatMapLatest {
|
val shapeThemeName = uiSettings.shapesId.flatMapLatest {
|
||||||
themeRepository.getShapesOrDefault(it)
|
themeRepository.shapes.getOrDefault(it)
|
||||||
|
}.map {
|
||||||
|
it.name
|
||||||
|
}
|
||||||
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||||
|
|
||||||
|
val transparencyThemeName = uiSettings.transparenciesId.flatMapLatest {
|
||||||
|
themeRepository.transparencies.getOrDefault(it)
|
||||||
}.map {
|
}.map {
|
||||||
it.name
|
it.name
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.size
|
|||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.rounded.CropSquare
|
import androidx.compose.material.icons.rounded.CropSquare
|
||||||
import androidx.compose.material.icons.rounded.KeyboardArrowDown
|
import androidx.compose.material.icons.rounded.KeyboardArrowDown
|
||||||
|
import androidx.compose.material.icons.rounded.Opacity
|
||||||
import androidx.compose.material.icons.rounded.Palette
|
import androidx.compose.material.icons.rounded.Palette
|
||||||
import androidx.compose.material.icons.rounded.Save
|
import androidx.compose.material.icons.rounded.Save
|
||||||
import androidx.compose.material.icons.rounded.Share
|
import androidx.compose.material.icons.rounded.Share
|
||||||
@ -50,10 +51,11 @@ fun ExportThemeSettingsScreen() {
|
|||||||
|
|
||||||
val colorSchemes by viewModel.colorSchemes.collectAsState(emptyList())
|
val colorSchemes by viewModel.colorSchemes.collectAsState(emptyList())
|
||||||
val shapeThemes by viewModel.shapeSchemes.collectAsState(emptyList())
|
val shapeThemes by viewModel.shapeSchemes.collectAsState(emptyList())
|
||||||
|
val transparencySchemes by viewModel.transparencySchemes.collectAsState(emptyList())
|
||||||
|
|
||||||
val isValidSelection by remember {
|
val isValidSelection by remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
viewModel.colorScheme != null || viewModel.shapeScheme != null
|
viewModel.colorScheme != null || viewModel.shapeScheme != null || viewModel.transparencyScheme != null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,6 +113,17 @@ fun ExportThemeSettingsScreen() {
|
|||||||
viewModel.setShapeScheme(newValue)
|
viewModel.setShapeScheme(newValue)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
ListPreference(
|
||||||
|
stringResource(R.string.preference_screen_transparencies),
|
||||||
|
icon = Icons.Rounded.Opacity,
|
||||||
|
value = viewModel.transparencyScheme,
|
||||||
|
items = listOf(stringResource(R.string.no_selection) to null) + transparencySchemes.map {
|
||||||
|
it.name to it
|
||||||
|
},
|
||||||
|
onValueChanged = { newValue ->
|
||||||
|
viewModel.setTransparencyScheme(newValue)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
|||||||
@ -3,7 +3,6 @@ package de.mm20.launcher2.ui.settings.appearance
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Log
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@ -11,11 +10,11 @@ import androidx.core.content.FileProvider
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import de.mm20.launcher2.ktx.tryStartActivity
|
import de.mm20.launcher2.ktx.tryStartActivity
|
||||||
import de.mm20.launcher2.themes.Colors
|
import de.mm20.launcher2.themes.colors.Colors
|
||||||
import de.mm20.launcher2.themes.Shapes
|
import de.mm20.launcher2.themes.shapes.Shapes
|
||||||
import de.mm20.launcher2.themes.ThemeBundle
|
import de.mm20.launcher2.themes.ThemeBundle
|
||||||
import de.mm20.launcher2.themes.ThemeRepository
|
import de.mm20.launcher2.themes.ThemeRepository
|
||||||
import de.mm20.launcher2.themes.toLegacyJson
|
import de.mm20.launcher2.themes.transparencies.Transparencies
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -28,8 +27,9 @@ class ExportThemeSettingsScreenVM: ViewModel(), KoinComponent {
|
|||||||
|
|
||||||
private val themeRepository: ThemeRepository by inject()
|
private val themeRepository: ThemeRepository by inject()
|
||||||
|
|
||||||
val colorSchemes = themeRepository.getAllColors().map { it.filter { !it.builtIn } }
|
val colorSchemes = themeRepository.colors.getAll().map { it.filter { !it.builtIn } }
|
||||||
val shapeSchemes = themeRepository.getAllShapes().map { it.filter { !it.builtIn } }
|
val shapeSchemes = themeRepository.shapes.getAll().map { it.filter { !it.builtIn } }
|
||||||
|
val transparencySchemes = themeRepository.transparencies.getAll().map { it.filter { !it.builtIn } }
|
||||||
|
|
||||||
var themeName by mutableStateOf("")
|
var themeName by mutableStateOf("")
|
||||||
var themeAuthor by mutableStateOf("")
|
var themeAuthor by mutableStateOf("")
|
||||||
@ -55,12 +55,21 @@ class ExportThemeSettingsScreenVM: ViewModel(), KoinComponent {
|
|||||||
shapeScheme = scheme
|
shapeScheme = scheme
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var transparencyScheme by mutableStateOf<Transparencies?>(null)
|
||||||
|
@JvmName("_setTransparencyScheme")
|
||||||
|
private set
|
||||||
|
fun setTransparencyScheme(scheme: Transparencies?) {
|
||||||
|
if (themeName.isBlank() && scheme != null) themeName = scheme.name
|
||||||
|
transparencyScheme = scheme
|
||||||
|
}
|
||||||
|
|
||||||
private fun getThemeBundle(): ThemeBundle {
|
private fun getThemeBundle(): ThemeBundle {
|
||||||
return ThemeBundle(
|
return ThemeBundle(
|
||||||
name = themeName,
|
name = themeName,
|
||||||
author = themeAuthor.takeIf { it.isNotBlank() },
|
author = themeAuthor.takeIf { it.isNotBlank() },
|
||||||
colors = colorScheme,
|
colors = colorScheme,
|
||||||
shapes = shapeScheme,
|
shapes = shapeScheme,
|
||||||
|
transparencies = transparencyScheme,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import androidx.compose.material.icons.rounded.Edit
|
|||||||
import androidx.compose.material.icons.rounded.ErrorOutline
|
import androidx.compose.material.icons.rounded.ErrorOutline
|
||||||
import androidx.compose.material.icons.rounded.LightMode
|
import androidx.compose.material.icons.rounded.LightMode
|
||||||
import androidx.compose.material.icons.rounded.MoreVert
|
import androidx.compose.material.icons.rounded.MoreVert
|
||||||
|
import androidx.compose.material.icons.rounded.Opacity
|
||||||
import androidx.compose.material.icons.rounded.Palette
|
import androidx.compose.material.icons.rounded.Palette
|
||||||
import androidx.compose.material.icons.rounded.Star
|
import androidx.compose.material.icons.rounded.Star
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
@ -35,6 +36,7 @@ import androidx.compose.material3.SegmentedButtonDefaults
|
|||||||
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
|
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@ -62,9 +64,13 @@ import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
|||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
||||||
import de.mm20.launcher2.ui.component.preferences.SwitchPreference
|
import de.mm20.launcher2.ui.component.preferences.SwitchPreference
|
||||||
import de.mm20.launcher2.ui.locals.LocalDarkTheme
|
import de.mm20.launcher2.ui.locals.LocalDarkTheme
|
||||||
|
import de.mm20.launcher2.ui.settings.transparencies.checkerboard
|
||||||
import de.mm20.launcher2.ui.theme.colorscheme.darkColorSchemeOf
|
import de.mm20.launcher2.ui.theme.colorscheme.darkColorSchemeOf
|
||||||
import de.mm20.launcher2.ui.theme.colorscheme.lightColorSchemeOf
|
import de.mm20.launcher2.ui.theme.colorscheme.lightColorSchemeOf
|
||||||
import de.mm20.launcher2.ui.theme.shapes.shapesOf
|
import de.mm20.launcher2.ui.theme.shapes.shapesOf
|
||||||
|
import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme
|
||||||
|
import de.mm20.launcher2.ui.theme.transparency.transparency
|
||||||
|
import de.mm20.launcher2.ui.theme.transparency.transparencySchemeOf
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@ -118,10 +124,15 @@ fun ImportThemeSettingsScreen(
|
|||||||
} ?: MaterialTheme.colorScheme,
|
} ?: MaterialTheme.colorScheme,
|
||||||
shapes = themeBundle.shapes?.let { shapesOf(it) } ?: MaterialTheme.shapes,
|
shapes = themeBundle.shapes?.let { shapesOf(it) } ?: MaterialTheme.shapes,
|
||||||
) {
|
) {
|
||||||
ThemePreview(
|
val transparencies = themeBundle.transparencies?.let { transparencySchemeOf(it) } ?: MaterialTheme.transparency
|
||||||
darkMode = darkModePreview,
|
CompositionLocalProvider(
|
||||||
onDarkModeChanged = { darkModePreview = it }
|
LocalTransparencyScheme provides transparencies
|
||||||
)
|
) {
|
||||||
|
ThemePreview(
|
||||||
|
darkMode = darkModePreview,
|
||||||
|
onDarkModeChanged = { darkModePreview = it }
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
@ -156,6 +167,21 @@ fun ImportThemeSettingsScreen(
|
|||||||
} else null,
|
} else null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (themeBundle.transparencies != null) {
|
||||||
|
Preference(
|
||||||
|
icon = Icons.Rounded.Opacity,
|
||||||
|
title = stringResource(R.string.preference_screen_transparencies),
|
||||||
|
summary = themeBundle.transparencies?.name,
|
||||||
|
controls = if (viewModel.transparenciesExists) {
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
Icons.Rounded.ChangeCircle,
|
||||||
|
stringResource(R.string.import_theme_exists)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else null,
|
||||||
|
)
|
||||||
|
}
|
||||||
if (viewModel.colorsExists || viewModel.shapesExists) {
|
if (viewModel.colorsExists || viewModel.shapesExists) {
|
||||||
Banner(
|
Banner(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -211,8 +237,13 @@ private fun ThemePreview(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(MaterialTheme.shapes.medium)
|
.clip(MaterialTheme.shapes.medium)
|
||||||
|
.checkerboard(
|
||||||
|
MaterialTheme.colorScheme.primary,
|
||||||
|
MaterialTheme.colorScheme.onPrimaryContainer,
|
||||||
|
12.dp,
|
||||||
|
)
|
||||||
.background(
|
.background(
|
||||||
MaterialTheme.colorScheme.surfaceContainer,
|
MaterialTheme.colorScheme.surfaceContainer.copy(alpha = MaterialTheme.transparency.background),
|
||||||
MaterialTheme.shapes.medium
|
MaterialTheme.shapes.medium
|
||||||
)
|
)
|
||||||
.innerShadow(
|
.innerShadow(
|
||||||
@ -225,7 +256,7 @@ private fun ThemePreview(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(top = 12.dp, start = 12.dp, end = 12.dp),
|
.padding(top = 12.dp, start = 12.dp, end = 12.dp),
|
||||||
level = SearchBarLevel.Active,
|
level = SearchBarLevel.Raised,
|
||||||
value = "",
|
value = "",
|
||||||
onValueChange = {},
|
onValueChange = {},
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
@ -239,7 +270,10 @@ private fun ThemePreview(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(top = 12.dp, start = 12.dp, end = 12.dp)
|
.padding(top = 12.dp, start = 12.dp, end = 12.dp)
|
||||||
.background(MaterialTheme.colorScheme.surface, MaterialTheme.shapes.medium)
|
.background(
|
||||||
|
MaterialTheme.colorScheme.surface.copy(alpha = MaterialTheme.transparency.surface),
|
||||||
|
MaterialTheme.shapes.medium
|
||||||
|
)
|
||||||
.padding(12.dp)
|
.padding(12.dp)
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
|
|||||||
@ -8,8 +8,6 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||||
import de.mm20.launcher2.preferences.ColorsDescriptor
|
|
||||||
import de.mm20.launcher2.preferences.ShapesDescriptor
|
|
||||||
import de.mm20.launcher2.preferences.ui.UiSettings
|
import de.mm20.launcher2.preferences.ui.UiSettings
|
||||||
import de.mm20.launcher2.themes.ThemeBundle
|
import de.mm20.launcher2.themes.ThemeBundle
|
||||||
import de.mm20.launcher2.themes.ThemeRepository
|
import de.mm20.launcher2.themes.ThemeRepository
|
||||||
@ -19,9 +17,8 @@ import kotlinx.coroutines.flow.first
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.core.component.KoinComponent
|
import org.koin.core.component.KoinComponent
|
||||||
import org.koin.core.component.inject
|
import org.koin.core.component.inject
|
||||||
import kotlin.getValue
|
|
||||||
|
|
||||||
class ImportThemeSettingsScreenVM: ViewModel(), KoinComponent {
|
class ImportThemeSettingsScreenVM : ViewModel(), KoinComponent {
|
||||||
|
|
||||||
private val themeRepository by inject<ThemeRepository>()
|
private val themeRepository by inject<ThemeRepository>()
|
||||||
private val uiSettings by inject<UiSettings>()
|
private val uiSettings by inject<UiSettings>()
|
||||||
@ -35,6 +32,9 @@ class ImportThemeSettingsScreenVM: ViewModel(), KoinComponent {
|
|||||||
var shapesExists by mutableStateOf(false)
|
var shapesExists by mutableStateOf(false)
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
var transparenciesExists by mutableStateOf(false)
|
||||||
|
private set
|
||||||
|
|
||||||
var loading by mutableStateOf(false)
|
var loading by mutableStateOf(false)
|
||||||
private set
|
private set
|
||||||
|
|
||||||
@ -54,11 +54,16 @@ class ImportThemeSettingsScreenVM: ViewModel(), KoinComponent {
|
|||||||
val text = it.readText()
|
val text = it.readText()
|
||||||
val theme = ThemeBundle.fromJson(text)
|
val theme = ThemeBundle.fromJson(text)
|
||||||
if (theme != null) {
|
if (theme != null) {
|
||||||
val colors = theme.colors?.id?.let { themeRepository.getColors(it) }?.first()
|
val colors =
|
||||||
val shapes = theme.shapes?.id?.let { themeRepository.getShapes(it) }?.first()
|
theme.colors?.id?.let { themeRepository.colors.get(it) }?.first()
|
||||||
|
val shapes =
|
||||||
|
theme.shapes?.id?.let { themeRepository.shapes.get(it) }?.first()
|
||||||
|
val transparencies =
|
||||||
|
theme.transparencies?.id?.let { themeRepository.transparencies.get(it) }?.first()
|
||||||
|
|
||||||
colorsExists = colors != null
|
colorsExists = colors != null
|
||||||
shapesExists = shapes != null
|
shapesExists = shapes != null
|
||||||
|
transparenciesExists = transparencies != null
|
||||||
themeBundle = theme
|
themeBundle = theme
|
||||||
loading = false
|
loading = false
|
||||||
} else {
|
} else {
|
||||||
@ -77,30 +82,42 @@ class ImportThemeSettingsScreenVM: ViewModel(), KoinComponent {
|
|||||||
|
|
||||||
val colors = themeBundle.colors
|
val colors = themeBundle.colors
|
||||||
val shapes = themeBundle.shapes
|
val shapes = themeBundle.shapes
|
||||||
|
val transparencies = themeBundle.transparencies
|
||||||
|
|
||||||
val colorsExist = this.colorsExists
|
val colorsExist = this.colorsExists
|
||||||
val shapesExist = this.shapesExists
|
val shapesExist = this.shapesExists
|
||||||
|
val transparenciesExist = this.transparenciesExists
|
||||||
|
|
||||||
loading = true
|
loading = true
|
||||||
return viewModelScope.launch {
|
return viewModelScope.launch {
|
||||||
if (colors != null) {
|
if (colors != null) {
|
||||||
if (colorsExist) {
|
if (colorsExist) {
|
||||||
themeRepository.updateColors(colors)
|
themeRepository.colors.update(colors)
|
||||||
} else {
|
} else {
|
||||||
themeRepository.createColors(colors)
|
themeRepository.colors.create(colors)
|
||||||
}
|
}
|
||||||
if (applyTheme) {
|
if (applyTheme) {
|
||||||
uiSettings.setColors(ColorsDescriptor.Custom(colors.id.toString()))
|
uiSettings.setColorsId(colors.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (shapes != null) {
|
if (shapes != null) {
|
||||||
if (shapesExist) {
|
if (shapesExist) {
|
||||||
themeRepository.updateShapes(shapes)
|
themeRepository.shapes.update(shapes)
|
||||||
} else {
|
} else {
|
||||||
themeRepository.createShapes(shapes)
|
themeRepository.shapes.create(shapes)
|
||||||
}
|
}
|
||||||
if (applyTheme) {
|
if (applyTheme) {
|
||||||
uiSettings.setShapes(ShapesDescriptor.Custom(shapes.id.toString()))
|
uiSettings.setShapesId(shapes.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (transparencies != null) {
|
||||||
|
if (transparenciesExist) {
|
||||||
|
themeRepository.transparencies.update(transparencies)
|
||||||
|
} else {
|
||||||
|
themeRepository.transparencies.create(transparencies)
|
||||||
|
}
|
||||||
|
if (applyTheme) {
|
||||||
|
uiSettings.setTransparenciesId(transparencies.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loading = false
|
loading = false
|
||||||
|
|||||||
@ -1,32 +1,19 @@
|
|||||||
package de.mm20.launcher2.ui.settings.calendarsearch
|
package de.mm20.launcher2.ui.settings.calendarsearch
|
||||||
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.rounded.ErrorOutline
|
|
||||||
import androidx.compose.material3.CheckboxDefaults
|
import androidx.compose.material3.CheckboxDefaults
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import de.mm20.launcher2.calendar.providers.CalendarList
|
import de.mm20.launcher2.calendar.providers.CalendarList
|
||||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
|
||||||
import de.mm20.launcher2.ktx.sendWithBackgroundPermission
|
|
||||||
import de.mm20.launcher2.plugin.PluginState
|
import de.mm20.launcher2.plugin.PluginState
|
||||||
import de.mm20.launcher2.themes.atTone
|
import de.mm20.launcher2.themes.colors.atTone
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.component.Banner
|
|
||||||
import de.mm20.launcher2.ui.component.preferences.CheckboxPreference
|
import de.mm20.launcher2.ui.component.preferences.CheckboxPreference
|
||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
||||||
|
|||||||
@ -47,16 +47,6 @@ fun CardsSettingsScreen() {
|
|||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
PreferenceCategory {
|
PreferenceCategory {
|
||||||
SliderPreference(
|
|
||||||
title = stringResource(R.string.preference_cards_opacity),
|
|
||||||
icon = Icons.Rounded.Opacity,
|
|
||||||
value = cardStyle.opacity,
|
|
||||||
min = 0f,
|
|
||||||
max = 1f,
|
|
||||||
onValueChanged = {
|
|
||||||
viewModel.setOpacity(it)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
SliderPreference(
|
SliderPreference(
|
||||||
title = stringResource(R.string.preference_cards_stroke_width),
|
title = stringResource(R.string.preference_cards_stroke_width),
|
||||||
icon = Icons.Rounded.LineWeight,
|
icon = Icons.Rounded.LineWeight,
|
||||||
|
|||||||
@ -28,7 +28,6 @@ import androidx.compose.material3.FilledTonalIconButton
|
|||||||
import androidx.compose.material3.FilterChip
|
import androidx.compose.material3.FilterChip
|
||||||
import androidx.compose.material3.FilterChipDefaults
|
import androidx.compose.material3.FilterChipDefaults
|
||||||
import androidx.compose.material3.FloatingActionButton
|
import androidx.compose.material3.FloatingActionButton
|
||||||
import androidx.compose.material3.HorizontalDivider
|
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
@ -51,7 +50,6 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
@ -60,9 +58,9 @@ import de.mm20.launcher2.badges.Badge
|
|||||||
import de.mm20.launcher2.icons.ColorLayer
|
import de.mm20.launcher2.icons.ColorLayer
|
||||||
import de.mm20.launcher2.icons.StaticLauncherIcon
|
import de.mm20.launcher2.icons.StaticLauncherIcon
|
||||||
import de.mm20.launcher2.icons.TintedIconLayer
|
import de.mm20.launcher2.icons.TintedIconLayer
|
||||||
import de.mm20.launcher2.themes.DefaultDarkColorScheme
|
import de.mm20.launcher2.themes.colors.DefaultDarkColorScheme
|
||||||
import de.mm20.launcher2.themes.DefaultLightColorScheme
|
import de.mm20.launcher2.themes.colors.DefaultLightColorScheme
|
||||||
import de.mm20.launcher2.themes.merge
|
import de.mm20.launcher2.themes.colors.merge
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.component.Banner
|
import de.mm20.launcher2.ui.component.Banner
|
||||||
import de.mm20.launcher2.ui.component.ShapedLauncherIcon
|
import de.mm20.launcher2.ui.component.ShapedLauncherIcon
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
package de.mm20.launcher2.ui.settings.colorscheme
|
package de.mm20.launcher2.ui.settings.colorscheme
|
||||||
|
|
||||||
import android.net.Uri
|
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
@ -17,7 +14,6 @@ import androidx.compose.material.icons.Icons
|
|||||||
import androidx.compose.material.icons.rounded.Add
|
import androidx.compose.material.icons.rounded.Add
|
||||||
import androidx.compose.material.icons.rounded.ContentCopy
|
import androidx.compose.material.icons.rounded.ContentCopy
|
||||||
import androidx.compose.material.icons.rounded.Delete
|
import androidx.compose.material.icons.rounded.Delete
|
||||||
import androidx.compose.material.icons.rounded.Download
|
|
||||||
import androidx.compose.material.icons.rounded.Edit
|
import androidx.compose.material.icons.rounded.Edit
|
||||||
import androidx.compose.material.icons.rounded.MoreVert
|
import androidx.compose.material.icons.rounded.MoreVert
|
||||||
import androidx.compose.material.icons.rounded.RadioButtonChecked
|
import androidx.compose.material.icons.rounded.RadioButtonChecked
|
||||||
@ -26,7 +22,6 @@ import androidx.compose.material.icons.rounded.Share
|
|||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.DropdownMenu
|
import androidx.compose.material3.DropdownMenu
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.FloatingActionButton
|
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
@ -45,9 +40,8 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import de.mm20.launcher2.themes.Colors
|
import de.mm20.launcher2.themes.colors.Colors
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.common.ImportThemeSheet
|
|
||||||
import de.mm20.launcher2.ui.component.preferences.Preference
|
import de.mm20.launcher2.ui.component.preferences.Preference
|
||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
||||||
|
|||||||
@ -6,11 +6,10 @@ import androidx.core.content.FileProvider
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import de.mm20.launcher2.ktx.tryStartActivity
|
import de.mm20.launcher2.ktx.tryStartActivity
|
||||||
import de.mm20.launcher2.preferences.ColorsDescriptor
|
|
||||||
import de.mm20.launcher2.preferences.ui.UiSettings
|
import de.mm20.launcher2.preferences.ui.UiSettings
|
||||||
import de.mm20.launcher2.themes.BlackAndWhiteThemeId
|
import de.mm20.launcher2.themes.BlackAndWhiteThemeId
|
||||||
import de.mm20.launcher2.themes.DefaultThemeId
|
import de.mm20.launcher2.themes.DefaultThemeId
|
||||||
import de.mm20.launcher2.themes.Colors
|
import de.mm20.launcher2.themes.colors.Colors
|
||||||
import de.mm20.launcher2.themes.HighContrastThemeId
|
import de.mm20.launcher2.themes.HighContrastThemeId
|
||||||
import de.mm20.launcher2.themes.ThemeRepository
|
import de.mm20.launcher2.themes.ThemeRepository
|
||||||
import de.mm20.launcher2.themes.toLegacyJson
|
import de.mm20.launcher2.themes.toLegacyJson
|
||||||
@ -30,39 +29,27 @@ class ColorSchemesSettingsScreenVM : ViewModel(), KoinComponent {
|
|||||||
private val themeRepository: ThemeRepository by inject()
|
private val themeRepository: ThemeRepository by inject()
|
||||||
private val uiSettings: UiSettings by inject()
|
private val uiSettings: UiSettings by inject()
|
||||||
|
|
||||||
val selectedColors = uiSettings.colors.map {
|
val selectedColors = uiSettings.colorsId
|
||||||
when(it) {
|
val colors: Flow<List<Colors>> = themeRepository.colors.getAll()
|
||||||
ColorsDescriptor.Default -> DefaultThemeId
|
|
||||||
ColorsDescriptor.HighContrast -> HighContrastThemeId
|
|
||||||
ColorsDescriptor.BlackAndWhite -> BlackAndWhiteThemeId
|
|
||||||
is ColorsDescriptor.Custom -> UUID.fromString(it.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val colors: Flow<List<Colors>> = themeRepository.getAllColors()
|
|
||||||
|
|
||||||
fun getTheme(id: UUID): Flow<Colors?> {
|
fun getTheme(id: UUID): Flow<Colors?> {
|
||||||
return themeRepository.getColors(id)
|
return themeRepository.colors.get(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateTheme(colors: Colors) {
|
fun updateTheme(colors: Colors) {
|
||||||
themeRepository.updateColors(colors)
|
themeRepository.colors.update(colors)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun selectTheme(colors: Colors) {
|
fun selectTheme(colors: Colors) {
|
||||||
uiSettings.setColors(when(colors.id) {
|
uiSettings.setColorsId(colors.id)
|
||||||
DefaultThemeId -> ColorsDescriptor.Default
|
|
||||||
HighContrastThemeId -> ColorsDescriptor.HighContrast
|
|
||||||
BlackAndWhiteThemeId -> ColorsDescriptor.BlackAndWhite
|
|
||||||
else -> ColorsDescriptor.Custom(colors.id.toString())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun duplicate(colors: Colors) {
|
fun duplicate(colors: Colors) {
|
||||||
themeRepository.createColors(colors.copy(id = UUID.randomUUID()))
|
themeRepository.colors.create(colors.copy(id = UUID.randomUUID()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun delete(colors: Colors) {
|
fun delete(colors: Colors) {
|
||||||
themeRepository.deleteColors(colors)
|
themeRepository.colors.delete(colors)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exportTheme(context: Context, colors: Colors) {
|
fun exportTheme(context: Context, colors: Colors) {
|
||||||
@ -85,10 +72,10 @@ class ColorSchemesSettingsScreenVM : ViewModel(), KoinComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createNew(context: Context) {
|
fun createNew(context: Context) {
|
||||||
themeRepository.createColors(
|
themeRepository.colors.create(
|
||||||
Colors(
|
Colors(
|
||||||
id = UUID.randomUUID(),
|
id = UUID.randomUUID(),
|
||||||
name = context.getString(R.string.new_color_scheme_name)
|
name = context.getString(R.string.new_theme_name)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import androidx.compose.animation.expandVertically
|
|||||||
import androidx.compose.animation.shrinkVertically
|
import androidx.compose.animation.shrinkVertically
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.combinedClickable
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
@ -33,14 +32,11 @@ import androidx.compose.ui.draw.clip
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import de.mm20.launcher2.themes.get
|
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
||||||
import de.mm20.launcher2.ui.component.Tooltip
|
|
||||||
import de.mm20.launcher2.ui.component.colorpicker.HctColorPicker
|
import de.mm20.launcher2.ui.component.colorpicker.HctColorPicker
|
||||||
import de.mm20.launcher2.ui.component.colorpicker.rememberHctColorPickerState
|
import de.mm20.launcher2.ui.component.colorpicker.rememberHctColorPickerState
|
||||||
import de.mm20.launcher2.ui.component.preferences.SwitchPreference
|
import de.mm20.launcher2.ui.component.preferences.SwitchPreference
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import androidx.compose.animation.AnimatedContent
|
|||||||
import androidx.compose.foundation.Canvas
|
import androidx.compose.foundation.Canvas
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
@ -12,7 +11,6 @@ import androidx.compose.foundation.layout.Spacer
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.requiredWidth
|
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
@ -51,21 +49,20 @@ import androidx.compose.ui.text.font.FontFamily
|
|||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import de.mm20.launcher2.themes.ColorRef
|
import de.mm20.launcher2.themes.colors.ColorRef
|
||||||
import de.mm20.launcher2.themes.CorePaletteColor
|
import de.mm20.launcher2.themes.colors.CorePaletteColor
|
||||||
import de.mm20.launcher2.themes.FullCorePalette
|
import de.mm20.launcher2.themes.colors.FullCorePalette
|
||||||
import de.mm20.launcher2.themes.StaticColor
|
import de.mm20.launcher2.themes.colors.StaticColor
|
||||||
import de.mm20.launcher2.themes.atTone
|
import de.mm20.launcher2.themes.colors.atTone
|
||||||
import de.mm20.launcher2.themes.get
|
import de.mm20.launcher2.themes.colors.get
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
||||||
import de.mm20.launcher2.ui.component.Tooltip
|
|
||||||
import de.mm20.launcher2.ui.component.colorpicker.HctColorPicker
|
import de.mm20.launcher2.ui.component.colorpicker.HctColorPicker
|
||||||
import de.mm20.launcher2.ui.component.colorpicker.rememberHctColorPickerState
|
import de.mm20.launcher2.ui.component.colorpicker.rememberHctColorPickerState
|
||||||
import de.mm20.launcher2.ui.ktx.hct
|
import de.mm20.launcher2.ui.ktx.hct
|
||||||
import hct.Hct
|
import hct.Hct
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import de.mm20.launcher2.themes.Color as ThemeColor
|
import de.mm20.launcher2.themes.colors.Color as ThemeColor
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ThemeColorPreference(
|
fun ThemeColorPreference(
|
||||||
|
|||||||
@ -14,8 +14,6 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
|
||||||
import androidx.compose.foundation.lazy.items
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
@ -26,11 +24,9 @@ import androidx.compose.material.icons.rounded.Error
|
|||||||
import androidx.compose.material.icons.rounded.Info
|
import androidx.compose.material.icons.rounded.Info
|
||||||
import androidx.compose.material.icons.rounded.Settings
|
import androidx.compose.material.icons.rounded.Settings
|
||||||
import androidx.compose.material.icons.rounded.Verified
|
import androidx.compose.material.icons.rounded.Verified
|
||||||
import androidx.compose.material3.CheckboxDefaults
|
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.ModalBottomSheet
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@ -40,12 +36,9 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.pluralStringResource
|
import androidx.compose.ui.res.pluralStringResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
@ -57,15 +50,12 @@ import coil.compose.AsyncImage
|
|||||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||||
import de.mm20.launcher2.ktx.sendWithBackgroundPermission
|
import de.mm20.launcher2.ktx.sendWithBackgroundPermission
|
||||||
import de.mm20.launcher2.plugin.PluginState
|
import de.mm20.launcher2.plugin.PluginState
|
||||||
import de.mm20.launcher2.themes.atTone
|
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.component.preferences.CheckboxPreference
|
|
||||||
import de.mm20.launcher2.ui.component.preferences.GuardedPreference
|
import de.mm20.launcher2.ui.component.preferences.GuardedPreference
|
||||||
import de.mm20.launcher2.ui.component.preferences.Preference
|
import de.mm20.launcher2.ui.component.preferences.Preference
|
||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceWithSwitch
|
import de.mm20.launcher2.ui.component.preferences.PreferenceWithSwitch
|
||||||
import de.mm20.launcher2.ui.component.preferences.SwitchPreference
|
import de.mm20.launcher2.ui.component.preferences.SwitchPreference
|
||||||
import de.mm20.launcher2.ui.locals.LocalDarkTheme
|
|
||||||
import de.mm20.launcher2.ui.locals.LocalNavController
|
import de.mm20.launcher2.ui.locals.LocalNavController
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@ -66,7 +66,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import de.mm20.launcher2.icons.CutCorner
|
import de.mm20.launcher2.icons.CutCorner
|
||||||
import de.mm20.launcher2.icons.RoundedCornerAlt
|
import de.mm20.launcher2.icons.RoundedCornerAlt
|
||||||
import de.mm20.launcher2.themes.CornerStyle
|
import de.mm20.launcher2.themes.shapes.CornerStyle
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
||||||
@ -76,7 +76,7 @@ import de.mm20.launcher2.ui.theme.shapes.shapesOf
|
|||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import de.mm20.launcher2.themes.Shape as ThemeShape
|
import de.mm20.launcher2.themes.shapes.Shape as ThemeShape
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ShapeSchemeSettingsScreen(themeId: UUID) {
|
fun ShapeSchemeSettingsScreen(themeId: UUID) {
|
||||||
@ -284,7 +284,7 @@ fun ShapeSchemeSettingsScreen(themeId: UUID) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
PreferenceCategory(title = "Large") {
|
PreferenceCategory {
|
||||||
ShapePreview(
|
ShapePreview(
|
||||||
previewShapes = previewShapes,
|
previewShapes = previewShapes,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@ -35,8 +35,8 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import de.mm20.launcher2.themes.CornerStyle
|
import de.mm20.launcher2.themes.shapes.CornerStyle
|
||||||
import de.mm20.launcher2.themes.Shapes
|
import de.mm20.launcher2.themes.shapes.Shapes
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.component.preferences.Preference
|
import de.mm20.launcher2.ui.component.preferences.Preference
|
||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
||||||
@ -49,7 +49,7 @@ fun ShapeSchemesSettingsScreen() {
|
|||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val selectedTheme by viewModel.selectedShapes.collectAsStateWithLifecycle(null)
|
val selectedTheme by viewModel.selectedShapesId.collectAsStateWithLifecycle(null)
|
||||||
val themes by viewModel.shapes.collectAsStateWithLifecycle(emptyList())
|
val themes by viewModel.shapes.collectAsStateWithLifecycle(emptyList())
|
||||||
|
|
||||||
var deleteShapes by remember { mutableStateOf<Shapes?>(null) }
|
var deleteShapes by remember { mutableStateOf<Shapes?>(null) }
|
||||||
|
|||||||
@ -2,17 +2,11 @@ package de.mm20.launcher2.ui.settings.shapes
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import de.mm20.launcher2.preferences.ShapesDescriptor
|
|
||||||
import de.mm20.launcher2.preferences.ui.UiSettings
|
import de.mm20.launcher2.preferences.ui.UiSettings
|
||||||
import de.mm20.launcher2.themes.CutShapesId
|
import de.mm20.launcher2.themes.shapes.Shapes
|
||||||
import de.mm20.launcher2.themes.DefaultThemeId
|
|
||||||
import de.mm20.launcher2.themes.ExtraRoundShapesId
|
|
||||||
import de.mm20.launcher2.themes.RectShapesId
|
|
||||||
import de.mm20.launcher2.themes.Shapes
|
|
||||||
import de.mm20.launcher2.themes.ThemeRepository
|
import de.mm20.launcher2.themes.ThemeRepository
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import org.koin.core.component.KoinComponent
|
import org.koin.core.component.KoinComponent
|
||||||
import org.koin.core.component.inject
|
import org.koin.core.component.inject
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
@ -23,45 +17,34 @@ class ShapeSchemesSettingsScreenVM : ViewModel(), KoinComponent {
|
|||||||
private val themeRepository: ThemeRepository by inject()
|
private val themeRepository: ThemeRepository by inject()
|
||||||
private val uiSettings: UiSettings by inject()
|
private val uiSettings: UiSettings by inject()
|
||||||
|
|
||||||
val selectedShapes = uiSettings.shapes.map {
|
val selectedShapesId = uiSettings.shapesId
|
||||||
when(it) {
|
val shapes: Flow<List<Shapes>> = themeRepository.shapes.getAll()
|
||||||
ShapesDescriptor.Default -> DefaultThemeId
|
|
||||||
ShapesDescriptor.Cut -> CutShapesId
|
|
||||||
ShapesDescriptor.ExtraRound -> ExtraRoundShapesId
|
|
||||||
ShapesDescriptor.Rect -> RectShapesId
|
|
||||||
is ShapesDescriptor.Custom -> UUID.fromString(it.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val shapes: Flow<List<Shapes>> = themeRepository.getAllShapes()
|
|
||||||
|
|
||||||
fun getShapes(id: UUID): Flow<Shapes?> {
|
fun getShapes(id: UUID): Flow<Shapes?> {
|
||||||
return themeRepository.getShapes(id)
|
return themeRepository.shapes.get(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateShapes(shapes: Shapes) {
|
fun updateShapes(shapes: Shapes) {
|
||||||
themeRepository.updateShapes(shapes)
|
themeRepository.shapes.update(shapes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun selectShapes(shapes: Shapes) {
|
fun selectShapes(shapes: Shapes) {
|
||||||
uiSettings.setShapes(when(shapes.id) {
|
uiSettings.setShapesId(shapes.id)
|
||||||
DefaultThemeId -> ShapesDescriptor.Default
|
|
||||||
else -> ShapesDescriptor.Custom(shapes.id.toString())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun duplicate(shapes: Shapes) {
|
fun duplicate(shapes: Shapes) {
|
||||||
themeRepository.createShapes(shapes.copy(id = UUID.randomUUID()))
|
themeRepository.shapes.create(shapes.copy(id = UUID.randomUUID()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun delete(shapes: Shapes) {
|
fun delete(shapes: Shapes) {
|
||||||
themeRepository.deleteShapes(shapes)
|
themeRepository.shapes.delete(shapes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createNew(context: Context) {
|
fun createNew(context: Context) {
|
||||||
themeRepository.createShapes(
|
themeRepository.shapes.create(
|
||||||
Shapes(
|
Shapes(
|
||||||
id = UUID.randomUUID(),
|
id = UUID.randomUUID(),
|
||||||
name = context.getString(R.string.new_shapes_name)
|
name = context.getString(R.string.new_theme_name)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,36 @@
|
|||||||
|
package de.mm20.launcher2.ui.settings.transparencies
|
||||||
|
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.drawBehind
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.geometry.Size
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import de.mm20.launcher2.ktx.ceilToInt
|
||||||
|
|
||||||
|
fun Modifier.checkerboard(
|
||||||
|
color1: Color = Color.LightGray,
|
||||||
|
color2: Color = Color.DarkGray,
|
||||||
|
tileSize: Dp = 16.dp
|
||||||
|
): Modifier {
|
||||||
|
return drawBehind {
|
||||||
|
val tileSizePx = with(density) { tileSize.toPx() }
|
||||||
|
val hTiles = (size.width / tileSizePx).ceilToInt()
|
||||||
|
val vTiles = (size.height / tileSizePx).ceilToInt()
|
||||||
|
|
||||||
|
for (i in 0 until hTiles) {
|
||||||
|
for (j in 0 until vTiles) {
|
||||||
|
val color = if ((i + j) % 2 == 0) color1 else color2
|
||||||
|
drawRect(
|
||||||
|
color = color,
|
||||||
|
topLeft = Offset(
|
||||||
|
x = i * tileSizePx,
|
||||||
|
y = j * tileSizePx
|
||||||
|
),
|
||||||
|
size = Size(tileSizePx + 1, tileSizePx + 1)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,304 @@
|
|||||||
|
package de.mm20.launcher2.ui.settings.transparencies
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
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.layout.requiredWidth
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.widthIn
|
||||||
|
import androidx.compose.foundation.shape.CornerSize
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.RestartAlt
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.LocalAbsoluteTonalElevation
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.Slider
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.draw.shadow
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import de.mm20.launcher2.ktx.isAtLeastApiLevel
|
||||||
|
import de.mm20.launcher2.themes.transparencies.Transparencies
|
||||||
|
import de.mm20.launcher2.ui.R
|
||||||
|
import de.mm20.launcher2.ui.component.LocalIconShape
|
||||||
|
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
||||||
|
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
||||||
|
import de.mm20.launcher2.ui.component.surfaceColorAtElevation
|
||||||
|
import de.mm20.launcher2.ui.locals.LocalGridSettings
|
||||||
|
import de.mm20.launcher2.ui.theme.transparency.transparencySchemeOf
|
||||||
|
import de.mm20.launcher2.ui.theme.wallpaperColorsAsState
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
import java.util.UUID
|
||||||
|
import kotlin.math.floor
|
||||||
|
import kotlin.math.log
|
||||||
|
import kotlin.math.round
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TransparencySchemeSettingsRoute(
|
||||||
|
val id: String
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TransparencySchemeSettingsScreen(themeId: UUID) {
|
||||||
|
val viewModel: TransparencySchemesSettingsScreenVM = viewModel()
|
||||||
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
val wallpaperColors by wallpaperColorsAsState()
|
||||||
|
|
||||||
|
val theme by remember(
|
||||||
|
viewModel,
|
||||||
|
themeId
|
||||||
|
) { viewModel.getTransparencies(themeId) }.collectAsStateWithLifecycle(null)
|
||||||
|
|
||||||
|
|
||||||
|
var editName by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
if (editName) {
|
||||||
|
var name by remember(theme) { mutableStateOf(theme?.name ?: "") }
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { editName = false },
|
||||||
|
text = {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = name,
|
||||||
|
onValueChange = { name = it },
|
||||||
|
singleLine = true
|
||||||
|
)
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
viewModel.updateTransparencies(theme!!.copy(name = name))
|
||||||
|
editName = false
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.save))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
PreferenceScreen(
|
||||||
|
title = {
|
||||||
|
Text(
|
||||||
|
theme?.name ?: "",
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
editName = true
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
helpUrl = "https://kvaesitso.mm20.de/docs/user-guide/customization/color-schemes",
|
||||||
|
) {
|
||||||
|
if (theme == null) return@PreferenceScreen
|
||||||
|
|
||||||
|
item {
|
||||||
|
PreferenceCategory {
|
||||||
|
TransparenciesPreview(theme!!)
|
||||||
|
TransparencyPreference(
|
||||||
|
title = "Background",
|
||||||
|
value = theme!!.background,
|
||||||
|
defaultValue = 0.85f,
|
||||||
|
onValueChange = { viewModel.updateTransparencies(theme!!.copy(background = it)) }
|
||||||
|
)
|
||||||
|
TransparencyPreference(
|
||||||
|
title = "Surface",
|
||||||
|
value = theme!!.surface,
|
||||||
|
defaultValue = 1f,
|
||||||
|
onValueChange = { viewModel.updateTransparencies(theme!!.copy(surface = it)) }
|
||||||
|
)
|
||||||
|
TransparencyPreference(
|
||||||
|
title = "Elevated Surface",
|
||||||
|
value = theme!!.elevatedSurface,
|
||||||
|
defaultValue = 1f,
|
||||||
|
onValueChange = { viewModel.updateTransparencies(theme!!.copy(elevatedSurface = it)) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun TransparenciesPreview(
|
||||||
|
theme: Transparencies,
|
||||||
|
) {
|
||||||
|
val transparencyScheme = transparencySchemeOf(theme)
|
||||||
|
|
||||||
|
Box {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(200.dp)
|
||||||
|
.clip(MaterialTheme.shapes.extraSmall)
|
||||||
|
.checkerboard(
|
||||||
|
MaterialTheme.colorScheme.primary,
|
||||||
|
MaterialTheme.colorScheme.onPrimaryContainer,
|
||||||
|
12.dp,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.BottomCenter)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(160.dp)
|
||||||
|
.background(
|
||||||
|
MaterialTheme.colorScheme.surfaceContainer.copy(transparencyScheme.background),
|
||||||
|
MaterialTheme.shapes.large.copy(
|
||||||
|
bottomStart = CornerSize(0f),
|
||||||
|
bottomEnd = CornerSize(0f),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
val xs = MaterialTheme.shapes.extraSmall
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(top = 48.dp, start = 12.dp, end = 12.dp, bottom = 2.dp)
|
||||||
|
.background(
|
||||||
|
MaterialTheme.colorScheme.surfaceContainer.copy(transparencyScheme.surface),
|
||||||
|
MaterialTheme.shapes.medium.copy(
|
||||||
|
bottomStart = xs.bottomStart,
|
||||||
|
bottomEnd = xs.bottomStart,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.padding(12.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
|
) {
|
||||||
|
repeat(LocalGridSettings.current.columnCount) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(vertical = 12.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(LocalGridSettings.current.iconSize.dp)
|
||||||
|
.background(
|
||||||
|
MaterialTheme.colorScheme.primaryContainer,
|
||||||
|
LocalIconShape.current,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val elevatedSurface = MaterialTheme.colorScheme
|
||||||
|
.surfaceColorAtElevation(8.dp + LocalAbsoluteTonalElevation.current)
|
||||||
|
.copy(alpha = transparencyScheme.elevatedSurface)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(end = 24.dp)
|
||||||
|
.shadow(
|
||||||
|
if (transparencyScheme.elevatedSurface < 1f) 0.dp else 8.dp,
|
||||||
|
MaterialTheme.shapes.medium,
|
||||||
|
clip = true
|
||||||
|
)
|
||||||
|
.background(elevatedSurface)
|
||||||
|
.align(Alignment.CenterEnd)
|
||||||
|
.size(144.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun TransparencyPreference(
|
||||||
|
title: String,
|
||||||
|
value: Float?,
|
||||||
|
defaultValue: Float,
|
||||||
|
onValueChange: (Float?) -> Unit,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(MaterialTheme.shapes.extraSmall)
|
||||||
|
.background(MaterialTheme.colorScheme.surface)
|
||||||
|
.padding(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(end = 20.dp)
|
||||||
|
.size(48.dp)
|
||||||
|
.clip(MaterialTheme.shapes.small)
|
||||||
|
.checkerboard(
|
||||||
|
MaterialTheme.colorScheme.primary,
|
||||||
|
MaterialTheme.colorScheme.onPrimaryContainer,
|
||||||
|
12.dp,
|
||||||
|
)
|
||||||
|
.padding(8.dp)
|
||||||
|
.background(
|
||||||
|
MaterialTheme.colorScheme.surface.copy(alpha = value ?: defaultValue),
|
||||||
|
MaterialTheme.shapes.extraSmall
|
||||||
|
),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(48.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style = MaterialTheme.typography.bodyMedium.copy(fontFamily = FontFamily.Monospace),
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
maxLines = 1,
|
||||||
|
)
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
Slider(
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
value = value ?: defaultValue,
|
||||||
|
onValueChange = {
|
||||||
|
val roundedValue = round(it * 100) / 100
|
||||||
|
onValueChange(roundedValue)
|
||||||
|
},
|
||||||
|
valueRange = 0f..1f,
|
||||||
|
)
|
||||||
|
val format = remember { DecimalFormat().apply {
|
||||||
|
maximumFractionDigits = 2
|
||||||
|
minimumFractionDigits = 0
|
||||||
|
} }
|
||||||
|
Text(
|
||||||
|
text = format.format(value ?: defaultValue),
|
||||||
|
style = MaterialTheme.typography.labelSmall,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier.padding(start = 8.dp).widthIn(min = 48.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,218 @@
|
|||||||
|
package de.mm20.launcher2.ui.settings.transparencies
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.Add
|
||||||
|
import androidx.compose.material.icons.rounded.ContentCopy
|
||||||
|
import androidx.compose.material.icons.rounded.Delete
|
||||||
|
import androidx.compose.material.icons.rounded.Edit
|
||||||
|
import androidx.compose.material.icons.rounded.MoreVert
|
||||||
|
import androidx.compose.material.icons.rounded.RadioButtonChecked
|
||||||
|
import androidx.compose.material.icons.rounded.RadioButtonUnchecked
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.material3.surfaceColorAtElevation
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.draw.shadow
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import de.mm20.launcher2.themes.transparencies.Transparencies
|
||||||
|
import de.mm20.launcher2.ui.R
|
||||||
|
import de.mm20.launcher2.ui.component.preferences.Preference
|
||||||
|
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
||||||
|
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
||||||
|
import de.mm20.launcher2.ui.locals.LocalNavController
|
||||||
|
import de.mm20.launcher2.ui.theme.WallpaperColors
|
||||||
|
import de.mm20.launcher2.ui.theme.transparency.transparencySchemeOf
|
||||||
|
import de.mm20.launcher2.ui.theme.wallpaperColorsAsState
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data object TransparencySchemesSettingsRoute
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TransparencySchemesSettingsScreen() {
|
||||||
|
val viewModel: TransparencySchemesSettingsScreenVM = viewModel()
|
||||||
|
val navController = LocalNavController.current
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
val selectedTheme by viewModel.selectedTransparencies.collectAsStateWithLifecycle(null)
|
||||||
|
val themes by viewModel.transparencies.collectAsStateWithLifecycle(emptyList())
|
||||||
|
|
||||||
|
var deleteTransparencies by remember { mutableStateOf<Transparencies?>(null) }
|
||||||
|
|
||||||
|
val wallpaperColors = wallpaperColorsAsState().value
|
||||||
|
|
||||||
|
PreferenceScreen(
|
||||||
|
title = stringResource(R.string.preference_screen_transparencies),
|
||||||
|
topBarActions = {
|
||||||
|
IconButton(onClick = { viewModel.createNew(context) }) {
|
||||||
|
Icon(Icons.Rounded.Add, null)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
item {
|
||||||
|
PreferenceCategory {
|
||||||
|
for (theme in themes) {
|
||||||
|
var showMenu by remember { mutableStateOf(false) }
|
||||||
|
Preference(
|
||||||
|
icon = if (theme.id == selectedTheme) Icons.Rounded.RadioButtonChecked else Icons.Rounded.RadioButtonUnchecked,
|
||||||
|
title = theme.name,
|
||||||
|
controls = {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
TransparenciesPreview(wallpaperColors, theme)
|
||||||
|
IconButton(
|
||||||
|
modifier = Modifier.padding(start = 12.dp),
|
||||||
|
onClick = { showMenu = true }) {
|
||||||
|
Icon(Icons.Rounded.MoreVert, null)
|
||||||
|
}
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = showMenu,
|
||||||
|
onDismissRequest = { showMenu = false }
|
||||||
|
) {
|
||||||
|
if (!theme.builtIn) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
leadingIcon = {
|
||||||
|
Icon(Icons.Rounded.Edit, null)
|
||||||
|
},
|
||||||
|
text = { Text(stringResource(R.string.edit)) },
|
||||||
|
onClick = {
|
||||||
|
navController?.navigate(
|
||||||
|
TransparencySchemeSettingsRoute(theme.id.toString())
|
||||||
|
)
|
||||||
|
showMenu = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
DropdownMenuItem(
|
||||||
|
leadingIcon = {
|
||||||
|
Icon(Icons.Rounded.ContentCopy, null)
|
||||||
|
},
|
||||||
|
text = { Text(stringResource(R.string.duplicate)) },
|
||||||
|
onClick = {
|
||||||
|
viewModel.duplicate(theme)
|
||||||
|
showMenu = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (!theme.builtIn) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
leadingIcon = {
|
||||||
|
Icon(Icons.Rounded.Delete, null)
|
||||||
|
},
|
||||||
|
text = { Text(stringResource(R.string.menu_delete)) },
|
||||||
|
onClick = {
|
||||||
|
deleteTransparencies = theme
|
||||||
|
showMenu = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClick = {
|
||||||
|
viewModel.selectTransparencies(theme)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (deleteTransparencies != null) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { deleteTransparencies = null },
|
||||||
|
text = {
|
||||||
|
Text(
|
||||||
|
stringResource(
|
||||||
|
R.string.confirmation_delete_transparencies_scheme,
|
||||||
|
deleteTransparencies!!.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
viewModel.delete(deleteTransparencies!!)
|
||||||
|
deleteTransparencies = null
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(stringResource(android.R.string.ok))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(
|
||||||
|
onClick = { deleteTransparencies = null }
|
||||||
|
) {
|
||||||
|
Text(stringResource(android.R.string.cancel))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun TransparenciesPreview(wallpaperColors: WallpaperColors, theme: Transparencies) {
|
||||||
|
val transparencies = transparencySchemeOf(theme)
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(MaterialTheme.shapes.extraSmall)
|
||||||
|
.checkerboard(
|
||||||
|
MaterialTheme.colorScheme.primary,
|
||||||
|
MaterialTheme.colorScheme.onPrimaryContainer,
|
||||||
|
12.dp,
|
||||||
|
)
|
||||||
|
.height(40.dp)
|
||||||
|
.width(56.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.background(MaterialTheme.colorScheme.surfaceContainer.copy(alpha = transparencies.background), MaterialTheme.shapes.extraSmall)
|
||||||
|
.height(40.dp)
|
||||||
|
.width(56.dp)
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.background(MaterialTheme.colorScheme.surface.copy(alpha = transparencies.surface), MaterialTheme.shapes.extraSmall)
|
||||||
|
.height(24.dp)
|
||||||
|
.width(48.dp)
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.height(32.dp)
|
||||||
|
.width(36.dp)
|
||||||
|
.shadow(
|
||||||
|
if (transparencies.elevatedSurface < 1f) 0.dp else 8.dp,
|
||||||
|
shape = MaterialTheme.shapes.extraSmall,
|
||||||
|
clip = true,
|
||||||
|
)
|
||||||
|
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(8.dp))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package de.mm20.launcher2.ui.settings.transparencies
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import de.mm20.launcher2.preferences.ui.UiSettings
|
||||||
|
import de.mm20.launcher2.themes.ThemeRepository
|
||||||
|
import de.mm20.launcher2.themes.transparencies.Transparencies
|
||||||
|
import de.mm20.launcher2.ui.R
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import org.koin.core.component.KoinComponent
|
||||||
|
import org.koin.core.component.inject
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class TransparencySchemesSettingsScreenVM : ViewModel(), KoinComponent {
|
||||||
|
|
||||||
|
private val themeRepository: ThemeRepository by inject()
|
||||||
|
private val uiSettings: UiSettings by inject()
|
||||||
|
|
||||||
|
val selectedTransparencies = uiSettings.transparenciesId
|
||||||
|
val transparencies: Flow<List<Transparencies>> = themeRepository.transparencies.getAll()
|
||||||
|
|
||||||
|
fun getTransparencies(id: UUID): Flow<Transparencies?> {
|
||||||
|
return themeRepository.transparencies.get(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateTransparencies(transparencies: Transparencies) {
|
||||||
|
themeRepository.transparencies.update(transparencies)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun selectTransparencies(transparencies: Transparencies) {
|
||||||
|
uiSettings.setTransparenciesId(transparencies.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun duplicate(transparencies: Transparencies) {
|
||||||
|
themeRepository.transparencies.create(transparencies.copy(id = UUID.randomUUID()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(transparencies: Transparencies) {
|
||||||
|
themeRepository.transparencies.delete(transparencies)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createNew(context: Context) {
|
||||||
|
themeRepository.transparencies.create(
|
||||||
|
Transparencies(
|
||||||
|
id = UUID.randomUUID(),
|
||||||
|
name = context.getString(R.string.new_theme_name)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,25 +2,20 @@ package de.mm20.launcher2.ui.theme
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.shape.CornerSize
|
|
||||||
import androidx.compose.foundation.shape.CutCornerShape
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.coerceAtMost
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import de.mm20.launcher2.preferences.Font
|
import de.mm20.launcher2.preferences.Font
|
||||||
import de.mm20.launcher2.preferences.SurfaceShape
|
|
||||||
import de.mm20.launcher2.preferences.ui.UiSettings
|
import de.mm20.launcher2.preferences.ui.UiSettings
|
||||||
import de.mm20.launcher2.themes.ThemeRepository
|
import de.mm20.launcher2.themes.ThemeRepository
|
||||||
import de.mm20.launcher2.ui.locals.LocalDarkTheme
|
import de.mm20.launcher2.ui.locals.LocalDarkTheme
|
||||||
import de.mm20.launcher2.ui.theme.colorscheme.*
|
import de.mm20.launcher2.ui.theme.colorscheme.*
|
||||||
import de.mm20.launcher2.ui.theme.shapes.shapesOf
|
import de.mm20.launcher2.ui.theme.shapes.shapesOf
|
||||||
|
import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme
|
||||||
|
import de.mm20.launcher2.ui.theme.transparency.transparencySchemeOf
|
||||||
import de.mm20.launcher2.ui.theme.typography.DefaultTypography
|
import de.mm20.launcher2.ui.theme.typography.DefaultTypography
|
||||||
import de.mm20.launcher2.ui.theme.typography.getDeviceDefaultTypography
|
import de.mm20.launcher2.ui.theme.typography.getDeviceDefaultTypography
|
||||||
import kotlinx.coroutines.flow.flatMapLatest
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
import de.mm20.launcher2.preferences.ColorScheme as ColorSchemePref
|
import de.mm20.launcher2.preferences.ColorScheme as ColorSchemePref
|
||||||
|
|
||||||
@ -35,14 +30,20 @@ fun LauncherTheme(
|
|||||||
val themeRepository: ThemeRepository = koinInject()
|
val themeRepository: ThemeRepository = koinInject()
|
||||||
|
|
||||||
val themeColors by remember {
|
val themeColors by remember {
|
||||||
uiSettings.colors.flatMapLatest {
|
uiSettings.colorsId.flatMapLatest {
|
||||||
themeRepository.getColorsOrDefault(it)
|
themeRepository.colors.getOrDefault(it)
|
||||||
}
|
}
|
||||||
}.collectAsState(null)
|
}.collectAsState(null)
|
||||||
|
|
||||||
val themeShapes by remember {
|
val themeShapes by remember {
|
||||||
uiSettings.shapes.flatMapLatest {
|
uiSettings.shapesId.flatMapLatest {
|
||||||
themeRepository.getShapesOrDefault(it)
|
themeRepository.shapes.getOrDefault(it)
|
||||||
|
}
|
||||||
|
}.collectAsState(null)
|
||||||
|
|
||||||
|
val themeTransparencies by remember {
|
||||||
|
uiSettings.transparenciesId.flatMapLatest {
|
||||||
|
themeRepository.transparencies.getOrDefault(it)
|
||||||
}
|
}
|
||||||
}.collectAsState(null)
|
}.collectAsState(null)
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ fun LauncherTheme(
|
|||||||
val darkTheme =
|
val darkTheme =
|
||||||
colorSchemePref == ColorSchemePref.Dark || colorSchemePref == ColorSchemePref.System && isSystemInDarkTheme()
|
colorSchemePref == ColorSchemePref.Dark || colorSchemePref == ColorSchemePref.System && isSystemInDarkTheme()
|
||||||
|
|
||||||
if (themeColors == null || themeShapes == null) {
|
if (themeColors == null || themeShapes == null || themeTransparencies == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ fun LauncherTheme(
|
|||||||
|
|
||||||
val shapes = shapesOf(themeShapes!!)
|
val shapes = shapesOf(themeShapes!!)
|
||||||
|
|
||||||
|
val transparencyScheme = transparencySchemeOf(themeTransparencies!!)
|
||||||
|
|
||||||
|
|
||||||
val font by remember { uiSettings.font }.collectAsState(
|
val font by remember { uiSettings.font }.collectAsState(
|
||||||
@ -75,7 +77,8 @@ fun LauncherTheme(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalDarkTheme provides darkTheme
|
LocalDarkTheme provides darkTheme,
|
||||||
|
LocalTransparencyScheme provides transparencyScheme,
|
||||||
) {
|
) {
|
||||||
MaterialExpressiveTheme(
|
MaterialExpressiveTheme(
|
||||||
colorScheme = colorScheme,
|
colorScheme = colorScheme,
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package de.mm20.launcher2.ui.theme.colorscheme
|
package de.mm20.launcher2.ui.theme.colorscheme
|
||||||
|
|
||||||
|
import android.R
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.compose.material3.ColorScheme
|
import androidx.compose.material3.ColorScheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@ -11,14 +12,14 @@ import androidx.compose.ui.graphics.toArgb
|
|||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import de.mm20.launcher2.preferences.ui.UiSettings
|
import de.mm20.launcher2.preferences.ui.UiSettings
|
||||||
import de.mm20.launcher2.themes.CorePalette
|
import de.mm20.launcher2.themes.colors.CorePalette
|
||||||
import de.mm20.launcher2.themes.DefaultDarkColorScheme
|
import de.mm20.launcher2.themes.colors.DefaultDarkColorScheme
|
||||||
import de.mm20.launcher2.themes.DefaultLightColorScheme
|
import de.mm20.launcher2.themes.colors.DefaultLightColorScheme
|
||||||
import de.mm20.launcher2.themes.FullColorScheme
|
import de.mm20.launcher2.themes.colors.FullColorScheme
|
||||||
import de.mm20.launcher2.themes.PartialCorePalette
|
import de.mm20.launcher2.themes.colors.PartialCorePalette
|
||||||
import de.mm20.launcher2.themes.Colors as ThemeColors
|
import de.mm20.launcher2.themes.colors.Colors as ThemeColors
|
||||||
import de.mm20.launcher2.themes.get
|
import de.mm20.launcher2.themes.colors.get
|
||||||
import de.mm20.launcher2.themes.merge
|
import de.mm20.launcher2.themes.colors.merge
|
||||||
import de.mm20.launcher2.ui.locals.LocalWallpaperColors
|
import de.mm20.launcher2.ui.locals.LocalWallpaperColors
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
|
|
||||||
@ -88,11 +89,11 @@ fun systemCorePalette(): CorePalette<Int> {
|
|||||||
if (Build.VERSION.SDK_INT >= 31 && !compatModeColors) {
|
if (Build.VERSION.SDK_INT >= 31 && !compatModeColors) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
return CorePalette(
|
return CorePalette(
|
||||||
primary = ContextCompat.getColor(context, android.R.color.system_accent1_500),
|
primary = ContextCompat.getColor(context, R.color.system_accent1_500),
|
||||||
secondary = ContextCompat.getColor(context, android.R.color.system_accent2_500),
|
secondary = ContextCompat.getColor(context, R.color.system_accent2_500),
|
||||||
tertiary = ContextCompat.getColor(context, android.R.color.system_accent3_500),
|
tertiary = ContextCompat.getColor(context, R.color.system_accent3_500),
|
||||||
neutral = ContextCompat.getColor(context, android.R.color.system_neutral1_500),
|
neutral = ContextCompat.getColor(context, R.color.system_neutral1_500),
|
||||||
neutralVariant = ContextCompat.getColor(context, android.R.color.system_neutral2_500),
|
neutralVariant = ContextCompat.getColor(context, R.color.system_neutral2_500),
|
||||||
error = 0xFFB3261E.toInt(),
|
error = 0xFFB3261E.toInt(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,9 +8,9 @@ import androidx.compose.material3.Shapes
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import de.mm20.launcher2.themes.CornerStyle
|
import de.mm20.launcher2.themes.shapes.CornerStyle
|
||||||
import de.mm20.launcher2.themes.Shape as ThemeShape
|
import de.mm20.launcher2.themes.shapes.Shape as ThemeShape
|
||||||
import de.mm20.launcher2.themes.Shapes as ThemeShapes
|
import de.mm20.launcher2.themes.shapes.Shapes as ThemeShapes
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun shapesOf(shapes: ThemeShapes): Shapes {
|
fun shapesOf(shapes: ThemeShapes): Shapes {
|
||||||
|
|||||||
@ -1,10 +1,31 @@
|
|||||||
package de.mm20.launcher2.ui.theme.transparency
|
package de.mm20.launcher2.ui.theme.transparency
|
||||||
|
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.compositionLocalOf
|
import androidx.compose.runtime.compositionLocalOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import de.mm20.launcher2.themes.transparencies.Transparencies
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun transparencySchemeOf(transparencies: Transparencies): TransparencyScheme {
|
||||||
|
return remember(transparencies) {
|
||||||
|
TransparencyScheme(
|
||||||
|
background = transparencies.background ?: 0.85f,
|
||||||
|
surface = transparencies.surface ?: 1f,
|
||||||
|
elevatedSurface = transparencies.elevatedSurface ?: 1f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data class TransparencyScheme(
|
data class TransparencyScheme(
|
||||||
val background: Float,
|
val background: Float = 0.85f,
|
||||||
val surface: Float,
|
val surface: Float = 1f,
|
||||||
|
val elevatedSurface: Float = 1f,
|
||||||
)
|
)
|
||||||
|
|
||||||
val LocalTransparencyScheme = compositionLocalOf { TransparencyScheme(0.85f, 1f) }
|
val LocalTransparencyScheme = compositionLocalOf { TransparencyScheme(background = 0.85f, surface = 1f, elevatedSurface = 1f) }
|
||||||
|
|
||||||
|
val MaterialTheme.transparency
|
||||||
|
@Composable
|
||||||
|
get() = LocalTransparencyScheme.current
|
||||||
@ -439,6 +439,9 @@
|
|||||||
<string name="preference_shapes_extra_round">Extra round</string>
|
<string name="preference_shapes_extra_round">Extra round</string>
|
||||||
<string name="preference_shapes_rect">Rectangular</string>
|
<string name="preference_shapes_rect">Rectangular</string>
|
||||||
<string name="preference_shapes_base">Base shape</string>
|
<string name="preference_shapes_base">Base shape</string>
|
||||||
|
<string name="preference_screen_transparencies">Transparency</string>
|
||||||
|
<string name="preference_transparencies_default">Default</string>
|
||||||
|
<string name="preference_transparencies_semi_transparent">Semi-transparent</string>
|
||||||
<string name="preference_font">Font</string>
|
<string name="preference_font">Font</string>
|
||||||
<string name="preference_font_system">System default</string>
|
<string name="preference_font_system">System default</string>
|
||||||
<string name="preference_screen_about">About</string>
|
<string name="preference_screen_about">About</string>
|
||||||
@ -821,8 +824,8 @@
|
|||||||
<string name="note_widget_file_write_error_description">The note could not be written to the linked file. Possibly, it has been moved or deleted. A copy has been saved to the launcher\'s internal storage.</string>
|
<string name="note_widget_file_write_error_description">The note could not be written to the linked file. Possibly, it has been moved or deleted. A copy has been saved to the launcher\'s internal storage.</string>
|
||||||
<string name="confirmation_delete_color_scheme">Do you really want to delete the color scheme %1$s\?</string>
|
<string name="confirmation_delete_color_scheme">Do you really want to delete the color scheme %1$s\?</string>
|
||||||
<string name="confirmation_delete_shapes_scheme">Do you really want to delete the shape scheme %1$s?</string>
|
<string name="confirmation_delete_shapes_scheme">Do you really want to delete the shape scheme %1$s?</string>
|
||||||
<string name="new_color_scheme_name">New color scheme</string>
|
<string name="confirmation_delete_transparencies_scheme">Do you really want to delete the transparency scheme %1$s?</string>
|
||||||
<string name="new_shapes_name">New shapes</string>
|
<string name="new_theme_name">(untitled)</string>
|
||||||
<string name="theme_color_scheme_system_default">Use system default</string>
|
<string name="theme_color_scheme_system_default">Use system default</string>
|
||||||
<string name="theme_color_scheme_autogenerate">From primary color</string>
|
<string name="theme_color_scheme_autogenerate">From primary color</string>
|
||||||
<string name="theme_color_scheme_palette_color">Palette</string>
|
<string name="theme_color_scheme_palette_color">Palette</string>
|
||||||
|
|||||||
@ -2,18 +2,22 @@ package de.mm20.launcher2.preferences
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import de.mm20.launcher2.search.SearchFilters
|
import de.mm20.launcher2.search.SearchFilters
|
||||||
|
import de.mm20.launcher2.serialization.UUIDSerializer
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.JsonNames
|
import java.util.UUID
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class LauncherSettingsData internal constructor(
|
data class LauncherSettingsData internal constructor(
|
||||||
val schemaVersion: Int = 5,
|
val schemaVersion: Int = 5,
|
||||||
|
|
||||||
val uiColorScheme: ColorScheme = ColorScheme.System,
|
val uiColorScheme: ColorScheme = ColorScheme.System,
|
||||||
@JsonNames("uiTheme")
|
@Serializable(with = UUIDSerializer::class)
|
||||||
val uiColors: ColorsDescriptor = ColorsDescriptor.Default,
|
val uiColorsId: UUID = UUID(0L, 0L),
|
||||||
val uiShapes: ShapesDescriptor = ShapesDescriptor.Default,
|
@Serializable(with = UUIDSerializer::class)
|
||||||
|
val uiShapesId: UUID = UUID(0L, 0L),
|
||||||
|
@Serializable(with = UUIDSerializer::class)
|
||||||
|
val uiTransparenciesId: UUID = UUID(0L, 0L),
|
||||||
|
|
||||||
val uiCompatModeColors: Boolean = false,
|
val uiCompatModeColors: Boolean = false,
|
||||||
val uiFont: Font = Font.Outfit,
|
val uiFont: Font = Font.Outfit,
|
||||||
@ -205,53 +209,6 @@ enum class Font {
|
|||||||
System,
|
System,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
sealed interface ColorsDescriptor {
|
|
||||||
@Serializable
|
|
||||||
@SerialName("default")
|
|
||||||
data object Default : ColorsDescriptor
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("high_contrast")
|
|
||||||
data object HighContrast : ColorsDescriptor
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("bw")
|
|
||||||
data object BlackAndWhite : ColorsDescriptor
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("custom")
|
|
||||||
data class Custom(
|
|
||||||
val id: String,
|
|
||||||
) : ColorsDescriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
sealed interface ShapesDescriptor {
|
|
||||||
@Serializable
|
|
||||||
@SerialName("default")
|
|
||||||
data object Default : ShapesDescriptor
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("cut")
|
|
||||||
data object Cut : ShapesDescriptor
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("extra_round")
|
|
||||||
data object ExtraRound : ShapesDescriptor
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("rect")
|
|
||||||
data object Rect : ShapesDescriptor
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("custom")
|
|
||||||
data class Custom(
|
|
||||||
val id: String,
|
|
||||||
) : ShapesDescriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum class ClockWidgetStyleEnum {
|
internal enum class ClockWidgetStyleEnum {
|
||||||
Digital1,
|
Digital1,
|
||||||
Digital2,
|
Digital2,
|
||||||
|
|||||||
@ -8,10 +8,9 @@ import de.mm20.launcher2.preferences.ScreenOrientation
|
|||||||
import de.mm20.launcher2.preferences.SearchBarColors
|
import de.mm20.launcher2.preferences.SearchBarColors
|
||||||
import de.mm20.launcher2.preferences.SearchBarStyle
|
import de.mm20.launcher2.preferences.SearchBarStyle
|
||||||
import de.mm20.launcher2.preferences.SystemBarColors
|
import de.mm20.launcher2.preferences.SystemBarColors
|
||||||
import de.mm20.launcher2.preferences.ColorsDescriptor
|
|
||||||
import de.mm20.launcher2.preferences.ShapesDescriptor
|
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
data class CardStyle(
|
data class CardStyle(
|
||||||
val opacity: Float = 1f,
|
val opacity: Float = 1f,
|
||||||
@ -286,25 +285,36 @@ class UiSettings internal constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val colors
|
val colorsId
|
||||||
get() = launcherDataStore.data.map {
|
get() = launcherDataStore.data.map {
|
||||||
it.uiColors
|
it.uiColorsId
|
||||||
}.distinctUntilChanged()
|
}.distinctUntilChanged()
|
||||||
|
|
||||||
fun setColors(colors: ColorsDescriptor) {
|
fun setColorsId(colorsId: UUID) {
|
||||||
launcherDataStore.update {
|
launcherDataStore.update {
|
||||||
it.copy(uiColors = colors)
|
it.copy(uiColorsId = colorsId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val shapes
|
val shapesId
|
||||||
get() = launcherDataStore.data.map {
|
get() = launcherDataStore.data.map {
|
||||||
it.uiShapes
|
it.uiShapesId
|
||||||
}.distinctUntilChanged()
|
}.distinctUntilChanged()
|
||||||
|
|
||||||
fun setShapes(shapes: ShapesDescriptor) {
|
fun setShapesId(shapesId: UUID) {
|
||||||
launcherDataStore.update {
|
launcherDataStore.update {
|
||||||
it.copy(uiShapes = shapes)
|
it.copy(uiShapesId = shapesId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val transparenciesId
|
||||||
|
get() = launcherDataStore.data.map {
|
||||||
|
it.uiTransparenciesId
|
||||||
|
}.distinctUntilChanged()
|
||||||
|
|
||||||
|
fun setTransparenciesId(transparenciesId: UUID) {
|
||||||
|
launcherDataStore.update {
|
||||||
|
it.copy(uiTransparenciesId = transparenciesId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import de.mm20.launcher2.database.entities.SavedSearchableEntity
|
|||||||
import de.mm20.launcher2.database.entities.SearchActionEntity
|
import de.mm20.launcher2.database.entities.SearchActionEntity
|
||||||
import de.mm20.launcher2.database.entities.ColorsEntity
|
import de.mm20.launcher2.database.entities.ColorsEntity
|
||||||
import de.mm20.launcher2.database.entities.ShapesEntity
|
import de.mm20.launcher2.database.entities.ShapesEntity
|
||||||
|
import de.mm20.launcher2.database.entities.TransparenciesEntity
|
||||||
import de.mm20.launcher2.database.entities.WidgetEntity
|
import de.mm20.launcher2.database.entities.WidgetEntity
|
||||||
import de.mm20.launcher2.database.migrations.Migration_10_11
|
import de.mm20.launcher2.database.migrations.Migration_10_11
|
||||||
import de.mm20.launcher2.database.migrations.Migration_11_12
|
import de.mm20.launcher2.database.migrations.Migration_11_12
|
||||||
@ -39,6 +40,7 @@ import de.mm20.launcher2.database.migrations.Migration_24_25
|
|||||||
import de.mm20.launcher2.database.migrations.Migration_25_26
|
import de.mm20.launcher2.database.migrations.Migration_25_26
|
||||||
import de.mm20.launcher2.database.migrations.Migration_26_27
|
import de.mm20.launcher2.database.migrations.Migration_26_27
|
||||||
import de.mm20.launcher2.database.migrations.Migration_27_28
|
import de.mm20.launcher2.database.migrations.Migration_27_28
|
||||||
|
import de.mm20.launcher2.database.migrations.Migration_28_29
|
||||||
import de.mm20.launcher2.database.migrations.Migration_6_7
|
import de.mm20.launcher2.database.migrations.Migration_6_7
|
||||||
import de.mm20.launcher2.database.migrations.Migration_7_8
|
import de.mm20.launcher2.database.migrations.Migration_7_8
|
||||||
import de.mm20.launcher2.database.migrations.Migration_8_9
|
import de.mm20.launcher2.database.migrations.Migration_8_9
|
||||||
@ -59,7 +61,8 @@ import java.util.UUID
|
|||||||
ColorsEntity::class,
|
ColorsEntity::class,
|
||||||
PluginEntity::class,
|
PluginEntity::class,
|
||||||
ShapesEntity::class,
|
ShapesEntity::class,
|
||||||
], version = 28, exportSchema = true
|
TransparenciesEntity::class,
|
||||||
|
], version = 29, exportSchema = true
|
||||||
)
|
)
|
||||||
@TypeConverters(ComponentNameConverter::class)
|
@TypeConverters(ComponentNameConverter::class)
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
@ -160,6 +163,7 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
Migration_25_26(),
|
Migration_25_26(),
|
||||||
Migration_26_27(),
|
Migration_26_27(),
|
||||||
Migration_27_28(),
|
Migration_27_28(),
|
||||||
|
Migration_28_29(),
|
||||||
).build()
|
).build()
|
||||||
if (_instance == null) _instance = instance
|
if (_instance == null) _instance = instance
|
||||||
return instance
|
return instance
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import androidx.room.Query
|
|||||||
import androidx.room.Update
|
import androidx.room.Update
|
||||||
import de.mm20.launcher2.database.entities.ColorsEntity
|
import de.mm20.launcher2.database.entities.ColorsEntity
|
||||||
import de.mm20.launcher2.database.entities.ShapesEntity
|
import de.mm20.launcher2.database.entities.ShapesEntity
|
||||||
|
import de.mm20.launcher2.database.entities.TransparenciesEntity
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@ -17,39 +18,60 @@ interface ThemeDao {
|
|||||||
@Query("SELECT * FROM Shapes")
|
@Query("SELECT * FROM Shapes")
|
||||||
fun getAllShapes(): Flow<List<ShapesEntity>>
|
fun getAllShapes(): Flow<List<ShapesEntity>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Transparencies")
|
||||||
|
fun getAllTransparencies(): Flow<List<TransparenciesEntity>>
|
||||||
|
|
||||||
@Query("SELECT * FROM Theme WHERE id = :id LIMIT 1")
|
@Query("SELECT * FROM Theme WHERE id = :id LIMIT 1")
|
||||||
fun getColors(id: UUID): Flow<ColorsEntity?>
|
fun getColors(id: UUID): Flow<ColorsEntity?>
|
||||||
|
|
||||||
@Query("SELECT * FROM Shapes WHERE id = :id LIMIT 1")
|
@Query("SELECT * FROM Shapes WHERE id = :id LIMIT 1")
|
||||||
fun getShapes(id: UUID): Flow<ShapesEntity?>
|
fun getShapes(id: UUID): Flow<ShapesEntity?>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Transparencies WHERE id = :id LIMIT 1")
|
||||||
|
fun getTransparencies(id: UUID): Flow<TransparenciesEntity?>
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
suspend fun insertColors(colors: ColorsEntity)
|
suspend fun insertColors(colors: ColorsEntity)
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
suspend fun insertShapes(shapes: ShapesEntity)
|
suspend fun insertShapes(shapes: ShapesEntity)
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
suspend fun insertTransparencies(transparencies: TransparenciesEntity)
|
||||||
|
|
||||||
@Update
|
@Update
|
||||||
suspend fun updateColors(colors: ColorsEntity)
|
suspend fun updateColors(colors: ColorsEntity)
|
||||||
|
|
||||||
@Update
|
@Update
|
||||||
suspend fun updateShapes(shapes: ShapesEntity)
|
suspend fun updateShapes(shapes: ShapesEntity)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
suspend fun updateTransparencies(transparencies: TransparenciesEntity)
|
||||||
|
|
||||||
@Query("DELETE FROM Theme WHERE id = :id")
|
@Query("DELETE FROM Theme WHERE id = :id")
|
||||||
suspend fun deleteColors(id: UUID)
|
suspend fun deleteColors(id: UUID)
|
||||||
|
|
||||||
@Query("DELETE FROM Shapes WHERE id = :id")
|
@Query("DELETE FROM Shapes WHERE id = :id")
|
||||||
suspend fun deleteShapes(id: UUID)
|
suspend fun deleteShapes(id: UUID)
|
||||||
|
|
||||||
|
@Query("DELETE FROM Transparencies WHERE id = :id")
|
||||||
|
suspend fun deleteTransparencies(id: UUID)
|
||||||
|
|
||||||
@Query("DELETE FROM Theme")
|
@Query("DELETE FROM Theme")
|
||||||
suspend fun deleteAllColors()
|
suspend fun deleteAllColors()
|
||||||
|
|
||||||
@Query("DELETE FROM Shapes")
|
@Query("DELETE FROM Shapes")
|
||||||
suspend fun deleteAllShapes()
|
suspend fun deleteAllShapes()
|
||||||
|
|
||||||
|
@Query("DELETE FROM Transparencies")
|
||||||
|
suspend fun deleteAllTransparencies()
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
fun insertAllColors(colors: List<ColorsEntity>)
|
fun insertAllColors(colors: List<ColorsEntity>)
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
fun insertAllShapes(shapes: List<ShapesEntity>)
|
fun insertAllShapes(shapes: List<ShapesEntity>)
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
fun insertAllTransparencies(transparencies: List<TransparenciesEntity>)
|
||||||
}
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package de.mm20.launcher2.database.entities
|
||||||
|
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
@Entity(tableName = "Transparencies")
|
||||||
|
data class TransparenciesEntity(
|
||||||
|
@PrimaryKey val id: UUID,
|
||||||
|
val name: String,
|
||||||
|
|
||||||
|
val background: Float?,
|
||||||
|
val surface: Float?,
|
||||||
|
val elevatedSurface: Float?,
|
||||||
|
)
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package de.mm20.launcher2.database.migrations
|
||||||
|
|
||||||
|
import androidx.room.migration.Migration
|
||||||
|
import androidx.sqlite.SQLiteConnection
|
||||||
|
import androidx.sqlite.execSQL
|
||||||
|
|
||||||
|
class Migration_28_29: Migration(28, 29) {
|
||||||
|
|
||||||
|
override fun migrate(connection: SQLiteConnection) {
|
||||||
|
connection.execSQL(
|
||||||
|
"""
|
||||||
|
CREATE TABLE IF NOT EXISTS `Transparencies` (
|
||||||
|
`id` BLOB NOT NULL PRIMARY KEY,
|
||||||
|
`name` TEXT NOT NULL,
|
||||||
|
`background` REAL,
|
||||||
|
`surface` REAL,
|
||||||
|
`elevatedSurface` REAL
|
||||||
|
)
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,245 +1,20 @@
|
|||||||
package de.mm20.launcher2.themes
|
package de.mm20.launcher2.themes
|
||||||
|
|
||||||
|
import de.mm20.launcher2.themes.colors.Color
|
||||||
|
import de.mm20.launcher2.themes.colors.ColorRef
|
||||||
|
import de.mm20.launcher2.themes.colors.ColorScheme
|
||||||
|
import de.mm20.launcher2.themes.colors.CorePaletteColor
|
||||||
|
import de.mm20.launcher2.themes.colors.StaticColor
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
|
|
||||||
val DefaultThemeId = UUID(0L, 0L)
|
val DefaultThemeId = UUID(0L, 0L)
|
||||||
|
|
||||||
val HighContrastThemeId = UUID(0L, 2L)
|
val HighContrastThemeId = UUID(0L, 2L)
|
||||||
val BlackAndWhiteThemeId = UUID(0L, 1L)
|
val BlackAndWhiteThemeId = UUID(0L, 1L)
|
||||||
|
|
||||||
val ExtraRoundShapesId = UUID(0L, 1L)
|
val ExtraRoundShapesId = UUID(0L, 1L)
|
||||||
val CutShapesId = UUID(0L, 2L)
|
val CutShapesId = UUID(0L, 2L)
|
||||||
val RectShapesId = UUID(0L, 3L)
|
val RectShapesId = UUID(0L, 3L)
|
||||||
|
|
||||||
val DefaultLightColorScheme = ColorScheme<Color>(
|
val SemiTransparentId = UUID(0L, 1L)
|
||||||
primary = ColorRef(CorePaletteColor.Primary, 40),
|
|
||||||
onPrimary = ColorRef(CorePaletteColor.Primary, 100),
|
|
||||||
primaryContainer = ColorRef(CorePaletteColor.Primary, 90),
|
|
||||||
onPrimaryContainer = ColorRef(CorePaletteColor.Primary, 30),
|
|
||||||
secondary = ColorRef(CorePaletteColor.Secondary, 40),
|
|
||||||
onSecondary = ColorRef(CorePaletteColor.Secondary, 100),
|
|
||||||
secondaryContainer = ColorRef(CorePaletteColor.Secondary, 90),
|
|
||||||
onSecondaryContainer = ColorRef(CorePaletteColor.Secondary, 30),
|
|
||||||
tertiary = ColorRef(CorePaletteColor.Tertiary, 40),
|
|
||||||
onTertiary = ColorRef(CorePaletteColor.Tertiary, 100),
|
|
||||||
tertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 90),
|
|
||||||
onTertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 30),
|
|
||||||
error = ColorRef(CorePaletteColor.Error, 40),
|
|
||||||
onError = ColorRef(CorePaletteColor.Error, 100),
|
|
||||||
errorContainer = ColorRef(CorePaletteColor.Error, 90),
|
|
||||||
onErrorContainer = ColorRef(CorePaletteColor.Error, 30),
|
|
||||||
surfaceDim = ColorRef(CorePaletteColor.Neutral, 87),
|
|
||||||
surface = ColorRef(CorePaletteColor.Neutral, 98),
|
|
||||||
surfaceBright = ColorRef(CorePaletteColor.Neutral, 98),
|
|
||||||
surfaceContainerLowest = ColorRef(CorePaletteColor.Neutral, 100),
|
|
||||||
surfaceContainerLow = ColorRef(CorePaletteColor.Neutral, 96),
|
|
||||||
surfaceContainer = ColorRef(CorePaletteColor.Neutral, 94),
|
|
||||||
surfaceContainerHigh = ColorRef(CorePaletteColor.Neutral, 92),
|
|
||||||
surfaceContainerHighest = ColorRef(CorePaletteColor.Neutral, 90),
|
|
||||||
onSurface = ColorRef(CorePaletteColor.Neutral, 10),
|
|
||||||
onSurfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 30),
|
|
||||||
outline = ColorRef(CorePaletteColor.NeutralVariant, 50),
|
|
||||||
outlineVariant = ColorRef(CorePaletteColor.NeutralVariant, 80),
|
|
||||||
inverseSurface = ColorRef(CorePaletteColor.Neutral, 20),
|
|
||||||
inverseOnSurface = ColorRef(CorePaletteColor.Neutral, 95),
|
|
||||||
inversePrimary = ColorRef(CorePaletteColor.Primary, 80),
|
|
||||||
surfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 90),
|
|
||||||
surfaceTint = ColorRef(CorePaletteColor.Primary, 40),
|
|
||||||
background = ColorRef(CorePaletteColor.Neutral, 98),
|
|
||||||
onBackground = ColorRef(CorePaletteColor.Neutral, 10),
|
|
||||||
scrim = ColorRef(CorePaletteColor.Neutral, 0),
|
|
||||||
)
|
|
||||||
|
|
||||||
val DefaultDarkColorScheme = ColorScheme<Color>(
|
|
||||||
primary = ColorRef(CorePaletteColor.Primary, 80),
|
|
||||||
onPrimary = ColorRef(CorePaletteColor.Primary, 20),
|
|
||||||
primaryContainer = ColorRef(CorePaletteColor.Primary, 30),
|
|
||||||
onPrimaryContainer = ColorRef(CorePaletteColor.Primary, 90),
|
|
||||||
secondary = ColorRef(CorePaletteColor.Secondary, 80),
|
|
||||||
onSecondary = ColorRef(CorePaletteColor.Secondary, 20),
|
|
||||||
secondaryContainer = ColorRef(CorePaletteColor.Secondary, 30),
|
|
||||||
onSecondaryContainer = ColorRef(CorePaletteColor.Secondary, 90),
|
|
||||||
tertiary = ColorRef(CorePaletteColor.Tertiary, 80),
|
|
||||||
onTertiary = ColorRef(CorePaletteColor.Tertiary, 20),
|
|
||||||
tertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 30),
|
|
||||||
onTertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 90),
|
|
||||||
error = ColorRef(CorePaletteColor.Error, 80),
|
|
||||||
onError = ColorRef(CorePaletteColor.Error, 20),
|
|
||||||
errorContainer = ColorRef(CorePaletteColor.Error, 30),
|
|
||||||
onErrorContainer = ColorRef(CorePaletteColor.Error, 90),
|
|
||||||
surfaceDim = ColorRef(CorePaletteColor.Neutral, 6),
|
|
||||||
surface = ColorRef(CorePaletteColor.Neutral, 6),
|
|
||||||
surfaceBright = ColorRef(CorePaletteColor.Neutral, 24),
|
|
||||||
surfaceContainerLowest = ColorRef(CorePaletteColor.Neutral, 4),
|
|
||||||
surfaceContainerLow = ColorRef(CorePaletteColor.Neutral, 10),
|
|
||||||
surfaceContainer = ColorRef(CorePaletteColor.Neutral, 12),
|
|
||||||
surfaceContainerHigh = ColorRef(CorePaletteColor.Neutral, 17),
|
|
||||||
surfaceContainerHighest = ColorRef(CorePaletteColor.Neutral, 22),
|
|
||||||
onSurface = ColorRef(CorePaletteColor.Neutral, 90),
|
|
||||||
onSurfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 80),
|
|
||||||
outline = ColorRef(CorePaletteColor.NeutralVariant, 60),
|
|
||||||
outlineVariant = ColorRef(CorePaletteColor.NeutralVariant, 30),
|
|
||||||
inverseSurface = ColorRef(CorePaletteColor.Neutral, 90),
|
|
||||||
inverseOnSurface = ColorRef(CorePaletteColor.Neutral, 20),
|
|
||||||
inversePrimary = ColorRef(CorePaletteColor.Primary, 40),
|
|
||||||
surfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 30),
|
|
||||||
surfaceTint = ColorRef(CorePaletteColor.Primary, 80),
|
|
||||||
background = ColorRef(CorePaletteColor.Neutral, 6),
|
|
||||||
onBackground = ColorRef(CorePaletteColor.Neutral, 90),
|
|
||||||
scrim = ColorRef(CorePaletteColor.Neutral, 0),
|
|
||||||
)
|
|
||||||
|
|
||||||
val HighContrastLightColorScheme = ColorScheme<Color>(
|
|
||||||
primary = ColorRef(CorePaletteColor.Primary, 20),
|
|
||||||
onPrimary = ColorRef(CorePaletteColor.Primary, 100),
|
|
||||||
primaryContainer = ColorRef(CorePaletteColor.Primary, 30),
|
|
||||||
onPrimaryContainer = ColorRef(CorePaletteColor.Primary, 100),
|
|
||||||
secondary = ColorRef(CorePaletteColor.Secondary, 20),
|
|
||||||
onSecondary = ColorRef(CorePaletteColor.Secondary, 100),
|
|
||||||
secondaryContainer = ColorRef(CorePaletteColor.Secondary, 30),
|
|
||||||
onSecondaryContainer = ColorRef(CorePaletteColor.Secondary, 100),
|
|
||||||
tertiary = ColorRef(CorePaletteColor.Tertiary, 20),
|
|
||||||
onTertiary = ColorRef(CorePaletteColor.Tertiary, 100),
|
|
||||||
tertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 30),
|
|
||||||
onTertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 100),
|
|
||||||
error = ColorRef(CorePaletteColor.Error, 20),
|
|
||||||
onError = ColorRef(CorePaletteColor.Error, 100),
|
|
||||||
errorContainer = ColorRef(CorePaletteColor.Error, 30),
|
|
||||||
onErrorContainer = ColorRef(CorePaletteColor.Error, 100),
|
|
||||||
surfaceDim = ColorRef(CorePaletteColor.Neutral, 87),
|
|
||||||
surface = ColorRef(CorePaletteColor.Neutral, 98),
|
|
||||||
surfaceBright = ColorRef(CorePaletteColor.Neutral, 98),
|
|
||||||
surfaceContainerLowest = ColorRef(CorePaletteColor.Neutral, 100),
|
|
||||||
surfaceContainerLow = ColorRef(CorePaletteColor.Neutral, 96),
|
|
||||||
surfaceContainer = ColorRef(CorePaletteColor.Neutral, 94),
|
|
||||||
surfaceContainerHigh = ColorRef(CorePaletteColor.Neutral, 92),
|
|
||||||
surfaceContainerHighest = ColorRef(CorePaletteColor.Neutral, 90),
|
|
||||||
onSurface = ColorRef(CorePaletteColor.Neutral, 0),
|
|
||||||
onSurfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 0),
|
|
||||||
outline = ColorRef(CorePaletteColor.NeutralVariant, 20),
|
|
||||||
outlineVariant = ColorRef(CorePaletteColor.NeutralVariant, 30),
|
|
||||||
inverseSurface = ColorRef(CorePaletteColor.Neutral, 20),
|
|
||||||
inverseOnSurface = ColorRef(CorePaletteColor.Neutral, 100),
|
|
||||||
inversePrimary = ColorRef(CorePaletteColor.Primary, 80),
|
|
||||||
surfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 90),
|
|
||||||
surfaceTint = ColorRef(CorePaletteColor.Primary, 20),
|
|
||||||
background = ColorRef(CorePaletteColor.Neutral, 98),
|
|
||||||
onBackground = ColorRef(CorePaletteColor.Neutral, 0),
|
|
||||||
scrim = ColorRef(CorePaletteColor.Neutral, 0),
|
|
||||||
)
|
|
||||||
|
|
||||||
val HighContrastDarkColorScheme = ColorScheme<Color>(
|
|
||||||
primary = ColorRef(CorePaletteColor.Primary, 95),
|
|
||||||
onPrimary = ColorRef(CorePaletteColor.Primary, 0),
|
|
||||||
primaryContainer = ColorRef(CorePaletteColor.Primary, 80),
|
|
||||||
onPrimaryContainer = ColorRef(CorePaletteColor.Primary, 0),
|
|
||||||
secondary = ColorRef(CorePaletteColor.Secondary, 95),
|
|
||||||
onSecondary = ColorRef(CorePaletteColor.Secondary, 0),
|
|
||||||
secondaryContainer = ColorRef(CorePaletteColor.Secondary, 80),
|
|
||||||
onSecondaryContainer = ColorRef(CorePaletteColor.Secondary, 0),
|
|
||||||
tertiary = ColorRef(CorePaletteColor.Tertiary, 95),
|
|
||||||
onTertiary = ColorRef(CorePaletteColor.Tertiary, 0),
|
|
||||||
tertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 80),
|
|
||||||
onTertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 0),
|
|
||||||
error = ColorRef(CorePaletteColor.Error, 95),
|
|
||||||
onError = ColorRef(CorePaletteColor.Error, 0),
|
|
||||||
errorContainer = ColorRef(CorePaletteColor.Error, 80),
|
|
||||||
onErrorContainer = ColorRef(CorePaletteColor.Error, 0),
|
|
||||||
surfaceDim = ColorRef(CorePaletteColor.Neutral, 6),
|
|
||||||
surface = ColorRef(CorePaletteColor.Neutral, 6),
|
|
||||||
surfaceBright = ColorRef(CorePaletteColor.Neutral, 24),
|
|
||||||
surfaceContainerLowest = ColorRef(CorePaletteColor.Neutral, 4),
|
|
||||||
surfaceContainerLow = ColorRef(CorePaletteColor.Neutral, 10),
|
|
||||||
surfaceContainer = ColorRef(CorePaletteColor.Neutral, 12),
|
|
||||||
surfaceContainerHigh = ColorRef(CorePaletteColor.Neutral, 17),
|
|
||||||
surfaceContainerHighest = ColorRef(CorePaletteColor.Neutral, 22),
|
|
||||||
onSurface = ColorRef(CorePaletteColor.Neutral, 100),
|
|
||||||
onSurfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 100),
|
|
||||||
outline = ColorRef(CorePaletteColor.NeutralVariant, 95),
|
|
||||||
outlineVariant = ColorRef(CorePaletteColor.NeutralVariant, 80),
|
|
||||||
inverseSurface = ColorRef(CorePaletteColor.Neutral, 90),
|
|
||||||
inverseOnSurface = ColorRef(CorePaletteColor.Neutral, 0),
|
|
||||||
inversePrimary = ColorRef(CorePaletteColor.Primary, 20),
|
|
||||||
surfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 30),
|
|
||||||
surfaceTint = ColorRef(CorePaletteColor.Primary, 95),
|
|
||||||
background = ColorRef(CorePaletteColor.Neutral, 6),
|
|
||||||
onBackground = ColorRef(CorePaletteColor.Neutral, 100),
|
|
||||||
scrim = ColorRef(CorePaletteColor.Neutral, 0),
|
|
||||||
)
|
|
||||||
|
|
||||||
val BlackAndWhiteLightColorScheme = ColorScheme<Color?>(
|
|
||||||
primary = StaticColor(0xFF000000.toInt()),
|
|
||||||
onPrimary = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
primaryContainer = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
onPrimaryContainer = StaticColor(0xFF000000.toInt()),
|
|
||||||
inversePrimary = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
secondary = StaticColor(0xFF000000.toInt()),
|
|
||||||
onSecondary = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
secondaryContainer = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
onSecondaryContainer = StaticColor(0xFF000000.toInt()),
|
|
||||||
tertiary = StaticColor(0xFF000000.toInt()),
|
|
||||||
onTertiary = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
tertiaryContainer = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
onTertiaryContainer = StaticColor(0xFF000000.toInt()),
|
|
||||||
background = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
onBackground = StaticColor(0xFF000000.toInt()),
|
|
||||||
surface = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
onSurface = StaticColor(0xFF000000.toInt()),
|
|
||||||
surfaceVariant = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
onSurfaceVariant = StaticColor(0xFF000000.toInt()),
|
|
||||||
inverseSurface = StaticColor(0xFF000000.toInt()),
|
|
||||||
inverseOnSurface = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
error = null,
|
|
||||||
onError = null,
|
|
||||||
errorContainer = null,
|
|
||||||
onErrorContainer = null,
|
|
||||||
outline = StaticColor(0xFF000000.toInt()),
|
|
||||||
surfaceTint = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
outlineVariant = StaticColor(0xFF000000.toInt()),
|
|
||||||
scrim = StaticColor(0xFF000000.toInt()),
|
|
||||||
surfaceDim = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
surfaceBright = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
surfaceContainer = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
surfaceContainerHigh = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
surfaceContainerHighest = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
surfaceContainerLow = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
surfaceContainerLowest = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
)
|
|
||||||
|
|
||||||
val BlackAndWhiteDarkColorScheme = ColorScheme<Color?>(
|
|
||||||
primary = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
onPrimary = StaticColor(0xFF000000.toInt()),
|
|
||||||
primaryContainer = StaticColor(0xFF000000.toInt()),
|
|
||||||
onPrimaryContainer = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
inversePrimary = StaticColor(0xFF000000.toInt()),
|
|
||||||
secondary = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
onSecondary = StaticColor(0xFF000000.toInt()),
|
|
||||||
secondaryContainer = StaticColor(0xFF000000.toInt()),
|
|
||||||
onSecondaryContainer = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
tertiary = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
onTertiary = StaticColor(0xFF000000.toInt()),
|
|
||||||
tertiaryContainer = StaticColor(0xFF000000.toInt()),
|
|
||||||
onTertiaryContainer = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
background = StaticColor(0xFF000000.toInt()),
|
|
||||||
onBackground = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
surface = StaticColor(0xFF000000.toInt()),
|
|
||||||
onSurface = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
surfaceVariant = StaticColor(0xFF000000.toInt()),
|
|
||||||
onSurfaceVariant = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
inverseSurface = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
inverseOnSurface = StaticColor(0xFF000000.toInt()),
|
|
||||||
error = null,
|
|
||||||
onError = null,
|
|
||||||
errorContainer = null,
|
|
||||||
onErrorContainer = null,
|
|
||||||
outline = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
surfaceTint = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
outlineVariant = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
scrim = StaticColor(0xFFFFFFFF.toInt()),
|
|
||||||
surfaceDim = StaticColor(0xFF000000.toInt()),
|
|
||||||
surfaceBright = StaticColor(0xFF000000.toInt()),
|
|
||||||
surfaceContainer = StaticColor(0xFF000000.toInt()),
|
|
||||||
surfaceContainerHigh = StaticColor(0xFF000000.toInt()),
|
|
||||||
surfaceContainerHighest = StaticColor(0xFF000000.toInt()),
|
|
||||||
surfaceContainerLow = StaticColor(0xFF000000.toInt()),
|
|
||||||
surfaceContainerLowest = StaticColor(0xFF000000.toInt()),
|
|
||||||
)
|
|
||||||
@ -1,5 +1,9 @@
|
|||||||
package de.mm20.launcher2.themes
|
package de.mm20.launcher2.themes
|
||||||
|
|
||||||
|
import de.mm20.launcher2.themes.colors.Color
|
||||||
|
import de.mm20.launcher2.themes.colors.ColorRef
|
||||||
|
import de.mm20.launcher2.themes.colors.Colors
|
||||||
|
import de.mm20.launcher2.themes.colors.StaticColor
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.SerializationException
|
import kotlinx.serialization.SerializationException
|
||||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
package de.mm20.launcher2.themes
|
package de.mm20.launcher2.themes
|
||||||
|
|
||||||
|
import de.mm20.launcher2.themes.colors.Color
|
||||||
|
import de.mm20.launcher2.themes.colors.StaticColor
|
||||||
|
import de.mm20.launcher2.themes.shapes.Shape
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||||
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
||||||
@ -8,7 +11,6 @@ import kotlinx.serialization.encoding.Decoder
|
|||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.modules.SerializersModule
|
import kotlinx.serialization.modules.SerializersModule
|
||||||
import kotlinx.serialization.modules.polymorphic
|
|
||||||
|
|
||||||
internal val module = SerializersModule {
|
internal val module = SerializersModule {
|
||||||
contextual(Color::class, ColorSerializer)
|
contextual(Color::class, ColorSerializer)
|
||||||
|
|||||||
@ -2,12 +2,17 @@ package de.mm20.launcher2.themes
|
|||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||||
import de.mm20.launcher2.serialization.Json
|
import de.mm20.launcher2.themes.colors.Color
|
||||||
import kotlinx.coroutines.Dispatchers
|
import de.mm20.launcher2.themes.colors.ColorScheme
|
||||||
import kotlinx.coroutines.withContext
|
import de.mm20.launcher2.themes.colors.Colors
|
||||||
|
import de.mm20.launcher2.themes.colors.CorePalette
|
||||||
|
import de.mm20.launcher2.themes.colors.DefaultDarkColorScheme
|
||||||
|
import de.mm20.launcher2.themes.colors.DefaultLightColorScheme
|
||||||
|
import de.mm20.launcher2.themes.colors.EmptyCorePalette
|
||||||
|
import de.mm20.launcher2.themes.shapes.Shapes
|
||||||
|
import de.mm20.launcher2.themes.transparencies.Transparencies
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.SerializationException
|
import kotlinx.serialization.SerializationException
|
||||||
import kotlinx.serialization.json.JsonElement
|
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.JsonPrimitive
|
import kotlinx.serialization.json.JsonPrimitive
|
||||||
import kotlinx.serialization.json.contentOrNull
|
import kotlinx.serialization.json.contentOrNull
|
||||||
@ -22,6 +27,7 @@ data class ThemeBundle(
|
|||||||
val author: String? = null,
|
val author: String? = null,
|
||||||
val colors: Colors? = null,
|
val colors: Colors? = null,
|
||||||
val shapes: Shapes? = null,
|
val shapes: Shapes? = null,
|
||||||
|
val transparencies: Transparencies? = null,
|
||||||
/**
|
/**
|
||||||
* The file version, always 2 for the new theme format.
|
* The file version, always 2 for the new theme format.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -4,225 +4,24 @@ import android.content.Context
|
|||||||
import de.mm20.launcher2.backup.Backupable
|
import de.mm20.launcher2.backup.Backupable
|
||||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||||
import de.mm20.launcher2.database.AppDatabase
|
import de.mm20.launcher2.database.AppDatabase
|
||||||
import de.mm20.launcher2.preferences.ColorsDescriptor
|
import de.mm20.launcher2.themes.colors.Colors
|
||||||
import de.mm20.launcher2.preferences.ShapesDescriptor
|
import de.mm20.launcher2.themes.colors.ColorsRepository
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import de.mm20.launcher2.themes.shapes.ShapesRepository
|
||||||
|
import de.mm20.launcher2.themes.transparencies.TransparenciesRepository
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.flowOf
|
|
||||||
import kotlinx.coroutines.flow.flowOn
|
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.serialization.SerializationException
|
import kotlinx.serialization.SerializationException
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
class ThemeRepository(
|
class ThemeRepository(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val database: AppDatabase,
|
private val database: AppDatabase,
|
||||||
) : Backupable {
|
) : Backupable {
|
||||||
private val scope = CoroutineScope(Dispatchers.IO + Job())
|
val colors = ColorsRepository(context, database)
|
||||||
|
val shapes = ShapesRepository(context, database)
|
||||||
|
val transparencies = TransparenciesRepository(context, database)
|
||||||
|
|
||||||
fun getAllColors(): Flow<List<Colors>> {
|
|
||||||
return database.themeDao().getAllColors().map {
|
|
||||||
getBuiltInColors() + it.map { Colors(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getColors(id: UUID): Flow<Colors?> {
|
|
||||||
if (id == DefaultThemeId) return flowOf(getDefaultColors())
|
|
||||||
if (id == HighContrastThemeId) return flowOf(getHighContrastColors())
|
|
||||||
if (id == BlackAndWhiteThemeId) return flowOf(getBlackAndWhiteColors())
|
|
||||||
return database.themeDao().getColors(id).map { it?.let { Colors(it) } }.flowOn(Dispatchers.Default)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createColors(colors: Colors) {
|
|
||||||
scope.launch {
|
|
||||||
database.themeDao().insertColors(colors.toEntity())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateColors(colors: Colors) {
|
|
||||||
scope.launch {
|
|
||||||
database.themeDao().updateColors(colors.toEntity())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getColorsOrDefault(theme: ColorsDescriptor?): Flow<Colors> {
|
|
||||||
return when(theme) {
|
|
||||||
is ColorsDescriptor.HighContrast -> flowOf(getHighContrastColors())
|
|
||||||
is ColorsDescriptor.BlackAndWhite -> flowOf(getBlackAndWhiteColors())
|
|
||||||
is ColorsDescriptor.Custom -> {
|
|
||||||
val id = UUID.fromString(theme.id)
|
|
||||||
getColors(id).map { it ?: getDefaultColors() }
|
|
||||||
}
|
|
||||||
else -> flowOf(getDefaultColors())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getBuiltInColors(): List<Colors> {
|
|
||||||
return listOf(
|
|
||||||
getDefaultColors(),
|
|
||||||
getHighContrastColors(),
|
|
||||||
getBlackAndWhiteColors(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getDefaultColors(): Colors {
|
|
||||||
return Colors(
|
|
||||||
id = DefaultThemeId,
|
|
||||||
builtIn = true,
|
|
||||||
name = context.getString(R.string.preference_colors_default),
|
|
||||||
corePalette = EmptyCorePalette,
|
|
||||||
lightColorScheme = DefaultLightColorScheme,
|
|
||||||
darkColorScheme = DefaultDarkColorScheme,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getHighContrastColors(): Colors {
|
|
||||||
return Colors(
|
|
||||||
id = HighContrastThemeId,
|
|
||||||
builtIn = true,
|
|
||||||
name = context.getString(R.string.preference_colors_high_contrast),
|
|
||||||
corePalette = EmptyCorePalette,
|
|
||||||
lightColorScheme = HighContrastLightColorScheme,
|
|
||||||
darkColorScheme = HighContrastDarkColorScheme,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getBlackAndWhiteColors(): Colors {
|
|
||||||
return Colors(
|
|
||||||
id = BlackAndWhiteThemeId,
|
|
||||||
builtIn = true,
|
|
||||||
name = context.getString(R.string.preference_colors_bw),
|
|
||||||
corePalette = EmptyCorePalette,
|
|
||||||
lightColorScheme = BlackAndWhiteLightColorScheme,
|
|
||||||
darkColorScheme = BlackAndWhiteDarkColorScheme,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteColors(colors: Colors) {
|
|
||||||
scope.launch {
|
|
||||||
database.themeDao().deleteColors(colors.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getAllShapes(): Flow<List<Shapes>> {
|
|
||||||
return database.themeDao().getAllShapes().map {
|
|
||||||
getBuiltInShapes() + it.map { Shapes(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getShapes(id: UUID): Flow<Shapes?> {
|
|
||||||
if (id == DefaultThemeId) return flowOf(getDefaultShapes())
|
|
||||||
if (id == ExtraRoundShapesId) return flowOf(getExtraRoundShapes())
|
|
||||||
if (id == RectShapesId) return flowOf(getRectShapes())
|
|
||||||
if (id == CutShapesId) return flowOf(getCutShapes())
|
|
||||||
return database.themeDao().getShapes(id).map { it?.let { Shapes(it) } }.flowOn(Dispatchers.Default)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createShapes(shapes: Shapes) {
|
|
||||||
scope.launch {
|
|
||||||
database.themeDao().insertShapes(shapes.toEntity())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateShapes(shapes: Shapes) {
|
|
||||||
scope.launch {
|
|
||||||
database.themeDao().updateShapes(shapes.toEntity())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getShapesOrDefault(theme: ShapesDescriptor?): Flow<Shapes> {
|
|
||||||
return when(theme) {
|
|
||||||
is ShapesDescriptor.Custom -> {
|
|
||||||
val id = UUID.fromString(theme.id)
|
|
||||||
getShapes(id).map { it ?: getDefaultShapes() }
|
|
||||||
}
|
|
||||||
is ShapesDescriptor.ExtraRound -> flowOf(getExtraRoundShapes())
|
|
||||||
is ShapesDescriptor.Rect -> flowOf(getRectShapes())
|
|
||||||
is ShapesDescriptor.Cut -> flowOf(getCutShapes())
|
|
||||||
else -> flowOf(getDefaultShapes())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getBuiltInShapes(): List<Shapes> {
|
|
||||||
return listOf(
|
|
||||||
getDefaultShapes(),
|
|
||||||
getExtraRoundShapes(),
|
|
||||||
getRectShapes(),
|
|
||||||
getCutShapes(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getDefaultShapes(): Shapes {
|
|
||||||
return Shapes(
|
|
||||||
id = DefaultThemeId,
|
|
||||||
builtIn = true,
|
|
||||||
name = context.getString(R.string.preference_shapes_default),
|
|
||||||
baseShape = Shape(
|
|
||||||
corners = CornerStyle.Rounded,
|
|
||||||
radii = intArrayOf(12, 12, 12, 12),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getCutShapes(): Shapes {
|
|
||||||
return Shapes(
|
|
||||||
id = CutShapesId,
|
|
||||||
builtIn = true,
|
|
||||||
name = context.getString(R.string.preference_cards_shape_cut),
|
|
||||||
baseShape = Shape(
|
|
||||||
corners = CornerStyle.Cut,
|
|
||||||
radii = intArrayOf(12, 12, 12, 12),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getExtraRoundShapes(): Shapes {
|
|
||||||
return Shapes(
|
|
||||||
id = ExtraRoundShapesId,
|
|
||||||
builtIn = true,
|
|
||||||
name = context.getString(R.string.preference_shapes_extra_round),
|
|
||||||
baseShape = Shape(
|
|
||||||
corners = CornerStyle.Rounded,
|
|
||||||
radii = intArrayOf(24, 24, 24, 24),
|
|
||||||
),
|
|
||||||
extraSmall = Shape(
|
|
||||||
radii = intArrayOf(4, 4, 4, 4),
|
|
||||||
),
|
|
||||||
extraLarge = Shape(
|
|
||||||
radii = intArrayOf(36, 36, 36, 36),
|
|
||||||
),
|
|
||||||
extraLargeIncreased = Shape(
|
|
||||||
radii = intArrayOf(40, 40, 40, 40),
|
|
||||||
),
|
|
||||||
extraExtraLarge = Shape(
|
|
||||||
radii = intArrayOf(56, 56, 56, 56),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getRectShapes(): Shapes {
|
|
||||||
return Shapes(
|
|
||||||
id = RectShapesId,
|
|
||||||
builtIn = true,
|
|
||||||
name = context.getString(R.string.preference_shapes_rect),
|
|
||||||
baseShape = Shape(
|
|
||||||
corners = CornerStyle.Rounded,
|
|
||||||
radii = intArrayOf(0, 0, 0, 0),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteShapes(shapes: Shapes) {
|
|
||||||
scope.launch {
|
|
||||||
database.themeDao().deleteShapes(shapes.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun backup(toDir: File) = withContext(Dispatchers.IO) {
|
override suspend fun backup(toDir: File) = withContext(Dispatchers.IO) {
|
||||||
val dao = database.themeDao()
|
val dao = database.themeDao()
|
||||||
@ -257,5 +56,4 @@ class ThemeRepository(
|
|||||||
dao.insertAllColors(colors.map { it.toEntity() })
|
dao.insertAllColors(colors.map { it.toEntity() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package de.mm20.launcher2.themes
|
package de.mm20.launcher2.themes.colors
|
||||||
|
|
||||||
import de.mm20.launcher2.database.entities.ColorsEntity
|
import de.mm20.launcher2.database.entities.ColorsEntity
|
||||||
import de.mm20.launcher2.serialization.ColorIntAsHexSerializer
|
import de.mm20.launcher2.serialization.ColorIntAsHexSerializer
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
package de.mm20.launcher2.themes.colors
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import de.mm20.launcher2.database.AppDatabase
|
||||||
|
import de.mm20.launcher2.themes.BlackAndWhiteThemeId
|
||||||
|
import de.mm20.launcher2.themes.DefaultThemeId
|
||||||
|
import de.mm20.launcher2.themes.HighContrastThemeId
|
||||||
|
import de.mm20.launcher2.themes.R
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class ColorsRepository(
|
||||||
|
private val context: Context,
|
||||||
|
private val database: AppDatabase,
|
||||||
|
) {
|
||||||
|
private val scope = CoroutineScope(Dispatchers.IO + Job())
|
||||||
|
|
||||||
|
fun getAll(): Flow<List<Colors>> {
|
||||||
|
return database.themeDao().getAllColors().map {
|
||||||
|
getBuiltIn() + it.map { Colors(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(id: UUID): Flow<Colors?> {
|
||||||
|
if (id == DefaultThemeId) return flowOf(default)
|
||||||
|
if (id == HighContrastThemeId) return flowOf(highContrast)
|
||||||
|
if (id == BlackAndWhiteThemeId) return flowOf(blackAndWhite)
|
||||||
|
return database.themeDao().getColors(id).map { it?.let { Colors(it) } }
|
||||||
|
.flowOn(Dispatchers.Default)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun create(colors: Colors) {
|
||||||
|
scope.launch {
|
||||||
|
database.themeDao().insertColors(colors.toEntity())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(colors: Colors) {
|
||||||
|
scope.launch {
|
||||||
|
database.themeDao().updateColors(colors.toEntity())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun delete(colors: Colors) {
|
||||||
|
scope.launch {
|
||||||
|
database.themeDao().deleteColors(colors.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOrDefault(id: UUID?): Flow<Colors> {
|
||||||
|
if (id == null) return flowOf(default)
|
||||||
|
return get(id).map { it ?: default }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBuiltIn(): List<Colors> {
|
||||||
|
return listOf(
|
||||||
|
default,
|
||||||
|
highContrast,
|
||||||
|
blackAndWhite,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val default: Colors
|
||||||
|
get() = Colors(
|
||||||
|
id = DefaultThemeId,
|
||||||
|
builtIn = true,
|
||||||
|
name = context.getString(R.string.preference_colors_default),
|
||||||
|
corePalette = EmptyCorePalette,
|
||||||
|
lightColorScheme = DefaultLightColorScheme,
|
||||||
|
darkColorScheme = DefaultDarkColorScheme,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
private val highContrast: Colors
|
||||||
|
get() = Colors(
|
||||||
|
id = HighContrastThemeId,
|
||||||
|
builtIn = true,
|
||||||
|
name = context.getString(R.string.preference_colors_high_contrast),
|
||||||
|
corePalette = EmptyCorePalette,
|
||||||
|
lightColorScheme = HighContrastLightColorScheme,
|
||||||
|
darkColorScheme = HighContrastDarkColorScheme,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
private val blackAndWhite: Colors
|
||||||
|
get() = Colors(
|
||||||
|
id = BlackAndWhiteThemeId,
|
||||||
|
builtIn = true,
|
||||||
|
name = context.getString(R.string.preference_colors_bw),
|
||||||
|
corePalette = EmptyCorePalette,
|
||||||
|
lightColorScheme = BlackAndWhiteLightColorScheme,
|
||||||
|
darkColorScheme = BlackAndWhiteDarkColorScheme,
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -0,0 +1,235 @@
|
|||||||
|
package de.mm20.launcher2.themes.colors
|
||||||
|
|
||||||
|
val DefaultLightColorScheme = ColorScheme<Color>(
|
||||||
|
primary = ColorRef(CorePaletteColor.Primary, 40),
|
||||||
|
onPrimary = ColorRef(CorePaletteColor.Primary, 100),
|
||||||
|
primaryContainer = ColorRef(CorePaletteColor.Primary, 90),
|
||||||
|
onPrimaryContainer = ColorRef(CorePaletteColor.Primary, 30),
|
||||||
|
secondary = ColorRef(CorePaletteColor.Secondary, 40),
|
||||||
|
onSecondary = ColorRef(CorePaletteColor.Secondary, 100),
|
||||||
|
secondaryContainer = ColorRef(CorePaletteColor.Secondary, 90),
|
||||||
|
onSecondaryContainer = ColorRef(CorePaletteColor.Secondary, 30),
|
||||||
|
tertiary = ColorRef(CorePaletteColor.Tertiary, 40),
|
||||||
|
onTertiary = ColorRef(CorePaletteColor.Tertiary, 100),
|
||||||
|
tertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 90),
|
||||||
|
onTertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 30),
|
||||||
|
error = ColorRef(CorePaletteColor.Error, 40),
|
||||||
|
onError = ColorRef(CorePaletteColor.Error, 100),
|
||||||
|
errorContainer = ColorRef(CorePaletteColor.Error, 90),
|
||||||
|
onErrorContainer = ColorRef(CorePaletteColor.Error, 30),
|
||||||
|
surfaceDim = ColorRef(CorePaletteColor.Neutral, 87),
|
||||||
|
surface = ColorRef(CorePaletteColor.Neutral, 98),
|
||||||
|
surfaceBright = ColorRef(CorePaletteColor.Neutral, 98),
|
||||||
|
surfaceContainerLowest = ColorRef(CorePaletteColor.Neutral, 100),
|
||||||
|
surfaceContainerLow = ColorRef(CorePaletteColor.Neutral, 96),
|
||||||
|
surfaceContainer = ColorRef(CorePaletteColor.Neutral, 94),
|
||||||
|
surfaceContainerHigh = ColorRef(CorePaletteColor.Neutral, 92),
|
||||||
|
surfaceContainerHighest = ColorRef(CorePaletteColor.Neutral, 90),
|
||||||
|
onSurface = ColorRef(CorePaletteColor.Neutral, 10),
|
||||||
|
onSurfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 30),
|
||||||
|
outline = ColorRef(CorePaletteColor.NeutralVariant, 50),
|
||||||
|
outlineVariant = ColorRef(CorePaletteColor.NeutralVariant, 80),
|
||||||
|
inverseSurface = ColorRef(CorePaletteColor.Neutral, 20),
|
||||||
|
inverseOnSurface = ColorRef(CorePaletteColor.Neutral, 95),
|
||||||
|
inversePrimary = ColorRef(CorePaletteColor.Primary, 80),
|
||||||
|
surfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 90),
|
||||||
|
surfaceTint = ColorRef(CorePaletteColor.Primary, 40),
|
||||||
|
background = ColorRef(CorePaletteColor.Neutral, 98),
|
||||||
|
onBackground = ColorRef(CorePaletteColor.Neutral, 10),
|
||||||
|
scrim = ColorRef(CorePaletteColor.Neutral, 0),
|
||||||
|
)
|
||||||
|
|
||||||
|
val DefaultDarkColorScheme = ColorScheme<Color>(
|
||||||
|
primary = ColorRef(CorePaletteColor.Primary, 80),
|
||||||
|
onPrimary = ColorRef(CorePaletteColor.Primary, 20),
|
||||||
|
primaryContainer = ColorRef(CorePaletteColor.Primary, 30),
|
||||||
|
onPrimaryContainer = ColorRef(CorePaletteColor.Primary, 90),
|
||||||
|
secondary = ColorRef(CorePaletteColor.Secondary, 80),
|
||||||
|
onSecondary = ColorRef(CorePaletteColor.Secondary, 20),
|
||||||
|
secondaryContainer = ColorRef(CorePaletteColor.Secondary, 30),
|
||||||
|
onSecondaryContainer = ColorRef(CorePaletteColor.Secondary, 90),
|
||||||
|
tertiary = ColorRef(CorePaletteColor.Tertiary, 80),
|
||||||
|
onTertiary = ColorRef(CorePaletteColor.Tertiary, 20),
|
||||||
|
tertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 30),
|
||||||
|
onTertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 90),
|
||||||
|
error = ColorRef(CorePaletteColor.Error, 80),
|
||||||
|
onError = ColorRef(CorePaletteColor.Error, 20),
|
||||||
|
errorContainer = ColorRef(CorePaletteColor.Error, 30),
|
||||||
|
onErrorContainer = ColorRef(CorePaletteColor.Error, 90),
|
||||||
|
surfaceDim = ColorRef(CorePaletteColor.Neutral, 6),
|
||||||
|
surface = ColorRef(CorePaletteColor.Neutral, 6),
|
||||||
|
surfaceBright = ColorRef(CorePaletteColor.Neutral, 24),
|
||||||
|
surfaceContainerLowest = ColorRef(CorePaletteColor.Neutral, 4),
|
||||||
|
surfaceContainerLow = ColorRef(CorePaletteColor.Neutral, 10),
|
||||||
|
surfaceContainer = ColorRef(CorePaletteColor.Neutral, 12),
|
||||||
|
surfaceContainerHigh = ColorRef(CorePaletteColor.Neutral, 17),
|
||||||
|
surfaceContainerHighest = ColorRef(CorePaletteColor.Neutral, 22),
|
||||||
|
onSurface = ColorRef(CorePaletteColor.Neutral, 90),
|
||||||
|
onSurfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 80),
|
||||||
|
outline = ColorRef(CorePaletteColor.NeutralVariant, 60),
|
||||||
|
outlineVariant = ColorRef(CorePaletteColor.NeutralVariant, 30),
|
||||||
|
inverseSurface = ColorRef(CorePaletteColor.Neutral, 90),
|
||||||
|
inverseOnSurface = ColorRef(CorePaletteColor.Neutral, 20),
|
||||||
|
inversePrimary = ColorRef(CorePaletteColor.Primary, 40),
|
||||||
|
surfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 30),
|
||||||
|
surfaceTint = ColorRef(CorePaletteColor.Primary, 80),
|
||||||
|
background = ColorRef(CorePaletteColor.Neutral, 6),
|
||||||
|
onBackground = ColorRef(CorePaletteColor.Neutral, 90),
|
||||||
|
scrim = ColorRef(CorePaletteColor.Neutral, 0),
|
||||||
|
)
|
||||||
|
|
||||||
|
val HighContrastLightColorScheme = ColorScheme<Color>(
|
||||||
|
primary = ColorRef(CorePaletteColor.Primary, 20),
|
||||||
|
onPrimary = ColorRef(CorePaletteColor.Primary, 100),
|
||||||
|
primaryContainer = ColorRef(CorePaletteColor.Primary, 30),
|
||||||
|
onPrimaryContainer = ColorRef(CorePaletteColor.Primary, 100),
|
||||||
|
secondary = ColorRef(CorePaletteColor.Secondary, 20),
|
||||||
|
onSecondary = ColorRef(CorePaletteColor.Secondary, 100),
|
||||||
|
secondaryContainer = ColorRef(CorePaletteColor.Secondary, 30),
|
||||||
|
onSecondaryContainer = ColorRef(CorePaletteColor.Secondary, 100),
|
||||||
|
tertiary = ColorRef(CorePaletteColor.Tertiary, 20),
|
||||||
|
onTertiary = ColorRef(CorePaletteColor.Tertiary, 100),
|
||||||
|
tertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 30),
|
||||||
|
onTertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 100),
|
||||||
|
error = ColorRef(CorePaletteColor.Error, 20),
|
||||||
|
onError = ColorRef(CorePaletteColor.Error, 100),
|
||||||
|
errorContainer = ColorRef(CorePaletteColor.Error, 30),
|
||||||
|
onErrorContainer = ColorRef(CorePaletteColor.Error, 100),
|
||||||
|
surfaceDim = ColorRef(CorePaletteColor.Neutral, 87),
|
||||||
|
surface = ColorRef(CorePaletteColor.Neutral, 98),
|
||||||
|
surfaceBright = ColorRef(CorePaletteColor.Neutral, 98),
|
||||||
|
surfaceContainerLowest = ColorRef(CorePaletteColor.Neutral, 100),
|
||||||
|
surfaceContainerLow = ColorRef(CorePaletteColor.Neutral, 96),
|
||||||
|
surfaceContainer = ColorRef(CorePaletteColor.Neutral, 94),
|
||||||
|
surfaceContainerHigh = ColorRef(CorePaletteColor.Neutral, 92),
|
||||||
|
surfaceContainerHighest = ColorRef(CorePaletteColor.Neutral, 90),
|
||||||
|
onSurface = ColorRef(CorePaletteColor.Neutral, 0),
|
||||||
|
onSurfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 0),
|
||||||
|
outline = ColorRef(CorePaletteColor.NeutralVariant, 20),
|
||||||
|
outlineVariant = ColorRef(CorePaletteColor.NeutralVariant, 30),
|
||||||
|
inverseSurface = ColorRef(CorePaletteColor.Neutral, 20),
|
||||||
|
inverseOnSurface = ColorRef(CorePaletteColor.Neutral, 100),
|
||||||
|
inversePrimary = ColorRef(CorePaletteColor.Primary, 80),
|
||||||
|
surfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 90),
|
||||||
|
surfaceTint = ColorRef(CorePaletteColor.Primary, 20),
|
||||||
|
background = ColorRef(CorePaletteColor.Neutral, 98),
|
||||||
|
onBackground = ColorRef(CorePaletteColor.Neutral, 0),
|
||||||
|
scrim = ColorRef(CorePaletteColor.Neutral, 0),
|
||||||
|
)
|
||||||
|
|
||||||
|
val HighContrastDarkColorScheme = ColorScheme<Color>(
|
||||||
|
primary = ColorRef(CorePaletteColor.Primary, 95),
|
||||||
|
onPrimary = ColorRef(CorePaletteColor.Primary, 0),
|
||||||
|
primaryContainer = ColorRef(CorePaletteColor.Primary, 80),
|
||||||
|
onPrimaryContainer = ColorRef(CorePaletteColor.Primary, 0),
|
||||||
|
secondary = ColorRef(CorePaletteColor.Secondary, 95),
|
||||||
|
onSecondary = ColorRef(CorePaletteColor.Secondary, 0),
|
||||||
|
secondaryContainer = ColorRef(CorePaletteColor.Secondary, 80),
|
||||||
|
onSecondaryContainer = ColorRef(CorePaletteColor.Secondary, 0),
|
||||||
|
tertiary = ColorRef(CorePaletteColor.Tertiary, 95),
|
||||||
|
onTertiary = ColorRef(CorePaletteColor.Tertiary, 0),
|
||||||
|
tertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 80),
|
||||||
|
onTertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 0),
|
||||||
|
error = ColorRef(CorePaletteColor.Error, 95),
|
||||||
|
onError = ColorRef(CorePaletteColor.Error, 0),
|
||||||
|
errorContainer = ColorRef(CorePaletteColor.Error, 80),
|
||||||
|
onErrorContainer = ColorRef(CorePaletteColor.Error, 0),
|
||||||
|
surfaceDim = ColorRef(CorePaletteColor.Neutral, 6),
|
||||||
|
surface = ColorRef(CorePaletteColor.Neutral, 6),
|
||||||
|
surfaceBright = ColorRef(CorePaletteColor.Neutral, 24),
|
||||||
|
surfaceContainerLowest = ColorRef(CorePaletteColor.Neutral, 4),
|
||||||
|
surfaceContainerLow = ColorRef(CorePaletteColor.Neutral, 10),
|
||||||
|
surfaceContainer = ColorRef(CorePaletteColor.Neutral, 12),
|
||||||
|
surfaceContainerHigh = ColorRef(CorePaletteColor.Neutral, 17),
|
||||||
|
surfaceContainerHighest = ColorRef(CorePaletteColor.Neutral, 22),
|
||||||
|
onSurface = ColorRef(CorePaletteColor.Neutral, 100),
|
||||||
|
onSurfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 100),
|
||||||
|
outline = ColorRef(CorePaletteColor.NeutralVariant, 95),
|
||||||
|
outlineVariant = ColorRef(CorePaletteColor.NeutralVariant, 80),
|
||||||
|
inverseSurface = ColorRef(CorePaletteColor.Neutral, 90),
|
||||||
|
inverseOnSurface = ColorRef(CorePaletteColor.Neutral, 0),
|
||||||
|
inversePrimary = ColorRef(CorePaletteColor.Primary, 20),
|
||||||
|
surfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 30),
|
||||||
|
surfaceTint = ColorRef(CorePaletteColor.Primary, 95),
|
||||||
|
background = ColorRef(CorePaletteColor.Neutral, 6),
|
||||||
|
onBackground = ColorRef(CorePaletteColor.Neutral, 100),
|
||||||
|
scrim = ColorRef(CorePaletteColor.Neutral, 0),
|
||||||
|
)
|
||||||
|
|
||||||
|
val BlackAndWhiteLightColorScheme = ColorScheme<Color?>(
|
||||||
|
primary = StaticColor(0xFF000000.toInt()),
|
||||||
|
onPrimary = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
primaryContainer = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
onPrimaryContainer = StaticColor(0xFF000000.toInt()),
|
||||||
|
inversePrimary = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
secondary = StaticColor(0xFF000000.toInt()),
|
||||||
|
onSecondary = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
secondaryContainer = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
onSecondaryContainer = StaticColor(0xFF000000.toInt()),
|
||||||
|
tertiary = StaticColor(0xFF000000.toInt()),
|
||||||
|
onTertiary = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
tertiaryContainer = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
onTertiaryContainer = StaticColor(0xFF000000.toInt()),
|
||||||
|
background = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
onBackground = StaticColor(0xFF000000.toInt()),
|
||||||
|
surface = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
onSurface = StaticColor(0xFF000000.toInt()),
|
||||||
|
surfaceVariant = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
onSurfaceVariant = StaticColor(0xFF000000.toInt()),
|
||||||
|
inverseSurface = StaticColor(0xFF000000.toInt()),
|
||||||
|
inverseOnSurface = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
error = null,
|
||||||
|
onError = null,
|
||||||
|
errorContainer = null,
|
||||||
|
onErrorContainer = null,
|
||||||
|
outline = StaticColor(0xFF000000.toInt()),
|
||||||
|
surfaceTint = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
outlineVariant = StaticColor(0xFF000000.toInt()),
|
||||||
|
scrim = StaticColor(0xFF000000.toInt()),
|
||||||
|
surfaceDim = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
surfaceBright = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
surfaceContainer = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
surfaceContainerHigh = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
surfaceContainerHighest = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
surfaceContainerLow = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
surfaceContainerLowest = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
)
|
||||||
|
|
||||||
|
val BlackAndWhiteDarkColorScheme = ColorScheme<Color?>(
|
||||||
|
primary = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
onPrimary = StaticColor(0xFF000000.toInt()),
|
||||||
|
primaryContainer = StaticColor(0xFF000000.toInt()),
|
||||||
|
onPrimaryContainer = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
inversePrimary = StaticColor(0xFF000000.toInt()),
|
||||||
|
secondary = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
onSecondary = StaticColor(0xFF000000.toInt()),
|
||||||
|
secondaryContainer = StaticColor(0xFF000000.toInt()),
|
||||||
|
onSecondaryContainer = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
tertiary = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
onTertiary = StaticColor(0xFF000000.toInt()),
|
||||||
|
tertiaryContainer = StaticColor(0xFF000000.toInt()),
|
||||||
|
onTertiaryContainer = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
background = StaticColor(0xFF000000.toInt()),
|
||||||
|
onBackground = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
surface = StaticColor(0xFF000000.toInt()),
|
||||||
|
onSurface = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
surfaceVariant = StaticColor(0xFF000000.toInt()),
|
||||||
|
onSurfaceVariant = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
inverseSurface = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
inverseOnSurface = StaticColor(0xFF000000.toInt()),
|
||||||
|
error = null,
|
||||||
|
onError = null,
|
||||||
|
errorContainer = null,
|
||||||
|
onErrorContainer = null,
|
||||||
|
outline = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
surfaceTint = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
outlineVariant = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
scrim = StaticColor(0xFFFFFFFF.toInt()),
|
||||||
|
surfaceDim = StaticColor(0xFF000000.toInt()),
|
||||||
|
surfaceBright = StaticColor(0xFF000000.toInt()),
|
||||||
|
surfaceContainer = StaticColor(0xFF000000.toInt()),
|
||||||
|
surfaceContainerHigh = StaticColor(0xFF000000.toInt()),
|
||||||
|
surfaceContainerHighest = StaticColor(0xFF000000.toInt()),
|
||||||
|
surfaceContainerLow = StaticColor(0xFF000000.toInt()),
|
||||||
|
surfaceContainerLowest = StaticColor(0xFF000000.toInt()),
|
||||||
|
)
|
||||||
@ -1,7 +1,8 @@
|
|||||||
package de.mm20.launcher2.themes
|
package de.mm20.launcher2.themes.shapes
|
||||||
|
|
||||||
import de.mm20.launcher2.database.entities.ShapesEntity
|
import de.mm20.launcher2.database.entities.ShapesEntity
|
||||||
import de.mm20.launcher2.serialization.UUIDSerializer
|
import de.mm20.launcher2.serialization.UUIDSerializer
|
||||||
|
import de.mm20.launcher2.themes.ShapeSerializer
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@ -0,0 +1,129 @@
|
|||||||
|
package de.mm20.launcher2.themes.shapes
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import de.mm20.launcher2.database.AppDatabase
|
||||||
|
import de.mm20.launcher2.themes.CutShapesId
|
||||||
|
import de.mm20.launcher2.themes.DefaultThemeId
|
||||||
|
import de.mm20.launcher2.themes.ExtraRoundShapesId
|
||||||
|
import de.mm20.launcher2.themes.R
|
||||||
|
import de.mm20.launcher2.themes.RectShapesId
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class ShapesRepository(
|
||||||
|
private val context: Context,
|
||||||
|
private val database: AppDatabase,
|
||||||
|
) {
|
||||||
|
private val scope = CoroutineScope(Dispatchers.IO + Job())
|
||||||
|
|
||||||
|
fun getAll(): Flow<List<Shapes>> {
|
||||||
|
return database.themeDao().getAllShapes().map {
|
||||||
|
getBuiltIn() + it.map { Shapes(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(id: UUID): Flow<Shapes?> {
|
||||||
|
if (id == DefaultThemeId) return flowOf(default)
|
||||||
|
if (id == ExtraRoundShapesId) return flowOf(extraRound)
|
||||||
|
if (id == RectShapesId) return flowOf(rect)
|
||||||
|
if (id == CutShapesId) return flowOf(cut)
|
||||||
|
return database.themeDao().getShapes(id).map { it?.let { Shapes(it) } }
|
||||||
|
.flowOn(Dispatchers.Default)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun create(shapes: Shapes) {
|
||||||
|
scope.launch {
|
||||||
|
database.themeDao().insertShapes(shapes.toEntity())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(shapes: Shapes) {
|
||||||
|
scope.launch {
|
||||||
|
database.themeDao().updateShapes(shapes.toEntity())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(shapes: Shapes) {
|
||||||
|
scope.launch {
|
||||||
|
database.themeDao().deleteShapes(shapes.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOrDefault(id: UUID?): Flow<Shapes> {
|
||||||
|
if (id == null) return flowOf(default)
|
||||||
|
return get(id).map { it ?: default }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBuiltIn(): List<Shapes> {
|
||||||
|
return listOf(
|
||||||
|
default,
|
||||||
|
extraRound,
|
||||||
|
rect,
|
||||||
|
cut,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val default: Shapes
|
||||||
|
get() = Shapes(
|
||||||
|
id = DefaultThemeId,
|
||||||
|
builtIn = true,
|
||||||
|
name = context.getString(R.string.preference_shapes_default),
|
||||||
|
baseShape = Shape(
|
||||||
|
corners = CornerStyle.Rounded,
|
||||||
|
radii = intArrayOf(12, 12, 12, 12),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
private val cut: Shapes
|
||||||
|
get() = Shapes(
|
||||||
|
id = CutShapesId,
|
||||||
|
builtIn = true,
|
||||||
|
name = context.getString(R.string.preference_cards_shape_cut),
|
||||||
|
baseShape = Shape(
|
||||||
|
corners = CornerStyle.Cut,
|
||||||
|
radii = intArrayOf(12, 12, 12, 12),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
private val extraRound: Shapes
|
||||||
|
get() = Shapes(
|
||||||
|
id = ExtraRoundShapesId,
|
||||||
|
builtIn = true,
|
||||||
|
name = context.getString(R.string.preference_shapes_extra_round),
|
||||||
|
baseShape = Shape(
|
||||||
|
corners = CornerStyle.Rounded,
|
||||||
|
radii = intArrayOf(24, 24, 24, 24),
|
||||||
|
),
|
||||||
|
extraSmall = Shape(
|
||||||
|
radii = intArrayOf(4, 4, 4, 4),
|
||||||
|
),
|
||||||
|
extraLarge = Shape(
|
||||||
|
radii = intArrayOf(36, 36, 36, 36),
|
||||||
|
),
|
||||||
|
extraLargeIncreased = Shape(
|
||||||
|
radii = intArrayOf(40, 40, 40, 40),
|
||||||
|
),
|
||||||
|
extraExtraLarge = Shape(
|
||||||
|
radii = intArrayOf(56, 56, 56, 56),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
private val rect: Shapes
|
||||||
|
get() = Shapes(
|
||||||
|
id = RectShapesId,
|
||||||
|
builtIn = true,
|
||||||
|
name = context.getString(R.string.preference_shapes_rect),
|
||||||
|
baseShape = Shape(
|
||||||
|
corners = CornerStyle.Rounded,
|
||||||
|
radii = intArrayOf(0, 0, 0, 0),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
package de.mm20.launcher2.themes.transparencies
|
||||||
|
|
||||||
|
import de.mm20.launcher2.database.entities.TransparenciesEntity
|
||||||
|
import de.mm20.launcher2.serialization.UUIDSerializer
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Transparencies(
|
||||||
|
@Serializable(with = UUIDSerializer::class) val id: UUID = UUID.randomUUID(),
|
||||||
|
val builtIn: Boolean = false,
|
||||||
|
val name: String,
|
||||||
|
val background: Float? = null,
|
||||||
|
val surface: Float? = null,
|
||||||
|
val elevatedSurface: Float? = null,
|
||||||
|
) {
|
||||||
|
constructor(entity: TransparenciesEntity) : this(
|
||||||
|
id = entity.id,
|
||||||
|
builtIn = false,
|
||||||
|
name = entity.name,
|
||||||
|
background = entity.background,
|
||||||
|
surface = entity.surface,
|
||||||
|
elevatedSurface = entity.elevatedSurface,
|
||||||
|
)
|
||||||
|
|
||||||
|
internal fun toEntity(): TransparenciesEntity {
|
||||||
|
return TransparenciesEntity(
|
||||||
|
id = id,
|
||||||
|
name = name,
|
||||||
|
background = background,
|
||||||
|
surface = surface,
|
||||||
|
elevatedSurface = elevatedSurface,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
package de.mm20.launcher2.themes.transparencies
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import de.mm20.launcher2.database.AppDatabase
|
||||||
|
import de.mm20.launcher2.themes.DefaultThemeId
|
||||||
|
import de.mm20.launcher2.themes.R
|
||||||
|
import de.mm20.launcher2.themes.SemiTransparentId
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class TransparenciesRepository(
|
||||||
|
private val context: Context,
|
||||||
|
private val database: AppDatabase,
|
||||||
|
) {
|
||||||
|
private val scope = CoroutineScope(Dispatchers.IO + Job())
|
||||||
|
|
||||||
|
fun getAll(): Flow<List<Transparencies>> {
|
||||||
|
return database.themeDao().getAllTransparencies().map {
|
||||||
|
getBuiltIn() + it.map { Transparencies(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(id: UUID): Flow<Transparencies?> {
|
||||||
|
if (id == DefaultThemeId) return flowOf(default)
|
||||||
|
if (id == SemiTransparentId) return flowOf(semiTransparent)
|
||||||
|
return database.themeDao().getTransparencies(id).map { it?.let { Transparencies(it) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun create(transparencies: Transparencies) {
|
||||||
|
scope.launch {
|
||||||
|
database.themeDao().insertTransparencies(transparencies.toEntity())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(transparencies: Transparencies) {
|
||||||
|
scope.launch {
|
||||||
|
database.themeDao().updateTransparencies(transparencies.toEntity())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun delete(transparencies: Transparencies) {
|
||||||
|
scope.launch {
|
||||||
|
database.themeDao().deleteTransparencies(transparencies.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOrDefault(id: UUID?): Flow<Transparencies> {
|
||||||
|
if (id == null) return flowOf(default)
|
||||||
|
return get(id).map { it ?: default }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBuiltIn(): List<Transparencies> {
|
||||||
|
return listOf(
|
||||||
|
default,
|
||||||
|
semiTransparent,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val default: Transparencies
|
||||||
|
get() = Transparencies(
|
||||||
|
id = DefaultThemeId,
|
||||||
|
builtIn = true,
|
||||||
|
name = context.getString(R.string.preference_transparencies_default),
|
||||||
|
background = 0.85f,
|
||||||
|
surface = 1f,
|
||||||
|
elevatedSurface = 1f,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
private val semiTransparent: Transparencies
|
||||||
|
get() = Transparencies(
|
||||||
|
id = SemiTransparentId,
|
||||||
|
builtIn = true,
|
||||||
|
name = context.getString(R.string.preference_transparencies_semi_transparent),
|
||||||
|
background = 0.40f,
|
||||||
|
surface = 0.65f,
|
||||||
|
elevatedSurface = 0.85f,
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
@ -37,7 +37,7 @@ androidx-constraint-layout = "1.1.1"
|
|||||||
androidx-emojipicker = "1.5.0"
|
androidx-emojipicker = "1.5.0"
|
||||||
|
|
||||||
accompanist = "0.36.0"
|
accompanist = "0.36.0"
|
||||||
haze = "1.6.3"
|
haze = "1.6.4"
|
||||||
coil = "2.7.0"
|
coil = "2.7.0"
|
||||||
koin = "4.0.4"
|
koin = "4.0.4"
|
||||||
retrofit = "2.11.0"
|
retrofit = "2.11.0"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user