mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-13 22:03:13 -06:00
feat(dashboard): surface per-device settings PIN + backfill existing fleet (#152)
The server provisions a unique settings-menu PIN per device, but nothing surfaced it — leaving the on-device hidden settings menu effectively unopenable. Show the PIN on the device Info tab (native players only), with i18n across 6 locales. Also backfill a unique 6-digit PIN for already-paired devices that predate the settings_pin column, so the existing fleet isn't locked out (delivered on their next reconnect via the existing device:paired re-send). Idempotent UPDATE. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d474122334
commit
b72e964433
|
|
@ -254,6 +254,8 @@ export default {
|
|||
'device.info.uptime': 'Betriebszeit',
|
||||
'device.info.android_version': 'Android-Version',
|
||||
'device.info.app_version': 'App-Version',
|
||||
'device.info.settings_pin': 'Einstellungs-PIN',
|
||||
'device.info.settings_pin_hint': 'Geräte-Einstellungsmenü (2× Zurück)',
|
||||
'device.info.screen_resolution': 'Bildschirmauflösung',
|
||||
'device.info.ram': 'RAM',
|
||||
'device.info.cpu_usage': 'CPU-Auslastung',
|
||||
|
|
|
|||
|
|
@ -296,6 +296,8 @@ export default {
|
|||
'device.info.uptime': 'Uptime',
|
||||
'device.info.android_version': 'Android Version',
|
||||
'device.info.app_version': 'App Version',
|
||||
'device.info.settings_pin': 'Settings PIN',
|
||||
'device.info.settings_pin_hint': 'On-device settings menu (2× Back)',
|
||||
'device.info.screen_resolution': 'Screen Resolution',
|
||||
'device.info.ram': 'RAM',
|
||||
'device.info.cpu_usage': 'CPU Usage',
|
||||
|
|
|
|||
|
|
@ -253,6 +253,8 @@ export default {
|
|||
'device.info.uptime': 'Tiempo activo',
|
||||
'device.info.android_version': 'Versión de Android',
|
||||
'device.info.app_version': 'Versión de la app',
|
||||
'device.info.settings_pin': 'PIN de ajustes',
|
||||
'device.info.settings_pin_hint': 'Menú de ajustes del dispositivo (2× Atrás)',
|
||||
'device.info.screen_resolution': 'Resolución de pantalla',
|
||||
'device.info.ram': 'RAM',
|
||||
'device.info.cpu_usage': 'Uso de CPU',
|
||||
|
|
|
|||
|
|
@ -254,6 +254,8 @@ export default {
|
|||
'device.info.uptime': 'Disponibilité',
|
||||
'device.info.android_version': 'Version d\'Android',
|
||||
'device.info.app_version': 'Version de l\'app',
|
||||
'device.info.settings_pin': 'Code PIN des réglages',
|
||||
'device.info.settings_pin_hint': 'Menu des réglages sur l\'appareil (2× Retour)',
|
||||
'device.info.screen_resolution': 'Résolution',
|
||||
'device.info.ram': 'RAM',
|
||||
'device.info.cpu_usage': 'Utilisation CPU',
|
||||
|
|
|
|||
|
|
@ -270,6 +270,8 @@ export default {
|
|||
'device.info.uptime': 'Tempo di attività',
|
||||
'device.info.android_version': 'Versione Android',
|
||||
'device.info.app_version': 'Versione App',
|
||||
'device.info.settings_pin': 'PIN impostazioni',
|
||||
'device.info.settings_pin_hint': 'Menu impostazioni sul dispositivo (2× Indietro)',
|
||||
'device.info.screen_resolution': 'Risoluzione Schermo',
|
||||
'device.info.ram': 'RAM',
|
||||
'device.info.cpu_usage': 'Utilizzo CPU',
|
||||
|
|
|
|||
|
|
@ -254,6 +254,8 @@ export default {
|
|||
'device.info.uptime': 'Tempo ativo',
|
||||
'device.info.android_version': 'Versão do Android',
|
||||
'device.info.app_version': 'Versão do app',
|
||||
'device.info.settings_pin': 'PIN de configurações',
|
||||
'device.info.settings_pin_hint': 'Menu de configurações no dispositivo (2× Voltar)',
|
||||
'device.info.screen_resolution': 'Resolução',
|
||||
'device.info.ram': 'RAM',
|
||||
'device.info.cpu_usage': 'Uso de CPU',
|
||||
|
|
|
|||
|
|
@ -305,6 +305,11 @@ async function loadDevice(deviceId, activeTab = null) {
|
|||
<div class="info-card-label">${t('device.info.app_version')}</div>
|
||||
<div class="info-card-value small">${device.app_version || '--'}</div>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<div class="info-card-label">${t('device.info.settings_pin')}</div>
|
||||
<div class="info-card-value small" style="font-family:monospace;letter-spacing:1px">${device.settings_pin || '--'}</div>
|
||||
<div style="font-size:11px;color:var(--text-muted);margin-top:2px">${t('device.info.settings_pin_hint')}</div>
|
||||
</div>
|
||||
` : ''}
|
||||
<div class="info-card">
|
||||
<div class="info-card-label">${t('device.info.screen_resolution')}</div>
|
||||
|
|
|
|||
|
|
@ -267,6 +267,12 @@ const migrations = [
|
|||
// settings_pin: 6-digit PIN for the in-app hidden settings menu, provisioned by
|
||||
// the server during pairing so each device gets a unique PIN (never a hardcoded default).
|
||||
"ALTER TABLE devices ADD COLUMN settings_pin TEXT",
|
||||
// Backfill a unique 6-digit PIN for already-paired devices that predate the
|
||||
// settings_pin column (their next reconnect re-sends device:paired with it, so
|
||||
// the existing fleet isn't locked out of the on-device menu). Idempotent: the
|
||||
// IS NULL guard means it only ever touches un-provisioned rows. Unpaired rows
|
||||
// (user_id IS NULL) are skipped — they get a PIN when they pair.
|
||||
"UPDATE devices SET settings_pin = CAST(abs(random()) % 900000 + 100000 AS TEXT) WHERE settings_pin IS NULL AND user_id IS NOT NULL",
|
||||
// #150: fingerprint-keyed device settings that SURVIVE device-row deletion, so a
|
||||
// delete + re-pair (MDM churn) restores orientation/name/playlist/etc for the SAME
|
||||
// physical device instead of silently resetting to defaults. NO FK to devices -> it
|
||||
|
|
|
|||
Loading…
Reference in a new issue