From 4382a644fd8e8cba6201a7555ddbf1bb92f754b2 Mon Sep 17 00:00:00 2001 From: Patrice Haltaya Date: Tue, 10 Nov 2026 13:35:01 +0100 Subject: [PATCH 1/2] fix(preview): a line end stays a line break (#57) Issue #57: three lines typed "1.Drink water", "2.Eat", "3.Sleep." came out in the preview as ONE line, "1.Drink water 2.Eat 3.Sleep.". Measured on the JVM: "1. Eat" with a space after the dot IS a list in the preview. Everything else followed CommonMark, as 2.0.9 did (softLineBreak: false): a single line end inside a paragraph became a space. So these all came out on one line: "1.Eat" with no space (not a list), a full-width dot or ideographic space typed by an Asian keyboard, a no-break space, a list starting at "2." under a line of text, and any run of plain text lines. Now every line end is a line break, as in the editor (D-045): a note is written on a phone, line by line, and Obsidian, Joplin and GitHub's comments keep line ends the same way. List recognition does not change. A hard break (two spaces or a backslash) still gives ONE break: the line end it sits on adds nothing after it. The legal pages go through the same reader. The five terms.md quoted the whisper.cpp MIT notice wrapped at about 100 columns (and, in English and French, the paragraph introducing it): each paragraph is now on one line. Only spacing changes, checked by script; the three copyright lines stay lines, as in the licence, and now show one under the other. PagesLegalesTest keeps every paragraph of a legal page on one line; negative control: the old English terms.md makes it fail. Changelogs 5071-5073 get one line in the five languages (longest: German, 491 characters). Co-Authored-By: Claude Opus 5.5 --- REPRISE.md | 5 ++ .../domain/markdown/MarkdownPreviewReader.kt | 51 ++++++++++++++----- app/src/main/res/raw-de/terms.md | 15 ++---- app/src/main/res/raw-es/terms.md | 15 ++---- app/src/main/res/raw-fr/terms.md | 21 ++------ app/src/main/res/raw-it/terms.md | 15 ++---- app/src/main/res/raw/terms.md | 20 ++------ .../markdown/MarkdownPreviewReaderTest.kt | 50 +++++++++++++++--- .../notes_tech/ui/about/PagesLegalesTest.kt | 35 +++++++++++++ docs/01-DECISIONS.md | 6 ++- docs/15-VERSION-3.4.md | 47 +++++++++++++++++ .../android/de-DE/changelogs/5071.txt | 2 +- .../android/de-DE/changelogs/5072.txt | 2 +- .../android/de-DE/changelogs/5073.txt | 2 +- .../android/en-US/changelogs/5071.txt | 2 +- .../android/en-US/changelogs/5072.txt | 2 +- .../android/en-US/changelogs/5073.txt | 2 +- .../android/es-ES/changelogs/5071.txt | 2 +- .../android/es-ES/changelogs/5072.txt | 2 +- .../android/es-ES/changelogs/5073.txt | 2 +- .../android/fr-FR/changelogs/5071.txt | 2 +- .../android/fr-FR/changelogs/5072.txt | 2 +- .../android/fr-FR/changelogs/5073.txt | 2 +- .../android/it-IT/changelogs/5071.txt | 2 +- .../android/it-IT/changelogs/5072.txt | 2 +- .../android/it-IT/changelogs/5073.txt | 2 +- 26 files changed, 206 insertions(+), 104 deletions(-) diff --git a/REPRISE.md b/REPRISE.md index 3d66bc09..064ce4c2 100644 --- a/REPRISE.md +++ b/REPRISE.md @@ -9,6 +9,11 @@ Patrice : « fais 2, 3, 4 ce serait génial pour la 3.4.0 + raccourcis et clavie « en intégrant les upgrade AGP aussi » (PR #51). **Spécification, décisions D-040 à D-044, audits, limites connues et état coché : `docs/15-VERSION-3.4.md`** — la lire en premier. +- **2026-11-10 — issue #57 (koad1x) corrigée dans la 3.4.0, pas encore publiée** : l'aperçu garde les + retours à la ligne (D-045) ; pages légales (5 `terms.md`) recollées, un paragraphe par ligne. Branche + `fix/57-preview-line-breaks`. Journaux 5071-5073 ×5 complétés. **Répondre à l'issue APRÈS la release** + (brouillon dans la PR). Au 11-10, F-Droid sert toujours la 3.2.2 (aucun journal 5061-5063, index du + 11-09 02 h 28 UTC) : l'attente de la 3.3.0 continue. - **PR #53 fusionnée** : `main` = `d523f1c` (commit de fusion), CI verte avant la fusion (porte, instrumentés API 29, release R8, zéro réseau, CodeQL), version 3.4.0 base **507** (5070-5073), journaux 5071-5073 ×5. - **⛔ Patrice, 2026-11-09 : « on attend que fdroid publie notes-tech 3.3.0 avant toute publication de la diff --git a/app/src/main/java/com/filestech/notes_tech/domain/markdown/MarkdownPreviewReader.kt b/app/src/main/java/com/filestech/notes_tech/domain/markdown/MarkdownPreviewReader.kt index 60abe1da..6818aaf1 100644 --- a/app/src/main/java/com/filestech/notes_tech/domain/markdown/MarkdownPreviewReader.kt +++ b/app/src/main/java/com/filestech/notes_tech/domain/markdown/MarkdownPreviewReader.kt @@ -716,20 +716,33 @@ private fun ASTNode.child(type: IElementType): ASTNode? = children.firstOrNull { /** * Accumulates the runs of one paragraph, heading or cell. * - * Line breaks follow notes_tech 2.0.9 (`flutter_markdown_plus`, `softLineBreak: false`): a soft one - * — a single line end — is a space, with the spaces around it folded (` ?\n *` → one space); a hard - * one — two trailing spaces or a backslash — is a line break. Leading and trailing whitespace of the - * whole is dropped, as its `TrimmingInlineHolderProvider` does for headings and cells. + * ⚠️ **Every line end is a line break** (issue #57, D-045, 2026-11-10): what the user wrote on its own + * line stays on its own line, as in the editor, the spaces around the break folded. CommonMark — and + * notes_tech 2.0.9 (`flutter_markdown_plus`, `softLineBreak: false`), which the preview followed until + * 3.4.0 — turns a single line end into a space: three lines typed `1.Eat` `2.Drink` `3.Sleep` (no space + * after the dot, so not a list), a list typed with a full-width `1.` or an ideographic space by an + * Asian keyboard, or one starting at `2.` under a line of text, all came out as ONE line. A note is + * written on a phone, line by line, not wrapped at 80 columns; Obsidian, Joplin and GitHub's comments + * keep line ends the same way. + * + * So a text drawn here is **never wrapped at a width**: the legal pages, drawn by the same reader, + * write each paragraph on one line (`PagesLegalesTest` keeps them so). Two trailing spaces or a + * backslash — CommonMark's hard break — break the line once. Leading and trailing whitespace of the + * whole is dropped, as 2.0.9's `TrimmingInlineHolderProvider` does for headings and cells. */ private class RunsBuilder { private val runs = mutableListOf() private var skipLeadingSpaces = true + /** A hard break was the last thing added: the line end it sits on is already drawn. */ + private var afterHardBreak = false + fun text(value: String, styles: Set, link: LinkTarget?) { // Spaces inside inline code are content, not layout: `` ` a` `` keeps its space. val kept = if (skipLeadingSpaces && RunStyle.CODE !in styles) value.trimStart(' ', '\t') else value if (kept.isEmpty()) return skipLeadingSpaces = false + afterHardBreak = false val last = runs.lastOrNull() if (last != null && last.styles == styles && last.link == link) { runs[runs.lastIndex] = last.copy(text = last.text + kept) @@ -739,20 +752,32 @@ private class RunsBuilder { } /** - * ⚠️ A line break drops trailing spaces and tabs, **never a `\n`**. A hard break is always - * followed by the line end it sits on, which arrives here as a soft break: dropping the `\n` as - * trailing whitespace erased the hard break, and the space that replaced it was then eaten as a - * leading space — `one··⏎two` came out `onetwo` (measured by `MarkdownPreviewReaderTest`, - * 2026-09-25). Kept, the `\n` leaves the soft break's space leading, hence skipped: nothing to add. + * ⚠️ **Nothing right after a hard break.** A hard break is always followed by the line end it + * sits on, which arrives here as a soft break: drawn too, `one··⏎two` would get a blank line + * between its two lines. Two hard breaks in a row — a line holding only `\` — still give two. */ - fun softBreak(styles: Set, link: LinkTarget?) = lineBreak(" ", styles, link) + fun softBreak(styles: Set, link: LinkTarget?) { + if (afterHardBreak) { + afterHardBreak = false + return + } + lineBreak(styles, link) + } - fun hardBreak(styles: Set, link: LinkTarget?) = lineBreak("\n", styles, link) + fun hardBreak(styles: Set, link: LinkTarget?) { + lineBreak(styles, link) + afterHardBreak = runs.isNotEmpty() + } - private fun lineBreak(separator: String, styles: Set, link: LinkTarget?) { + /** + * ⚠️ A line break drops trailing spaces and tabs, **never a `\n`**: dropping the `\n` of the + * break before it as trailing whitespace would erase that break — `one··⏎two` came out `onetwo` + * (measured by `MarkdownPreviewReaderTest`, 2026-09-25). + */ + private fun lineBreak(styles: Set, link: LinkTarget?) { if (runs.isEmpty()) return dropTrailing(' ', '\t') - text(separator, styles, link) + text("\n", styles, link) skipLeadingSpaces = true } diff --git a/app/src/main/res/raw-de/terms.md b/app/src/main/res/raw-de/terms.md index 946cb290..55aac391 100644 --- a/app/src/main/res/raw-de/terms.md +++ b/app/src/main/res/raw-de/terms.md @@ -45,20 +45,11 @@ Das Sprachdiktat läuft vollständig auf Ihrem Telefon, mit einer **in der App e > Copyright (C) 2024 Intel Corporation > Copyright (c) 2023 Jeffrey Quesnelle and Bowen Peng > -> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -> associated documentation files (the "Software"), to deal in the Software without restriction, -> including without limitation the rights to use, copy, modify, merge, publish, distribute, -> sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -> furnished to do so, subject to the following conditions: +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: > -> The above copyright notice and this permission notice shall be included in all copies or -> substantial portions of the Software. +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. > -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -> NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -> DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Daten diff --git a/app/src/main/res/raw-es/terms.md b/app/src/main/res/raw-es/terms.md index eecc02ce..37a09bca 100644 --- a/app/src/main/res/raw-es/terms.md +++ b/app/src/main/res/raw-es/terms.md @@ -45,20 +45,11 @@ El dictado por voz funciona íntegramente en su teléfono, con un motor de trans > Copyright (C) 2024 Intel Corporation > Copyright (c) 2023 Jeffrey Quesnelle and Bowen Peng > -> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -> associated documentation files (the "Software"), to deal in the Software without restriction, -> including without limitation the rights to use, copy, modify, merge, publish, distribute, -> sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -> furnished to do so, subject to the following conditions: +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: > -> The above copyright notice and this permission notice shall be included in all copies or -> substantial portions of the Software. +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. > -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -> NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -> DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Datos diff --git a/app/src/main/res/raw-fr/terms.md b/app/src/main/res/raw-fr/terms.md index ecccb302..1ed8326f 100644 --- a/app/src/main/res/raw-fr/terms.md +++ b/app/src/main/res/raw-fr/terms.md @@ -37,11 +37,7 @@ Vous êtes responsable du respect de ces licences. ## Composants tiers embarqués dans l'application -La dictée vocale s'exécute entièrement sur votre téléphone, au moyen d'un moteur de transcription -**inclus dans l'application** : `whisper.cpp` et `ggml`, version 1.8.3, publiés sous licence MIT. -Cette licence exige que sa notice accompagne toute copie du logiciel ; elle est donc reproduite -ci-dessous, et le code correspondant figure dans le dépôt source sous -`app/src/main/cpp/vendor/whisper/`. +La dictée vocale s'exécute entièrement sur votre téléphone, au moyen d'un moteur de transcription **inclus dans l'application** : `whisper.cpp` et `ggml`, version 1.8.3, publiés sous licence MIT. Cette licence exige que sa notice accompagne toute copie du logiciel ; elle est donc reproduite ci-dessous, et le code correspondant figure dans le dépôt source sous `app/src/main/cpp/vendor/whisper/`. > MIT License > @@ -49,20 +45,11 @@ ci-dessous, et le code correspondant figure dans le dépôt source sous > Copyright (C) 2024 Intel Corporation > Copyright (c) 2023 Jeffrey Quesnelle and Bowen Peng > -> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -> associated documentation files (the "Software"), to deal in the Software without restriction, -> including without limitation the rights to use, copy, modify, merge, publish, distribute, -> sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -> furnished to do so, subject to the following conditions: +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: > -> The above copyright notice and this permission notice shall be included in all copies or -> substantial portions of the Software. +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. > -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -> NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -> DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Données diff --git a/app/src/main/res/raw-it/terms.md b/app/src/main/res/raw-it/terms.md index a6a91051..4ddab469 100644 --- a/app/src/main/res/raw-it/terms.md +++ b/app/src/main/res/raw-it/terms.md @@ -45,20 +45,11 @@ La dettatura vocale funziona interamente sul suo telefono, con un motore di tras > Copyright (C) 2024 Intel Corporation > Copyright (c) 2023 Jeffrey Quesnelle and Bowen Peng > -> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -> associated documentation files (the "Software"), to deal in the Software without restriction, -> including without limitation the rights to use, copy, modify, merge, publish, distribute, -> sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -> furnished to do so, subject to the following conditions: +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: > -> The above copyright notice and this permission notice shall be included in all copies or -> substantial portions of the Software. +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. > -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -> NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -> DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Dati diff --git a/app/src/main/res/raw/terms.md b/app/src/main/res/raw/terms.md index 644c00c3..d1ae149e 100644 --- a/app/src/main/res/raw/terms.md +++ b/app/src/main/res/raw/terms.md @@ -37,10 +37,7 @@ You are responsible for complying with those licenses. ## Third-party components bundled in the app -Voice dictation runs entirely on your phone, using a transcription engine **included in the app**: -`whisper.cpp` and `ggml`, version 1.8.3, released under the MIT license. That license requires its -notice to accompany every copy of the software; it is therefore reproduced below, and the matching -source code sits in the source repository under `app/src/main/cpp/vendor/whisper/`. +Voice dictation runs entirely on your phone, using a transcription engine **included in the app**: `whisper.cpp` and `ggml`, version 1.8.3, released under the MIT license. That license requires its notice to accompany every copy of the software; it is therefore reproduced below, and the matching source code sits in the source repository under `app/src/main/cpp/vendor/whisper/`. > MIT License > @@ -48,20 +45,11 @@ source code sits in the source repository under `app/src/main/cpp/vendor/whisper > Copyright (C) 2024 Intel Corporation > Copyright (c) 2023 Jeffrey Quesnelle and Bowen Peng > -> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -> associated documentation files (the "Software"), to deal in the Software without restriction, -> including without limitation the rights to use, copy, modify, merge, publish, distribute, -> sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -> furnished to do so, subject to the following conditions: +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: > -> The above copyright notice and this permission notice shall be included in all copies or -> substantial portions of the Software. +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. > -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -> NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -> DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Data diff --git a/app/src/test/java/com/filestech/notes_tech/domain/markdown/MarkdownPreviewReaderTest.kt b/app/src/test/java/com/filestech/notes_tech/domain/markdown/MarkdownPreviewReaderTest.kt index dc534da2..b733e6ec 100644 --- a/app/src/test/java/com/filestech/notes_tech/domain/markdown/MarkdownPreviewReaderTest.kt +++ b/app/src/test/java/com/filestech/notes_tech/domain/markdown/MarkdownPreviewReaderTest.kt @@ -117,10 +117,10 @@ class MarkdownPreviewReaderTest { PreviewBlock.Quote( listOf(paragraph(run("outer")), PreviewBlock.Quote(listOf(paragraph(run("inner"))))), ), - PreviewBlock.Quote(listOf(paragraph(run("first lazy")))), + PreviewBlock.Quote(listOf(paragraph(run("first\nlazy")))), ).inOrder() // The `>` token the library leaves inside a continued paragraph is not text. - assertThat(read("> a\n> b")).containsExactly(PreviewBlock.Quote(listOf(paragraph(run("a b"))))) + assertThat(read("> a\n> b")).containsExactly(PreviewBlock.Quote(listOf(paragraph(run("a\nb"))))) } @Test @@ -190,7 +190,7 @@ class MarkdownPreviewReaderTest { @Test fun `block math is an ordinary paragraph, as in 2_0_9 which has no math`() { - assertThat(read("$$\nx^2\n$$")).containsExactly(paragraph(run("$$ x^2 $$"))) + assertThat(read("$$\nx^2\n$$")).containsExactly(paragraph(run("$$\nx^2\n$$"))) } } @@ -223,15 +223,53 @@ class MarkdownPreviewReaderTest { } @Test - fun `a soft line break is a space, spaces around it folded — 2_0_9's softLineBreak false`() { - assertThat(runsOf("one \n two\nthree")).containsExactly(run("one two three")) + fun `a line end stays a line break, spaces around it folded — a deliberate gap with 2_0_9 (issue #57)`() { + assertThat(runsOf("one \n two\nthree")).containsExactly(run("one\ntwo\nthree")) } @Test - fun `a hard line break — two spaces or a backslash — is a line break`() { + fun `a hard line break — two spaces or a backslash — is ONE line break, not two`() { assertThat(runsOf("one \ntwo\\\nthree")).containsExactly(run("one\ntwo\nthree")) } + @Test + fun `a line holding only a backslash keeps its empty line`() { + assertThat(runsOf("one\\\n\\\ntwo")).containsExactly(run("one\n\ntwo")) + } + + @Test + fun `a line break inside a style or a link stays in it`() { + assertThat(runsOf("**one\ntwo** [three\nfour](https://a.example)")).containsExactly( + run("one\ntwo", RunStyle.BOLD), + run(" "), + run("three\nfour", link = web("https://a.example")), + ).inOrder() + } + + /** + * Issue #57: lines that look like a list to the user but are not one in CommonMark were + * joined into one line. They are not a list — the dot has no space after it, the dot or the + * space is full-width, the list starts at 2 under a line of text — but each stays on its line. + */ + @Test + fun `lines that are not a list keep their own lines — issue #57`() { + assertThat(runsOf("1.Drink water\n2.Eat\n3.Sleep.")).containsExactly(run("1.Drink water\n2.Eat\n3.Sleep.")) + assertThat(runsOf("1.Eat\n2.Drink")).containsExactly(run("1.Eat\n2.Drink")) + assertThat(runsOf("1. Eat\n2. Drink")).containsExactly(run("1. Eat\n2. Drink")) + assertThat(runsOf("Today:\n2. Eat\n3. Drink")).containsExactly(run("Today:\n2. Eat\n3. Drink")) + } + + @Test + fun `a real ordered list is still a list — issue #57`() { + assertThat(read("1. Eat\n2. Drink\n3. Sleep")).containsExactly( + PreviewBlock.ListBlock( + ordered = true, + start = 1, + items = listOf("Eat", "Drink", "Sleep").map { ListItem(null, listOf(paragraph(run(it)))) }, + ), + ) + } + @Test fun `inline code keeps its inner spaces and strips one padding space each side`() { assertThat(runsOf("`` a`b ``")).containsExactly(run("a`b", RunStyle.CODE)) diff --git a/app/src/test/java/com/filestech/notes_tech/ui/about/PagesLegalesTest.kt b/app/src/test/java/com/filestech/notes_tech/ui/about/PagesLegalesTest.kt index 0bdd99ca..952c6a01 100644 --- a/app/src/test/java/com/filestech/notes_tech/ui/about/PagesLegalesTest.kt +++ b/app/src/test/java/com/filestech/notes_tech/ui/about/PagesLegalesTest.kt @@ -33,6 +33,36 @@ class PagesLegalesTest { } } + /** + * 🔴 **No paragraph is wrapped at a width** (issue #57, D-045). The reader keeps every line end as + * a line break, as a note needs; a paragraph cut at 100 columns — the MIT notice of whisper.cpp + * was, until 3.4.0 — would come out cut short on every line of a phone's screen. The only lines a + * paragraph may hold are the notice's three copyright lines, which are lines in the licence too. + */ + @Test + fun `no paragraph of a legal page is wrapped at a width — only the copyright lines are lines`() { + for (page in PAGES) { + val multilignes = paragraphes(MarkdownPreviewReader.read(page.readText())) + .map { runs -> runs.joinToString("") { it.text } } + .filter { '\n' in it } + + val attendus = if (page.name == "terms.md") listOf(COPYRIGHTS) else emptyList() + assertWithMessage(page.path).that(multilignes).isEqualTo(attendus) + } + } + + /** Every paragraph's runs, quotes and lists included — where a wrapped line would show. */ + private fun paragraphes(blocs: List): List> = blocs.flatMap { bloc -> + when (bloc) { + is PreviewBlock.Paragraph -> listOf(bloc.runs) + is PreviewBlock.ListBlock -> bloc.items.flatMap { paragraphes(it.blocks) } + is PreviewBlock.Quote -> paragraphes(bloc.blocks) + is PreviewBlock.Heading, is PreviewBlock.Table, is PreviewBlock.Code, is PreviewBlock.AsWritten, + is PreviewBlock.RawHtml, PreviewBlock.Rule, + -> emptyList() + } + } + /** The control of the case above: the privacy pages do write a `[[…]]`, and it stays text. */ @Test fun `the privacy pages write a note link in code, which stays text`() { @@ -83,5 +113,10 @@ class PagesLegalesTest { val PAGES = LocalePreference.LANGUES.map { if (it == "en") "raw" else "raw-$it" }.flatMap { dossier -> listOf("privacy.md", "terms.md").map { File("src/main/res/$dossier/$it") } } + + /** The three copyright lines of the MIT notice, one under the other as in the licence. */ + const val COPYRIGHTS = "Copyright (c) 2023-2024 The ggml authors\n" + + "Copyright (C) 2024 Intel Corporation\n" + + "Copyright (c) 2023 Jeffrey Quesnelle and Bowen Peng" } } diff --git a/docs/01-DECISIONS.md b/docs/01-DECISIONS.md index 54bed585..321d18af 100644 --- a/docs/01-DECISIONS.md +++ b/docs/01-DECISIONS.md @@ -751,7 +751,11 @@ inactif depuis 2021. *`AnnotatedString.fromHtml`* : ni tableaux, ni cases, ni bl - `www.…` s'ouvre en `https://` (la 2.0.9 : `http://`) ; - les cases de tâche sont **nommées** pour un lecteur d'écran (« Fait » / « À faire ») ; - le code se replie à la ligne au lieu de défiler de côté ; - - « aucune application ne peut ouvrir ce lien » est dit, au lieu d'un appui sans effet. + - « aucune application ne peut ouvrir ce lien » est dit, au lieu d'un appui sans effet ; + - **depuis la 3.4.0 (D-045, `docs/15-VERSION-3.4.md`, issue #57)** : dans une note, un retour à la + ligne simple reste un retour à la ligne — la 2.0.9 et CommonMark en font une espace. Les pages + légales, qui passent par le même lecteur, écrivent donc chaque paragraphe sur une ligne + (`PagesLegalesTest`). - **Borné, quelle que soit la note** (`04-PIEGES.md` §147) : balayage linéaire avant l'analyse — plus de 500 000 caractères, plus de 8 marqueurs de conteneur en tête d'une ligne, plus de 300 `[` dans un bloc ou 3 000 dans la note (liens `[[…]]` et cases de tâche non comptés) : la note s'affiche **telle diff --git a/docs/15-VERSION-3.4.md b/docs/15-VERSION-3.4.md index 9f0bb85e..ea5adf04 100644 --- a/docs/15-VERSION-3.4.md +++ b/docs/15-VERSION-3.4.md @@ -130,6 +130,53 @@ « Ajouter » la met dans la Boîte de réception, jamais dans un coffre. - Une note de coffre se partage scellée seulement coffre ouvert, comme l'export. +## D-045 — Aperçu : un retour à la ligne d'une note reste un retour à la ligne (issue #57) + +**2026-11-10, ajoutée à la 3.4.0 après sa fusion, avant sa publication** (Patrice : « c'est possible de +corriger ou non ?? »). + +**Signalement (koad1x, issue #57).** Une liste tapée ligne par ligne — `1.Drink water` ⏎ `2.Eat` ⏎ +`3.Sleep.` — sort dans l'aperçu sur UNE ligne : `1.Drink water 2.Eat 3.Sleep.` + +**Mesuré (JVM, 2026-11-10).** `1. Eat` ⏎ `2. Drink` (espace après le point) EST une liste dans l'aperçu. +Tout le reste suivait CommonMark et la 2.0.9 (`softLineBreak: false`) : un retour à la ligne simple dans +un paragraphe devient une espace. Sont donc écrasés sur une ligne : `1.Eat` sans espace (pas une liste), +le point ou l'espace **pleine chasse** d'un clavier chinois (`1.Eat`, `1. Eat`) ou une espace insécable, +une liste qui commence à `2.` sous une ligne de texte (CommonMark l'interdit), et toute suite de lignes +de texte ordinaire. + +**Décision.** Dans l'aperçu, un retour à la ligne simple est un **retour à la ligne** +(`RunsBuilder`) : ce qui est sur sa propre ligne dans l'éditeur le reste. Une note s'écrit au téléphone, +ligne par ligne, pas coupée à 80 colonnes ; c'est le défaut d'Obsidian, de Joplin et des commentaires +GitHub. Écart assumé avec CommonMark et la 2.0.9. La reconnaissance des listes, elle, **ne change pas** +(CommonMark strict) : `1.Eat` reste du texte, mais à sa ligne. **Une seule règle**, pour les notes et +pour les pages légales, qui passent par le même lecteur. + +- **Pages légales recollées** (Patrice : « corrige les textes aussi alors dans à propos et autres pages + légales ») : les 5 `terms.md` citaient la licence MIT de whisper.cpp coupée à ~100 colonnes (et, en + anglais et en français, le paragraphe qui la présente) ; avec la nouvelle règle, chaque ligne se + serait arrêtée court sur un téléphone. Chaque paragraphe est remis sur UNE ligne — **seul l'espacement + change**, contrôlé par script (texte identique, espaces repliées) ; date de mise à jour inchangée. + Les trois lignes `Copyright` de la notice restent des lignes : elles le sont dans la licence, et + s'affichent enfin l'une sous l'autre (elles étaient collées bout à bout). Les `privacy.md` n'avaient + aucune coupure. « À propos » n'affiche que des chaînes traduites, sans Markdown : rien à y changer. +- **Garde-fou** : `PagesLegalesTest` — aucun paragraphe d'une page légale n'a de fin de ligne, sauf les + trois lignes `Copyright`. **Contrôle négatif** : l'ancien `terms.md` anglais remis en place, le test + échoue sur le paragraphe de présentation et ceux de la licence ; restauré ensuite à l'octet. +- Un premier essai gardait CommonMark pour les pages légales (un mode « document ») : abandonné pour + une seule règle, le mode n'ayant plus d'usage une fois les textes recollés. +- **Coupure forcée** (deux espaces ou `\` en fin de ligne) : UN retour à la ligne, dans les deux modes — + elle est toujours suivie de la fin de ligne qui la porte, qui n'ajoute rien derrière elle. Une ligne + faite d'un seul `\` garde sa ligne vide. +- **Non touchés** : la recherche dans la note (mot par mot, l'espace ou le `\n` n'y change rien), le + code en ligne (ses fins de ligne restent des espaces, CommonMark), l'export, l'import. +- **Tests** (`MarkdownPreviewReaderTest`) : les cas de l'issue, la vraie liste, le mode document, la + coupure forcée unique, la ligne de `\`, le retour dans un style et un lien ; deux attendus qui figeaient + l'ancienne règle (citation continuée, bloc `$$`) mis à jour. +- Journaux 5071-5073 : une ligne « l'aperçu garde les retours à la ligne » dans les 5 langues (≤ 491 + caractères, l'allemand). +- **Réponse à l'issue #57 : après la publication de la 3.4.0**, comme pour #48. + ## État > **Audits et relectures (2026-11-09)** — tous appliqués avant la PR, sauf ce que « Limites connues » dit. diff --git a/fastlane/metadata/android/de-DE/changelogs/5071.txt b/fastlane/metadata/android/de-DE/changelogs/5071.txt index 75adc174..e2bde697 100644 --- a/fastlane/metadata/android/de-DE/changelogs/5071.txt +++ b/fastlane/metadata/android/de-DE/changelogs/5071.txt @@ -1 +1 @@ -Neu: Notizen, die sich selbst löschen — nach 1 Std., 24 Std., 7 oder 30 Tagen oder nach dem Lesen (⋮ › Lebensdauer). Versiegelt teilen: eine verschlüsselte Datei, die nur ihr Code öffnet, über jede App gesendet (⋮ › Versiegelt teilen). Schnellablage: eine Notiz schreiben, ohne die App zu entsperren — per Kachel der Schnelleinstellungen oder langem Druck auf das Symbol (auch Neue Notiz, Diktieren). Die Tastatur wird gebeten, nichts zu lernen. +Neu: Notizen, die sich selbst löschen — nach 1 Std., 24 Std., 7 oder 30 Tagen oder nach dem Lesen (⋮ › Lebensdauer). Versiegelt teilen: eine verschlüsselte Datei, die nur ihr Code öffnet, über jede App gesendet (⋮ › Versiegelt teilen). Schnellablage: eine Notiz schreiben, ohne die App zu entsperren — per Kachel der Schnelleinstellungen oder langem Druck auf das Symbol (auch Neue Notiz, Diktieren). Die Tastatur wird gebeten, nichts zu lernen. Behoben: Die Vorschau behält Zeilenumbrüche. diff --git a/fastlane/metadata/android/de-DE/changelogs/5072.txt b/fastlane/metadata/android/de-DE/changelogs/5072.txt index 75adc174..e2bde697 100644 --- a/fastlane/metadata/android/de-DE/changelogs/5072.txt +++ b/fastlane/metadata/android/de-DE/changelogs/5072.txt @@ -1 +1 @@ -Neu: Notizen, die sich selbst löschen — nach 1 Std., 24 Std., 7 oder 30 Tagen oder nach dem Lesen (⋮ › Lebensdauer). Versiegelt teilen: eine verschlüsselte Datei, die nur ihr Code öffnet, über jede App gesendet (⋮ › Versiegelt teilen). Schnellablage: eine Notiz schreiben, ohne die App zu entsperren — per Kachel der Schnelleinstellungen oder langem Druck auf das Symbol (auch Neue Notiz, Diktieren). Die Tastatur wird gebeten, nichts zu lernen. +Neu: Notizen, die sich selbst löschen — nach 1 Std., 24 Std., 7 oder 30 Tagen oder nach dem Lesen (⋮ › Lebensdauer). Versiegelt teilen: eine verschlüsselte Datei, die nur ihr Code öffnet, über jede App gesendet (⋮ › Versiegelt teilen). Schnellablage: eine Notiz schreiben, ohne die App zu entsperren — per Kachel der Schnelleinstellungen oder langem Druck auf das Symbol (auch Neue Notiz, Diktieren). Die Tastatur wird gebeten, nichts zu lernen. Behoben: Die Vorschau behält Zeilenumbrüche. diff --git a/fastlane/metadata/android/de-DE/changelogs/5073.txt b/fastlane/metadata/android/de-DE/changelogs/5073.txt index 75adc174..e2bde697 100644 --- a/fastlane/metadata/android/de-DE/changelogs/5073.txt +++ b/fastlane/metadata/android/de-DE/changelogs/5073.txt @@ -1 +1 @@ -Neu: Notizen, die sich selbst löschen — nach 1 Std., 24 Std., 7 oder 30 Tagen oder nach dem Lesen (⋮ › Lebensdauer). Versiegelt teilen: eine verschlüsselte Datei, die nur ihr Code öffnet, über jede App gesendet (⋮ › Versiegelt teilen). Schnellablage: eine Notiz schreiben, ohne die App zu entsperren — per Kachel der Schnelleinstellungen oder langem Druck auf das Symbol (auch Neue Notiz, Diktieren). Die Tastatur wird gebeten, nichts zu lernen. +Neu: Notizen, die sich selbst löschen — nach 1 Std., 24 Std., 7 oder 30 Tagen oder nach dem Lesen (⋮ › Lebensdauer). Versiegelt teilen: eine verschlüsselte Datei, die nur ihr Code öffnet, über jede App gesendet (⋮ › Versiegelt teilen). Schnellablage: eine Notiz schreiben, ohne die App zu entsperren — per Kachel der Schnelleinstellungen oder langem Druck auf das Symbol (auch Neue Notiz, Diktieren). Die Tastatur wird gebeten, nichts zu lernen. Behoben: Die Vorschau behält Zeilenumbrüche. diff --git a/fastlane/metadata/android/en-US/changelogs/5071.txt b/fastlane/metadata/android/en-US/changelogs/5071.txt index f4d4ccdd..777cbd0b 100644 --- a/fastlane/metadata/android/en-US/changelogs/5071.txt +++ b/fastlane/metadata/android/en-US/changelogs/5071.txt @@ -1 +1 @@ -New: notes that erase themselves — in 1 h, 24 h, 7 or 30 days, or after reading (⋮ › Lifetime). Share a note sealed: an encrypted file that only its code opens, sent by any app (⋮ › Share sealed). Quick drop: write a note without unlocking the app, from a quick settings tile or a long press on the icon, which also offers New note and Dictate. The keyboard is asked not to learn what you type (Settings). +New: notes that erase themselves — in 1 h, 24 h, 7 or 30 days, or after reading (⋮ › Lifetime). Share a note sealed: an encrypted file that only its code opens, sent by any app (⋮ › Share sealed). Quick drop: write a note without unlocking the app, from a quick settings tile or a long press on the icon, which also offers New note and Dictate. The keyboard is asked not to learn what you type (Settings). Fixed: the preview keeps your line breaks. diff --git a/fastlane/metadata/android/en-US/changelogs/5072.txt b/fastlane/metadata/android/en-US/changelogs/5072.txt index f4d4ccdd..777cbd0b 100644 --- a/fastlane/metadata/android/en-US/changelogs/5072.txt +++ b/fastlane/metadata/android/en-US/changelogs/5072.txt @@ -1 +1 @@ -New: notes that erase themselves — in 1 h, 24 h, 7 or 30 days, or after reading (⋮ › Lifetime). Share a note sealed: an encrypted file that only its code opens, sent by any app (⋮ › Share sealed). Quick drop: write a note without unlocking the app, from a quick settings tile or a long press on the icon, which also offers New note and Dictate. The keyboard is asked not to learn what you type (Settings). +New: notes that erase themselves — in 1 h, 24 h, 7 or 30 days, or after reading (⋮ › Lifetime). Share a note sealed: an encrypted file that only its code opens, sent by any app (⋮ › Share sealed). Quick drop: write a note without unlocking the app, from a quick settings tile or a long press on the icon, which also offers New note and Dictate. The keyboard is asked not to learn what you type (Settings). Fixed: the preview keeps your line breaks. diff --git a/fastlane/metadata/android/en-US/changelogs/5073.txt b/fastlane/metadata/android/en-US/changelogs/5073.txt index f4d4ccdd..777cbd0b 100644 --- a/fastlane/metadata/android/en-US/changelogs/5073.txt +++ b/fastlane/metadata/android/en-US/changelogs/5073.txt @@ -1 +1 @@ -New: notes that erase themselves — in 1 h, 24 h, 7 or 30 days, or after reading (⋮ › Lifetime). Share a note sealed: an encrypted file that only its code opens, sent by any app (⋮ › Share sealed). Quick drop: write a note without unlocking the app, from a quick settings tile or a long press on the icon, which also offers New note and Dictate. The keyboard is asked not to learn what you type (Settings). +New: notes that erase themselves — in 1 h, 24 h, 7 or 30 days, or after reading (⋮ › Lifetime). Share a note sealed: an encrypted file that only its code opens, sent by any app (⋮ › Share sealed). Quick drop: write a note without unlocking the app, from a quick settings tile or a long press on the icon, which also offers New note and Dictate. The keyboard is asked not to learn what you type (Settings). Fixed: the preview keeps your line breaks. diff --git a/fastlane/metadata/android/es-ES/changelogs/5071.txt b/fastlane/metadata/android/es-ES/changelogs/5071.txt index 80658d2d..102d7aee 100644 --- a/fastlane/metadata/android/es-ES/changelogs/5071.txt +++ b/fastlane/metadata/android/es-ES/changelogs/5071.txt @@ -1 +1 @@ -Nuevo: notas que se borran solas — en 1 h, 24 h, 7 o 30 días, o tras la lectura (⋮ › Duración). Compartir una nota sellada: un archivo cifrado que solo su código abre, enviado con cualquier app. Depósito rápido: escribir una nota sin desbloquear la app, desde un mosaico de los ajustes rápidos o una pulsación larga en el icono (también Nueva nota, Dictar). Se pide al teclado que no aprenda nada (Ajustes). +Nuevo: notas que se borran solas — en 1 h, 24 h, 7 o 30 días, o tras la lectura (⋮ › Duración). Compartir una nota sellada: un archivo cifrado que solo su código abre, enviado con cualquier app. Depósito rápido: escribir una nota sin desbloquear la app, desde un mosaico de los ajustes rápidos o una pulsación larga en el icono (también Nueva nota, Dictar). Se pide al teclado que no aprenda nada (Ajustes). Corregido: la vista previa conserva los saltos de línea. diff --git a/fastlane/metadata/android/es-ES/changelogs/5072.txt b/fastlane/metadata/android/es-ES/changelogs/5072.txt index 80658d2d..102d7aee 100644 --- a/fastlane/metadata/android/es-ES/changelogs/5072.txt +++ b/fastlane/metadata/android/es-ES/changelogs/5072.txt @@ -1 +1 @@ -Nuevo: notas que se borran solas — en 1 h, 24 h, 7 o 30 días, o tras la lectura (⋮ › Duración). Compartir una nota sellada: un archivo cifrado que solo su código abre, enviado con cualquier app. Depósito rápido: escribir una nota sin desbloquear la app, desde un mosaico de los ajustes rápidos o una pulsación larga en el icono (también Nueva nota, Dictar). Se pide al teclado que no aprenda nada (Ajustes). +Nuevo: notas que se borran solas — en 1 h, 24 h, 7 o 30 días, o tras la lectura (⋮ › Duración). Compartir una nota sellada: un archivo cifrado que solo su código abre, enviado con cualquier app. Depósito rápido: escribir una nota sin desbloquear la app, desde un mosaico de los ajustes rápidos o una pulsación larga en el icono (también Nueva nota, Dictar). Se pide al teclado que no aprenda nada (Ajustes). Corregido: la vista previa conserva los saltos de línea. diff --git a/fastlane/metadata/android/es-ES/changelogs/5073.txt b/fastlane/metadata/android/es-ES/changelogs/5073.txt index 80658d2d..102d7aee 100644 --- a/fastlane/metadata/android/es-ES/changelogs/5073.txt +++ b/fastlane/metadata/android/es-ES/changelogs/5073.txt @@ -1 +1 @@ -Nuevo: notas que se borran solas — en 1 h, 24 h, 7 o 30 días, o tras la lectura (⋮ › Duración). Compartir una nota sellada: un archivo cifrado que solo su código abre, enviado con cualquier app. Depósito rápido: escribir una nota sin desbloquear la app, desde un mosaico de los ajustes rápidos o una pulsación larga en el icono (también Nueva nota, Dictar). Se pide al teclado que no aprenda nada (Ajustes). +Nuevo: notas que se borran solas — en 1 h, 24 h, 7 o 30 días, o tras la lectura (⋮ › Duración). Compartir una nota sellada: un archivo cifrado que solo su código abre, enviado con cualquier app. Depósito rápido: escribir una nota sin desbloquear la app, desde un mosaico de los ajustes rápidos o una pulsación larga en el icono (también Nueva nota, Dictar). Se pide al teclado que no aprenda nada (Ajustes). Corregido: la vista previa conserva los saltos de línea. diff --git a/fastlane/metadata/android/fr-FR/changelogs/5071.txt b/fastlane/metadata/android/fr-FR/changelogs/5071.txt index 4a64b4f7..4fee7aa6 100644 --- a/fastlane/metadata/android/fr-FR/changelogs/5071.txt +++ b/fastlane/metadata/android/fr-FR/changelogs/5071.txt @@ -1 +1 @@ -Nouveau : des notes qui s'effacent seules — dans 1 h, 24 h, 7 ou 30 jours, ou après lecture (⋮ › Durée de vie). Partager une note scellée : un fichier chiffré que seul son code ouvre, envoyé par n'importe quelle appli. Dépôt rapide : écrire une note sans déverrouiller l'appli, depuis une tuile des réglages rapides ou un appui long sur l'icône (aussi Nouvelle note, Dicter). Le clavier est prié de ne rien apprendre (Réglages). +Nouveau : des notes qui s'effacent seules — dans 1 h, 24 h, 7 ou 30 jours, ou après lecture (⋮ › Durée de vie). Partager une note scellée : un fichier chiffré que seul son code ouvre, envoyé par n'importe quelle appli. Dépôt rapide : écrire une note sans déverrouiller l'appli, depuis une tuile des réglages rapides ou un appui long sur l'icône (aussi Nouvelle note, Dicter). Le clavier est prié de ne rien apprendre (Réglages). Corrigé : l'aperçu garde les retours à la ligne. diff --git a/fastlane/metadata/android/fr-FR/changelogs/5072.txt b/fastlane/metadata/android/fr-FR/changelogs/5072.txt index 4a64b4f7..4fee7aa6 100644 --- a/fastlane/metadata/android/fr-FR/changelogs/5072.txt +++ b/fastlane/metadata/android/fr-FR/changelogs/5072.txt @@ -1 +1 @@ -Nouveau : des notes qui s'effacent seules — dans 1 h, 24 h, 7 ou 30 jours, ou après lecture (⋮ › Durée de vie). Partager une note scellée : un fichier chiffré que seul son code ouvre, envoyé par n'importe quelle appli. Dépôt rapide : écrire une note sans déverrouiller l'appli, depuis une tuile des réglages rapides ou un appui long sur l'icône (aussi Nouvelle note, Dicter). Le clavier est prié de ne rien apprendre (Réglages). +Nouveau : des notes qui s'effacent seules — dans 1 h, 24 h, 7 ou 30 jours, ou après lecture (⋮ › Durée de vie). Partager une note scellée : un fichier chiffré que seul son code ouvre, envoyé par n'importe quelle appli. Dépôt rapide : écrire une note sans déverrouiller l'appli, depuis une tuile des réglages rapides ou un appui long sur l'icône (aussi Nouvelle note, Dicter). Le clavier est prié de ne rien apprendre (Réglages). Corrigé : l'aperçu garde les retours à la ligne. diff --git a/fastlane/metadata/android/fr-FR/changelogs/5073.txt b/fastlane/metadata/android/fr-FR/changelogs/5073.txt index 4a64b4f7..4fee7aa6 100644 --- a/fastlane/metadata/android/fr-FR/changelogs/5073.txt +++ b/fastlane/metadata/android/fr-FR/changelogs/5073.txt @@ -1 +1 @@ -Nouveau : des notes qui s'effacent seules — dans 1 h, 24 h, 7 ou 30 jours, ou après lecture (⋮ › Durée de vie). Partager une note scellée : un fichier chiffré que seul son code ouvre, envoyé par n'importe quelle appli. Dépôt rapide : écrire une note sans déverrouiller l'appli, depuis une tuile des réglages rapides ou un appui long sur l'icône (aussi Nouvelle note, Dicter). Le clavier est prié de ne rien apprendre (Réglages). +Nouveau : des notes qui s'effacent seules — dans 1 h, 24 h, 7 ou 30 jours, ou après lecture (⋮ › Durée de vie). Partager une note scellée : un fichier chiffré que seul son code ouvre, envoyé par n'importe quelle appli. Dépôt rapide : écrire une note sans déverrouiller l'appli, depuis une tuile des réglages rapides ou un appui long sur l'icône (aussi Nouvelle note, Dicter). Le clavier est prié de ne rien apprendre (Réglages). Corrigé : l'aperçu garde les retours à la ligne. diff --git a/fastlane/metadata/android/it-IT/changelogs/5071.txt b/fastlane/metadata/android/it-IT/changelogs/5071.txt index c50832b1..f016931b 100644 --- a/fastlane/metadata/android/it-IT/changelogs/5071.txt +++ b/fastlane/metadata/android/it-IT/changelogs/5071.txt @@ -1 +1 @@ -Novità: note che si cancellano da sole — tra 1 h, 24 h, 7 o 30 giorni, o dopo la lettura (⋮ › Durata). Condividere una nota sigillata: un file cifrato che solo il suo codice apre, inviato con qualsiasi app. Deposito rapido: scrivere una nota senza sbloccare l'app, da un riquadro delle impostazioni rapide o tenendo premuta l'icona (anche Nuova nota, Dettare). Alla tastiera si chiede di non imparare nulla (Impostazioni). +Novità: note che si cancellano da sole — tra 1 h, 24 h, 7 o 30 giorni, o dopo la lettura (⋮ › Durata). Condividere una nota sigillata: un file cifrato che solo il suo codice apre, inviato con qualsiasi app. Deposito rapido: scrivere una nota senza sbloccare l'app, da un riquadro delle impostazioni rapide o tenendo premuta l'icona (anche Nuova nota, Dettare). Alla tastiera si chiede di non imparare nulla (Impostazioni). Corretto: l'anteprima mantiene gli a capo. diff --git a/fastlane/metadata/android/it-IT/changelogs/5072.txt b/fastlane/metadata/android/it-IT/changelogs/5072.txt index c50832b1..f016931b 100644 --- a/fastlane/metadata/android/it-IT/changelogs/5072.txt +++ b/fastlane/metadata/android/it-IT/changelogs/5072.txt @@ -1 +1 @@ -Novità: note che si cancellano da sole — tra 1 h, 24 h, 7 o 30 giorni, o dopo la lettura (⋮ › Durata). Condividere una nota sigillata: un file cifrato che solo il suo codice apre, inviato con qualsiasi app. Deposito rapido: scrivere una nota senza sbloccare l'app, da un riquadro delle impostazioni rapide o tenendo premuta l'icona (anche Nuova nota, Dettare). Alla tastiera si chiede di non imparare nulla (Impostazioni). +Novità: note che si cancellano da sole — tra 1 h, 24 h, 7 o 30 giorni, o dopo la lettura (⋮ › Durata). Condividere una nota sigillata: un file cifrato che solo il suo codice apre, inviato con qualsiasi app. Deposito rapido: scrivere una nota senza sbloccare l'app, da un riquadro delle impostazioni rapide o tenendo premuta l'icona (anche Nuova nota, Dettare). Alla tastiera si chiede di non imparare nulla (Impostazioni). Corretto: l'anteprima mantiene gli a capo. diff --git a/fastlane/metadata/android/it-IT/changelogs/5073.txt b/fastlane/metadata/android/it-IT/changelogs/5073.txt index c50832b1..f016931b 100644 --- a/fastlane/metadata/android/it-IT/changelogs/5073.txt +++ b/fastlane/metadata/android/it-IT/changelogs/5073.txt @@ -1 +1 @@ -Novità: note che si cancellano da sole — tra 1 h, 24 h, 7 o 30 giorni, o dopo la lettura (⋮ › Durata). Condividere una nota sigillata: un file cifrato che solo il suo codice apre, inviato con qualsiasi app. Deposito rapido: scrivere una nota senza sbloccare l'app, da un riquadro delle impostazioni rapide o tenendo premuta l'icona (anche Nuova nota, Dettare). Alla tastiera si chiede di non imparare nulla (Impostazioni). +Novità: note che si cancellano da sole — tra 1 h, 24 h, 7 o 30 giorni, o dopo la lettura (⋮ › Durata). Condividere una nota sigillata: un file cifrato che solo il suo codice apre, inviato con qualsiasi app. Deposito rapido: scrivere una nota senza sbloccare l'app, da un riquadro delle impostazioni rapide o tenendo premuta l'icona (anche Nuova nota, Dettare). Alla tastiera si chiede di non imparare nulla (Impostazioni). Corretto: l'anteprima mantiene gli a capo. From c15634dea572427fa882ba216955a339a60bf4dd Mon Sep 17 00:00:00 2001 From: Patrice Haltaya Date: Tue, 10 Nov 2026 13:42:10 +0100 Subject: [PATCH 2/2] docs(reprise): 3.4.0 ready for Friday 13 November Signed 3.4.0 APKs checked (TOUT OK), update 3.3.0 -> 3.4.0 tried on the S9 with the issue #57 note, F-Droid state of 10 November, site draft PR, and the steps of release day. Co-Authored-By: Claude Opus 5.5 --- REPRISE.md | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/REPRISE.md b/REPRISE.md index 064ce4c2..c5839c7c 100644 --- a/REPRISE.md +++ b/REPRISE.md @@ -9,11 +9,23 @@ Patrice : « fais 2, 3, 4 ce serait génial pour la 3.4.0 + raccourcis et clavie « en intégrant les upgrade AGP aussi » (PR #51). **Spécification, décisions D-040 à D-044, audits, limites connues et état coché : `docs/15-VERSION-3.4.md`** — la lire en premier. -- **2026-11-10 — issue #57 (koad1x) corrigée dans la 3.4.0, pas encore publiée** : l'aperçu garde les - retours à la ligne (D-045) ; pages légales (5 `terms.md`) recollées, un paragraphe par ligne. Branche - `fix/57-preview-line-breaks`. Journaux 5071-5073 ×5 complétés. **Répondre à l'issue APRÈS la release** - (brouillon dans la PR). Au 11-10, F-Droid sert toujours la 3.2.2 (aucun journal 5061-5063, index du - 11-09 02 h 28 UTC) : l'attente de la 3.3.0 continue. +- **📅 Release 3.4.0 prévue VENDREDI 2026-11-13 (Patrice, 11-10)**, si F-Droid sert alors la 3.3.0. +- **2026-11-10 — issue #57 (koad1x) corrigée dans la 3.4.0** (PR #58) : l'aperçu garde les retours à la + ligne (D-045) ; pages légales (5 `terms.md`) recollées, un paragraphe par ligne. Journaux 5071-5073 ×5 + complétés. **Répondre à l'issue APRÈS la release** (brouillon dans la PR #58). +- **F-Droid au 11-10** : 3.2.2 servie ; la 3.3.0 est dans la recette `fdroiddata` (commit du robot, 11-10 + 05 h 52 UTC), à construire au cycle suivant (celui en cours a démarré le 11-09 à 10 h 02 UTC, avant). + Ce cycle a **construit SMS 1.30.0 (307) avec succès** (`status/running.json`) : AGP 9.5 passe chez eux. +- **Prêt le 11-10** : 4 APK 3.4.0 construits depuis `4382a64` et signés, **TOUT OK** (cert, v2+v3, + 5070-5073, mêmes 4 permissions que la 3.3.0, pas d'INTERNET) ; **mise à jour essayée sur le S9** : + 3.3.0 arm64 (5062) → 3.4.0 signée (5072), 3 notes gardées dont la note de coffre PIN (verrouillée), + lancement sans plantage, défaut #57 vu en 3.3.0 et corrigé en 3.4.0. Le S9 est désormais en 3.4.0. + Site : **PR brouillon files-tech-site #45** (cartes des 5 nouveautés + méta, FR/EN/DE, `check-site` OK). +- **Jour J** : API F-Droid (5061-5063 servies) ; CI de `main` verte ; tag léger `v3.4.0` sur le commit de + `main` ; build `assembleRelease -Pnotestech.replaceInstalledApp=true` + `signer_notes_tech.py 3.4.0 + ` ; release (notes EN puis FR), SHA retéléchargés ; site #45 + complété (ligne `apps.php` à la date `publishedAt`, 3 résumés = journaux 5071 fr/en/de) puis fusionné ; + réponse à #57. - **PR #53 fusionnée** : `main` = `d523f1c` (commit de fusion), CI verte avant la fusion (porte, instrumentés API 29, release R8, zéro réseau, CodeQL), version 3.4.0 base **507** (5070-5073), journaux 5071-5073 ×5. - **⛔ Patrice, 2026-11-09 : « on attend que fdroid publie notes-tech 3.3.0 avant toute publication de la