diff --git a/android-client/web/app.html b/android-client/web/app.html index f76b4b9..170c608 100644 --- a/android-client/web/app.html +++ b/android-client/web/app.html @@ -285,8 +285,15 @@ function drain() { f.src = 'cmd://' + queue.shift(); document.body.appendChild(f); setTimeout(function () { - f.parentNode.removeChild(f); - drain(); + // LE try/finally EST L'INTERET DE CE BLOC. Sans lui, une exception au + // retrait de l'iframe laisse "sending" a vrai pour toujours : plus une + // seule commande ne repart, et l'interface devient muette sans rien + // signaler. Le meme piege existait cote Delphi sur l'indicateur d'occupation. + try { + if (f.parentNode) f.parentNode.removeChild(f); + } finally { + drain(); + } }, 60); } @@ -496,7 +503,9 @@ var PM = { setActions: function (canOpen, syncLabel, busy) { var o = document.getElementById('btnOpen'), s = document.getElementById('btnSync'); o.hidden = !canOpen; - s.innerHTML = '↻  ' + syncLabel; + // textContent et non innerHTML : l'intitule vient de Delphi, et une valeur + // interpretee comme du balisage n'a pas de raison de l'etre. + s.textContent = '\u21BB ' + syncLabel; o.disabled = busy; s.disabled = busy; o.style.opacity = busy ? .4 : 1; s.style.opacity = busy ? .4 : 1; diff --git a/mainApk.pas b/mainApk.pas index 8bbbfa2..b08ebc6 100644 --- a/mainApk.pas +++ b/mainApk.pas @@ -119,6 +119,14 @@ type FClipTimer: TTimer; FCopied: string; + /// ECHEANCE SUR UNE OPERATION RESEAU. Sans elle, un appel qui ne rend + /// jamais la main laisse l'interface morte et muette : les deux actions + /// restent desactivees, aucun message n'apparait, et rien n'y ramene - + /// c'est arrive avec le serveur local arrete. Les delais de THTTPClient + /// sont censes couvrir ce cas ; celui-ci couvre le jour ou ils ne le font + /// pas, quelle qu'en soit la raison. + FDeadline: TTimer; + // --- verrouillage sur inactivite FIdleTimer: TTimer; FLastActivity: TDateTime; @@ -161,6 +169,7 @@ type procedure PushConfig; procedure OpenEntry(AVaultIndex: Integer); procedure OnClipTimer(Sender: TObject); + procedure OnDeadline(Sender: TObject); procedure OnHardwareBack(Sender: TObject; var Key: Word; var KeyChar: WideChar; Shift: TShiftState); @@ -228,6 +237,14 @@ begin FClipTimer.Interval := CLIPBOARD_CLEAR_SECONDS * 1000; FClipTimer.OnTimer := OnClipTimer; + // Plus long que les delais de THTTPClient (15 s), pour que le message precis + // du client reseau arrive le premier quand il fonctionne. Celui-ci n'est que + // le filet. + FDeadline := TTimer.Create(Self); + FDeadline.Enabled := False; + FDeadline.Interval := 25000; + FDeadline.OnTimer := OnDeadline; + FTotpTimer := TTimer.Create(Self); FTotpTimer.Enabled := False; FTotpTimer.Interval := 1000; @@ -1022,11 +1039,35 @@ begin end; procedure TForm8.SetBusy(ABusy: Boolean); +var + LCanOpen: Boolean; + LLabel: string; begin FBusy := ABusy; - WebCall(Format('PM.setActions(%s, "Sync", %s)', - [LowerCase(BoolToStr(HasVault and not FVaultUnreadable, True)), + FDeadline.Enabled := False; // reposee a zero, pas prolongee + FDeadline.Enabled := ABusy; + LCanOpen := HasVault and not FVaultUnreadable; + // L'intitule suit l'etat du cache et non un mot fixe : sans coffre local, + // l'action n'est pas une synchronisation mais un premier telechargement, et + // le reprendre en dur ici effacait cette distinction a chaque passage. + if LCanOpen then LLabel := 'Sync' else LLabel := 'Download vault'; + WebCall(Format('PM.setActions(%s, %s, %s)', + [LowerCase(BoolToStr(LCanOpen, True)), JsArg(LLabel), LowerCase(BoolToStr(ABusy, True))])); end; +/// L'operation reseau n'a pas rendu la main dans le delai. On rend l'interface +/// a l'utilisateur et on le dit. Le thread, lui, est ABANDONNE : il mourra +/// quand sa socket finira par echouer, et s'il aboutit malgre tout, son +/// resultat s'affichera - il n'y a rien a annuler. +procedure TForm8.OnDeadline(Sender: TObject); +begin + FDeadline.Enabled := False; + if not FBusy then Exit; + Log(' no reply after ' + (FDeadline.Interval div 1000).ToString + + ' s - request abandoned'); + Status('No reply from the server'); + SetBusy(False); +end; + end.