From 75a1169dc94b135c3212d5e980ba38b53ab7b079 Mon Sep 17 00:00:00 2001 From: r-zakarya <82443831+r-zakarya@users.noreply.github.com> Date: Sat, 26 Sep 2026 14:24:11 +0100 Subject: [PATCH] feat(sync): nom par defaut neutre (data.json), et plus de clavier pendant une synchro Un fichier nomme "vault-sync.json" annonce un coffre a qui parcourt la liste des depots ; le contenu est chiffre, le nom ne l'etait pas. Les configurations existantes gardent leur nom - c'est l'URL complete qui est enregistree - et le QR du poste ne raccourcit plus que le nom par defaut courant, sinon le telephone rallongerait vers un autre fichier. Synchroniser coffre ferme ouvre d'abord le coffre : ce chemin depliait le clavier de recherche au milieu d'une synchro. Co-Authored-By: Claude Opus 5 --- android-client/web/app.html | 12 ++++++++---- delphi-backend/UMainForm.pas | 13 +++++++++---- js/app.sync.js | 13 ++++++++++--- mainApk.pas | 8 ++++++-- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/android-client/web/app.html b/android-client/web/app.html index 1cf4345..5ad06b6 100644 --- a/android-client/web/app.html +++ b/android-client/web/app.html @@ -1839,14 +1839,18 @@ document.addEventListener('input', function (ev) { }); // L'inverse, pour l'affichage : l'URL d'API se relit comme l'adresse du depot. +// Meme nom par defaut que le poste - les deux doivent designer le meme +// fichier. Un depot configure avec un autre nom garde son URL complete. +var SYNC_DEFAULT_FILE = 'data.json'; + function shortRepoUrl(u) { var g = /^https:\/\/api\.github\.com\/repos\/([^\/]+)\/([^\/]+)\/contents\/(.+)$/i.exec(u || ''); if (g) return 'https://github.com/' + g[1] + '/' + g[2] + - (g[3] === 'vault-sync.json' ? '' : '/blob/main/' + g[3]); + (g[3] === SYNC_DEFAULT_FILE ? '' : '/blob/main/' + g[3]); var m = /^(https?:\/\/[^\/]+)\/api\/v1\/repos\/([^\/]+)\/([^\/]+)\/contents\/(.+)$/i.exec(u || ''); if (!m) return u; return m[1] + '/' + m[2] + '/' + m[3] + - (m[4] === 'vault-sync.json' ? '' : '/src/branch/main/' + m[4]); + (m[4] === SYNC_DEFAULT_FILE ? '' : '/src/branch/main/' + m[4]); } function normalizeRepoUrl(u) { u = u.replace(/\s+/g, ''); @@ -1855,10 +1859,10 @@ function normalizeRepoUrl(u) { // GITHUB : l'adresse du depot est sur github.com, l'API sur api.github.com. var g = u.match(/^https?:\/\/(www\.)?github\.com\/([^\/]+)\/([^\/]+?)(?:\.git)?(?:\/blob\/[^\/]+\/(.+?))?\/?$/i); if (g) return 'https://api.github.com/repos/' + g[2] + '/' + g[3] + - '/contents/' + (g[4] || 'vault-sync.json'); + '/contents/' + (g[4] || SYNC_DEFAULT_FILE); var m = u.match(/^(https?:\/\/[^\/]+)\/([^\/]+)\/([^\/]+?)(?:\.git)?(?:\/src\/branch\/[^\/]+\/(.+?))?\/?$/i); if (!m) return u; - return m[1] + '/api/v1/repos/' + m[2] + '/' + m[3] + '/contents/' + (m[4] || 'vault-sync.json'); + return m[1] + '/api/v1/repos/' + m[2] + '/' + m[3] + '/contents/' + (m[4] || SYNC_DEFAULT_FILE); } // Pas de Save pour ces deux-la : une case se voit cochee, elle s'applique. ['sBack', 'sKbd'].forEach(function (id) { diff --git a/delphi-backend/UMainForm.pas b/delphi-backend/UMainForm.pas index fd455ae..bf3e482 100644 --- a/delphi-backend/UMainForm.pas +++ b/delphi-backend/UMainForm.pas @@ -1448,16 +1448,21 @@ begin var LShort := LQrUrl; var LApi := Pos('/api/v1/repos/', LShort); // GitHub : l'adresse du depot est sur github.com, l'API sur api.github.com. + // RACCOURCI SEULEMENT POUR LE NOM PAR DEFAUT COURANT. Un depot + // configure avec un autre nom - dont l'ancien vault-sync.json - voyage + // en URL complete : le telephone rallongerait sinon vers le defaut et + // les deux appareils ne regarderaient pas le meme fichier. + const SyncDefaultFile = '/contents/data.json'; if StartsText('https://api.github.com/repos/', LShort) and - EndsText('/contents/vault-sync.json', LShort) then + EndsText(SyncDefaultFile, LShort) then LShort := 'https://github.com/' + Copy(LShort, Length('https://api.github.com/repos/') + 1, Length(LShort) - Length('https://api.github.com/repos/') - - Length('/contents/vault-sync.json')) - else if (LApi > 0) and EndsText('/contents/vault-sync.json', LShort) then + Length(SyncDefaultFile)) + else if (LApi > 0) and EndsText(SyncDefaultFile, LShort) then LShort := Copy(LShort, 1, LApi) + Copy(LShort, LApi + Length('/api/v1/repos/'), - Length(LShort) - LApi - Length('/api/v1/repos/') - Length('/contents/vault-sync.json') + 1); + Length(LShort) - LApi - Length('/api/v1/repos/') - Length(SyncDefaultFile) + 1); LShort := StringReplace(LShort, '%', '%25', [rfReplaceAll]); LShort := StringReplace(LShort, '&', '%26', [rfReplaceAll]); LShort := StringReplace(LShort, '#', '%23', [rfReplaceAll]); diff --git a/js/app.sync.js b/js/app.sync.js index 2800532..4b2dc9c 100644 --- a/js/app.sync.js +++ b/js/app.sync.js @@ -92,21 +92,28 @@ function syncIsGitea(url) { // ADRESSE DU DEPOT TELLE QUE LE NAVIGATEUR (OU "git clone") LA DONNE. // https://github.com/O/R(.git) -> API de GitHub ; https://hote/O/R(.git) -> API -// de Gitea. Fichier par defaut vault-sync.json, ou celui d'un lien .../blob/B/F +// de Gitea. Fichier par defaut SYNC_DEFAULT_FILE, ou celui d'un lien .../blob/B/F // (GitHub) ou .../src/branch/B/F (Gitea). Tout le reste passe tel quel - une // URL WebDAV, une URL d'API deja complete. GARDE : un dernier segment qui a // l'air d'un fichier (.json...) n'est pas un depot - sinon // https://serveur/webdav/vault.json deviendrait une API Gitea imaginaire. +// LE NOM NE DIT PAS CE QUE C'EST. Un fichier appele "vault-sync.json" dans un +// depot annonce un coffre a qui parcourt la liste des depots ; le contenu est +// chiffre, mais le nom, lui, designe la cible. Les anciennes configurations +// gardent leur nom : c'est l'URL complete qui est enregistree, et elle ne +// passe pas par ici. +const SYNC_DEFAULT_FILE = 'data.json'; + function syncNormalizeRepoUrl(u) { u = (u || '').replace(/\s+/g, ''); if (!u || syncIsGitea(u)) return u; const g = u.match(/^https?:\/\/(www\.)?github\.com\/([^\/]+)\/([^\/]+?)(?:\.git)?(?:\/blob\/[^\/]+\/(.+?))?\/?$/i); if (g) return 'https://api.github.com/repos/' + g[2] + '/' + g[3] + - '/contents/' + (g[4] || 'vault-sync.json'); + '/contents/' + (g[4] || SYNC_DEFAULT_FILE); const m = u.match(/^(https?:\/\/[^\/]+)\/([^\/]+)\/([^\/]+?)(\.git)?(?:\/src\/branch\/[^\/]+\/(.+?))?\/?$/i); if (!m) return u; if (!m[4] && !m[5] && /\.[a-z0-9]{2,5}$/i.test(m[3])) return u; // un fichier, pas un depot - return m[1] + '/api/v1/repos/' + m[2] + '/' + m[3] + '/contents/' + (m[5] || 'vault-sync.json'); + return m[1] + '/api/v1/repos/' + m[2] + '/' + m[3] + '/contents/' + (m[5] || SYNC_DEFAULT_FILE); } // UN DEPOT PUBLIC EST REFUSE. Chaque synchro est un commit : l'historique garde diff --git a/mainApk.pas b/mainApk.pas index 8b777cd..fcae712 100644 --- a/mainApk.pas +++ b/mainApk.pas @@ -2567,8 +2567,12 @@ begin try LSw := TStopwatch.StartNew; AdoptVault(LPlain); - if FUiKbdOnSearch then - WebCall('PM.focusSearch()'); // on ouvre pour chercher : clavier pret + // ON OUVRE POUR CHERCHER - sauf quand l'ouverture n'est qu'une etape. + // Synchroniser coffre ferme passe par ici avant de publier : le clavier + // montait alors au milieu d'une synchro, pour une recherche que personne + // n'avait demandee. + if FUiKbdOnSearch and (not LChainSync) then + WebCall('PM.focusSearch()'); Log(' displayed in ' + LSw.ElapsedMilliseconds.ToString + ' ms'); // Afficher d'abord, synchroniser ensuite : le coffre est a l'ecran, le // reseau se debrouille derriere. Sans mot de passe range, on ne peut