Repo created
This commit is contained in:
parent
75dc487a7a
commit
39c29d175b
6317 changed files with 388324 additions and 2 deletions
13
core/ui/account/build.gradle.kts
Normal file
13
core/ui/account/build.gradle.kts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
plugins {
|
||||
id(ThunderbirdPlugins.Library.android)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "net.thunderbird.core.ui.account"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.core.ui.legacy.designsystem)
|
||||
|
||||
implementation(libs.glide)
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package net.thunderbird.core.ui.account
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.InsetDrawable
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.util.TypedValue
|
||||
import androidx.core.content.ContextCompat
|
||||
import app.k9mail.core.ui.legacy.designsystem.atom.icon.Icons
|
||||
|
||||
private const val PADDING_DP = 8f
|
||||
|
||||
/**
|
||||
* Provides a [Drawable] for the account using the account's color as background color.
|
||||
*/
|
||||
class AccountFallbackImageProvider(private val context: Context) {
|
||||
fun getDrawable(color: Int): Drawable {
|
||||
val drawable = ContextCompat.getDrawable(context, Icons.Outlined.Person)
|
||||
?: error("Error loading drawable")
|
||||
|
||||
val inset = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
PADDING_DP,
|
||||
context.resources.displayMetrics,
|
||||
).toInt()
|
||||
|
||||
return LayerDrawable(
|
||||
arrayOf(
|
||||
ColorDrawable(color),
|
||||
InsetDrawable(drawable, inset),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package net.thunderbird.core.ui.account
|
||||
|
||||
import com.bumptech.glide.load.Key
|
||||
import java.security.MessageDigest
|
||||
|
||||
data class AccountImage(val email: String, val color: Int) : Key {
|
||||
override fun updateDiskCacheKey(messageDigest: MessageDigest) {
|
||||
messageDigest.update(toString().toByteArray(Key.CHARSET))
|
||||
}
|
||||
}
|
||||
3
core/ui/compose/common/README.md
Normal file
3
core/ui/compose/common/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
## Core - UI - Compose - Common
|
||||
|
||||
This module contains common code for the compose UI.
|
||||
13
core/ui/compose/common/build.gradle.kts
Normal file
13
core/ui/compose/common/build.gradle.kts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
plugins {
|
||||
id(ThunderbirdPlugins.Library.androidCompose)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "app.k9mail.core.ui.compose.common"
|
||||
resourcePrefix = "core_ui_common_"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation(projects.core.ui.compose.testing)
|
||||
testImplementation(projects.core.ui.compose.designsystem)
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package app.k9mail.core.ui.compose.common.annotation
|
||||
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
||||
/**
|
||||
* A marker annotation for device previews.
|
||||
*
|
||||
* It's used to provide previews for a set of different devices and form factors.
|
||||
*/
|
||||
@Preview(name = "Small phone", device = "spec:width=360dp,height=640dp,dpi=160")
|
||||
@Preview(name = "Phone", device = "spec:width=411dp,height=891dp,dpi=420")
|
||||
@Preview(name = "Phone landscape", device = "spec:width=891dp,height=411dp,dpi=420")
|
||||
@Preview(name = "Foldable", device = "spec:width=673dp,height=841dp,dpi=420")
|
||||
@Preview(name = "Tablet", device = "spec:width=1280dp,height=800dp,dpi=240")
|
||||
@Preview(name = "Desktop", device = "spec:width=1920dp,height=1080dp,dpi=160")
|
||||
annotation class PreviewDevices
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package app.k9mail.core.ui.compose.common.annotation
|
||||
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
||||
/**
|
||||
* A marker annotation for device previews with background.
|
||||
*
|
||||
* It's used to provide previews for a set of different devices and form factors.
|
||||
*/
|
||||
@Preview(name = "Small phone", device = "spec:width=360dp,height=640dp,dpi=160", showBackground = true)
|
||||
@Preview(name = "Phone", device = "spec:width=411dp,height=891dp,dpi=420", showBackground = true)
|
||||
@Preview(name = "Phone landscape", device = "spec:width=891dp,height=411dp,dpi=420", showBackground = true)
|
||||
@Preview(name = "Foldable", device = "spec:width=673dp,height=841dp,dpi=420", showBackground = true)
|
||||
@Preview(name = "Tablet", device = "spec:width=1280dp,height=800dp,dpi=240", showBackground = true)
|
||||
@Preview(name = "Desktop", device = "spec:width=1920dp,height=1080dp,dpi=160", showBackground = true)
|
||||
annotation class PreviewDevicesWithBackground
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package app.k9mail.core.ui.compose.common.baseline
|
||||
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.FirstBaseline
|
||||
import androidx.compose.ui.layout.LastBaseline
|
||||
import androidx.compose.ui.layout.layout
|
||||
import androidx.compose.ui.unit.Dp
|
||||
|
||||
/**
|
||||
* Adds a baseline to a Composable that typically doesn't have one.
|
||||
*
|
||||
* This can be used to align e.g. an icon to the baseline of some text next to it. See e.g. [RowScope.alignByBaseline].
|
||||
*
|
||||
* @param baseline The number of device-independent pixels (dp) the baseline is from the top of the Composable.
|
||||
*/
|
||||
fun Modifier.withBaseline(baseline: Dp) = layout { measurable, constraints ->
|
||||
val placeable = measurable.measure(constraints)
|
||||
val baselineInPx = baseline.roundToPx()
|
||||
|
||||
layout(
|
||||
width = placeable.width,
|
||||
height = placeable.height,
|
||||
alignmentLines = mapOf(
|
||||
FirstBaseline to baselineInPx,
|
||||
LastBaseline to baselineInPx,
|
||||
),
|
||||
) {
|
||||
placeable.placeRelative(x = 0, y = 0)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package app.k9mail.core.ui.compose.common.image
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.Dp
|
||||
|
||||
@Immutable
|
||||
data class ImageWithBaseline(
|
||||
val image: ImageVector,
|
||||
val baseline: Dp,
|
||||
)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package app.k9mail.core.ui.compose.common.image
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.Dp
|
||||
|
||||
/**
|
||||
* An image with a coordinate to draw a (smaller) overlay icon on top of it.
|
||||
*
|
||||
* Example: An icon representing an Android permission with an overlay icon to indicate whether the permission has been
|
||||
* granted.
|
||||
*/
|
||||
@Immutable
|
||||
data class ImageWithOverlayCoordinate(
|
||||
val image: ImageVector,
|
||||
val overlayOffsetX: Dp,
|
||||
val overlayOffsetY: Dp,
|
||||
)
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package app.k9mail.core.ui.compose.common.koin
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import org.koin.compose.KoinContext
|
||||
import org.koin.core.Koin
|
||||
import org.koin.dsl.ModuleDeclaration
|
||||
import org.koin.dsl.module
|
||||
|
||||
/**
|
||||
* Helper to make Compose previews work when some dependencies are injected via Koin.
|
||||
*/
|
||||
fun koinPreview(moduleDeclaration: ModuleDeclaration): KoinPreview {
|
||||
val koin = Koin().apply {
|
||||
loadModules(listOf(module(moduleDeclaration = moduleDeclaration)))
|
||||
}
|
||||
|
||||
return KoinPreview(koin)
|
||||
}
|
||||
|
||||
class KoinPreview internal constructor(private val koin: Koin) {
|
||||
@Composable
|
||||
infix fun WithContent(content: @Composable () -> Unit) {
|
||||
KoinContext(context = koin) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package app.k9mail.core.ui.compose.common.mvi
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* An abstract base ViewModel that implements [UnidirectionalViewModel] and provides basic
|
||||
* functionality for managing state and effects.
|
||||
*
|
||||
* @param STATE The type that represents the state of the ViewModel. For example, the UI state of a screen can be
|
||||
* represented as a state.
|
||||
* @param EVENT The type that represents user actions that can occur and should be handled by the ViewModel. For
|
||||
* example, a button click can be represented as an event.
|
||||
* @param EFFECT The type that represents side-effects that can occur in response to the state changes. For example,
|
||||
* a navigation event can be represented as an effect.
|
||||
*
|
||||
* @param initialState The initial [STATE] of the ViewModel.
|
||||
*/
|
||||
abstract class BaseViewModel<STATE, EVENT, EFFECT>(
|
||||
initialState: STATE,
|
||||
) : ViewModel(),
|
||||
UnidirectionalViewModel<STATE, EVENT, EFFECT> {
|
||||
|
||||
private val _state = MutableStateFlow(initialState)
|
||||
override val state: StateFlow<STATE> = _state.asStateFlow()
|
||||
|
||||
private val _effect = MutableSharedFlow<EFFECT>()
|
||||
override val effect: SharedFlow<EFFECT> = _effect.asSharedFlow()
|
||||
|
||||
private val handledOneTimeEvents = mutableSetOf<EVENT>()
|
||||
|
||||
/**
|
||||
* Updates the [STATE] of the ViewModel.
|
||||
*
|
||||
* @param update A function that takes the current [STATE] and produces a new [STATE].
|
||||
*/
|
||||
protected fun updateState(update: (STATE) -> STATE) {
|
||||
_state.update(update)
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a side effect.
|
||||
*
|
||||
* @param effect The [EFFECT] to emit.
|
||||
*/
|
||||
protected fun emitEffect(effect: EFFECT) {
|
||||
viewModelScope.launch {
|
||||
_effect.emit(effect)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that one-time events are only handled once.
|
||||
*
|
||||
* When you can't ensure that an event is only sent once, but you want the event to only be handled once, call this
|
||||
* method. It will ensure [block] is only executed the first time this function is called. Subsequent calls with an
|
||||
* [event] argument equal to that of a previous invocation will not execute [block].
|
||||
*
|
||||
* Multiple one-time events are supported.
|
||||
*/
|
||||
protected fun handleOneTimeEvent(event: EVENT, block: () -> Unit) {
|
||||
if (event !in handledOneTimeEvents) {
|
||||
handledOneTimeEvents.add(event)
|
||||
block()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
package app.k9mail.core.ui.compose.common.mvi
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
/**
|
||||
* Interface for a unidirectional view model with side-effects ([EFFECT]). It has a [STATE] and can handle [EVENT]'s.
|
||||
*
|
||||
* @param STATE The type that represents the state of the ViewModel. For example, the UI state of a screen can be
|
||||
* represented as a state.
|
||||
* @param EVENT The type that represents user actions that can occur and should be handled by the ViewModel. For
|
||||
* example, a button click can be represented as an event.
|
||||
* @param EFFECT The type that represents side-effects that can occur in response to the state changes. For example,
|
||||
* a navigation event can be represented as an effect.
|
||||
*/
|
||||
interface UnidirectionalViewModel<STATE, EVENT, EFFECT> {
|
||||
/**
|
||||
* The current [STATE] of the view model.
|
||||
*/
|
||||
val state: StateFlow<STATE>
|
||||
|
||||
/**
|
||||
* The side-effects ([EFFECT]) produced by the view model.
|
||||
*/
|
||||
val effect: SharedFlow<EFFECT>
|
||||
|
||||
/**
|
||||
* Handles an [EVENT] and updates the [STATE] of the view model.
|
||||
*
|
||||
* @param event The [EVENT] to handle.
|
||||
*/
|
||||
fun event(event: EVENT)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data class representing a state and a dispatch function, used for destructuring in [observe].
|
||||
*/
|
||||
data class StateDispatch<STATE, EVENT>(
|
||||
val state: State<STATE>,
|
||||
val dispatch: (EVENT) -> Unit,
|
||||
)
|
||||
|
||||
/**
|
||||
* Composable function that observes a UnidirectionalViewModel and handles its side effects.
|
||||
*
|
||||
* Example usage:
|
||||
* ```
|
||||
* @Composable
|
||||
* fun MyScreen(
|
||||
* onNavigateNext: () -> Unit,
|
||||
* onNavigateBack: () -> Unit,
|
||||
* viewModel: MyUnidirectionalViewModel<MyState, MyEvent, MyEffect>,
|
||||
* ) {
|
||||
* val (state, dispatch) = viewModel.observe { effect ->
|
||||
* when (effect) {
|
||||
* MyEffect.OnBackPressed -> onNavigateBack()
|
||||
* MyEffect.OnNextPressed -> onNavigateNext()
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* MyContent(
|
||||
* onNextClick = {
|
||||
* dispatch(MyEvent.OnNext)
|
||||
* },
|
||||
* onBackClick = {
|
||||
* dispatch(MyEvent.OnBack)
|
||||
* },
|
||||
* state = state.value,
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param STATE The type that represents the state of the ViewModel.
|
||||
* @param EVENT The type that represents user actions that can occur and should be handled by the ViewModel.
|
||||
* @param EFFECT The type that represents side-effects that can occur in response to the state changes.
|
||||
*
|
||||
* @param handleEffect A function to handle side effects ([EFFECT]).
|
||||
*
|
||||
* @return A [StateDispatch] containing the state and a dispatch function.
|
||||
*/
|
||||
@Composable
|
||||
inline fun <reified STATE, EVENT, EFFECT> UnidirectionalViewModel<STATE, EVENT, EFFECT>.observe(
|
||||
crossinline handleEffect: (EFFECT) -> Unit,
|
||||
): StateDispatch<STATE, EVENT> {
|
||||
val collectedState = state.collectAsStateWithLifecycle()
|
||||
|
||||
val dispatch: (EVENT) -> Unit = { event(it) }
|
||||
|
||||
LaunchedEffect(key1 = effect) {
|
||||
effect.collect {
|
||||
handleEffect(it)
|
||||
}
|
||||
}
|
||||
|
||||
return StateDispatch(
|
||||
state = collectedState,
|
||||
dispatch = dispatch,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Composable function that observes a UnidirectionalViewModel without handling side effects.
|
||||
*
|
||||
* Example usage:
|
||||
* ```
|
||||
* @Composable
|
||||
* fun MyScreen(
|
||||
* viewModel: MyUnidirectionalViewModel<MyState, MyEvent, MyEffect>,
|
||||
* onNavigateNext: () -> Unit,
|
||||
* onNavigateBack: () -> Unit,
|
||||
* ) {
|
||||
* val (state, dispatch) = viewModel.observeWithoutEffect()
|
||||
*
|
||||
* MyContent(
|
||||
* onNextClick = {
|
||||
* dispatch(MyEvent.OnNext)
|
||||
* },
|
||||
* onBackClick = {
|
||||
* dispatch(MyEvent.OnBack)
|
||||
* },
|
||||
* state = state.value,
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param STATE The type that represents the state of the ViewModel.
|
||||
* @param EVENT The type that represents user actions that can occur and should be handled by the ViewModel.
|
||||
*
|
||||
* @return A [StateDispatch] containing the state and a dispatch function.
|
||||
*/
|
||||
@Suppress("MaxLineLength")
|
||||
@Composable
|
||||
inline fun <reified STATE, EVENT, EFFECT> UnidirectionalViewModel<STATE, EVENT, EFFECT>.observeWithoutEffect(
|
||||
// no effect handler
|
||||
): StateDispatch<STATE, EVENT> {
|
||||
val collectedState = state.collectAsStateWithLifecycle()
|
||||
val dispatch: (EVENT) -> Unit = { event(it) }
|
||||
|
||||
return StateDispatch(
|
||||
state = collectedState,
|
||||
dispatch = dispatch,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package app.k9mail.core.ui.compose.common.padding
|
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.k9mail.core.ui.compose.common.window.WindowSizeClass
|
||||
import app.k9mail.core.ui.compose.common.window.getWindowSizeInfo
|
||||
|
||||
@Composable
|
||||
fun calculateResponsiveWidthPadding(): PaddingValues {
|
||||
val windowSizeInfo = getWindowSizeInfo()
|
||||
val horizontalPadding = when (windowSizeInfo.screenWidthSizeClass) {
|
||||
WindowSizeClass.Compact -> 0.dp
|
||||
|
||||
WindowSizeClass.Medium -> (windowSizeInfo.screenWidth - WindowSizeClass.COMPACT_MAX_WIDTH.dp) / 2
|
||||
|
||||
WindowSizeClass.Expanded -> (windowSizeInfo.screenWidth - WindowSizeClass.MEDIUM_MAX_WIDTH.dp) / 2
|
||||
}
|
||||
return PaddingValues(horizontal = horizontalPadding)
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package app.k9mail.core.ui.compose.common.resources
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
|
||||
private const val PLACE_HOLDER = "{placeHolder}"
|
||||
|
||||
/**
|
||||
* Loads a string resource with a single string parameter that will be replaced with the given [AnnotatedString].
|
||||
*/
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
fun annotatedStringResource(@StringRes id: Int, argument: AnnotatedString): AnnotatedString {
|
||||
val stringWithPlaceHolder = stringResource(id, PLACE_HOLDER)
|
||||
return buildAnnotatedString {
|
||||
// In Android Studio previews loading string resources with formatting is not working
|
||||
if (LocalInspectionMode.current) {
|
||||
append(stringWithPlaceHolder)
|
||||
return@buildAnnotatedString
|
||||
}
|
||||
|
||||
val placeHolderStartIndex = stringWithPlaceHolder.indexOf(PLACE_HOLDER)
|
||||
require(placeHolderStartIndex != -1)
|
||||
|
||||
append(text = stringWithPlaceHolder, start = 0, end = placeHolderStartIndex)
|
||||
append(argument)
|
||||
append(
|
||||
text = stringWithPlaceHolder,
|
||||
start = placeHolderStartIndex + PLACE_HOLDER.length,
|
||||
end = stringWithPlaceHolder.length,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package app.k9mail.core.ui.compose.common.text
|
||||
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
|
||||
/**
|
||||
* Converts a [String] into an [AnnotatedString] with all of the text being bold.
|
||||
*/
|
||||
fun String.bold(): AnnotatedString {
|
||||
return buildAnnotatedString {
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append(this@bold)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package app.k9mail.core.ui.compose.common.visibility
|
||||
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.semantics.clearAndSetSemantics
|
||||
|
||||
/**
|
||||
* Sets a composable to be fully transparent when it should be hidden (but still present for layout purposes).
|
||||
*/
|
||||
fun Modifier.hide(hide: Boolean): Modifier {
|
||||
return if (hide) {
|
||||
alpha(0f).clearAndSetSemantics {}
|
||||
} else {
|
||||
alpha(1f)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package app.k9mail.core.ui.compose.common.window
|
||||
|
||||
/**
|
||||
* WindowSizeClass as defined by supporting different screen sizes.
|
||||
*
|
||||
* See: https://developer.android.com/guide/topics/large-screens/support-different-screen-sizes#window_size_classes
|
||||
*/
|
||||
enum class WindowSizeClass {
|
||||
Compact,
|
||||
Medium,
|
||||
Expanded,
|
||||
;
|
||||
|
||||
companion object {
|
||||
const val COMPACT_MAX_WIDTH = 600
|
||||
const val COMPACT_MAX_HEIGHT = 480
|
||||
|
||||
const val MEDIUM_MAX_WIDTH = 840
|
||||
|
||||
const val MEDIUM_MAX_HEIGHT = 900
|
||||
|
||||
fun fromWidth(width: Int): WindowSizeClass {
|
||||
return when {
|
||||
width < COMPACT_MAX_WIDTH -> Compact
|
||||
width < MEDIUM_MAX_WIDTH -> Medium
|
||||
else -> Expanded
|
||||
}
|
||||
}
|
||||
|
||||
fun fromHeight(height: Int): WindowSizeClass {
|
||||
return when {
|
||||
height < COMPACT_MAX_HEIGHT -> Compact
|
||||
height < MEDIUM_MAX_HEIGHT -> Medium
|
||||
else -> Expanded
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package app.k9mail.core.ui.compose.common.window
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
/**
|
||||
* Returns the current window size info based on current Configuration.
|
||||
*/
|
||||
@Composable
|
||||
fun getWindowSizeInfo(): WindowSizeInfo {
|
||||
val configuration = LocalConfiguration.current
|
||||
|
||||
return WindowSizeInfo(
|
||||
screenWidthSizeClass = WindowSizeClass.fromWidth(configuration.screenWidthDp),
|
||||
screenHeightSizeClass = WindowSizeClass.fromHeight(configuration.screenHeightDp),
|
||||
screenWidth = configuration.screenWidthDp.dp,
|
||||
screenHeight = configuration.screenHeightDp.dp,
|
||||
)
|
||||
}
|
||||
|
||||
@Immutable
|
||||
data class WindowSizeInfo(
|
||||
val screenWidthSizeClass: WindowSizeClass,
|
||||
val screenHeightSizeClass: WindowSizeClass,
|
||||
val screenWidth: Dp,
|
||||
val screenHeight: Dp,
|
||||
)
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package net.thunderbird.core.ui.compose.common.date
|
||||
|
||||
import androidx.compose.runtime.staticCompositionLocalOf
|
||||
import kotlinx.datetime.format.DayOfWeekNames
|
||||
import kotlinx.datetime.format.MonthNames
|
||||
|
||||
/**
|
||||
* Configuration for date and time formatting.
|
||||
*
|
||||
* @property monthNames The names of the months.
|
||||
* @property dayOfWeekNames The names of the days of the week.
|
||||
*/
|
||||
data class DateTimeConfiguration(
|
||||
val monthNames: MonthNames,
|
||||
val dayOfWeekNames: DayOfWeekNames,
|
||||
)
|
||||
|
||||
/**
|
||||
* CompositionLocal that provides the default [DateTimeConfiguration] for date and time formatting.
|
||||
* This configuration uses abbreviated English month and day of the week names by default.
|
||||
* It can be overridden at a lower level in the composition tree to customize date and time formatting.
|
||||
*/
|
||||
val LocalDateTimeConfiguration = staticCompositionLocalOf {
|
||||
DateTimeConfiguration(
|
||||
monthNames = MonthNames.ENGLISH_ABBREVIATED,
|
||||
dayOfWeekNames = DayOfWeekNames.ENGLISH_ABBREVIATED,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package net.thunderbird.core.ui.compose.common.modifier
|
||||
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.semantics.testTagsAsResourceId
|
||||
|
||||
/**
|
||||
* Adds a test tag to the element with testTagsAsResourceId set to true.
|
||||
* This allows the element to be found by its test tag during UI testing.
|
||||
*
|
||||
* @param tag The test tag to be assigned to the element.
|
||||
* @return A [Modifier] with the test tag applied.
|
||||
*/
|
||||
fun Modifier.testTagAsResourceId(tag: String): Modifier = this
|
||||
.semantics { testTagsAsResourceId = true }
|
||||
.testTag(tag)
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package app.k9mail.core.ui.compose.common.koin
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyLarge
|
||||
import app.k9mail.core.ui.compose.testing.ComposeTest
|
||||
import app.k9mail.core.ui.compose.testing.onNodeWithText
|
||||
import app.k9mail.core.ui.compose.testing.setContentWithTheme
|
||||
import kotlin.test.Test
|
||||
import org.koin.compose.koinInject
|
||||
|
||||
class KoinPreviewTest : ComposeTest() {
|
||||
@Test
|
||||
fun `koinPreview should make dependencies available in WithContent block`() = runComposeTest {
|
||||
val injectString = "Test"
|
||||
|
||||
setContentWithTheme {
|
||||
koinPreview {
|
||||
factory { injectString }
|
||||
} WithContent {
|
||||
TestComposable()
|
||||
}
|
||||
}
|
||||
|
||||
onNodeWithText(injectString).assertExists()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TestComposable(
|
||||
injected: String = koinInject(),
|
||||
) {
|
||||
TextBodyLarge(text = injected)
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
package app.k9mail.core.ui.compose.common.mvi
|
||||
|
||||
import app.cash.turbine.test
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isFalse
|
||||
import assertk.assertions.isTrue
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import net.thunderbird.core.testing.coroutines.MainDispatcherRule
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
class BaseViewModelTest {
|
||||
|
||||
@get:Rule
|
||||
val mainDispatcherRule = MainDispatcherRule()
|
||||
|
||||
@Test
|
||||
fun `should emit initial state`() = runTest {
|
||||
val viewModel = TestBaseViewModel()
|
||||
assertThat(viewModel.state.value).isEqualTo("Initial state")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should update state`() = runTest {
|
||||
val viewModel = TestBaseViewModel()
|
||||
|
||||
viewModel.event("Test event")
|
||||
|
||||
assertThat(viewModel.state.value).isEqualTo("Test event")
|
||||
|
||||
viewModel.event("Another test event")
|
||||
|
||||
assertThat(viewModel.state.value).isEqualTo("Another test event")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should emit effects`() = runTest {
|
||||
val viewModel = TestBaseViewModel()
|
||||
|
||||
viewModel.effect.test {
|
||||
viewModel.event("Test effect")
|
||||
|
||||
assertThat(awaitItem()).isEqualTo("Test effect")
|
||||
|
||||
viewModel.event("Another test effect")
|
||||
|
||||
assertThat(awaitItem()).isEqualTo("Another test effect")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `handleOneTimeEvent() should execute block`() = runTest {
|
||||
val viewModel = TestBaseViewModel()
|
||||
var eventHandled = false
|
||||
|
||||
viewModel.callHandleOneTimeEvent(event = "event") {
|
||||
eventHandled = true
|
||||
}
|
||||
|
||||
assertThat(eventHandled).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `handleOneTimeEvent() should execute block only once`() = runTest {
|
||||
val viewModel = TestBaseViewModel()
|
||||
var eventHandledCount = 0
|
||||
|
||||
repeat(2) {
|
||||
viewModel.callHandleOneTimeEvent(event = "event") {
|
||||
eventHandledCount++
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(eventHandledCount).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `handleOneTimeEvent() should support multiple one-time events`() = runTest {
|
||||
val viewModel = TestBaseViewModel()
|
||||
var eventOneHandled = false
|
||||
var eventTwoHandled = false
|
||||
|
||||
viewModel.callHandleOneTimeEvent(event = "eventOne") {
|
||||
eventOneHandled = true
|
||||
}
|
||||
|
||||
assertThat(eventOneHandled).isTrue()
|
||||
assertThat(eventTwoHandled).isFalse()
|
||||
|
||||
viewModel.callHandleOneTimeEvent(event = "eventTwo") {
|
||||
eventTwoHandled = true
|
||||
}
|
||||
|
||||
assertThat(eventOneHandled).isTrue()
|
||||
assertThat(eventTwoHandled).isTrue()
|
||||
}
|
||||
|
||||
private class TestBaseViewModel : BaseViewModel<String, String, String>("Initial state") {
|
||||
override fun event(event: String) {
|
||||
updateState { event }
|
||||
emitEffect(event)
|
||||
}
|
||||
|
||||
fun callHandleOneTimeEvent(event: String, block: () -> Unit) {
|
||||
handleOneTimeEvent(event, block)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
package app.k9mail.core.ui.compose.common.mvi
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import app.k9mail.core.ui.compose.testing.ComposeTest
|
||||
import app.k9mail.core.ui.compose.testing.setContent
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import net.thunderbird.core.testing.coroutines.MainDispatcherRule
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
class UnidirectionalViewModelKtTest : ComposeTest() {
|
||||
|
||||
@get:Rule
|
||||
val mainDispatcherRule = MainDispatcherRule()
|
||||
|
||||
@Test
|
||||
fun `observe should emit state changes, allow event dispatch and expose effects`() = runTest {
|
||||
val viewModel = TestViewModel()
|
||||
val effects = mutableListOf<TestEffect>()
|
||||
lateinit var stateDispatch: StateDispatch<TestState, TestEvent>
|
||||
|
||||
setContent {
|
||||
stateDispatch = viewModel.observe { effect ->
|
||||
effects.add(effect)
|
||||
}
|
||||
}
|
||||
|
||||
val (state, dispatch) = stateDispatch
|
||||
|
||||
// Initial state
|
||||
assertThat(state.value.data).isEqualTo("TestState: Initial")
|
||||
|
||||
// Dispatch an event
|
||||
dispatch(TestEvent("Event 1"))
|
||||
|
||||
assertThat(state.value.data).isEqualTo("TestState: Event 1")
|
||||
assertThat(effects.last().result).isEqualTo("TestEffect: Event 1")
|
||||
|
||||
// Dispatch another event
|
||||
dispatch(TestEvent("Event 2"))
|
||||
|
||||
assertThat(state.value.data).isEqualTo("TestState: Event 2")
|
||||
assertThat(effects.last().result).isEqualTo("TestEffect: Event 2")
|
||||
}
|
||||
|
||||
private data class TestState(val data: String)
|
||||
private data class TestEvent(val action: String)
|
||||
private data class TestEffect(val result: String)
|
||||
|
||||
private class TestViewModel(
|
||||
initialState: TestState = TestState("TestState: Initial"),
|
||||
) : ViewModel(), UnidirectionalViewModel<TestState, TestEvent, TestEffect> {
|
||||
|
||||
private val _state = MutableStateFlow(initialState)
|
||||
override val state: StateFlow<TestState> = _state.asStateFlow()
|
||||
|
||||
private val _effect = MutableSharedFlow<TestEffect>()
|
||||
override val effect: SharedFlow<TestEffect> = _effect.asSharedFlow()
|
||||
|
||||
override fun event(event: TestEvent) {
|
||||
_state.update { it.copy(data = "TestState: ${event.action}") }
|
||||
viewModelScope.launch {
|
||||
_effect.emit(TestEffect(result = "TestEffect: ${event.action}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package app.k9mail.core.ui.compose.common.resources
|
||||
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import app.k9mail.core.ui.compose.common.test.R
|
||||
import app.k9mail.core.ui.compose.common.text.bold
|
||||
import app.k9mail.core.ui.compose.testing.ComposeTest
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import org.junit.Test
|
||||
|
||||
class StringResourcesTest : ComposeTest() {
|
||||
@Test
|
||||
fun `annotatedStringResource() with bold text`() = runComposeTest {
|
||||
val argument = "text".bold()
|
||||
|
||||
setContent {
|
||||
val result = annotatedStringResource(id = R.string.StringResourcesTest, argument)
|
||||
|
||||
assertThat(result).isEqualTo(
|
||||
buildAnnotatedString {
|
||||
append("prefix ")
|
||||
append(argument)
|
||||
append(" suffix")
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package app.k9mail.core.ui.compose.common.text
|
||||
|
||||
import androidx.compose.ui.text.AnnotatedString.Range
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.containsExactly
|
||||
import assertk.assertions.isEqualTo
|
||||
import kotlin.test.Test
|
||||
|
||||
class AnnotatedStringsTest {
|
||||
@Test
|
||||
fun bold() {
|
||||
val input = "text"
|
||||
|
||||
val result = input.bold()
|
||||
|
||||
assertThat(result.toString()).isEqualTo(input)
|
||||
assertThat(result.spanStyles).containsExactly(
|
||||
Range(
|
||||
item = SpanStyle(fontWeight = FontWeight.Bold),
|
||||
start = 0,
|
||||
end = input.length,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package app.k9mail.core.ui.compose.common.window
|
||||
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import org.junit.Test
|
||||
|
||||
class WindowSizeClassTest {
|
||||
|
||||
@Test
|
||||
fun `should return compact when width is less than 600`() {
|
||||
val width = 599
|
||||
|
||||
val windowSizeClass = WindowSizeClass.fromWidth(width)
|
||||
|
||||
assertThat(windowSizeClass).isEqualTo(WindowSizeClass.Compact)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return medium when width is 600`() {
|
||||
val width = 600
|
||||
|
||||
val windowSizeClass = WindowSizeClass.fromWidth(width)
|
||||
|
||||
assertThat(windowSizeClass).isEqualTo(WindowSizeClass.Medium)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return medium when width is less than 840`() {
|
||||
val width = 839
|
||||
|
||||
val windowSizeClass = WindowSizeClass.fromWidth(width)
|
||||
|
||||
assertThat(windowSizeClass).isEqualTo(WindowSizeClass.Medium)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return expanded when width is 840`() {
|
||||
val width = 840
|
||||
|
||||
val windowSizeClass = WindowSizeClass.fromWidth(width)
|
||||
|
||||
assertThat(windowSizeClass).isEqualTo(WindowSizeClass.Expanded)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return compact when height is less than 480`() {
|
||||
val height = 479
|
||||
|
||||
val windowSizeClass = WindowSizeClass.fromHeight(height)
|
||||
|
||||
assertThat(windowSizeClass).isEqualTo(WindowSizeClass.Compact)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return medium when height is 480`() {
|
||||
val height = 480
|
||||
|
||||
val windowSizeClass = WindowSizeClass.fromHeight(height)
|
||||
|
||||
assertThat(windowSizeClass).isEqualTo(WindowSizeClass.Medium)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return medium when height is less than 900`() {
|
||||
val height = 899
|
||||
|
||||
val windowSizeClass = WindowSizeClass.fromHeight(height)
|
||||
|
||||
assertThat(windowSizeClass).isEqualTo(WindowSizeClass.Medium)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return expanded when height is 900`() {
|
||||
val height = 900
|
||||
|
||||
val windowSizeClass = WindowSizeClass.fromHeight(height)
|
||||
|
||||
assertThat(windowSizeClass).isEqualTo(WindowSizeClass.Expanded)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<resources>
|
||||
<string name="StringResourcesTest">prefix %s suffix</string>
|
||||
</resources>
|
||||
39
core/ui/compose/designsystem/README.md
Normal file
39
core/ui/compose/designsystem/README.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
## Core - UI - Compose - Design system
|
||||
|
||||
Uses [`:core:ui:compose:theme`](../theme/README.md)
|
||||
|
||||
## Background
|
||||
|
||||
[Jetpack Compose](https://developer.android.com/jetpack/compose) is a declarative UI toolkit for Android that provides a modern and efficient way to build UIs for Android apps. In this context, design systems and atomic design can help designers and developers create more scalable, maintainable, and reusable UIs.
|
||||
|
||||
### Design system
|
||||
|
||||
A design system is a collection of guidelines, principles, and tools that help teams create consistent and cohesive visual designs and user experiences.
|
||||
It typically includes a set of reusable components, such as icons, typography, color palettes, and layouts, that can be combined and customized to create new designs.
|
||||
|
||||
The design system also provides documentation and resources for designers and developers to ensure that the designs are implemented consistently and efficiently across all platforms and devices.
|
||||
The goal of a design system is to streamline the design process, improve design quality, and maintain brand consistency.
|
||||
|
||||
An example is Google's [Material Design](https://m3.material.io/) that is used to develop cohesive apps.
|
||||
|
||||
### Atomic Design
|
||||
|
||||

|
||||
|
||||
Atomic design is a methodology for creating user interfaces (UI) in a design system by breaking them down into smaller, reusable components.
|
||||
These components are classified into five categories based on their level of abstraction: **atoms**, **molecules**, **organisms**, **templates**, and **pages**.
|
||||
|
||||
- **Atoms** are the smallest building blocks, such as buttons, labels, and input fields and could be combined to create more complex components.
|
||||
- **Molecules** are groups of atoms that work together, like search bars, forms or menus
|
||||
- **Organisms** are more complex components that combine molecules and atoms, such as headers or cards.
|
||||
- **Templates** are pages with placeholders for components
|
||||
- **Pages** are the final UI
|
||||
|
||||
By using atomic design, designers and developers can create more consistent and reusable UIs.
|
||||
This can save time and improve the overall quality, as well as facilitate collaboration between team members.
|
||||
|
||||
## Acknowledgement
|
||||
|
||||
- [Atomic Design Methodology | Atomic Design by Brad Frost](https://atomicdesign.bradfrost.com/chapter-2/)
|
||||
- [Atomic Design: Getting Started | Blog | We Are Mobile First](https://www.wearemobilefirst.com/blog/atomic-design)
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 17 KiB |
33
core/ui/compose/designsystem/build.gradle.kts
Normal file
33
core/ui/compose/designsystem/build.gradle.kts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
plugins {
|
||||
id(ThunderbirdPlugins.Library.androidCompose)
|
||||
alias(libs.plugins.kotlin.parcelize)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "app.k9mail.core.ui.compose.designsystem"
|
||||
resourcePrefix = "designsystem_"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(projects.core.ui.compose.theme2.common)
|
||||
|
||||
debugApi(projects.core.ui.compose.theme2.k9mail)
|
||||
debugApi(projects.core.ui.compose.theme2.thunderbird)
|
||||
|
||||
implementation(libs.androidx.autofill)
|
||||
implementation(libs.androidx.compose.material3)
|
||||
implementation(libs.androidx.compose.material3.adaptive)
|
||||
implementation(libs.androidx.compose.material3.adaptive.layout)
|
||||
implementation(libs.androidx.compose.material3.adaptive.navigation)
|
||||
implementation(libs.androidx.compose.material.icons.extended)
|
||||
|
||||
// Landscapist imports a lot of dependencies that we don't need. We exclude them here.
|
||||
implementation(libs.lanscapist.coil) {
|
||||
exclude(group = "io.coil-kt", module = "coil-gif")
|
||||
exclude(group = "io.coil-kt", module = "coil-video")
|
||||
exclude(group = "io.coil-kt.coil3", module = "coil-network-ktor3")
|
||||
exclude(group = "io.ktor")
|
||||
}
|
||||
|
||||
testImplementation(projects.core.ui.compose.testing)
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package app.k9mail.core.ui.compose.designsystem
|
||||
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
import android.content.res.Configuration.UI_MODE_TYPE_NORMAL
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
||||
@Preview(name = "Light", device = "spec:width=673dp,height=841dp,orientation=landscape")
|
||||
@Preview(
|
||||
name = "Dark",
|
||||
uiMode = UI_MODE_NIGHT_YES or UI_MODE_TYPE_NORMAL,
|
||||
device = "spec:width=673dp,height=841dp,orientation=landscape",
|
||||
)
|
||||
annotation class PreviewLightDarkLandscape
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
package app.k9mail.core.ui.compose.designsystem
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.movableContentOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
/**
|
||||
* A Composable function that displays a preview of the content in both Thunderbird and K-9 Mail themes.
|
||||
*
|
||||
* It uses the current system theme (light or dark) for both previews.
|
||||
*
|
||||
* @param modifier The modifier to be applied to the layout.
|
||||
* @param useRow Whether to display the previews in a row or column. Defaults to `false` (column).
|
||||
* @param useScrim Whether to display a scrim behind the content. Defaults to `false`.
|
||||
* @param scrimAlpha The alpha value for the scrim. Defaults to `0.8f`.
|
||||
* @param scrimPadding The padding for the scrim. Defaults to `MainTheme.spacings.triple`.
|
||||
* @param arrangement The arrangement for the previews. Defaults to `Arrangement.spacedBy(MainTheme.spacings.triple)`.
|
||||
* @param content The content to be displayed in the previews.
|
||||
*
|
||||
* @see app.k9mail.core.ui.compose.theme2.default.defaultThemeSpacings for MainTheme.spacings
|
||||
*/
|
||||
@Composable
|
||||
fun PreviewWithThemesLightDark(
|
||||
modifier: Modifier = Modifier,
|
||||
useRow: Boolean = false,
|
||||
useScrim: Boolean = false,
|
||||
scrimAlpha: Float = 0.8f,
|
||||
scrimPadding: PaddingValues = PaddingValues(24.dp),
|
||||
arrangement: Arrangement.HorizontalOrVertical = Arrangement.spacedBy(24.dp),
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val movableContent = remember {
|
||||
movableContentOf {
|
||||
PreviewWithThemeLightDark(
|
||||
themeType = PreviewThemeType.THUNDERBIRD,
|
||||
useScrim = useScrim,
|
||||
scrimAlpha = scrimAlpha,
|
||||
scrimPadding = scrimPadding,
|
||||
content = content,
|
||||
)
|
||||
PreviewWithThemeLightDark(
|
||||
themeType = PreviewThemeType.K9MAIL,
|
||||
useScrim = useScrim,
|
||||
scrimAlpha = scrimAlpha,
|
||||
scrimPadding = scrimPadding,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (useRow) {
|
||||
Row(
|
||||
horizontalArrangement = arrangement,
|
||||
modifier = modifier,
|
||||
) {
|
||||
movableContent()
|
||||
}
|
||||
} else {
|
||||
Column(
|
||||
verticalArrangement = arrangement,
|
||||
modifier = modifier,
|
||||
) {
|
||||
movableContent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("ModifierMissing")
|
||||
@Composable
|
||||
fun PreviewWithThemeLightDark(
|
||||
themeType: PreviewThemeType = PreviewThemeType.THUNDERBIRD,
|
||||
useScrim: Boolean = false,
|
||||
scrimAlpha: Float = 0f,
|
||||
scrimPadding: PaddingValues = PaddingValues(0.dp),
|
||||
content: @Composable (() -> Unit),
|
||||
) {
|
||||
val movableContent = remember { movableContentOf { content() } }
|
||||
PreviewWithTheme(
|
||||
themeType = themeType,
|
||||
isDarkTheme = isSystemInDarkTheme(),
|
||||
) {
|
||||
PreviewSurface {
|
||||
if (useScrim) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(MainTheme.colors.scrim.copy(alpha = scrimAlpha))
|
||||
.padding(scrimPadding),
|
||||
) {
|
||||
movableContent()
|
||||
}
|
||||
} else {
|
||||
movableContent()
|
||||
}
|
||||
PreviewHeader(themeName = themeType.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
package app.k9mail.core.ui.compose.designsystem
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.sp
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import app.k9mail.core.ui.compose.theme2.k9mail.K9MailTheme2
|
||||
import app.k9mail.core.ui.compose.theme2.thunderbird.ThunderbirdTheme2
|
||||
|
||||
@Composable
|
||||
fun PreviewWithThemes(
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier,
|
||||
) {
|
||||
K9MailTheme2 {
|
||||
PreviewSurface {
|
||||
Column {
|
||||
PreviewHeader(themeName = "K9Theme Light")
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
K9MailTheme2(darkTheme = true) {
|
||||
PreviewSurface {
|
||||
Column {
|
||||
PreviewHeader(themeName = "K9Theme Dark")
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
ThunderbirdTheme2 {
|
||||
PreviewSurface {
|
||||
Column {
|
||||
PreviewHeader(themeName = "ThunderbirdTheme Light")
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
ThunderbirdTheme2(darkTheme = true) {
|
||||
PreviewSurface {
|
||||
Column {
|
||||
PreviewHeader(themeName = "ThunderbirdTheme Dark")
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class PreviewThemeType {
|
||||
K9MAIL,
|
||||
THUNDERBIRD,
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PreviewWithTheme(
|
||||
themeType: PreviewThemeType = PreviewThemeType.THUNDERBIRD,
|
||||
isDarkTheme: Boolean = false,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
when (themeType) {
|
||||
PreviewThemeType.K9MAIL -> {
|
||||
PreviewWithK9MailTheme(isDarkTheme, content)
|
||||
}
|
||||
|
||||
PreviewThemeType.THUNDERBIRD -> {
|
||||
PreviewWithThunderbirdTheme(isDarkTheme, content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PreviewWithK9MailTheme(
|
||||
isDarkTheme: Boolean,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
K9MailTheme2(
|
||||
darkTheme = isDarkTheme,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PreviewWithThunderbirdTheme(
|
||||
isDarkTheme: Boolean,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
ThunderbirdTheme2(
|
||||
darkTheme = isDarkTheme,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun PreviewHeader(
|
||||
themeName: String,
|
||||
) {
|
||||
Surface(
|
||||
color = MainTheme.colors.primary,
|
||||
) {
|
||||
Text(
|
||||
text = themeName,
|
||||
fontSize = 4.sp,
|
||||
modifier = Modifier.padding(
|
||||
start = MainTheme.spacings.half,
|
||||
end = MainTheme.spacings.half,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun PreviewSurface(
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Surface(
|
||||
color = MainTheme.colors.surface,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun CheckboxPreview() {
|
||||
PreviewWithThemes {
|
||||
Checkbox(
|
||||
checked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun CheckboxDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
Checkbox(
|
||||
checked = true,
|
||||
onCheckedChange = {},
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun CircularProgressIndicatorPreview() {
|
||||
PreviewWithThemes {
|
||||
CircularProgressIndicator(
|
||||
progress = { 0.75f },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun CircularProgressIndicatorColoredPreview() {
|
||||
PreviewWithThemes {
|
||||
CircularProgressIndicator(
|
||||
progress = { 0.75f },
|
||||
color = MainTheme.colors.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun DividerHorizontalPreview() {
|
||||
PreviewWithThemes {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(MainTheme.spacings.double),
|
||||
) {
|
||||
DividerHorizontal(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun DividerVerticalPreview() {
|
||||
PreviewWithThemes {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.padding(MainTheme.spacings.double),
|
||||
) {
|
||||
DividerVertical(
|
||||
modifier = Modifier.fillMaxHeight(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom
|
||||
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
val choice = persistentListOf(
|
||||
Pair("1", "Native Android"),
|
||||
Pair("2", "Native iOS"),
|
||||
Pair("3", "KMM"),
|
||||
Pair("4", "Flutter"),
|
||||
)
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun RadioGroupSelectedPreview() {
|
||||
PreviewWithThemes {
|
||||
var selectedOption by remember { mutableStateOf(choice[0]) }
|
||||
RadioGroup(
|
||||
onClick = { selectedOption = it },
|
||||
options = choice,
|
||||
optionTitle = { it.second },
|
||||
selectedOption = selectedOption,
|
||||
modifier = Modifier.padding(MainTheme.spacings.default),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun RadioGroupUnSelectedPreview() {
|
||||
PreviewWithThemes {
|
||||
RadioGroup(
|
||||
onClick = {},
|
||||
options = choice,
|
||||
optionTitle = { it.second },
|
||||
modifier = Modifier.padding(MainTheme.spacings.default),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom
|
||||
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.requiredWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun SurfacePreview() {
|
||||
PreviewWithThemes {
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.requiredHeight(MainTheme.sizes.larger)
|
||||
.requiredWidth(MainTheme.sizes.larger),
|
||||
content = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun SurfaceWithShapePreview() {
|
||||
PreviewWithThemes {
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.requiredHeight(MainTheme.sizes.larger)
|
||||
.requiredWidth(MainTheme.sizes.larger),
|
||||
shape = MainTheme.shapes.small,
|
||||
color = MainTheme.colors.primary,
|
||||
content = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun SwitchPreview() {
|
||||
PreviewWithThemes {
|
||||
Switch(
|
||||
checked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun SwitchDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
Switch(
|
||||
checked = true,
|
||||
onCheckedChange = {},
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.button
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonElevatedPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonElevated(
|
||||
text = "Button Elevated",
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonElevatedDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonElevated(
|
||||
text = "Button Elevated Disabled",
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonElevatedMultiLinePreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonElevated(
|
||||
text = "First\nSecond line",
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.button
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonFilledPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonFilled(
|
||||
text = "Button Filled",
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonFilledDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonFilled(
|
||||
text = "Button Filled Disabled",
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonFilledMultiLinePreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonFilled(
|
||||
text = "First\nSecond line",
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.button
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonFilledTonalPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonFilledTonal(
|
||||
text = "Button Filled Tonal",
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonFilledTonalDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonFilledTonal(
|
||||
text = "Button Filled Tonal Disabled",
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonFilledTonalMultiLinePreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonFilledTonal(
|
||||
text = "First\nSecond line",
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.button
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonIconPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonIcon(
|
||||
onClick = { },
|
||||
imageVector = Icons.Outlined.Info,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonIconFilledPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonIcon(
|
||||
onClick = { },
|
||||
imageVector = Icons.Filled.Cancel,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.button
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonOutlinedPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonOutlined(
|
||||
text = "Button Outlined",
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonOutlinedDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonOutlined(
|
||||
text = "Button Outlined Disabled",
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonOutlinedMultiLinePreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonOutlined(
|
||||
text = "First\nSecond line",
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.button
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
private val options = persistentListOf<String>(
|
||||
"Option 1",
|
||||
"Option 2",
|
||||
"Option 3",
|
||||
)
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonSegmentedSingleChoicePreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonSegmentedSingleChoice(
|
||||
modifier = Modifier,
|
||||
onClick = {},
|
||||
options = options,
|
||||
optionTitle = { it },
|
||||
selectedOption = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonSegmentedSingleChoiceWithSelectionPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonSegmentedSingleChoice(
|
||||
modifier = Modifier,
|
||||
onClick = {},
|
||||
options = options,
|
||||
optionTitle = { it },
|
||||
selectedOption = options[1],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonSegmentedSingleChoiceEmptyPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonSegmentedSingleChoice(
|
||||
modifier = Modifier,
|
||||
onClick = {},
|
||||
options = persistentListOf<String>(),
|
||||
optionTitle = { it },
|
||||
selectedOption = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.button
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonTextPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonText(
|
||||
text = "Button Text",
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonTextColoredPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonText(
|
||||
text = "Button Text Colored",
|
||||
onClick = {},
|
||||
color = Color.Magenta,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonTextDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonText(
|
||||
text = "Button Text Disabled",
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ButtonTextMultiLinePreview() {
|
||||
PreviewWithThemes {
|
||||
ButtonText(
|
||||
text = "First\nSecond line",
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.card
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun CardElevatedPreview() {
|
||||
PreviewWithThemes {
|
||||
CardElevated {
|
||||
Box(modifier = Modifier.padding(MainTheme.spacings.double)) {
|
||||
TextBodyMedium("Text in card")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.card
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun CardFilledPreview() {
|
||||
PreviewWithThemes {
|
||||
CardFilled {
|
||||
Box(modifier = Modifier.padding(MainTheme.spacings.double)) {
|
||||
TextBodyMedium("Text in card")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.card
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemesLightDark
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.Surface
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun CardOutlinedPreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(modifier = Modifier.padding(MainTheme.spacings.quadruple)) {
|
||||
CardOutlined {
|
||||
Box(modifier = Modifier.padding(MainTheme.spacings.double)) {
|
||||
TextBodyMedium("Text in card")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.icon
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
internal fun IconPreview() {
|
||||
PreviewWithThemes {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Info,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
internal fun IconTintedPreview() {
|
||||
PreviewWithThemes {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Info,
|
||||
tint = Color.Magenta,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.image
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun FixedScaleImageBottomCenterPreview() {
|
||||
PreviewWithTheme {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.width(MainTheme.sizes.huge)
|
||||
.height(MainTheme.sizes.huge),
|
||||
) {
|
||||
FixedScaleImage(
|
||||
id = MainTheme.images.logo,
|
||||
alignment = Alignment.BottomCenter,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun FixedScaleImageCroppedPreview() {
|
||||
PreviewWithTheme {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.width(MainTheme.sizes.medium)
|
||||
.height(MainTheme.sizes.medium),
|
||||
) {
|
||||
FixedScaleImage(
|
||||
id = MainTheme.images.logo,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun FixedScaleImageHorizontallyCroppedPreview() {
|
||||
PreviewWithTheme {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.width(MainTheme.sizes.huge)
|
||||
.height(MainTheme.sizes.medium),
|
||||
) {
|
||||
FixedScaleImage(
|
||||
id = MainTheme.images.logo,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun FixedScaleImageVerticallyCroppedPreview() {
|
||||
PreviewWithTheme {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.width(MainTheme.sizes.medium)
|
||||
.height(MainTheme.sizes.huge),
|
||||
) {
|
||||
FixedScaleImage(
|
||||
id = MainTheme.images.logo,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.image
|
||||
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun RemoteImagePreview() {
|
||||
PreviewWithTheme {
|
||||
val painter = rememberVectorPainter(Icons.Outlined.AccountCircle)
|
||||
RemoteImage(
|
||||
url = "",
|
||||
modifier = Modifier.size(MainTheme.sizes.large),
|
||||
previewPlaceholder = painter,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextBodyLargePreview() {
|
||||
PreviewWithThemes {
|
||||
TextBodyLarge(
|
||||
text = "Text Body Large",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextBodyLargeWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextBodyLarge(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Body Large ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextBodyLargeWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextBodyLarge(
|
||||
text = "Text Body Large with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextBodyLargeWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextBodyLarge(
|
||||
text = "Text Body Large with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextBodyMediumPreview() {
|
||||
PreviewWithThemes {
|
||||
TextBodyMedium(
|
||||
text = "Text Body Medium",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextBodyMediumWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextBodyMedium(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Body Medium ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextBodyMediumWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextBodyMedium(
|
||||
text = "Text Body Medium with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextBodyMediumWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextBodyMedium(
|
||||
text = "Text Body Medium with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextBodySmallPreview() {
|
||||
PreviewWithThemes {
|
||||
TextBodySmall(
|
||||
text = "Text Body Small",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextBodySmallWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextBodySmall(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Body Small ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextBodySmallWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextBodySmall(
|
||||
text = "Text Body Small with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextBodySmallWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextBodySmall(
|
||||
text = "Text Body Small with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextDisplayLargePreview() {
|
||||
PreviewWithThemes {
|
||||
TextDisplayLarge(
|
||||
text = "Text Display Large",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextDisplayLargeWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextDisplayLarge(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Display Large ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextDisplayLargeWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextDisplayLarge(
|
||||
text = "Text Display Large with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextDisplayLargeWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextDisplayLarge(
|
||||
text = "Text Display Large with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextDisplayMediumPreview() {
|
||||
PreviewWithThemes {
|
||||
TextDisplayMedium(
|
||||
text = "Text Display Medium",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextDisplayMediumWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextDisplayMedium(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Display Medium ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextDisplayMediumWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextDisplayMedium(
|
||||
text = "Text Display Medium with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextDisplayMediumWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextDisplayMedium(
|
||||
text = "Text Display Medium with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextDisplaySmallPreview() {
|
||||
PreviewWithThemes {
|
||||
TextDisplaySmall(
|
||||
text = "Text Display Small",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextDisplaySmallWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextDisplaySmall(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Display Small ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextDisplaySmallWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextDisplaySmall(
|
||||
text = "Text Display Small with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextDisplaySmallWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextDisplaySmall(
|
||||
text = "Text Display Small with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextHeadlineLargePreview() {
|
||||
PreviewWithThemes {
|
||||
TextHeadlineLarge(
|
||||
text = "Text Headline Large",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextHeadlineLargeWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextHeadlineLarge(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Headline Large ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextHeadlineLargeWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextHeadlineLarge(
|
||||
text = "Text Headline Large with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextHeadlineLargeWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextHeadlineLarge(
|
||||
text = "Text Headline Large with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextHeadlineMediumPreview() {
|
||||
PreviewWithThemes {
|
||||
TextHeadlineMedium(
|
||||
text = "Text Headline Medium",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextHeadlineMediumWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextHeadlineMedium(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Headline Medium ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextHeadlineMediumWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextHeadlineMedium(
|
||||
text = "Text Headline Medium with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextHeadlineMediumWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextHeadlineMedium(
|
||||
text = "Text Headline Medium with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextHeadlineSmallPreview() {
|
||||
PreviewWithThemes {
|
||||
TextHeadlineSmall(
|
||||
text = "Text Headline Small",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextHeadlineSmallWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextHeadlineSmall(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Headline Small ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextHeadlineSmallWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextHeadlineSmall(
|
||||
text = "Text Headline Small with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextHeadlineSmallWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextHeadlineSmall(
|
||||
text = "Text Headline Small with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextLabelLargePreview() {
|
||||
PreviewWithThemes {
|
||||
TextLabelLarge(
|
||||
text = "Text Label Large",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextLabelLargeWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextLabelLarge(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Label Large ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextLabelLargeWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextLabelLarge(
|
||||
text = "Text Label Large with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextLabelLargeWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextLabelLarge(
|
||||
text = "Text Label Large with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextLabelMediumPreview() {
|
||||
PreviewWithThemes {
|
||||
TextLabelMedium(
|
||||
text = "Text Label Medium",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextLabelMediumWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextLabelMedium(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Label Medium ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextLabelMediumWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextLabelMedium(
|
||||
text = "Text Label Medium with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextLabelMediumWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextLabelMedium(
|
||||
text = "Text Label Medium with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextLabelSmallPreview() {
|
||||
PreviewWithThemes {
|
||||
TextLabelSmall(
|
||||
text = "Text Label Small",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextLabelSmallWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextLabelSmall(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Label Small ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextLabelSmallWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextLabelSmall(
|
||||
text = "Text Label Small with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextLabelSmallWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextLabelSmall(
|
||||
text = "Text Label Small with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextTitleLargePreview() {
|
||||
PreviewWithThemes {
|
||||
TextTitleLarge(
|
||||
text = "Text Title Large",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextTitleLargeWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextTitleLarge(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Title Large ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextTitleLargeWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextTitleLarge(
|
||||
text = "Text Title Large with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextTitleLargeWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextTitleLarge(
|
||||
text = "Text Title Large with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextTitleMediumPreview() {
|
||||
PreviewWithThemes {
|
||||
TextTitleMedium(
|
||||
text = "Text Title Medium",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextTitleMediumWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextTitleMedium(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Title Medium ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextTitleMediumWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextTitleMedium(
|
||||
text = "Text Title Medium with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextTitleMediumWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextTitleMedium(
|
||||
text = "Text Title Medium with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.text
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextTitleSmallPreview() {
|
||||
PreviewWithThemes {
|
||||
TextTitleSmall(
|
||||
text = "Text Title Small",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextTitleSmallWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
TextTitleSmall(
|
||||
text = buildAnnotatedString {
|
||||
append("Text Title Small ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextTitleSmallWithColorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextTitleSmall(
|
||||
text = "Text Title Small with color",
|
||||
color = MainTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextTitleSmallWithTextAlignPreview() {
|
||||
PreviewWithThemes {
|
||||
TextTitleSmall(
|
||||
text = "Text Title Small with TextAlign End",
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldLabelPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldLabel(
|
||||
label = "Label",
|
||||
isRequired = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldLabelRequiredPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldLabel(
|
||||
label = "Label",
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldLabelRequiredEmptyLabelPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldLabel(
|
||||
label = "",
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedEmailAddressPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedEmailAddress(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedEmailAddressWithLabelPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedEmailAddress(
|
||||
value = "Input text",
|
||||
label = "Label",
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedEmailDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedEmailAddress(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
isEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedEmailErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedEmailAddress(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
hasError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedFakeSelectPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedFakeSelect(
|
||||
text = "Current value",
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedFakeSelectPreviewWithLabel() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedFakeSelect(
|
||||
text = "Current value",
|
||||
onClick = {},
|
||||
label = "Label",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedNumberPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedNumber(
|
||||
value = 123L,
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedNumberWithLabelPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedNumber(
|
||||
value = 123L,
|
||||
label = "Label",
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedNumberDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedNumber(
|
||||
value = 123L,
|
||||
onValueChange = {},
|
||||
isEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedNumberErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedNumber(
|
||||
value = 123L,
|
||||
onValueChange = {},
|
||||
hasError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedPasswordPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedPassword(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedPasswordWithLabelPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedPassword(
|
||||
value = "Input text",
|
||||
label = "Label",
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedPasswordDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedPassword(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
isEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedPasswordErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedPassword(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
hasError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icon
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlined(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedWithLabelPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlined(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
label = "Label",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlined(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
isEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlined(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
hasError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedRequiredPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlined(
|
||||
value = "",
|
||||
onValueChange = {},
|
||||
label = "Label",
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedWithTrailingIconPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlined(
|
||||
value = "",
|
||||
onValueChange = {},
|
||||
trailingIcon = { Icon(imageVector = Icons.Outlined.AccountCircle) },
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedSelectPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedSelect(
|
||||
options = persistentListOf("Option 1", "Option 2", "Option 3"),
|
||||
selectedOption = "Option 1",
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextFieldOutlinedSelectPreviewWithLabel() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlinedSelect(
|
||||
options = persistentListOf("Option 1", "Option 2", "Option 3"),
|
||||
selectedOption = "Option 1",
|
||||
onValueChange = {},
|
||||
label = "Label",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextTitleMedium
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContentLoadingErrorViewContentPreview() {
|
||||
PreviewWithThemes {
|
||||
DefaultContentLoadingErrorView(
|
||||
state = ContentLoadingErrorState.Content,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContentLoadingErrorViewLoadingPreview() {
|
||||
PreviewWithThemes {
|
||||
DefaultContentLoadingErrorView(
|
||||
state = ContentLoadingErrorState.Loading,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContentLoadingErrorViewErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
DefaultContentLoadingErrorView(
|
||||
state = ContentLoadingErrorState.Error,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContentLoadingErrorViewInteractivePreview() {
|
||||
PreviewWithThemes {
|
||||
val state = remember {
|
||||
mutableStateOf<ContentLoadingErrorState>(ContentLoadingErrorState.Loading)
|
||||
}
|
||||
|
||||
DefaultContentLoadingErrorView(
|
||||
state = state.value,
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
when (state.value) {
|
||||
ContentLoadingErrorState.Loading -> {
|
||||
state.value = ContentLoadingErrorState.Content
|
||||
}
|
||||
|
||||
ContentLoadingErrorState.Content -> {
|
||||
state.value = ContentLoadingErrorState.Error
|
||||
}
|
||||
|
||||
ContentLoadingErrorState.Error -> {
|
||||
state.value = ContentLoadingErrorState.Loading
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DefaultContentLoadingErrorView(
|
||||
state: ContentLoadingErrorState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
ContentLoadingErrorView(
|
||||
state = state,
|
||||
error = {
|
||||
TextTitleMedium(text = "Error")
|
||||
},
|
||||
loading = {
|
||||
TextTitleMedium(text = "Loading...")
|
||||
},
|
||||
content = {
|
||||
TextTitleMedium(text = "Content")
|
||||
},
|
||||
modifier = modifier.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextTitleMedium
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContentLoadingViewPreview() {
|
||||
PreviewWithThemes {
|
||||
DefaultContentLoadingView(
|
||||
state = ContentLoadingState.Content,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContentLoadingViewLoadingPreview() {
|
||||
PreviewWithThemes {
|
||||
DefaultContentLoadingView(
|
||||
state = ContentLoadingState.Loading,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DefaultContentLoadingView(
|
||||
state: ContentLoadingState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
ContentLoadingView(
|
||||
state = state,
|
||||
loading = {
|
||||
TextTitleMedium(text = "Loading...")
|
||||
},
|
||||
content = {
|
||||
TextTitleMedium(text = "Content")
|
||||
},
|
||||
modifier = modifier.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContentLoadingViewInteractivePreview() {
|
||||
PreviewWithThemes {
|
||||
val state = remember {
|
||||
mutableStateOf(State(isLoading = true, content = "Hello world"))
|
||||
}
|
||||
|
||||
ContentLoadingView(
|
||||
state = state.value,
|
||||
loading = {
|
||||
TextTitleMedium(text = "Loading...")
|
||||
},
|
||||
content = { targetState ->
|
||||
TextTitleMedium(text = targetState.content)
|
||||
},
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
val currentValue = state.value
|
||||
state.value = currentValue.copy(isLoading = currentValue.isLoading.not())
|
||||
}
|
||||
.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private data class State(
|
||||
override val isLoading: Boolean,
|
||||
val content: String,
|
||||
) : LoadingState
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ErrorViewPreview() {
|
||||
PreviewWithThemes {
|
||||
ErrorView(
|
||||
title = "Error",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ErrorViewWithMessagePreview() {
|
||||
PreviewWithThemes {
|
||||
ErrorView(
|
||||
title = "Error",
|
||||
message = "Something went wrong.",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ErrorViewWithRetryPreview() {
|
||||
PreviewWithThemes {
|
||||
ErrorView(
|
||||
title = "Error",
|
||||
onRetry = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ErrorViewWithRetryAndMessagePreview() {
|
||||
PreviewWithThemes {
|
||||
ErrorView(
|
||||
title = "Error",
|
||||
message = "Something went wrong.",
|
||||
onRetry = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun LoadingViewPreview() {
|
||||
PreviewWithThemes {
|
||||
LoadingView()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun LoadingViewWithMessagePreview() {
|
||||
PreviewWithThemes {
|
||||
LoadingView(
|
||||
message = "Loading ...",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.Surface
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyLarge
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PullToRefreshBoxPreview() {
|
||||
PreviewWithThemes {
|
||||
PullToRefreshBox(
|
||||
isRefreshing = false,
|
||||
onRefresh = {},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
.height(MainTheme.sizes.medium),
|
||||
) {
|
||||
Surface {
|
||||
TextBodyLarge("Pull to refresh")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PullToRefreshBoxRefreshingPreview() {
|
||||
PreviewWithThemes {
|
||||
PullToRefreshBox(
|
||||
isRefreshing = true,
|
||||
onRefresh = {},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
.height(MainTheme.sizes.medium),
|
||||
) {
|
||||
Surface {
|
||||
TextBodyLarge("Refreshing ...")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule.input
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.TextRange
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun AdvancedTextInputPreview() {
|
||||
PreviewWithThemes {
|
||||
AdvancedTextInput(
|
||||
onTextChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun AdvancedTextInputIsRequiredPreview() {
|
||||
PreviewWithThemes {
|
||||
AdvancedTextInput(
|
||||
onTextChange = {},
|
||||
label = "Text input is required",
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun AdvancedTextInputWithErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
AdvancedTextInput(
|
||||
onTextChange = {},
|
||||
errorMessage = "Text input error",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun AdvancedTextInputWithAnnotatedStringPreview() {
|
||||
PreviewWithThemes {
|
||||
AdvancedTextInput(
|
||||
onTextChange = {},
|
||||
text = TextFieldValue(
|
||||
annotatedString = buildAnnotatedString {
|
||||
append("Text input with ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append("Annotated")
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun AdvancedTextInputWithSelectionPreview() {
|
||||
PreviewWithThemes {
|
||||
AdvancedTextInput(
|
||||
onTextChange = {},
|
||||
text = TextFieldValue("Text input with selection", selection = TextRange(0, 4)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun AdvancedTextInputWithCompositionPreview() {
|
||||
PreviewWithThemes {
|
||||
AdvancedTextInput(
|
||||
onTextChange = {},
|
||||
text = TextFieldValue(
|
||||
text = "Text input with composition",
|
||||
composition = TextRange(0, 4),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule.input
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun CheckboxInputPreview() {
|
||||
PreviewWithThemes {
|
||||
CheckboxInput(
|
||||
text = "CheckboxInput",
|
||||
checked = false,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun CheckboxInputWithErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
CheckboxInput(
|
||||
text = "CheckboxInput",
|
||||
checked = false,
|
||||
onCheckedChange = {},
|
||||
errorMessage = "Error message",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun CheckboxInputCheckedPreview() {
|
||||
PreviewWithThemes {
|
||||
CheckboxInput(
|
||||
text = "CheckboxInput",
|
||||
checked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule.input
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun EmailAddressInputPreview() {
|
||||
PreviewWithThemes {
|
||||
EmailAddressInput(
|
||||
onEmailAddressChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun EmailAddressInputWithErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
EmailAddressInput(
|
||||
onEmailAddressChange = {},
|
||||
errorMessage = "Email address error",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule.input
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.textfield.TextFieldOutlined
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun InputLayoutPreview() {
|
||||
PreviewWithThemes {
|
||||
InputLayout {
|
||||
TextFieldOutlined(value = "InputLayout", onValueChange = {})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun InputLayoutWithErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
InputLayout(
|
||||
errorMessage = "Error message",
|
||||
) {
|
||||
TextFieldOutlined(value = "InputLayout", onValueChange = {})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun InputLayoutWithWarningPreview() {
|
||||
PreviewWithThemes {
|
||||
InputLayout(
|
||||
warningMessage = "Warning message",
|
||||
) {
|
||||
TextFieldOutlined(value = "InputLayout", onValueChange = {})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule.input
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun NumberInputPreview() {
|
||||
PreviewWithThemes {
|
||||
NumberInput(
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun NumberInputIsRequiredPreview() {
|
||||
PreviewWithThemes {
|
||||
NumberInput(
|
||||
onValueChange = {},
|
||||
label = "Text input is required",
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun NumberInputWithErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
NumberInput(
|
||||
onValueChange = {},
|
||||
errorMessage = "Text input error",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule.input
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PasswordInputPreview() {
|
||||
PreviewWithThemes {
|
||||
PasswordInput(
|
||||
onPasswordChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PasswordInputWithErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
PasswordInput(
|
||||
onPasswordChange = {},
|
||||
errorMessage = "Password error",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule.input
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun SelectInputPreview() {
|
||||
PreviewWithThemes {
|
||||
SelectInput(
|
||||
options = persistentListOf("Option 1", "Option 2", "Option 3"),
|
||||
selectedOption = "Option 1",
|
||||
onOptionChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule.input
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun SwitchInputPreview() {
|
||||
PreviewWithThemes {
|
||||
SwitchInput(
|
||||
text = "SwitchInput",
|
||||
checked = false,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun SwitchInputWithErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
SwitchInput(
|
||||
text = "SwitchInput",
|
||||
checked = false,
|
||||
onCheckedChange = {},
|
||||
errorMessage = "Error message",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun SwitchInputCheckedPreview() {
|
||||
PreviewWithThemes {
|
||||
SwitchInput(
|
||||
text = "SwitchInput",
|
||||
checked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule.input
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextInputPreview() {
|
||||
PreviewWithThemes {
|
||||
TextInput(
|
||||
onTextChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextInputIsRequiredPreview() {
|
||||
PreviewWithThemes {
|
||||
TextInput(
|
||||
onTextChange = {},
|
||||
label = "Text input is required",
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TextInputWithErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextInput(
|
||||
onTextChange = {},
|
||||
errorMessage = "Text input error",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemesLightDark
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.notification.NotificationActionButton
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun NotificationActionButtonPreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
) {
|
||||
NotificationActionButton(
|
||||
onClick = {},
|
||||
text = "Sign in",
|
||||
)
|
||||
NotificationActionButton(
|
||||
onClick = {},
|
||||
text = "View support article",
|
||||
isExternalLink = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.organism
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun AlertDialogPreview() {
|
||||
PreviewWithTheme {
|
||||
AlertDialog(
|
||||
title = "Title",
|
||||
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
|
||||
"Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
confirmText = "Accept",
|
||||
onConfirmClick = {},
|
||||
onDismissRequest = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun AlertDialogWithIconPreview() {
|
||||
PreviewWithTheme {
|
||||
AlertDialog(
|
||||
icon = Icons.Outlined.Info,
|
||||
title = "Title",
|
||||
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
|
||||
"Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
confirmText = "Accept",
|
||||
onConfirmClick = {},
|
||||
onDismissRequest = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun AlertDialogWithCancelPreview() {
|
||||
PreviewWithTheme {
|
||||
AlertDialog(
|
||||
icon = Icons.Outlined.Info,
|
||||
title = "Title",
|
||||
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
|
||||
"Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
confirmText = "Accept",
|
||||
dismissText = "Cancel",
|
||||
onConfirmClick = {},
|
||||
onDismissRequest = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun AlertDialogWithCustomContentPreview() {
|
||||
PreviewWithTheme {
|
||||
AlertDialog(
|
||||
icon = Icons.Outlined.Info,
|
||||
title = "Title",
|
||||
confirmText = "Accept",
|
||||
dismissText = "Cancel",
|
||||
onConfirmClick = {},
|
||||
onDismissRequest = {},
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.double),
|
||||
) {
|
||||
TextBodyMedium("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
|
||||
TextBodyMedium("Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.organism
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Refresh
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewLightDarkLandscape
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemesLightDark
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextHeadlineSmall
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@PreviewLightDarkLandscape
|
||||
@Composable
|
||||
private fun BasicDialogPreview() {
|
||||
PreviewWithThemesLightDark(
|
||||
useRow = true,
|
||||
useScrim = true,
|
||||
scrimPadding = PaddingValues(32.dp),
|
||||
arrangement = Arrangement.spacedBy(24.dp),
|
||||
) {
|
||||
BasicDialogContent(
|
||||
headline = {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.double),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Icon(imageVector = Icons.Default.Refresh, contentDescription = null)
|
||||
TextHeadlineSmall(text = "Reset settings?")
|
||||
}
|
||||
},
|
||||
supportingText = {
|
||||
TextBodyMedium(
|
||||
text = "This will reset your app preferences back to their default settings. " +
|
||||
"The following accounts will also be signed out:",
|
||||
color = MainTheme.colors.onSurfaceVariant,
|
||||
)
|
||||
},
|
||||
content = {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.double),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
start = MainTheme.spacings.triple,
|
||||
end = MainTheme.spacings.triple,
|
||||
),
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(MainTheme.spacings.double),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(MainTheme.sizes.iconAvatar)
|
||||
.background(color = MainTheme.colors.primary, shape = CircleShape),
|
||||
)
|
||||
Text(text = "Account 1")
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(MainTheme.spacings.double),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(MainTheme.sizes.iconAvatar)
|
||||
.background(color = MainTheme.colors.primary, shape = CircleShape),
|
||||
)
|
||||
Text(text = "Account 2")
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(MainTheme.spacings.double),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(MainTheme.sizes.iconAvatar)
|
||||
.background(color = MainTheme.colors.primary, shape = CircleShape),
|
||||
)
|
||||
Text(text = "Account 3")
|
||||
}
|
||||
}
|
||||
},
|
||||
buttons = {
|
||||
TextButton(onClick = {}) {
|
||||
Text(text = "Cancel")
|
||||
}
|
||||
TextButton(onClick = {}) {
|
||||
Text(text = "Accept")
|
||||
}
|
||||
},
|
||||
showDividers = true,
|
||||
modifier = Modifier.width(300.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDarkLandscape
|
||||
@Composable
|
||||
private fun PreviewOnlySupportingText() {
|
||||
PreviewWithThemesLightDark(
|
||||
useRow = true,
|
||||
useScrim = true,
|
||||
scrimPadding = PaddingValues(32.dp),
|
||||
arrangement = Arrangement.spacedBy(24.dp),
|
||||
) {
|
||||
BasicDialogContent(
|
||||
headline = {
|
||||
TextHeadlineSmall(text = "Email can not be archived")
|
||||
},
|
||||
supportingText = {
|
||||
TextBodyMedium(
|
||||
text = "Configure archive folder now",
|
||||
color = MainTheme.colors.onSurfaceVariant,
|
||||
)
|
||||
},
|
||||
content = null,
|
||||
buttons = {
|
||||
TextButton(onClick = {}) {
|
||||
Text(text = "Skip for now")
|
||||
}
|
||||
TextButton(onClick = {}) {
|
||||
Text(text = "Set archive folder")
|
||||
}
|
||||
},
|
||||
showDividers = false,
|
||||
modifier = Modifier.width(300.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.organism
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonIcon
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun SubtitleTopAppBarPreview() {
|
||||
PreviewWithThemes {
|
||||
SubtitleTopAppBar(
|
||||
title = "Title",
|
||||
subtitle = "Subtitle",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun SubtitleTopAppBarWithLongSubtitlePreview() {
|
||||
PreviewWithThemes {
|
||||
SubtitleTopAppBar(
|
||||
title = "Title",
|
||||
subtitle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
|
||||
"Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun SubtitleTopAppBarWithActionsPreview() {
|
||||
PreviewWithThemes {
|
||||
SubtitleTopAppBar(
|
||||
title = "Title",
|
||||
subtitle = "Subtitle",
|
||||
actions = {
|
||||
ButtonIcon(
|
||||
onClick = {},
|
||||
imageVector = Icons.Outlined.Info,
|
||||
)
|
||||
ButtonIcon(
|
||||
onClick = {},
|
||||
imageVector = Icons.Outlined.Check,
|
||||
)
|
||||
ButtonIcon(
|
||||
onClick = {},
|
||||
imageVector = Icons.Outlined.Visibility,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun SubtitleTopAppBarWithMenuButtonPreview() {
|
||||
PreviewWithThemes {
|
||||
SubtitleTopAppBarWithMenuButton(
|
||||
title = "Title",
|
||||
subtitle = "Subtitle",
|
||||
onMenuClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun SubtitleTopAppBarWithBackButtonPreview() {
|
||||
PreviewWithThemes {
|
||||
SubtitleTopAppBarWithBackButton(
|
||||
title = "Title",
|
||||
subtitle = "Subtitle",
|
||||
onBackClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.organism
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonIcon
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TopAppBarPreview() {
|
||||
PreviewWithThemes {
|
||||
TopAppBar(
|
||||
title = "Title",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TopAppBarWithActionsPreview() {
|
||||
PreviewWithThemes {
|
||||
TopAppBar(
|
||||
title = "Title",
|
||||
actions = {
|
||||
ButtonIcon(
|
||||
onClick = {},
|
||||
imageVector = Icons.Outlined.Info,
|
||||
)
|
||||
ButtonIcon(
|
||||
onClick = {},
|
||||
imageVector = Icons.Outlined.Check,
|
||||
)
|
||||
ButtonIcon(
|
||||
onClick = {},
|
||||
imageVector = Icons.Outlined.Visibility,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TopAppBarWithMenuButtonPreview() {
|
||||
PreviewWithThemes {
|
||||
TopAppBarWithMenuButton(
|
||||
title = "Title",
|
||||
onMenuClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun TopAppBarWithBackButtonPreview() {
|
||||
PreviewWithThemes {
|
||||
TopAppBarWithBackButton(
|
||||
title = "Title",
|
||||
onBackClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.organism.banner.global
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemesLightDark
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.Surface
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonText
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icon
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.outlined.Warning
|
||||
import app.k9mail.core.ui.compose.designsystem.organism.banner.global.BannerGlobalNotificationCard
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun BannerGlobalNotificationCardStringTitlePreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
BannerGlobalNotificationCard(
|
||||
icon = { Icon(imageVector = Icons.Outlined.Warning) },
|
||||
text = "Offline. No internet connection found.",
|
||||
action = {
|
||||
ButtonText(
|
||||
text = "Retry",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun BannerGlobalNotificationCardAnnotatedStringTitlePreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
BannerGlobalNotificationCard(
|
||||
icon = { Icon(imageVector = Icons.Outlined.Warning) },
|
||||
text = buildAnnotatedString {
|
||||
withStyle(SpanStyle(fontWeight = FontWeight.Black)) {
|
||||
append("Offline. ")
|
||||
}
|
||||
append("No internet connection found.")
|
||||
},
|
||||
action = {
|
||||
ButtonText(
|
||||
text = "Retry",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.organism.banner.global
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemesLightDark
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.Surface
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.notification.NotificationActionButton
|
||||
import app.k9mail.core.ui.compose.designsystem.organism.banner.global.ErrorBannerGlobalNotificationCard
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun ErrorBannerGlobalNotificationCardStringTitlePreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
ErrorBannerGlobalNotificationCard(
|
||||
text = "Offline. No internet connection found.",
|
||||
action = {
|
||||
NotificationActionButton(
|
||||
text = "Retry",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun ErrorBannerGlobalNotificationCardAnnotatedStringTitlePreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
ErrorBannerGlobalNotificationCard(
|
||||
text = buildAnnotatedString {
|
||||
withStyle(SpanStyle(fontWeight = FontWeight.Black)) {
|
||||
append("Offline. ")
|
||||
}
|
||||
append("No internet connection found.")
|
||||
},
|
||||
action = {
|
||||
NotificationActionButton(
|
||||
text = "Retry",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.organism.banner.global
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemesLightDark
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.Surface
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.notification.NotificationActionButton
|
||||
import app.k9mail.core.ui.compose.designsystem.organism.banner.global.InfoBannerGlobalNotificationCard
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun InfoBannerGlobalNotificationCardStringTitlePreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
InfoBannerGlobalNotificationCard(
|
||||
text = "Offline. No internet connection found.",
|
||||
action = {
|
||||
NotificationActionButton(
|
||||
text = "Retry",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun InfoBannerGlobalNotificationCardNoActionPreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
InfoBannerGlobalNotificationCard(
|
||||
text = "Offline. No internet connection found.",
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun InfoBannerGlobalNotificationCardLongTextPreview(
|
||||
@PreviewParameter(LoremIpsum::class) text: String,
|
||||
) {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
InfoBannerGlobalNotificationCard(
|
||||
text = text,
|
||||
action = {
|
||||
NotificationActionButton(
|
||||
text = "Retry",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun InfoBannerGlobalNotificationCardLongNoActionTextPreview(
|
||||
@PreviewParameter(LoremIpsum::class) text: String,
|
||||
) {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
InfoBannerGlobalNotificationCard(
|
||||
text = text,
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun InfoBannerGlobalNotificationCardAnnotatedStringTitlePreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
InfoBannerGlobalNotificationCard(
|
||||
text = buildAnnotatedString {
|
||||
withStyle(SpanStyle(fontWeight = FontWeight.Black)) {
|
||||
append("Offline. ")
|
||||
}
|
||||
append("No internet connection found.")
|
||||
},
|
||||
action = {
|
||||
NotificationActionButton(
|
||||
text = "Retry",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.organism.banner.global
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemesLightDark
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.Surface
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.notification.NotificationActionButton
|
||||
import app.k9mail.core.ui.compose.designsystem.organism.banner.global.SuccessBannerGlobalNotificationCard
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun SuccessBannerGlobalNotificationCardStringTitlePreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
SuccessBannerGlobalNotificationCard(
|
||||
text = "What an awesome notification, isn't it?",
|
||||
action = {
|
||||
NotificationActionButton(
|
||||
text = "Action",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun SuccessBannerGlobalNotificationCardNoActionPreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
SuccessBannerGlobalNotificationCard(
|
||||
text = "What an awesome notification, isn't it?",
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun SuccessBannerGlobalNotificationCardLongTextPreview(
|
||||
@PreviewParameter(LoremIpsum::class) text: String,
|
||||
) {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
SuccessBannerGlobalNotificationCard(
|
||||
text = text,
|
||||
action = {
|
||||
NotificationActionButton(
|
||||
text = "Retry",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun SuccessBannerGlobalNotificationCardLongNoActionTextPreview(
|
||||
@PreviewParameter(LoremIpsum::class) text: String,
|
||||
) {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
SuccessBannerGlobalNotificationCard(
|
||||
text = text,
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun SuccessBannerGlobalNotificationCardAnnotatedStringTitlePreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
SuccessBannerGlobalNotificationCard(
|
||||
text = buildAnnotatedString {
|
||||
withStyle(SpanStyle(fontWeight = FontWeight.Black)) {
|
||||
append("Offline. ")
|
||||
}
|
||||
append("No internet connection found.")
|
||||
},
|
||||
action = {
|
||||
NotificationActionButton(
|
||||
text = "Retry",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.organism.banner.global
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemesLightDark
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.Surface
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.notification.NotificationActionButton
|
||||
import app.k9mail.core.ui.compose.designsystem.organism.banner.global.WarningBannerGlobalNotificationCard
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun WarningBannerGlobalNotificationCardStringTitlePreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
WarningBannerGlobalNotificationCard(
|
||||
text = "Offline. No internet connection found.",
|
||||
action = {
|
||||
NotificationActionButton(
|
||||
text = "Retry",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun WarningBannerGlobalNotificationCardNoActionPreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
WarningBannerGlobalNotificationCard(
|
||||
text = "Offline. No internet connection found.",
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun WarningBannerGlobalNotificationCardLongTextPreview(
|
||||
@PreviewParameter(LoremIpsum::class) text: String,
|
||||
) {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
WarningBannerGlobalNotificationCard(
|
||||
text = text,
|
||||
action = {
|
||||
NotificationActionButton(
|
||||
text = "Retry",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun WarningBannerGlobalNotificationCardLongNoActionTextPreview(
|
||||
@PreviewParameter(LoremIpsum::class) text: String,
|
||||
) {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
WarningBannerGlobalNotificationCard(
|
||||
text = text,
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun WarningBannerGlobalNotificationCardAnnotatedStringTitlePreview() {
|
||||
PreviewWithThemesLightDark {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
WarningBannerGlobalNotificationCard(
|
||||
text = buildAnnotatedString {
|
||||
withStyle(SpanStyle(fontWeight = FontWeight.Black)) {
|
||||
append("Offline. ")
|
||||
}
|
||||
append("No internet connection found.")
|
||||
},
|
||||
action = {
|
||||
NotificationActionButton(
|
||||
text = "Retry",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.quadruple),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue