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", )