Pithos: renames and vault unlocks reach every open view
A renamed user kept its old name in the full page and in the other open views until they were reloaded, and the pithos.sia address still named the old user. The server now tells every view, and each one updates its selection, its address and the page on screen. When the vault locked while pithos.sia was open, the page fell through to the console password sign-in, which a Theseus user has no use for. It now shows the vault's PIN unlock, and it opens again on its own once the vault is unlocked anywhere, the sidebar's PIN pad included. The sidebar likewise opens again when the vault is unlocked elsewhere.
This commit is contained in:
parent
24e90e16ce
commit
527bfee4d4
2 changed files with 67 additions and 4 deletions
|
|
@ -320,6 +320,9 @@ export async function createPithos(opts = {}) {
|
|||
if (wasRunning) { try { daemon.start(); } catch (e) { daemon.pushLog('sys', `could not start s3d: ${e.message}`); } }
|
||||
}
|
||||
daemon.pushLog('sys', `renamed user ${p.name} to ${name}`);
|
||||
// every open view (sidebar, full page, browser) follows the new name
|
||||
siteUsersCache = { at: 0, set: new Set() };
|
||||
broadcast('user-renamed', { from: p.name, to: name });
|
||||
return { name };
|
||||
});
|
||||
route('GET', '/api/keys', (req, url) => cli.listKeys(url.searchParams.get('user') || undefined));
|
||||
|
|
|
|||
68
ui/app.js
68
ui/app.js
|
|
@ -175,6 +175,7 @@ const eventHandlers = {
|
|||
if (['done', 'already'].includes(d?.state) && d.state !== was) refreshNavAccount(true);
|
||||
},
|
||||
install(p) { if (p.phase === 'extract') toast('Verified checksum, installing…'); },
|
||||
'user-renamed'(d) { followRename(d); },
|
||||
move(p) { progressSink?.(p); },
|
||||
convert(p) { progressSink?.(p); },
|
||||
};
|
||||
|
|
@ -274,6 +275,29 @@ function navTo(hash) {
|
|||
route();
|
||||
}
|
||||
|
||||
// A user renamed here or in another Pithos view (sidebar, full page,
|
||||
// browser): the selection, the address and the page on screen follow.
|
||||
function followRename({ from, to } = {}) {
|
||||
if (!from || !to || from === to) return;
|
||||
if (state.selectedUser === from) { state.selectedUser = to; try { localStorage.setItem('pithos.user', to); } catch {} }
|
||||
const swap = (parts, i) => {
|
||||
let cur = '';
|
||||
try { cur = decodeURIComponent(parts[i] || ''); } catch {}
|
||||
if (cur !== from) return false;
|
||||
parts[i] = encodeURIComponent(to);
|
||||
return true;
|
||||
};
|
||||
if (PATH_MODE) {
|
||||
const segs = location.pathname.split('/');
|
||||
if (swap(segs, 1)) history.replaceState(null, '', segs.join('/') + location.search);
|
||||
} else if (location.hash.startsWith('#/u/')) {
|
||||
const parts = location.hash.split('/');
|
||||
if (swap(parts, 2)) history.replaceState(null, '', parts.join('/'));
|
||||
}
|
||||
const [page] = currentRoute();
|
||||
if (page === 'users' || page === 'buckets') route();
|
||||
}
|
||||
|
||||
function route() {
|
||||
cleanup.forEach((fn) => fn());
|
||||
cleanup = [];
|
||||
|
|
@ -1101,10 +1125,8 @@ function users(main) {
|
|||
if (!name || name === current) return;
|
||||
try {
|
||||
await api('POST', `/api/users/${encodeURIComponent(current)}/rename`, { name });
|
||||
if (state.selectedUser === current) { state.selectedUser = name; try { localStorage.setItem('pithos.user', name); } catch {} }
|
||||
expanded.delete(current);
|
||||
toast(`Renamed to ${name}`);
|
||||
load();
|
||||
followRename({ from: current, to: name });
|
||||
} catch (e) { fail(e); load(); }
|
||||
}
|
||||
|
||||
|
|
@ -2735,6 +2757,10 @@ function watchVaultLock() {
|
|||
if (st.setup && st.prompt && !st.unlocked && $('#locked').hidden) {
|
||||
$('#app').hidden = true;
|
||||
$('#locked').hidden = false;
|
||||
} else if (st.unlocked && !$('#locked').hidden) {
|
||||
// unlocked somewhere else (the full page, Settings): open again
|
||||
$('#locked').hidden = true;
|
||||
$('#app').hidden = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -2902,14 +2928,48 @@ function addBackToSidebar() {
|
|||
}
|
||||
|
||||
function showSignin() {
|
||||
// pithos.sia in Theseus signs out when the vault locks (idle, Lock now):
|
||||
// that is the vault's PIN prompt, not the console password.
|
||||
if (PATH_MODE) {
|
||||
api('GET', '/api/session').then((s) => (s.locked ? showLocked() : showPassword())).catch(showPassword);
|
||||
return;
|
||||
}
|
||||
showPassword();
|
||||
}
|
||||
function showPassword() {
|
||||
$('#app').hidden = true;
|
||||
$('#locked').hidden = true;
|
||||
$('#signin').hidden = false;
|
||||
}
|
||||
|
||||
// Locked with the Theseus vault. Unlocking anywhere (this page's button, the
|
||||
// sidebar's PIN pad, Settings) reopens the page by itself.
|
||||
let lockWatch = null;
|
||||
function showLocked() {
|
||||
$('#app').hidden = true;
|
||||
$('#signin').hidden = true;
|
||||
$('#locked').hidden = false;
|
||||
if (lockWatch) return;
|
||||
const check = async () => {
|
||||
let s;
|
||||
try { s = await api('GET', '/api/session'); } catch { return; }
|
||||
if (s.locked || !s.authenticated) return;
|
||||
clearInterval(lockWatch);
|
||||
lockWatch = null;
|
||||
document.removeEventListener('visibilitychange', onShow);
|
||||
window.removeEventListener('focus', check);
|
||||
location.reload(); // a fresh start: the event stream ended with the lock
|
||||
};
|
||||
const onShow = () => { if (!document.hidden) check(); };
|
||||
lockWatch = setInterval(check, 2000);
|
||||
document.addEventListener('visibilitychange', onShow);
|
||||
window.addEventListener('focus', check);
|
||||
}
|
||||
|
||||
async function boot() {
|
||||
const s = await api('GET', '/api/session');
|
||||
// pithos.sia in Theseus: locked with the vault, like the sidebar panel.
|
||||
if (s.locked) { $('#locked').hidden = false; return; }
|
||||
if (s.locked) { showLocked(); return; }
|
||||
if (!s.authenticated) {
|
||||
showSignin();
|
||||
if (!s.passwordLogin) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue