Spotless and ktlint

This commit is contained in:
Sad Ellie 2024-02-15 22:04:46 +03:00
parent 8b21721f48
commit eb00d8a76e
232 changed files with 1852 additions and 1601 deletions

7
.editorconfig Normal file
View File

@ -0,0 +1,7 @@
# https://editorconfig.org/
# This configuration is used by ktlint when spotless invokes it
[*.{kt,kts}]
ij_kotlin_allow_trailing_comma=true
ij_kotlin_allow_trailing_comma_on_call_site=true
ktlint_function_naming_ignore_when_annotated_with=Composable, Test

View File

@ -0,0 +1,42 @@
<!--
~ Unitto is a calculator for Android
~ Copyright (c) 2024 Elshan Agaev
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="spotlessApply" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="--init-script gradle/init.gradle.kts --no-configuration-cache" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="spotlessApply" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<ForceTestExec>false</ForceTestExec>
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,42 @@
<!--
~ Unitto is a calculator for Android
~ Copyright (c) 2024 Elshan Agaev
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="spotlessCheck" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="--init-script gradle/init.gradle.kts --no-configuration-cache" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="spotlessCheck" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<ForceTestExec>false</ForceTestExec>
<method v="2" />
</configuration>
</component>

View File

@ -76,14 +76,14 @@ internal fun ComponentActivity.App(prefs: AppPreferences?) {
dynamicThemeEnabled = prefs.enableDynamicTheme, dynamicThemeEnabled = prefs.enableDynamicTheme,
amoledThemeEnabled = prefs.enableAmoledTheme, amoledThemeEnabled = prefs.enableAmoledTheme,
customColor = prefs.customColor.toColor(), customColor = prefs.customColor.toColor(),
monetMode = prefs.monetMode monetMode = prefs.monetMode,
) )
} }
Themmo( Themmo(
themmoController = themmoController, themmoController = themmoController,
typography = TypographySystem, typography = TypographySystem,
animationSpec = tween(250) animationSpec = tween(250),
) { ) {
val backgroundColor = MaterialTheme.colorScheme.background val backgroundColor = MaterialTheme.colorScheme.background
val isDarkThemeEnabled = remember(backgroundColor) { backgroundColor.luminance() < 0.5f } val isDarkThemeEnabled = remember(backgroundColor) { backgroundColor.luminance() < 0.5f }
@ -113,9 +113,9 @@ internal fun ComponentActivity.App(prefs: AppPreferences?) {
navController = navController, navController = navController,
themmoController = it, themmoController = it,
startDestination = prefs.startingScreen, startDestination = prefs.startingScreen,
openDrawer = { drawerScope.launch { drawerState.open() } } openDrawer = { drawerScope.launch { drawerState.open() } },
) )
} },
) )
DisposableEffect(isDarkThemeEnabled) { DisposableEffect(isDarkThemeEnabled) {

View File

@ -68,7 +68,7 @@ internal class MainActivity : AppCompatActivity() {
LocalLocale provides locale, LocalLocale provides locale,
LocalWindowSize provides calculateWindowSizeClass(this@MainActivity), LocalWindowSize provides calculateWindowSizeClass(this@MainActivity),
LocalNumberTypography provides numbersTypography, LocalNumberTypography provides numbersTypography,
LocalHapticPreference provides (prefs?.enableVibrations ?: true) LocalHapticPreference provides (prefs?.enableVibrations ?: true),
) { ) {
App(prefs) App(prefs)
} }

View File

@ -18,6 +18,7 @@
package com.sadellie.unitto package com.sadellie.unitto
import android.annotation.SuppressLint
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Intent import android.content.Intent
import android.os.Build import android.os.Build
@ -26,6 +27,7 @@ import androidx.annotation.RequiresApi
@RequiresApi(Build.VERSION_CODES.N) @RequiresApi(Build.VERSION_CODES.N)
class UnittoTileService : TileService() { class UnittoTileService : TileService() {
@SuppressLint("StartActivityAndCollapseDeprecated")
override fun onClick() { override fun onClick() {
super.onClick() super.onClick()

View File

@ -31,7 +31,7 @@ class StartupBaselineProfile {
@Test @Test
fun generate() = baselineProfileRule.collect( fun generate() = baselineProfileRule.collect(
packageName = "com.sadellie.unitto", packageName = "com.sadellie.unitto",
includeInStartupProfile = true includeInStartupProfile = true,
) { ) {
startActivityAndWait() startActivityAndWait()
device.pressBack() device.pressBack()

View File

@ -61,7 +61,7 @@ class StartupBenchmark {
fun startupFullyPrecompiled() = startup(CompilationMode.Full()) fun startupFullyPrecompiled() = startup(CompilationMode.Full())
private fun startup( private fun startup(
compilationMode: CompilationMode compilationMode: CompilationMode,
) = benchmarkRule.measureRepeated( ) = benchmarkRule.measureRepeated(
packageName = "com.sadellie.unitto", packageName = "com.sadellie.unitto",
metrics = listOf(StartupTimingMetric()), metrics = listOf(StartupTimingMetric()),
@ -70,7 +70,7 @@ class StartupBenchmark {
startupMode = StartupMode.COLD, startupMode = StartupMode.COLD,
setupBlock = { setupBlock = {
pressHome() pressHome()
} },
) { ) {
startActivityAndWait() startActivityAndWait()
} }

View File

@ -24,8 +24,10 @@ package com.sadellie.unitto.core.base
object OutputFormat { object OutputFormat {
// Never use engineering notation // Never use engineering notation
const val PLAIN = 0 const val PLAIN = 0
// Use format that a lower API returns // Use format that a lower API returns
const val ALLOW_ENGINEERING = 1 const val ALLOW_ENGINEERING = 1
// App will try it's best to use engineering notation // App will try it's best to use engineering notation
const val FORCE_ENGINEERING = 2 const val FORCE_ENGINEERING = 2
} }

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.base package com.sadellie.unitto.core.base
@Suppress("ObjectPropertyName") @Suppress("ObjectPropertyName")
@ -100,14 +102,14 @@ object Token {
val all by lazy { val all by lazy {
listOf( listOf(
arsin, arcos, actan, sin, cos, tan, log, exp, ln arsin, arcos, actan, sin, cos, tan, log, exp, ln,
).sortedByDescending { it.length } ).sortedByDescending { it.length }
} }
val allWithOpeningBracket by lazy { val allWithOpeningBracket by lazy {
listOf( listOf(
arsinBracket, arcosBracket, actanBracket, sinBracket, cosBracket, tanBracket, arsinBracket, arcosBracket, actanBracket, sinBracket, cosBracket, tanBracket,
logBracket, expBracket, lnBracket logBracket, expBracket, lnBracket,
) )
} }
} }
@ -144,7 +146,7 @@ object Token {
Operator.multiply to listOf("*", ""), Operator.multiply to listOf("*", ""),
Func.arsin to listOf("arsin"), Func.arsin to listOf("arsin"),
Func.arcos to listOf("arcos"), Func.arcos to listOf("arcos"),
Func.actan to listOf("actan") Func.actan to listOf("actan"),
) )
} }
} }

View File

@ -150,7 +150,12 @@ class TokenTest {
@Test @Test
fun testSexyToUgly() { fun testSexyToUgly() {
listOf( listOf(
"", "÷", "×", "sin⁻¹", "cos⁻¹", "tan⁻¹" "",
"÷",
"×",
"sin⁻¹",
"cos⁻¹",
"tan⁻¹",
).forEach { ).forEach {
assert(it in Token.sexyToUgly.keys) assert(it in Token.sexyToUgly.keys)
} }

View File

@ -83,7 +83,7 @@ fun calculateWindowSizeClass(activity: Activity): WindowSizeClass {
@Immutable @Immutable
class WindowSizeClass( class WindowSizeClass(
val widthSizeClass: WindowWidthSizeClass, val widthSizeClass: WindowWidthSizeClass,
val heightSizeClass: WindowHeightSizeClass val heightSizeClass: WindowHeightSizeClass,
) { ) {
companion object { companion object {
/** /**
@ -118,7 +118,7 @@ class WindowSizeClass(
supportedWidthSizeClasses: Set<WindowWidthSizeClass> = supportedWidthSizeClasses: Set<WindowWidthSizeClass> =
WindowWidthSizeClass.DefaultSizeClasses, WindowWidthSizeClass.DefaultSizeClasses,
supportedHeightSizeClasses: Set<WindowHeightSizeClass> = supportedHeightSizeClasses: Set<WindowHeightSizeClass> =
WindowHeightSizeClass.DefaultSizeClasses WindowHeightSizeClass.DefaultSizeClasses,
): WindowSizeClass { ): WindowSizeClass {
val windowWidthSizeClass = val windowWidthSizeClass =
WindowWidthSizeClass.fromWidth(size.width, density, supportedWidthSizeClasses) WindowWidthSizeClass.fromWidth(size.width, density, supportedWidthSizeClasses)
@ -225,7 +225,9 @@ value class WindowWidthSizeClass private constructor(private val value: Int) :
/** Calculates the [WindowWidthSizeClass] for a given [width] */ /** Calculates the [WindowWidthSizeClass] for a given [width] */
internal fun fromWidth(width: Dp): WindowWidthSizeClass { internal fun fromWidth(width: Dp): WindowWidthSizeClass {
return fromWidth( return fromWidth(
with(defaultDensity) { width.toPx() }, defaultDensity, DefaultSizeClasses with(defaultDensity) { width.toPx() },
defaultDensity,
DefaultSizeClasses,
) )
} }
@ -236,7 +238,7 @@ value class WindowWidthSizeClass private constructor(private val value: Int) :
internal fun fromWidth( internal fun fromWidth(
width: Float, width: Float,
density: Density, density: Density,
supportedSizeClasses: Set<WindowWidthSizeClass> supportedSizeClasses: Set<WindowWidthSizeClass>,
): WindowWidthSizeClass { ): WindowWidthSizeClass {
require(width >= 0) { "Width must not be negative" } require(width >= 0) { "Width must not be negative" }
require(supportedSizeClasses.isNotEmpty()) { "Must support at least one size class" } require(supportedSizeClasses.isNotEmpty()) { "Must support at least one size class" }
@ -323,7 +325,9 @@ value class WindowHeightSizeClass private constructor(private val value: Int) :
/** Calculates the [WindowHeightSizeClass] for a given [height] */ /** Calculates the [WindowHeightSizeClass] for a given [height] */
internal fun fromHeight(height: Dp): WindowHeightSizeClass { internal fun fromHeight(height: Dp): WindowHeightSizeClass {
return fromHeight( return fromHeight(
with(defaultDensity) { height.toPx() }, defaultDensity, DefaultSizeClasses with(defaultDensity) { height.toPx() },
defaultDensity,
DefaultSizeClasses,
) )
} }
@ -334,7 +338,7 @@ value class WindowHeightSizeClass private constructor(private val value: Int) :
internal fun fromHeight( internal fun fromHeight(
height: Float, height: Float,
density: Density, density: Density,
supportedSizeClasses: Set<WindowHeightSizeClass> supportedSizeClasses: Set<WindowHeightSizeClass>,
): WindowHeightSizeClass { ): WindowHeightSizeClass {
require(height >= 0) { "Width must not be negative" } require(height >= 0) { "Width must not be negative" }
require(supportedSizeClasses.isNotEmpty()) { "Must support at least one size class" } require(supportedSizeClasses.isNotEmpty()) { "Must support at least one size class" }

View File

@ -44,16 +44,22 @@ fun NavGraphBuilder.unittoComposable(
route: String, route: String,
arguments: List<NamedNavArgument> = emptyList(), arguments: List<NamedNavArgument> = emptyList(),
deepLinks: List<NavDeepLink> = emptyList(), deepLinks: List<NavDeepLink> = emptyList(),
enterTransition: (@JvmSuppressWildcards enterTransition: (
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?)? = { unittoFadeIn() }, @JvmSuppressWildcards
exitTransition: (@JvmSuppressWildcards AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?)? = { unittoFadeOut() }, )? = { unittoFadeIn() },
popEnterTransition: (@JvmSuppressWildcards exitTransition: (
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?)? = @JvmSuppressWildcards
enterTransition, AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?
popExitTransition: (@JvmSuppressWildcards )? = { unittoFadeOut() },
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?)? = popEnterTransition: (
exitTransition, @JvmSuppressWildcards
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?
)? = enterTransition,
popExitTransition: (
@JvmSuppressWildcards
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?
)? = exitTransition,
content: @Composable AnimatedContentScope.(NavBackStackEntry) -> Unit, content: @Composable AnimatedContentScope.(NavBackStackEntry) -> Unit,
): Unit = composable( ): Unit = composable(
route = route, route = route,
@ -79,22 +85,26 @@ fun NavGraphBuilder.unittoStackedComposable(
enterTransition = { enterTransition = {
slideInHorizontally( slideInHorizontally(
animationSpec = unittoEnterTween(), animationSpec = unittoEnterTween(),
initialOffsetX = { (it * 0.2f).toInt() }) + unittoFadeIn() initialOffsetX = { (it * 0.2f).toInt() },
) + unittoFadeIn()
}, },
exitTransition = { exitTransition = {
slideOutHorizontally( slideOutHorizontally(
animationSpec = unittoExitTween(), animationSpec = unittoExitTween(),
targetOffsetX = { -(it * 0.2f).toInt() }) + unittoFadeOut() targetOffsetX = { -(it * 0.2f).toInt() },
) + unittoFadeOut()
}, },
popEnterTransition = { popEnterTransition = {
slideInHorizontally( slideInHorizontally(
animationSpec = unittoEnterTween(), animationSpec = unittoEnterTween(),
initialOffsetX = { -(it * 0.2f).toInt() }) + unittoFadeIn() initialOffsetX = { -(it * 0.2f).toInt() },
) + unittoFadeIn()
}, },
popExitTransition = { popExitTransition = {
slideOutHorizontally( slideOutHorizontally(
animationSpec = unittoExitTween(), animationSpec = unittoExitTween(),
targetOffsetX = { (it * 0.2f).toInt() }) + unittoFadeOut() targetOffsetX = { (it * 0.2f).toInt() },
) + unittoFadeOut()
}, },
content = content, content = content,
) )
@ -128,7 +138,7 @@ fun NavGraphBuilder.unittoNavigation(
exitTransition = exitTransition, exitTransition = exitTransition,
popEnterTransition = popEnterTransition, popEnterTransition = popEnterTransition,
popExitTransition = popExitTransition, popExitTransition = popExitTransition,
builder = builder builder = builder,
) )
private const val ENTER_DURATION = 350 private const val ENTER_DURATION = 350

View File

@ -48,7 +48,7 @@ suspend fun Context.pushDynamicShortcut(
val shortcutCompat = shortcutInfoCompat( val shortcutCompat = shortcutInfoCompat(
context = context, context = context,
route = drawerItem.graph, route = drawerItem.graph,
shortcut = shortcut shortcut = shortcut,
) )
kotlin.runCatching { kotlin.runCatching {
@ -71,7 +71,7 @@ fun Context.addShortcut(
val shortcutCompat = shortcutInfoCompat( val shortcutCompat = shortcutInfoCompat(
context = context, context = context,
route = drawerItem.graph, route = drawerItem.graph,
shortcut = shortcut shortcut = shortcut,
) )
val shortCutIntent = ShortcutManagerCompat.createShortcutResultIntent(context, shortcutCompat) val shortCutIntent = ShortcutManagerCompat.createShortcutResultIntent(context, shortcutCompat)
@ -80,7 +80,7 @@ fun Context.addShortcut(
ShortcutManagerCompat.requestPinShortcut( ShortcutManagerCompat.requestPinShortcut(
context, context,
shortcutCompat, shortcutCompat,
PendingIntent.getBroadcast(context, 0, shortCutIntent, FLAG_IMMUTABLE).intentSender PendingIntent.getBroadcast(context, 0, shortCutIntent, FLAG_IMMUTABLE).intentSender,
) )
} catch (e: Exception) { } catch (e: Exception) {
showToast(context, e.message ?: "Error") showToast(context, e.message ?: "Error")
@ -101,8 +101,8 @@ private fun Context.shortcutInfoCompat(
Intent.ACTION_VIEW, Intent.ACTION_VIEW,
Uri.parse("app://com.sadellie.unitto/$route"), Uri.parse("app://com.sadellie.unitto/$route"),
context, context,
context.javaClass context.javaClass,
) ),
) )
.build() .build()
} }

View File

@ -50,7 +50,7 @@ fun Button(
border: BorderStroke? = null, border: BorderStroke? = null,
contentPadding: PaddingValues = ButtonDefaults.ContentPadding, contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
content: @Composable RowScope.() -> Unit content: @Composable RowScope.() -> Unit,
) { ) {
Surface( Surface(
modifier = modifier.squashable( modifier = modifier.squashable(
@ -58,7 +58,7 @@ fun Button(
onLongClick = onLongClick, onLongClick = onLongClick,
interactionSource = interactionSource, interactionSource = interactionSource,
cornerRadiusRange = 30..50, cornerRadiusRange = 30..50,
enabled = enabled enabled = enabled,
), ),
color = containerColor, color = containerColor,
contentColor = contentColor, contentColor = contentColor,
@ -70,12 +70,12 @@ fun Button(
Modifier Modifier
.defaultMinSize( .defaultMinSize(
minWidth = ButtonDefaults.MinWidth, minWidth = ButtonDefaults.MinWidth,
minHeight = ButtonDefaults.MinHeight minHeight = ButtonDefaults.MinHeight,
) )
.padding(contentPadding), .padding(contentPadding),
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
content = content content = content,
) )
} }
} }

View File

@ -70,16 +70,16 @@ fun FilterChip(
.border( .border(
width = 1.dp, width = 1.dp,
color = borderColor.value, color = borderColor.value,
shape = FilterChipDefaults.shape shape = FilterChipDefaults.shape,
) )
.height(FilterChipDefaults.Height) .height(FilterChipDefaults.Height)
.padding(horizontal = 16.dp), .padding(horizontal = 16.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically,
) { ) {
Text( Text(
text = label, text = label,
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
color = if (isSelected) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSurfaceVariant color = if (isSelected) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSurfaceVariant,
) )
} }
} }
@ -100,17 +100,17 @@ fun AssistChip(
.border( .border(
width = 1.dp, width = 1.dp,
color = MaterialTheme.colorScheme.outline, color = MaterialTheme.colorScheme.outline,
shape = AssistChipDefaults.shape shape = AssistChipDefaults.shape,
) )
.height(32.dp) .height(32.dp)
.padding(horizontal = 8.dp), .padding(horizontal = 8.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically,
) { ) {
Icon( Icon(
modifier = Modifier.height(AssistChipDefaults.IconSize), modifier = Modifier.height(AssistChipDefaults.IconSize),
imageVector = imageVector, imageVector = imageVector,
contentDescription = contentDescription, contentDescription = contentDescription,
tint = MaterialTheme.colorScheme.onSurfaceVariant tint = MaterialTheme.colorScheme.onSurfaceVariant,
) )
} }
} }
@ -121,7 +121,7 @@ fun PreviewAssistChip() {
AssistChip( AssistChip(
onClick = {}, onClick = {},
imageVector = Icons.Default.Settings, imageVector = Icons.Default.Settings,
contentDescription = "" contentDescription = "",
) )
} }

View File

@ -33,13 +33,13 @@ internal fun DrawerItem(
destination: DrawerItem, destination: DrawerItem,
icon: ImageVector, icon: ImageVector,
selected: Boolean, selected: Boolean,
onClick: (DrawerItem) -> Unit onClick: (DrawerItem) -> Unit,
) { ) {
NavigationDrawerItem( NavigationDrawerItem(
modifier = modifier, modifier = modifier,
label = { Text(stringResource(destination.name)) }, label = { Text(stringResource(destination.name)) },
icon = { Icon(icon, stringResource(destination.name)) }, icon = { Icon(icon, stringResource(destination.name)) },
selected = selected, selected = selected,
onClick = { onClick(destination) } onClick = { onClick(destination) },
) )
} }

View File

@ -43,8 +43,8 @@ fun Header(
start = 56.dp, start = 56.dp,
end = 16.dp, end = 16.dp,
top = 24.dp, top = 24.dp,
bottom = 12.dp bottom = 12.dp,
) ),
) { ) {
Text( Text(
modifier = modifier modifier = modifier
@ -53,6 +53,6 @@ fun Header(
.fillMaxWidth(), .fillMaxWidth(),
text = text, text = text,
style = MaterialTheme.typography.titleSmall, style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.primary color = MaterialTheme.colorScheme.primary,
) )
} }

View File

@ -64,15 +64,24 @@ fun BasicKeyboardButton(
Box( Box(
modifier = modifier modifier = modifier
.squashable( .squashable(
onClick = { onClick(); vibrate() }, onClick = {
onLongClick = if (onLongClick != null) { { onLongClick(); vibrate() } } else null, onClick()
vibrate()
},
onLongClick = if (onLongClick != null) {
{
onLongClick()
vibrate()
}
} else {
null
},
interactionSource = remember { MutableInteractionSource() }, interactionSource = remember { MutableInteractionSource() },
cornerRadiusRange = 30..50, cornerRadiusRange = 30..50,
animationSpec = tween(200) animationSpec = tween(200),
) )
.background(containerColor) .background(containerColor),
, contentAlignment = Alignment.Center,
contentAlignment = Alignment.Center
) { ) {
Icon( Icon(
imageVector = icon, imageVector = icon,
@ -84,7 +93,7 @@ fun BasicKeyboardButton(
scaleX = contentHeight scaleX = contentHeight
scaleY = contentHeight scaleY = contentHeight
}, },
tint = iconColor tint = iconColor,
) )
} }
} }
@ -173,22 +182,25 @@ fun KeyboardButtonTertiary(
) )
} }
object KeyboardButtonToken {
/** /**
* Mostly for main button in portrait mode. Changes icon size inside. * Mostly for main button in portrait mode. Changes icon size inside.
*/ */
const val KeyboardButtonContentHeightTall = 1.1f const val CONTENT_HEIGHT_TALL = 1.1f
/** /**
* Mostly for additional button in portrait mode. Changes icon size inside. * Mostly for additional button in portrait mode. Changes icon size inside.
*/ */
const val KeyboardButtonContentHeightTallAdditional = 1.6f const val CONTENT_HEIGHT_TALL_ADDITIONAL = 1.6f
/** /**
* Mostly for main button in landscape mode. Changes icon size inside. * Mostly for main button in landscape mode. Changes icon size inside.
*/ */
const val KeyboardButtonContentHeightShort = 1.3f const val CONTENT_HEIGHT_SHORT = 1.3f
/** /**
* Mostly for additional button in landscape mode. Changes icon size inside. * Mostly for additional button in landscape mode. Changes icon size inside.
*/ */
const val KeyboardButtonContentHeightShortAdditional = 1.1f const val CONTENT_HEIGHT_SHORT_ADDITIONAL = 1.1f
}

View File

@ -49,7 +49,7 @@ fun KeypadFlow(
columns: Int, columns: Int,
@IntRange(0, 100) horizontalPadding: Int = 10, @IntRange(0, 100) horizontalPadding: Int = 10,
@IntRange(0, 100) verticalPadding: Int = 10, @IntRange(0, 100) verticalPadding: Int = 10,
content: @Composable FlowRowScope.(width: Float, height: Float) -> Unit content: @Composable FlowRowScope.(width: Float, height: Float) -> Unit,
) { ) {
val height: Float = remember { (1f - verticalPadding / 100f) / rows } val height: Float = remember { (1f - verticalPadding / 100f) / rows }
val width: Float = remember { (1f - horizontalPadding / 100f) / columns } val width: Float = remember { (1f - horizontalPadding / 100f) / columns }
@ -58,7 +58,7 @@ fun KeypadFlow(
modifier = modifier, modifier = modifier,
maxItemsInEachRow = columns, maxItemsInEachRow = columns,
horizontalArrangement = Arrangement.SpaceAround, horizontalArrangement = Arrangement.SpaceAround,
verticalArrangement = Arrangement.SpaceAround verticalArrangement = Arrangement.SpaceAround,
) { ) {
content(width, height) content(width, height)
} }

View File

@ -57,12 +57,12 @@ fun ListItem(
.padding(start = 16.dp, end = 24.dp) .padding(start = 16.dp, end = 24.dp)
.heightIn(min = if (supportingContent == null) 56.dp else 72.dp), .heightIn(min = if (supportingContent == null) 56.dp else 72.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp), horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically,
) { ) {
leadingContent?.let { leadingContent?.let {
ProvideColor( ProvideColor(
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
content = it content = it,
) )
} }
@ -70,20 +70,20 @@ fun ListItem(
ProvideStyle( ProvideStyle(
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.onSurface,
textStyle = MaterialTheme.typography.bodyLarge, textStyle = MaterialTheme.typography.bodyLarge,
content = headlineContent content = headlineContent,
) )
supportingContent?.let { supportingContent?.let {
ProvideStyle( ProvideStyle(
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
textStyle = MaterialTheme.typography.bodyMedium, textStyle = MaterialTheme.typography.bodyMedium,
content = it content = it,
) )
} }
} }
trailingContent?.let { trailingContent?.let {
ProvideColor( ProvideColor(
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
content = it content = it,
) )
} }
} }
@ -106,10 +106,10 @@ fun ListItem(
imageVector = icon, imageVector = icon,
contentDescription = iconDescription, contentDescription = iconDescription,
modifier = Modifier.size(24.dp), modifier = Modifier.size(24.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant tint = MaterialTheme.colorScheme.onSurfaceVariant,
) )
}, },
trailingContent = trailing trailingContent = trailing,
) )
@Composable @Composable
@ -120,14 +120,14 @@ fun ListItem(
iconDescription: String = headlineText, iconDescription: String = headlineText,
supportingText: String? = null, supportingText: String? = null,
switchState: Boolean, switchState: Boolean,
onSwitchChange: (Boolean) -> Unit onSwitchChange: (Boolean) -> Unit,
) = ListItem( ) = ListItem(
modifier = modifier modifier = modifier
.clickable( .clickable(
interactionSource = remember { MutableInteractionSource() }, interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(), indication = rememberRipple(),
onClick = { onSwitchChange(!switchState) }, onClick = { onSwitchChange(!switchState) },
role = Role.Switch role = Role.Switch,
), ),
headlineText = headlineText, headlineText = headlineText,
supportingText = supportingText, supportingText = supportingText,
@ -136,9 +136,9 @@ fun ListItem(
trailing = { trailing = {
Switch( Switch(
checked = switchState, checked = switchState,
onCheckedChange = { onSwitchChange(it) } onCheckedChange = { onSwitchChange(it) },
) )
} },
) )
@Preview @Preview
@ -152,7 +152,7 @@ fun PreviewListItem1() {
leadingContent = { leadingContent = {
Icon( Icon(
imageVector = Icons.Default.Home, imageVector = Icons.Default.Home,
contentDescription = null contentDescription = null,
) )
}, },
) )
@ -171,7 +171,7 @@ fun PreviewListItem1() {
supportingText = "Support text support text support text support text", supportingText = "Support text support text support text support text",
modifier = Modifier, modifier = Modifier,
trailing = {}, trailing = {},
iconDescription = "" iconDescription = "",
) )
ListItem( ListItem(

View File

@ -47,7 +47,7 @@ fun Modifier.squashable(
val cornerRadius: Int by animateIntAsState( val cornerRadius: Int by animateIntAsState(
targetValue = if (isPressed) cornerRadiusRange.first else cornerRadiusRange.last, targetValue = if (isPressed) cornerRadiusRange.first else cornerRadiusRange.last,
animationSpec = animationSpec, animationSpec = animationSpec,
label = "Squashed animation" label = "Squashed animation",
) )
this this
@ -58,7 +58,7 @@ fun Modifier.squashable(
interactionSource = interactionSource, interactionSource = interactionSource,
indication = rememberRipple(), indication = rememberRipple(),
role = role, role = role,
enabled = enabled enabled = enabled,
) )
} }
@ -75,7 +75,7 @@ fun Modifier.squashable(
val cornerRadius: Dp by animateDpAsState( val cornerRadius: Dp by animateDpAsState(
targetValue = if (isPressed) cornerRadiusRange.start else cornerRadiusRange.endInclusive, targetValue = if (isPressed) cornerRadiusRange.start else cornerRadiusRange.endInclusive,
animationSpec = animationSpec, animationSpec = animationSpec,
label = "Squashed animation" label = "Squashed animation",
) )
this this
@ -86,6 +86,6 @@ fun Modifier.squashable(
interactionSource = interactionSource, interactionSource = interactionSource,
indication = rememberRipple(), indication = rememberRipple(),
role = role, role = role,
enabled = enabled enabled = enabled,
) )
} }

View File

@ -36,7 +36,7 @@ fun NavigateUpButton(onClick: () -> Unit) {
IconButton(onClick = onClick) { IconButton(onClick = onClick) {
Icon( Icon(
Icons.AutoMirrored.Outlined.ArrowBack, Icons.AutoMirrored.Outlined.ArrowBack,
contentDescription = stringResource(R.string.navigate_up_description) contentDescription = stringResource(R.string.navigate_up_description),
) )
} }
} }

View File

@ -73,7 +73,7 @@ class DrawerState(
initialValue = initialValue, initialValue = initialValue,
positionalThreshold = { distance -> distance * 0.5f }, positionalThreshold = { distance -> distance * 0.5f },
velocityThreshold = { with(requireNotNull(density)) { 400.dp.toPx() } }, velocityThreshold = { with(requireNotNull(density)) { 400.dp.toPx() } },
animationSpec = tween() animationSpec = tween(),
) )
val isOpen: Boolean val isOpen: Boolean
@ -89,10 +89,10 @@ class DrawerState(
suspend fun close() = anchoredDraggableState.animateTo(DrawerValue.Closed) suspend fun close() = anchoredDraggableState.animateTo(DrawerValue.Closed)
companion object { companion object {
internal fun Saver() = internal fun saver() =
Saver<DrawerState, DrawerValue>( Saver<DrawerState, DrawerValue>(
save = { it.currentValue }, save = { it.currentValue },
restore = { DrawerState(it) } restore = { DrawerState(it) },
) )
} }
} }
@ -101,7 +101,7 @@ class DrawerState(
fun rememberDrawerState( fun rememberDrawerState(
initialValue: DrawerValue = DrawerValue.Closed, initialValue: DrawerValue = DrawerValue.Closed,
): DrawerState { ): DrawerState {
return rememberSaveable(saver = DrawerState.Saver()) { return rememberSaveable(saver = DrawerState.saver()) {
DrawerState(initialValue) DrawerState(initialValue)
} }
} }
@ -124,17 +124,17 @@ fun NavigationDrawer(
PermanentDrawerSheet( PermanentDrawerSheet(
modifier = Modifier modifier = Modifier
.fillMaxHeight() .fillMaxHeight()
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState()),
) { ) {
SheetContent( SheetContent(
mainTabs = mainTabs, mainTabs = mainTabs,
additionalTabs = additionalTabs, additionalTabs = additionalTabs,
currentDestination = currentDestination, currentDestination = currentDestination,
onItemClick = onItemClick onItemClick = onItemClick,
) )
} }
}, },
content = content content = content,
) )
} else { } else {
UnittoModalNavigationDrawer( UnittoModalNavigationDrawer(
@ -143,19 +143,19 @@ fun NavigationDrawer(
ModalDrawerSheet( ModalDrawerSheet(
modifier = Modifier modifier = Modifier
.fillMaxHeight() .fillMaxHeight()
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState()),
) { ) {
SheetContent( SheetContent(
mainTabs = mainTabs, mainTabs = mainTabs,
additionalTabs = additionalTabs, additionalTabs = additionalTabs,
currentDestination = currentDestination, currentDestination = currentDestination,
onItemClick = onItemClick onItemClick = onItemClick,
) )
} }
}, },
gesturesEnabled = gesturesEnabled, gesturesEnabled = gesturesEnabled,
state = state, state = state,
content = content content = content,
) )
} }
} }
@ -173,7 +173,7 @@ private fun UnittoModalNavigationDrawer(
val drawerScope = rememberCoroutineScope() val drawerScope = rememberCoroutineScope()
Box( Box(
modifier = modifier.fillMaxSize() modifier = modifier.fillMaxSize(),
) { ) {
val drawerWidth = 360.dp val drawerWidth = 360.dp
val drawerWidthPx = with(density) { drawerWidth.toPx() } val drawerWidthPx = with(density) { drawerWidth.toPx() }
@ -186,7 +186,7 @@ private fun UnittoModalNavigationDrawer(
DraggableAnchors { DraggableAnchors {
DrawerValue.Closed at minValue DrawerValue.Closed at minValue
DrawerValue.Open at maxValue DrawerValue.Open at maxValue
} },
) )
} }
@ -202,7 +202,7 @@ private fun UnittoModalNavigationDrawer(
state = state.anchoredDraggableState, state = state.anchoredDraggableState,
orientation = Orientation.Horizontal, orientation = Orientation.Horizontal,
enabled = gesturesEnabled or state.isOpen, enabled = gesturesEnabled or state.isOpen,
) ),
) )
Scrim( Scrim(
@ -210,7 +210,9 @@ private fun UnittoModalNavigationDrawer(
onClose = { if (gesturesEnabled) drawerScope.launch { state.close() } }, onClose = { if (gesturesEnabled) drawerScope.launch { state.close() } },
fraction = { fraction = {
fraction( fraction(
minValue, maxValue, state.anchoredDraggableState.requireOffset() minValue,
maxValue,
state.anchoredDraggableState.requireOffset(),
) )
}, },
) )
@ -224,14 +226,14 @@ private fun UnittoModalNavigationDrawer(
.anchoredDraggableState .anchoredDraggableState
.requireOffset() .requireOffset()
.roundToInt(), .roundToInt(),
y = 0 y = 0,
) )
} }
.anchoredDraggable( .anchoredDraggable(
state = state.anchoredDraggableState, state = state.anchoredDraggableState,
orientation = Orientation.Horizontal, orientation = Orientation.Horizontal,
enabled = gesturesEnabled or state.isOpen, enabled = gesturesEnabled or state.isOpen,
) ),
) { ) {
drawerContent() drawerContent()
} }
@ -254,7 +256,7 @@ private fun Scrim(
Canvas( Canvas(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.then(dismissDrawer) .then(dismissDrawer),
) { ) {
drawRect(color, alpha = fraction()) drawRect(color, alpha = fraction())
} }
@ -266,12 +268,12 @@ private fun fraction(a: Float, b: Float, pos: Float) =
@Preview( @Preview(
backgroundColor = 0xFFC8F7D4, backgroundColor = 0xFFC8F7D4,
showBackground = true, showBackground = true,
device = "spec:width=320dp,height=500dp,dpi=320" device = "spec:width=320dp,height=500dp,dpi=320",
) )
@Preview( @Preview(
backgroundColor = 0xFFC8F7D4, backgroundColor = 0xFFC8F7D4,
showBackground = true, showBackground = true,
device = "spec:width=440dp,height=500dp,dpi=440" device = "spec:width=440dp,height=500dp,dpi=440",
) )
@Composable @Composable
private fun PreviewUnittoModalNavigationDrawerClose() { private fun PreviewUnittoModalNavigationDrawerClose() {
@ -290,11 +292,11 @@ private fun PreviewUnittoModalNavigationDrawerClose() {
Column { Column {
Text(text = "Content") Text(text = "Content")
Button( Button(
onClick = { corScope.launch { drawerState.open() } } onClick = { corScope.launch { drawerState.open() } },
) { ) {
Text(text = "BUTTON") Text(text = "BUTTON")
} }
} }
} },
) )
} }

View File

@ -81,12 +81,12 @@ fun PagedIsland(
corScope.launch { corScope.launch {
pagerState.animateScrollToPage( pagerState.animateScrollToPage(
// Animate to first page if target page is out of bounds // Animate to first page if target page is out of bounds
if (targetPage >= pagerState.pageCount) 0 else targetPage if (targetPage >= pagerState.pageCount) 0 else targetPage,
) )
} }
} }
.background(backgroundColor) .background(backgroundColor)
.padding(16.dp) .padding(16.dp),
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
@ -105,7 +105,7 @@ fun PagedIsland(
.fillMaxWidth(), .fillMaxWidth(),
verticalAlignment = Alignment.Top, verticalAlignment = Alignment.Top,
state = pagerState, state = pagerState,
pageContent = { page -> pageContent(page % pageCount) } pageContent = { page -> pageContent(page % pageCount) },
) )
} }
} }

View File

@ -52,8 +52,11 @@ fun PortraitLandscape(
.weight(1f) .weight(1f)
.fillMaxSize() .fillMaxSize()
.padding( .padding(
it.maxWidth * 0.015f, 0.dp, it.maxWidth * 0.015f,
it.maxHeight * 0.03f, it.maxHeight * 0.03f) 0.dp,
it.maxHeight * 0.03f,
it.maxHeight * 0.03f,
)
content1(contentModifier) content1(contentModifier)
content2(contentModifier) content2(contentModifier)
} }

View File

@ -41,10 +41,10 @@ fun ScaffoldWithLargeTopBar(
title: String, title: String,
navigationIcon: @Composable () -> Unit, navigationIcon: @Composable () -> Unit,
actions: @Composable RowScope.() -> Unit = {}, actions: @Composable RowScope.() -> Unit = {},
content: @Composable (PaddingValues) -> Unit content: @Composable (PaddingValues) -> Unit,
) { ) {
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior( val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(
rememberTopAppBarState() rememberTopAppBarState(),
) )
Scaffold( Scaffold(
modifier = Modifier modifier = Modifier
@ -56,9 +56,9 @@ fun ScaffoldWithLargeTopBar(
}, },
navigationIcon = navigationIcon, navigationIcon = navigationIcon,
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
actions = actions actions = actions,
) )
}, },
content = content content = content,
) )
} }

View File

@ -59,7 +59,7 @@ fun ScaffoldWithTopBar(
floatingActionButton: @Composable () -> Unit = {}, floatingActionButton: @Composable () -> Unit = {},
floatingActionButtonPosition: FabPosition = FabPosition.End, floatingActionButtonPosition: FabPosition = FabPosition.End,
scrollBehavior: TopAppBarScrollBehavior? = null, scrollBehavior: TopAppBarScrollBehavior? = null,
content: @Composable (PaddingValues) -> Unit content: @Composable (PaddingValues) -> Unit,
) { ) {
Scaffold( Scaffold(
modifier = modifier, modifier = modifier,
@ -67,7 +67,7 @@ fun ScaffoldWithTopBar(
AnimatedVisibility( AnimatedVisibility(
visible = LocalWindowSize.current.heightSizeClass > WindowHeightSizeClass.Compact, visible = LocalWindowSize.current.heightSizeClass > WindowHeightSizeClass.Compact,
enter = slideInVertically() + fadeIn(), enter = slideInVertically() + fadeIn(),
exit = slideOutVertically() + fadeOut() exit = slideOutVertically() + fadeOut(),
) { ) {
CenterAlignedTopAppBar( CenterAlignedTopAppBar(
title = title, title = title,
@ -84,6 +84,6 @@ fun ScaffoldWithTopBar(
}, },
floatingActionButton = floatingActionButton, floatingActionButton = floatingActionButton,
floatingActionButtonPosition = floatingActionButtonPosition, floatingActionButtonPosition = floatingActionButtonPosition,
content = content content = content,
) )
} }

View File

@ -109,7 +109,7 @@ fun SearchBar(
modifier = modifier modifier = modifier
.windowInsetsPadding(TopAppBarDefaults.windowInsets) .windowInsetsPadding(TopAppBarDefaults.windowInsets)
.height(height), .height(height),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center,
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
@ -121,10 +121,9 @@ fun SearchBar(
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp), .padding(horizontal = 16.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(16.dp) horizontalArrangement = Arrangement.spacedBy(16.dp),
) { ) {
ProvideColor(MaterialTheme.colorScheme.onSurface) { ProvideColor(MaterialTheme.colorScheme.onSurface) {
NavigateButton { if (notEmpty) clear() else navigateUp() } NavigateButton { if (notEmpty) clear() else navigateUp() }
SearchTextField( SearchTextField(
@ -135,7 +134,7 @@ fun SearchBar(
value = query, value = query,
placeholder = stringResource(R.string.search_text_field_placeholder), placeholder = stringResource(R.string.search_text_field_placeholder),
onValueChange = onQueryChange, onValueChange = onQueryChange,
onSearch = onSearch onSearch = onSearch,
) )
ClearButton(notEmpty, ::clear) ClearButton(notEmpty, ::clear)
@ -152,7 +151,7 @@ private fun SearchTextField(
value: TextFieldValue, value: TextFieldValue,
placeholder: String, placeholder: String,
onValueChange: (TextFieldValue) -> Unit, onValueChange: (TextFieldValue) -> Unit,
onSearch: KeyboardActionScope.() -> Unit onSearch: KeyboardActionScope.() -> Unit,
) { ) {
BasicTextField( BasicTextField(
modifier = modifier, modifier = modifier,
@ -171,33 +170,33 @@ private fun SearchTextField(
modifier = Modifier.alpha(0.7f), modifier = Modifier.alpha(0.7f),
text = placeholder, text = placeholder,
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurface color = MaterialTheme.colorScheme.onSurface,
) )
} }
} },
) )
} }
@Composable @Composable
private fun SearchButton( private fun SearchButton(
onClick: () -> Unit onClick: () -> Unit,
) { ) {
SearchBarIconButton(onClick) { SearchBarIconButton(onClick) {
Icon( Icon(
imageVector = Icons.Default.Search, imageVector = Icons.Default.Search,
contentDescription = stringResource(R.string.search_button_description) contentDescription = stringResource(R.string.search_button_description),
) )
} }
} }
@Composable @Composable
private fun NavigateButton( private fun NavigateButton(
onClick: () -> Unit onClick: () -> Unit,
) { ) {
SearchBarIconButton(onClick) { SearchBarIconButton(onClick) {
Icon( Icon(
imageVector = Icons.AutoMirrored.Outlined.ArrowBack, imageVector = Icons.AutoMirrored.Outlined.ArrowBack,
contentDescription = stringResource(R.string.navigate_up_description) contentDescription = stringResource(R.string.navigate_up_description),
) )
} }
} }
@ -205,17 +204,17 @@ private fun NavigateButton(
@Composable @Composable
private fun ClearButton( private fun ClearButton(
visible: Boolean, visible: Boolean,
onClick: () -> Unit onClick: () -> Unit,
) { ) {
AnimatedVisibility( AnimatedVisibility(
visible = visible, visible = visible,
enter = fadeIn(), enter = fadeIn(),
exit = fadeOut() exit = fadeOut(),
) { ) {
SearchBarIconButton(onClick) { SearchBarIconButton(onClick) {
Icon( Icon(
imageVector = Icons.Outlined.Clear, imageVector = Icons.Outlined.Clear,
contentDescription = stringResource(R.string.clear_input_description) contentDescription = stringResource(R.string.clear_input_description),
) )
} }
} }
@ -224,7 +223,7 @@ private fun ClearButton(
@Composable @Composable
fun SearchBarIconButton( fun SearchBarIconButton(
onClick: () -> Unit, onClick: () -> Unit,
content: @Composable () -> Unit content: @Composable () -> Unit,
) { ) {
Box( Box(
modifier = Modifier modifier = Modifier
@ -236,10 +235,10 @@ fun SearchBarIconButton(
interactionSource = remember { MutableInteractionSource() }, interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple( indication = rememberRipple(
bounded = false, bounded = false,
radius = 20.dp radius = 20.dp,
)
), ),
contentAlignment = Alignment.Center ),
contentAlignment = Alignment.Center,
) { ) {
content() content()
} }
@ -259,6 +258,6 @@ fun UnittoSearchBarPreview() {
query = TextFieldValue("test"), query = TextFieldValue("test"),
onQueryChange = {}, onQueryChange = {},
navigateUp = {}, navigateUp = {},
scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior() scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(),
) )
} }

View File

@ -41,29 +41,29 @@ import com.sadellie.unitto.core.base.R
fun SearchPlaceholder( fun SearchPlaceholder(
onButtonClick: () -> Unit, onButtonClick: () -> Unit,
supportText: String, supportText: String,
buttonLabel: String buttonLabel: String,
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(16.dp), .padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp) verticalArrangement = Arrangement.spacedBy(16.dp),
) { ) {
Icon( Icon(
imageVector = Icons.Default.SearchOff, imageVector = Icons.Default.SearchOff,
contentDescription = stringResource(R.string.no_results_description), contentDescription = stringResource(R.string.no_results_description),
modifier = Modifier.size(48.dp) modifier = Modifier.size(48.dp),
) )
Text( Text(
text = stringResource(R.string.no_results_label), text = stringResource(R.string.no_results_label),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
style = MaterialTheme.typography.bodyLarge style = MaterialTheme.typography.bodyLarge,
) )
Text( Text(
text = supportText, text = supportText,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
style = MaterialTheme.typography.bodySmall style = MaterialTheme.typography.bodySmall,
) )
ElevatedButton(onClick = onButtonClick) { ElevatedButton(onClick = onButtonClick) {
Text(text = buttonLabel) Text(text = buttonLabel)

View File

@ -47,14 +47,14 @@ import androidx.compose.ui.unit.dp
@Composable @Composable
fun SegmentedButtonsRow( fun SegmentedButtonsRow(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
content: @Composable RowScope.() -> Unit content: @Composable RowScope.() -> Unit,
) { ) {
Row( Row(
modifier modifier
.width(IntrinsicSize.Max) .width(IntrinsicSize.Max)
.height(40.dp) .height(40.dp)
.clip(CircleShape) .clip(CircleShape)
.border(1.dp, MaterialTheme.colorScheme.outline, CircleShape) .border(1.dp, MaterialTheme.colorScheme.outline, CircleShape),
) { ) {
content() content()
} }
@ -66,7 +66,7 @@ fun RowScope.SegmentedButton(
label: String, label: String,
onClick: () -> Unit, onClick: () -> Unit,
selected: Boolean, selected: Boolean,
icon: ImageVector? = null icon: ImageVector? = null,
) { ) {
val containerColor = val containerColor =
if (selected) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.surface if (selected) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.surface
@ -77,9 +77,9 @@ fun RowScope.SegmentedButton(
shape = RectangleShape, shape = RectangleShape,
colors = ButtonDefaults.outlinedButtonColors( colors = ButtonDefaults.outlinedButtonColors(
containerColor = containerColor, containerColor = containerColor,
contentColor = contentColorFor(containerColor) contentColor = contentColorFor(containerColor),
), ),
contentPadding = PaddingValues(horizontal = 12.dp) contentPadding = PaddingValues(horizontal = 12.dp),
) { ) {
if (icon != null) { if (icon != null) {
Crossfade(selected, label = "Selected state") { Crossfade(selected, label = "Selected state") {

View File

@ -67,14 +67,14 @@ internal fun ColumnScope.SheetContent(
modifier = Modifier.clickable( modifier = Modifier.clickable(
interactionSource = interactionSource, interactionSource = interactionSource,
indication = null, indication = null,
onClick = { showHello = true } onClick = { showHello = true },
) ),
) { hello -> ) { hello ->
Text( Text(
text = if (hello) stringResource(R.string.hello_label) else stringResource(R.string.app_name), text = if (hello) stringResource(R.string.hello_label) else stringResource(R.string.app_name),
modifier = Modifier.padding(horizontal = 28.dp, vertical = 24.dp), modifier = Modifier.padding(horizontal = 28.dp, vertical = 24.dp),
style = MaterialTheme.typography.titleLarge, style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.primary color = MaterialTheme.colorScheme.primary,
) )
} }
@ -85,7 +85,7 @@ internal fun ColumnScope.SheetContent(
destination = drawerItem, destination = drawerItem,
icon = if (selected) drawerItem.selectedIcon else drawerItem.defaultIcon, icon = if (selected) drawerItem.selectedIcon else drawerItem.defaultIcon,
selected = selected, selected = selected,
onClick = onItemClick onClick = onItemClick,
) )
} }
@ -98,7 +98,7 @@ internal fun ColumnScope.SheetContent(
destination = drawerItem, destination = drawerItem,
icon = if (selected) drawerItem.selectedIcon else drawerItem.defaultIcon, icon = if (selected) drawerItem.selectedIcon else drawerItem.defaultIcon,
selected = selected, selected = selected,
onClick = onItemClick onClick = onItemClick,
) )
} }
} }
@ -119,7 +119,7 @@ private fun PreviewDrawerSheet() {
DrawerItem.Calculator, DrawerItem.Calculator,
), ),
currentDestination = DrawerItem.Calculator.start, currentDestination = DrawerItem.Calculator.start,
onItemClick = {} onItemClick = {},
) )
} }
} }

View File

@ -56,12 +56,12 @@ fun Slider(
value: Float, value: Float,
valueRange: ClosedFloatingPointRange<Float>, valueRange: ClosedFloatingPointRange<Float>,
onValueChange: (Float) -> Unit, onValueChange: (Float) -> Unit,
onValueChangeFinished: (Float) -> Unit = {} onValueChangeFinished: (Float) -> Unit = {},
) { ) {
val animated = animateFloatAsState( val animated = animateFloatAsState(
targetValue = value.roundToInt().toFloat(), targetValue = value.roundToInt().toFloat(),
animationSpec = spring(), animationSpec = spring(),
label = "Thumb animation" label = "Thumb animation",
) )
Slider( Slider(
@ -81,14 +81,14 @@ private fun SquigglyTrack(
@FloatRange(0.0, 1.0) waveHeight: Float = 0.7f, @FloatRange(0.0, 1.0) waveHeight: Float = 0.7f,
strokeWidth: Float = 15f, strokeWidth: Float = 15f,
filledColor: Color = MaterialTheme.colorScheme.primary, filledColor: Color = MaterialTheme.colorScheme.primary,
unfilledColor: Color = MaterialTheme.colorScheme.surfaceVariant unfilledColor: Color = MaterialTheme.colorScheme.surfaceVariant,
) { ) {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
var direct by remember { mutableFloatStateOf(waveHeight * (100f - strokeWidth * 2f) / 100f) } var direct by remember { mutableFloatStateOf(waveHeight * (100f - strokeWidth * 2f) / 100f) }
val animatedDirect = animateFloatAsState( val animatedDirect = animateFloatAsState(
targetValue = direct, targetValue = direct,
animationSpec = spring(stiffness = Spring.StiffnessLow), animationSpec = spring(stiffness = Spring.StiffnessLow),
label = "Track animation" label = "Track animation",
) )
LaunchedEffect(sliderState.value) { LaunchedEffect(sliderState.value) {
@ -101,7 +101,7 @@ private fun SquigglyTrack(
Canvas( Canvas(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.height(20.dp) .height(20.dp),
) { ) {
val width = size.width val width = size.width
val height = size.height val height = size.height
@ -114,7 +114,7 @@ private fun SquigglyTrack(
val path = Path().apply { val path = Path().apply {
moveTo( moveTo(
x = initialOffset, x = initialOffset,
y = height.times(0.5f) y = height.times(0.5f),
) )
val amount = ceil(width.div(eachWaveWidth)) val amount = ceil(width.div(eachWaveWidth))
@ -125,7 +125,7 @@ private fun SquigglyTrack(
dx1 = eachWaveWidth * 0.5f, dx1 = eachWaveWidth * 0.5f,
dy1 = height.times(peek), dy1 = height.times(peek),
dx2 = eachWaveWidth, dx2 = eachWaveWidth,
dy2 = 0f dy2 = 0f,
) )
} }
} }
@ -135,12 +135,12 @@ private fun SquigglyTrack(
left = 0f, left = 0f,
right = thumbPosition, right = thumbPosition,
bottom = height, bottom = height,
clipOp = ClipOp.Intersect clipOp = ClipOp.Intersect,
) { ) {
drawPath( drawPath(
path = path, path = path,
color = filledColor, color = filledColor,
style = Stroke(strokeWidth, cap = StrokeCap.Round) style = Stroke(strokeWidth, cap = StrokeCap.Round),
) )
} }
@ -149,7 +149,7 @@ private fun SquigglyTrack(
start = Offset(thumbPosition, height.times(0.5f)), start = Offset(thumbPosition, height.times(0.5f)),
end = Offset(width, height.times(0.5f)), end = Offset(width, height.times(0.5f)),
strokeWidth = strokeWidth, strokeWidth = strokeWidth,
cap = StrokeCap.Round cap = StrokeCap.Round,
) )
} }
} }
@ -165,6 +165,6 @@ private fun PreviewNewSlider() {
com.sadellie.unitto.core.ui.common.Slider( com.sadellie.unitto.core.ui.common.Slider(
value = currentValue, value = currentValue,
valueRange = 0f..16f, valueRange = 0f..16f,
onValueChange = { currentValue = it } onValueChange = { currentValue = it },
) )
} }

View File

@ -70,7 +70,7 @@ fun Switch(
) )
val thumbOffset = animateDpAsState( val thumbOffset = animateDpAsState(
targetValue = if (checked) ThumbPaddingEnd else ThumbPaddingStart, targetValue = if (checked) ThumbPaddingEnd else ThumbPaddingStart,
label = "Thumb offset" label = "Thumb offset",
) )
Box( Box(
@ -81,15 +81,15 @@ fun Switch(
enabled = true, enabled = true,
onClickLabel = null, onClickLabel = null,
role = Role.Switch, role = Role.Switch,
onClick = { onCheckedChange(!checked) } onClick = { onCheckedChange(!checked) },
) )
.background(trackColor.value, CircleShape) .background(trackColor.value, CircleShape)
.size(TrackWidth, TrackHeight) .size(TrackWidth, TrackHeight)
.border( .border(
TrackOutlineWidth, TrackOutlineWidth,
borderColor(enabled, checked, colors), borderColor(enabled, checked, colors),
CircleShape CircleShape,
) ),
) { ) {
Box( Box(
modifier = Modifier modifier = Modifier
@ -100,7 +100,7 @@ fun Switch(
) )
.align(Alignment.CenterStart) .align(Alignment.CenterStart)
.background(thumbColor.value, CircleShape) .background(thumbColor.value, CircleShape)
.size(thumbSize.value) .size(thumbSize.value),
) )
} }
} }
@ -109,7 +109,7 @@ fun Switch(
private fun trackColor( private fun trackColor(
enabled: Boolean, enabled: Boolean,
checked: Boolean, checked: Boolean,
colors: SwitchColors colors: SwitchColors,
): Color = ): Color =
if (enabled) { if (enabled) {
if (checked) colors.checkedTrackColor else colors.uncheckedTrackColor if (checked) colors.checkedTrackColor else colors.uncheckedTrackColor
@ -121,7 +121,7 @@ private fun trackColor(
private fun thumbColor( private fun thumbColor(
enabled: Boolean, enabled: Boolean,
checked: Boolean, checked: Boolean,
colors: SwitchColors colors: SwitchColors,
): Color = ): Color =
if (enabled) { if (enabled) {
if (checked) colors.checkedThumbColor else colors.uncheckedThumbColor if (checked) colors.checkedThumbColor else colors.uncheckedThumbColor
@ -133,7 +133,7 @@ private fun thumbColor(
private fun borderColor( private fun borderColor(
enabled: Boolean, enabled: Boolean,
checked: Boolean, checked: Boolean,
colors: SwitchColors colors: SwitchColors,
): Color = ): Color =
if (enabled) { if (enabled) {
if (checked) colors.checkedBorderColor else colors.uncheckedBorderColor if (checked) colors.checkedBorderColor else colors.uncheckedBorderColor
@ -156,6 +156,6 @@ fun PreviewPixelSwitch() {
var checked by remember { mutableStateOf(false) } var checked by remember { mutableStateOf(false) }
Switch( Switch(
checked = checked, checked = checked,
onCheckedChange = { checked = !checked } onCheckedChange = { checked = !checked },
) )
} }

View File

@ -34,11 +34,11 @@ fun ColumnWithConstraints(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
verticalArrangement: Arrangement.Vertical = Arrangement.Top, verticalArrangement: Arrangement.Vertical = Arrangement.Top,
horizontalAlignment: Alignment.Horizontal = Alignment.Start, horizontalAlignment: Alignment.Horizontal = Alignment.Start,
content: @Composable (ColumnScope.(BoxWithConstraintsScope)-> Unit) content: @Composable (ColumnScope.(BoxWithConstraintsScope) -> Unit),
) = BoxWithConstraints(modifier) { ) = BoxWithConstraints(modifier) {
Column( Column(
verticalArrangement = verticalArrangement, verticalArrangement = verticalArrangement,
horizontalAlignment = horizontalAlignment horizontalAlignment = horizontalAlignment,
) { content(this@BoxWithConstraints) } ) { content(this@BoxWithConstraints) }
} }
@ -47,10 +47,10 @@ fun RowWithConstraints(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
verticalAlignment: Alignment.Vertical = Alignment.Top, verticalAlignment: Alignment.Vertical = Alignment.Top,
content: @Composable (RowScope.(BoxWithConstraintsScope)-> Unit) content: @Composable (RowScope.(BoxWithConstraintsScope) -> Unit),
) = BoxWithConstraints(modifier) { ) = BoxWithConstraints(modifier) {
Row( Row(
horizontalArrangement = horizontalArrangement, horizontalArrangement = horizontalArrangement,
verticalAlignment = verticalAlignment verticalAlignment = verticalAlignment,
) { content(this@BoxWithConstraints) } ) { content(this@BoxWithConstraints) }
} }

View File

@ -43,54 +43,6 @@ import androidx.compose.ui.unit.TextUnit
import kotlin.math.min import kotlin.math.min
import kotlin.math.roundToInt import kotlin.math.roundToInt
// HUGE performance drop. Don't use for buttons
///**
// * Composable function that automatically adjusts the text size to fit within given constraints using AnnotatedString, considering the ratio of line spacing to text size.
// *
// * Features:
// * Similar to AutoSizeText(String), with support for AnnotatedString.
// *
// * @param inlineContent a map storing composables that replaces certain ranges of the text, used to
// * insert composables into text layout. See [InlineTextContent].
// * @see AutoSizeText
// */
//@Composable
//internal fun AutoSizeText(
// text: AnnotatedString,
// modifier: Modifier = Modifier,
// minRatio: Float = 1f,
// maxTextSize: TextUnit = TextUnit.Unspecified,
// alignment: Alignment = Alignment.TopStart,
// overflow: TextOverflow = TextOverflow.Clip,
// softWrap: Boolean = true,
// maxLines: Int = Int.MAX_VALUE,
// minLines: Int = 1,
// inlineContent: Map<String, InlineTextContent> = mapOf(),
// onTextLayout: (TextLayoutResult) -> Unit = {},
// style: TextStyle = LocalTextStyle.current,
//) = AutoSizeTextStyleBox(
// modifier = modifier,
// text = text,
// maxTextSize = maxTextSize,
// maxLines = maxLines,
// minLines = minLines,
// softWrap = softWrap,
// style = style,
// minRatio = minRatio,
// alignment = alignment
//) {
// Text(
// text = text,
// overflow = overflow,
// softWrap = softWrap,
// maxLines = maxLines,
// minLines = minLines,
// inlineContent = inlineContent,
// onTextLayout = onTextLayout,
// style = LocalTextStyle.current,
// )
//}
/** /**
* [BoxWithConstraints] with [autoTextStyle] passed via [LocalTextStyle]. * [BoxWithConstraints] with [autoTextStyle] passed via [LocalTextStyle].
* *
@ -122,11 +74,11 @@ internal fun AutoSizeTextStyleBox(
style: TextStyle, style: TextStyle,
minRatio: Float, minRatio: Float,
alignment: Alignment, alignment: Alignment,
content: @Composable () -> Unit content: @Composable () -> Unit,
) { ) {
val density = LocalDensity.current val density = LocalDensity.current
CompositionLocalProvider( CompositionLocalProvider(
LocalDensity provides Density(density = density.density, fontScale = 1F) LocalDensity provides Density(density = density.density, fontScale = 1F),
) { ) {
BoxWithConstraints( BoxWithConstraints(
modifier = modifier, modifier = modifier,
@ -141,12 +93,12 @@ internal fun AutoSizeTextStyleBox(
style = style, style = style,
alignment = alignment, alignment = alignment,
density = density, density = density,
minRatio = minRatio minRatio = minRatio,
) )
CompositionLocalProvider( CompositionLocalProvider(
value = LocalTextStyle.provides(autoTextStyle), value = LocalTextStyle.provides(autoTextStyle),
content = content content = content,
) )
} }
} }
@ -290,10 +242,11 @@ private fun <E> IntProgression.findElectedValue(
var high = last var high = last
while (low <= high) { while (low <= high) {
val mid = low + (high - low) / 2 val mid = low + (high - low) / 2
if (shouldMoveBackward(transform(mid))) if (shouldMoveBackward(transform(mid))) {
high = mid - 1 high = mid - 1
else } else {
low = mid + 1 low = mid + 1
} }
}
transform(high.coerceAtLeast(minimumValue = first)) transform(high.coerceAtLeast(minimumValue = first))
} }

View File

@ -27,5 +27,8 @@ import androidx.compose.ui.unit.isSpecified
internal fun Density.roundToPx(sp: TextUnit): Int = sp.roundToPx() internal fun Density.roundToPx(sp: TextUnit): Int = sp.roundToPx()
internal fun Density.toSp(px: Int): TextUnit = px.toSp() internal fun Density.toSp(px: Int): TextUnit = px.toSp()
internal fun Density.toIntSize(dpSize: DpSize): IntSize = internal fun Density.toIntSize(dpSize: DpSize): IntSize =
if (dpSize.isSpecified) IntSize(dpSize.width.roundToPx(), dpSize.height.roundToPx()) if (dpSize.isSpecified) {
else IntSize.Zero IntSize(dpSize.width.roundToPx(), dpSize.height.roundToPx())
} else {
IntSize.Zero
}

View File

@ -67,7 +67,7 @@ fun DatePickerDialog(
BasicAlertDialog( BasicAlertDialog(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
modifier = modifier.wrapContentHeight(), modifier = modifier.wrapContentHeight(),
properties = DialogProperties(usePlatformDefaultWidth = false) properties = DialogProperties(usePlatformDefaultWidth = false),
) { ) {
Surface( Surface(
modifier = modifier modifier = modifier
@ -83,15 +83,14 @@ fun DatePickerDialog(
Box( Box(
modifier = Modifier modifier = Modifier
.align(Alignment.End) .align(Alignment.End)
.padding(_dialogButtonsPadding) .padding(_dialogButtonsPadding),
) { ) {
AlertDialogFlowRow( AlertDialogFlowRow(
mainAxisSpacing = _dialogButtonsMainAxisSpacing, mainAxisSpacing = _dialogButtonsMainAxisSpacing,
crossAxisSpacing = _dialogButtonsCrossAxisSpacing crossAxisSpacing = _dialogButtonsCrossAxisSpacing,
) { ) {
TextButton( TextButton(
onClick = onDismiss onClick = onDismiss,
) { ) {
Text(text = dismissLabel) Text(text = dismissLabel)
} }
@ -100,16 +99,17 @@ fun DatePickerDialog(
val millis = pickerState.selectedDateMillis ?: return@TextButton val millis = pickerState.selectedDateMillis ?: return@TextButton
val date = LocalDateTime.ofInstant( val date = LocalDateTime.ofInstant(
Instant.ofEpochMilli(millis), ZoneId.systemDefault() Instant.ofEpochMilli(millis),
ZoneId.systemDefault(),
) )
onConfirm( onConfirm(
localDateTime localDateTime
.withYear(date.year) .withYear(date.year)
.withMonth(date.monthValue) .withMonth(date.monthValue)
.withDayOfMonth(date.dayOfMonth) .withDayOfMonth(date.dayOfMonth),
) )
} },
) { ) {
Text(text = confirmLabel) Text(text = confirmLabel)
} }
@ -125,7 +125,7 @@ fun DatePickerDialog(
private fun AlertDialogFlowRow( private fun AlertDialogFlowRow(
mainAxisSpacing: Dp, mainAxisSpacing: Dp,
crossAxisSpacing: Dp, crossAxisSpacing: Dp,
content: @Composable () -> Unit content: @Composable () -> Unit,
) { ) {
Layout(content) { measurables, constraints -> Layout(content) { measurables, constraints ->
val sequences = mutableListOf<List<Placeable>>() val sequences = mutableListOf<List<Placeable>>()
@ -193,14 +193,16 @@ private fun AlertDialogFlowRow(
val mainAxisPositions = IntArray(childrenMainAxisSizes.size) { 0 } val mainAxisPositions = IntArray(childrenMainAxisSizes.size) { 0 }
with(arrangement) { with(arrangement) {
arrange( arrange(
mainAxisLayoutSize, childrenMainAxisSizes, mainAxisLayoutSize,
layoutDirection, mainAxisPositions childrenMainAxisSizes,
layoutDirection,
mainAxisPositions,
) )
} }
placeables.forEachIndexed { j, placeable -> placeables.forEachIndexed { j, placeable ->
placeable.place( placeable.place(
x = mainAxisPositions[j], x = mainAxisPositions[j],
y = crossAxisPositions[i] y = crossAxisPositions[i],
) )
} }
} }

View File

@ -73,7 +73,7 @@ fun TimePickerDialog(
val pickerState = rememberTimePickerState( val pickerState = rememberTimePickerState(
initialHour = hour, initialHour = hour,
initialMinute = minute, initialMinute = minute,
is24Hour = DateFormat.is24HourFormat(LocalContext.current) is24Hour = DateFormat.is24HourFormat(LocalContext.current),
) )
val configuration = LocalConfiguration.current val configuration = LocalConfiguration.current
var showingPicker by rememberSaveable { mutableStateOf(true) } var showingPicker by rememberSaveable { mutableStateOf(true) }
@ -81,8 +81,8 @@ fun TimePickerDialog(
BasicAlertDialog( BasicAlertDialog(
onDismissRequest = onCancel, onDismissRequest = onCancel,
properties = DialogProperties( properties = DialogProperties(
usePlatformDefaultWidth = false usePlatformDefaultWidth = false,
) ),
) { ) {
Surface( Surface(
shape = MaterialTheme.shapes.extraLarge, shape = MaterialTheme.shapes.extraLarge,
@ -92,7 +92,7 @@ fun TimePickerDialog(
.height(IntrinsicSize.Min) .height(IntrinsicSize.Min)
.background( .background(
shape = MaterialTheme.shapes.extraLarge, shape = MaterialTheme.shapes.extraLarge,
color = MaterialTheme.colorScheme.surface color = MaterialTheme.colorScheme.surface,
), ),
) { ) {
if (configuration.screenHeightDp > 400) { if (configuration.screenHeightDp > 400) {
@ -103,7 +103,7 @@ fun TimePickerDialog(
.fillMaxSize() .fillMaxSize()
.semantics { .semantics {
isTraversalGroup = true isTraversalGroup = true
} },
) { ) {
IconButton( IconButton(
modifier = Modifier modifier = Modifier
@ -114,7 +114,8 @@ fun TimePickerDialog(
.size(64.dp, 72.dp) .size(64.dp, 72.dp)
.align(Alignment.BottomStart) .align(Alignment.BottomStart)
.zIndex(5f), .zIndex(5f),
onClick = { showingPicker = !showingPicker }) { onClick = { showingPicker = !showingPicker },
) {
val icon = if (showingPicker) { val icon = if (showingPicker) {
Icons.Outlined.Keyboard Icons.Outlined.Keyboard
} else { } else {
@ -122,21 +123,21 @@ fun TimePickerDialog(
} }
Icon( Icon(
imageVector = icon, imageVector = icon,
contentDescription = stringResource(R.string.select_time_label) contentDescription = stringResource(R.string.select_time_label),
) )
} }
} }
} }
Column( Column(
modifier = Modifier.padding(24.dp), modifier = Modifier.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
Text( Text(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(bottom = 20.dp), .padding(bottom = 20.dp),
text = stringResource(R.string.select_time_label), text = stringResource(R.string.select_time_label),
style = MaterialTheme.typography.labelMedium style = MaterialTheme.typography.labelMedium,
) )
if (showingPicker && configuration.screenHeightDp > 400) { if (showingPicker && configuration.screenHeightDp > 400) {
TimePicker(state = pickerState) TimePicker(state = pickerState)
@ -146,14 +147,14 @@ fun TimePickerDialog(
Row( Row(
modifier = Modifier modifier = Modifier
.height(40.dp) .height(40.dp)
.fillMaxWidth() .fillMaxWidth(),
) { ) {
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
TextButton( TextButton(
onClick = onCancel onClick = onCancel,
) { Text(stringResource(R.string.cancel_label)) } ) { Text(stringResource(R.string.cancel_label)) }
TextButton( TextButton(
onClick = { onConfirm(pickerState.hour, pickerState.minute) } onClick = { onConfirm(pickerState.hour, pickerState.minute) },
) { Text(confirmLabel) } ) { Text(confirmLabel) }
} }
} }

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@file:Suppress("ktlint:standard:property-naming")
package com.sadellie.unitto.core.ui.common.icons.iconpack package com.sadellie.unitto.core.ui.common.icons.iconpack
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -32,15 +32,15 @@ import com.sadellie.unitto.core.base.Token
*/ */
internal class ExpressionClipboardManager( internal class ExpressionClipboardManager(
private val formatterSymbols: FormatterSymbols, private val formatterSymbols: FormatterSymbols,
private val clipboardManager: android.content.ClipboardManager private val clipboardManager: android.content.ClipboardManager,
) : ClipboardManager { ) : ClipboardManager {
override fun setText(annotatedString: AnnotatedString) = clipboardManager.setPrimaryClip( override fun setText(annotatedString: AnnotatedString) = clipboardManager.setPrimaryClip(
ClipData.newPlainText( ClipData.newPlainText(
PLAIN_TEXT_LABEL, PLAIN_TEXT_LABEL,
annotatedString annotatedString
.text .text
.replace(Token.Digit.dot, formatterSymbols.fractional) .replace(Token.Digit.dot, formatterSymbols.fractional),
) ),
) )
override fun getText(): AnnotatedString? = clipboardManager.primaryClip?.let { primaryClip -> override fun getText(): AnnotatedString? = clipboardManager.primaryClip?.let { primaryClip ->

View File

@ -22,7 +22,6 @@ import com.sadellie.unitto.core.base.Token
import kotlin.math.abs import kotlin.math.abs
fun String.fixCursor(pos: Int, grouping: String): Int { fun String.fixCursor(pos: Int, grouping: String): Int {
if (isEmpty()) return pos if (isEmpty()) return pos
// Best position if we move cursor left // Best position if we move cursor left
@ -75,7 +74,7 @@ private fun Int.isAtToken(str: String, token: String): Boolean {
return str return str
.substring( .substring(
startIndex = (this - checkBound).coerceAtLeast(0), startIndex = (this - checkBound).coerceAtLeast(0),
endIndex = (this + checkBound).coerceAtMost(str.length) endIndex = (this + checkBound).coerceAtMost(str.length),
) )
.contains(token) .contains(token)
} }
@ -86,7 +85,6 @@ private fun Int.isAfterToken(str: String, token: String): Boolean {
.contains(token) .contains(token)
} }
// This can also make [TextFieldValue.addTokens] better by checking tokens both ways. Needs more tests // This can also make [TextFieldValue.addTokens] better by checking tokens both ways. Needs more tests
fun String.tokenAfter(pos: Int): String { fun String.tokenAfter(pos: Int): String {
Token.Func.allWithOpeningBracket.forEach { Token.Func.allWithOpeningBracket.forEach {
@ -96,23 +94,6 @@ fun String.tokenAfter(pos: Int): String {
return substring(pos, (pos + 1).coerceAtMost(this.length)) return substring(pos, (pos + 1).coerceAtMost(this.length))
} }
//private fun String.numberNearby(cursor: Int): String {
// val text = this
//
// var aheadCursor = cursor
// var afterCursor = cursor
//
// while (text.tokenAhead(aheadCursor) in Token.Digit.allWithDot) {
// aheadCursor--
// }
//
// while (text.tokenAfter(afterCursor) in Token.Digit.allWithDot) {
// afterCursor++
// }
//
// return text.substring(aheadCursor, afterCursor)
//}
private fun Int.isBeforeToken(str: String, token: String): Boolean { private fun Int.isBeforeToken(str: String, token: String): Boolean {
return str return str
.substring(this, (this + token.length).coerceAtMost(str.length)) .substring(this, (this + token.length).coerceAtMost(str.length))

View File

@ -30,13 +30,13 @@ class ExpressionTransformer(private val formatterSymbols: FormatterSymbols) : Vi
val formatted = text.text.formatExpression(formatterSymbols) val formatted = text.text.formatExpression(formatterSymbols)
return TransformedText( return TransformedText(
text = AnnotatedString(formatted), text = AnnotatedString(formatted),
offsetMapping = ExpressionMapping(text.text, formatted) offsetMapping = ExpressionMapping(text.text, formatted),
) )
} }
inner class ExpressionMapping( inner class ExpressionMapping(
private val original: String, private val original: String,
private val transformed: String private val transformed: String,
) : OffsetMapping { ) : OffsetMapping {
// Called when entering text (on each text change) // Called when entering text (on each text change)
// Basically moves cursor to the right position // Basically moves cursor to the right position

View File

@ -49,7 +49,7 @@ fun FixedExpressionInputTextField(
val clipboardManager = FormattedExpressionClipboardManager( val clipboardManager = FormattedExpressionClipboardManager(
formatterSymbols = formatterSymbols, formatterSymbols = formatterSymbols,
clipboardManager = LocalContext.current.getSystemService(Context.CLIPBOARD_SERVICE) clipboardManager = LocalContext.current.getSystemService(Context.CLIPBOARD_SERVICE)
as android.content.ClipboardManager as android.content.ClipboardManager,
) )
CompositionLocalProvider(LocalClipboardManager provides clipboardManager) { CompositionLocalProvider(LocalClipboardManager provides clipboardManager) {
@ -57,7 +57,7 @@ fun FixedExpressionInputTextField(
modifier = Modifier modifier = Modifier
.horizontalScroll(rememberScrollState()) // Must be first .horizontalScroll(rememberScrollState()) // Must be first
.clickable(onClick = onClick) .clickable(onClick = onClick)
.then(modifier) .then(modifier),
) { ) {
Text( Text(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@ -71,7 +71,7 @@ fun FixedExpressionInputTextField(
private class FormattedExpressionClipboardManager( private class FormattedExpressionClipboardManager(
private val formatterSymbols: FormatterSymbols, private val formatterSymbols: FormatterSymbols,
private val clipboardManager: android.content.ClipboardManager private val clipboardManager: android.content.ClipboardManager,
) : ClipboardManager { ) : ClipboardManager {
override fun getText(): AnnotatedString? = null override fun getText(): AnnotatedString? = null
@ -81,8 +81,8 @@ private class FormattedExpressionClipboardManager(
PLAIN_TEXT_LABEL, PLAIN_TEXT_LABEL,
annotatedString annotatedString
.text .text
.replace(formatterSymbols.grouping, "") .replace(formatterSymbols.grouping, ""),
) ),
) )
} }
} }

View File

@ -51,7 +51,7 @@ internal fun String.clearAndFilterNumberBase(): String {
} }
fun String.formatExpression( fun String.formatExpression(
formatterSymbols: FormatterSymbols formatterSymbols: FormatterSymbols,
): String { ): String {
var input = this var input = this
@ -84,7 +84,7 @@ fun String.formatExpression(
} }
private fun String.formatNumber( private fun String.formatNumber(
formatterSymbols: FormatterSymbols formatterSymbols: FormatterSymbols,
): String { ): String {
val input = this val input = this
@ -114,7 +114,7 @@ private fun String.leaveLegalTokensOnly(legalTokens: List<String>): String {
val subs = streamOfTokens val subs = streamOfTokens
.substring( .substring(
cursor, cursor,
(cursor + token.length).coerceAtMost(streamOfTokens.length) (cursor + token.length).coerceAtMost(streamOfTokens.length),
) )
if (subs == token) { if (subs == token) {
// Got a digit, see if there are other digits coming after // Got a digit, see if there are other digits coming after

View File

@ -64,7 +64,7 @@ fun ExpressionTextField(
ExpressionClipboardManager( ExpressionClipboardManager(
formatterSymbols = formatterSymbols, formatterSymbols = formatterSymbols,
clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE)
as android.content.ClipboardManager as android.content.ClipboardManager,
) )
} }
val expressionTransformer = remember(formatterSymbols) { val expressionTransformer = remember(formatterSymbols) {
@ -72,7 +72,7 @@ fun ExpressionTextField(
} }
CompositionLocalProvider( CompositionLocalProvider(
LocalClipboardManager provides clipboardManager LocalClipboardManager provides clipboardManager,
) { ) {
AutoSizeTextField( AutoSizeTextField(
modifier = modifier, modifier = modifier,
@ -85,7 +85,7 @@ fun ExpressionTextField(
textStyle = LocalNumberTypography.current.displayLarge.copy(textColor), textStyle = LocalNumberTypography.current.displayLarge.copy(textColor),
visualTransformation = expressionTransformer, visualTransformation = expressionTransformer,
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant), cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant),
minRatio = minRatio minRatio = minRatio,
) )
} }
} }
@ -110,7 +110,7 @@ fun NumberBaseTextField(
readOnly = readOnly, readOnly = readOnly,
textStyle = LocalNumberTypography.current.displayLarge.copy(textColor), textStyle = LocalNumberTypography.current.displayLarge.copy(textColor),
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant), cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant),
minRatio = minRatio minRatio = minRatio,
) )
} }
@ -132,7 +132,7 @@ fun SimpleTextField(
readOnly = readOnly, readOnly = readOnly,
textStyle = LocalNumberTypography.current.displayLarge.copy(textColor), textStyle = LocalNumberTypography.current.displayLarge.copy(textColor),
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant), cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant),
minRatio = minRatio minRatio = minRatio,
) )
} }
@ -174,7 +174,7 @@ private fun AutoSizeTextField(
softWrap = false, softWrap = false,
style = textStyle, style = textStyle,
minRatio = minRatio, minRatio = minRatio,
alignment = alignment alignment = alignment,
) { ) {
CompositionLocalProvider( CompositionLocalProvider(
LocalTextInputService provides null, LocalTextInputService provides null,
@ -204,8 +204,8 @@ private fun AutoSizeTextField(
text = placeholder!!, text = placeholder!!,
style = style.copy( style = style.copy(
textAlign = TextAlign.End, textAlign = TextAlign.End,
color = MaterialTheme.colorScheme.onSurface.copy(0.5f) color = MaterialTheme.colorScheme.onSurface.copy(0.5f),
) ),
) )
} }
innerTextField() innerTextField()

View File

@ -62,8 +62,8 @@ fun OutlinedDecimalTextField(
visualTransformation = expressionFormatter, visualTransformation = expressionFormatter,
keyboardOptions = KeyboardOptions( keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Decimal, keyboardType = KeyboardType.Decimal,
imeAction = imeAction imeAction = imeAction,
), ),
colors = colors colors = colors,
) )
} }

View File

@ -30,7 +30,8 @@ fun TextFieldValue.addTokens(tokens: String): TextFieldValue {
Token.Operator.plus, Token.Operator.plus,
Token.Operator.multiply, Token.Operator.multiply,
Token.Operator.divide, Token.Operator.divide,
Token.Operator.power -> { Token.Operator.power,
-> {
if (ahead == Token.Operator.plus) return deleteAheadAndAdd(tokens) if (ahead == Token.Operator.plus) return deleteAheadAndAdd(tokens)
if (ahead == Token.Operator.minus) return deleteAheadAndAdd(tokens) if (ahead == Token.Operator.minus) return deleteAheadAndAdd(tokens)
if (ahead == Token.Operator.multiply) return deleteAheadAndAdd(tokens) if (ahead == Token.Operator.multiply) return deleteAheadAndAdd(tokens)
@ -50,7 +51,7 @@ fun TextFieldValue.addTokens(tokens: String): TextFieldValue {
return this.copy( return this.copy(
text = text.replaceRange(selection.start, selection.end, tokens), text = text.replaceRange(selection.start, selection.end, tokens),
selection = TextRange(selection.start + tokens.length) selection = TextRange(selection.start + tokens.length),
) )
} }
@ -93,7 +94,7 @@ fun TextFieldValue.addBracket(): TextFieldValue {
Token.Operator.plus, Token.Operator.plus,
Token.Operator.minus, Token.Operator.minus,
Token.Operator.power, Token.Operator.power,
Token.Operator.leftBracket Token.Operator.leftBracket,
) )
if (text.tokenAhead(selection.start) in operators2) { if (text.tokenAhead(selection.start) in operators2) {
return addTokens(Token.Operator.leftBracket) return addTokens(Token.Operator.leftBracket)
@ -122,7 +123,7 @@ fun TextFieldValue.deleteTokens(): TextFieldValue {
return this.copy( return this.copy(
text = newText, text = newText,
selection = TextRange((newText.length - distanceFromEnd).coerceAtLeast(0)) selection = TextRange((newText.length - distanceFromEnd).coerceAtLeast(0)),
) )
} }

View File

@ -27,7 +27,7 @@ import androidx.annotation.RequiresApi
@RequiresApi(Build.VERSION_CODES.M) @RequiresApi(Build.VERSION_CODES.M)
internal class FloatingTextActionModeCallback( internal class FloatingTextActionModeCallback(
private val callback: UnittoActionModeCallback private val callback: UnittoActionModeCallback,
) : ActionMode.Callback2() { ) : ActionMode.Callback2() {
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
return callback.onActionItemClicked(mode, item) return callback.onActionItemClicked(mode, item)
@ -48,14 +48,14 @@ internal class FloatingTextActionModeCallback(
override fun onGetContentRect( override fun onGetContentRect(
mode: ActionMode?, mode: ActionMode?,
view: View?, view: View?,
outRect: android.graphics.Rect? outRect: android.graphics.Rect?,
) { ) {
val rect = callback.rect val rect = callback.rect
outRect?.set( outRect?.set(
rect.left.toInt(), rect.left.toInt(),
rect.top.toInt(), rect.top.toInt(),
rect.right.toInt(), rect.right.toInt(),
rect.bottom.toInt() rect.bottom.toInt(),
) )
} }
} }

View File

@ -33,7 +33,7 @@ internal class UnittoActionModeCallback(
var onCopyRequested: (() -> Unit)? = null, var onCopyRequested: (() -> Unit)? = null,
var onPasteRequested: (() -> Unit)? = null, var onPasteRequested: (() -> Unit)? = null,
var onCutRequested: (() -> Unit)? = null, var onCutRequested: (() -> Unit)? = null,
var onSelectAllRequested: (() -> Unit)? = null var onSelectAllRequested: (() -> Unit)? = null,
) { ) {
fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
requireNotNull(menu) requireNotNull(menu)

View File

@ -23,7 +23,7 @@ import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
internal class UnittoPrimaryTextActionModeCallback( internal class UnittoPrimaryTextActionModeCallback(
private val callback: UnittoActionModeCallback private val callback: UnittoActionModeCallback,
) : ActionMode.Callback { ) : ActionMode.Callback {
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
return callback.onActionItemClicked(mode, item) return callback.onActionItemClicked(mode, item)

View File

@ -29,7 +29,7 @@ class UnittoTextToolbar(
private val view: View, private val view: View,
private val copyCallback: () -> Unit, private val copyCallback: () -> Unit,
private val pasteCallback: (() -> Unit)? = null, private val pasteCallback: (() -> Unit)? = null,
private val cutCallback: (() -> Unit)? = null private val cutCallback: (() -> Unit)? = null,
) : TextToolbar { ) : TextToolbar {
private var actionMode: ActionMode? = null private var actionMode: ActionMode? = null
@ -42,7 +42,7 @@ class UnittoTextToolbar(
onCopyRequested: (() -> Unit)?, onCopyRequested: (() -> Unit)?,
onPasteRequested: (() -> Unit)?, onPasteRequested: (() -> Unit)?,
onCutRequested: (() -> Unit)?, onCutRequested: (() -> Unit)?,
onSelectAllRequested: (() -> Unit)? onSelectAllRequested: (() -> Unit)?,
) { ) {
textActionModeCallback.rect = rect textActionModeCallback.rect = rect
textActionModeCallback.onCopyRequested = copyCallback textActionModeCallback.onCopyRequested = copyCallback
@ -66,17 +66,17 @@ class UnittoTextToolbar(
private fun startActionMode( private fun startActionMode(
view: View, view: View,
textActionModeCallback: UnittoActionModeCallback textActionModeCallback: UnittoActionModeCallback,
): ActionMode { ): ActionMode {
return if (Build.VERSION.SDK_INT >= 23) { return if (Build.VERSION.SDK_INT >= 23) {
view.startActionMode( view.startActionMode(
FloatingTextActionModeCallback(textActionModeCallback), FloatingTextActionModeCallback(textActionModeCallback),
ActionMode.TYPE_FLOATING ActionMode.TYPE_FLOATING,
) )
} else { } else {
// Old devices use toolbar instead of a floating menu // Old devices use toolbar instead of a floating menu
view.startActionMode( view.startActionMode(
UnittoPrimaryTextActionModeCallback(textActionModeCallback) UnittoPrimaryTextActionModeCallback(textActionModeCallback),
) )
} }
} }

View File

@ -83,10 +83,11 @@ fun ZonedDateTime.formatTimeHours(
locale: Locale, locale: Locale,
is24Hour: Boolean, is24Hour: Boolean,
): String = ): String =
if (is24Hour) if (is24Hour) {
format(UnittoDateTimeFormatter.time24Hours(locale)) format(UnittoDateTimeFormatter.time24Hours(locale))
else } else {
format(UnittoDateTimeFormatter.time12Hours(locale)) format(UnittoDateTimeFormatter.time12Hours(locale))
}
/** /**
* @see UnittoDateTimeFormatter.timeMinutes * @see UnittoDateTimeFormatter.timeMinutes
@ -132,7 +133,7 @@ fun ZonedDateTime.formatDateDayMonthYear(
* @see UnittoDateTimeFormatter.dateWeekDayMonthYear * @see UnittoDateTimeFormatter.dateWeekDayMonthYear
*/ */
fun LocalDate.formatDateWeekDayMonthYear( fun LocalDate.formatDateWeekDayMonthYear(
locale: Locale locale: Locale,
): String = ): String =
format(UnittoDateTimeFormatter.dateWeekDayMonthYear(locale)) format(UnittoDateTimeFormatter.dateWeekDayMonthYear(locale))
@ -155,7 +156,6 @@ fun LocalDate.formatDateWeekDayMonthYear(
fun ZonedDateTime.formatOffset( fun ZonedDateTime.formatOffset(
currentTime: ZonedDateTime, currentTime: ZonedDateTime,
): String? { ): String? {
val offsetFixed = ChronoUnit.SECONDS.between(currentTime, this) val offsetFixed = ChronoUnit.SECONDS.between(currentTime, this)
var resultBuffer = "" var resultBuffer = ""

Some files were not shown because too many files have changed in this diff Show More