From 352cf3afaa9c5b87338958c2f90bd28c496d1c63 Mon Sep 17 00:00:00 2001 From: vivganes Date: Sun, 30 Apr 2023 07:11:10 +0530 Subject: [PATCH 01/19] allow attributes for images in markdown --- buildSrc/src/main/kotlin/Dependencies.kt | 1 + richtext-commonmark/build.gradle.kts | 2 ++ .../kotlin/com/halilibo/richtext/markdown/AstNodeConvert.kt | 2 ++ 3 files changed, 5 insertions(+) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index c56998a1..ccbf2d86 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -57,6 +57,7 @@ object Commonmark { val tables = "org.commonmark:commonmark-ext-gfm-tables:$version" val strikethrough = "org.commonmark:commonmark-ext-gfm-strikethrough:$version" val autolink = "org.commonmark:commonmark-ext-autolink:$version" + val imageAttributes = "org.commonmark:commonmark-ext-image-attributes:$version" } object AndroidConfiguration { diff --git a/richtext-commonmark/build.gradle.kts b/richtext-commonmark/build.gradle.kts index 8b4acb83..c1046999 100644 --- a/richtext-commonmark/build.gradle.kts +++ b/richtext-commonmark/build.gradle.kts @@ -28,6 +28,7 @@ kotlin { implementation(Commonmark.tables) implementation(Commonmark.strikethrough) implementation(Commonmark.autolink) + implementation(Commonmark.imageAttributes) } } @@ -41,6 +42,7 @@ kotlin { implementation(Commonmark.tables) implementation(Commonmark.strikethrough) implementation(Commonmark.autolink) + implementation(Commonmark.imageAttributes) } } diff --git a/richtext-commonmark/src/commonJvmAndroid/kotlin/com/halilibo/richtext/markdown/AstNodeConvert.kt b/richtext-commonmark/src/commonJvmAndroid/kotlin/com/halilibo/richtext/markdown/AstNodeConvert.kt index a9f3fa0a..8e165a91 100644 --- a/richtext-commonmark/src/commonJvmAndroid/kotlin/com/halilibo/richtext/markdown/AstNodeConvert.kt +++ b/richtext-commonmark/src/commonJvmAndroid/kotlin/com/halilibo/richtext/markdown/AstNodeConvert.kt @@ -47,6 +47,7 @@ import org.commonmark.ext.gfm.tables.TableCell.Alignment.RIGHT import org.commonmark.ext.gfm.tables.TableHead import org.commonmark.ext.gfm.tables.TableRow import org.commonmark.ext.gfm.tables.TablesExtension +import org.commonmark.ext.image.attributes.ImageAttributesExtension import org.commonmark.node.BlockQuote import org.commonmark.node.BulletList import org.commonmark.node.Code @@ -196,6 +197,7 @@ internal actual fun parsedMarkdownAst(text: String, options: MarkdownParseOption listOfNotNull( TablesExtension.create(), StrikethroughExtension.create(), + ImageAttributesExtension.create(), if (options.autolink) AutolinkExtension.create() else null ) ) From 29b8c918a627066f2269b7bd41d61cd77b146665 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Sat, 10 Jun 2023 17:18:42 -0400 Subject: [PATCH 02/19] Forces Coil to request the OriginalSize so that Images can be rendered in bigger sizes than just the line height. --- .../main/java/com/zachklipp/richtext/sample/MarkdownSample.kt | 4 ++++ .../kotlin/com/halilibo/richtext/markdown/RemoteImage.kt | 2 ++ 2 files changed, 6 insertions(+) diff --git a/android-sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt b/android-sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt index fc8350df..bbb20226 100644 --- a/android-sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt +++ b/android-sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt @@ -153,6 +153,10 @@ private val sampleMarkdown = """ ##### Header 5 ###### Header 6 --- + + ## Full-bleed Image + + ![](https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/1920px-Image_created_with_a_mobile_phone.png) ## Emphasis diff --git a/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt b/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt index 1e22b534..453c6480 100644 --- a/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt +++ b/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt @@ -16,6 +16,7 @@ import androidx.compose.ui.unit.dp import coil.annotation.ExperimentalCoilApi import coil.compose.rememberAsyncImagePainter import coil.request.ImageRequest +import coil.size.Size private val DEFAULT_IMAGE_SIZE = 64.dp @@ -33,6 +34,7 @@ internal actual fun RemoteImage( val painter = rememberAsyncImagePainter( ImageRequest.Builder(LocalContext.current) .data(data = url) + .size(Size.ORIGINAL) .crossfade(true) .build() ) From 2dfcad6691ed49364ca20203caf21b4206b1e929 Mon Sep 17 00:00:00 2001 From: Halil Ozercan Date: Fri, 30 Jun 2023 20:15:50 +0100 Subject: [PATCH 03/19] Update dependencies and release new version This commit updates Compose Multiplatform to 1.4.1 AGP to 7.4.0 Kotlin to 18.10 --- android-sample/build.gradle.kts | 9 +- buildSrc/build.gradle.kts | 4 +- buildSrc/src/main/kotlin/Dependencies.kt | 27 ++-- .../richtext-android-library.gradle.kts | 8 +- .../kotlin/richtext-kmp-library.gradle.kts | 9 ++ gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- printing/build.gradle.kts | 4 + printing/src/main/AndroidManifest.xml | 2 +- .../ui/printing/ComposePdfRenderer.kt | 8 +- richtext-commonmark/build.gradle.kts | 4 + richtext-ui-material/build.gradle.kts | 4 + richtext-ui-material3/build.gradle.kts | 4 + richtext-ui/build.gradle.kts | 6 +- .../ui/util/ConditionalTapGestureDetector.kt | 128 +++++++++--------- slideshow/build.gradle.kts | 4 + slideshow/src/main/AndroidManifest.xml | 2 +- .../richtext/ui/slideshow/Slideshow.kt | 6 +- 18 files changed, 137 insertions(+), 96 deletions(-) diff --git a/android-sample/build.gradle.kts b/android-sample/build.gradle.kts index 0def1f04..451f9463 100644 --- a/android-sample/build.gradle.kts +++ b/android-sample/build.gradle.kts @@ -4,6 +4,7 @@ plugins { } android { + namespace = "com.zachklipp.richtext.sample" compileSdk = AndroidConfiguration.compileSdk defaultConfig { @@ -15,7 +16,13 @@ android { compose = true } - kotlinOptions { jvmTarget = "11" } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" + } composeOptions { kotlinCompilerExtensionVersion = Compose.compilerVersion diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 339ffd46..0cef419f 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -10,8 +10,8 @@ plugins { dependencies { // keep in sync with Dependencies.BuildPlugins.androidGradlePlugin - implementation("com.android.tools.build:gradle:7.2.2") + implementation("com.android.tools.build:gradle:7.4.0") // keep in sync with Dependencies.Kotlin.gradlePlugin - implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10") + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10") implementation(kotlin("script-runtime")) } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index ccbf2d86..4742f8a4 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -1,18 +1,13 @@ object BuildPlugins { - val androidGradlePlugin = "com.android.tools.build:gradle:7.2.2" + // keep in sync with buildSrc/build.gradle.kts + val androidGradlePlugin = "com.android.tools.build:gradle:7.4.0" } object AndroidX { val activity = "androidx.activity:activity:1.5.0-rc01" val annotations = "androidx.annotation:annotation:1.1.0" val appcompat = "androidx.appcompat:appcompat:1.3.0" - val constraintLayout = "androidx.constraintlayout:constraintlayout:1.1.3" - val fragment = "androidx.fragment:fragment:1.2.2" val material = "com.google.android.material:material:1.1.0" - val recyclerview = "androidx.recyclerview:recyclerview:1.1.0" - val savedstate = "androidx.savedstate:savedstate-ktx:1.2.0-rc01" - val transition = "androidx.transition:transition:1.3.1" - val viewbinding = "androidx.databinding:viewbinding:3.6.1" } object Network { @@ -20,7 +15,8 @@ object Network { } object Kotlin { - val version = "1.7.10" + // keep in sync with buildSrc/build.gradle.kts + val version = "1.8.10" val binaryCompatibilityValidatorPlugin = "org.jetbrains.kotlinx:binary-compatibility-validator:0.9.0" val gradlePlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:$version" @@ -28,31 +24,30 @@ object Kotlin { val common = "org.jetbrains.kotlin:kotlin-test-common" val annotations = "org.jetbrains.kotlin:kotlin-test-annotations-common" val jdk = "org.jetbrains.kotlin:kotlin-test-junit" - val mockito = "com.nhaarman:mockito-kotlin-kt1.1:1.6.0" } } val ktlint = "org.jlleitschuh.gradle:ktlint-gradle:10.0.0" object Compose { - val version = "1.2.1" - val compilerVersion = "1.3.1" - val desktopVersion = "1.2.0" - val activity = "androidx.activity:activity-compose:1.6.0-rc01" + val version = "1.4.3" + val compilerVersion = "1.4.4" + val desktopVersion = "1.4.1" + val activity = "androidx.activity:activity-compose:1.7.2" val foundation = "androidx.compose.foundation:foundation:$version" val material = "androidx.compose.material:material:$version" - val material3 = "androidx.compose.material3:material3:1.0.0-beta02" + val material3 = "androidx.compose.material3:material3:1.0.1" val icons = "androidx.compose.material:material-icons-extended:$version" val test = "androidx.ui:ui-test:$version" val tooling = "androidx.compose.ui:ui-tooling:$version" val toolingData = "androidx.compose.ui:ui-tooling-data:$version" val desktopPreview = "org.jetbrains.compose.ui:ui-tooling-preview-desktop:$desktopVersion" val multiplatformUiUtil = "org.jetbrains.compose.ui:ui-util:$desktopVersion" - val coil = "io.coil-kt:coil-compose:2.2.1" + val coil = "io.coil-kt:coil-compose:2.4.0" } object Commonmark { - private val version = "0.20.0" + private val version = "0.21.0" val core = "org.commonmark:commonmark:$version" val tables = "org.commonmark:commonmark-ext-gfm-tables:$version" val strikethrough = "org.commonmark:commonmark-ext-gfm-strikethrough:$version" diff --git a/buildSrc/src/main/kotlin/richtext-android-library.gradle.kts b/buildSrc/src/main/kotlin/richtext-android-library.gradle.kts index 80564a05..6ae88989 100644 --- a/buildSrc/src/main/kotlin/richtext-android-library.gradle.kts +++ b/buildSrc/src/main/kotlin/richtext-android-library.gradle.kts @@ -17,7 +17,13 @@ android { targetSdk = AndroidConfiguration.targetSdk } - kotlinOptions { jvmTarget = "11" } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" + } buildFeatures { compose = true diff --git a/buildSrc/src/main/kotlin/richtext-kmp-library.gradle.kts b/buildSrc/src/main/kotlin/richtext-kmp-library.gradle.kts index 5f39c7de..c7412748 100644 --- a/buildSrc/src/main/kotlin/richtext-kmp-library.gradle.kts +++ b/buildSrc/src/main/kotlin/richtext-kmp-library.gradle.kts @@ -14,6 +14,9 @@ kotlin { jvm() android { publishLibraryVariants("release", "debug") + compilations.all { + kotlinOptions.jvmTarget = "11" + } } explicitApi() } @@ -21,6 +24,12 @@ kotlin { android { compileSdk = 33 sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + defaultConfig { minSdk = 21 targetSdk = compileSdk diff --git a/gradle.properties b/gradle.properties index b36deb34..81f7437d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,7 +22,7 @@ kotlin.code.style=official systemProp.org.gradle.internal.publish.checksums.insecure=true GROUP=com.halilibo.compose-richtext -VERSION_NAME=0.16.0 +VERSION_NAME=0.17.0 POM_DESCRIPTION=A collection of Compose libraries for advanced text formatting and alternative display types. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fce..3a029079 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.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/printing/build.gradle.kts b/printing/build.gradle.kts index c6b65698..21fb919b 100644 --- a/printing/build.gradle.kts +++ b/printing/build.gradle.kts @@ -3,6 +3,10 @@ plugins { id("org.jetbrains.dokka") } +android { + namespace = "com.zachklipp.richtext.ui.printing" +} + dependencies { implementation(Compose.foundation) implementation(Compose.tooling) diff --git a/printing/src/main/AndroidManifest.xml b/printing/src/main/AndroidManifest.xml index b4b8b1fe..cc947c56 100644 --- a/printing/src/main/AndroidManifest.xml +++ b/printing/src/main/AndroidManifest.xml @@ -1 +1 @@ - + diff --git a/printing/src/main/java/com/zachklipp/richtext/ui/printing/ComposePdfRenderer.kt b/printing/src/main/java/com/zachklipp/richtext/ui/printing/ComposePdfRenderer.kt index 1098796f..d9bf1f73 100644 --- a/printing/src/main/java/com/zachklipp/richtext/ui/printing/ComposePdfRenderer.kt +++ b/printing/src/main/java/com/zachklipp/richtext/ui/printing/ComposePdfRenderer.kt @@ -24,8 +24,8 @@ import androidx.compose.ui.graphics.Color.Companion.White import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.Density -import androidx.lifecycle.ViewTreeLifecycleOwner -import androidx.lifecycle.ViewTreeViewModelStoreOwner +import androidx.lifecycle.setViewTreeLifecycleOwner +import androidx.lifecycle.setViewTreeViewModelStoreOwner import androidx.savedstate.setViewTreeSavedStateRegistryOwner import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay @@ -175,8 +175,8 @@ private fun createWindowComposeView( activity: ComponentActivity, content: @Composable () -> Unit ): View = ComposeView(activity).apply { - ViewTreeLifecycleOwner.set(this, activity) - ViewTreeViewModelStoreOwner.set(this, activity) + this.setViewTreeLifecycleOwner(activity) + this.setViewTreeViewModelStoreOwner(activity) setViewTreeSavedStateRegistryOwner(activity) setContent(content) } diff --git a/richtext-commonmark/build.gradle.kts b/richtext-commonmark/build.gradle.kts index c1046999..46f73d99 100644 --- a/richtext-commonmark/build.gradle.kts +++ b/richtext-commonmark/build.gradle.kts @@ -8,6 +8,10 @@ repositories { maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } +android { + namespace = "com.halilibo.richtext.markdown" +} + kotlin { sourceSets { val commonMain by getting { diff --git a/richtext-ui-material/build.gradle.kts b/richtext-ui-material/build.gradle.kts index 7a4699cd..5d07cc34 100644 --- a/richtext-ui-material/build.gradle.kts +++ b/richtext-ui-material/build.gradle.kts @@ -8,6 +8,10 @@ repositories { maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } +android { + namespace = "com.halilibo.richtext.ui.material" +} + kotlin { sourceSets { val commonMain by getting { diff --git a/richtext-ui-material3/build.gradle.kts b/richtext-ui-material3/build.gradle.kts index 416c0e92..ef0a16fa 100644 --- a/richtext-ui-material3/build.gradle.kts +++ b/richtext-ui-material3/build.gradle.kts @@ -8,6 +8,10 @@ repositories { maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } +android { + namespace = "com.halilibo.richtext.ui.material3" +} + kotlin { sourceSets { val commonMain by getting { diff --git a/richtext-ui/build.gradle.kts b/richtext-ui/build.gradle.kts index 3b5a50bf..5eb08c36 100644 --- a/richtext-ui/build.gradle.kts +++ b/richtext-ui/build.gradle.kts @@ -1,5 +1,3 @@ -import org.jetbrains.compose.compose - plugins { id("richtext-kmp-library") id("org.jetbrains.compose") version Compose.desktopVersion @@ -10,6 +8,10 @@ repositories { maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } +android { + namespace = "com.halilibo.richtext.ui" +} + kotlin { sourceSets { val commonMain by getting { diff --git a/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/util/ConditionalTapGestureDetector.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/util/ConditionalTapGestureDetector.kt index e4ea2360..7e0f7c21 100644 --- a/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/util/ConditionalTapGestureDetector.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/util/ConditionalTapGestureDetector.kt @@ -4,7 +4,9 @@ package com.halilibo.richtext.ui.util import androidx.compose.foundation.gestures.GestureCancellationException import androidx.compose.foundation.gestures.PressGestureScope +import androidx.compose.foundation.gestures.awaitEachGesture import androidx.compose.foundation.gestures.awaitFirstDown +import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.gestures.forEachGesture import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.geometry.Offset @@ -64,79 +66,77 @@ public suspend fun PointerInputScope.detectTapGesturesIf( val pressScope = PressGestureScopeImpl(this@detectTapGesturesIf) - forEachGesture { - awaitPointerEventScope { - val down = awaitFirstDown() - if (!predicate(down.position)) { - pressScope.reset() - return@awaitPointerEventScope - } - down.consume() + awaitEachGesture { + val down = awaitFirstDown() + if (!predicate(down.position)) { pressScope.reset() - if (onPress !== NoPressGesture) launch { - pressScope.onPress(down.position) + return@awaitEachGesture + } + down.consume() + pressScope.reset() + if (onPress !== NoPressGesture) launch { + pressScope.onPress(down.position) + } + val longPressTimeout = onLongPress?.let { + viewConfiguration.longPressTimeoutMillis + } ?: (Long.MAX_VALUE / 2) + var upOrCancel: PointerInputChange? = null + try { + // wait for first tap up or long press + upOrCancel = withTimeout(longPressTimeout) { + waitForUpOrCancellation() } - val longPressTimeout = onLongPress?.let { - viewConfiguration.longPressTimeoutMillis - } ?: (Long.MAX_VALUE / 2) - var upOrCancel: PointerInputChange? = null - try { - // wait for first tap up or long press - upOrCancel = withTimeout(longPressTimeout) { - waitForUpOrCancellation() - } - if (upOrCancel == null) { - pressScope.cancel() // tap-up was canceled - } else { - upOrCancel.consume() - pressScope.release() - } - } catch (_: PointerEventTimeoutCancellationException) { - onLongPress?.invoke(down.position) - consumeUntilUp() + if (upOrCancel == null) { + pressScope.cancel() // tap-up was canceled + } else { + upOrCancel.consume() pressScope.release() } + } catch (_: PointerEventTimeoutCancellationException) { + onLongPress?.invoke(down.position) + consumeUntilUp() + pressScope.release() + } + + if (upOrCancel != null) { + // tap was successful. + if (onDoubleTap == null) { + onTap?.invoke(upOrCancel.position) // no need to check for double-tap. + } else { + // check for second tap + val secondDown = awaitSecondDown(upOrCancel) - if (upOrCancel != null) { - // tap was successful. - if (onDoubleTap == null) { - onTap?.invoke(upOrCancel.position) // no need to check for double-tap. + if (secondDown == null) { + onTap?.invoke(upOrCancel.position) // no valid second tap started } else { - // check for second tap - val secondDown = awaitSecondDown(upOrCancel) - - if (secondDown == null) { - onTap?.invoke(upOrCancel.position) // no valid second tap started - } else { - // Second tap down detected - pressScope.reset() - if (onPress !== NoPressGesture) { - launch { pressScope.onPress(secondDown.position) } - } + // Second tap down detected + pressScope.reset() + if (onPress !== NoPressGesture) { + launch { pressScope.onPress(secondDown.position) } + } - try { - // Might have a long second press as the second tap - withTimeout(longPressTimeout) { - val secondUp = waitForUpOrCancellation() - if (secondUp != null) { - secondUp.consume() - pressScope.release() - onDoubleTap(secondUp.position) - } else { - pressScope.cancel() - onTap?.invoke(upOrCancel.position) - } + try { + // Might have a long second press as the second tap + withTimeout(longPressTimeout) { + val secondUp = waitForUpOrCancellation() + if (secondUp != null) { + secondUp.consume() + pressScope.release() + onDoubleTap(secondUp.position) + } else { + pressScope.cancel() + onTap?.invoke(upOrCancel.position) } - } catch (e: PointerEventTimeoutCancellationException) { - // The first tap was valid, but the second tap is a long press. - // notify for the first tap - onTap?.invoke(upOrCancel.position) - - // notify for the long press - onLongPress?.invoke(secondDown.position) - consumeUntilUp() - pressScope.release() } + } catch (e: PointerEventTimeoutCancellationException) { + // The first tap was valid, but the second tap is a long press. + // notify for the first tap + onTap?.invoke(upOrCancel.position) + + // notify for the long press + onLongPress?.invoke(secondDown.position) + consumeUntilUp() + pressScope.release() } } } diff --git a/slideshow/build.gradle.kts b/slideshow/build.gradle.kts index 3022eb7b..c93de4e8 100644 --- a/slideshow/build.gradle.kts +++ b/slideshow/build.gradle.kts @@ -3,6 +3,10 @@ plugins { id("org.jetbrains.dokka") } +android { + namespace = "com.zachklipp.richtext.ui.slideshow" +} + dependencies { implementation(Compose.foundation) implementation(Compose.material) diff --git a/slideshow/src/main/AndroidManifest.xml b/slideshow/src/main/AndroidManifest.xml index bb74b8ce..dbf799a7 100644 --- a/slideshow/src/main/AndroidManifest.xml +++ b/slideshow/src/main/AndroidManifest.xml @@ -1 +1 @@ - + diff --git a/slideshow/src/main/java/com/zachklipp/richtext/ui/slideshow/Slideshow.kt b/slideshow/src/main/java/com/zachklipp/richtext/ui/slideshow/Slideshow.kt index 0b3c061e..f70c555a 100644 --- a/slideshow/src/main/java/com/zachklipp/richtext/ui/slideshow/Slideshow.kt +++ b/slideshow/src/main/java/com/zachklipp/richtext/ui/slideshow/Slideshow.kt @@ -257,8 +257,10 @@ private fun Modifier.splitClickable( onClick: (left: Boolean) -> Unit ): Modifier = composed { val sizeRef = remember { Ref() } - val splitPoint by derivedStateOf { - (sizeRef.value?.width ?: 0) * splitFraction + val splitPoint by remember { + derivedStateOf { + (sizeRef.value?.width ?: 0) * splitFraction + } } onSizeChanged { sizeRef.value = it } From f25b6bdf1b40da21e03478678539b994f1ec6fa0 Mon Sep 17 00:00:00 2001 From: Halil Ozercan Date: Sun, 2 Jul 2023 14:25:14 +0100 Subject: [PATCH 04/19] Fix dokka --- build.gradle.kts | 2 +- gradle.properties | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2e361692..c90e3dfc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,7 +22,7 @@ buildscript { } plugins { - id("org.jetbrains.dokka") version "1.5.0" + id("org.jetbrains.dokka") version "1.8.10" } repositories { diff --git a/gradle.properties b/gradle.properties index 81f7437d..6264f5ea 100644 --- a/gradle.properties +++ b/gradle.properties @@ -27,3 +27,4 @@ VERSION_NAME=0.17.0 POM_DESCRIPTION=A collection of Compose libraries for advanced text formatting and alternative display types. kotlin.mpp.stability.nowarn=true +kotlin.mpp.androidSourceSetLayoutVersion=2 \ No newline at end of file From 6bfaa495d6f1a7c06bec4d6d7528a78cddb10cdf Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 7 Aug 2023 18:13:34 -0400 Subject: [PATCH 05/19] BugFix: Image goes over the text (#117) --- .../richtext/sample/MarkdownSample.kt | 34 ++++++++++++------- .../com/halilibo/richtext/desktop/Main.kt | 31 +++++++++++++---- .../halilibo/richtext/markdown/RemoteImage.kt | 5 ++- .../richtext/ui/string/RichTextString.kt | 12 +++++++ 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/android-sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt b/android-sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt index bbb20226..1e9c1557 100644 --- a/android-sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt +++ b/android-sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material.Card import androidx.compose.material.Checkbox import androidx.compose.material.MaterialTheme +import androidx.compose.material.ProvideTextStyle import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.material.darkColors @@ -25,8 +26,10 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.em import com.halilibo.richtext.markdown.Markdown import com.halilibo.richtext.markdown.MarkdownParseOptions import com.halilibo.richtext.ui.RichTextStyle @@ -100,17 +103,19 @@ import com.halilibo.richtext.ui.resolveDefaults SelectionContainer { Column(Modifier.verticalScroll(rememberScrollState())) { - MaterialRichText( - style = richTextStyle, - modifier = Modifier.padding(8.dp), - ) { - Markdown( - content = sampleMarkdown, - markdownParseOptions = markdownParseOptions, - onLinkClicked = { - Toast.makeText(context, it, Toast.LENGTH_SHORT).show() - } - ) + ProvideTextStyle(TextStyle(lineHeight = 1.3.em)) { + MaterialRichText( + style = richTextStyle, + modifier = Modifier.padding(8.dp), + ) { + Markdown( + content = sampleMarkdown, + markdownParseOptions = markdownParseOptions, + onLinkClicked = { + Toast.makeText(context, it, Toast.LENGTH_SHORT).show() + } + ) + } } } } @@ -155,9 +160,14 @@ private val sampleMarkdown = """ --- ## Full-bleed Image - ![](https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/1920px-Image_created_with_a_mobile_phone.png) + ## Images smaller than the width should center + ![](https://cdn.nostr.build/p/4a84.png) + + On LineHeight bug, the image below goes over this text. + ![](https://cdn.nostr.build/p/PxZ0.jpg) + ## Emphasis Emphasis, aka italics, with *asterisks* or _underscores_. diff --git a/desktop-sample/src/main/kotlin/com/halilibo/richtext/desktop/Main.kt b/desktop-sample/src/main/kotlin/com/halilibo/richtext/desktop/Main.kt index ae85ea22..16a1a6d9 100644 --- a/desktop-sample/src/main/kotlin/com/halilibo/richtext/desktop/Main.kt +++ b/desktop-sample/src/main/kotlin/com/halilibo/richtext/desktop/Main.kt @@ -15,6 +15,7 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.foundation.verticalScroll +import androidx.compose.material.ProvideTextStyle import androidx.compose.material.Slider import androidx.compose.material.Surface import androidx.compose.material.Text @@ -26,8 +27,10 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.em import androidx.compose.ui.unit.sp import androidx.compose.ui.window.singleWindowApplication import com.halilibo.richtext.markdown.Markdown @@ -76,13 +79,15 @@ fun main(): Unit = singleWindowApplication( .padding(8.dp) ) } - MaterialRichText( - modifier = Modifier - .weight(1f) - .verticalScroll(rememberScrollState()), - style = richTextStyle - ) { - Markdown(content = text) + ProvideTextStyle(TextStyle(lineHeight = 1.3.em)) { + MaterialRichText( + modifier = Modifier + .weight(1f) + .verticalScroll(rememberScrollState()), + style = richTextStyle + ) { + Markdown(content = text) + } } } } @@ -177,6 +182,18 @@ private val sampleMarkdown = """ ###### Header 6 --- + ## Full-bleed Image + + ![](https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/1920px-Image_created_with_a_mobile_phone.png) + + ## Images smaller than the width should center + ![](https://cdn.nostr.build/p/4a84.png) + + On LineHeight bug, the image below goes over this text. + ![](https://cdn.nostr.build/p/PxZ0.jpg) + + --- + ## Emphasis Emphasis, aka italics, with *asterisks* or _underscores_. diff --git a/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt b/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt index 453c6480..9d865300 100644 --- a/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt +++ b/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt @@ -7,13 +7,13 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.isSpecified import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp -import coil.annotation.ExperimentalCoilApi import coil.compose.rememberAsyncImagePainter import coil.request.ImageRequest import coil.size.Size @@ -23,7 +23,6 @@ private val DEFAULT_IMAGE_SIZE = 64.dp /** * Implementation of RemoteImage by using Coil library for Android. */ -@OptIn(ExperimentalCoilApi::class) @Composable internal actual fun RemoteImage( url: String, @@ -41,7 +40,7 @@ internal actual fun RemoteImage( val density = LocalDensity.current - BoxWithConstraints { + BoxWithConstraints(modifier, contentAlignment = Alignment.Center) { val sizeModifier by remember(density, painter) { derivedStateOf { val painterIntrinsicSize = painter.state.painter?.intrinsicSize diff --git a/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/string/RichTextString.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/string/RichTextString.kt index 35355a71..d175c2f1 100644 --- a/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/string/RichTextString.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/string/RichTextString.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.text.appendInlineContent import androidx.compose.runtime.Immutable import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.ParagraphStyle import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontFamily @@ -295,7 +296,18 @@ public data class RichTextString internal constructor( ) { val tag = randomUUID() formatObjects["inline:$tag"] = content + + // Resets the style to defaults. + // + // This is important for inline content because the user might set a global line height + // via ProvideTextStyle(TextStyle(lineHeight = 1.3.em)) { ... } + // Once set, the line height is fixed for all objects and any inline content (like images) + // will expand over the text. Since this is not a text section, it should be fine. + // + // Fixed line height seems to only affect mobile. + builder.pushStyle(ParagraphStyle()) builder.appendInlineContent(tag, alternateText) + builder.pop() } /** From c35d10a2a14e2f56dd139cec35f88cdcf3bb6141 Mon Sep 17 00:00:00 2001 From: Halil Ozercan Date: Wed, 3 Jan 2024 20:42:49 +0000 Subject: [PATCH 06/19] 0.20.0 Update Version updates; - Kotlin 1.9.20 - AGP 8.2.0 - Gradle 8.2 - Compose Multiplatform: 1.5.11 - Compose Compiler: 1.5.4 Api Updates; - Renamed RichText to BasicRichText - Renamed MaterialRichText to RichText - Renamed Material3RichText to RichText - Removed SetupMaterialRichText - Removed SetupMaterial3RichText --- .github/workflows/android.yml | 8 +- .github/workflows/docs.yml | 2 +- .github/workflows/publish.yml | 4 +- .idea/codeStyles/Project.xml | 3 - .../com/zachklipp/richtext/sample/Demo.kt | 4 +- .../richtext/sample/DocumentSample.kt | 4 +- .../richtext/sample/MarkdownSample.kt | 4 +- .../richtext/sample/SlideshowSample.kt | 4 +- .../com/zachklipp/richtext/sample/TextDemo.kt | 4 +- buildSrc/build.gradle.kts | 4 +- buildSrc/src/main/kotlin/Dependencies.kt | 12 +-- .../kotlin/richtext-kmp-library.gradle.kts | 2 +- .../com/halilibo/richtext/desktop/Main.kt | 7 +- docs/index.md | 8 +- docs/richtext-commonmark.md | 11 +-- docs/richtext-ui-material.md | 32 ++------ docs/richtext-ui-material3.md | 36 +++----- docs/richtext-ui.md | 14 ++-- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../{MaterialRichText.kt => RichText.kt} | 30 +++---- .../{MaterialRichText3.kt => RichText.kt} | 30 +++---- .../ui/{RichText.kt => BasicRichText.kt} | 2 +- .../com/halilibo/richtext/ui/BlockQuote.kt | 2 +- .../com/halilibo/richtext/ui/CodeBlock.kt | 5 +- .../com/halilibo/richtext/ui/FormattedList.kt | 2 +- .../com/halilibo/richtext/ui/Heading.kt | 7 +- .../com/halilibo/richtext/ui/InfoPanel.kt | 2 +- .../halilibo/richtext/ui/RichTextLocals.kt | 4 +- .../com/halilibo/richtext/ui/RichTextScope.kt | 4 +- .../richtext/ui/RichTextThemeConfiguration.kt | 46 +++++++++++ .../richtext/ui/RichTextThemeIntegration.kt | 82 ------------------- .../richtext/ui/RichTextThemeProvider.kt | 52 ++++++++++++ .../kotlin/com/halilibo/richtext/ui/Table.kt | 9 +- 34 files changed, 199 insertions(+), 245 deletions(-) rename richtext-ui-material/src/commonMain/kotlin/com/halilibo/richtext/ui/material/{MaterialRichText.kt => RichText.kt} (69%) rename richtext-ui-material3/src/commonMain/kotlin/com/halilibo/richtext/ui/material3/{MaterialRichText3.kt => RichText.kt} (69%) rename richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/{RichText.kt => BasicRichText.kt} (97%) create mode 100644 richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextThemeConfiguration.kt delete mode 100644 richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextThemeIntegration.kt create mode 100644 richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextThemeProvider.kt diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 74f7c726..922d0110 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -11,10 +11,10 @@ jobs: steps: - uses: actions/checkout@v2 - uses: gradle/wrapper-validation-action@v1 - - name: set up JDK 11 + - name: set up JDK 17 uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - uses: actions/cache@v1 with: path: ~/.gradle/caches @@ -32,10 +32,10 @@ jobs: - 29 steps: - uses: actions/checkout@v2 - - name: set up JDK 11 + - name: set up JDK 17 uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - uses: actions/cache@v1 with: path: ~/.gradle/caches diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index deaeea81..3fc96a74 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - uses: actions/setup-python@v2 with: python-version: 3.x diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8210749b..538e7069 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -12,10 +12,10 @@ jobs: steps: - uses: actions/checkout@v2 - uses: gradle/wrapper-validation-action@v1 - - name: set up JDK 11 + - name: set up JDK 17 uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - uses: actions/cache@v1 with: path: ~/.gradle/caches diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index dc9f22b7..a3589852 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -86,9 +86,6 @@