feat(sync): le QR porte un lien pmserver://sync ouvert directement par l'app
Le scanner du telephone envoyait le texte a une recherche web (Google, Chrome) : le jeton serait parti a un appui pres. Le lien a schema propre n'a qu'une application pour l'ouvrir. Rien n'est enregistre avant Save. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+62
-21
@@ -36,7 +36,7 @@ uses
|
||||
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,
|
||||
FMX.WebBrowser,
|
||||
FMX.WebBrowser, System.Messaging,
|
||||
PMA.Vault;
|
||||
|
||||
const
|
||||
@@ -342,6 +342,10 @@ type
|
||||
procedure SetUnlockCode(const ANew: string);
|
||||
procedure PushUnlockMode;
|
||||
procedure PasteSyncSettings;
|
||||
function ApplySyncLink(const ALink: string): Boolean;
|
||||
{$IFDEF ANDROID}
|
||||
procedure OnActivityMessage(const Sender: TObject; const M: TMessage);
|
||||
{$ENDIF}
|
||||
function PwdName: string;
|
||||
/// Va chercher l'icone du site de l'entree ouverte, ou l'efface.
|
||||
procedure SetEntryIcon(AFetch: Boolean);
|
||||
@@ -381,7 +385,11 @@ implementation
|
||||
uses
|
||||
PMA.Crypto, PMA.SyncClient, PMA.Store, PMA.Biometric, PMA.Totp,
|
||||
PMA.ScreenGuard, PMA.Clipboard, PMA.Theme, PMA.WebUI, PMA.VaultPatch,
|
||||
PMA.SaveFile, PMA.Favicon, System.JSON;
|
||||
PMA.SaveFile, PMA.Favicon, System.JSON
|
||||
{$IFDEF ANDROID}
|
||||
, Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.JavaTypes,
|
||||
Androidapi.Helpers, FMX.Platform.Android
|
||||
{$ENDIF};
|
||||
|
||||
{$R *.fmx}
|
||||
|
||||
@@ -668,6 +676,18 @@ begin
|
||||
FWeb.OnDidFinishLoad := OnWebLoaded;
|
||||
FWeb.OnShouldStartLoadWithRequest := OnWebNavigate;
|
||||
FWeb.LoadFromStrings(PageHtml, '');
|
||||
|
||||
{$IFDEF ANDROID}
|
||||
// LIEN DU QR DU POSTE. Au lancement par le lien, il arrive dans l'intent de
|
||||
// depart ; app deja ouverte (singleTask), il arrive par message. WebCall met
|
||||
// en attente tant que la page n'est pas chargee.
|
||||
MainActivity.registerIntentAction(TJIntent.JavaClass.ACTION_VIEW);
|
||||
TMessageManager.DefaultManager.SubscribeToMessage(TMessageReceivedNotification,
|
||||
OnActivityMessage);
|
||||
if (TAndroidHelper.Activity.getIntent <> nil) and
|
||||
(TAndroidHelper.Activity.getIntent.getDataString <> nil) then
|
||||
ApplySyncLink(JStringToString(TAndroidHelper.Activity.getIntent.getDataString));
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure TForm8.OnWebLoaded(ASender: TObject);
|
||||
@@ -3206,33 +3226,54 @@ begin
|
||||
end;
|
||||
|
||||
procedure TForm8.PasteSyncSettings;
|
||||
var
|
||||
LDoc: TJSONObject;
|
||||
LUrl, LTok: string;
|
||||
begin
|
||||
if ApplySyncLink(CurrentClipboard.Trim) then
|
||||
ClearClipboard
|
||||
else
|
||||
WebCall('PM.toast("No settings in the clipboard - copy the link of the QR shown on the PC first")');
|
||||
end;
|
||||
|
||||
/// pmserver://sync?u=URL&t=JETON -> champs des reglages remplis, RIEN
|
||||
/// d'enregistre. Le lien peut venir de n'importe quelle page ou application :
|
||||
/// c'est Save, geste de l'utilisateur devant l'URL affichee, qui valide.
|
||||
function TForm8.ApplySyncLink(const ALink: string): Boolean;
|
||||
var
|
||||
LPair: string;
|
||||
LUrl, LTok, LName, LValue: string;
|
||||
LEq: Integer;
|
||||
begin
|
||||
Result := False;
|
||||
if not StartsText('pmserver://sync?', ALink) then Exit;
|
||||
LUrl := '';
|
||||
LTok := '';
|
||||
LDoc := TJSONObject.ParseJSONValue(CurrentClipboard.Trim) as TJSONObject;
|
||||
if LDoc <> nil then
|
||||
try
|
||||
if LDoc.GetValue<Integer>('pmsync', 0) = 1 then
|
||||
begin
|
||||
LUrl := LDoc.GetValue<string>('u', '');
|
||||
LTok := LDoc.GetValue<string>('t', '');
|
||||
end;
|
||||
finally
|
||||
LDoc.Free;
|
||||
end;
|
||||
if (LUrl = '') or (LTok = '') then
|
||||
for LPair in Copy(ALink, Length('pmserver://sync?') + 1, MaxInt).Split(['&']) do
|
||||
begin
|
||||
WebCall('PM.toast("No settings in the clipboard - scan the QR on the PC and copy its text first")');
|
||||
Exit;
|
||||
LEq := Pos('=', LPair);
|
||||
if LEq = 0 then Continue;
|
||||
LName := Copy(LPair, 1, LEq - 1);
|
||||
LValue := TNetEncoding.URL.Decode(Copy(LPair, LEq + 1, MaxInt));
|
||||
if LName = 'u' then LUrl := LValue
|
||||
else if LName = 't' then LTok := LValue;
|
||||
end;
|
||||
ClearClipboard;
|
||||
Log('Sync settings pasted from the clipboard: token ' + Fingerprint(LTok));
|
||||
if (LUrl = '') or (LTok = '') then Exit;
|
||||
Result := True;
|
||||
Log('Sync settings received from a link: token ' + Fingerprint(LTok));
|
||||
WebCall('openSettings()');
|
||||
WebCall(Format('PM.pasteConfig(%s, %s)', [JsArg(LUrl), JsArg(LTok)]));
|
||||
end;
|
||||
|
||||
{$IFDEF ANDROID}
|
||||
procedure TForm8.OnActivityMessage(const Sender: TObject; const M: TMessage);
|
||||
var
|
||||
LIntent: JIntent;
|
||||
begin
|
||||
if not (M is TMessageReceivedNotification) then Exit;
|
||||
LIntent := TMessageReceivedNotification(M).Value;
|
||||
if (LIntent <> nil) and (LIntent.getDataString <> nil) then
|
||||
ApplySyncLink(JStringToString(LIntent.getDataString));
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
function TForm8.CachePwd: string;
|
||||
begin
|
||||
if HasLocalContainer then Result := FVaultPwd else Result := FSyncPwd;
|
||||
|
||||
Reference in New Issue
Block a user