feat(ui): limit visible reactions and overhaul retro theme

- Limit the number of initially visible reactions per file to 2 and calculate the overflow count on the backend.
- Redesign the retro theme CSS to mimic a classic Windows 98 Explorer window, including title bars, toolbars, and sunken panes.
- Add local storage persistence for the file browser view preference (list vs. thumbnails).
This commit is contained in:
2026-06-02 14:43:16 +03:00
parent 8e3f783780
commit cf5d8bb50d
7 changed files with 740 additions and 110 deletions

View File

@@ -1,30 +1,25 @@
(function () {
const fileBrowser = document.querySelector("[data-file-browser]");
const viewButtons = document.querySelectorAll("[data-view-button]");
const previewImages = document.querySelector("[data-preview-images]");
const previewActions = document.querySelectorAll("[data-preview-action]");
const fileContextMenu = document.querySelector("[data-file-context-menu]");
const fileBrowserWindow = document.querySelector("[data-file-browser-window]");
let ctrlCopyMode = false;
let contextFile = null;
const contextMenuCloseDistance = 80;
const viewStorageKey = "warpbox.fileBrowser.view";
if (fileBrowser) {
applySavedFileBrowserPreferences();
viewButtons.forEach((button) => {
button.addEventListener("click", () => {
const view = button.getAttribute("data-view-button");
fileBrowser.classList.toggle("is-list", view === "list");
fileBrowser.classList.toggle("is-thumbs", view === "thumbs");
viewButtons.forEach((item) => item.classList.toggle("is-active", item === button));
setFileBrowserView(view);
savePreference(viewStorageKey, view);
});
});
if (previewImages) {
previewImages.addEventListener("click", () => {
fileBrowser.classList.toggle("images-only");
previewImages.classList.toggle("is-active");
});
}
}
if (fileBrowser && fileContextMenu) {
@@ -188,4 +183,40 @@
y >= rect.top - contextMenuCloseDistance &&
y <= rect.bottom + contextMenuCloseDistance;
}
function applySavedFileBrowserPreferences() {
const savedView = readPreference(viewStorageKey);
setFileBrowserView(savedView === "list" ? "list" : "thumbs");
}
function setFileBrowserView(view) {
const normalized = view === "thumbs" ? "thumbs" : "list";
fileBrowser.classList.toggle("is-list", normalized === "list");
fileBrowser.classList.toggle("is-thumbs", normalized === "thumbs");
if (fileBrowserWindow) {
fileBrowserWindow.classList.toggle("is-list-view", normalized === "list");
fileBrowserWindow.classList.toggle("is-icon-view", normalized === "thumbs");
}
viewButtons.forEach((item) => {
const active = item.getAttribute("data-view-button") === normalized;
item.classList.toggle("is-active", active);
item.setAttribute("aria-pressed", active ? "true" : "false");
});
}
function readPreference(key) {
try {
return window.localStorage.getItem(key);
} catch (_) {
return "";
}
}
function savePreference(key, value) {
try {
window.localStorage.setItem(key, value);
} catch (_) {
// LocalStorage can be unavailable in private or locked-down browsers.
}
}
})();