mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-18 08:15:26 +02:00
Spotless and ktlint
This commit is contained in:
parent
8b21721f48
commit
eb00d8a76e
7
.editorconfig
Normal file
7
.editorconfig
Normal 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
|
42
.run/spotlessApply.run.xml
Normal file
42
.run/spotlessApply.run.xml
Normal 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>
|
42
.run/spotlessCheck.run.xml
Normal file
42
.run/spotlessCheck.run.xml
Normal 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>
|
@ -76,14 +76,14 @@ internal fun ComponentActivity.App(prefs: AppPreferences?) {
|
||||
dynamicThemeEnabled = prefs.enableDynamicTheme,
|
||||
amoledThemeEnabled = prefs.enableAmoledTheme,
|
||||
customColor = prefs.customColor.toColor(),
|
||||
monetMode = prefs.monetMode
|
||||
monetMode = prefs.monetMode,
|
||||
)
|
||||
}
|
||||
|
||||
Themmo(
|
||||
themmoController = themmoController,
|
||||
typography = TypographySystem,
|
||||
animationSpec = tween(250)
|
||||
animationSpec = tween(250),
|
||||
) {
|
||||
val backgroundColor = MaterialTheme.colorScheme.background
|
||||
val isDarkThemeEnabled = remember(backgroundColor) { backgroundColor.luminance() < 0.5f }
|
||||
@ -113,9 +113,9 @@ internal fun ComponentActivity.App(prefs: AppPreferences?) {
|
||||
navController = navController,
|
||||
themmoController = it,
|
||||
startDestination = prefs.startingScreen,
|
||||
openDrawer = { drawerScope.launch { drawerState.open() } }
|
||||
openDrawer = { drawerScope.launch { drawerState.open() } },
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
DisposableEffect(isDarkThemeEnabled) {
|
||||
|
@ -68,7 +68,7 @@ internal class MainActivity : AppCompatActivity() {
|
||||
LocalLocale provides locale,
|
||||
LocalWindowSize provides calculateWindowSizeClass(this@MainActivity),
|
||||
LocalNumberTypography provides numbersTypography,
|
||||
LocalHapticPreference provides (prefs?.enableVibrations ?: true)
|
||||
LocalHapticPreference provides (prefs?.enableVibrations ?: true),
|
||||
) {
|
||||
App(prefs)
|
||||
}
|
||||
|
@ -22,4 +22,4 @@ import android.app.Application
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
|
||||
@HiltAndroidApp
|
||||
internal class UnittoApplication: Application()
|
||||
internal class UnittoApplication : Application()
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
package com.sadellie.unitto
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.PendingIntent
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
@ -26,6 +27,7 @@ import androidx.annotation.RequiresApi
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
class UnittoTileService : TileService() {
|
||||
@SuppressLint("StartActivityAndCollapseDeprecated")
|
||||
override fun onClick() {
|
||||
super.onClick()
|
||||
|
||||
@ -33,7 +35,7 @@ class UnittoTileService : TileService() {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
startActivityAndCollapse(PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE))
|
||||
startActivityAndCollapse(PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE))
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
startActivityAndCollapse(intent)
|
||||
|
@ -31,7 +31,7 @@ class StartupBaselineProfile {
|
||||
@Test
|
||||
fun generate() = baselineProfileRule.collect(
|
||||
packageName = "com.sadellie.unitto",
|
||||
includeInStartupProfile = true
|
||||
includeInStartupProfile = true,
|
||||
) {
|
||||
startActivityAndWait()
|
||||
device.pressBack()
|
||||
|
@ -61,7 +61,7 @@ class StartupBenchmark {
|
||||
fun startupFullyPrecompiled() = startup(CompilationMode.Full())
|
||||
|
||||
private fun startup(
|
||||
compilationMode: CompilationMode
|
||||
compilationMode: CompilationMode,
|
||||
) = benchmarkRule.measureRepeated(
|
||||
packageName = "com.sadellie.unitto",
|
||||
metrics = listOf(StartupTimingMetric()),
|
||||
@ -70,7 +70,7 @@ class StartupBenchmark {
|
||||
startupMode = StartupMode.COLD,
|
||||
setupBlock = {
|
||||
pressHome()
|
||||
}
|
||||
},
|
||||
) {
|
||||
startActivityAndWait()
|
||||
}
|
||||
|
@ -24,8 +24,10 @@ package com.sadellie.unitto.core.base
|
||||
object OutputFormat {
|
||||
// Never use engineering notation
|
||||
const val PLAIN = 0
|
||||
|
||||
// Use format that a lower API returns
|
||||
const val ALLOW_ENGINEERING = 1
|
||||
|
||||
// App will try it's best to use engineering notation
|
||||
const val FORCE_ENGINEERING = 2
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
@file:Suppress("ktlint:standard:property-naming")
|
||||
|
||||
package com.sadellie.unitto.core.base
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
@ -100,14 +102,14 @@ object Token {
|
||||
|
||||
val all by lazy {
|
||||
listOf(
|
||||
arsin, arcos, actan, sin, cos, tan, log, exp, ln
|
||||
arsin, arcos, actan, sin, cos, tan, log, exp, ln,
|
||||
).sortedByDescending { it.length }
|
||||
}
|
||||
|
||||
val allWithOpeningBracket by lazy {
|
||||
listOf(
|
||||
arsinBracket, arcosBracket, actanBracket, sinBracket, cosBracket, tanBracket,
|
||||
logBracket, expBracket, lnBracket
|
||||
logBracket, expBracket, lnBracket,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -144,7 +146,7 @@ object Token {
|
||||
Operator.multiply to listOf("*", "•"),
|
||||
Func.arsin to listOf("arsin"),
|
||||
Func.arcos to listOf("arcos"),
|
||||
Func.actan to listOf("actan")
|
||||
Func.actan to listOf("actan"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -42,4 +42,4 @@ class OutputFormatTest {
|
||||
fun testOutputFormatForceEngineering() {
|
||||
Assert.assertEquals(2, OutputFormat.FORCE_ENGINEERING)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,9 +150,14 @@ class TokenTest {
|
||||
@Test
|
||||
fun testSexyToUgly() {
|
||||
listOf(
|
||||
"−", "÷", "×", "sin⁻¹", "cos⁻¹", "tan⁻¹"
|
||||
"−",
|
||||
"÷",
|
||||
"×",
|
||||
"sin⁻¹",
|
||||
"cos⁻¹",
|
||||
"tan⁻¹",
|
||||
).forEach {
|
||||
assert(it in Token.sexyToUgly.keys)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ import java.time.ZonedDateTime
|
||||
|
||||
class ZonedDateTimeUtilsTest {
|
||||
|
||||
@get: Rule
|
||||
@get:Rule
|
||||
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
|
||||
|
||||
@Test
|
||||
|
@ -83,7 +83,7 @@ fun calculateWindowSizeClass(activity: Activity): WindowSizeClass {
|
||||
@Immutable
|
||||
class WindowSizeClass(
|
||||
val widthSizeClass: WindowWidthSizeClass,
|
||||
val heightSizeClass: WindowHeightSizeClass
|
||||
val heightSizeClass: WindowHeightSizeClass,
|
||||
) {
|
||||
companion object {
|
||||
/**
|
||||
@ -118,7 +118,7 @@ class WindowSizeClass(
|
||||
supportedWidthSizeClasses: Set<WindowWidthSizeClass> =
|
||||
WindowWidthSizeClass.DefaultSizeClasses,
|
||||
supportedHeightSizeClasses: Set<WindowHeightSizeClass> =
|
||||
WindowHeightSizeClass.DefaultSizeClasses
|
||||
WindowHeightSizeClass.DefaultSizeClasses,
|
||||
): WindowSizeClass {
|
||||
val windowWidthSizeClass =
|
||||
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] */
|
||||
internal fun fromWidth(width: Dp): WindowWidthSizeClass {
|
||||
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(
|
||||
width: Float,
|
||||
density: Density,
|
||||
supportedSizeClasses: Set<WindowWidthSizeClass>
|
||||
supportedSizeClasses: Set<WindowWidthSizeClass>,
|
||||
): WindowWidthSizeClass {
|
||||
require(width >= 0) { "Width must not be negative" }
|
||||
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] */
|
||||
internal fun fromHeight(height: Dp): WindowHeightSizeClass {
|
||||
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(
|
||||
height: Float,
|
||||
density: Density,
|
||||
supportedSizeClasses: Set<WindowHeightSizeClass>
|
||||
supportedSizeClasses: Set<WindowHeightSizeClass>,
|
||||
): WindowHeightSizeClass {
|
||||
require(height >= 0) { "Width must not be negative" }
|
||||
require(supportedSizeClasses.isNotEmpty()) { "Must support at least one size class" }
|
||||
|
@ -44,16 +44,22 @@ fun NavGraphBuilder.unittoComposable(
|
||||
route: String,
|
||||
arguments: List<NamedNavArgument> = emptyList(),
|
||||
deepLinks: List<NavDeepLink> = emptyList(),
|
||||
enterTransition: (@JvmSuppressWildcards
|
||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?)? = { unittoFadeIn() },
|
||||
exitTransition: (@JvmSuppressWildcards
|
||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?)? = { unittoFadeOut() },
|
||||
popEnterTransition: (@JvmSuppressWildcards
|
||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?)? =
|
||||
enterTransition,
|
||||
popExitTransition: (@JvmSuppressWildcards
|
||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?)? =
|
||||
exitTransition,
|
||||
enterTransition: (
|
||||
@JvmSuppressWildcards
|
||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?
|
||||
)? = { unittoFadeIn() },
|
||||
exitTransition: (
|
||||
@JvmSuppressWildcards
|
||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?
|
||||
)? = { unittoFadeOut() },
|
||||
popEnterTransition: (
|
||||
@JvmSuppressWildcards
|
||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?
|
||||
)? = enterTransition,
|
||||
popExitTransition: (
|
||||
@JvmSuppressWildcards
|
||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?
|
||||
)? = exitTransition,
|
||||
content: @Composable AnimatedContentScope.(NavBackStackEntry) -> Unit,
|
||||
): Unit = composable(
|
||||
route = route,
|
||||
@ -79,22 +85,26 @@ fun NavGraphBuilder.unittoStackedComposable(
|
||||
enterTransition = {
|
||||
slideInHorizontally(
|
||||
animationSpec = unittoEnterTween(),
|
||||
initialOffsetX = { (it * 0.2f).toInt() }) + unittoFadeIn()
|
||||
initialOffsetX = { (it * 0.2f).toInt() },
|
||||
) + unittoFadeIn()
|
||||
},
|
||||
exitTransition = {
|
||||
slideOutHorizontally(
|
||||
animationSpec = unittoExitTween(),
|
||||
targetOffsetX = { -(it * 0.2f).toInt() }) + unittoFadeOut()
|
||||
targetOffsetX = { -(it * 0.2f).toInt() },
|
||||
) + unittoFadeOut()
|
||||
},
|
||||
popEnterTransition = {
|
||||
slideInHorizontally(
|
||||
animationSpec = unittoEnterTween(),
|
||||
initialOffsetX = { -(it * 0.2f).toInt() }) + unittoFadeIn()
|
||||
initialOffsetX = { -(it * 0.2f).toInt() },
|
||||
) + unittoFadeIn()
|
||||
},
|
||||
popExitTransition = {
|
||||
slideOutHorizontally(
|
||||
animationSpec = unittoExitTween(),
|
||||
targetOffsetX = { (it * 0.2f).toInt() }) + unittoFadeOut()
|
||||
targetOffsetX = { (it * 0.2f).toInt() },
|
||||
) + unittoFadeOut()
|
||||
},
|
||||
content = content,
|
||||
)
|
||||
@ -113,10 +123,10 @@ fun NavGraphBuilder.unittoNavigation(
|
||||
exitTransition: (AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?)? =
|
||||
null,
|
||||
popEnterTransition: (
|
||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?
|
||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?
|
||||
)? = enterTransition,
|
||||
popExitTransition: (
|
||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?
|
||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?
|
||||
)? = exitTransition,
|
||||
builder: NavGraphBuilder.() -> Unit,
|
||||
): Unit = navigation(
|
||||
@ -128,7 +138,7 @@ fun NavGraphBuilder.unittoNavigation(
|
||||
exitTransition = exitTransition,
|
||||
popEnterTransition = popEnterTransition,
|
||||
popExitTransition = popExitTransition,
|
||||
builder = builder
|
||||
builder = builder,
|
||||
)
|
||||
|
||||
private const val ENTER_DURATION = 350
|
||||
|
@ -48,7 +48,7 @@ suspend fun Context.pushDynamicShortcut(
|
||||
val shortcutCompat = shortcutInfoCompat(
|
||||
context = context,
|
||||
route = drawerItem.graph,
|
||||
shortcut = shortcut
|
||||
shortcut = shortcut,
|
||||
)
|
||||
|
||||
kotlin.runCatching {
|
||||
@ -71,7 +71,7 @@ fun Context.addShortcut(
|
||||
val shortcutCompat = shortcutInfoCompat(
|
||||
context = context,
|
||||
route = drawerItem.graph,
|
||||
shortcut = shortcut
|
||||
shortcut = shortcut,
|
||||
)
|
||||
|
||||
val shortCutIntent = ShortcutManagerCompat.createShortcutResultIntent(context, shortcutCompat)
|
||||
@ -80,7 +80,7 @@ fun Context.addShortcut(
|
||||
ShortcutManagerCompat.requestPinShortcut(
|
||||
context,
|
||||
shortcutCompat,
|
||||
PendingIntent.getBroadcast(context, 0, shortCutIntent, FLAG_IMMUTABLE).intentSender
|
||||
PendingIntent.getBroadcast(context, 0, shortCutIntent, FLAG_IMMUTABLE).intentSender,
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
showToast(context, e.message ?: "Error")
|
||||
@ -101,8 +101,8 @@ private fun Context.shortcutInfoCompat(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse("app://com.sadellie.unitto/$route"),
|
||||
context,
|
||||
context.javaClass
|
||||
)
|
||||
context.javaClass,
|
||||
),
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ fun Button(
|
||||
border: BorderStroke? = null,
|
||||
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
content: @Composable RowScope.() -> Unit
|
||||
content: @Composable RowScope.() -> Unit,
|
||||
) {
|
||||
Surface(
|
||||
modifier = modifier.squashable(
|
||||
@ -58,7 +58,7 @@ fun Button(
|
||||
onLongClick = onLongClick,
|
||||
interactionSource = interactionSource,
|
||||
cornerRadiusRange = 30..50,
|
||||
enabled = enabled
|
||||
enabled = enabled,
|
||||
),
|
||||
color = containerColor,
|
||||
contentColor = contentColor,
|
||||
@ -70,12 +70,12 @@ fun Button(
|
||||
Modifier
|
||||
.defaultMinSize(
|
||||
minWidth = ButtonDefaults.MinWidth,
|
||||
minHeight = ButtonDefaults.MinHeight
|
||||
minHeight = ButtonDefaults.MinHeight,
|
||||
)
|
||||
.padding(contentPadding),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
content = content
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -70,16 +70,16 @@ fun FilterChip(
|
||||
.border(
|
||||
width = 1.dp,
|
||||
color = borderColor.value,
|
||||
shape = FilterChipDefaults.shape
|
||||
shape = FilterChipDefaults.shape,
|
||||
)
|
||||
.height(FilterChipDefaults.Height)
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
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(
|
||||
width = 1.dp,
|
||||
color = MaterialTheme.colorScheme.outline,
|
||||
shape = AssistChipDefaults.shape
|
||||
shape = AssistChipDefaults.shape,
|
||||
)
|
||||
.height(32.dp)
|
||||
.padding(horizontal = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.height(AssistChipDefaults.IconSize),
|
||||
imageVector = imageVector,
|
||||
contentDescription = contentDescription,
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -121,7 +121,7 @@ fun PreviewAssistChip() {
|
||||
AssistChip(
|
||||
onClick = {},
|
||||
imageVector = Icons.Default.Settings,
|
||||
contentDescription = ""
|
||||
contentDescription = "",
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -33,13 +33,13 @@ internal fun DrawerItem(
|
||||
destination: DrawerItem,
|
||||
icon: ImageVector,
|
||||
selected: Boolean,
|
||||
onClick: (DrawerItem) -> Unit
|
||||
onClick: (DrawerItem) -> Unit,
|
||||
) {
|
||||
NavigationDrawerItem(
|
||||
modifier = modifier,
|
||||
label = { Text(stringResource(destination.name)) },
|
||||
icon = { Icon(icon, stringResource(destination.name)) },
|
||||
selected = selected,
|
||||
onClick = { onClick(destination) }
|
||||
onClick = { onClick(destination) },
|
||||
)
|
||||
}
|
||||
|
@ -43,8 +43,8 @@ fun Header(
|
||||
start = 56.dp,
|
||||
end = 16.dp,
|
||||
top = 24.dp,
|
||||
bottom = 12.dp
|
||||
)
|
||||
bottom = 12.dp,
|
||||
),
|
||||
) {
|
||||
Text(
|
||||
modifier = modifier
|
||||
@ -53,6 +53,6 @@ fun Header(
|
||||
.fillMaxWidth(),
|
||||
text = text,
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
|
@ -64,15 +64,24 @@ fun BasicKeyboardButton(
|
||||
Box(
|
||||
modifier = modifier
|
||||
.squashable(
|
||||
onClick = { onClick(); vibrate() },
|
||||
onLongClick = if (onLongClick != null) { { onLongClick(); vibrate() } } else null,
|
||||
onClick = {
|
||||
onClick()
|
||||
vibrate()
|
||||
},
|
||||
onLongClick = if (onLongClick != null) {
|
||||
{
|
||||
onLongClick()
|
||||
vibrate()
|
||||
}
|
||||
} else {
|
||||
null
|
||||
},
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
cornerRadiusRange = 30..50,
|
||||
animationSpec = tween(200)
|
||||
animationSpec = tween(200),
|
||||
)
|
||||
.background(containerColor)
|
||||
,
|
||||
contentAlignment = Alignment.Center
|
||||
.background(containerColor),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
@ -84,7 +93,7 @@ fun BasicKeyboardButton(
|
||||
scaleX = contentHeight
|
||||
scaleY = contentHeight
|
||||
},
|
||||
tint = iconColor
|
||||
tint = iconColor,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -173,22 +182,25 @@ fun KeyboardButtonTertiary(
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Mostly for main button in portrait mode. Changes icon size inside.
|
||||
*/
|
||||
const val KeyboardButtonContentHeightTall = 1.1f
|
||||
object KeyboardButtonToken {
|
||||
|
||||
/**
|
||||
* Mostly for additional button in portrait mode. Changes icon size inside.
|
||||
*/
|
||||
const val KeyboardButtonContentHeightTallAdditional = 1.6f
|
||||
/**
|
||||
* Mostly for main button in portrait mode. Changes icon size inside.
|
||||
*/
|
||||
const val CONTENT_HEIGHT_TALL = 1.1f
|
||||
|
||||
/**
|
||||
* Mostly for main button in landscape mode. Changes icon size inside.
|
||||
*/
|
||||
const val KeyboardButtonContentHeightShort = 1.3f
|
||||
/**
|
||||
* Mostly for additional button in portrait mode. Changes icon size inside.
|
||||
*/
|
||||
const val CONTENT_HEIGHT_TALL_ADDITIONAL = 1.6f
|
||||
|
||||
/**
|
||||
* Mostly for additional button in landscape mode. Changes icon size inside.
|
||||
*/
|
||||
const val KeyboardButtonContentHeightShortAdditional = 1.1f
|
||||
/**
|
||||
* Mostly for main button in landscape mode. Changes icon size inside.
|
||||
*/
|
||||
const val CONTENT_HEIGHT_SHORT = 1.3f
|
||||
|
||||
/**
|
||||
* Mostly for additional button in landscape mode. Changes icon size inside.
|
||||
*/
|
||||
const val CONTENT_HEIGHT_SHORT_ADDITIONAL = 1.1f
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ fun KeypadFlow(
|
||||
columns: Int,
|
||||
@IntRange(0, 100) horizontalPadding: 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 width: Float = remember { (1f - horizontalPadding / 100f) / columns }
|
||||
@ -58,7 +58,7 @@ fun KeypadFlow(
|
||||
modifier = modifier,
|
||||
maxItemsInEachRow = columns,
|
||||
horizontalArrangement = Arrangement.SpaceAround,
|
||||
verticalArrangement = Arrangement.SpaceAround
|
||||
verticalArrangement = Arrangement.SpaceAround,
|
||||
) {
|
||||
content(width, height)
|
||||
}
|
||||
|
@ -57,12 +57,12 @@ fun ListItem(
|
||||
.padding(start = 16.dp, end = 24.dp)
|
||||
.heightIn(min = if (supportingContent == null) 56.dp else 72.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
leadingContent?.let {
|
||||
ProvideColor(
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
content = it
|
||||
content = it,
|
||||
)
|
||||
}
|
||||
|
||||
@ -70,20 +70,20 @@ fun ListItem(
|
||||
ProvideStyle(
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
textStyle = MaterialTheme.typography.bodyLarge,
|
||||
content = headlineContent
|
||||
content = headlineContent,
|
||||
)
|
||||
supportingContent?.let {
|
||||
ProvideStyle(
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
textStyle = MaterialTheme.typography.bodyMedium,
|
||||
content = it
|
||||
content = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
trailingContent?.let {
|
||||
ProvideColor(
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
content = it
|
||||
content = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -106,10 +106,10 @@ fun ListItem(
|
||||
imageVector = icon,
|
||||
contentDescription = iconDescription,
|
||||
modifier = Modifier.size(24.dp),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
},
|
||||
trailingContent = trailing
|
||||
trailingContent = trailing,
|
||||
)
|
||||
|
||||
@Composable
|
||||
@ -120,14 +120,14 @@ fun ListItem(
|
||||
iconDescription: String = headlineText,
|
||||
supportingText: String? = null,
|
||||
switchState: Boolean,
|
||||
onSwitchChange: (Boolean) -> Unit
|
||||
onSwitchChange: (Boolean) -> Unit,
|
||||
) = ListItem(
|
||||
modifier = modifier
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
onClick = { onSwitchChange(!switchState) },
|
||||
role = Role.Switch
|
||||
role = Role.Switch,
|
||||
),
|
||||
headlineText = headlineText,
|
||||
supportingText = supportingText,
|
||||
@ -136,9 +136,9 @@ fun ListItem(
|
||||
trailing = {
|
||||
Switch(
|
||||
checked = switchState,
|
||||
onCheckedChange = { onSwitchChange(it) }
|
||||
onCheckedChange = { onSwitchChange(it) },
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@Preview
|
||||
@ -152,7 +152,7 @@ fun PreviewListItem1() {
|
||||
leadingContent = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Home,
|
||||
contentDescription = null
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
)
|
||||
@ -171,7 +171,7 @@ fun PreviewListItem1() {
|
||||
supportingText = "Support text support text support text support text",
|
||||
modifier = Modifier,
|
||||
trailing = {},
|
||||
iconDescription = ""
|
||||
iconDescription = "",
|
||||
)
|
||||
|
||||
ListItem(
|
||||
|
@ -47,7 +47,7 @@ fun Modifier.squashable(
|
||||
val cornerRadius: Int by animateIntAsState(
|
||||
targetValue = if (isPressed) cornerRadiusRange.first else cornerRadiusRange.last,
|
||||
animationSpec = animationSpec,
|
||||
label = "Squashed animation"
|
||||
label = "Squashed animation",
|
||||
)
|
||||
|
||||
this
|
||||
@ -58,7 +58,7 @@ fun Modifier.squashable(
|
||||
interactionSource = interactionSource,
|
||||
indication = rememberRipple(),
|
||||
role = role,
|
||||
enabled = enabled
|
||||
enabled = enabled,
|
||||
)
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ fun Modifier.squashable(
|
||||
val cornerRadius: Dp by animateDpAsState(
|
||||
targetValue = if (isPressed) cornerRadiusRange.start else cornerRadiusRange.endInclusive,
|
||||
animationSpec = animationSpec,
|
||||
label = "Squashed animation"
|
||||
label = "Squashed animation",
|
||||
)
|
||||
|
||||
this
|
||||
@ -86,6 +86,6 @@ fun Modifier.squashable(
|
||||
interactionSource = interactionSource,
|
||||
indication = rememberRipple(),
|
||||
role = role,
|
||||
enabled = enabled
|
||||
enabled = enabled,
|
||||
)
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ fun NavigateUpButton(onClick: () -> Unit) {
|
||||
IconButton(onClick = onClick) {
|
||||
Icon(
|
||||
Icons.AutoMirrored.Outlined.ArrowBack,
|
||||
contentDescription = stringResource(R.string.navigate_up_description)
|
||||
contentDescription = stringResource(R.string.navigate_up_description),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ class DrawerState(
|
||||
initialValue = initialValue,
|
||||
positionalThreshold = { distance -> distance * 0.5f },
|
||||
velocityThreshold = { with(requireNotNull(density)) { 400.dp.toPx() } },
|
||||
animationSpec = tween()
|
||||
animationSpec = tween(),
|
||||
)
|
||||
|
||||
val isOpen: Boolean
|
||||
@ -89,10 +89,10 @@ class DrawerState(
|
||||
suspend fun close() = anchoredDraggableState.animateTo(DrawerValue.Closed)
|
||||
|
||||
companion object {
|
||||
internal fun Saver() =
|
||||
internal fun saver() =
|
||||
Saver<DrawerState, DrawerValue>(
|
||||
save = { it.currentValue },
|
||||
restore = { DrawerState(it) }
|
||||
restore = { DrawerState(it) },
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -101,7 +101,7 @@ class DrawerState(
|
||||
fun rememberDrawerState(
|
||||
initialValue: DrawerValue = DrawerValue.Closed,
|
||||
): DrawerState {
|
||||
return rememberSaveable(saver = DrawerState.Saver()) {
|
||||
return rememberSaveable(saver = DrawerState.saver()) {
|
||||
DrawerState(initialValue)
|
||||
}
|
||||
}
|
||||
@ -124,17 +124,17 @@ fun NavigationDrawer(
|
||||
PermanentDrawerSheet(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.verticalScroll(rememberScrollState()),
|
||||
) {
|
||||
SheetContent(
|
||||
mainTabs = mainTabs,
|
||||
additionalTabs = additionalTabs,
|
||||
currentDestination = currentDestination,
|
||||
onItemClick = onItemClick
|
||||
onItemClick = onItemClick,
|
||||
)
|
||||
}
|
||||
},
|
||||
content = content
|
||||
content = content,
|
||||
)
|
||||
} else {
|
||||
UnittoModalNavigationDrawer(
|
||||
@ -143,19 +143,19 @@ fun NavigationDrawer(
|
||||
ModalDrawerSheet(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.verticalScroll(rememberScrollState()),
|
||||
) {
|
||||
SheetContent(
|
||||
mainTabs = mainTabs,
|
||||
additionalTabs = additionalTabs,
|
||||
currentDestination = currentDestination,
|
||||
onItemClick = onItemClick
|
||||
onItemClick = onItemClick,
|
||||
)
|
||||
}
|
||||
},
|
||||
gesturesEnabled = gesturesEnabled,
|
||||
state = state,
|
||||
content = content
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -173,7 +173,7 @@ private fun UnittoModalNavigationDrawer(
|
||||
val drawerScope = rememberCoroutineScope()
|
||||
|
||||
Box(
|
||||
modifier = modifier.fillMaxSize()
|
||||
modifier = modifier.fillMaxSize(),
|
||||
) {
|
||||
val drawerWidth = 360.dp
|
||||
val drawerWidthPx = with(density) { drawerWidth.toPx() }
|
||||
@ -186,7 +186,7 @@ private fun UnittoModalNavigationDrawer(
|
||||
DraggableAnchors {
|
||||
DrawerValue.Closed at minValue
|
||||
DrawerValue.Open at maxValue
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@ -202,7 +202,7 @@ private fun UnittoModalNavigationDrawer(
|
||||
state = state.anchoredDraggableState,
|
||||
orientation = Orientation.Horizontal,
|
||||
enabled = gesturesEnabled or state.isOpen,
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
Scrim(
|
||||
@ -210,7 +210,9 @@ private fun UnittoModalNavigationDrawer(
|
||||
onClose = { if (gesturesEnabled) drawerScope.launch { state.close() } },
|
||||
fraction = {
|
||||
fraction(
|
||||
minValue, maxValue, state.anchoredDraggableState.requireOffset()
|
||||
minValue,
|
||||
maxValue,
|
||||
state.anchoredDraggableState.requireOffset(),
|
||||
)
|
||||
},
|
||||
)
|
||||
@ -224,14 +226,14 @@ private fun UnittoModalNavigationDrawer(
|
||||
.anchoredDraggableState
|
||||
.requireOffset()
|
||||
.roundToInt(),
|
||||
y = 0
|
||||
y = 0,
|
||||
)
|
||||
}
|
||||
.anchoredDraggable(
|
||||
state = state.anchoredDraggableState,
|
||||
orientation = Orientation.Horizontal,
|
||||
enabled = gesturesEnabled or state.isOpen,
|
||||
)
|
||||
),
|
||||
) {
|
||||
drawerContent()
|
||||
}
|
||||
@ -254,7 +256,7 @@ private fun Scrim(
|
||||
Canvas(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.then(dismissDrawer)
|
||||
.then(dismissDrawer),
|
||||
) {
|
||||
drawRect(color, alpha = fraction())
|
||||
}
|
||||
@ -266,12 +268,12 @@ private fun fraction(a: Float, b: Float, pos: Float) =
|
||||
@Preview(
|
||||
backgroundColor = 0xFFC8F7D4,
|
||||
showBackground = true,
|
||||
device = "spec:width=320dp,height=500dp,dpi=320"
|
||||
device = "spec:width=320dp,height=500dp,dpi=320",
|
||||
)
|
||||
@Preview(
|
||||
backgroundColor = 0xFFC8F7D4,
|
||||
showBackground = true,
|
||||
device = "spec:width=440dp,height=500dp,dpi=440"
|
||||
device = "spec:width=440dp,height=500dp,dpi=440",
|
||||
)
|
||||
@Composable
|
||||
private fun PreviewUnittoModalNavigationDrawerClose() {
|
||||
@ -290,11 +292,11 @@ private fun PreviewUnittoModalNavigationDrawerClose() {
|
||||
Column {
|
||||
Text(text = "Content")
|
||||
Button(
|
||||
onClick = { corScope.launch { drawerState.open() } }
|
||||
onClick = { corScope.launch { drawerState.open() } },
|
||||
) {
|
||||
Text(text = "BUTTON")
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -81,12 +81,12 @@ fun PagedIsland(
|
||||
corScope.launch {
|
||||
pagerState.animateScrollToPage(
|
||||
// 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)
|
||||
.padding(16.dp)
|
||||
.padding(16.dp),
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
@ -105,7 +105,7 @@ fun PagedIsland(
|
||||
.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.Top,
|
||||
state = pagerState,
|
||||
pageContent = { page -> pageContent(page % pageCount) }
|
||||
pageContent = { page -> pageContent(page % pageCount) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -52,8 +52,11 @@ fun PortraitLandscape(
|
||||
.weight(1f)
|
||||
.fillMaxSize()
|
||||
.padding(
|
||||
it.maxWidth * 0.015f, 0.dp,
|
||||
it.maxHeight * 0.03f, it.maxHeight * 0.03f)
|
||||
it.maxWidth * 0.015f,
|
||||
0.dp,
|
||||
it.maxHeight * 0.03f,
|
||||
it.maxHeight * 0.03f,
|
||||
)
|
||||
content1(contentModifier)
|
||||
content2(contentModifier)
|
||||
}
|
||||
|
@ -41,10 +41,10 @@ fun ScaffoldWithLargeTopBar(
|
||||
title: String,
|
||||
navigationIcon: @Composable () -> Unit,
|
||||
actions: @Composable RowScope.() -> Unit = {},
|
||||
content: @Composable (PaddingValues) -> Unit
|
||||
content: @Composable (PaddingValues) -> Unit,
|
||||
) {
|
||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(
|
||||
rememberTopAppBarState()
|
||||
rememberTopAppBarState(),
|
||||
)
|
||||
Scaffold(
|
||||
modifier = Modifier
|
||||
@ -56,9 +56,9 @@ fun ScaffoldWithLargeTopBar(
|
||||
},
|
||||
navigationIcon = navigationIcon,
|
||||
scrollBehavior = scrollBehavior,
|
||||
actions = actions
|
||||
actions = actions,
|
||||
)
|
||||
},
|
||||
content = content
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ fun ScaffoldWithTopBar(
|
||||
floatingActionButton: @Composable () -> Unit = {},
|
||||
floatingActionButtonPosition: FabPosition = FabPosition.End,
|
||||
scrollBehavior: TopAppBarScrollBehavior? = null,
|
||||
content: @Composable (PaddingValues) -> Unit
|
||||
content: @Composable (PaddingValues) -> Unit,
|
||||
) {
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
@ -67,7 +67,7 @@ fun ScaffoldWithTopBar(
|
||||
AnimatedVisibility(
|
||||
visible = LocalWindowSize.current.heightSizeClass > WindowHeightSizeClass.Compact,
|
||||
enter = slideInVertically() + fadeIn(),
|
||||
exit = slideOutVertically() + fadeOut()
|
||||
exit = slideOutVertically() + fadeOut(),
|
||||
) {
|
||||
CenterAlignedTopAppBar(
|
||||
title = title,
|
||||
@ -84,6 +84,6 @@ fun ScaffoldWithTopBar(
|
||||
},
|
||||
floatingActionButton = floatingActionButton,
|
||||
floatingActionButtonPosition = floatingActionButtonPosition,
|
||||
content = content
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ fun SearchBar(
|
||||
modifier = modifier
|
||||
.windowInsetsPadding(TopAppBarDefaults.windowInsets)
|
||||
.height(height),
|
||||
contentAlignment = Alignment.Center
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
@ -121,10 +121,9 @@ fun SearchBar(
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp)
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
ProvideColor(MaterialTheme.colorScheme.onSurface) {
|
||||
|
||||
NavigateButton { if (notEmpty) clear() else navigateUp() }
|
||||
|
||||
SearchTextField(
|
||||
@ -135,7 +134,7 @@ fun SearchBar(
|
||||
value = query,
|
||||
placeholder = stringResource(R.string.search_text_field_placeholder),
|
||||
onValueChange = onQueryChange,
|
||||
onSearch = onSearch
|
||||
onSearch = onSearch,
|
||||
)
|
||||
|
||||
ClearButton(notEmpty, ::clear)
|
||||
@ -152,7 +151,7 @@ private fun SearchTextField(
|
||||
value: TextFieldValue,
|
||||
placeholder: String,
|
||||
onValueChange: (TextFieldValue) -> Unit,
|
||||
onSearch: KeyboardActionScope.() -> Unit
|
||||
onSearch: KeyboardActionScope.() -> Unit,
|
||||
) {
|
||||
BasicTextField(
|
||||
modifier = modifier,
|
||||
@ -171,33 +170,33 @@ private fun SearchTextField(
|
||||
modifier = Modifier.alpha(0.7f),
|
||||
text = placeholder,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SearchButton(
|
||||
onClick: () -> Unit
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
SearchBarIconButton(onClick) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Search,
|
||||
contentDescription = stringResource(R.string.search_button_description)
|
||||
contentDescription = stringResource(R.string.search_button_description),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NavigateButton(
|
||||
onClick: () -> Unit
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
SearchBarIconButton(onClick) {
|
||||
Icon(
|
||||
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
|
||||
private fun ClearButton(
|
||||
visible: Boolean,
|
||||
onClick: () -> Unit
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = visible,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut()
|
||||
exit = fadeOut(),
|
||||
) {
|
||||
SearchBarIconButton(onClick) {
|
||||
Icon(
|
||||
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
|
||||
fun SearchBarIconButton(
|
||||
onClick: () -> Unit,
|
||||
content: @Composable () -> Unit
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
@ -236,10 +235,10 @@ fun SearchBarIconButton(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(
|
||||
bounded = false,
|
||||
radius = 20.dp
|
||||
)
|
||||
radius = 20.dp,
|
||||
),
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
content()
|
||||
}
|
||||
@ -259,6 +258,6 @@ fun UnittoSearchBarPreview() {
|
||||
query = TextFieldValue("test"),
|
||||
onQueryChange = {},
|
||||
navigateUp = {},
|
||||
scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
|
||||
scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(),
|
||||
)
|
||||
}
|
||||
|
@ -41,29 +41,29 @@ import com.sadellie.unitto.core.base.R
|
||||
fun SearchPlaceholder(
|
||||
onButtonClick: () -> Unit,
|
||||
supportText: String,
|
||||
buttonLabel: String
|
||||
buttonLabel: String,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.SearchOff,
|
||||
contentDescription = stringResource(R.string.no_results_description),
|
||||
modifier = Modifier.size(48.dp)
|
||||
modifier = Modifier.size(48.dp),
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.no_results_label),
|
||||
textAlign = TextAlign.Center,
|
||||
style = MaterialTheme.typography.bodyLarge
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
)
|
||||
Text(
|
||||
text = supportText,
|
||||
textAlign = TextAlign.Center,
|
||||
style = MaterialTheme.typography.bodySmall
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
)
|
||||
ElevatedButton(onClick = onButtonClick) {
|
||||
Text(text = buttonLabel)
|
||||
|
@ -47,14 +47,14 @@ import androidx.compose.ui.unit.dp
|
||||
@Composable
|
||||
fun SegmentedButtonsRow(
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable RowScope.() -> Unit
|
||||
content: @Composable RowScope.() -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier
|
||||
.width(IntrinsicSize.Max)
|
||||
.height(40.dp)
|
||||
.clip(CircleShape)
|
||||
.border(1.dp, MaterialTheme.colorScheme.outline, CircleShape)
|
||||
.border(1.dp, MaterialTheme.colorScheme.outline, CircleShape),
|
||||
) {
|
||||
content()
|
||||
}
|
||||
@ -66,7 +66,7 @@ fun RowScope.SegmentedButton(
|
||||
label: String,
|
||||
onClick: () -> Unit,
|
||||
selected: Boolean,
|
||||
icon: ImageVector? = null
|
||||
icon: ImageVector? = null,
|
||||
) {
|
||||
val containerColor =
|
||||
if (selected) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.surface
|
||||
@ -77,9 +77,9 @@ fun RowScope.SegmentedButton(
|
||||
shape = RectangleShape,
|
||||
colors = ButtonDefaults.outlinedButtonColors(
|
||||
containerColor = containerColor,
|
||||
contentColor = contentColorFor(containerColor)
|
||||
contentColor = contentColorFor(containerColor),
|
||||
),
|
||||
contentPadding = PaddingValues(horizontal = 12.dp)
|
||||
contentPadding = PaddingValues(horizontal = 12.dp),
|
||||
) {
|
||||
if (icon != null) {
|
||||
Crossfade(selected, label = "Selected state") {
|
||||
|
@ -67,14 +67,14 @@ internal fun ColumnScope.SheetContent(
|
||||
modifier = Modifier.clickable(
|
||||
interactionSource = interactionSource,
|
||||
indication = null,
|
||||
onClick = { showHello = true }
|
||||
)
|
||||
onClick = { showHello = true },
|
||||
),
|
||||
) { hello ->
|
||||
Text(
|
||||
text = if (hello) stringResource(R.string.hello_label) else stringResource(R.string.app_name),
|
||||
modifier = Modifier.padding(horizontal = 28.dp, vertical = 24.dp),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ internal fun ColumnScope.SheetContent(
|
||||
destination = drawerItem,
|
||||
icon = if (selected) drawerItem.selectedIcon else drawerItem.defaultIcon,
|
||||
selected = selected,
|
||||
onClick = onItemClick
|
||||
onClick = onItemClick,
|
||||
)
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ internal fun ColumnScope.SheetContent(
|
||||
destination = drawerItem,
|
||||
icon = if (selected) drawerItem.selectedIcon else drawerItem.defaultIcon,
|
||||
selected = selected,
|
||||
onClick = onItemClick
|
||||
onClick = onItemClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -119,7 +119,7 @@ private fun PreviewDrawerSheet() {
|
||||
DrawerItem.Calculator,
|
||||
),
|
||||
currentDestination = DrawerItem.Calculator.start,
|
||||
onItemClick = {}
|
||||
onItemClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -56,12 +56,12 @@ fun Slider(
|
||||
value: Float,
|
||||
valueRange: ClosedFloatingPointRange<Float>,
|
||||
onValueChange: (Float) -> Unit,
|
||||
onValueChangeFinished: (Float) -> Unit = {}
|
||||
onValueChangeFinished: (Float) -> Unit = {},
|
||||
) {
|
||||
val animated = animateFloatAsState(
|
||||
targetValue = value.roundToInt().toFloat(),
|
||||
animationSpec = spring(),
|
||||
label = "Thumb animation"
|
||||
label = "Thumb animation",
|
||||
)
|
||||
|
||||
Slider(
|
||||
@ -81,14 +81,14 @@ private fun SquigglyTrack(
|
||||
@FloatRange(0.0, 1.0) waveHeight: Float = 0.7f,
|
||||
strokeWidth: Float = 15f,
|
||||
filledColor: Color = MaterialTheme.colorScheme.primary,
|
||||
unfilledColor: Color = MaterialTheme.colorScheme.surfaceVariant
|
||||
unfilledColor: Color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
) {
|
||||
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(
|
||||
targetValue = direct,
|
||||
animationSpec = spring(stiffness = Spring.StiffnessLow),
|
||||
label = "Track animation"
|
||||
label = "Track animation",
|
||||
)
|
||||
|
||||
LaunchedEffect(sliderState.value) {
|
||||
@ -101,7 +101,7 @@ private fun SquigglyTrack(
|
||||
Canvas(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(20.dp)
|
||||
.height(20.dp),
|
||||
) {
|
||||
val width = size.width
|
||||
val height = size.height
|
||||
@ -114,7 +114,7 @@ private fun SquigglyTrack(
|
||||
val path = Path().apply {
|
||||
moveTo(
|
||||
x = initialOffset,
|
||||
y = height.times(0.5f)
|
||||
y = height.times(0.5f),
|
||||
)
|
||||
val amount = ceil(width.div(eachWaveWidth))
|
||||
|
||||
@ -125,7 +125,7 @@ private fun SquigglyTrack(
|
||||
dx1 = eachWaveWidth * 0.5f,
|
||||
dy1 = height.times(peek),
|
||||
dx2 = eachWaveWidth,
|
||||
dy2 = 0f
|
||||
dy2 = 0f,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -135,12 +135,12 @@ private fun SquigglyTrack(
|
||||
left = 0f,
|
||||
right = thumbPosition,
|
||||
bottom = height,
|
||||
clipOp = ClipOp.Intersect
|
||||
clipOp = ClipOp.Intersect,
|
||||
) {
|
||||
drawPath(
|
||||
path = path,
|
||||
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)),
|
||||
end = Offset(width, height.times(0.5f)),
|
||||
strokeWidth = strokeWidth,
|
||||
cap = StrokeCap.Round
|
||||
cap = StrokeCap.Round,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -165,6 +165,6 @@ private fun PreviewNewSlider() {
|
||||
com.sadellie.unitto.core.ui.common.Slider(
|
||||
value = currentValue,
|
||||
valueRange = 0f..16f,
|
||||
onValueChange = { currentValue = it }
|
||||
onValueChange = { currentValue = it },
|
||||
)
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ fun Switch(
|
||||
)
|
||||
val thumbOffset = animateDpAsState(
|
||||
targetValue = if (checked) ThumbPaddingEnd else ThumbPaddingStart,
|
||||
label = "Thumb offset"
|
||||
label = "Thumb offset",
|
||||
)
|
||||
|
||||
Box(
|
||||
@ -81,15 +81,15 @@ fun Switch(
|
||||
enabled = true,
|
||||
onClickLabel = null,
|
||||
role = Role.Switch,
|
||||
onClick = { onCheckedChange(!checked) }
|
||||
onClick = { onCheckedChange(!checked) },
|
||||
)
|
||||
.background(trackColor.value, CircleShape)
|
||||
.size(TrackWidth, TrackHeight)
|
||||
.border(
|
||||
TrackOutlineWidth,
|
||||
borderColor(enabled, checked, colors),
|
||||
CircleShape
|
||||
)
|
||||
CircleShape,
|
||||
),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
@ -100,7 +100,7 @@ fun Switch(
|
||||
)
|
||||
.align(Alignment.CenterStart)
|
||||
.background(thumbColor.value, CircleShape)
|
||||
.size(thumbSize.value)
|
||||
.size(thumbSize.value),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -109,7 +109,7 @@ fun Switch(
|
||||
private fun trackColor(
|
||||
enabled: Boolean,
|
||||
checked: Boolean,
|
||||
colors: SwitchColors
|
||||
colors: SwitchColors,
|
||||
): Color =
|
||||
if (enabled) {
|
||||
if (checked) colors.checkedTrackColor else colors.uncheckedTrackColor
|
||||
@ -121,7 +121,7 @@ private fun trackColor(
|
||||
private fun thumbColor(
|
||||
enabled: Boolean,
|
||||
checked: Boolean,
|
||||
colors: SwitchColors
|
||||
colors: SwitchColors,
|
||||
): Color =
|
||||
if (enabled) {
|
||||
if (checked) colors.checkedThumbColor else colors.uncheckedThumbColor
|
||||
@ -133,7 +133,7 @@ private fun thumbColor(
|
||||
private fun borderColor(
|
||||
enabled: Boolean,
|
||||
checked: Boolean,
|
||||
colors: SwitchColors
|
||||
colors: SwitchColors,
|
||||
): Color =
|
||||
if (enabled) {
|
||||
if (checked) colors.checkedBorderColor else colors.uncheckedBorderColor
|
||||
@ -147,7 +147,7 @@ val TrackOutlineWidth = 1.8.dp
|
||||
val SelectedHandleSize = 20.0.dp
|
||||
val UnselectedHandleSize = 20.0.dp
|
||||
|
||||
val ThumbPaddingStart = (TrackHeight - UnselectedHandleSize) / 2
|
||||
val ThumbPaddingStart = (TrackHeight - UnselectedHandleSize) / 2
|
||||
val ThumbPaddingEnd = TrackWidth - SelectedHandleSize / 2 - TrackHeight / 2
|
||||
|
||||
@Preview
|
||||
@ -156,6 +156,6 @@ fun PreviewPixelSwitch() {
|
||||
var checked by remember { mutableStateOf(false) }
|
||||
Switch(
|
||||
checked = checked,
|
||||
onCheckedChange = { checked = !checked }
|
||||
onCheckedChange = { checked = !checked },
|
||||
)
|
||||
}
|
||||
|
@ -34,11 +34,11 @@ fun ColumnWithConstraints(
|
||||
modifier: Modifier = Modifier,
|
||||
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
|
||||
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
|
||||
content: @Composable (ColumnScope.(BoxWithConstraintsScope)-> Unit)
|
||||
content: @Composable (ColumnScope.(BoxWithConstraintsScope) -> Unit),
|
||||
) = BoxWithConstraints(modifier) {
|
||||
Column(
|
||||
verticalArrangement = verticalArrangement,
|
||||
horizontalAlignment = horizontalAlignment
|
||||
horizontalAlignment = horizontalAlignment,
|
||||
) { content(this@BoxWithConstraints) }
|
||||
}
|
||||
|
||||
@ -47,10 +47,10 @@ fun RowWithConstraints(
|
||||
modifier: Modifier = Modifier,
|
||||
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
|
||||
verticalAlignment: Alignment.Vertical = Alignment.Top,
|
||||
content: @Composable (RowScope.(BoxWithConstraintsScope)-> Unit)
|
||||
content: @Composable (RowScope.(BoxWithConstraintsScope) -> Unit),
|
||||
) = BoxWithConstraints(modifier) {
|
||||
Row(
|
||||
horizontalArrangement = horizontalArrangement,
|
||||
verticalAlignment = verticalAlignment
|
||||
verticalAlignment = verticalAlignment,
|
||||
) { content(this@BoxWithConstraints) }
|
||||
}
|
||||
|
@ -43,54 +43,6 @@ import androidx.compose.ui.unit.TextUnit
|
||||
import kotlin.math.min
|
||||
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].
|
||||
*
|
||||
@ -122,11 +74,11 @@ internal fun AutoSizeTextStyleBox(
|
||||
style: TextStyle,
|
||||
minRatio: Float,
|
||||
alignment: Alignment,
|
||||
content: @Composable () -> Unit
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val density = LocalDensity.current
|
||||
CompositionLocalProvider(
|
||||
LocalDensity provides Density(density = density.density, fontScale = 1F)
|
||||
LocalDensity provides Density(density = density.density, fontScale = 1F),
|
||||
) {
|
||||
BoxWithConstraints(
|
||||
modifier = modifier,
|
||||
@ -141,12 +93,12 @@ internal fun AutoSizeTextStyleBox(
|
||||
style = style,
|
||||
alignment = alignment,
|
||||
density = density,
|
||||
minRatio = minRatio
|
||||
minRatio = minRatio,
|
||||
)
|
||||
|
||||
CompositionLocalProvider(
|
||||
value = LocalTextStyle.provides(autoTextStyle),
|
||||
content = content
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -290,10 +242,11 @@ private fun <E> IntProgression.findElectedValue(
|
||||
var high = last
|
||||
while (low <= high) {
|
||||
val mid = low + (high - low) / 2
|
||||
if (shouldMoveBackward(transform(mid)))
|
||||
if (shouldMoveBackward(transform(mid))) {
|
||||
high = mid - 1
|
||||
else
|
||||
} else {
|
||||
low = mid + 1
|
||||
}
|
||||
}
|
||||
transform(high.coerceAtLeast(minimumValue = first))
|
||||
}
|
||||
|
@ -27,5 +27,8 @@ import androidx.compose.ui.unit.isSpecified
|
||||
internal fun Density.roundToPx(sp: TextUnit): Int = sp.roundToPx()
|
||||
internal fun Density.toSp(px: Int): TextUnit = px.toSp()
|
||||
internal fun Density.toIntSize(dpSize: DpSize): IntSize =
|
||||
if (dpSize.isSpecified) IntSize(dpSize.width.roundToPx(), dpSize.height.roundToPx())
|
||||
else IntSize.Zero
|
||||
if (dpSize.isSpecified) {
|
||||
IntSize(dpSize.width.roundToPx(), dpSize.height.roundToPx())
|
||||
} else {
|
||||
IntSize.Zero
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ fun DatePickerDialog(
|
||||
BasicAlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
modifier = modifier.wrapContentHeight(),
|
||||
properties = DialogProperties(usePlatformDefaultWidth = false)
|
||||
properties = DialogProperties(usePlatformDefaultWidth = false),
|
||||
) {
|
||||
Surface(
|
||||
modifier = modifier
|
||||
@ -83,15 +83,14 @@ fun DatePickerDialog(
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(Alignment.End)
|
||||
.padding(_dialogButtonsPadding)
|
||||
.padding(_dialogButtonsPadding),
|
||||
) {
|
||||
|
||||
AlertDialogFlowRow(
|
||||
mainAxisSpacing = _dialogButtonsMainAxisSpacing,
|
||||
crossAxisSpacing = _dialogButtonsCrossAxisSpacing
|
||||
crossAxisSpacing = _dialogButtonsCrossAxisSpacing,
|
||||
) {
|
||||
TextButton(
|
||||
onClick = onDismiss
|
||||
onClick = onDismiss,
|
||||
) {
|
||||
Text(text = dismissLabel)
|
||||
}
|
||||
@ -100,16 +99,17 @@ fun DatePickerDialog(
|
||||
val millis = pickerState.selectedDateMillis ?: return@TextButton
|
||||
|
||||
val date = LocalDateTime.ofInstant(
|
||||
Instant.ofEpochMilli(millis), ZoneId.systemDefault()
|
||||
Instant.ofEpochMilli(millis),
|
||||
ZoneId.systemDefault(),
|
||||
)
|
||||
|
||||
onConfirm(
|
||||
localDateTime
|
||||
.withYear(date.year)
|
||||
.withMonth(date.monthValue)
|
||||
.withDayOfMonth(date.dayOfMonth)
|
||||
.withDayOfMonth(date.dayOfMonth),
|
||||
)
|
||||
}
|
||||
},
|
||||
) {
|
||||
Text(text = confirmLabel)
|
||||
}
|
||||
@ -125,7 +125,7 @@ fun DatePickerDialog(
|
||||
private fun AlertDialogFlowRow(
|
||||
mainAxisSpacing: Dp,
|
||||
crossAxisSpacing: Dp,
|
||||
content: @Composable () -> Unit
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Layout(content) { measurables, constraints ->
|
||||
val sequences = mutableListOf<List<Placeable>>()
|
||||
@ -142,7 +142,7 @@ private fun AlertDialogFlowRow(
|
||||
// Return whether the placeable can be added to the current sequence.
|
||||
fun canAddToCurrentSequence(placeable: Placeable) =
|
||||
currentSequence.isEmpty() || currentMainAxisSize + mainAxisSpacing.roundToPx() +
|
||||
placeable.width <= constraints.maxWidth
|
||||
placeable.width <= constraints.maxWidth
|
||||
|
||||
// Store current sequence information and start a new sequence.
|
||||
fun startNewSequence() {
|
||||
@ -187,20 +187,22 @@ private fun AlertDialogFlowRow(
|
||||
sequences.forEachIndexed { i, placeables ->
|
||||
val childrenMainAxisSizes = IntArray(placeables.size) { j ->
|
||||
placeables[j].width +
|
||||
if (j < placeables.lastIndex) mainAxisSpacing.roundToPx() else 0
|
||||
if (j < placeables.lastIndex) mainAxisSpacing.roundToPx() else 0
|
||||
}
|
||||
val arrangement = Arrangement.End
|
||||
val mainAxisPositions = IntArray(childrenMainAxisSizes.size) { 0 }
|
||||
with(arrangement) {
|
||||
arrange(
|
||||
mainAxisLayoutSize, childrenMainAxisSizes,
|
||||
layoutDirection, mainAxisPositions
|
||||
mainAxisLayoutSize,
|
||||
childrenMainAxisSizes,
|
||||
layoutDirection,
|
||||
mainAxisPositions,
|
||||
)
|
||||
}
|
||||
placeables.forEachIndexed { j, placeable ->
|
||||
placeable.place(
|
||||
x = mainAxisPositions[j],
|
||||
y = crossAxisPositions[i]
|
||||
y = crossAxisPositions[i],
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -210,4 +212,4 @@ private fun AlertDialogFlowRow(
|
||||
|
||||
private val _dialogButtonsPadding by lazy { PaddingValues(bottom = 8.dp, end = 6.dp) }
|
||||
private val _dialogButtonsMainAxisSpacing by lazy { 8.dp }
|
||||
private val _dialogButtonsCrossAxisSpacing by lazy { 12.dp }
|
||||
private val _dialogButtonsCrossAxisSpacing by lazy { 12.dp }
|
||||
|
@ -73,7 +73,7 @@ fun TimePickerDialog(
|
||||
val pickerState = rememberTimePickerState(
|
||||
initialHour = hour,
|
||||
initialMinute = minute,
|
||||
is24Hour = DateFormat.is24HourFormat(LocalContext.current)
|
||||
is24Hour = DateFormat.is24HourFormat(LocalContext.current),
|
||||
)
|
||||
val configuration = LocalConfiguration.current
|
||||
var showingPicker by rememberSaveable { mutableStateOf(true) }
|
||||
@ -81,8 +81,8 @@ fun TimePickerDialog(
|
||||
BasicAlertDialog(
|
||||
onDismissRequest = onCancel,
|
||||
properties = DialogProperties(
|
||||
usePlatformDefaultWidth = false
|
||||
)
|
||||
usePlatformDefaultWidth = false,
|
||||
),
|
||||
) {
|
||||
Surface(
|
||||
shape = MaterialTheme.shapes.extraLarge,
|
||||
@ -92,7 +92,7 @@ fun TimePickerDialog(
|
||||
.height(IntrinsicSize.Min)
|
||||
.background(
|
||||
shape = MaterialTheme.shapes.extraLarge,
|
||||
color = MaterialTheme.colorScheme.surface
|
||||
color = MaterialTheme.colorScheme.surface,
|
||||
),
|
||||
) {
|
||||
if (configuration.screenHeightDp > 400) {
|
||||
@ -103,7 +103,7 @@ fun TimePickerDialog(
|
||||
.fillMaxSize()
|
||||
.semantics {
|
||||
isTraversalGroup = true
|
||||
}
|
||||
},
|
||||
) {
|
||||
IconButton(
|
||||
modifier = Modifier
|
||||
@ -114,7 +114,8 @@ fun TimePickerDialog(
|
||||
.size(64.dp, 72.dp)
|
||||
.align(Alignment.BottomStart)
|
||||
.zIndex(5f),
|
||||
onClick = { showingPicker = !showingPicker }) {
|
||||
onClick = { showingPicker = !showingPicker },
|
||||
) {
|
||||
val icon = if (showingPicker) {
|
||||
Icons.Outlined.Keyboard
|
||||
} else {
|
||||
@ -122,21 +123,21 @@ fun TimePickerDialog(
|
||||
}
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = stringResource(R.string.select_time_label)
|
||||
contentDescription = stringResource(R.string.select_time_label),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.padding(24.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 20.dp),
|
||||
text = stringResource(R.string.select_time_label),
|
||||
style = MaterialTheme.typography.labelMedium
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
if (showingPicker && configuration.screenHeightDp > 400) {
|
||||
TimePicker(state = pickerState)
|
||||
@ -146,14 +147,14 @@ fun TimePickerDialog(
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.height(40.dp)
|
||||
.fillMaxWidth()
|
||||
.fillMaxWidth(),
|
||||
) {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
TextButton(
|
||||
onClick = onCancel
|
||||
onClick = onCancel,
|
||||
) { Text(stringResource(R.string.cancel_label)) }
|
||||
TextButton(
|
||||
onClick = { onConfirm(pickerState.hour, pickerState.minute) }
|
||||
onClick = { onConfirm(pickerState.hour, pickerState.minute) },
|
||||
) { Text(confirmLabel) }
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -16,6 +16,8 @@
|
||||
* 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
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -32,20 +32,20 @@ import com.sadellie.unitto.core.base.Token
|
||||
*/
|
||||
internal class ExpressionClipboardManager(
|
||||
private val formatterSymbols: FormatterSymbols,
|
||||
private val clipboardManager: android.content.ClipboardManager
|
||||
): ClipboardManager {
|
||||
private val clipboardManager: android.content.ClipboardManager,
|
||||
) : ClipboardManager {
|
||||
override fun setText(annotatedString: AnnotatedString) = clipboardManager.setPrimaryClip(
|
||||
ClipData.newPlainText(
|
||||
PLAIN_TEXT_LABEL,
|
||||
annotatedString
|
||||
.text
|
||||
.replace(Token.Digit.dot, formatterSymbols.fractional)
|
||||
)
|
||||
.replace(Token.Digit.dot, formatterSymbols.fractional),
|
||||
),
|
||||
)
|
||||
|
||||
override fun getText(): AnnotatedString? = clipboardManager.primaryClip?.let { primaryClip ->
|
||||
if (primaryClip.itemCount > 0) {
|
||||
val clipText = primaryClip.getItemAt(0)?.text ?:return@let null
|
||||
val clipText = primaryClip.getItemAt(0)?.text ?: return@let null
|
||||
|
||||
clipText
|
||||
.toString()
|
||||
|
@ -22,7 +22,6 @@ import com.sadellie.unitto.core.base.Token
|
||||
import kotlin.math.abs
|
||||
|
||||
fun String.fixCursor(pos: Int, grouping: String): Int {
|
||||
|
||||
if (isEmpty()) return pos
|
||||
|
||||
// Best position if we move cursor left
|
||||
@ -75,7 +74,7 @@ private fun Int.isAtToken(str: String, token: String): Boolean {
|
||||
return str
|
||||
.substring(
|
||||
startIndex = (this - checkBound).coerceAtLeast(0),
|
||||
endIndex = (this + checkBound).coerceAtMost(str.length)
|
||||
endIndex = (this + checkBound).coerceAtMost(str.length),
|
||||
)
|
||||
.contains(token)
|
||||
}
|
||||
@ -86,7 +85,6 @@ private fun Int.isAfterToken(str: String, token: String): Boolean {
|
||||
.contains(token)
|
||||
}
|
||||
|
||||
|
||||
// This can also make [TextFieldValue.addTokens] better by checking tokens both ways. Needs more tests
|
||||
fun String.tokenAfter(pos: Int): String {
|
||||
Token.Func.allWithOpeningBracket.forEach {
|
||||
@ -96,23 +94,6 @@ fun String.tokenAfter(pos: Int): String {
|
||||
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 {
|
||||
return str
|
||||
.substring(this, (this + token.length).coerceAtMost(str.length))
|
||||
|
@ -30,13 +30,13 @@ class ExpressionTransformer(private val formatterSymbols: FormatterSymbols) : Vi
|
||||
val formatted = text.text.formatExpression(formatterSymbols)
|
||||
return TransformedText(
|
||||
text = AnnotatedString(formatted),
|
||||
offsetMapping = ExpressionMapping(text.text, formatted)
|
||||
offsetMapping = ExpressionMapping(text.text, formatted),
|
||||
)
|
||||
}
|
||||
|
||||
inner class ExpressionMapping(
|
||||
private val original: String,
|
||||
private val transformed: String
|
||||
private val transformed: String,
|
||||
) : OffsetMapping {
|
||||
// Called when entering text (on each text change)
|
||||
// Basically moves cursor to the right position
|
||||
|
@ -49,15 +49,15 @@ fun FixedExpressionInputTextField(
|
||||
val clipboardManager = FormattedExpressionClipboardManager(
|
||||
formatterSymbols = formatterSymbols,
|
||||
clipboardManager = LocalContext.current.getSystemService(Context.CLIPBOARD_SERVICE)
|
||||
as android.content.ClipboardManager
|
||||
as android.content.ClipboardManager,
|
||||
)
|
||||
|
||||
CompositionLocalProvider(LocalClipboardManager provides clipboardManager) {
|
||||
SelectionContainer(
|
||||
modifier = Modifier
|
||||
modifier = Modifier
|
||||
.horizontalScroll(rememberScrollState()) // Must be first
|
||||
.clickable(onClick = onClick)
|
||||
.then(modifier)
|
||||
.then(modifier),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
@ -71,8 +71,8 @@ fun FixedExpressionInputTextField(
|
||||
|
||||
private class FormattedExpressionClipboardManager(
|
||||
private val formatterSymbols: FormatterSymbols,
|
||||
private val clipboardManager: android.content.ClipboardManager
|
||||
): ClipboardManager {
|
||||
private val clipboardManager: android.content.ClipboardManager,
|
||||
) : ClipboardManager {
|
||||
override fun getText(): AnnotatedString? = null
|
||||
|
||||
override fun setText(annotatedString: AnnotatedString) {
|
||||
@ -81,8 +81,8 @@ private class FormattedExpressionClipboardManager(
|
||||
PLAIN_TEXT_LABEL,
|
||||
annotatedString
|
||||
.text
|
||||
.replace(formatterSymbols.grouping, "")
|
||||
)
|
||||
.replace(formatterSymbols.grouping, ""),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ internal fun String.clearAndFilterNumberBase(): String {
|
||||
}
|
||||
|
||||
fun String.formatExpression(
|
||||
formatterSymbols: FormatterSymbols
|
||||
formatterSymbols: FormatterSymbols,
|
||||
): String {
|
||||
var input = this
|
||||
|
||||
@ -84,7 +84,7 @@ fun String.formatExpression(
|
||||
}
|
||||
|
||||
private fun String.formatNumber(
|
||||
formatterSymbols: FormatterSymbols
|
||||
formatterSymbols: FormatterSymbols,
|
||||
): String {
|
||||
val input = this
|
||||
|
||||
@ -114,7 +114,7 @@ private fun String.leaveLegalTokensOnly(legalTokens: List<String>): String {
|
||||
val subs = streamOfTokens
|
||||
.substring(
|
||||
cursor,
|
||||
(cursor + token.length).coerceAtMost(streamOfTokens.length)
|
||||
(cursor + token.length).coerceAtMost(streamOfTokens.length),
|
||||
)
|
||||
if (subs == token) {
|
||||
// Got a digit, see if there are other digits coming after
|
||||
|
@ -64,7 +64,7 @@ fun ExpressionTextField(
|
||||
ExpressionClipboardManager(
|
||||
formatterSymbols = formatterSymbols,
|
||||
clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE)
|
||||
as android.content.ClipboardManager
|
||||
as android.content.ClipboardManager,
|
||||
)
|
||||
}
|
||||
val expressionTransformer = remember(formatterSymbols) {
|
||||
@ -72,7 +72,7 @@ fun ExpressionTextField(
|
||||
}
|
||||
|
||||
CompositionLocalProvider(
|
||||
LocalClipboardManager provides clipboardManager
|
||||
LocalClipboardManager provides clipboardManager,
|
||||
) {
|
||||
AutoSizeTextField(
|
||||
modifier = modifier,
|
||||
@ -85,7 +85,7 @@ fun ExpressionTextField(
|
||||
textStyle = LocalNumberTypography.current.displayLarge.copy(textColor),
|
||||
visualTransformation = expressionTransformer,
|
||||
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant),
|
||||
minRatio = minRatio
|
||||
minRatio = minRatio,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -110,7 +110,7 @@ fun NumberBaseTextField(
|
||||
readOnly = readOnly,
|
||||
textStyle = LocalNumberTypography.current.displayLarge.copy(textColor),
|
||||
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant),
|
||||
minRatio = minRatio
|
||||
minRatio = minRatio,
|
||||
)
|
||||
}
|
||||
|
||||
@ -132,7 +132,7 @@ fun SimpleTextField(
|
||||
readOnly = readOnly,
|
||||
textStyle = LocalNumberTypography.current.displayLarge.copy(textColor),
|
||||
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant),
|
||||
minRatio = minRatio
|
||||
minRatio = minRatio,
|
||||
)
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ private fun AutoSizeTextField(
|
||||
softWrap = false,
|
||||
style = textStyle,
|
||||
minRatio = minRatio,
|
||||
alignment = alignment
|
||||
alignment = alignment,
|
||||
) {
|
||||
CompositionLocalProvider(
|
||||
LocalTextInputService provides null,
|
||||
@ -204,8 +204,8 @@ private fun AutoSizeTextField(
|
||||
text = placeholder!!,
|
||||
style = style.copy(
|
||||
textAlign = TextAlign.End,
|
||||
color = MaterialTheme.colorScheme.onSurface.copy(0.5f)
|
||||
)
|
||||
color = MaterialTheme.colorScheme.onSurface.copy(0.5f),
|
||||
),
|
||||
)
|
||||
}
|
||||
innerTextField()
|
||||
|
@ -62,8 +62,8 @@ fun OutlinedDecimalTextField(
|
||||
visualTransformation = expressionFormatter,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Decimal,
|
||||
imeAction = imeAction
|
||||
imeAction = imeAction,
|
||||
),
|
||||
colors = colors
|
||||
colors = colors,
|
||||
)
|
||||
}
|
||||
|
@ -30,7 +30,8 @@ fun TextFieldValue.addTokens(tokens: String): TextFieldValue {
|
||||
Token.Operator.plus,
|
||||
Token.Operator.multiply,
|
||||
Token.Operator.divide,
|
||||
Token.Operator.power -> {
|
||||
Token.Operator.power,
|
||||
-> {
|
||||
if (ahead == Token.Operator.plus) return deleteAheadAndAdd(tokens)
|
||||
if (ahead == Token.Operator.minus) return deleteAheadAndAdd(tokens)
|
||||
if (ahead == Token.Operator.multiply) return deleteAheadAndAdd(tokens)
|
||||
@ -50,7 +51,7 @@ fun TextFieldValue.addTokens(tokens: String): TextFieldValue {
|
||||
|
||||
return this.copy(
|
||||
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.minus,
|
||||
Token.Operator.power,
|
||||
Token.Operator.leftBracket
|
||||
Token.Operator.leftBracket,
|
||||
)
|
||||
if (text.tokenAhead(selection.start) in operators2) {
|
||||
return addTokens(Token.Operator.leftBracket)
|
||||
@ -122,7 +123,7 @@ fun TextFieldValue.deleteTokens(): TextFieldValue {
|
||||
|
||||
return this.copy(
|
||||
text = newText,
|
||||
selection = TextRange((newText.length - distanceFromEnd).coerceAtLeast(0))
|
||||
selection = TextRange((newText.length - distanceFromEnd).coerceAtLeast(0)),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ import androidx.annotation.RequiresApi
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.M)
|
||||
internal class FloatingTextActionModeCallback(
|
||||
private val callback: UnittoActionModeCallback
|
||||
private val callback: UnittoActionModeCallback,
|
||||
) : ActionMode.Callback2() {
|
||||
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
|
||||
return callback.onActionItemClicked(mode, item)
|
||||
@ -48,14 +48,14 @@ internal class FloatingTextActionModeCallback(
|
||||
override fun onGetContentRect(
|
||||
mode: ActionMode?,
|
||||
view: View?,
|
||||
outRect: android.graphics.Rect?
|
||||
outRect: android.graphics.Rect?,
|
||||
) {
|
||||
val rect = callback.rect
|
||||
outRect?.set(
|
||||
rect.left.toInt(),
|
||||
rect.top.toInt(),
|
||||
rect.right.toInt(),
|
||||
rect.bottom.toInt()
|
||||
rect.bottom.toInt(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ internal class UnittoActionModeCallback(
|
||||
var onCopyRequested: (() -> Unit)? = null,
|
||||
var onPasteRequested: (() -> Unit)? = null,
|
||||
var onCutRequested: (() -> Unit)? = null,
|
||||
var onSelectAllRequested: (() -> Unit)? = null
|
||||
var onSelectAllRequested: (() -> Unit)? = null,
|
||||
) {
|
||||
fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
||||
requireNotNull(menu)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user