From d1d5d2987953dfd6ee3fa2bf0e3bf20627e28960 Mon Sep 17 00:00:00 2001 From: r-zakarya <82443831+r-zakarya@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:18:33 +0100 Subject: [PATCH] fix(android): the page stops sliding, and locking comes back A swipe with nothing to scroll dragged the whole document, showing the body gradient sliding under the screen gradient - two gradients stacked and no content at all. overflow:hidden does not prevent that in an Android WebView; position:fixed does. The lock button went missing when the list moved to HTML: it lived in the old FMX bottom bar and had no counterpart in the page. It returns as a padlock next to the search field, no label - it is the one icon universal enough to stand alone. Icons on the unlock screen too, as code points since this source is read as ANSI. All four are basic-plane and common, so a font without them would show an empty box rather than a wrong glyph; checked on the device, they render. Co-Authored-By: Claude Opus 5 --- android-client/web/app.html | 44 +++++++++++++++++++++++++++++++++---- mainApk.pas | 23 ++++++++++++++----- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/android-client/web/app.html b/android-client/web/app.html index 8e23f73..c5dd0dd 100644 --- a/android-client/web/app.html +++ b/android-client/web/app.html @@ -31,8 +31,15 @@ } * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; } html, body { - margin: 0; height: 100%; overflow: hidden; - background: linear-gradient(var(--bg-top), var(--bg-bot)) fixed; + /* CLOUE AU CADRE. overflow:hidden ne suffit pas dans un WebView Android : + un glissement qui ne trouve rien a faire defiler fait quand meme + glisser le document entier, et on voit alors le degrade du corps passer + sous celui de l'ecran - deux degrades empiles, sans le moindre contenu. + position:fixed lui retire cette liberte. */ + position: fixed; inset: 0; + margin: 0; overflow: hidden; + overscroll-behavior: none; + background: var(--bg-bot); color: var(--text); font: 15px/1.4 system-ui, "Roboto", sans-serif; /* Le texte de l'interface ne se selectionne pas - un appui maintenu sur @@ -56,7 +63,7 @@ body.on-detail #detail { transform: translateX(0); } .scroll { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; - padding: 0 12px 16px; } + overscroll-behavior: contain; padding: 0 12px 16px; } /* --- barre de recherche ------------------------------------------------ */ .top { padding: 10px 12px 6px; display: flex; gap: 8px; } @@ -74,6 +81,7 @@ color: var(--muted); font-size: 17px; } .glass { left: 2px; } + .glass svg { width: 19px; height: 19px; } .clear { right: 2px; display: none; font-size: 20px; } body.searching .glass { display: none; } body.searching .clear { display: flex; } @@ -122,6 +130,18 @@ .empty { text-align: center; color: var(--muted); padding: 48px 16px; } + /* --- boutons a icone ---------------------------------------------------- */ + /* Une icone seule ne dit ce qu'elle fait que si elle est archi-connue. Le + cadenas l'est ; c'est pourquoi il est le seul a se passer d'intitule. */ + .ico { + flex: 0 0 46px; width: 46px; height: 46px; border: 0; padding: 0; + border-radius: var(--radius-s); background: rgba(255,255,255,.10); + color: var(--text); display: flex; align-items: center; + justify-content: center; + } + .ico:active { opacity: .62; } + .ico svg { width: 21px; height: 21px; } + /* --- detail ------------------------------------------------------------ */ .head { display: flex; align-items: center; gap: 10px; padding: 10px 12px; } .head h1 { flex: 1; margin: 0; font-size: 19px; font-weight: 600; @@ -156,11 +176,24 @@
+
@@ -286,6 +319,9 @@ q.addEventListener('input', function () { renderRows(); send('touch'); }); +document.getElementById('lock').addEventListener('click', function () { + send('lock'); +}); document.getElementById('qx').addEventListener('click', function () { q.value = ''; query = ''; document.body.classList.remove('searching'); diff --git a/mainApk.pas b/mainApk.pas index 79babfe..3811650 100644 --- a/mainApk.pas +++ b/mainApk.pas @@ -187,6 +187,17 @@ uses {$R *.fmx} +const + // Pictogrammes des boutons, EN POINTS DE CODE : ce fichier n'a pas de marque + // d'ordre d'octets, Delphi le lit en ANSI, et un caractere ecrit tel quel y + // deviendrait deux ou trois glyphes. Tous choisis dans le plan de base et + // parmi les plus courants - une police systeme qui n'en aurait pas + // afficherait un rectangle vide, ce qui se verrait tout de suite. + GLYPH_OPEN = #$279C; // fleche pleine + GLYPH_SYNC = #$21BB; // fleche circulaire + GLYPH_GEAR = #$2699; // engrenage + GLYPH_LOG = #$2261; // trois traits + { ---------------------------------------------------------------------------- Construction ---------------------------------------------------------------------------- } @@ -334,17 +345,17 @@ begin LRow.Height := 48; LRow.Margins.Rect := RectF(16, 8, 16, 0); - FBtnLog := FlatButton(LRow, 'Log', OnToggleLog); + FBtnLog := FlatButton(LRow, GLYPH_LOG + ' Log', OnToggleLog); FBtnLog.Align := TAlignLayout.Right; FBtnLog.Width := 120; FBtnLog.Margins.Left := 8; - FBtnSettings := FlatButton(LRow, 'Server settings', OnToggleSettings); + FBtnSettings := FlatButton(LRow, GLYPH_GEAR + ' Server settings', OnToggleSettings); FBtnSettings.Align := TAlignLayout.Client; - FBtnSync := TopButton(FLayUnlock, 'Sync', DoSync); + FBtnSync := TopButton(FLayUnlock, GLYPH_SYNC + ' Sync', DoSync); // Accentue : c'est l'action attendue quand aucun coffre n'est encore la. - FBtnOpen := TopButton(FLayUnlock, 'Open vault', DoOpenLocal, 52, True); + FBtnOpen := TopButton(FLayUnlock, GLYPH_OPEN + ' Open vault', DoOpenLocal, 52, True); FStatus := TLabel.Create(Self); FStatus.Parent := FLayUnlock; @@ -373,12 +384,12 @@ begin Status('Vault on this device - protected') else Status('Vault on this device'); - SetButtonText(FBtnSync, 'Sync'); + SetButtonText(FBtnSync, GLYPH_SYNC + ' Sync'); end else begin Status('No local vault - first download'); - SetButtonText(FBtnSync, 'Download vault'); + SetButtonText(FBtnSync, GLYPH_SYNC + ' Download vault'); end; end;