Changes
4 changed files (+185/-7)
-
-
@@ -69,6 +69,138 @@ function setupThemeColor() {} } function setupTreeLayout() { const LOCAL_STORAGE_KEY = "legit_tree_layout"; const VALID_LAYOUTS = ["compact"]; function applyTreeLayout(layout) { if (layout) { localStorage.setItem(LOCAL_STORAGE_KEY, layout); } else { localStorage.removeItem(LOCAL_STORAGE_KEY); } for (const tree of document.getElementsByClassName("tree-row")) { tree.dataset.layout = layout; } } const saved = localStorage.getItem(LOCAL_STORAGE_KEY) || ""; applyTreeLayout(saved); const selector = document.getElementById("tree-layout"); if (selector) { selector.value = saved; selector.addEventListener("change", event => { const value = event.currentTarget.value; if (value && !VALID_LAYOUTS.includes(value)) { return; } applyTreeLayout(value); }); } } function setupFileModeFormat() { const LOCAL_STORAGE_KEY = "legit_file_mode_format"; const VALID_FORMATS = ["octal", "hidden"]; const FILE_MODE_PATTERN = /^[d-]([r-][w-][x-]){3}$/; function applyFileMode(format) { if (format) { localStorage.setItem(LOCAL_STORAGE_KEY, format); } else { localStorage.removeItem(LOCAL_STORAGE_KEY); } for (const el of document.querySelectorAll("[data-file-mode]")) { const mode = el.dataset.fileMode; if (!FILE_MODE_PATTERN.test(mode || "")) { continue; } el.dataset.format = format; switch (format) { case "octal": { const n = 0 + (mode[1] === "r" ? 0o400 : 0) + (mode[2] === "w" ? 0o200 : 0) + (mode[3] === "x" ? 0o100 : 0) + (mode[4] === "r" ? 0o40 : 0) + (mode[5] === "w" ? 0o20 : 0) + (mode[6] === "x" ? 0o10 : 0) + (mode[7] === "r" ? 0o4 : 0) + (mode[8] === "w" ? 0o2 : 0) + (mode[9] === "x" ? 0o1 : 0); el.textContent = n.toString(8).padStart(3, "0"); break; } default: el.textContent = mode; break; } } } const saved = localStorage.getItem(LOCAL_STORAGE_KEY) || ""; applyFileMode(saved); const selector = document.getElementById("file-mode-format"); if (selector) { selector.value = saved; selector.addEventListener("change", event => { const value = event.currentTarget.value; if (value && !VALID_FORMATS.includes(value)) { return; } applyFileMode(value); }); } } function setupFileSizeFormat() { const LOCAL_STORAGE_KEY = "legit_file_size_format"; const VALID_FORMATS = ["hidden"]; function applyFileSize(format) { if (format) { localStorage.setItem(LOCAL_STORAGE_KEY, format); } else { localStorage.removeItem(LOCAL_STORAGE_KEY); } for (const el of document.querySelectorAll("[data-file-size]")) { const size = parseInt(el.dataset.fileSize, 10); if (!Number.isFinite(size)) { continue; } el.dataset.format = format; } } const saved = localStorage.getItem(LOCAL_STORAGE_KEY) || ""; applyFileSize(saved); const selector = document.getElementById("file-size-format"); if (selector) { selector.value = saved; selector.addEventListener("change", event => { const value = event.currentTarget.value; if (value && !VALID_FORMATS.includes(value)) { return; } applyFileSize(value); }); } } function setupPreferencesDialog() { const preferences = document.getElementById("preferences-dialog"); document.getElementById("preferences-dialog-trigger")?.addEventListener("click", (event) => {
-
@@ -81,4 +213,7 @@ function setupPreferencesDialog() {setupTabWidthSelector(); setupThemeColor(); setupTreeLayout(); setupFileModeFormat(); setupFileSizeFormat(); setupPreferencesDialog();
-
-
-
@@ -12,7 +12,7 @@.tree-row { display: grid; grid-template-columns: max-content minmax(0, 1fr) max-content max-content; grid-template-columns: max-content minmax(0, 1fr) repeat(2, max-content); grid-template-areas: "icon name name name" ". . mode size";
-
@@ -21,6 +21,10 @@padding: var(--space-sm) 0; border-block-end: 1px solid var(--color-border-subtle); } .tree-row[data-layout="compact"] { grid-template-columns: repeat(2, max-content) minmax(0, 1fr) max-content; grid-template-areas: "mode icon name size"; } @media (any-hover: hover) { .tree-row:hover {
-
@@ -50,16 +54,21 @@line-height: 1.3; color: var(--color-fg); overflow: hidden; text-overflow: ellipsis; } .tree-row--mode { grid-area: mode; font-size: var(--font-sm); font-size: var(--font-xs); line-height: 1.1; font-family: var(--font-ui); font-family: var(--font-mono); color: var(--color-fg-subtle); } .tree-row--mode[data-format="hidden"] { display: none; } .tree-row--size { grid-area: size;
-
@@ -68,3 +77,6 @@color: var(--color-fg-weak); } .tree-row--size[data-format="hidden"] { display: none; }
-
-
-
@@ -66,8 +66,8 @@ SPDX-License-Identifier: MIT<use href="#icon_dir" /> </svg> <span class="tree-row--name">{{ .Name }}/</span> <span class="tree-row--mode">{{ .Mode }}</span> <span class="tree-row--size">{{ .Size }} bytes</span> <span class="tree-row--mode" data-file-mode="{{ .Mode }}">{{ .Mode }}</span> <span class="tree-row--size" data-file-size="{{ .Size }}">{{ .Size }} bytes</span> </a> {{- else -}} <a class="tree-row" href="/{{ $meta.DirName }}/blob/{{ $meta.Ref }}/{{ $prefix }}{{ .Name }}">
-
@@ -75,8 +75,8 @@ SPDX-License-Identifier: MIT<use href="#icon_file" /> </svg> <span class="tree-row--name">{{ .Name }}</span> <span class="tree-row--mode">{{ .Mode }}</span> <span class="tree-row--size">{{ .Size }} bytes</span> <span class="tree-row--mode" data-file-mode="{{ .Mode }}">{{ .Mode }}</span> <span class="tree-row--size" data-file-size="{{ .Size }}">{{ .Size }} bytes</span> </a> {{- end }} </li>
-
-
-
@@ -47,6 +47,37 @@ SPDX-License-Identifier: MITChanges the primary color to use for links, buttons, and icons. </p> </div> <div class="preferences--field"> <label for="tree-layout">File list layout</label> <select id="tree-layout" aria-describedby="tree-layout-description"> <option value="">Default</option> <option value="compact">Compact</option> </select> <p id="tree-layout-description"> Row layout of a file list in "Files" page. </p> </div> <div class="preferences--field"> <label for="file-mode-format">File permission format</label> <select id="file-mode-format" aria-describedby="file-mode-format-description"> <option value="">Default (drwx)</option> <option value="octal">Octal</option> <option value="hidden">Hidden</option> </select> <p id="file-mode-format-description"> How to render file permission? </p> </div> <div class="preferences--field"> <label for="file-size-format">File size format</label> <select id="file-size-format" aria-describedby="file-size-format-description"> <option value="">Default</option> <option value="hidden">Hidden</option> </select> <p id="file-size-format-description"> Change display of file size in "Files" page. </p> </div> <button id="preferences-dialog-closer">Close</button> </dialog> {{- if .Config.UI.Footer.PoweredBy }}
-