mobile-connector: merge pairing+devices into one self-service Mobile App page
Nightly Build / build (push) Successful in 7m3s

The two admin-only console pages become a single "Mobile App" page
visible to every logged-in user: connection status (with the last
connection error for troubleshooting), the device list (admin sees all,
others only their own), a pairing dialog with the QR, and — admin-only —
a settings dialog hosting the plugin config, including a relay picker
(official grayed out, test, custom URL). The generic plugin-detail
config form defers to it via the new Plugin::config_in_detail_page flag.

Pairing is now self-service: any user opens a window and the device
auto-binds to them; revocation is admin-for-anyone, owner-for-self;
(re)binding to another user stays admin-only. Binding-managed plugins
(manages_own_access) now expose their non-admin pages to all users and
self-scope per caller (web_pages_for). The relay client records the
error that ends a WS session and clears it on reconnect.
This commit is contained in:
2026-07-27 23:49:50 +01:00
parent a78259551e
commit 50e1333d99
18 changed files with 834 additions and 411 deletions
+139 -49
View File
@@ -1,4 +1,4 @@
// Frontend translations for the mobile-connector page fragments.
// Frontend translations for the mobile-connector "Mobile App" page fragment.
//
// Served at `/api/plugin/mobile-connector/web/i18n.js` and imported by
// `common.js`, which registers it into the host's shared dictionaries via
@@ -10,30 +10,60 @@ const P = 'plugin.mobile-connector';
export default {
en: {
[`${P}.pairing.title`]: 'Pair a device',
[`${P}.pairing.intro`]: 'Open a pairing window, then scan the QR code with the Skald mobile app. The device is linked to you and works immediately — you can reassign it to another user from the Mobile devices page.',
[`${P}.pairing.open`]: 'Open pairing window',
[`${P}.pairing.opening`]: 'Opening…',
[`${P}.pairing.qr_alt`]: 'Pairing QR',
[`${P}.pairing.expired`]: 'Window expired',
[`${P}.pairing.scan_within`]: 'Scan within {n}s',
[`${P}.pairing.new_code`]: 'New code',
[`${P}.pairing.close`]: 'Close',
[`${P}.app.title`]: 'Mobile App',
[`${P}.app.pair_new`]: 'Pair new device',
[`${P}.status.loading`]: 'Checking…',
[`${P}.status.connected`]: 'Connected',
[`${P}.status.connecting`]: 'Connecting…',
[`${P}.status.off`]: 'Not running',
[`${P}.status.connecting_hint`]: 'The connector is not reachable at the moment — reconnecting automatically. Pairing is unavailable until the connection is back.',
[`${P}.status.last_error`]: 'Last error',
[`${P}.status.off_hint`]: 'The mobile connector is not running. Ask an administrator to configure it.',
[`${P}.status.off_hint_admin`]: 'The mobile connector is not running — open the settings (gear icon) and pick a relay server to bring it up.',
[`${P}.pair.title`]: 'Pair new device',
[`${P}.pair.intro`]: 'Scan the QR code with the Skald mobile app. The device is linked to your account and works immediately.',
[`${P}.pair.opening`]: 'Opening…',
[`${P}.pair.qr_alt`]: 'Pairing QR',
[`${P}.pair.expired`]: 'Code expired',
[`${P}.pair.scan_within`]: 'Scan within {n}s',
[`${P}.pair.new_code`]: 'New code',
[`${P}.pair.retry`]: 'Try again',
[`${P}.pair.cancel`]: 'Cancel',
[`${P}.pair.close`]: 'Done',
[`${P}.pair.done`]: 'Device paired!',
[`${P}.pair.done_hint`]: 'The device has been linked to your account and appears in the list.',
[`${P}.cfg.title`]: 'Mobile connector settings',
[`${P}.cfg.open`]: 'Settings',
[`${P}.cfg.not_found`]: 'Plugin not found.',
[`${P}.cfg.relay`]: 'Relay server',
[`${P}.cfg.relay_official`]: 'SkaldCircle — Official Relay Server',
[`${P}.cfg.relay_test`]: 'SkaldCircle — Test Server',
[`${P}.cfg.relay_custom`]: 'Custom — enter the URL manually',
[`${P}.cfg.coming_soon`]: 'coming soon',
[`${P}.cfg.bad_url`]: 'Enter a valid ws:// or wss:// URL.',
[`${P}.cfg.pairing_ttl`]: 'Pairing code lifetime (seconds)',
[`${P}.cfg.pairing_ttl_desc`]: 'How long a pairing QR code stays valid. Max 600.',
[`${P}.cfg.require_confirmation`]: 'Require device confirmation',
[`${P}.cfg.require_confirmation_desc`]:'A device paired outside a web pairing window stays pending until an admin assigns it (recommended).',
[`${P}.cfg.notify_delay`]: 'Notification delay (seconds)',
[`${P}.cfg.notify_delay_desc`]: 'Wait this long before pushing an approval/question to the phone. If you answer on the computer within the window, no phone notification is sent. 0 = push immediately.',
[`${P}.cfg.cancel`]: 'Cancel',
[`${P}.cfg.save`]: 'Save',
[`${P}.cfg.saving`]: 'Saving…',
[`${P}.cfg.saved`]: 'Saved — the connector is restarting with the new settings.',
[`${P}.devices.title`]: 'Mobile devices',
[`${P}.devices.refresh`]: 'Refresh',
[`${P}.devices.loading`]: 'Loading…',
[`${P}.devices.empty`]: 'No paired devices yet.',
[`${P}.devices.empty_hint`]: 'Use the Pair a device page to add one.',
[`${P}.devices.col_device`]: 'Device',
[`${P}.devices.col_state`]: 'State',
[`${P}.devices.col_bound`]: 'Bound to',
[`${P}.devices.empty_hint`]: 'Use "Pair new device" above to add one.',
[`${P}.devices.col_last_seen`]: 'Last seen',
[`${P}.devices.col_actions`]: 'Actions',
[`${P}.devices.state_authorized`]: 'authorized',
[`${P}.devices.state_pending`]: 'pending',
[`${P}.devices.assign_to`]: 'Assign to…',
[`${P}.devices.bind`]: 'Bind',
[`${P}.devices.revoke`]: 'Revoke',
[`${P}.devices.revoke_confirm`]: 'Revoke this device? It loses access immediately.',
[`${P}.devices.unknown`]: 'Unknown device',
@@ -45,30 +75,60 @@ export default {
},
it: {
[`${P}.pairing.title`]: 'Associa un dispositivo',
[`${P}.pairing.intro`]: 'Apri una finestra di associazione, poi scansiona il codice QR con lapp Skald sul telefono. Il dispositivo viene collegato a te e funziona subito — puoi riassegnarlo a un altro utente dalla pagina Dispositivi mobili.',
[`${P}.pairing.open`]: 'Apri finestra di associazione',
[`${P}.pairing.opening`]: 'Apertura…',
[`${P}.pairing.qr_alt`]: 'QR di associazione',
[`${P}.pairing.expired`]: 'Finestra scaduta',
[`${P}.pairing.scan_within`]: 'Scansiona entro {n}s',
[`${P}.pairing.new_code`]: 'Nuovo codice',
[`${P}.pairing.close`]: 'Chiudi',
[`${P}.app.title`]: 'Mobile App',
[`${P}.app.pair_new`]: 'Associa nuovo dispositivo',
[`${P}.status.loading`]: 'Verifica…',
[`${P}.status.connected`]: 'Connesso',
[`${P}.status.connecting`]: 'Connessione…',
[`${P}.status.off`]: 'Non attivo',
[`${P}.status.connecting_hint`]: 'Il connettore non è raggiungibile al momento — riconnessione automatica in corso. Lassociazione non è disponibile finché la connessione non torna.',
[`${P}.status.last_error`]: 'Ultimo errore',
[`${P}.status.off_hint`]: 'Il connettore mobile non è attivo. Chiedi a un amministratore di configurarlo.',
[`${P}.status.off_hint_admin`]: 'Il connettore mobile non è attivo — apri le impostazioni (icona a ingranaggio) e scegli un relay server per avviarlo.',
[`${P}.pair.title`]: 'Associa nuovo dispositivo',
[`${P}.pair.intro`]: 'Scansiona il codice QR con lapp Skald sul telefono. Il dispositivo viene collegato al tuo account e funziona subito.',
[`${P}.pair.opening`]: 'Apertura…',
[`${P}.pair.qr_alt`]: 'QR di associazione',
[`${P}.pair.expired`]: 'Codice scaduto',
[`${P}.pair.scan_within`]: 'Scansiona entro {n}s',
[`${P}.pair.new_code`]: 'Nuovo codice',
[`${P}.pair.retry`]: 'Riprova',
[`${P}.pair.cancel`]: 'Annulla',
[`${P}.pair.close`]: 'Fatto',
[`${P}.pair.done`]: 'Dispositivo associato!',
[`${P}.pair.done_hint`]: 'Il dispositivo è stato collegato al tuo account e compare nellelenco.',
[`${P}.cfg.title`]: 'Impostazioni connettore mobile',
[`${P}.cfg.open`]: 'Impostazioni',
[`${P}.cfg.not_found`]: 'Plugin non trovato.',
[`${P}.cfg.relay`]: 'Relay server',
[`${P}.cfg.relay_official`]: 'SkaldCircle — Relay Server ufficiale',
[`${P}.cfg.relay_test`]: 'SkaldCircle — Test Server',
[`${P}.cfg.relay_custom`]: 'Personalizzato — inserisci lURL a mano',
[`${P}.cfg.coming_soon`]: 'in arrivo',
[`${P}.cfg.bad_url`]: 'Inserisci un URL ws:// o wss:// valido.',
[`${P}.cfg.pairing_ttl`]: 'Durata del codice di associazione (secondi)',
[`${P}.cfg.pairing_ttl_desc`]: 'Per quanto tempo un QR di associazione resta valido. Massimo 600.',
[`${P}.cfg.require_confirmation`]: 'Richiedi conferma del dispositivo',
[`${P}.cfg.require_confirmation_desc`]:'Un dispositivo associato fuori da una finestra web resta in attesa finché un amministratore non lo assegna (consigliato).',
[`${P}.cfg.notify_delay`]: 'Ritardo notifiche (secondi)',
[`${P}.cfg.notify_delay_desc`]: 'Attendi questo tempo prima di inviare unapprovazione/domanda al telefono. Se rispondi dal computer entro la finestra, nessuna notifica viene inviata. 0 = invia subito.',
[`${P}.cfg.cancel`]: 'Annulla',
[`${P}.cfg.save`]: 'Salva',
[`${P}.cfg.saving`]: 'Salvataggio…',
[`${P}.cfg.saved`]: 'Salvato — il connettore si sta riavviando con le nuove impostazioni.',
[`${P}.devices.title`]: 'Dispositivi mobili',
[`${P}.devices.refresh`]: 'Aggiorna',
[`${P}.devices.loading`]: 'Caricamento…',
[`${P}.devices.empty`]: 'Nessun dispositivo associato.',
[`${P}.devices.empty_hint`]: 'Usa la pagina Associa un dispositivo per aggiungerne uno.',
[`${P}.devices.col_device`]: 'Dispositivo',
[`${P}.devices.col_state`]: 'Stato',
[`${P}.devices.col_bound`]: 'Assegnato a',
[`${P}.devices.empty_hint`]: 'Usa "Associa nuovo dispositivo" qui sopra per aggiungerne uno.',
[`${P}.devices.col_last_seen`]: 'Ultimo accesso',
[`${P}.devices.col_actions`]: 'Azioni',
[`${P}.devices.state_authorized`]: 'autorizzato',
[`${P}.devices.state_pending`]: 'in attesa',
[`${P}.devices.assign_to`]: 'Assegna a…',
[`${P}.devices.bind`]: 'Associa',
[`${P}.devices.revoke`]: 'Revoca',
[`${P}.devices.revoke_confirm`]: 'Revocare questo dispositivo? Perderà laccesso immediatamente.',
[`${P}.devices.unknown`]: 'Dispositivo sconosciuto',
@@ -80,30 +140,60 @@ export default {
},
fr: {
[`${P}.pairing.title`]: 'Associer un appareil',
[`${P}.pairing.intro`]: 'Ouvrez une fenêtre dassociation, puis scannez le QR code avec lapp mobile Skald. Lappareil est lié à vous et fonctionne immédiatement — vous pouvez le réassigner à un autre utilisateur depuis la page Appareils mobiles.',
[`${P}.pairing.open`]: 'Ouvrir la fenêtre dassociation',
[`${P}.pairing.opening`]: 'Ouverture…',
[`${P}.pairing.qr_alt`]: 'QR dassociation',
[`${P}.pairing.expired`]: 'Fenêtre expirée',
[`${P}.pairing.scan_within`]: 'Scannez sous {n}s',
[`${P}.pairing.new_code`]: 'Nouveau code',
[`${P}.pairing.close`]: 'Fermer',
[`${P}.app.title`]: 'Mobile App',
[`${P}.app.pair_new`]: 'Associer un appareil',
[`${P}.status.loading`]: 'Vérification…',
[`${P}.status.connected`]: 'Connecté',
[`${P}.status.connecting`]: 'Connexion…',
[`${P}.status.off`]: 'Inactif',
[`${P}.status.connecting_hint`]: 'Le connecteur est injoignable pour le moment — reconnexion automatique en cours. Lassociation est indisponible jusquau retour de la connexion.',
[`${P}.status.last_error`]: 'Dernière erreur',
[`${P}.status.off_hint`]: 'Le connecteur mobile est inactif. Demandez à un administrateur de le configurer.',
[`${P}.status.off_hint_admin`]: 'Le connecteur mobile est inactif — ouvrez les réglages (icône engrenage) et choisissez un serveur relais pour le démarrer.',
[`${P}.pair.title`]: 'Associer un appareil',
[`${P}.pair.intro`]: 'Scannez le QR code avec lapp mobile Skald. Lappareil est lié à votre compte et fonctionne immédiatement.',
[`${P}.pair.opening`]: 'Ouverture…',
[`${P}.pair.qr_alt`]: 'QR dassociation',
[`${P}.pair.expired`]: 'Code expiré',
[`${P}.pair.scan_within`]: 'Scannez sous {n}s',
[`${P}.pair.new_code`]: 'Nouveau code',
[`${P}.pair.retry`]: 'Réessayer',
[`${P}.pair.cancel`]: 'Annuler',
[`${P}.pair.close`]: 'Terminé',
[`${P}.pair.done`]: 'Appareil associé !',
[`${P}.pair.done_hint`]: 'Lappareil a été lié à votre compte et apparaît dans la liste.',
[`${P}.cfg.title`]: 'Réglages du connecteur mobile',
[`${P}.cfg.open`]: 'Réglages',
[`${P}.cfg.not_found`]: 'Plugin introuvable.',
[`${P}.cfg.relay`]: 'Serveur relais',
[`${P}.cfg.relay_official`]: 'SkaldCircle — Serveur relais officiel',
[`${P}.cfg.relay_test`]: 'SkaldCircle — Serveur de test',
[`${P}.cfg.relay_custom`]: 'Personnalisé — saisir lURL manuellement',
[`${P}.cfg.coming_soon`]: 'bientôt disponible',
[`${P}.cfg.bad_url`]: 'Saisissez une URL ws:// ou wss:// valide.',
[`${P}.cfg.pairing_ttl`]: 'Durée de vie du code dassociation (secondes)',
[`${P}.cfg.pairing_ttl_desc`]: 'Durée de validité dun QR dassociation. Max 600.',
[`${P}.cfg.require_confirmation`]: 'Exiger une confirmation de lappareil',
[`${P}.cfg.require_confirmation_desc`]:'Un appareil associé hors dune fenêtre web reste en attente jusqu’à son assignation par un admin (recommandé).',
[`${P}.cfg.notify_delay`]: 'Délai de notification (secondes)',
[`${P}.cfg.notify_delay_desc`]: 'Attendre ce délai avant de pousser une approbation/question sur le téléphone. Si vous répondez sur lordinateur dans ce délai, aucune notification nest envoyée. 0 = envoi immédiat.',
[`${P}.cfg.cancel`]: 'Annuler',
[`${P}.cfg.save`]: 'Enregistrer',
[`${P}.cfg.saving`]: 'Enregistrement…',
[`${P}.cfg.saved`]: 'Enregistré — le connecteur redémarre avec les nouveaux réglages.',
[`${P}.devices.title`]: 'Appareils mobiles',
[`${P}.devices.refresh`]: 'Actualiser',
[`${P}.devices.loading`]: 'Chargement…',
[`${P}.devices.empty`]: 'Aucun appareil associé.',
[`${P}.devices.empty_hint`]: 'Utilisez la page Associer un appareil pour en ajouter un.',
[`${P}.devices.col_device`]: 'Appareil',
[`${P}.devices.col_state`]: 'État',
[`${P}.devices.col_bound`]: 'Assigné à',
[`${P}.devices.empty_hint`]: 'Utilisez « Associer un appareil » ci-dessus pour en ajouter un.',
[`${P}.devices.col_last_seen`]: 'Vu la dernière fois',
[`${P}.devices.col_actions`]: 'Actions',
[`${P}.devices.state_authorized`]: 'autorisé',
[`${P}.devices.state_pending`]: 'en attente',
[`${P}.devices.assign_to`]: 'Assigner à…',
[`${P}.devices.bind`]: 'Associer',
[`${P}.devices.revoke`]: 'Révoquer',
[`${P}.devices.revoke_confirm`]: 'Révoquer cet appareil ? Il perd laccès immédiatement.',
[`${P}.devices.unknown`]: 'Appareil inconnu',