diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 6ffbeb8..4cec74a 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -3,9 +3,11 @@ name: CI
on:
push:
branches: [main]
- # Release tag format is [module-name]-v[androidx-version]-[ktx-version]
- # For example: fragment-ktx-v1.3.5-0
- tags: ['*-ktx-v*-[0-9]+']
+ # Release tag format is [module-name]-[namespace-name]-v[version]-[sub-version]
+ # For example: fragment-ktx-v1.3.5-0, compose-gears-v.1.1.1-1
+ tags:
+ - '*-ktx-v*-[0-9]+'
+ - '*-gears-v*-[0-9]+'
pull_request:
branches: [main]
@@ -34,7 +36,7 @@ jobs:
run: ./gradlew detektAll detektReleaseAll
publish:
- name: Publish KTX
+ name: Publish gears
needs: check
runs-on: ubuntu-latest
if: ${{ startsWith(github.ref, 'refs/tags/') }}
@@ -49,17 +51,24 @@ jobs:
distribution: 'temurin'
java-version: 17
- - name: Get module name from tag
- id: get-module-name
+ - name: Get namespace and module name from tag
+ id: parse-tag
run: |
tag=${GITHUB_REF#refs/tags/}
- echo "result=${tag/-v*}" >> "$GITHUB_OUTPUT"
+ module=$(echo "${tag%-*-v*}")
+ namespace=$(echo "${tag/-v*}" | rev | cut -d '-' -f 1 | rev)
+ echo "module=$module" >> "$GITHUB_OUTPUT"
+ echo "namespace=$namespace" >> "$GITHUB_OUTPUT"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
- name: Run Publish
- run: ./gradlew :ktx:${{ steps.get-module-name.outputs.result }}:publish
+ run: ./gradlew :${{ steps.parse-tag.outputs.namespace }}:${{ steps.parse-tag.outputs.module }}:publish
env:
+ ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_USERNAME }}
+ ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_PASSWORD }}
+ ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_KEY }}
+ ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_KEY_PASSWORD }}
ORG_GRADLE_PROJECT_githubPackagesUsername: ${{ github.actor }}
ORG_GRADLE_PROJECT_githubPackagesPassword: ${{ secrets.GITHUB_TOKEN }}
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 7675dc5..444e72f 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -14,6 +14,7 @@ java {
dependencies {
implementation(rmr.infrastructure.publish)
implementation(rmr.infrastructure.android)
+ implementation(libs.publish.gradlePlugin)
implementation(stack.gradle.android.cacheFixGradlePlugin)
implementation(stack.kotlin.gradlePlugin)
implementation(stack.detekt.gradlePlugin)
diff --git a/buildSrc/src/main/kotlin/convention.library.kotlin.gradle.kts b/buildSrc/src/main/kotlin/convention.library.kotlin.gradle.kts
new file mode 100644
index 0000000..ff378c7
--- /dev/null
+++ b/buildSrc/src/main/kotlin/convention.library.kotlin.gradle.kts
@@ -0,0 +1,5 @@
+plugins {
+ id("com.redmadrobot.kotlin-library")
+ id("convention.publishing")
+ id("convention.detekt")
+}
diff --git a/buildSrc/src/main/kotlin/convention.publishing.gradle.kts b/buildSrc/src/main/kotlin/convention.publishing.gradle.kts
index 5c0bcd6..a3d37a7 100644
--- a/buildSrc/src/main/kotlin/convention.publishing.gradle.kts
+++ b/buildSrc/src/main/kotlin/convention.publishing.gradle.kts
@@ -1,31 +1,33 @@
import com.redmadrobot.build.dsl.*
+import com.vanniktech.maven.publish.SonatypeHost
plugins {
- id("com.redmadrobot.publish-config")
- id("com.redmadrobot.publish")
+ id("com.vanniktech.maven.publish")
}
-redmadrobot {
- publishing {
- signArtifacts = !isRunningOnCi
- pom {
- setGitHubProject("RedMadRobot/gears-android")
+mavenPublishing {
+ publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL, automaticRelease = true)
+ signAllPublications()
- licenses {
- mit()
- }
+ pom {
+ name.convention(project.name)
+ description.convention(project.description)
- developers {
- developer(id = "osipxd", name = "Osip Fatkullin", email = "o.fatkullin@redmadrobot.com")
- developer(id = "sonulen", name = "Andrey Tolmachev", email = "a.tolmachev@redmadrobot.com")
- }
+ licenses {
+ mit()
}
+
+ developers {
+ developer(id = "osipxd", name = "Osip Fatkullin", email = "o.fatkullin@redmadrobot.com")
+ developer(id = "sonulen", name = "Andrey Tolmachev", email = "a.tolmachev@redmadrobot.com")
+ }
+
+ setGitHubProject("RedMadRobot/gears-android")
}
}
publishing {
repositories {
if (isRunningOnCi) githubPackages("RedMadRobot/gears-android")
- if (isReleaseVersion && credentialsExist("ossrh")) ossrh()
}
}
diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml
index 2cfad52..d6ec68b 100644
--- a/config/detekt/detekt.yml
+++ b/config/detekt/detekt.yml
@@ -433,6 +433,7 @@ naming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
functionPattern: '([a-z][a-zA-Z0-9]*)|(`.*`)'
+ ignoreAnnotated: ['Composable']
excludeClassPattern: '$^'
FunctionParameterNaming:
active: true
diff --git a/gears/build.gradle.kts b/gears/build.gradle.kts
new file mode 100644
index 0000000..0673c51
--- /dev/null
+++ b/gears/build.gradle.kts
@@ -0,0 +1,3 @@
+// For some reason gradle.properties in this project doesn't affect its subprojects
+val gearsGroup = group
+subprojects { group = gearsGroup }
diff --git a/gears/gears-compose/CHANGELOG.md b/gears/gears-compose/CHANGELOG.md
new file mode 100644
index 0000000..80889f1
--- /dev/null
+++ b/gears/gears-compose/CHANGELOG.md
@@ -0,0 +1,5 @@
+## Unreleased
+
+### Added
+
+- `FixedFontScaleContainer` - A container that fixes the font scale, ignoring values that are set in the phone's system settings
diff --git a/gears/gears-compose/README.md b/gears/gears-compose/README.md
new file mode 100644
index 0000000..f196eeb
--- /dev/null
+++ b/gears/gears-compose/README.md
@@ -0,0 +1,53 @@
+# compose
+[![Version](https://img.shields.io/maven-central/v/com.redmadrobot.gears/gears-compose?style=flat-square)][mavenCentral]
+[![License](https://img.shields.io/github/license/RedMadRobot/gears-android?style=flat-square)][license]
+
+---
+
+
+
+- [Installation](#installation)
+- [Usage](#usage)
+- [Contributing](#contributing)
+
+
+
+A set of gears for compose.
+
+## Installation
+
+Add the dependency:
+```groovy
+repositories {
+ mavenCentral()
+ google()
+}
+
+dependencies {
+ implementation("com.redmadrobot.gears:gears-compose:")
+}
+```
+
+
+The library was developed and tested using:
+
+> - `compose-runtime` [1.6.5](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.6.5)
+> - `compose-ui` [1.6.5](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.6.5)
+
+> [!NOTE]
+> These dependencies will be transiently included in your project.
+
+## Usage
+
+| Gear | Description |
+|:--------------------|:-----------|
+| `FixedFontScaleContainer` | A container that fixes the font scale, ignoring values, that are set in the phone's system settings |
+
+## Contributing
+
+Merge requests are welcome.
+For major changes, please open an issue first to discuss what you would like to change.
+
+
+[mavenCentral]: https://search.maven.org/artifact/com.redmadrobot.gears/compose
+[license]: ../LICENSE
diff --git a/gears/gears-compose/build.gradle.kts b/gears/gears-compose/build.gradle.kts
new file mode 100644
index 0000000..124121e
--- /dev/null
+++ b/gears/gears-compose/build.gradle.kts
@@ -0,0 +1,27 @@
+plugins {
+ convention.library.android
+}
+
+version = "0.1.0"
+description = "A set of gears for compose"
+
+redmadrobot {
+ android.minSdk = 21
+}
+
+android {
+ namespace = "$group.compose"
+
+ buildFeatures {
+ compose = true
+ }
+
+ composeOptions {
+ kotlinCompilerExtensionVersion = androidx.versions.compose.compiler.get()
+ }
+}
+
+dependencies {
+ api(androidx.compose.ui)
+ api(androidx.compose.runtime)
+}
diff --git a/gears/gears-compose/src/main/kotlin/FixedFontScaleContainer.kt b/gears/gears-compose/src/main/kotlin/FixedFontScaleContainer.kt
new file mode 100644
index 0000000..95acc20
--- /dev/null
+++ b/gears/gears-compose/src/main/kotlin/FixedFontScaleContainer.kt
@@ -0,0 +1,43 @@
+package com.redmadrobot.extensions.compose
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.unit.Density
+
+/**
+ * A container that fixes the font scale, ignoring values,
+ * that are set in the phone's system settings
+ */
+@Composable
+public fun FixedFontScaleContainer(
+ content: @Composable () -> Unit,
+) {
+ val fixedFontScaleDensity = Density(LocalDensity.current.density)
+ CompositionLocalProvider(
+ LocalDensity provides fixedFontScaleDensity,
+ content = content,
+ )
+}
+
+/**
+ * A container that restricts the font scale, ignoring values,
+ * that are set in the phone's system settings
+ *
+ * @param limit - the upper limit of font enlargement
+ */
+@Composable
+public fun LimitedFontScaleContainer(
+ limit: Float,
+ content: @Composable () -> Unit,
+) {
+ val fontScale = LocalDensity.current.fontScale.coerceAtMost(limit)
+ val fixedFontScaleDensity = Density(
+ density = LocalDensity.current.density,
+ fontScale = fontScale,
+ )
+ CompositionLocalProvider(
+ LocalDensity provides fixedFontScaleDensity,
+ content = content,
+ )
+}
diff --git a/gears/gears-kotlin/CHANGELOG.md b/gears/gears-kotlin/CHANGELOG.md
new file mode 100644
index 0000000..6ef2c80
--- /dev/null
+++ b/gears/gears-kotlin/CHANGELOG.md
@@ -0,0 +1,6 @@
+## Unreleased
+
+### Added
+
+- `T.applyIf` - Applies the given block of modifications to the T if the condition is true
+- `T.applyIfNotNull` - Applies the given block of modifications to the T if the value is not null
diff --git a/gears/gears-kotlin/README.md b/gears/gears-kotlin/README.md
new file mode 100644
index 0000000..753971e
--- /dev/null
+++ b/gears/gears-kotlin/README.md
@@ -0,0 +1,52 @@
+# kotlin
+[![Version](https://img.shields.io/maven-central/v/com.redmadrobot.gears/kotlin?style=flat-square)][mavenCentral]
+[![License](https://img.shields.io/github/license/RedMadRobot/gears-android?style=flat-square)][license]
+
+---
+
+
+
+- [Installation](#installation)
+- [Usage](#usage)
+- [Contributing](#contributing)
+
+
+
+A set of gears for kotlin.
+
+## Installation
+
+Add the dependency:
+```groovy
+repositories {
+ mavenCentral()
+ google()
+}
+
+dependencies {
+ implementation("com.redmadrobot.gears:gears-kotlin:")
+}
+```
+
+The library was developed and tested using:
+
+> - `kotlin` [1.9.23](https://github.com/JetBrains/kotlin/releases/tag/v1.9.23)
+
+> [!NOTE]
+> These dependencies will be transiently included in your project.
+
+## Usage
+
+| Gear | Description |
+|:-----------------------|:---------------------------------------------------------------------------------------------|
+| `T.applyIf` | Applies the given block of modifications to the T if the condition is true |
+| `T.applyIfNotNull` | Applies the given block of modifications to the T if the value is not null |
+
+## Contributing
+
+Merge requests are welcome.
+For major changes, please open an issue first to discuss what you would like to change.
+
+
+[mavenCentral]: https://search.maven.org/artifact/com.redmadrobot.gears/gears-kotlin
+[license]: ../LICENSE
diff --git a/gears/gears-kotlin/build.gradle.kts b/gears/gears-kotlin/build.gradle.kts
new file mode 100644
index 0000000..9feb1c7
--- /dev/null
+++ b/gears/gears-kotlin/build.gradle.kts
@@ -0,0 +1,10 @@
+plugins {
+ convention.library.kotlin
+}
+
+version = "0.1.0"
+description = "A set of gears for kotlin"
+
+dependencies {
+ api(kotlin("stdlib"))
+}
diff --git a/gears/gears-kotlin/src/main/kotlin/ApplyIf.kt b/gears/gears-kotlin/src/main/kotlin/ApplyIf.kt
new file mode 100644
index 0000000..763624e
--- /dev/null
+++ b/gears/gears-kotlin/src/main/kotlin/ApplyIf.kt
@@ -0,0 +1,19 @@
+package com.redmadrobot.gears.kotlin
+
+/**
+ * Calls the specified function [block] with [this] value as its receiver if the [condition] is `true`
+ * and returns its result.
+ */
+public inline fun T.applyIf(
+ condition: Boolean,
+ block: T.() -> T,
+): T = if (condition) block() else this
+
+/**
+ * Calls the specified function [block] with [this] value as its receiver if the [value] is not null
+ * and returns its result.
+ */
+public inline fun T.applyIfNotNull(
+ value: P?,
+ block: T.(P) -> T
+): T = if (value != null) block(value) else this
diff --git a/gears/gradle.properties b/gears/gradle.properties
new file mode 100644
index 0000000..4f66e6a
--- /dev/null
+++ b/gears/gradle.properties
@@ -0,0 +1 @@
+group=com.redmadrobot.gears
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index b23be7a..1302371 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,11 +1,13 @@
[versions]
-androidGradlePlugin = "8.4.0"
+androidGradlePlugin = "8.4.1"
assertj-core = "3.25.1"
androidx-arch-core = "2.2.0"
-viewbinding = "8.4.0"
+viewbinding = "8.4.1"
+publish-plugin = "0.28.0"
[libraries]
androidx-viewbinding = { module = "androidx.databinding:viewbinding", version.ref = "viewbinding" }
assertj-core = { module = "org.assertj:assertj-core", version.ref = "assertj-core" }
androidx-arch-core-testing = { module = "androidx.arch.core:core-testing", version.ref = "androidx-arch-core"}
android-gradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "androidGradlePlugin" }
+publish-gradlePlugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version.ref = "publish-plugin" }
diff --git a/settings.gradle.kts b/settings.gradle.kts
index ea870e8..d66aa98 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -34,4 +34,6 @@ include(
":ktx:lifecycle-livedata-ktx",
":ktx:resources-ktx",
":ktx:viewbinding-ktx",
+ ":gears:gears-compose",
+ ":gears:gears-kotlin",
)