From 382e38913b966485f520beeeffd126d2e95f7582 Mon Sep 17 00:00:00 2001 From: r-zakarya <82443831+r-zakarya@users.noreply.github.com> Date: Mon, 17 Aug 2026 19:05:28 +0100 Subject: [PATCH] feat(android): the write path works, and settings survive a 304 Proven on device, against the real repository: GET first: HTTP 200, sha 8feb3b7d... PUT .../write-test.json OK 200 - new sha 67d6a4b2... Read the sha, write with it, receive the next one. Section 4 step 3 is done. The probe reads before writing because that is the real sequence: an empty sha means "create", and Gitea answers 422 when the file is already there - which is what it did, and rightly. The second fix comes from an interaction between two changes made hours apart today, and only visible once both were in place. Settings are stored on the line after "received N bytes"; but now that the sha comparison works, a sync answers 304 and returns before ever reaching it. So a freshly typed token was never saved and vanished on close - which is exactly what the user reported. They are now kept as soon as the transport answered at all, 200 or 304: both prove the address and the token, only the body differs. Co-Authored-By: Claude Opus 5 --- mainApk.pas | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/mainApk.pas b/mainApk.pas index 20ca97a..1008254 100644 --- a/mainApk.pas +++ b/mainApk.pas @@ -32,7 +32,7 @@ interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Diagnostics, System.Rtti, System.NetEncoding, System.DateUtils, - System.Generics.Collections, System.IOUtils, System.Hash, + System.Generics.Collections, System.IOUtils, System.Hash, System.StrUtils, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Platform, FMX.Controls.Presentation, FMX.StdCtrls, FMX.Memo, FMX.Memo.Types, FMX.ScrollBox, FMX.Layouts, FMX.Edit, FMX.ListBox, FMX.Objects, @@ -493,8 +493,8 @@ begin procedure var LClient: TSyncClient; - LRes: TSyncResult; - LBody: string; + LRes, LGet: TSyncResult; + LBody, LSha: string; begin LClient := TSyncClient.Create(LUrl, FToken); try @@ -503,12 +503,23 @@ begin [FormatDateTime('yyyy-mm-dd"T"hh:nn:ss"Z"', TTimeZone.Local.ToUniversalTime(Now))]), FSyncPwd, 1000); + // LIRE D'ABORD, ECRIRE ENSUITE - la sequence reelle. Un sha vide veut + // dire « cree », et Gitea refuse alors en 422 si le fichier est deja + // la ; c'est le cas de mise a jour qui compte, et il exige le sha + // courant. Un 404 au GET signifie simplement qu'il n'existe pas + // encore : on cree, sha vide. + LGet := LClient.Fetch; + if LGet.Status = ssOK then + LSha := LGet.ETag + else + LSha := ''; + Log(Format('GET first: HTTP %d, sha %s', [LGet.HttpCode, + IfThen(LSha = '', '(aucun - creation)', LSha)])); + Log('PUT ' + LUrl); Log(Format(' token %s (%d chars), body %d chars', [Fingerprint(FToken), Length(FToken), Length(LBody)])); - // Sha vide : on cree le fichier, ou on echoue en 409 s'il existe deja - - // ce qui prouverait le controle de concurrence aussi surement. - LRes := LClient.Put(LBody, '', 'write path probe from phone'); + LRes := LClient.Put(LBody, LSha, 'write path probe from phone'); case LRes.Status of ssOK: Log(' OK ' + LRes.HttpCode.ToString + ' - new sha ' + LRes.ETag); ssConflict: Log(' 409 - file already there, concurrency control works'); @@ -980,6 +991,20 @@ begin else Log(' no HTTP reply after ' + LSw.ElapsedMilliseconds.ToString + ' ms'); + // LES COORDONNEES SONT RETENUES DES QUE LE TRANSPORT A REPONDU, 200 + // comme 304 : les deux prouvent l'adresse et le jeton, seul le corps + // differe. Elles ne l'etaient que sur le chemin du 200, et depuis que + // la comparaison de sha fonctionne une synchronisation repond + // presque toujours 304 - donc un jeton fraichement saisi n'etait + // jamais enregistre, et disparaissait a la fermeture. + if LRes.Status in [ssOK, ssNotModified] then + try + SaveDeviceSettings(AUrl, ATok); + except + on E: Exception do + Log(' settings not saved: ' + E.ClassName + ' - ' + E.Message); + end; + case LRes.Status of ssNotModified: begin