Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 41 additions & 26 deletions .github/workflows/deployment.yml
Original file line number Diff line number Diff line change
@@ -1,41 +1,56 @@
name: Release - Deployment
name: Publish to Maven Central

on:
workflow_dispatch:
push:
tags:
- release.*
- 'release.[0-9]+.[0-9]+.[0-9]+'

jobs:
deploy:
name: Deployment
runs-on: [ Linux ]
env:
ARTIFACTORY_URL: ${{secrets.MUDITA_ARTIFACTORY_OUTPUT_URL}}
ARTIFACTORY_USERNAME: ${{secrets.MUDITA_ARTIFACTORY_USERNAME}}
ARTIFACTORY_PASSWORD: ${{secrets.MUDITA_ARTIFACTORY_PASSWORD}}
publish:
runs-on: ubuntu-latest

steps:
- name: Checkout
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 100

- name: Set up JDK 17
uses: actions/setup-java@v1
uses: actions/setup-java@v4
with:
java-version: 17
java-version: '17'
distribution: 'temurin'

- name: Validate version consistency
run: |
TAG_VERSION=${GITHUB_REF#refs/tags/release.}
GRADLE_VERSION=$(grep "library.version=" gradle.properties | cut -d'=' -f2)

echo "Tag version: $TAG_VERSION"
echo "Gradle version: $GRADLE_VERSION"

if [ "$TAG_VERSION" != "$GRADLE_VERSION" ]; then
echo "Error: Tag version ($TAG_VERSION) doesn't match gradle.properties version ($GRADLE_VERSION)"
exit 1
fi

echo "Version consistency validated"

- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Build release
run: ./gradlew assembleRelease --no-daemon --stacktrace

- name: Lint kotlin check
timeout-minutes: 5
run: ./gradlew ktlintCheck
- name: Create signing key file
run: echo "${{ secrets.SIGNING_KEY }}" | base64 -d > secring.gpg

- name: Full build
timeout-minutes: 5
run: ./gradlew clean build
- name: Publish to Maven Central
env:
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
ORG_GRADLE_PROJECT_signing.keyId: ${{ secrets.SIGNING_KEY_ID }}
ORG_GRADLE_PROJECT_signing.password: ${{ secrets.SIGNING_PASSWORD }}
run: ./gradlew publishToMavenCentral --no-daemon --stacktrace

- name: Deploy artifactory
timeout-minutes: 5
run: ./gradlew publish
- name: Clean up
if: always()
run: rm -f secring.gpg
2 changes: 1 addition & 1 deletion .github/workflows/library-bump.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ on:
jobs:
check:
name: Check Version Bump
runs-on: [ Linux ]
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'

steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pull-request-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ on:
jobs:
test:
name: Lint - Android
runs-on: [ Linux ]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ google-services.json
*.hprof

.DS_Store

secring.gpg
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Mudita Mindful Design (MMD)

A UI component library optimized for e‑ink displays on Android, built on top of Jetpack Compose Material 3 guidelines and classes. Our goal is to provide a consistent, predictable set of components that respects Material Design while addressing the specifics of e‑ink displays.
A UI component library optimized for E Ink® displays on Android, built on top of Jetpack Compose Material 3 guidelines and classes. Our goal is to provide a consistent, predictable set of components that respects Material Design while addressing the specifics of E Ink® displays.

> We intentionally rely on Material Design (Material 3) classes and patterns. This is by design and a good practice. It keeps us aligned with the Android ecosystem while adapting behavior and styling to e‑ink.
> We intentionally rely on Material Design (Material 3) classes and patterns. This is by design and a good practice. It keeps us aligned with the Android ecosystem while adapting behavior and styling to E Ink®.

## Why e‑ink?
E‑ink displays differ from standard LCD/OLED:
## Why E Ink®?
E Ink® displays differ from standard LCD/OLED:
- slower refresh rates and potential ghosting/afterimage,
- limited color palette (often grayscale),
- great daylight readability with low power consumption,
Expand All @@ -14,9 +14,9 @@ E‑ink displays differ from standard LCD/OLED:
MMD minimizes flicker, reduces unnecessary animations, and simplifies color and typography to make the UI readable and energy‑efficient.

## Features
- **E‑ink optimized**: default color scheme, typography, and interaction patterns for e‑ink.
- **E Ink® optimized**: default color scheme, typography, and interaction patterns for E Ink®.
- **Material Design 3‑based**: integration with `MaterialTheme` and compatibility with M3 components.
- **Ripple disabled**: ripple effects are turned off by default for better UX on e‑ink.
- **Ripple disabled**: ripple effects are turned off by default for better UX on E Ink®.
- **Consistent typography**: ready‑to‑use `eInkTypography` and `eInkColorScheme` (monochromatic).
- **Component set**: buttons, text fields, switches, tabs, app bars, and more.

Expand All @@ -28,7 +28,7 @@ dependencies {
```

## Configuration and theming
Enable the MMD theme in your Compose tree. By default, it applies an e‑ink‑friendly color scheme and typography and disables ripple effects globally.
Enable the MMD theme in your Compose tree. By default, it applies an E Ink®‑friendly color scheme and typography and disables ripple effects globally.

```kotlin
import com.mudita.mmd.components.buttons.ButtonMMD
Expand All @@ -39,14 +39,14 @@ import com.mudita.mmd.ThemeMMD
fun App() {
ThemeMMD {
ButtonMMD(onClick = { /* ... */ }) {
TextMMD("Hello e‑ink")
TextMMD("Hello E Ink®")
}
}
}
```

## Using components
MMD works well with both Material 3 components and MMD‑provided components. Use our components where they bring e‑ink optimizations; otherwise, standard M3 components will remain consistent via theming.
MMD works well with both Material 3 components and MMD‑provided components. Use our components where they bring E Ink® optimizations; otherwise, standard M3 components will remain consistent via theming.

```kotlin
import com.mudita.mmd.components.buttons.ButtonMMD
Expand All @@ -63,11 +63,11 @@ fun Screen() {
> Component names may vary by module and version. Explore `com.mudita.mmd.components.*` in your IDE for the full list and API.

## Accessibility and readability
- contrast and font sizes tuned for e‑ink,
- contrast and font sizes tuned for E Ink®,
- avoid animations/effects that reduce readability,
- utilities to support accessibility (e.g., unified text styles).

## Performance on e‑ink – best practices
## Performance on E Ink® – best practices
- limit animations, auto‑refresh, and fancy transitions,
- avoid frequent state changes leading to redraws,
- prefer monochrome graphics and simple shapes,
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ library.namespace=com.mudita.mmd
library.compileSdk=34
library.minSdk=28
library.targetSdk=34
library.version=1.0.0
library.version=1.0.1
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ compose = "1.7.3"
material3 = "1.3.1"
activity-compose = "1.10.1"
dokka = "2.0.0"
maven = "0.34.0"

[libraries]
ktlint = { module = "org.jlleitschuh.gradle:ktlint-gradle", version.ref = "ktlint" }
Expand All @@ -23,3 +24,4 @@ kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref
compose = { id = "org.jetbrains.compose", version.ref = "compose" }
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
maven-publish = {id = "com.vanniktech.maven.publish", version.ref = "maven" }
63 changes: 53 additions & 10 deletions mmd-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,53 @@ plugins {
alias(libs.plugins.compose)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.dokka)
`maven-publish`
alias(libs.plugins.maven.publish)
id("signing")
}

group = properties["library.group"].toString()
version =
run {
System.getenv("GITHUB_REF_NAME")?.removePrefix("release.")
?: properties["library.version"].toString()
}

kotlin {
androidTarget {
mavenPublication {
artifactId = properties["library.artifactId"].toString()
mavenPublishing {
publishToMavenCentral()
signAllPublications()

coordinates(
groupId = properties["library.group"].toString(),
artifactId = properties["library.artifactId"].toString(),
version = properties["library.version"].toString()
)

pom {
name.set("Mudita MMD Library")
description.set(
"A UI component library optimized for e‑ink displays on Android, " +
"built on top of Jetpack Compose Material 3 guidelines and classes. " +
"Our goal is to provide a consistent, " +
"predictable set of components that respects Material Design " +
"while addressing the specifics of e‑ink displays.",
)
inceptionYear.set("2025")
url.set("https://github.com/mudita/MMD")
licenses {
license {
name.set("The Apache License, Version 2.0")
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
distribution.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
}
}
developers {
developer {
id.set("krystianbroniszewskimudita")
name.set("Krystian Broniszewski")
email.set("krystian.broniszewski@mudita.com")
}
}
scm {
connection.set("scm:git:github.com/mudita/MMD.git")
developerConnection.set("scm:git:ssh://github.com/mudita/MMD.git")
url.set("https://github.com/mudita/MMD/tree/main")
}
}
}

publishLibraryVariants("release")
Expand Down Expand Up @@ -64,3 +97,13 @@ android {
}
}
}

signing {
val keyFile = rootProject.file("secring.gpg")
val password = project.findProperty("signing.password") as? String

if (keyFile.exists() && password != null) {
useInMemoryPgpKeys(keyFile.readText(), password)
sign(publishing.publications)
}
}