diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/playlist-menu.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/playlist-menu.js | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/playlist-menu.js b/packages/meshbay-hub/src/meshbay_hub/static/playlist-menu.js index 8d85b68..e2fb3f9 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/playlist-menu.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/playlist-menu.js @@ -183,7 +183,25 @@ function PlaylistMenuButton({ userId, lists, reload, onPlayQueue, onSync, cached onSelect: async () => { const r = await onSync(); await reload(); - say(r && r.ok ? t('playlists.synced') : t('playlists.sync_failed')); + // The reason, not just "it failed": a sync that quietly does nothing + // is the one failure mode nobody can act on, and the reason is what + // separates an offline node from a wedged one. + // On success, say how much moved; on failure, say why. Either way + // the reader learns something they can act on — the one thing this + // never did. + const last = P.lastSync(); + const why = (r && r.reason) || last.reason || '?'; + // `no_key` is not a fault the reader can do anything about unless it + // is spelled out. This browser signed in with its remembered device + // key, so the only bundle key it has is one persisted before the + // playlist subkey existed — and an AES handle is non-extractable, so + // there is nothing to derive it from. One sign-in with the passphrase + // fixes it for good; a code on screen does not say that. + say(r && r.ok + ? `${t('playlists.synced')} (${r.pushed || 0}↑ ${r.pulled || 0}↓)` + : (why === 'no_key' + ? t('playlists.err_no_key') + : `${t('playlists.sync_failed')}: ${why}`)); }, }, ]); |