fix: the editor shows an empty page, not the last file, while a file loads; text in UTF-16 and with BOM; + menu groups open and shut smoothly; the assistant's errors in plain words
This commit is contained in:
1 parent
b272aed8fd
commit
352b016384
5 files changed
+178
-70
No files matched your search
@@ -474,23 +474,23 @@
|
||||
return b;
|
||||
};
|
||||
const FILES = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7a2 2 0 0 1 2-2h4l2 2.5h8a2 2 0 0 1 2 2V17a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>';
|
||||
// A group: «Терминал ›» or «Файловый менеджер ›», opening to here, the
|
||||
// other machines and an SSH host.
|
||||
const group = (icon, label, kind, sshKind, mode) => {
|
||||
const g = item(addMenu, '<span class="ico">' + icon + '</span><span><b>' + label + '</b></span><span class="chev">›</span>', () => {
|
||||
if (g.nextSibling && g.nextSibling.classList && g.nextSibling.classList.contains('mlist')) { g.nextSibling.remove(); placeMenu(anchor); return; }
|
||||
addMenu.querySelectorAll('.mlist').forEach(x => x.remove());
|
||||
const list = document.createElement('div');
|
||||
list.className = 'mlist';
|
||||
g.after(list);
|
||||
if (here) item(list, '<span class="ico">+</span><span><b>Здесь</b><small>' + esc(here.name) + ' · ' + esc(here.user + '@' + here.host) + '</small></span>',
|
||||
() => { closeMenu(); openPane(kind, here); });
|
||||
const box = document.createElement('div');
|
||||
box.innerHTML = '<div class="muted" style="padding:8px 10px;font-size:13px">загрузка…</div>';
|
||||
list.appendChild(box);
|
||||
item(list, '<span class="ico">' + KEYI + '</span><span><b>SSH-хост…</b><small>машина откроет SSH к другому хосту</small></span>',
|
||||
() => { closeMenu(); openSSH(here, mode); });
|
||||
// Both groups keep their contents mounted so they can animate in both directions.
|
||||
const group = (icon, label, kind, mode) => {
|
||||
let loaded = false;
|
||||
const g = item(addMenu, '<span class="ico">' + icon + '</span><span><b>' + label + '</b></span><span class="chev" aria-hidden="true">›</span>', () => {
|
||||
const opening = g.getAttribute('aria-expanded') !== 'true';
|
||||
addMenu.querySelectorAll('.item[aria-expanded="true"]').forEach(b => {
|
||||
b.setAttribute('aria-expanded', 'false');
|
||||
b.nextSibling.classList.remove('open');
|
||||
b.nextSibling.inert = true;
|
||||
});
|
||||
if (!opening) { placeMenu(anchor); return; }
|
||||
g.setAttribute('aria-expanded', 'true');
|
||||
list.classList.add('open');
|
||||
list.inert = false;
|
||||
placeMenu(anchor);
|
||||
if (loaded) return;
|
||||
loaded = true;
|
||||
(agentsCache ? Promise.resolve(agentsCache) : fetch('/api/panel/agents/presence', { cache: 'no-store' }).then(r => r.json()))
|
||||
.then(all => {
|
||||
agentsCache = all;
|
||||
@@ -501,15 +501,33 @@
|
||||
() => { closeMenu(); openPane(kind, { id: a.id, name: a.name, host: a.hostname, user: a.user }); }, 'machine');
|
||||
b.disabled = !a.online;
|
||||
});
|
||||
placeMenu(anchor);
|
||||
if (list.isConnected) placeMenu(anchor);
|
||||
})
|
||||
.catch(() => { box.innerHTML = '<div class="muted" style="padding:8px 10px">не загрузилось</div>'; });
|
||||
});
|
||||
g.setAttribute('aria-expanded', 'false');
|
||||
const list = document.createElement('div');
|
||||
list.className = 'mlist';
|
||||
list.inert = true;
|
||||
const inner = document.createElement('div');
|
||||
inner.className = 'mlist-inner';
|
||||
const content = document.createElement('div');
|
||||
content.className = 'mlist-content';
|
||||
inner.appendChild(content);
|
||||
list.appendChild(inner);
|
||||
g.after(list);
|
||||
if (here) item(content, '<span class="ico">+</span><span><b>Здесь</b><small>' + esc(here.name) + ' · ' + esc(here.user + '@' + here.host) + '</small></span>',
|
||||
() => { closeMenu(); openPane(kind, here); });
|
||||
const box = document.createElement('div');
|
||||
box.innerHTML = '<div class="muted" style="padding:8px 10px;font-size:13px">загрузка…</div>';
|
||||
content.appendChild(box);
|
||||
item(content, '<span class="ico">' + KEYI + '</span><span><b>SSH-хост…</b><small>машина откроет SSH к другому хосту</small></span>',
|
||||
() => { closeMenu(); openSSH(here, mode); });
|
||||
if (!paneTypes[kind]) g.disabled = true;
|
||||
return g;
|
||||
};
|
||||
group('>_', 'Терминал', 'term', 'ssh', 'term');
|
||||
group(FILES, 'Файловый менеджер', 'files', 'sshfiles', 'files');
|
||||
group('>_', 'Терминал', 'term', 'term');
|
||||
group(FILES, 'Файловый менеджер', 'files', 'files');
|
||||
addMenu.hidden = false;
|
||||
placeMenu(anchor);
|
||||
setTimeout(() => document.addEventListener('pointerdown', outside, true), 0);
|
||||
|
||||
Reference in new issue
Block a user