From b4cf2cfdd374276ce7d13810961bed76ee5f8dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=9A=A9=EC=9D=80?= Date: Mon, 27 Jul 2026 09:23:28 +0900 Subject: [PATCH 1/4] fix(editor): colour the caret from the theme (#283) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The note editor's `BasicTextField` never passed `cursorBrush`, so Compose's default — `SolidColor(Color.Black)` — was in effect. On a dark background that left a black caret on a near-black page, in both Markleaf Green and Material You, while the drag handle beside it was themed all along. It is the only raw foundation text field in the app; every Material field already takes its cursor colour from the theme, and `primary` is what they use. `ThemedCaretTest` scans `src/main` and fails if a `BasicTextField` call site omits `cursorBrush`. Nothing else could catch this class of defect: the caret blinks, so a Roborazzi golden cannot assert it, and lint has no opinion about a Compose default. Verified by removing the fix and watching the test name the call site. Co-Authored-By: Claude Opus 5 --- .../notes/feature/editor/EditorScreen.kt | 9 ++ .../com/markleaf/notes/ThemedCaretTest.kt | 100 ++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 app/src/test/java/com/markleaf/notes/ThemedCaretTest.kt diff --git a/app/src/main/java/com/markleaf/notes/feature/editor/EditorScreen.kt b/app/src/main/java/com/markleaf/notes/feature/editor/EditorScreen.kt index d52b0d2..0a622b9 100644 --- a/app/src/main/java/com/markleaf/notes/feature/editor/EditorScreen.kt +++ b/app/src/main/java/com/markleaf/notes/feature/editor/EditorScreen.kt @@ -59,6 +59,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.input.key.Key import androidx.compose.ui.input.key.KeyEventType import androidx.compose.ui.input.key.isShiftPressed @@ -950,6 +951,14 @@ fun EditorScreen( color = MaterialTheme.colorScheme.onBackground ), visualTransformation = markdownVisualTransformation, + // `BasicTextField` defaults its caret to opaque black, and + // this is the only field in the app that draws its own — + // every Material text field takes the colour from the theme. + // On a dark background the default was all but invisible + // while the drag handle beside it was themed, in both + // Markleaf Green and Material You (#283). `primary` is what + // the Material fields use, so the caret now matches them. + cursorBrush = SolidColor(colorScheme.primary), decorationBox = { innerTextField -> Box(modifier = Modifier.fillMaxSize()) { innerTextField() diff --git a/app/src/test/java/com/markleaf/notes/ThemedCaretTest.kt b/app/src/test/java/com/markleaf/notes/ThemedCaretTest.kt new file mode 100644 index 0000000..c794888 --- /dev/null +++ b/app/src/test/java/com/markleaf/notes/ThemedCaretTest.kt @@ -0,0 +1,100 @@ +package com.markleaf.notes + +import java.io.File +import org.junit.Assert.assertTrue +import org.junit.Test + +/** + * Fails if a `BasicTextField` in `src/main` never says what colour its caret is. + * + * Compose defaults `cursorBrush` to `SolidColor(Color.Black)`, a literal that no + * theme touches. The note editor is the app's only raw foundation text field — + * every Material field takes its cursor colour from the theme — so it drew a + * black caret on a dark background, all but invisible in both Markleaf Green and + * Material You, while the drag handle right beside it was themed (#283). + * + * Nothing else in the suite can see this: the caret blinks, so a Roborazzi + * golden cannot assert it, `HardcodedStringTest` looks at text rather than + * colour, and lint has no opinion about a Compose default. What this checks is + * only that the colour is stated at the call site; whether it contrasts is a + * judgement the theme makes. + */ +class ThemedCaretTest { + + @Test + fun everyBasicTextFieldSetsItsCursorBrush() { + val root = File("src/main/java") + assertTrue( + "Expected the app module as the working directory, but ${root.absolutePath} " + + "does not exist", + root.isDirectory + ) + + val callSites = mutableListOf>() + root.walkTopDown().filter { it.isFile && it.extension == "kt" }.forEach { file -> + val relative = file.relativeTo(root).invariantSeparatorsPath + val lines = file.readLines() + lines.forEachIndexed { index, line -> + if (line.trimStart().startsWith("//")) return@forEachIndexed + val opening = CALL.find(line) ?: return@forEachIndexed + callSites += "$relative:${index + 1}" to callText(lines, index, opening.range.last) + } + } + + // A scan that matches nothing passes for the wrong reason — the editor + // could move to another text field API and take the blind spot with it. + assertTrue( + "Expected at least one BasicTextField call site in src/main, found none. " + + "If the editor no longer uses one, this test needs rewriting rather " + + "than deleting: the caret still has to come from the theme.", + callSites.isNotEmpty() + ) + + val offenders = callSites.filterNot { (_, call) -> "cursorBrush" in call }.map { it.first } + assertTrue( + buildString { + appendLine("These BasicTextField call sites do not set cursorBrush, so the caret") + appendLine("falls back to Compose's opaque black and ignores the theme (#283).") + appendLine("Pass a brush built from MaterialTheme.colorScheme:") + offenders.forEach { appendLine(" - $it") } + }, + offenders.isEmpty() + ) + } + + /** + * The source of the call that opens at [column] of line [start], up to its + * closing parenthesis. Parentheses inside string and character literals are + * ignored, as are trailing line comments, so a `")"` in an argument cannot + * end the call early. + */ + private fun callText(lines: List, start: Int, column: Int): String { + val text = StringBuilder() + var depth = 0 + for (index in start until lines.size) { + val line = lines[index] + text.appendLine(line) + val counted = if (index == start) line.substring(column) else line + for (char in strippedOfLiterals(counted)) { + when (char) { + '(' -> depth++ + ')' -> depth-- + } + } + if (depth <= 0) break + } + return text.toString() + } + + /** Literals go first: a `"https://…"` argument must not read as a comment. */ + private fun strippedOfLiterals(line: String) = + LITERAL.replace(line, "").substringBefore("//") + + private companion object { + /** The `(` at the end of the match is where the argument list opens. */ + val CALL = Regex("""\bBasicTextField\s*\(""") + + /** String and character literals, escapes included, so `"\")"` is inert. */ + val LITERAL = Regex(""""(\\.|[^"\\])*"|'(\\.|[^'\\])*'""") + } +} From c9edc43a7febea97c8fe9b8437384bbf16f90f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=9A=A9=EC=9D=80?= Date: Mon, 27 Jul 2026 09:23:37 +0900 Subject: [PATCH 2/4] chore: prepare v2.32.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Version bump, both CHANGELOG editions, six store changelogs (428 chars at the longest, against the 500-char Play cap — every locale now keeps more than the 50 characters of headroom `verify-release-notes.ps1` warns below), and the version strings on the six landing pages and six READMEs. THANKS.md gains @ElizabethWega for #283, and picks up #279 and #280 on @bit2bold's row — those two were reported after the file was last touched. Co-Authored-By: Claude Opus 5 --- CHANGELOG.ko.md | 7 +++++++ CHANGELOG.md | 7 +++++++ README.de.md | 4 ++-- README.es.md | 4 ++-- README.fr.md | 4 ++-- README.ja.md | 4 ++-- README.ko.md | 4 ++-- README.md | 4 ++-- THANKS.md | 3 ++- app/build.gradle.kts | 4 ++-- docs/index.de.html | 6 +++--- docs/index.es.html | 6 +++--- docs/index.fr.html | 6 +++--- docs/index.html | 6 +++--- docs/index.ja.html | 6 +++--- docs/index.ko.html | 6 +++--- fastlane/metadata/android/de-DE/changelogs/123.txt | 1 + fastlane/metadata/android/en-US/changelogs/123.txt | 1 + fastlane/metadata/android/es-ES/changelogs/123.txt | 1 + fastlane/metadata/android/fr-FR/changelogs/123.txt | 1 + fastlane/metadata/android/ja-JP/changelogs/123.txt | 1 + fastlane/metadata/android/ko-KR/changelogs/123.txt | 1 + 22 files changed, 54 insertions(+), 33 deletions(-) create mode 100644 fastlane/metadata/android/de-DE/changelogs/123.txt create mode 100644 fastlane/metadata/android/en-US/changelogs/123.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/123.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/123.txt create mode 100644 fastlane/metadata/android/ja-JP/changelogs/123.txt create mode 100644 fastlane/metadata/android/ko-KR/changelogs/123.txt diff --git a/CHANGELOG.ko.md b/CHANGELOG.ko.md index 216d930..f7104f8 100644 --- a/CHANGELOG.ko.md +++ b/CHANGELOG.ko.md @@ -6,6 +6,13 @@ Markleaf의 주요 변경 사항을 기록합니다. 영어판이 기본이며 G v2.15.3 이전 항목은 이 파일에만 한국어로 보존되어 있습니다. +## v2.32.1 - 어두운 화면에서도 보이는 커서 (A caret you can see in the dark) - 2026-07-27 + +편집기 수정 한 건이며, F-Droid 설치본에서 제보되었습니다. 기능·권한·저장 형식 변경은 없습니다. + +### Fixed +- **텍스트 커서가 검은색에 머물지 않고 테마 색을 따릅니다 (#283).** 노트 편집기는 Markleaf에서 커서를 직접 그리는 유일한 입력란인데 색을 지정하지 않아, 프레임워크 기본값인 불투명한 검정이 그대로 쓰였습니다. 어두운 배경에서는 거의 검은 화면 위에 검은 막대가 놓인 셈이라 *Markleaf 그린*과 *Material You* 양쪽에서 찾기 어려웠고, 바로 옆의 드래그 핸들은 처음부터 테마 색이었던 탓에 더 어긋나 보였습니다. 이제 커서는 검색창과 대화상자가 쓰는 것과 같은 테마 강조색을 씁니다 — 어두운 *Markleaf 그린*에서는 연한 초록, *Material You*에서는 배경화면에서 뽑은 색입니다. 밝은 테마에서는 여전히 어두운 커서이며, 편집기의 다른 부분은 달라지지 않았습니다. + ## v2.32.0 - 노트를 정리해 보는 두 가지 방법 (Two ways to arrange your notes) - 2026-07-25 두 가지 모두 같은 제보자의 요청이며, 기존 동작을 대체하지 않는 선택지입니다. 직접 바꾸기 전까지 목록의 모양도, 노트의 제목도 그대로입니다. 권한 변경과 저장 형식 변경은 없습니다. diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f908c2..bd477b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to Markleaf are documented in this file. This English editio > 💬 **Questions or feedback?** Start a thread in [GitHub Discussions](https://github.com/jeiel85/markleaf-android/discussions). Bug reports still belong in [Issues](https://github.com/jeiel85/markleaf-android/issues). +## v2.32.1 - A caret you can see in the dark - 2026-07-27 + +One editor fix, reported against an F-Droid install. No feature, permission, or storage-format changes. + +### Fixed +- **The text cursor follows your theme instead of staying black (#283).** The note editor is the one field in Markleaf that draws its own caret, and it never named a colour, so it kept the framework default: opaque black. On a dark background that put a black bar on a near-black page — hard to find in both *Markleaf Green* and *Material You*, and at odds with the drag handle right beside it, which was themed all along. The caret now takes the theme's accent colour, the same one the search field and the dialogs use: the light green under dark *Markleaf Green*, and your wallpaper's tone under *Material You*. Light themes keep a dark caret, and nothing else about the editor changed. + ## v2.32.0 - Two ways to arrange your notes - 2026-07-25 Both additions came from the same reporter, and both are choices rather than replacements: your list keeps its shape and your notes keep their titles until you say otherwise. No permission or storage-format changes. diff --git a/README.de.md b/README.de.md index 98fd474..68ca128 100644 --- a/README.de.md +++ b/README.de.md @@ -55,7 +55,7 @@ **Markleaf** ist eine Android-Markdown-Notiz-App, die bewusst auf Ballast verzichtet, damit du dich auf zwei Dinge konzentrieren kannst: festhalten und ordnen. Deine Daten liegen ausschließlich auf deinem Gerät, und das standardisierte Markdown-Format garantiert volle Eigentümerschaft und Portabilität. Auch die Synchronisierung läuft nur über *einen von dir gewählten Ordner* – Markleaf selbst geht nie online. -[**Branding-Seite ansehen**](https://jeiel85.github.io/markleaf-android/) · [Aktuelle Version: v2.32.0](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.0) · [Datenschutzerklärung](https://jeiel85.github.io/markleaf-android/privacy.html) · [F-Droid](https://f-droid.org/packages/com.markleaf.notes/) · [Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) +[**Branding-Seite ansehen**](https://jeiel85.github.io/markleaf-android/) · [Aktuelle Version: v2.32.1](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.1) · [Datenschutzerklärung](https://jeiel85.github.io/markleaf-android/privacy.html) · [F-Droid](https://f-droid.org/packages/com.markleaf.notes/) · [Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) --- @@ -162,7 +162,7 @@ com.markleaf.notes > **Google-Play-Updates sind derzeit ausgesetzt.** Bis eine koreanische Gewerbeanmeldungs-Anforderung für den Einzelentwickler geklärt ist, werden keine neuen Versionen in den Play Store geladen. Hol dir in der Zwischenzeit **die neueste Version über F-Droid, GitHub Releases oder GitLab Releases.** (Wenn du sie bereits aus dem Play Store installiert hast, funktioniert sie weiterhin.) - **F-Droid** *(empfohlen)*: [Markleaf on F-Droid](https://f-droid.org/packages/com.markleaf.notes/) – im F-Droid-Client suchen oder über den Link oben installieren. Es wird derselbe Signaturschlüssel (SHA-256 `0be97352…f91a`) verwendet, sodass Updates auch dann nahtlos weiterlaufen, wenn du ein APK aus den GitHub- oder GitLab-Releases per Sideload installiert hast. -- **Direkte APK-Installation**: lade das APK aus dem [GitHub-v2.32.0-Release](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.0) herunter und führe es auf deinem Android-Gerät aus. +- **Direkte APK-Installation**: lade das APK aus dem [GitHub-v2.32.1-Release](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.1) herunter und führe es auf deinem Android-Gerät aus. - **Google Play**: [Markleaf on Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) – **Updates sind ausgesetzt** (siehe Hinweis oben). Wenn du die App bereits hast, funktioniert sie weiter, aber die neueste Version gibt es über F-Droid, GitHub oder GitLab. ### Aus dem Quellcode bauen diff --git a/README.es.md b/README.es.md index 4817bce..3698dc3 100644 --- a/README.es.md +++ b/README.es.md @@ -55,7 +55,7 @@ **Markleaf** es una app de notas Markdown para Android diseñada para eliminar lo superfluo y dejarte concentrar en solo dos cosas: capturar y organizar. Tus datos se guardan únicamente en tu dispositivo, y el formato Markdown estándar garantiza la propiedad total y la portabilidad de tus datos. Incluso la sincronización ocurre solo a través de *una carpeta que tú eliges* — Markleaf en sí nunca se conecta a internet. -[**Ver la página de branding**](https://jeiel85.github.io/markleaf-android/) · [Versión actual: v2.32.0](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.0) · [Política de privacidad](https://jeiel85.github.io/markleaf-android/privacy.html) · [F-Droid](https://f-droid.org/packages/com.markleaf.notes/) · [Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) +[**Ver la página de branding**](https://jeiel85.github.io/markleaf-android/) · [Versión actual: v2.32.1](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.1) · [Política de privacidad](https://jeiel85.github.io/markleaf-android/privacy.html) · [F-Droid](https://f-droid.org/packages/com.markleaf.notes/) · [Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) --- @@ -162,7 +162,7 @@ com.markleaf.notes > **Las actualizaciones en Google Play están en pausa por ahora.** No se publicarán nuevas versiones en la Play Store hasta que se resuelva un requisito de política de registro de negocio en Corea para el desarrollador individual. Mientras tanto, **obtén la última versión desde F-Droid, GitHub Releases o GitLab Releases.** (Si ya la instalaste desde la Play Store, seguirá funcionando.) - **F-Droid** *(recomendado)*: [Markleaf en F-Droid](https://f-droid.org/packages/com.markleaf.notes/) — búscalo en el cliente de F-Droid o instálalo con el enlace de arriba. Usa la misma clave de firma (SHA-256 `0be97352…f91a`), así que las actualizaciones continúan sin problemas incluso si instalaste un APK de GitHub o GitLab Releases mediante sideload. -- **Instalación directa del APK**: descarga el APK desde el [release v2.32.0 de GitHub](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.0), y ejecútalo en tu dispositivo Android. +- **Instalación directa del APK**: descarga el APK desde el [release v2.32.1 de GitHub](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.1), y ejecútalo en tu dispositivo Android. - **Google Play**: [Markleaf en Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) — **las actualizaciones están en pausa** (ver la nota de arriba). Si ya la tienes instalada, seguirá funcionando, pero obtén la última versión desde F-Droid, GitHub o GitLab. ### Compilar desde el código fuente diff --git a/README.fr.md b/README.fr.md index 8460037..f8d32a4 100644 --- a/README.fr.md +++ b/README.fr.md @@ -55,7 +55,7 @@ **Markleaf** est une application Android de prise de notes Markdown conçue pour éliminer le superflu afin que vous puissiez vous concentrer sur seulement deux choses : capturer et organiser. Vos données sont stockées uniquement sur votre appareil, et le format Markdown standard garantit une propriété et une portabilité complètes. Même la synchronisation ne passe que par *un dossier que vous choisissez* — Markleaf lui-même ne se connecte jamais à internet. -[**Voir la page de branding**](https://jeiel85.github.io/markleaf-android/) · [Version actuelle : v2.32.0](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.0) · [Politique de confidentialité](https://jeiel85.github.io/markleaf-android/privacy.html) · [F-Droid](https://f-droid.org/packages/com.markleaf.notes/) · [Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) +[**Voir la page de branding**](https://jeiel85.github.io/markleaf-android/) · [Version actuelle : v2.32.1](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.1) · [Politique de confidentialité](https://jeiel85.github.io/markleaf-android/privacy.html) · [F-Droid](https://f-droid.org/packages/com.markleaf.notes/) · [Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) --- @@ -162,7 +162,7 @@ com.markleaf.notes > **Les mises à jour sur Google Play sont actuellement en pause.** Aucune nouvelle version ne sera publiée sur le Play Store tant qu'une exigence de politique d'enregistrement d'entreprise en Corée pour le développeur indépendant ne sera pas résolue. En attendant, **obtenez la dernière version via F-Droid, GitHub Releases ou GitLab Releases.** (Si vous l'avez déjà installée depuis le Play Store, elle continue de fonctionner.) - **F-Droid** *(recommandé)* : [Markleaf sur F-Droid](https://f-droid.org/packages/com.markleaf.notes/) — recherchez-le dans le client F-Droid ou installez-le via le lien ci-dessus. Il utilise la même clé de signature (SHA-256 `0be97352…f91a`), donc les mises à jour continuent sans interruption même si vous avez installé un APK via sideload depuis GitHub ou GitLab Releases. -- **Installation directe de l'APK** : téléchargez l'APK depuis la [release GitHub v2.32.0](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.0), puis exécutez-le sur votre appareil Android. +- **Installation directe de l'APK** : téléchargez l'APK depuis la [release GitHub v2.32.1](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.1), puis exécutez-le sur votre appareil Android. - **Google Play** : [Markleaf sur Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) — **les mises à jour sont en pause** (voir la note ci-dessus). Si vous l'avez déjà, elle continue de fonctionner, mais obtenez la dernière version via F-Droid, GitHub ou GitLab. ### Compilation depuis les sources diff --git a/README.ja.md b/README.ja.md index cec73e5..4f11554 100644 --- a/README.ja.md +++ b/README.ja.md @@ -55,7 +55,7 @@ **Markleaf** は、余計なものをそぎ落とし「記録」と「整理」だけに集中できるよう設計された Android 向け Markdown メモアプリです。データは端末内にのみ保存され、標準 Markdown 形式によってデータの所有権と移植性が完全に保証されます。同期も *あなたが選んだフォルダ* を介してのみ行われ、Markleaf 自体はインターネットに接続しません。 -[**ブランディングページを見る**](https://jeiel85.github.io/markleaf-android/) · [現在のバージョン: v2.32.0](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.0) · [プライバシーポリシー](https://jeiel85.github.io/markleaf-android/privacy.html) · [F-Droid](https://f-droid.org/packages/com.markleaf.notes/) · [Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) +[**ブランディングページを見る**](https://jeiel85.github.io/markleaf-android/) · [現在のバージョン: v2.32.1](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.1) · [プライバシーポリシー](https://jeiel85.github.io/markleaf-android/privacy.html) · [F-Droid](https://f-droid.org/packages/com.markleaf.notes/) · [Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) --- @@ -162,7 +162,7 @@ com.markleaf.notes > **現在、Google Play での更新は一時保留中です。** 個人開発者の韓国の事業者登録に関するポリシー要件が解決するまで、新しいバージョンは Play ストアに公開しません。その間は **最新版を F-Droid、GitHub Releases、または GitLab Releases から入手してください。**(すでに Play ストアからインストール済みの場合はそのまま使えます。) - **F-Droid** *(推奨)*: [Markleaf on F-Droid](https://f-droid.org/packages/com.markleaf.notes/) — F-Droid クライアントで検索するか、上のリンクから直接インストールできます。同じ署名鍵(SHA-256 `0be97352…f91a`)を使用するため、GitHub/GitLab Releases の APK をサイドロードした場合でも途切れなく更新が続きます。 -- **APK の直接インストール**: [GitHub v2.32.0](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.0) リリースから APK をダウンロードし、Android 端末で実行してインストールします。 +- **APK の直接インストール**: [GitHub v2.32.1](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.1) リリースから APK をダウンロードし、Android 端末で実行してインストールします。 - **Google Play**: [Markleaf on Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) — **更新は一時保留中**です(上の注記を参照)。すでにインストール済みなら引き続き使えますが、最新版は F-Droid・GitHub・GitLab から入手してください。 ### 開発環境の構築 diff --git a/README.ko.md b/README.ko.md index 041d5cf..696aba4 100644 --- a/README.ko.md +++ b/README.ko.md @@ -55,7 +55,7 @@ **Markleaf**는 군더더기를 덜어내고 오직 '기록'과 '정리'에만 집중할 수 있도록 설계된 Android Markdown 메모 앱입니다. 당신의 데이터는 오직 당신의 기기에만 저장되며, 표준 Markdown 형식을 사용하여 데이터의 소유권과 이식성을 완벽히 보장합니다. 동기화도 *당신이 선택한 폴더* 를 통해서만 일어납니다 — Markleaf 자체는 인터넷에 나가지 않습니다. -[**브랜딩 페이지 보기**](https://jeiel85.github.io/markleaf-android/) · [현재 버전: v2.32.0](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.0) · [Privacy Policy](https://jeiel85.github.io/markleaf-android/privacy.html) · [F-Droid](https://f-droid.org/packages/com.markleaf.notes/) · [Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) +[**브랜딩 페이지 보기**](https://jeiel85.github.io/markleaf-android/) · [현재 버전: v2.32.1](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.1) · [Privacy Policy](https://jeiel85.github.io/markleaf-android/privacy.html) · [F-Droid](https://f-droid.org/packages/com.markleaf.notes/) · [Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) --- @@ -162,7 +162,7 @@ com.markleaf.notes > **Google Play 업데이트는 현재 잠정 보류 중입니다.** 1인 개발자의 한국 사업자 등록 요건 관련 정책 이슈가 정리될 때까지 새 버전을 Play Store에 올리지 않습니다. 그동안 **최신 버전은 F-Droid, GitHub Releases 또는 GitLab Releases에서 받아 주세요.** (Play Store에 이미 설치돼 있다면 그대로 사용할 수 있습니다.) - **F-Droid** *(권장)*: [Markleaf on F-Droid](https://f-droid.org/packages/com.markleaf.notes/) — F-Droid 클라이언트에서 검색하거나 위 링크로 바로 설치할 수 있습니다. 동일 서명 키(SHA-256 `0be97352…f91a`)를 사용하므로 GitHub/GitLab Releases APK로 사이드로드한 경우에도 끊김 없이 업데이트가 이어집니다. -- **APK 직접 설치**: [GitHub v2.32.0](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.0) 릴리스에서 APK를 다운로드한 뒤 Android 기기에서 실행해 설치합니다. +- **APK 직접 설치**: [GitHub v2.32.1](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.1) 릴리스에서 APK를 다운로드한 뒤 Android 기기에서 실행해 설치합니다. - **Google Play**: [Markleaf on Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) — **업데이트 잠정 보류 중**입니다(위 안내 참고). 이미 설치돼 있으면 계속 쓸 수 있지만, 최신 버전은 F-Droid·GitHub·GitLab에서 받으세요. ### 개발 환경 구축 diff --git a/README.md b/README.md index b17546d..4bfa111 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ **Markleaf** is an Android Markdown note app designed to strip away the clutter so you can focus on just two things: capturing and organizing. Your data is stored only on your device, and standard Markdown guarantees full ownership and portability. Even sync happens only through *a folder you choose* — Markleaf itself never goes online. -[**View the branding page**](https://jeiel85.github.io/markleaf-android/) · [Current version: v2.32.0](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.0) · [Privacy Policy](https://jeiel85.github.io/markleaf-android/privacy.html) · [F-Droid](https://f-droid.org/packages/com.markleaf.notes/) · [Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) +[**View the branding page**](https://jeiel85.github.io/markleaf-android/) · [Current version: v2.32.1](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.1) · [Privacy Policy](https://jeiel85.github.io/markleaf-android/privacy.html) · [F-Droid](https://f-droid.org/packages/com.markleaf.notes/) · [Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) --- @@ -162,7 +162,7 @@ com.markleaf.notes > **Google Play updates are currently on hold.** New versions won't be pushed to the Play Store until a Korean business-registration policy requirement for the solo developer is resolved. In the meantime, **get the latest version from F-Droid, GitHub Releases, or GitLab Releases.** (If you already installed it from the Play Store, it keeps working.) - **F-Droid** *(recommended)*: [Markleaf on F-Droid](https://f-droid.org/packages/com.markleaf.notes/) — search in the F-Droid client or install via the link above. It uses the same signing key (SHA-256 `0be97352…f91a`), so updates continue seamlessly even if you sideloaded an APK from GitHub or GitLab Releases. -- **Direct APK install**: download the APK from the [GitHub v2.32.0 release](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.0), then run it on your Android device. +- **Direct APK install**: download the APK from the [GitHub v2.32.1 release](https://github.com/jeiel85/markleaf-android/releases/tag/v2.32.1), then run it on your Android device. - **Google Play**: [Markleaf on Google Play](https://play.google.com/store/apps/details?id=com.markleaf.notes) — **updates are paused** (see the note above). If you already have it, it keeps working, but get the latest version from F-Droid, GitHub, or GitLab. ### Building from source diff --git a/THANKS.md b/THANKS.md index ded28c3..facb8a3 100644 --- a/THANKS.md +++ b/THANKS.md @@ -32,10 +32,11 @@ Listed by first report. | [@Alice-afg](https://github.com/Alice-afg) | [#143](https://github.com/jeiel85/markleaf-android/issues/143) | | [@pescepalla](https://github.com/pescepalla) | [#145](https://github.com/jeiel85/markleaf-android/issues/145) | | [@miladmp73](https://github.com/miladmp73) | [#146](https://github.com/jeiel85/markleaf-android/issues/146) | -| [@bit2bold](https://github.com/bit2bold) | [#155](https://github.com/jeiel85/markleaf-android/issues/155), [#199](https://github.com/jeiel85/markleaf-android/issues/199) | +| [@bit2bold](https://github.com/bit2bold) | [#155](https://github.com/jeiel85/markleaf-android/issues/155), [#199](https://github.com/jeiel85/markleaf-android/issues/199), [#279](https://github.com/jeiel85/markleaf-android/issues/279), [#280](https://github.com/jeiel85/markleaf-android/issues/280) | | [@Cwpute](https://github.com/Cwpute) | [#188](https://github.com/jeiel85/markleaf-android/issues/188), [#189](https://github.com/jeiel85/markleaf-android/issues/189), [#190](https://github.com/jeiel85/markleaf-android/issues/190), [#191](https://github.com/jeiel85/markleaf-android/issues/191), [#192](https://github.com/jeiel85/markleaf-android/issues/192), [#193](https://github.com/jeiel85/markleaf-android/issues/193), [#213](https://github.com/jeiel85/markleaf-android/issues/213), [#214](https://github.com/jeiel85/markleaf-android/issues/214), [#215](https://github.com/jeiel85/markleaf-android/issues/215), [#216](https://github.com/jeiel85/markleaf-android/issues/216) | | [@xentenza](https://github.com/xentenza) | [#197](https://github.com/jeiel85/markleaf-android/issues/197) | | [@Me-2u](https://github.com/Me-2u) | [#200](https://github.com/jeiel85/markleaf-android/issues/200) | +| [@ElizabethWega](https://github.com/ElizabethWega) | [#283](https://github.com/jeiel85/markleaf-android/issues/283) | Not every request here was accepted — a couple were declined, and saying no to a thoughtful suggestion is its own kind of debt. Being told what you want from the diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3dbadce..f719e66 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -62,8 +62,8 @@ android { applicationId = "com.markleaf.notes" minSdk = 26 targetSdk = 35 - versionCode = 122 - versionName = "2.32.0" + versionCode = 123 + versionName = "2.32.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/docs/index.de.html b/docs/index.de.html index f77b712..718211d 100644 --- a/docs/index.de.html +++ b/docs/index.de.html @@ -39,7 +39,7 @@ "name": "Markleaf", "applicationCategory": "ProductivityApplication", "operatingSystem": "Android", - "softwareVersion": "2.32.0", + "softwareVersion": "2.32.1", "description": "A lightweight, local-first Markdown note app for Android.", "downloadUrl": "https://f-droid.org/packages/com.markleaf.notes/", "codeRepository": "https://github.com/jeiel85/markleaf-android", @@ -91,7 +91,7 @@

Notizen auf deinem Gerät.
Gedanken in Markdown.Über F-Droid installieren GitHub APK -

Jetzt v2.32.0 · Kostenlos · Apache-2.0

+

Jetzt v2.32.1 · Kostenlos · Apache-2.0

@@ -112,7 +112,7 @@

Notizen auf deinem Gerät.
Gedanken in Markdown.

Aktuelle Version

- v2.32.0 + v2.32.1 Inklusive Quiet Formatting
diff --git a/docs/index.es.html b/docs/index.es.html index 5db6618..36bbfbd 100644 --- a/docs/index.es.html +++ b/docs/index.es.html @@ -39,7 +39,7 @@ "name": "Markleaf", "applicationCategory": "ProductivityApplication", "operatingSystem": "Android", - "softwareVersion": "2.32.0", + "softwareVersion": "2.32.1", "description": "A lightweight, local-first Markdown note app for Android.", "downloadUrl": "https://f-droid.org/packages/com.markleaf.notes/", "codeRepository": "https://github.com/jeiel85/markleaf-android", @@ -91,7 +91,7 @@

Notas en tu dispositivo.
Pensamientos en Markdown.< Instalar en F-Droid GitHub APK -

Ahora v2.32.0 · Gratis · Apache-2.0

+

Ahora v2.32.1 · Gratis · Apache-2.0

@@ -112,7 +112,7 @@

Notas en tu dispositivo.
Pensamientos en Markdown.<

Versión actual

- v2.32.0 + v2.32.1 Incluye Quiet Formatting
diff --git a/docs/index.fr.html b/docs/index.fr.html index 9a28b19..f7622a3 100644 --- a/docs/index.fr.html +++ b/docs/index.fr.html @@ -39,7 +39,7 @@ "name": "Markleaf", "applicationCategory": "ProductivityApplication", "operatingSystem": "Android", - "softwareVersion": "2.32.0", + "softwareVersion": "2.32.1", "description": "A lightweight, local-first Markdown note app for Android.", "downloadUrl": "https://f-droid.org/packages/com.markleaf.notes/", "codeRepository": "https://github.com/jeiel85/markleaf-android", @@ -91,7 +91,7 @@

Notes sur votre appareil.
Pensées en Markdown.Installer sur F-Droid GitHub APK

-

Maintenant v2.32.0 · Gratuit · Apache-2.0

+

Maintenant v2.32.1 · Gratuit · Apache-2.0

@@ -112,7 +112,7 @@

Notes sur votre appareil.
Pensées en Markdown.

Version actuelle

- v2.32.0 + v2.32.1 Inclut Quiet Formatting
diff --git a/docs/index.html b/docs/index.html index 4fa22a5..e2a885b 100644 --- a/docs/index.html +++ b/docs/index.html @@ -39,7 +39,7 @@ "name": "Markleaf", "applicationCategory": "ProductivityApplication", "operatingSystem": "Android", - "softwareVersion": "2.32.0", + "softwareVersion": "2.32.1", "description": "A lightweight, local-first Markdown note app for Android.", "downloadUrl": "https://f-droid.org/packages/com.markleaf.notes/", "codeRepository": "https://github.com/jeiel85/markleaf-android", @@ -91,7 +91,7 @@

Notes on your device.
Thoughts in Markdown.< Install on F-Droid GitHub APK -

Now v2.32.0 · Free · Apache-2.0

+

Now v2.32.1 · Free · Apache-2.0

@@ -112,7 +112,7 @@

Notes on your device.
Thoughts in Markdown.<

Current release

- v2.32.0 + v2.32.1 Includes Quiet Formatting
diff --git a/docs/index.ja.html b/docs/index.ja.html index 3e0a576..1f406e7 100644 --- a/docs/index.ja.html +++ b/docs/index.ja.html @@ -39,7 +39,7 @@ "name": "Markleaf", "applicationCategory": "ProductivityApplication", "operatingSystem": "Android", - "softwareVersion": "2.32.0", + "softwareVersion": "2.32.1", "description": "A lightweight, local-first Markdown note app for Android.", "downloadUrl": "https://f-droid.org/packages/com.markleaf.notes/", "codeRepository": "https://github.com/jeiel85/markleaf-android", @@ -91,7 +91,7 @@

ノートは端末に。
思考は Markdown で。< F-Droid でインストール GitHub APK

-

現在 v2.32.0 · 無料 · Apache-2.0

+

現在 v2.32.1 · 無料 · Apache-2.0

@@ -112,7 +112,7 @@

ノートは端末に。
思考は Markdown で。<

現在のリリース

- v2.32.0 + v2.32.1 Quiet Formatting を搭載
diff --git a/docs/index.ko.html b/docs/index.ko.html index f8ca3b0..72fa3e7 100644 --- a/docs/index.ko.html +++ b/docs/index.ko.html @@ -39,7 +39,7 @@ "name": "Markleaf", "applicationCategory": "ProductivityApplication", "operatingSystem": "Android", - "softwareVersion": "2.32.0", + "softwareVersion": "2.32.1", "description": "A lightweight, local-first Markdown note app for Android.", "downloadUrl": "https://f-droid.org/packages/com.markleaf.notes/", "codeRepository": "https://github.com/jeiel85/markleaf-android", @@ -91,7 +91,7 @@

메모는 기기에.
생각은 Markdown으로.F-Droid에서 설치 GitHub APK

-

현재 v2.32.0 · 무료 · Apache-2.0

+

현재 v2.32.1 · 무료 · Apache-2.0

@@ -112,7 +112,7 @@

메모는 기기에.
생각은 Markdown으로.

현재 릴리스

- v2.32.0 + v2.32.1 Quiet Formatting 포함
diff --git a/fastlane/metadata/android/de-DE/changelogs/123.txt b/fastlane/metadata/android/de-DE/changelogs/123.txt new file mode 100644 index 0000000..13d2aa3 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/123.txt @@ -0,0 +1 @@ +Der Textcursor im Editor ist in dunklen Themes nicht mehr schwarz. Er nannte keine Farbe, also galt der Standard des Frameworks: ein schwarzer Cursor auf fast schwarzer Seite, in Markleaf-Grün wie in Material You. Jetzt nimmt er die Akzentfarbe des Themes, die das Suchfeld längst verwendet - helles Grün im dunklen Markleaf-Grün, unter Material You der Ton Ihres Hintergrundbilds. In hellen Themes bleibt der Cursor dunkel. \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/123.txt b/fastlane/metadata/android/en-US/changelogs/123.txt new file mode 100644 index 0000000..a45d1e8 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/123.txt @@ -0,0 +1 @@ +The editor's text cursor is no longer black in dark themes. It never named a colour, so the framework default applied: a black caret on a near-black page, in both Markleaf green and Material You. It now takes the theme's accent colour, the one the search field already used - light green in dark Markleaf green, your wallpaper's tone under Material You. Light themes keep a dark caret, and nothing else about the editor changed. \ No newline at end of file diff --git a/fastlane/metadata/android/es-ES/changelogs/123.txt b/fastlane/metadata/android/es-ES/changelogs/123.txt new file mode 100644 index 0000000..938c9e8 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/123.txt @@ -0,0 +1 @@ +El cursor de texto del editor ya no es negro en los temas oscuros. No indicaba ningún color, así que se aplicaba el valor por defecto del framework: un cursor negro sobre una página casi negra, tanto en Verde Markleaf como en Material You. Ahora toma el color de acento del tema: verde claro en Verde Markleaf oscuro y el tono de tu fondo de pantalla en Material You. Los temas claros mantienen un cursor oscuro. \ No newline at end of file diff --git a/fastlane/metadata/android/fr-FR/changelogs/123.txt b/fastlane/metadata/android/fr-FR/changelogs/123.txt new file mode 100644 index 0000000..f01d4de --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/123.txt @@ -0,0 +1 @@ +Le curseur de texte de l'éditeur n'est plus noir dans les thèmes sombres. Aucune couleur n'était indiquée, donc la valeur par défaut du framework s'appliquait : un curseur noir sur une page presque noire, en Vert Markleaf comme en Material You. Il prend désormais la couleur d'accent du thème - vert clair en Vert Markleaf sombre, la teinte de votre fond d'écran en Material You. Les thèmes clairs gardent un curseur foncé. \ No newline at end of file diff --git a/fastlane/metadata/android/ja-JP/changelogs/123.txt b/fastlane/metadata/android/ja-JP/changelogs/123.txt new file mode 100644 index 0000000..1fe80f3 --- /dev/null +++ b/fastlane/metadata/android/ja-JP/changelogs/123.txt @@ -0,0 +1 @@ +エディターのテキストカーソルがダークテーマで黒くなくなりました。色を指定していなかったためフレームワークの既定値が使われ、ほぼ黒い画面に黒いカーソルが置かれていました。Markleaf グリーンでも Material You でも同じです。今後は検索欄がすでに使っているテーマのアクセントカラーになります。ダークの Markleaf グリーンでは淡い緑、Material You では壁紙から取った色です。ライトテーマではこれまでどおり濃いカーソルで、エディターのほかの部分は変わりません。 \ No newline at end of file diff --git a/fastlane/metadata/android/ko-KR/changelogs/123.txt b/fastlane/metadata/android/ko-KR/changelogs/123.txt new file mode 100644 index 0000000..f6bc057 --- /dev/null +++ b/fastlane/metadata/android/ko-KR/changelogs/123.txt @@ -0,0 +1 @@ +편집기의 텍스트 커서가 어두운 테마에서 더 이상 검은색이 아닙니다. 색을 지정하지 않아 프레임워크 기본값이 쓰였고, 그래서 거의 검은 화면 위에 검은 커서가 놓였습니다 - Markleaf 그린과 Material You 양쪽 모두에서요. 이제 커서는 검색창이 이미 쓰던 테마 강조색을 씁니다. 어두운 Markleaf 그린에서는 연한 초록, Material You에서는 배경화면에서 뽑은 색입니다. 밝은 테마에서는 여전히 어두운 커서이며, 편집기의 다른 부분은 그대로입니다. \ No newline at end of file From 2e19b095921bbf304ffaacc6af0f1e5cbd0acd39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=9A=A9=EC=9D=80?= Date: Mon, 27 Jul 2026 09:29:39 +0900 Subject: [PATCH 3/4] test: re-record the editor-screen golden on the Linux runner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `editor_screen_quiet_appbar_phone` renders the real `EditorScreen` with the field focused, so the caret is in the image — the only golden the colour change touches. Recorded by the `record_roborazzi` dispatch rather than locally, where font hinting moves half the snapshots; the artifact came back with 61 of 62 goldens byte-identical, which is the evidence that nothing else moved. Co-Authored-By: Claude Opus 5 --- .../editor_screen_quiet_appbar_phone.png | Bin 12089 -> 12089 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/app/src/test/snapshots/roborazzi/editor_screen_quiet_appbar_phone.png b/app/src/test/snapshots/roborazzi/editor_screen_quiet_appbar_phone.png index 8596bacdf56e4ac9974489b6e421f6b2f1318a2b..2253a26322ce47cf20f3d114dcaa35f76601c174 100644 GIT binary patch delta 9479 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 AD*ylh delta 9499 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 c Date: Mon, 27 Jul 2026 09:30:14 +0900 Subject: [PATCH 4/4] docs: log the caret fix and v2.32.1 Co-Authored-By: Claude Opus 5 --- HISTORY.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 676cd2c..48122dc 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,12 @@ +## 2026-07-27 - The editor caret takes the theme's colour, and v2.32.1 (#283) + +- Trigger: an F-Droid user on 2.28.3 wrote in with two screenshots — a dark page, a themed drag handle, and a black caret they had to hunt for, in both Markleaf Green and Material You (#283). +- Analysis: the editor's `BasicTextField` never passed `cursorBrush`, so Compose's default `SolidColor(Color.Black)` applied. It is the only raw foundation text field in the app; the Material fields (search, rename, settings, passcode) take their cursor colour from the theme, which is why the editor was the only place it showed. The report's "no matter which theme I choose" is exactly what a hardcoded literal predicts. +- Contract/scope: one argument at the call site — `cursorBrush = SolidColor(colorScheme.primary)`, the colour the Material fields already use — plus a guard so the same omission cannot come back. Nothing else about the editor changes. The `Color.Gray` defaults in `MarkdownSyntaxColors` (code fences, tables, blockquotes, rules) are the same defect family and are deliberately left alone: fixing them moves rendering, so they go to the tracker rather than into a patch release. +- Implementation: PR #284. `ThemedCaretTest` scans `src/main` for `BasicTextField(` call sites and fails any that omit `cursorBrush`, reading each call with a paren counter that ignores string and character literals so a `")"` in an argument cannot end it early. It also fails when the scan matches nothing — a text field renamed out from under it would otherwise pass for the wrong reason. +- Verification: `testDebugUnitTest` (548 tests) + `lintRelease` locally. The guard itself was checked by removing the fix and confirming it named `EditorScreen.kt:886`. Device pass on `markleaf-phone-api36`, caret core pixels sampled from a screenshot burst because the caret blinks and a single capture catches it half the time: dark Markleaf Green `#81C784` on `#191C19` (8.7:1), dark Material You `(176,198,255)` on `(18,19,24)` (11.2:1), light Material You `(71,93,146)` (6.1:1), light Markleaf Green `#2E7D32` (4.9:1). The same measurement before the fix was black on `#191C19` — 1.2:1, which is the report. The `editor_screen_quiet_appbar_phone` golden holds a focused caret, so it was re-recorded on the Linux runner rather than locally. +- Release: versionCode 122→123, versionName 2.32.0→2.32.1, CHANGELOG both editions, six store-locale `123.txt` (428 chars at the longest; every locale now keeps more than the 50 characters of headroom `verify-release-notes.ps1` warns below, which fr-FR and es-ES did not on the first pass), landing ×6 + README ×6, and THANKS.md gains the reporter. No hardening issue filed — this is issue-response work, and AGENTS.md keeps that flow from growing the backlog it is meant to spend. + ## 2026-07-27 - Landing stylesheets made direction-aware (#146) - Trigger: looking back at #146 — the Persian reader whose right-to-left note content laid out left-to-right, fixed in v2.28.0 — the same question one level up: the app handles RTL, the site around it never had to. The work started as a Persian README plus landing page; the maintainer cut that mid-flight, leaving only the part that has to exist before any RTL page can.