
Offers extensions and implementations for standard and third-party libraries, enhancing functionality with modules like comparators, Jetpack Compose support, localization, and serialization for various data types.
Kotlin Multiplatform extensions and implementations for the Kotlin standard library and third-party libraries.
Published to Maven Central.
repositories {
mavenCentral()
}implementation("io.github.woody230.ktx:$Module:$Version")Extensions for AboutLibraries. See compose-aboutlibraries for the associated composable.
Compose Multiplatform is the compose version used by this project to support both Android and the JVM.
New to Compose?
compose-multiplatform composable for AboutLibraries
@Composable
fun Libraries(libraries: List<Library>) = LibraryProjector(
interactor = LibraryInteractor(
libraries = libraries
)
).Projection()Using the AssetReader from the resource module, you can use the libraries output from AboutLibraries as a moko-resource asset.
First, you will need to add the following to gradle in order to copy it as a resource.
val aboutLibrariesResource = task("aboutLibrariesResource") {
dependsOn("exportLibraryDefinitions")
copy {
from("$buildDir\\generated\\aboutLibraries") {
include("aboutlibraries.json")
}
into("$projectDir\\src\\commonMain\\resources\\MR\\assets")
}
}
tasks.whenTaskAdded {
if (name == "generateMRcommonMain") {
dependsOn(aboutLibrariesResource)
}
}Now you can use the AssetReader to read the resource and create the libraries from it.
val libraries = with(AssetReader) {
val content = MyResources.assets.aboutlibraries.readText()
Libs.Builder().withJson(content).build().libraries
}A copy of Accompanist modules (v0.23.1 and v0.2.1 Snapper) with multiplatform capability. Currently this only includes the pager and pager indicators.
A copy of ConstraintLayout (v2.1.3 core and v1.0.0 compose) with multiplatform capability.
Wrappers for strings and images for the compose module using the resource module.
Conversion of image moko-resources:
val painter = MyResources.images.my_resource.painter()
val localized = MyResources.strings.my_resource.localized()Standardized AlertDialog buttons:
val withConfirmation = AlertDialogInteractor.Builder().uniText().build()
val withConfirmationCancel = AlertDialogInteractor.Builder().biText().build()
val withConfirmationCancelReset = AlertDialogInteractor.Builder().triText().build()IconInteractor wrappers for common use cases such as:
val delete = deleteIconInteractor()
val language = languageIconInteractor()
val settings = settingsIconInteractor()Conversion of text moko-resources:
val text = MyResources.strings.my_resource.textInteractor()kotlinx.serialization extensions for compose related classes.
ColorSerializer for storing the Hex associated with a androidx.compose.ui.graphics.Color
Setting to compose-multiplatform state converters.
@Composable
fun Observe(setting: Setting<Instant>, nullableSetting: Setting<Instant?>) {
val defaulted: MutableState<Instant> = setting.safeState()
val nullable: MutableState<Instant?> = setting.nullState()
// Keep the ability to be nullable, but the value will be defaulted and not null.
val defaultedNullable: MutableState<Instant?> = nullableSetting.defaultState()
}ColorSetting for androidx.compose.ui.graphics.Color.
fun color(settings: SuspendSettings): Setting<Color> = ColorSetting(
settings = settings,
key = "Color",
defaultValue = Color.Blue
)The ShowAlert() composable method is used to send notifications.
@Composable
fun SendMessage() = ShowAlert(title = "Important!", "An error occurred.", type = AlertType.ERROR)The ApplicationSize companion object can be used to get the current size of the Android device or desktop window size.
val size: DpSize = ApplicationSize.currentConversion of a ByteArray to an androidx.compose.ui.graphics.ImageBitmap.
val content = byteArrayOf()
val bitmap = content.asImageBitmap()ArcShape for creating arcs.
Converting hexadecimal colors in ARGB or RGB string format (with optional # prefix) to androidx.compose.ui.graphics.Color.
val color = Hex("3dab5a").color()
val hex = color.hex()Converter for the com.bselzer.ktx.intl.Locale to androidx.compose.ui.text.intl.Locale.
LocalLocale composition local that can be provided by the following in order to recompose on Localizer.locale changes:
@Composable
fun Content() {
ProvideLocale {
val locale = LocalLocale.current
// ...
}
}Wrappers and custom composable components using the content/presentation model and projection concept as described by kirill-grouchnikov's Aurora project.
The common module contains wrappers for official components. The custom module contains completely custom components or special wrappers for official components.
See the compose-layout file for documentation on the custom components provided.
AnnotatedString and SpanStyle extensions.
Pixel to Dp and Dp to pixel conversions.
val dp = 50f.toDp()
val pixel = dp.toPx()Managing locks by a key:
val lock = LockByKey<Int>()
lock.withLock(1) {
// Perform
}val patternFormatter = PatternDateTimeFormatter("EEEE")
val timeFormatter = FormatStyleDateTimeFormatter(dateStyle = null, timeStyle = FormatStyle.SHORT)General Kotlin standard library extensions.
enum class Position {
FIRST, SECOND
}
val userFriendly: String = Position.FIRST.userFriendly()
val first: Position = "FIRST".enumValue<Position>()
val items: Array<Position> = buildArray {
add(Position.FIRST)
add(Position.SECOND)
}
val bytes = "AdsnAAA=".decodeBase64ToByteArray()
val string = bytes.encodeBase64ToString()Two and three dimensional geometrical objects.
Two dimensional objects include a digon, quadrilateral, 2D point, 2D size. Three dimensional objects include a 3D point.
Serializers for two and three dimensional geometrical objects using kotlinx.serialization.
Based on Android intents. Currently supports browser opening and mailto.
Browser.open("https://google.com")
Emailer.send(
email = Email(
to = listOf("foo@bar.com", "fizz@buzz.com"),
cc = listOf("test@test.com"),
bcc = listOf("bar@baz.com", "test@test.com"),
subject = "This is a test subject.",
body = "This is a test body."
)
)Internationalization through locale support.
com.bselzer.ktx.intl.Locale is added as a non-composable way to handle locale changes. However, it can be converted to androidx.compose.ui.text.intl.Locale. See the compose section.
DefaultLocale provides the system's default locale. However, there is no ability to be notified of changes to this locale. Instead, a Localizer should be used to maintain an instance of a locale and to be able to be notified of changes by adding a listener which can then be used to update the DefaultLocale if needed.
Serializer for the com.bselzer.ktx.intl.Locale using kotlinx.serialization.
Kodein-DB extensions.
Note that Kodein-DB is currently archived but may return under a new name.
If you would still like to use it, then apply the following:
val version = "0.9.0-beta"
// For applications
implementation("org.kodein.db:kodein-db:$version")
// For libraries
implementation("org.kodein.db:kodein-db-api:$version")
// kotlinx.serialization
implementation("org.kodein.db:kodein-db-serializer-kotlinx:$version")
// Desktop LevelDB native build depending on OS
implementation("org.kodein.db:kodein-leveldb-jni-jvm-linux:$version")
implementation("org.kodein.db:kodein-leveldb-jni-jvm-macos:$version")
implementation("org.kodein.db:kodein-leveldb-jni-jvm-windows:$version")The fully intact documentation can be found in commit 0f310b317920fbbea56d5dc81a9049a072aaa435.
IdentifiableMetadataExtractor for Identifiable objects from the value module to use the identifier's value as the metadata.IdentifierValueConverter for using an Identifier.value as a Value if it is for an Int, Long, or String.DBTransaction for managing reading and writing a batch to a DB instance
Identifiable models based on given idsIdentifiable model with a given id or requesting it if it does not existIdentifiable models based on given ids and then requesting those missing to be put into the DB
Client side Ktor extensions.
GenericTypeInfo for enforcing the type of the reified usage of TypeInfo creation.UrlOptions can be used to merge url based options and to replace path parameters.Connectivity for determining if an active connection is able to be establishedLogging wrapper around Napier.
moko-resources extensions.
org.jetbrains.compose.material:material-icons-extended-desktop.Resources are generated with the name KtxResources:
val days = KtxResources.strings.dayskotlinx.serialization core extensions.
StringFormatContext:@SerialName associated with the enum, which is different from the function conversion that would compare the name of the enum instead.enum class LegendName {
@SerialName("Legend1")
DRAGON,
}
with(JsonContext) {
val legend: LegendName = "Legend1".decode() // LegendName.DRAGON
val nullableLegend: LegendName? = "Legend2".decodeOrNull() // Null
}Array merging:
Null merging:
IntegerSerializer for lenient integer parsing as a string or numeric
kotlinx.serialization json extensions.
JsonContext which extends from StringFormatContext
JsonElements.DelimitedListSerializer for converting a delimited string into a list.xmlutil extensions.
XmlContext which extends from StringFormatContext
LoggingUnknownChildHandler for XML deserialization that will log the failed deserialization of a child not defined in your object instead of throwing an exceptionyamlkt extensions
YamlContext which extends from StringFormatContext
YamlElements.Extensions for converting a YamlElement from yamlkt to a JsonElement from kotlinx.serialization and vice versa.
Async wrapper of primitive and serializable multiplatform-settings settings.
Identifier counterparts from the value module.SerializableSetting by providing the serializer associated with the object, and for the Duration class.fun lastRefresh(settings: SuspendSettings): Setting<Instant> {
return SerializableSetting(
settings = settings,
key = "LastRefresh",
defaultValue = Instant.DISTANT_FUTURE,
serializer = serializer()
)
}These wrappers must provide an instance of SuspendSettings, a key, and a default value to use when the preference is not set.
When calling get() or observe(), this default value will be used as the default instead of null.
| Method | Purpose |
|---|---|
| get | Gets the value of the preference or the default value if it does not exist. |
| getOrNull | Gets the value of the preference or null if it does not exist. |
| set | Sets the value of preference and notifies observers about the change. |
| remove | Removes the value of the preference and notifies observers about the change. |
| exists | Used to determine if the preference has been initialized. |
| initialize | Only sets a value if the preference has not been set. |
| observe | Creates a callback flow that listens to preference changes. Uses the default value if the preference does not exist. |
| observeOrNull | Creates a callback flow that listens to preference changes. Uses null if the preference does not exist. |
Value classes for wrapping an enumeration.
The StringEnum class:
Value classes for an Identifier wrapping a Byte, Boolean, Double, Float, Int, Long, Short, or String.
The Identifiable interface can be used to specify an Identifier id.
@JvmInline
value class LuckId(override val value: String = "") : StringIdentifier {
override fun toString(): String = value
}
data class AccountLuck(
override val id: LuckId = LuckId(),
val value: Int = 0
) : Identifiable<LuckId, String>Kotlin Multiplatform extensions and implementations for the Kotlin standard library and third-party libraries.
Published to Maven Central.
repositories {
mavenCentral()
}implementation("io.github.woody230.ktx:$Module:$Version")Extensions for AboutLibraries. See compose-aboutlibraries for the associated composable.
Compose Multiplatform is the compose version used by this project to support both Android and the JVM.
New to Compose?
compose-multiplatform composable for AboutLibraries
@Composable
fun Libraries(libraries: List<Library>) = LibraryProjector(
interactor = LibraryInteractor(
libraries = libraries
)
).Projection()Using the AssetReader from the resource module, you can use the libraries output from AboutLibraries as a moko-resource asset.
First, you will need to add the following to gradle in order to copy it as a resource.
val aboutLibrariesResource = task("aboutLibrariesResource") {
dependsOn("exportLibraryDefinitions")
copy {
from("$buildDir\\generated\\aboutLibraries") {
include("aboutlibraries.json")
}
into("$projectDir\\src\\commonMain\\resources\\MR\\assets")
}
}
tasks.whenTaskAdded {
if (name == "generateMRcommonMain") {
dependsOn(aboutLibrariesResource)
}
}Now you can use the AssetReader to read the resource and create the libraries from it.
val libraries = with(AssetReader) {
val content = MyResources.assets.aboutlibraries.readText()
Libs.Builder().withJson(content).build().libraries
}A copy of Accompanist modules (v0.23.1 and v0.2.1 Snapper) with multiplatform capability. Currently this only includes the pager and pager indicators.
A copy of ConstraintLayout (v2.1.3 core and v1.0.0 compose) with multiplatform capability.
Wrappers for strings and images for the compose module using the resource module.
Conversion of image moko-resources:
val painter = MyResources.images.my_resource.painter()
val localized = MyResources.strings.my_resource.localized()Standardized AlertDialog buttons:
val withConfirmation = AlertDialogInteractor.Builder().uniText().build()
val withConfirmationCancel = AlertDialogInteractor.Builder().biText().build()
val withConfirmationCancelReset = AlertDialogInteractor.Builder().triText().build()IconInteractor wrappers for common use cases such as:
val delete = deleteIconInteractor()
val language = languageIconInteractor()
val settings = settingsIconInteractor()Conversion of text moko-resources:
val text = MyResources.strings.my_resource.textInteractor()kotlinx.serialization extensions for compose related classes.
ColorSerializer for storing the Hex associated with a androidx.compose.ui.graphics.Color
Setting to compose-multiplatform state converters.
@Composable
fun Observe(setting: Setting<Instant>, nullableSetting: Setting<Instant?>) {
val defaulted: MutableState<Instant> = setting.safeState()
val nullable: MutableState<Instant?> = setting.nullState()
// Keep the ability to be nullable, but the value will be defaulted and not null.
val defaultedNullable: MutableState<Instant?> = nullableSetting.defaultState()
}ColorSetting for androidx.compose.ui.graphics.Color.
fun color(settings: SuspendSettings): Setting<Color> = ColorSetting(
settings = settings,
key = "Color",
defaultValue = Color.Blue
)The ShowAlert() composable method is used to send notifications.
@Composable
fun SendMessage() = ShowAlert(title = "Important!", "An error occurred.", type = AlertType.ERROR)The ApplicationSize companion object can be used to get the current size of the Android device or desktop window size.
val size: DpSize = ApplicationSize.currentConversion of a ByteArray to an androidx.compose.ui.graphics.ImageBitmap.
val content = byteArrayOf()
val bitmap = content.asImageBitmap()ArcShape for creating arcs.
Converting hexadecimal colors in ARGB or RGB string format (with optional # prefix) to androidx.compose.ui.graphics.Color.
val color = Hex("3dab5a").color()
val hex = color.hex()Converter for the com.bselzer.ktx.intl.Locale to androidx.compose.ui.text.intl.Locale.
LocalLocale composition local that can be provided by the following in order to recompose on Localizer.locale changes:
@Composable
fun Content() {
ProvideLocale {
val locale = LocalLocale.current
// ...
}
}Wrappers and custom composable components using the content/presentation model and projection concept as described by kirill-grouchnikov's Aurora project.
The common module contains wrappers for official components. The custom module contains completely custom components or special wrappers for official components.
See the compose-layout file for documentation on the custom components provided.
AnnotatedString and SpanStyle extensions.
Pixel to Dp and Dp to pixel conversions.
val dp = 50f.toDp()
val pixel = dp.toPx()Managing locks by a key:
val lock = LockByKey<Int>()
lock.withLock(1) {
// Perform
}val patternFormatter = PatternDateTimeFormatter("EEEE")
val timeFormatter = FormatStyleDateTimeFormatter(dateStyle = null, timeStyle = FormatStyle.SHORT)General Kotlin standard library extensions.
enum class Position {
FIRST, SECOND
}
val userFriendly: String = Position.FIRST.userFriendly()
val first: Position = "FIRST".enumValue<Position>()
val items: Array<Position> = buildArray {
add(Position.FIRST)
add(Position.SECOND)
}
val bytes = "AdsnAAA=".decodeBase64ToByteArray()
val string = bytes.encodeBase64ToString()Two and three dimensional geometrical objects.
Two dimensional objects include a digon, quadrilateral, 2D point, 2D size. Three dimensional objects include a 3D point.
Serializers for two and three dimensional geometrical objects using kotlinx.serialization.
Based on Android intents. Currently supports browser opening and mailto.
Browser.open("https://google.com")
Emailer.send(
email = Email(
to = listOf("foo@bar.com", "fizz@buzz.com"),
cc = listOf("test@test.com"),
bcc = listOf("bar@baz.com", "test@test.com"),
subject = "This is a test subject.",
body = "This is a test body."
)
)Internationalization through locale support.
com.bselzer.ktx.intl.Locale is added as a non-composable way to handle locale changes. However, it can be converted to androidx.compose.ui.text.intl.Locale. See the compose section.
DefaultLocale provides the system's default locale. However, there is no ability to be notified of changes to this locale. Instead, a Localizer should be used to maintain an instance of a locale and to be able to be notified of changes by adding a listener which can then be used to update the DefaultLocale if needed.
Serializer for the com.bselzer.ktx.intl.Locale using kotlinx.serialization.
Kodein-DB extensions.
Note that Kodein-DB is currently archived but may return under a new name.
If you would still like to use it, then apply the following:
val version = "0.9.0-beta"
// For applications
implementation("org.kodein.db:kodein-db:$version")
// For libraries
implementation("org.kodein.db:kodein-db-api:$version")
// kotlinx.serialization
implementation("org.kodein.db:kodein-db-serializer-kotlinx:$version")
// Desktop LevelDB native build depending on OS
implementation("org.kodein.db:kodein-leveldb-jni-jvm-linux:$version")
implementation("org.kodein.db:kodein-leveldb-jni-jvm-macos:$version")
implementation("org.kodein.db:kodein-leveldb-jni-jvm-windows:$version")The fully intact documentation can be found in commit 0f310b317920fbbea56d5dc81a9049a072aaa435.
IdentifiableMetadataExtractor for Identifiable objects from the value module to use the identifier's value as the metadata.IdentifierValueConverter for using an Identifier.value as a Value if it is for an Int, Long, or String.DBTransaction for managing reading and writing a batch to a DB instance
Identifiable models based on given idsIdentifiable model with a given id or requesting it if it does not existIdentifiable models based on given ids and then requesting those missing to be put into the DB
Client side Ktor extensions.
GenericTypeInfo for enforcing the type of the reified usage of TypeInfo creation.UrlOptions can be used to merge url based options and to replace path parameters.Connectivity for determining if an active connection is able to be establishedLogging wrapper around Napier.
moko-resources extensions.
org.jetbrains.compose.material:material-icons-extended-desktop.Resources are generated with the name KtxResources:
val days = KtxResources.strings.dayskotlinx.serialization core extensions.
StringFormatContext:@SerialName associated with the enum, which is different from the function conversion that would compare the name of the enum instead.enum class LegendName {
@SerialName("Legend1")
DRAGON,
}
with(JsonContext) {
val legend: LegendName = "Legend1".decode() // LegendName.DRAGON
val nullableLegend: LegendName? = "Legend2".decodeOrNull() // Null
}Array merging:
Null merging:
IntegerSerializer for lenient integer parsing as a string or numeric
kotlinx.serialization json extensions.
JsonContext which extends from StringFormatContext
JsonElements.DelimitedListSerializer for converting a delimited string into a list.xmlutil extensions.
XmlContext which extends from StringFormatContext
LoggingUnknownChildHandler for XML deserialization that will log the failed deserialization of a child not defined in your object instead of throwing an exceptionyamlkt extensions
YamlContext which extends from StringFormatContext
YamlElements.Extensions for converting a YamlElement from yamlkt to a JsonElement from kotlinx.serialization and vice versa.
Async wrapper of primitive and serializable multiplatform-settings settings.
Identifier counterparts from the value module.SerializableSetting by providing the serializer associated with the object, and for the Duration class.fun lastRefresh(settings: SuspendSettings): Setting<Instant> {
return SerializableSetting(
settings = settings,
key = "LastRefresh",
defaultValue = Instant.DISTANT_FUTURE,
serializer = serializer()
)
}These wrappers must provide an instance of SuspendSettings, a key, and a default value to use when the preference is not set.
When calling get() or observe(), this default value will be used as the default instead of null.
| Method | Purpose |
|---|---|
| get | Gets the value of the preference or the default value if it does not exist. |
| getOrNull | Gets the value of the preference or null if it does not exist. |
| set | Sets the value of preference and notifies observers about the change. |
| remove | Removes the value of the preference and notifies observers about the change. |
| exists | Used to determine if the preference has been initialized. |
| initialize | Only sets a value if the preference has not been set. |
| observe | Creates a callback flow that listens to preference changes. Uses the default value if the preference does not exist. |
| observeOrNull | Creates a callback flow that listens to preference changes. Uses null if the preference does not exist. |
Value classes for wrapping an enumeration.
The StringEnum class:
Value classes for an Identifier wrapping a Byte, Boolean, Double, Float, Int, Long, Short, or String.
The Identifiable interface can be used to specify an Identifier id.
@JvmInline
value class LuckId(override val value: String = "") : StringIdentifier {
override fun toString(): String = value
}
data class AccountLuck(
override val id: LuckId = LuckId(),
val value: Int = 0
) : Identifiable<LuckId, String>