From 430c409011d90226526fd1713280e1bf38897761 Mon Sep 17 00:00:00 2001 From: Takuma Homma Date: Tue, 9 Apr 2024 15:03:45 +0900 Subject: [PATCH 1/8] Update gitignore for IDEA --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index ede6257..e6f02ff 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,8 @@ local.properties .idea/inspectionProfiles/ .idea/androidTestResultsUserPreferences.xml .idea/kotlinc.xml +.idea/deploymentTargetDropDown.xml +.idea/migrations.xml *.iml .env From 2e7fb47bcb6999dc5381fef2812abd7e42c9f76c Mon Sep 17 00:00:00 2001 From: Takuma Homma Date: Sun, 14 Apr 2024 14:06:18 +0900 Subject: [PATCH 2/8] Make MiddleEllipsisText multiplatform compatible --- .github/workflows/test.yml | 7 +- MiddleEllipsisText/build.gradle.kts | 170 +++++++++++++---- .../MiddleEllipsisText_multibyte.png | Bin 0 -> 31650 bytes .../internal/BreakIterator.android.kt | 24 +++ .../MiddleEllipsisTextTest.kt | 180 ------------------ .../mataku/middleellipsistext/TestHelper.kt | 16 -- .../MiddleEllipsisTextTest.kt | 64 +++++++ .../{main => commonMain}/AndroidManifest.xml | 0 .../middleellipsistext/MiddleEllipsisText.kt | 5 +- .../internal/BreakIterator.kt | 17 ++ .../MiddleEllipsisTextTest.kt | 37 ++++ .../internal/BreakIterator.ios.kt | 24 +++ .../MiddleEllipsisTextTest.kt | 37 ++++ build-logic/convention/build.gradle.kts | 4 + .../src/main/java/ext/AndroidConfiguration.kt | 4 +- .../src/main/java/ext/ComposeConfiguration.kt | 2 +- .../src/main/java/ext/KotlinConfiguration.kt | 2 +- .../src/main/java/ext/TestConfiguration.kt | 2 +- build.gradle.kts | 10 +- gradle.properties | 11 +- gradle/libs.versions.toml | 43 +++-- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle.kts | 4 +- 23 files changed, 402 insertions(+), 263 deletions(-) create mode 100644 MiddleEllipsisText/screenshot/MiddleEllipsisText_multibyte.png create mode 100644 MiddleEllipsisText/src/androidMain/kotlin/io/github/mataku/middleellipsistext/internal/BreakIterator.android.kt delete mode 100644 MiddleEllipsisText/src/androidTest/java/io/github/mataku/middleellipsistext/MiddleEllipsisTextTest.kt delete mode 100644 MiddleEllipsisText/src/androidTest/java/io/github/mataku/middleellipsistext/TestHelper.kt create mode 100644 MiddleEllipsisText/src/androidUnitTest/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisTextTest.kt rename MiddleEllipsisText/src/{main => commonMain}/AndroidManifest.xml (100%) rename MiddleEllipsisText/src/{main/java => commonMain/kotlin}/io/github/mataku/middleellipsistext/MiddleEllipsisText.kt (97%) create mode 100644 MiddleEllipsisText/src/commonMain/kotlin/io/github/mataku/middleellipsistext/internal/BreakIterator.kt create mode 100644 MiddleEllipsisText/src/commonTest/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisTextTest.kt create mode 100644 MiddleEllipsisText/src/iosMain/kotlin/io/github/mataku/middleellipsistext/internal/BreakIterator.ios.kt create mode 100644 MiddleEllipsisText/src/iosTest/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisTextTest.kt diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e60bce1..19a100b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,8 +11,7 @@ concurrency: jobs: instrumentation_test: - # ubuntu-latest is enough, but needed for Android Emulator: https://issuetracker.google.com/issues/193118030 - runs-on: macos-latest + runs-on: ubuntu-latest timeout-minutes: 20 steps: @@ -33,9 +32,9 @@ jobs: ${{ runner.os }}-gradle- - name: Setup Android SDK uses: android-actions/setup-android@v2 - - name: Run layout tests + - name: Run build run: | - ./gradlew cleanManagedDevices --unused-only && ./gradlew MiddleEllipsisText:pixel4Api30DebugAndroidTest MiddleEllipsisText3:pixel4Api30DebugAndroidTest -Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" + ./gradlew MiddleEllipsisText:assembleRelease MiddleEllipsisText3:assembleRelease env: OSSRH_USERNAME: username OSSRH_PASSWORD: password diff --git a/MiddleEllipsisText/build.gradle.kts b/MiddleEllipsisText/build.gradle.kts index 8c08b05..9d11080 100644 --- a/MiddleEllipsisText/build.gradle.kts +++ b/MiddleEllipsisText/build.gradle.kts @@ -1,45 +1,127 @@ +import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeSimulatorTest + plugins { - id("middleellipsistext.android.library") - id("middleellipsistext.android.compose") - id("middleellipsistext.android.test") + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.android.library) + alias(libs.plugins.compose.jb) + alias(libs.plugins.roborazzi) id("maven-publish") signing } -android { - testOptions { - managedDevices { - devices.maybeCreate("pixel4Api30").apply { - device = "Pixel 4" - apiLevel = 30 - systemImageSource = "aosp-atd" +kotlin { + androidTarget { + publishLibraryVariants("release") + compilations.all { + kotlinOptions { + jvmTarget = "11" } } } + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { + it.binaries.framework { + baseName = "middle-ellipsis-text" + isStatic = true + } + } - namespace = "io.github.mataku.middleellipsistext" -} + applyDefaultHierarchyTemplate() -dependencies { - implementation(platform(libs.compose.bom)) - implementation(libs.compose.ui) - implementation(libs.compose.runtime) - implementation(libs.compose.foundation) - implementation(libs.compose.material) + sourceSets { + val commonMain by getting { + dependencies { + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material) + implementation(compose.ui) + implementation(libs.skiko) + } + } - androidTestImplementation(libs.compose.ui.test.junit4) - debugImplementation(libs.compose.ui.test.manifest) -} + val commonTest by getting { + dependencies { + implementation(libs.kotlin.test.common) + implementation(libs.kotlin.test.annotations.common) + implementation(libs.compose.ui.test) + + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + implementation(compose.ui) + } + } -val androidSourcesJar = tasks.register("androidSourcesJar") { - archiveClassifier.set("sources") - from("android.sourceSets.main.java.srcDirs") + val iosTest by getting { + dependencies { + implementation(libs.compose.ui.test) + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material) + implementation(compose.ui) + } + } + val androidUnitTest by getting { + dependencies { + implementation(libs.kotlin.test) + implementation(libs.kotlin.test.junit) + implementation(libs.androidx.test.ext.junit) + implementation(libs.robolectric) + implementation(libs.roborazzi) + implementation(libs.compose.ui.test.junit4) + implementation(libs.compose.ui.test.manifest) + } + } + } + + tasks.getByName("iosSimulatorArm64Test") { + device.set("iPhone 13") + } + tasks.getByName("iosX64Test") { + device.set("iPhone 13") + } } -artifacts { - archives(androidSourcesJar) +android { + namespace = "io.github.mataku.middleellipsistext" + compileSdk = 34 + + defaultConfig { + minSdk = 24 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + dependencies { + implementation(platform(libs.compose.bom)) + implementation(libs.compose.ui) + implementation(libs.compose.runtime) + implementation(libs.compose.foundation) + implementation(libs.compose.material) + + debugImplementation(libs.compose.ui.test.manifest) + + testImplementation(libs.kotlin.test) + testImplementation(libs.kotlin.test.junit) + testImplementation(libs.androidx.test.ext.junit) + testImplementation(libs.robolectric) + } + + testOptions { + unitTests.isIncludeAndroidResources = true + } } + ext["signing.password"] = "" signing { @@ -53,20 +135,20 @@ signing { val libName = "middle-ellipsis-text" +group = "io.github.mataku" +version = "1.0.1-SNAPSHOT" + afterEvaluate { publishing { - publications { - create("maven") { - groupId = "io.github.mataku" - artifactId = libName - version = "1.0.0" - if (project.plugins.hasPlugin("com.android.library")) { - from(components["release"]) - } else { - from(components["java"]) - } - artifact(androidSourcesJar) + publications.forEach { + val publication = it as? MavenPublication ?: return@forEach + with(publication) { pom { + artifactId = if (publication.name == "kotlinMultiplatform") { + libName + } else { + "${libName}-${publication.name}" + } name.set(libName) description.set("Jetpack Compose Component with ellipsis in the middle of text") url.set("https://github.com/mataku/MiddleEllipsisText") @@ -94,3 +176,17 @@ afterEvaluate { } } } + +tasks.withType { + dependsOn(":MiddleEllipsisText:signIosX64Publication") + dependsOn(":MiddleEllipsisText:signIosArm64Publication") + dependsOn(":MiddleEllipsisText:signIosSimulatorArm64Publication") + dependsOn(":MiddleEllipsisText:signKotlinMultiplatformPublication") +} + +tasks.withType { + dependsOn(":MiddleEllipsisText:signIosX64Publication") + dependsOn(":MiddleEllipsisText:signIosArm64Publication") + dependsOn(":MiddleEllipsisText:signIosSimulatorArm64Publication") + dependsOn(":MiddleEllipsisText:signKotlinMultiplatformPublication") +} diff --git a/MiddleEllipsisText/screenshot/MiddleEllipsisText_multibyte.png b/MiddleEllipsisText/screenshot/MiddleEllipsisText_multibyte.png new file mode 100644 index 0000000000000000000000000000000000000000..77e3a6c11aaa50b395b074d8ecdaf78fb1a44254 GIT binary patch literal 31650 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 - bmp.compress(Bitmap.CompressFormat.PNG, 100, out) - } - println("Saved screenshot to $path/$filename.png") - } -} diff --git a/MiddleEllipsisText/src/androidUnitTest/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisTextTest.kt b/MiddleEllipsisText/src/androidUnitTest/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisTextTest.kt new file mode 100644 index 0000000..fcd2945 --- /dev/null +++ b/MiddleEllipsisText/src/androidUnitTest/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisTextTest.kt @@ -0,0 +1,64 @@ +package io.github.mataku.middleellipsistext + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.test.isRoot +import androidx.compose.ui.test.junit4.ComposeContentTestRule +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.RobolectricDeviceQualifiers +import com.github.takahirom.roborazzi.captureRoboImage +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +@Config( + qualifiers = RobolectricDeviceQualifiers.Pixel7, + sdk = [33] +) +class MiddleEllipsisTextTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun layout_multibyte() { + composeTestRule.captureScreenshot( + fileName = "MiddleEllipsisText_multibyte.png", + content = { + Column(modifier = Modifier.fillMaxSize()) { + MiddleEllipsisText( + text = "あいうえおかきくけこさしすせそだぢづでどなにぬねのばびぶべぼまみむめも" + ) + } + } + ) + } +} + +fun ComposeContentTestRule.captureScreenshot( + fileName: String, + content: @Composable () -> Unit, + actionsBeforeCapturing: () -> Unit = {} +) { + this.setContent { + MaterialTheme { + Surface { + content() + } + } + } + + actionsBeforeCapturing.invoke() + + this.onNode(isRoot()).captureRoboImage( + filePath = "screenshot/${fileName}", + ) +} diff --git a/MiddleEllipsisText/src/main/AndroidManifest.xml b/MiddleEllipsisText/src/commonMain/AndroidManifest.xml similarity index 100% rename from MiddleEllipsisText/src/main/AndroidManifest.xml rename to MiddleEllipsisText/src/commonMain/AndroidManifest.xml diff --git a/MiddleEllipsisText/src/main/java/io/github/mataku/middleellipsistext/MiddleEllipsisText.kt b/MiddleEllipsisText/src/commonMain/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisText.kt similarity index 97% rename from MiddleEllipsisText/src/main/java/io/github/mataku/middleellipsistext/MiddleEllipsisText.kt rename to MiddleEllipsisText/src/commonMain/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisText.kt index 644695d..af88468 100644 --- a/MiddleEllipsisText/src/main/java/io/github/mataku/middleellipsistext/MiddleEllipsisText.kt +++ b/MiddleEllipsisText/src/commonMain/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisText.kt @@ -1,6 +1,5 @@ package io.github.mataku.middleellipsistext -import android.icu.text.BreakIterator import androidx.compose.material.LocalTextStyle import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -17,6 +16,8 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.TextUnit +import io.github.mataku.middleellipsistext.internal.BreakIterator +import io.github.mataku.middleellipsistext.internal.getBreakIterator @Composable fun MiddleEllipsisText( @@ -54,10 +55,10 @@ fun MiddleEllipsisText( style = style ) } else { + val breakIterator: BreakIterator = getBreakIterator() var textLayoutResult: TextLayoutResult? = null val ellipsisText = ellipsisChar.toString().repeat(ellipsisCharCount) - val breakIterator = BreakIterator.getCharacterInstance() breakIterator.setText(text) val charSplitIndexList = mutableListOf() while (breakIterator.next() != BreakIterator.DONE) { diff --git a/MiddleEllipsisText/src/commonMain/kotlin/io/github/mataku/middleellipsistext/internal/BreakIterator.kt b/MiddleEllipsisText/src/commonMain/kotlin/io/github/mataku/middleellipsistext/internal/BreakIterator.kt new file mode 100644 index 0000000..5f1774f --- /dev/null +++ b/MiddleEllipsisText/src/commonMain/kotlin/io/github/mataku/middleellipsistext/internal/BreakIterator.kt @@ -0,0 +1,17 @@ +package io.github.mataku.middleellipsistext.internal + +interface BreakIterator { + fun next(): Int + + fun makeCharacterInstance(): BreakIterator + + fun setText(text: String?) + + fun current(): Int + + companion object { + const val DONE = -1 + } +} + +expect fun getBreakIterator(): BreakIterator diff --git a/MiddleEllipsisText/src/commonTest/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisTextTest.kt b/MiddleEllipsisText/src/commonTest/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisTextTest.kt new file mode 100644 index 0000000..c868e51 --- /dev/null +++ b/MiddleEllipsisText/src/commonTest/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisTextTest.kt @@ -0,0 +1,37 @@ +//package io.github.mataku.middleellipsistext +// +//import androidx.compose.foundation.layout.Column +//import androidx.compose.foundation.layout.fillMaxSize +//import androidx.compose.material.MaterialTheme +//import androidx.compose.material.Surface +//import androidx.compose.runtime.Composable +//import androidx.compose.ui.Modifier +//import androidx.compose.ui.test.ExperimentalTestApi +//import androidx.compose.ui.test.assertIsDisplayed +//import androidx.compose.ui.test.onNodeWithText +//import androidx.compose.ui.test.runComposeUiTest +//import kotlin.test.Test +// +//@OptIn(ExperimentalTestApi::class) +//class MiddleEllipsisTextTest { +// @Test +// fun way2() = runComposeUiTest { +// setContent { +// TestScreen() +// } +// onNodeWithText("あいうえお".repeat(10)).assertIsDisplayed() +// } +//} +// +//@Composable +//private fun TestScreen() { +// MaterialTheme { +// Surface { +// Column(modifier = Modifier.fillMaxSize()) { +// MiddleEllipsisText( +// text = "あいうえお".repeat(10) +// ) +// } +// } +// } +//} diff --git a/MiddleEllipsisText/src/iosMain/kotlin/io/github/mataku/middleellipsistext/internal/BreakIterator.ios.kt b/MiddleEllipsisText/src/iosMain/kotlin/io/github/mataku/middleellipsistext/internal/BreakIterator.ios.kt new file mode 100644 index 0000000..76ed188 --- /dev/null +++ b/MiddleEllipsisText/src/iosMain/kotlin/io/github/mataku/middleellipsistext/internal/BreakIterator.ios.kt @@ -0,0 +1,24 @@ +package io.github.mataku.middleellipsistext.internal + +class IOSBreakIterator : BreakIterator { + + private val instance = org.jetbrains.skia.BreakIterator.makeCharacterInstance() + + override fun next(): Int { + return instance.next() + } + + override fun makeCharacterInstance(): BreakIterator { + return this + } + + override fun setText(text: String?) { + instance.setText(text) + } + + override fun current(): Int { + return instance.current() + } +} + +actual fun getBreakIterator(): BreakIterator = IOSBreakIterator() diff --git a/MiddleEllipsisText/src/iosTest/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisTextTest.kt b/MiddleEllipsisText/src/iosTest/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisTextTest.kt new file mode 100644 index 0000000..9874c8f --- /dev/null +++ b/MiddleEllipsisText/src/iosTest/kotlin/io/github/mataku/middleellipsistext/MiddleEllipsisTextTest.kt @@ -0,0 +1,37 @@ +//package io.github.mataku.middleellipsistext +// +//import androidx.compose.foundation.layout.Column +//import androidx.compose.foundation.layout.fillMaxSize +//import androidx.compose.material.MaterialTheme +//import androidx.compose.material.Surface +//import androidx.compose.runtime.Composable +//import androidx.compose.ui.Modifier +//import androidx.compose.ui.test.ExperimentalTestApi +//import androidx.compose.ui.test.assertIsDisplayed +//import androidx.compose.ui.test.onNodeWithText +//import androidx.compose.ui.test.runComposeUiTest +//import kotlin.test.Test +// +//@OptIn(ExperimentalTestApi::class) +//class MiddleEllipsisTextTest2 { +// @Test +// fun way() = runComposeUiTest { +// setContent { +// TestScreen() +// } +// onNodeWithText("あいうえお".repeat(10)).assertIsDisplayed() +// } +//} +// +//@Composable +//private fun TestScreen() { +// MaterialTheme { +// Surface { +// Column(modifier = Modifier.fillMaxSize()) { +// MiddleEllipsisText( +// text = "あいうえお".repeat(10) +// ) +// } +// } +// } +//} diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index ec18473..64b41c7 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -7,6 +7,10 @@ java { targetCompatibility = JavaVersion.VERSION_11 } +kotlin { + jvmToolchain(11) +} + dependencies { compileOnly(libs.android.gradle.plugin) compileOnly(libs.kotlin.gradle.plugin) diff --git a/build-logic/convention/src/main/java/ext/AndroidConfiguration.kt b/build-logic/convention/src/main/java/ext/AndroidConfiguration.kt index ff943d4..eeb71f9 100644 --- a/build-logic/convention/src/main/java/ext/AndroidConfiguration.kt +++ b/build-logic/convention/src/main/java/ext/AndroidConfiguration.kt @@ -4,8 +4,8 @@ import com.android.build.api.dsl.CommonExtension import com.android.build.api.dsl.LibraryExtension import com.android.build.gradle.internal.dsl.BaseAppModuleExtension -fun CommonExtension<*, *, *, *>.androidConfiguration() { - compileSdk = 33 +fun CommonExtension<*, *, *, *, *>.androidConfiguration() { + compileSdk = 34 if (this is LibraryExtension) { defaultConfig { diff --git a/build-logic/convention/src/main/java/ext/ComposeConfiguration.kt b/build-logic/convention/src/main/java/ext/ComposeConfiguration.kt index cb99cbf..ade3034 100644 --- a/build-logic/convention/src/main/java/ext/ComposeConfiguration.kt +++ b/build-logic/convention/src/main/java/ext/ComposeConfiguration.kt @@ -3,7 +3,7 @@ package ext import com.android.build.api.dsl.CommonExtension import org.gradle.api.artifacts.VersionCatalog -fun CommonExtension<*, *, *, *>.composeConfiguration( +fun CommonExtension<*, *, *, *, *>.composeConfiguration( libs: VersionCatalog ) { buildFeatures { diff --git a/build-logic/convention/src/main/java/ext/KotlinConfiguration.kt b/build-logic/convention/src/main/java/ext/KotlinConfiguration.kt index d980c86..37c390e 100644 --- a/build-logic/convention/src/main/java/ext/KotlinConfiguration.kt +++ b/build-logic/convention/src/main/java/ext/KotlinConfiguration.kt @@ -3,7 +3,7 @@ import org.gradle.api.JavaVersion import org.gradle.api.plugins.ExtensionAware import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions -fun CommonExtension<*, *, *, *>.kotlinConfiguration() { +fun CommonExtension<*, *, *, *, *>.kotlinConfiguration() { compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 diff --git a/build-logic/convention/src/main/java/ext/TestConfiguration.kt b/build-logic/convention/src/main/java/ext/TestConfiguration.kt index 2d3039f..2e76f50 100644 --- a/build-logic/convention/src/main/java/ext/TestConfiguration.kt +++ b/build-logic/convention/src/main/java/ext/TestConfiguration.kt @@ -2,7 +2,7 @@ package ext import com.android.build.api.dsl.CommonExtension -fun CommonExtension<*, *, *, *>.testConfiguration() { +fun CommonExtension<*, *, *, *, *>.testConfiguration() { testOptions { unitTests { isIncludeAndroidResources = true diff --git a/build.gradle.kts b/build.gradle.kts index 54e6dc2..fa8828e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,9 +2,13 @@ import java.io.FileInputStream import java.util.Properties plugins { - id("com.android.application") version "7.4.1" apply false - id("com.android.library") version "7.4.1" apply false - id("org.jetbrains.kotlin.android") version "1.7.10" apply false + alias(libs.plugins.kotlin.jvm) apply false + alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.kotlin.multiplatform) apply false + alias(libs.plugins.android.application) apply false + alias(libs.plugins.android.library) apply false + alias(libs.plugins.compose.jb) apply false + alias(libs.plugins.roborazzi) apply false id("io.github.gradle-nexus.publish-plugin") version "1.1.0" } diff --git a/gradle.properties b/gradle.properties index cd0519b..b137ca0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,4 +20,13 @@ kotlin.code.style=official # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file +android.nonTransitiveRClass=true + +# multiplatform +kotlin.mpp.stability.nowarn=true +kotlin.mpp.enableCInteropCommonization=true +kotlin.mpp.androidSourceSetLayoutVersion=2 +kotlin.mpp.applyDefaultHierarchyTemplate=false + +# Compose +org.jetbrains.compose.experimental.uikit.enabled=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8c70e6a..b7e0d7a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,18 +1,21 @@ [versions] -agp = "7.4.1" -android-gradle-plugin = "7.4.1" +agp = "8.1.4" +android-gradle-plugin = "8.1.0" androidx-test-ext-junit = "1.1.5" appcompat = "1.6.1" -compose = "2022.11.00" -compose-kotlin-compiler-extension = "1.3.1" +compose = "2024.04.00" +compose-kotlin-compiler-extension = "1.5.11" +compose-multiplatform = "1.6.1" core-ktx = "1.9.0" espresso-core = "3.5.1" gradle-publish-plugin = "1.1.0" -kotlin = "1.7.10" -org-jetbrains-kotlin-android = "1.7.10" +kotlin = "1.9.23" +kotlin-android = "1.9.23" kotlin-bom = "1.8.0" junit = "4.13.2" material = "1.9.0" +robolectric = "4.11.1" +roborazzi = "1.11.0" [libraries] compose-bom = { module = "androidx.compose:compose-bom", version.ref = "compose" } @@ -22,22 +25,36 @@ compose-foundation = { module = "androidx.compose.foundation:foundation" } compose-material = { module = "androidx.compose.material:material" } compose-material3 = { module = "androidx.compose.material3:material3" } -compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" } -compose-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest", version = "1.3.3" } +compose-ui-test = { module = "org.jetbrains.compose.ui:ui-test", version.ref = "compose-multiplatform" } +compose-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest", version.ref = "compose-multiplatform" } +compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "compose-multiplatform" } android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "android-gradle-plugin" } kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" } kotlin-bom = { group = "org.jetbrains.kotlin", name = "kotlin-bom", version.ref = "kotlin-bom" } -junit = { group = "junit", name = "junit", version.ref = "junit" } -androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-ext-junit" } -espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso-core" } appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } material = { group = "com.google.android.material", name = "material", version.ref = "material" } gradle-publish-plugin = { module = "com.gradle.publish:plugin-publish-plugin", version.ref = "gradle-publish-plugin" } +skiko = { module = "org.jetbrains.skiko:skiko", version = "0.7.97" } + +kotlin-test-common = { module = "org.jetbrains.kotlin:kotlin-test-common", version.ref = "kotlin" } +kotlin-test-annotations-common = { module = "org.jetbrains.kotlin:kotlin-test-annotations-common", version.ref = "kotlin" } +kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } +kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } +junit = { group = "junit", name = "junit", version.ref = "junit" } +androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-ext-junit" } +espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso-core" } +robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" } +roborazzi = { module = "io.github.takahirom.roborazzi:roborazzi", version.ref = "roborazzi" } [plugins] -com-android-library = { id = "com.android.library", version.ref = "agp" } -org-jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "org-jetbrains-kotlin-android" } +android-application = { id = "com.android.application", version.ref = "agp" } +android-library = { id = "com.android.library", version.ref = "agp" } +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin-android" } +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin-android" } +kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +compose-jb = { id = "org.jetbrains.compose", version.ref = "compose-multiplatform" } +roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 070cb70..48c0a02 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index c8e0a6d..66e176b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,10 +7,11 @@ pluginManagement { } } dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) +// repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } versionCatalogs { maybeCreate("sampleLibs").apply { @@ -30,3 +31,4 @@ rootProject.name = "MiddleEllipsisText" include(":sample") include(":MiddleEllipsisText") include(":MiddleEllipsisText3") +// include(":shared") From 957a3c600e20b3830d3f93d745f4f3e5a22513bd Mon Sep 17 00:00:00 2001 From: Takuma Homma Date: Sun, 14 Apr 2024 14:06:44 +0900 Subject: [PATCH 3/8] Make MiddleEllipsisText3 multiplatform compatible --- MiddleEllipsisText3/build.gradle.kts | 112 ++++++++++++------ .../internal/BreakIterator.android.kt | 24 ++++ .../{main => commonMain}/AndroidManifest.xml | 0 .../middleellipsistext3/MiddleEllipsisText.kt | 5 +- .../internal/BreakIterator.kt | 17 +++ .../internal/BreakIterator.ios.kt | 24 ++++ .../middleellipsistext3/ExampleUnitTest.kt | 17 --- 7 files changed, 145 insertions(+), 54 deletions(-) create mode 100644 MiddleEllipsisText3/src/androidMain/kotlin/io/github/mataku/middleellipsistext3/internal/BreakIterator.android.kt rename MiddleEllipsisText3/src/{main => commonMain}/AndroidManifest.xml (100%) rename MiddleEllipsisText3/src/{main/java => commonMain/kotlin}/io/github/mataku/middleellipsistext3/MiddleEllipsisText.kt (97%) create mode 100644 MiddleEllipsisText3/src/commonMain/kotlin/io/github/mataku/middleellipsistext3/internal/BreakIterator.kt create mode 100644 MiddleEllipsisText3/src/iosMain/kotlin/io/github/mataku/middleellipsistext3/internal/BreakIterator.ios.kt delete mode 100644 MiddleEllipsisText3/src/test/java/com/mataku/middleellipsistext3/ExampleUnitTest.kt diff --git a/MiddleEllipsisText3/build.gradle.kts b/MiddleEllipsisText3/build.gradle.kts index f6d6362..bed77da 100644 --- a/MiddleEllipsisText3/build.gradle.kts +++ b/MiddleEllipsisText3/build.gradle.kts @@ -1,23 +1,63 @@ plugins { - id("middleellipsistext.android.library") - id("middleellipsistext.android.compose") - id("middleellipsistext.android.test") + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.android.library) + alias(libs.plugins.compose.jb) id("maven-publish") signing } -android { - namespace = "com.mataku.middleellipsistext3" - - testOptions { - managedDevices { - devices.maybeCreate("pixel4Api30").apply { - device = "Pixel 4" - apiLevel = 30 - systemImageSource = "aosp-atd" +kotlin { + androidTarget { + publishLibraryVariants("release") + compilations.all { + kotlinOptions { + jvmTarget = "11" } } } + iosX64() + iosArm64() + iosSimulatorArm64() + + applyDefaultHierarchyTemplate() + + sourceSets { + val commonMain by getting { + dependencies { + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + implementation(compose.ui) + } + } + + val commonTest by getting { + dependencies { + implementation(kotlin("test")) + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + implementation(compose.ui) + } + } + } +} + +android { + namespace = "io.github.mataku.middleellipsistext3" + compileSdk = 34 + + defaultConfig { + minSdk = 24 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } } dependencies { @@ -25,21 +65,11 @@ dependencies { implementation(libs.compose.ui) implementation(libs.compose.runtime) implementation(libs.compose.foundation) - implementation(libs.compose.material3) + implementation(libs.compose.material) - androidTestImplementation(libs.compose.ui.test.junit4) debugImplementation(libs.compose.ui.test.manifest) } -val androidSourcesJar = tasks.register("androidSourcesJar") { - archiveClassifier.set("sources") - from("android.sourceSets.main.java.srcDirs") -} - -artifacts { - archives(androidSourcesJar) -} - ext["signing.password"] = "" signing { @@ -52,23 +82,22 @@ signing { } val libName = "middle-ellipsis-text3" +group = "io.github.mataku" +version = "1.0.1-SNAPSHOT" afterEvaluate { publishing { - publications { - create("maven") { - groupId = "io.github.mataku" - artifactId = libName - version = "1.0.0" - if (project.plugins.hasPlugin("com.android.library")) { - from(components["release"]) - } else { - from(components["java"]) - } - artifact(androidSourcesJar) + publications.forEach { + val publication = it as? MavenPublication ?: return@forEach + with(publication) { pom { + artifactId = if (publication.name == "kotlinMultiplatform") { + libName + } else { + "${libName}-${publication.name}" + } name.set(libName) - description.set("Jetpack Compose Component with ellipsis in the middle of Material3 text") + description.set("Jetpack Compose Component with ellipsis in the middle of text") url.set("https://github.com/mataku/MiddleEllipsisText") licenses { @@ -95,3 +124,16 @@ afterEvaluate { } } +tasks.withType { + dependsOn(":MiddleEllipsisText3:signIosX64Publication") + dependsOn(":MiddleEllipsisText3:signIosArm64Publication") + dependsOn(":MiddleEllipsisText3:signIosSimulatorArm64Publication") + dependsOn(":MiddleEllipsisText3:signKotlinMultiplatformPublication") +} + +tasks.withType { + dependsOn(":MiddleEllipsisText3:signIosX64Publication") + dependsOn(":MiddleEllipsisText3:signIosArm64Publication") + dependsOn(":MiddleEllipsisText3:signIosSimulatorArm64Publication") + dependsOn(":MiddleEllipsisText3:signKotlinMultiplatformPublication") +} diff --git a/MiddleEllipsisText3/src/androidMain/kotlin/io/github/mataku/middleellipsistext3/internal/BreakIterator.android.kt b/MiddleEllipsisText3/src/androidMain/kotlin/io/github/mataku/middleellipsistext3/internal/BreakIterator.android.kt new file mode 100644 index 0000000..ec60fa9 --- /dev/null +++ b/MiddleEllipsisText3/src/androidMain/kotlin/io/github/mataku/middleellipsistext3/internal/BreakIterator.android.kt @@ -0,0 +1,24 @@ +package io.github.mataku.middleellipsistext3.internal + +internal class AndroidBreakIterator : BreakIterator { + + private val instance = android.icu.text.BreakIterator.getCharacterInstance() + + override fun next(): Int { + return instance.next() + } + + override fun makeCharacterInstance(): BreakIterator { + return this + } + + override fun setText(text: String?) { + instance.setText(text) + } + + override fun current(): Int { + return instance.current() + } +} + +actual fun getBreakIterator(): BreakIterator = AndroidBreakIterator() diff --git a/MiddleEllipsisText3/src/main/AndroidManifest.xml b/MiddleEllipsisText3/src/commonMain/AndroidManifest.xml similarity index 100% rename from MiddleEllipsisText3/src/main/AndroidManifest.xml rename to MiddleEllipsisText3/src/commonMain/AndroidManifest.xml diff --git a/MiddleEllipsisText3/src/main/java/io/github/mataku/middleellipsistext3/MiddleEllipsisText.kt b/MiddleEllipsisText3/src/commonMain/kotlin/io/github/mataku/middleellipsistext3/MiddleEllipsisText.kt similarity index 97% rename from MiddleEllipsisText3/src/main/java/io/github/mataku/middleellipsistext3/MiddleEllipsisText.kt rename to MiddleEllipsisText3/src/commonMain/kotlin/io/github/mataku/middleellipsistext3/MiddleEllipsisText.kt index 5a97958..aa7fcde 100644 --- a/MiddleEllipsisText3/src/main/java/io/github/mataku/middleellipsistext3/MiddleEllipsisText.kt +++ b/MiddleEllipsisText3/src/commonMain/kotlin/io/github/mataku/middleellipsistext3/MiddleEllipsisText.kt @@ -1,6 +1,5 @@ package io.github.mataku.middleellipsistext3 -import android.icu.text.BreakIterator import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -17,6 +16,8 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.TextUnit +import io.github.mataku.middleellipsistext3.internal.BreakIterator +import io.github.mataku.middleellipsistext3.internal.getBreakIterator @Composable fun MiddleEllipsisText( @@ -54,10 +55,10 @@ fun MiddleEllipsisText( style = style ) } else { + val breakIterator = getBreakIterator() var textLayoutResult: TextLayoutResult? = null val ellipsisText = ellipsisChar.toString().repeat(ellipsisCharCount) - val breakIterator = BreakIterator.getCharacterInstance() breakIterator.setText(text) val charSplitIndexList = mutableListOf() while (breakIterator.next() != BreakIterator.DONE) { diff --git a/MiddleEllipsisText3/src/commonMain/kotlin/io/github/mataku/middleellipsistext3/internal/BreakIterator.kt b/MiddleEllipsisText3/src/commonMain/kotlin/io/github/mataku/middleellipsistext3/internal/BreakIterator.kt new file mode 100644 index 0000000..af0569d --- /dev/null +++ b/MiddleEllipsisText3/src/commonMain/kotlin/io/github/mataku/middleellipsistext3/internal/BreakIterator.kt @@ -0,0 +1,17 @@ +package io.github.mataku.middleellipsistext3.internal + +interface BreakIterator { + fun next(): Int + + fun makeCharacterInstance(): BreakIterator + + fun setText(text: String?) + + fun current(): Int + + companion object { + const val DONE = -1 + } +} + +expect fun getBreakIterator(): BreakIterator diff --git a/MiddleEllipsisText3/src/iosMain/kotlin/io/github/mataku/middleellipsistext3/internal/BreakIterator.ios.kt b/MiddleEllipsisText3/src/iosMain/kotlin/io/github/mataku/middleellipsistext3/internal/BreakIterator.ios.kt new file mode 100644 index 0000000..20a741a --- /dev/null +++ b/MiddleEllipsisText3/src/iosMain/kotlin/io/github/mataku/middleellipsistext3/internal/BreakIterator.ios.kt @@ -0,0 +1,24 @@ +package io.github.mataku.middleellipsistext3.internal + +class IOSBreakIterator : BreakIterator { + + private val instance = org.jetbrains.skia.BreakIterator.makeCharacterInstance() + + override fun next(): Int { + return instance.next() + } + + override fun makeCharacterInstance(): BreakIterator { + return this + } + + override fun setText(text: String?) { + instance.setText(text) + } + + override fun current(): Int { + return instance.current() + } +} + +actual fun getBreakIterator(): BreakIterator = IOSBreakIterator() diff --git a/MiddleEllipsisText3/src/test/java/com/mataku/middleellipsistext3/ExampleUnitTest.kt b/MiddleEllipsisText3/src/test/java/com/mataku/middleellipsistext3/ExampleUnitTest.kt deleted file mode 100644 index 4072bdd..0000000 --- a/MiddleEllipsisText3/src/test/java/com/mataku/middleellipsistext3/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.mataku.middleellipsistext3 - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} From ecbe812fca74ef2da016a92c7d0f0d75683f0069 Mon Sep 17 00:00:00 2001 From: Takuma Homma Date: Sun, 14 Apr 2024 14:06:54 +0900 Subject: [PATCH 4/8] Add MiddleEllipsisText3 implementation to sample app --- sample/build.gradle | 2 + sample/src/main/AndroidManifest.xml | 7 + .../middleellipsistextsample/MainActivity.kt | 135 ++---------------- .../middleellipsistextsample/MainScreen.kt | 63 ++++++++ .../component/ContentHeader.kt | 71 +++++++++ .../component/ContentHeader3.kt | 59 ++++++++ .../material/MaterialActivity.kt | 20 +++ .../material/MaterialScreen.kt | 109 ++++++++++++++ .../material3/Material3Activity.kt | 20 +++ .../material3/Material3Screen.kt | 109 ++++++++++++++ 10 files changed, 471 insertions(+), 124 deletions(-) create mode 100644 sample/src/main/java/com/mataku/middleellipsistextsample/MainScreen.kt create mode 100644 sample/src/main/java/com/mataku/middleellipsistextsample/component/ContentHeader.kt create mode 100644 sample/src/main/java/com/mataku/middleellipsistextsample/component/ContentHeader3.kt create mode 100644 sample/src/main/java/com/mataku/middleellipsistextsample/material/MaterialActivity.kt create mode 100644 sample/src/main/java/com/mataku/middleellipsistextsample/material/MaterialScreen.kt create mode 100644 sample/src/main/java/com/mataku/middleellipsistextsample/material3/Material3Activity.kt create mode 100644 sample/src/main/java/com/mataku/middleellipsistextsample/material3/Material3Screen.kt diff --git a/sample/build.gradle b/sample/build.gradle index 22285bc..36feb44 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -4,6 +4,7 @@ plugins { dependencies { implementation project(":MiddleEllipsisText") + implementation project(":MiddleEllipsisText3") implementation platform(libs.compose.bom) implementation sampleLibs.core.ktx @@ -12,6 +13,7 @@ dependencies { implementation libs.compose.runtime implementation libs.compose.foundation implementation libs.compose.material + implementation libs.compose.material3 implementation sampleLibs.activity.compose implementation sampleLibs.material debugImplementation sampleLibs.ui.tooling diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index e0c1ff3..8dead66 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -23,6 +23,13 @@ + + + diff --git a/sample/src/main/java/com/mataku/middleellipsistextsample/MainActivity.kt b/sample/src/main/java/com/mataku/middleellipsistextsample/MainActivity.kt index 9a17082..766995f 100644 --- a/sample/src/main/java/com/mataku/middleellipsistextsample/MainActivity.kt +++ b/sample/src/main/java/com/mataku/middleellipsistextsample/MainActivity.kt @@ -1,26 +1,13 @@ package com.mataku.middleellipsistextsample +import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import io.github.mataku.middleellipsistext.MiddleEllipsisText +import com.mataku.middleellipsistextsample.material.MaterialActivity +import com.mataku.middleellipsistextsample.material3.Material3Activity class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -28,116 +15,16 @@ class MainActivity : ComponentActivity() { setContent { MaterialTheme { Surface { - MainContent() + MainScreen( + navigateToMaterial = { + startActivity(Intent(this, MaterialActivity::class.java)) + }, + navigateToMaterial3 = { + startActivity(Intent(this, Material3Activity::class.java)) + } + ) } } } } } - -@Composable -private fun MainContent() { - Column( - modifier = Modifier.fillMaxSize() - ) { - ContentHeader(text = "Demo") - - Spacer(modifier = Modifier.height(32.dp)) - - Text(text = "ellipsis applied", fontSize = 20.sp, fontWeight = FontWeight.Bold) - - MiddleEllipsisText( - text = "soooooooooooooooooooooooooooooooooooooooooooloooooooooooooooooooongtext", - ) - - Spacer(modifier = Modifier.height(32.dp)) - - Text( - text = "ellipsis applied with horizontal margin", - fontSize = 20.sp, - fontWeight = FontWeight.Bold - ) - - MiddleEllipsisText( - text = "sooooooooooooooooooooooooooooooooooooooooooooooloooooooooooooooooooongtext", - modifier = Modifier.padding(horizontal = 16.dp) - ) - - Spacer(modifier = Modifier.height(32.dp)) - - Text(text = "with multibyte string", fontSize = 20.sp, fontWeight = FontWeight.Bold) - - Spacer(modifier = Modifier.height(4.dp)) - - MiddleEllipsisText( - text = "sooooooooooooooooooooooooooooooooooooooooooloooooooooooooooooooongtextツツツツツツ", - ) - - Spacer(modifier = Modifier.height(32.dp)) - - Text(text = "with short text", fontSize = 20.sp, fontWeight = FontWeight.Bold) - - Spacer(modifier = Modifier.height(4.dp)) - - MiddleEllipsisText( - text = "sooooooooooツツツツツツ", - ) - - Spacer(modifier = Modifier.height(32.dp)) - - Text(text = "with emoji", fontSize = 20.sp, fontWeight = FontWeight.Bold) - - Spacer(modifier = Modifier.height(4.dp)) - - val emojis2 = "\uD83D\uDE00".repeat(40) - - MiddleEllipsisText( - text = emojis2, - ) - - Spacer(modifier = Modifier.height(32.dp)) - Text(text = "with multi-codepoints emoji", fontSize = 20.sp, fontWeight = FontWeight.Bold) - - Spacer(modifier = Modifier.height(4.dp)) - - val emojis = "\uD83C\uDDE7\uD83C\uDDEB".repeat(40) - MiddleEllipsisText( - text = emojis, - ) - } -} - -@Preview -@Composable -private fun MainContentPreview() { - MaterialTheme { - Surface { - MainContent() - } - } -} - -@Composable -fun ContentHeader( - text: String -) { - Surface( - elevation = 2.dp - ) { - Box( - modifier = Modifier - .fillMaxWidth() - ) { - Text( - text = text, - style = TextStyle( - fontWeight = FontWeight.Medium, - fontSize = 24.sp, - letterSpacing = 0.15.sp - ), - modifier = Modifier - .padding(16.dp) - ) - } - } -} diff --git a/sample/src/main/java/com/mataku/middleellipsistextsample/MainScreen.kt b/sample/src/main/java/com/mataku/middleellipsistextsample/MainScreen.kt new file mode 100644 index 0000000..e262400 --- /dev/null +++ b/sample/src/main/java/com/mataku/middleellipsistextsample/MainScreen.kt @@ -0,0 +1,63 @@ +package com.mataku.middleellipsistextsample + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.mataku.middleellipsistextsample.component.ContentHeader + +@Composable +fun MainScreen( + navigateToMaterial: () -> Unit, + navigateToMaterial3: () -> Unit +) { + Column(modifier = Modifier.fillMaxSize()) { + ContentHeader(text = "MiddleEllipsisText Sample") + + ContentCell( + title = "Material", + onTapCell = navigateToMaterial + ) + + ContentCell( + title = "Material3", + onTapCell = navigateToMaterial3 + ) + } +} + +@Composable +private fun ContentCell( + title: String, + onTapCell: () -> Unit +) { + Column( + modifier = Modifier + .fillMaxWidth() + .height(64.dp) + .clickable { + onTapCell.invoke() + } + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.SpaceEvenly + ) { + Text( + text = title, + style = TextStyle( + fontWeight = FontWeight.Medium, + fontSize = 16.sp, + letterSpacing = 0.15.sp, + ) + ) + } +} diff --git a/sample/src/main/java/com/mataku/middleellipsistextsample/component/ContentHeader.kt b/sample/src/main/java/com/mataku/middleellipsistextsample/component/ContentHeader.kt new file mode 100644 index 0000000..8c4eea9 --- /dev/null +++ b/sample/src/main/java/com/mataku/middleellipsistextsample/component/ContentHeader.kt @@ -0,0 +1,71 @@ +package com.mataku.middleellipsistextsample.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.rememberVectorPainter +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +@Composable +fun ContentHeader( + text: String, + onBackPressed: (() -> Unit)? = null +) { + Surface( + elevation = 2.dp + ) { + Box( + modifier = Modifier + .fillMaxWidth() + ) { + if (onBackPressed != null) { + Image( + painter = rememberVectorPainter(image = Icons.AutoMirrored.Default.ArrowBack), + contentDescription = "back", + modifier = Modifier + .align(alignment = Alignment.CenterStart) + .clickable { + onBackPressed.invoke() + } + .padding(start = 12.dp) + ) + } + + Text( + text = text, + style = TextStyle( + fontWeight = FontWeight.Medium, + fontSize = 24.sp, + letterSpacing = 0.15.sp + ), + modifier = Modifier + .padding(vertical = 16.dp) + .align(alignment = Alignment.Center) + ) + } + } +} + +@Preview +@Composable +private fun ContentHeaderSample() { + MaterialTheme { + Surface { + ContentHeader(text = "MiddleEllipsisText Sample", onBackPressed = {}) + } + } +} diff --git a/sample/src/main/java/com/mataku/middleellipsistextsample/component/ContentHeader3.kt b/sample/src/main/java/com/mataku/middleellipsistextsample/component/ContentHeader3.kt new file mode 100644 index 0000000..9093b28 --- /dev/null +++ b/sample/src/main/java/com/mataku/middleellipsistextsample/component/ContentHeader3.kt @@ -0,0 +1,59 @@ +package com.mataku.middleellipsistextsample.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.rememberVectorPainter +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +@Composable +fun ContentHeader3( + text: String, + onBackPressed: (() -> Unit)? = null +) { + Surface( + shadowElevation = 2.dp + ) { + + Box( + modifier = Modifier + .fillMaxWidth() + ) { + if (onBackPressed != null) { + Image( + painter = rememberVectorPainter(image = Icons.AutoMirrored.Default.ArrowBack), + contentDescription = "back", + modifier = Modifier + .align(alignment = Alignment.CenterStart) + .clickable { + onBackPressed.invoke() + } + .padding(start = 12.dp) + ) + } + Text( + text = text, + style = TextStyle( + fontWeight = FontWeight.Medium, + fontSize = 24.sp, + letterSpacing = 0.15.sp + ), + modifier = Modifier + .padding(vertical = 16.dp) + .align(alignment = Alignment.Center) + ) + } + } +} diff --git a/sample/src/main/java/com/mataku/middleellipsistextsample/material/MaterialActivity.kt b/sample/src/main/java/com/mataku/middleellipsistextsample/material/MaterialActivity.kt new file mode 100644 index 0000000..94b07b6 --- /dev/null +++ b/sample/src/main/java/com/mataku/middleellipsistextsample/material/MaterialActivity.kt @@ -0,0 +1,20 @@ +package com.mataku.middleellipsistextsample.material + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface + +class MaterialActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + MaterialTheme { + Surface { + MaterialContent() + } + } + } + } +} diff --git a/sample/src/main/java/com/mataku/middleellipsistextsample/material/MaterialScreen.kt b/sample/src/main/java/com/mataku/middleellipsistextsample/material/MaterialScreen.kt new file mode 100644 index 0000000..4c920b4 --- /dev/null +++ b/sample/src/main/java/com/mataku/middleellipsistextsample/material/MaterialScreen.kt @@ -0,0 +1,109 @@ +package com.mataku.middleellipsistextsample.material + +import androidx.activity.compose.LocalOnBackPressedDispatcherOwner +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.mataku.middleellipsistextsample.component.ContentHeader +import io.github.mataku.middleellipsistext.MiddleEllipsisText + + +@Composable +fun MaterialContent() { + val dispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher + + Column( + modifier = Modifier.fillMaxSize() + ) { + ContentHeader( + text = "Demo", + onBackPressed = { + dispatcher?.onBackPressed() + } + ) + + Spacer(modifier = Modifier.height(32.dp)) + + Text(text = "ellipsis applied", fontSize = 20.sp, fontWeight = FontWeight.Bold) + + MiddleEllipsisText( + text = "soooooooooooooooooooooooooooooooooooooooooooloooooooooooooooooooongtext", + ) + + Spacer(modifier = Modifier.height(32.dp)) + + Text( + text = "ellipsis applied with horizontal margin", + fontSize = 20.sp, + fontWeight = FontWeight.Bold + ) + + MiddleEllipsisText( + text = "sooooooooooooooooooooooooooooooooooooooooooooooloooooooooooooooooooongtext", + modifier = Modifier.padding(horizontal = 16.dp) + ) + + Spacer(modifier = Modifier.height(32.dp)) + + Text(text = "with multibyte string", fontSize = 20.sp, fontWeight = FontWeight.Bold) + + Spacer(modifier = Modifier.height(4.dp)) + + MiddleEllipsisText( + text = "あいうえお".repeat(10), + ) + + Spacer(modifier = Modifier.height(32.dp)) + + Text(text = "with short text", fontSize = 20.sp, fontWeight = FontWeight.Bold) + + Spacer(modifier = Modifier.height(4.dp)) + + MiddleEllipsisText( + text = "sooooooooooツツツツツツ", + ) + + Spacer(modifier = Modifier.height(32.dp)) + + Text(text = "with emoji", fontSize = 20.sp, fontWeight = FontWeight.Bold) + + Spacer(modifier = Modifier.height(4.dp)) + + val emojis2 = "\uD83D\uDE00".repeat(40) + + MiddleEllipsisText( + text = emojis2, + ) + + Spacer(modifier = Modifier.height(32.dp)) + Text(text = "with multi-codepoints emoji", fontSize = 20.sp, fontWeight = FontWeight.Bold) + + Spacer(modifier = Modifier.height(4.dp)) + + val emojis = "\uD83C\uDDE7\uD83C\uDDEB".repeat(40) + MiddleEllipsisText( + text = emojis, + ) + } +} + +@Preview +@Composable +private fun MainContentPreview() { + MaterialTheme { + Surface { + MaterialContent() + } + } +} diff --git a/sample/src/main/java/com/mataku/middleellipsistextsample/material3/Material3Activity.kt b/sample/src/main/java/com/mataku/middleellipsistextsample/material3/Material3Activity.kt new file mode 100644 index 0000000..8920f04 --- /dev/null +++ b/sample/src/main/java/com/mataku/middleellipsistextsample/material3/Material3Activity.kt @@ -0,0 +1,20 @@ +package com.mataku.middleellipsistextsample.material3 + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface + +class Material3Activity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + MaterialTheme { + Surface { + Material3Content() + } + } + } + } +} diff --git a/sample/src/main/java/com/mataku/middleellipsistextsample/material3/Material3Screen.kt b/sample/src/main/java/com/mataku/middleellipsistextsample/material3/Material3Screen.kt new file mode 100644 index 0000000..2a2fbc8 --- /dev/null +++ b/sample/src/main/java/com/mataku/middleellipsistextsample/material3/Material3Screen.kt @@ -0,0 +1,109 @@ +package com.mataku.middleellipsistextsample.material3 + +import androidx.activity.compose.LocalOnBackPressedDispatcherOwner +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.mataku.middleellipsistextsample.component.ContentHeader3 +import io.github.mataku.middleellipsistext3.MiddleEllipsisText + + +@Composable +fun Material3Content() { + val dispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher + + Column( + modifier = Modifier.fillMaxSize() + ) { + ContentHeader3( + text = "Demo", + onBackPressed = { + dispatcher?.onBackPressed() + } + ) + + Spacer(modifier = Modifier.height(32.dp)) + + Text(text = "ellipsis applied", fontSize = 20.sp, fontWeight = FontWeight.Bold) + + MiddleEllipsisText( + text = "soooooooooooooooooooooooooooooooooooooooooooloooooooooooooooooooongtext", + ) + + Spacer(modifier = Modifier.height(32.dp)) + + Text( + text = "ellipsis applied with horizontal margin", + fontSize = 20.sp, + fontWeight = FontWeight.Bold + ) + + MiddleEllipsisText( + text = "sooooooooooooooooooooooooooooooooooooooooooooooloooooooooooooooooooongtext", + modifier = Modifier.padding(horizontal = 16.dp) + ) + + Spacer(modifier = Modifier.height(32.dp)) + + Text(text = "with multibyte string", fontSize = 20.sp, fontWeight = FontWeight.Bold) + + Spacer(modifier = Modifier.height(4.dp)) + + MiddleEllipsisText( + text = "sooooooooooooooooooooooooooooooooooooooooooloooooooooooooooooooongtextツツツツツツ", + ) + + Spacer(modifier = Modifier.height(32.dp)) + + Text(text = "with short text", fontSize = 20.sp, fontWeight = FontWeight.Bold) + + Spacer(modifier = Modifier.height(4.dp)) + + MiddleEllipsisText( + text = "sooooooooooツツツツツツ", + ) + + Spacer(modifier = Modifier.height(32.dp)) + + Text(text = "with emoji", fontSize = 20.sp, fontWeight = FontWeight.Bold) + + Spacer(modifier = Modifier.height(4.dp)) + + val emojis2 = "\uD83D\uDE00".repeat(40) + + MiddleEllipsisText( + text = emojis2, + ) + + Spacer(modifier = Modifier.height(32.dp)) + Text(text = "with multi-codepoints emoji", fontSize = 20.sp, fontWeight = FontWeight.Bold) + + Spacer(modifier = Modifier.height(4.dp)) + + val emojis = "\uD83C\uDDE7\uD83C\uDDEB".repeat(40) + MiddleEllipsisText( + text = emojis, + ) + } +} + +@Preview +@Composable +private fun Material3ScreenPreview() { + MaterialTheme { + Surface { + Material3Content() + } + } +} From 7c631f2da60ebfc9402a3223a117212c486a6184 Mon Sep 17 00:00:00 2001 From: Takuma Homma Date: Sun, 14 Apr 2024 15:38:54 +0900 Subject: [PATCH 5/8] 17 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 19a100b..9d3a5a2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,7 +20,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: zulu - java-version: 11 + java-version: 17 - name: Cache gradle dir uses: actions/cache@v3 with: From 19213132cb485d2cdf968ca3c8ac3bea54373ab9 Mon Sep 17 00:00:00 2001 From: Takuma Homma Date: Sun, 14 Apr 2024 20:26:06 +0900 Subject: [PATCH 6/8] Separate snapshot and release publishing settings --- MiddleEllipsisText/build.gradle.kts | 32 +++++++++++++++++++++++----- MiddleEllipsisText3/build.gradle.kts | 32 +++++++++++++++++++++++----- gradle.properties | 3 +++ settings.gradle.kts | 1 + 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/MiddleEllipsisText/build.gradle.kts b/MiddleEllipsisText/build.gradle.kts index 9d11080..3b4ceaf 100644 --- a/MiddleEllipsisText/build.gradle.kts +++ b/MiddleEllipsisText/build.gradle.kts @@ -135,14 +135,36 @@ signing { val libName = "middle-ellipsis-text" -group = "io.github.mataku" -version = "1.0.1-SNAPSHOT" +group = rootProject.properties["groupId"] as String +version = rootProject.properties["version"] as String afterEvaluate { publishing { - publications.forEach { - val publication = it as? MavenPublication ?: return@forEach - with(publication) { + repositories { + maven { + name = "Snapshot" + val snapshotsRepoUrl = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") + url = snapshotsRepoUrl + credentials { + username = System.getenv("OSSRH_USERNAME") ?: rootProject.extra["ossrhUsername"] as String + password = System.getenv("OSSRH_PASSWORD") ?: rootProject.extra["ossrhPassword"] as String + } + } + + maven { + name = "Release" + val releasesRepoUrl = + uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/") + url = releasesRepoUrl + credentials { + username = System.getenv("OSSRH_USERNAME") ?: rootProject.extra["ossrhUsername"] as String + password = System.getenv("OSSRH_PASSWORD") ?: rootProject.extra["ossrhPassword"] as String + } + } + } + publications { + withType { + val publication = this pom { artifactId = if (publication.name == "kotlinMultiplatform") { libName diff --git a/MiddleEllipsisText3/build.gradle.kts b/MiddleEllipsisText3/build.gradle.kts index bed77da..57e2659 100644 --- a/MiddleEllipsisText3/build.gradle.kts +++ b/MiddleEllipsisText3/build.gradle.kts @@ -82,14 +82,36 @@ signing { } val libName = "middle-ellipsis-text3" -group = "io.github.mataku" -version = "1.0.1-SNAPSHOT" +group = rootProject.properties["groupId"] as String +version = rootProject.properties["version"] as String afterEvaluate { publishing { - publications.forEach { - val publication = it as? MavenPublication ?: return@forEach - with(publication) { + repositories { + maven { + name = "Snapshot" + val snapshotsRepoUrl = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") + url = snapshotsRepoUrl + credentials { + username = System.getenv("OSSRH_USERNAME") ?: rootProject.extra["ossrhUsername"] as String + password = System.getenv("OSSRH_PASSWORD") ?: rootProject.extra["ossrhPassword"] as String + } + } + + maven { + name = "Release" + val releasesRepoUrl = + uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/") + url = releasesRepoUrl + credentials { + username = System.getenv("OSSRH_USERNAME") ?: rootProject.extra["ossrhUsername"] as String + password = System.getenv("OSSRH_PASSWORD") ?: rootProject.extra["ossrhPassword"] as String + } + } + } + publications { + withType { + val publication = this pom { artifactId = if (publication.name == "kotlinMultiplatform") { libName diff --git a/gradle.properties b/gradle.properties index b137ca0..b28e1eb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -30,3 +30,6 @@ kotlin.mpp.applyDefaultHierarchyTemplate=false # Compose org.jetbrains.compose.experimental.uikit.enabled=true + +groupId = "io.github.mataku" +version="1.0.1-SNAPSHOT" diff --git a/settings.gradle.kts b/settings.gradle.kts index 66e176b..6c12f86 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,6 +4,7 @@ pluginManagement { google() mavenCentral() gradlePluginPortal() + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } } dependencyResolutionManagement { From 170cbcd3c37e563e8800cfd25c1b816980c7918c Mon Sep 17 00:00:00 2001 From: Takuma Homma Date: Sun, 14 Apr 2024 20:30:44 +0900 Subject: [PATCH 7/8] Rename tasks in release workflow --- .github/workflows/publish.yml | 6 +++--- .github/workflows/snapshot.yml | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/snapshot.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b754aca..1002ba4 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -23,12 +23,12 @@ jobs: uses: actions/setup-java@v3 with: distribution: zulu - java-version: 11 + java-version: 17 - name: Build run: | ./gradlew MiddleEllipsisText:assembleRelease ./gradlew MiddleEllipsisText3:assembleRelease - name: Publish to Sonatype run: | - ./gradlew MiddleEllipsisText:publishMavenPublicationToSonatypeRepository - ./gradlew MiddleEllipsisText3:publishMavenPublicationToSonatypeRepository + ./gradlew MiddleEllipsisText:publishMavenPublicationToReleaseRepository + ./gradlew MiddleEllipsisText3:publishMavenPublicationToReleaseRepository diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml new file mode 100644 index 0000000..6878ab2 --- /dev/null +++ b/.github/workflows/snapshot.yml @@ -0,0 +1,34 @@ +name: Publish + +on: + workflow_dispatch: + # release: + # types: [released] + +env: + OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} + OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} + SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }} + SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} + SIGNING_KEY: ${{ secrets.SIGNING_KEY }} + SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }} + +jobs: + publish: + name: Build and publish + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up JDK + uses: actions/setup-java@v3 + with: + distribution: zulu + java-version: 17 + - name: Build + run: | + ./gradlew MiddleEllipsisText:assembleRelease + ./gradlew MiddleEllipsisText3:assembleRelease + - name: Publish to Sonatype + run: | + ./gradlew MiddleEllipsisText:publishMavenPublicationToSnapshotRepository + ./gradlew MiddleEllipsisText3:publishMavenPublicationToSnapshotRepository From 4808e6ab6d29a824c1e16a2ddcee97145a09b008 Mon Sep 17 00:00:00 2001 From: Takuma Homma Date: Sun, 14 Apr 2024 20:31:50 +0900 Subject: [PATCH 8/8] snapshot --- .github/workflows/snapshot.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 6878ab2..4d172c3 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -1,9 +1,7 @@ -name: Publish +name: Snapshot Publish on: workflow_dispatch: - # release: - # types: [released] env: OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} @@ -14,8 +12,8 @@ env: SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }} jobs: - publish: - name: Build and publish + publish_snapshot: + name: Build and publish to snapshpt runs-on: ubuntu-latest steps: - uses: actions/checkout@v3