diff --git a/internal/server/web/templates/files.html b/internal/server/web/templates/files.html index fd2c5b0..72b8d6f 100644 --- a/internal/server/web/templates/files.html +++ b/internal/server/web/templates/files.html @@ -13,6 +13,8 @@ display:inline-flex; align-items:center; justify-content:center; vertical-align:middle; height:34px; line-height:1; margin:0; box-sizing:border-box; } + /* A button with an icon before its text. */ + .fm-bar .btn.ico { gap:6px; } input.fm-path { font-family:ui-monospace,Menlo,monospace; font-size:13px; color:var(--muted); background:#0c0f13; border:1px solid var(--border); border-radius:8px; padding:8px 12px; flex:1; min-width:200px; height:34px; box-sizing:border-box; } @@ -27,14 +29,16 @@ @keyframes spin { to { transform:rotate(360deg); } } /* Busy indicator; while files upload it also shows how far they got, and a click on it lists them. It takes room only while it shows. */ - #uppct:empty { display:none; } + #uppct { display:inline-block; max-width:0; margin-left:0; overflow:hidden; white-space:nowrap; + transition:max-width .3s ease, margin-left .3s ease; } + #uppct.on { max-width:110px; margin-left:8px; } .busy { flex:none; display:none; align-items:center; gap:8px; background:none; border:0; padding:0 2px; height:34px; color:var(--muted); font-size:13px; font-variant-numeric:tabular-nums; cursor:default; } /* Folded to nothing when idle (the negative margin takes back the bar's gap), it opens smoothly, and only for work that lasts a moment. */ - .fm-bar .busy { display:inline-flex; box-sizing:border-box; max-width:0; padding:0; margin-left:-8px; opacity:0; + .fm-bar .busy { display:inline-flex; gap:0; box-sizing:border-box; max-width:0; padding:0; margin-left:-8px; opacity:0; overflow:hidden; white-space:nowrap; transition:max-width .3s ease, margin-left .3s ease, opacity .25s ease; } - .fm-bar .busy.on { max-width:120px; margin-left:0; opacity:1; transition-delay:.15s; } + .fm-bar .busy.on { max-width:140px; margin-left:0; opacity:1; transition-delay:.15s; } .busy:hover { background:none; } .busy.up { cursor:pointer; color:var(--text); } .busy.up:hover { color:var(--accent); } @@ -75,6 +79,9 @@ dialog { background:var(--panel); color:var(--text); border:1px solid var(--border); border-radius:12px; padding:0; max-width:900px; width:92vw; } dialog::backdrop { background:rgba(0,0,0,.6); } + /* A dialog takes the focus itself when it opens, rather than its first + button, which would light up as if tabbed to. */ + dialog:focus { outline:none; } .dlg-h { padding:14px 18px; border-bottom:1px solid var(--border); display:flex; align-items:center; gap:10px; } .dlg-b { padding:16px 18px; } #save { display:inline-flex; align-items:center; gap:8px; } @@ -107,7 +114,9 @@ /* File viewer: the code editor, a picture / video / sound, or the hex editor. */ #viewer { max-width:1100px; } #viewer .dlg-h { flex-wrap:wrap; } - .vpath { flex:1; min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; + /* Right to left so a long path is cut at its start, keeping the name in + sight; still set to the left like any title. */ + .vpath { flex:1; min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; text-align:left; font-family:ui-monospace,Menlo,monospace; font-size:13px; font-weight:600; } .vmsg { width:100%; order:9; font-size:12px; } .vbody { padding:0; } @@ -225,7 +234,7 @@
- +
@@ -234,9 +243,9 @@
- - - + + + @@ -256,7 +265,7 @@

Перетащите файлы сюда для загрузки. Клик по файлу - просмотр и правка.

- +
@@ -295,7 +304,7 @@
- +
Загрузка файлов @@ -303,7 +312,7 @@
- +
Свойства @@ -369,6 +378,8 @@ // An open dialog sits in the page's top layer, above any z-index: the toast // goes inside it then, so "сохранено" or an error shows over the editor. let toastTimer = null; + // Opens a dialog with the focus on the dialog itself, not its first button. + const openModal = d => { d.showModal(); d.focus(); }; const toast = (msg, err) => { const t = $('toast'), host = [...document.querySelectorAll('dialog[open]')].pop() || document.body; if (t.parentNode !== host) host.appendChild(t); @@ -607,7 +618,7 @@ V.path = path; V.dirty = false; $('vname').textContent = path; $('vname').parentElement.title = path; - if (!$('viewer').open) $('viewer').showModal(); + if (!$('viewer').open) openModal($('viewer')); } async function view(e) { @@ -1036,7 +1047,7 @@ showMode(d.mode); $('pp-rec').hidden = !d.is_dir; $('pp-recursive').checked = false; $('pp-only').value = ''; $('pp-only').disabled = true; - if (!$('propdlg').open) $('propdlg').showModal(); + if (!$('propdlg').open) openModal($('propdlg')); } $('pp-apply').onclick = async () => { const o = P.orig, mode = readMode(); @@ -1137,7 +1148,10 @@ const busy = $('busy'); busy.classList.toggle('up', uploads.length > 0); busy.title = uploads.length ? 'Показать загружаемые файлы' : ''; - $('uppct').textContent = pend.length ? Math.floor(100 * sent / total) + '%' + (counted.length > 1 ? ' · ' + (counted.length - pend.length) + '/' + counted.length : '') : ''; + // The figures slide in while files go and slide out after, keeping the + // last text as they go. + if (pend.length) $('uppct').textContent = Math.floor(100 * sent / total) + '%' + (counted.length > 1 ? ' · ' + (counted.length - pend.length) + '/' + counted.length : ''); + $('uppct').classList.toggle('on', pend.length > 0); const list = $('updlg-list'); if (!$('updlg').open) return; list.innerHTML = uploads.length ? '' : '

Сейчас ничего не загружается.

'; @@ -1156,7 +1170,7 @@ list.appendChild(el); } } - $('busy').onclick = () => { if (!uploads.length) return; $('updlg').showModal(); renderUploads(); }; + $('busy').onclick = () => { if (!uploads.length) return; openModal($('updlg')); renderUploads(); }; $('updlg-close').onclick = () => $('updlg').close(); // The pieces go on to the client as they come, so the bar follows the diff --git a/internal/server/web/templates/settings.html b/internal/server/web/templates/settings.html index ce63e14..66d9363 100644 --- a/internal/server/web/templates/settings.html +++ b/internal/server/web/templates/settings.html @@ -5,6 +5,14 @@ Настройки - LPRA +
@@ -27,14 +35,14 @@ поставит сервис и зарегистрирует машину.

-
{{.InstallShort}}
+
{{.InstallShort}}
Полные варианты (секрет в команде) -
{{.InstallCurl}}
+
{{.InstallCurl}}
-
{{.InstallWget}}
+
{{.InstallWget}}

Без переменных окружения скрипт спросит секрет интерактивно: curl -fsSL {{.Host}}/install.sh | sudo sh

@@ -176,5 +184,31 @@

LPRA сервер · версия {{.ServerVersion}}

+