From 8315ce92309609275e1e543ff3847cbd3fcdb13f Mon Sep 17 00:00:00 2001 From: r-zakarya <82443831+r-zakarya@users.noreply.github.com> Date: Sat, 22 Aug 2026 11:33:10 +0100 Subject: [PATCH] fix(android): editing a note was about to strip its line breaks Making every field editable put a note's body behind an , and HTML's value sanitization removes CR and LF without a word. The formatting would have been lost on the phone and published to the repository at the next save - silent, and irreversible once the desktop pulled it. Multi-line is marked on the row in Delphi, like the field name, rather than guessed from the caption or from whether the value happens to contain a newline today: a single-line note one wants to make multi-line deserves the same control. The row wraps through a class set when the editor opens, not through :has() - that selector does not exist before Chrome 105, and an older engine would ignore the rule without saying so. --- android-client/PMA.WebUI.pas | 12 ++++++++++-- android-client/web/app.html | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/android-client/PMA.WebUI.pas b/android-client/PMA.WebUI.pas index 206fc52..b0b3726 100644 --- a/android-client/PMA.WebUI.pas +++ b/android-client/PMA.WebUI.pas @@ -166,6 +166,11 @@ type /// Rang de la piece jointe dans l'entree, ou -1. Il ne se deduit pas du /// rang de la ligne : les champs personnalises s'intercalent avant. AttachIndex: Integer; + /// La valeur tient sur plusieurs lignes. Marque ICI, pas devine du libelle + /// ni du contenu : un APPLIQUE la sanitisation de HTML et retire + /// les retours a la ligne en silence. Une note modifiee depuis le telephone + /// y perdait sa mise en forme, et la perte partait au depot. + Multiline: Boolean; end; function BuildRows(const E: TVaultEntry): TArray; @@ -174,7 +179,8 @@ var I: Integer; procedure Add(const ACaption, AValue: string; ASecret: Boolean; - const AField: string = ''; AAttach: Integer = -1); + const AField: string = ''; AAttach: Integer = -1; + AMultiline: Boolean = False); begin // Une ligne vide n'apprend rien - SAUF si elle se remplit. Un identifiant // absent qu'on ne peut pas ajouter serait une impasse. @@ -185,6 +191,7 @@ var LRows[High(LRows)].Secret := ASecret; LRows[High(LRows)].Field := AField; LRows[High(LRows)].AttachIndex := AAttach; + LRows[High(LRows)].Multiline := AMultiline; end; begin @@ -195,7 +202,7 @@ begin // Un site et un identifiant n'ont aucun sens pour une note. Les proposer // vides reviendrait a inviter a remplir ce que rien n'affichera jamais. if E.IsNote then - Add('Content', E.Password, False, 'password') + Add('Content', E.Password, False, 'password', -1, True) else begin Add('Site', E.Site, False, 'site'); @@ -263,6 +270,7 @@ begin // "enregistrable", et la page y met le bouton de telechargement. if LRows[I].AttachIndex >= 0 then LObj.AddPair('a', TJSONNumber.Create(LRows[I].AttachIndex)); + if LRows[I].Multiline then LObj.AddPair('m', TJSONBool.Create(True)); LArr.AddElement(LObj); end; Result := LRoot.ToJSON; diff --git a/android-client/web/app.html b/android-client/web/app.html index 6a56f12..aae2afd 100644 --- a/android-client/web/app.html +++ b/android-client/web/app.html @@ -85,6 +85,13 @@ dependre d'une mesure qui n'arrive jamais. Elle disparait au premier champ quitte, donc rien ne flotte quand on ne tape pas. */ body.typing .scroll { padding-bottom: 60vh; } + /* Une zone de texte occupe plusieurs lignes : la rangee cesse d'etre une + rangee. Sans cela les boutons la compriment a la hauteur d'un champ. + UNE CLASSE POSEE A L'OUVERTURE, pas un selecteur :has() - celui-ci + n'existe pas avant Chrome 105, et un moteur plus ancien ignorerait la + regle sans rien dire. */ + .line.wrap { flex-wrap: wrap; } + .line.wrap textarea { flex-basis: 100%; } /* --- barre de recherche ------------------------------------------------ */ .top { padding: 10px 12px 6px; display: flex; gap: 8px; } @@ -830,6 +837,15 @@ document.getElementById('fields').addEventListener('click', function (ev) { function editorControl(k) { var val = detailRows[k].v; var style = ' style="margin:0;flex:1;min-width:0;width:auto"'; + // UNE ZONE DE TEXTE POUR CE QUI TIENT SUR PLUSIEURS LIGNES. Un + // applique la sanitisation de HTML et retire les retours a la ligne en + // silence : le corps d'une note y perdait sa mise en forme, et la perte + // partait au depot a l'enregistrement suivant. + if (detailRows[k].m) + return ''; if (editField !== 'folder') return '