Differences
This shows you the differences between two versions of the page.
| wip:internal:downloads [2025/11/20 21:59] – created ayush | wip:internal:downloads [2025/11/20 22:07] (current) – ayush | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | |||
| - | |||
| < | < | ||
| < | < | ||
| - | /* File listing fills available viewport space, scrolls beyond | + | |
| - | .plugin__filelisting_bodytable | + | |
| - | | + | @import url(' |
| - | | + | |
| - | | + | /* CSS Custom Properties |
| + | .plugin__filelisting | ||
| + | --fl-font-sans: ' | ||
| + | | ||
| + | | ||
| + | --fl-bg: #ffffff; | ||
| + | --fl-bg-hover: | ||
| + | --fl-bg-nested: | ||
| + | |||
| + | --fl-border: | ||
| + | --fl-border-light: | ||
| + | |||
| + | --fl-text: #212529; | ||
| + | --fl-text-secondary: | ||
| + | --fl-text-muted: | ||
| + | |||
| + | --fl-accent: | ||
| + | --fl-accent-light: | ||
| + | |||
| + | --fl-folder: | ||
| + | --fl-file-pdf: | ||
| + | --fl-file-video: | ||
| + | --fl-file-default: | ||
| + | |||
| + | --fl-radius: | ||
| + | --fl-radius-sm: | ||
| + | |||
| + | --fl-transition: | ||
| + | |||
| + | --fl-indent: 28px; | ||
| } | } | ||
| - | .plugin__filelisting_collapsible | + | /* Container */ |
| - | | + | .plugin__filelisting |
| - | | + | |
| - | | + | background: var(--fl-bg); |
| + | border: 1px solid var(--fl-border); | ||
| + | border-radius: | ||
| + | overflow: hidden; | ||
| + | font-size: 13px; | ||
| + | line-height: 1.5; | ||
| + | } | ||
| + | |||
| + | /* Header */ | ||
| + | .plugin__filelisting_capiton { | ||
| + | display: flex; | ||
| + | align-items: | ||
| + | justify-content: | ||
| + | padding: 12px 16px; | ||
| + | background: var(--fl-bg); | ||
| + | border-bottom: | ||
| + | font-weight: | ||
| + | font-size: 12px; | ||
| + | color: var(--fl-text-secondary); | ||
| + | text-transform: | ||
| + | letter-spacing: | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_capiton span { | ||
| + | font-family: | ||
| + | font-size: 11px; | ||
| + | font-weight: | ||
| + | color: var(--fl-text-muted); | ||
| + | background: var(--fl-bg-hover); | ||
| + | padding: 2px 8px; | ||
| + | border-radius: | ||
| + | margin-left: | ||
| + | text-transform: none; | ||
| + | | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_toggle { | ||
| + | | ||
| + | color: var(--fl-text-muted); | ||
| + | transition: transform var(--fl-transition); | ||
| + | float: none !important; | ||
| } | } | ||
| + | /* Content containers */ | ||
| + | .plugin__filelisting_collapsible, | ||
| .plugin__filelisting_content { | .plugin__filelisting_content { | ||
| max-height: none !important; | max-height: none !important; | ||
| - | height: auto !important; | ||
| overflow: visible !important; | overflow: visible !important; | ||
| } | } | ||
| - | .plugin__filelisting | + | /* Scrollable body */ |
| - | max-height: | + | .plugin__filelisting_bodytable |
| - | overflow: | + | max-height: |
| + | overflow-y: auto !important; | ||
| + | overflow-x: hidden; | ||
| + | } | ||
| + | |||
| + | /* Minimal scrollbar */ | ||
| + | .plugin__filelisting_bodytable:: | ||
| + | width: 4px; | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_bodytable:: | ||
| + | background: transparent; | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_bodytable:: | ||
| + | background: var(--fl-border); | ||
| + | border-radius: | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_bodytable:: | ||
| + | background: var(--fl-text-muted); | ||
| + | } | ||
| + | |||
| + | /* Tables */ | ||
| + | .plugin__filelisting table { | ||
| + | width: 100%; | ||
| + | border-collapse: | ||
| + | table-layout: | ||
| + | } | ||
| + | |||
| + | /* Header row */ | ||
| + | .plugin__filelisting_headertable { | ||
| + | border-bottom: | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_headertable thead tr { | ||
| + | background: transparent; | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_headertable th { | ||
| + | padding: 8px 12px; | ||
| + | font-size: 10px; | ||
| + | font-weight: | ||
| + | text-transform: | ||
| + | letter-spacing: | ||
| + | color: var(--fl-text-muted); | ||
| + | text-align: left; | ||
| + | border: none; | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_headertable th: | ||
| + | padding-left: | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_headertable th a { | ||
| + | color: inherit; | ||
| + | text-decoration: | ||
| + | } | ||
| + | |||
| + | /* Body rows */ | ||
| + | .plugin__filelisting_bodytable tbody tr { | ||
| + | border-bottom: | ||
| + | transition: background-color var(--fl-transition); | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_bodytable tbody tr: | ||
| + | border-bottom: | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_bodytable tbody tr:hover { | ||
| + | background-color: | ||
| + | } | ||
| + | |||
| + | /* Folder rows */ | ||
| + | .plugin__filelisting_bodytable tbody tr[data-namespace] { | ||
| + | cursor: pointer; | ||
| + | } | ||
| + | |||
| + | /* Nested file rows */ | ||
| + | .plugin__filelisting_bodytable tbody tr.fl-nested { | ||
| + | background: var(--fl-bg-nested); | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_bodytable tbody tr.fl-nested: | ||
| + | background: #f4f6f8; | ||
| + | } | ||
| + | |||
| + | /* Cells */ | ||
| + | .plugin__filelisting_bodytable td { | ||
| + | padding: 10px 12px; | ||
| + | font-size: 13px; | ||
| + | color: var(--fl-text); | ||
| + | border: none; | ||
| + | vertical-align: | ||
| + | } | ||
| + | |||
| + | /* Checkbox column */ | ||
| + | .plugin__filelisting_bodytable td: | ||
| + | width: 36px; | ||
| + | padding: 10px 4px 10px 16px; | ||
| + | } | ||
| + | |||
| + | /* Nested row indentation - checkbox cell */ | ||
| + | .plugin__filelisting_bodytable tr.fl-nested td: | ||
| + | padding-left: | ||
| + | } | ||
| + | |||
| + | /* Custom checkbox */ | ||
| + | .plugin__filelisting_bodytable input[type=" | ||
| + | appearance: none; | ||
| + | -webkit-appearance: | ||
| + | width: 16px; | ||
| + | height: 16px; | ||
| + | border: 1.5px solid var(--fl-border); | ||
| + | border-radius: | ||
| + | background: var(--fl-bg); | ||
| + | cursor: pointer; | ||
| + | transition: all var(--fl-transition); | ||
| + | position: relative; | ||
| + | flex-shrink: | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_bodytable input[type=" | ||
| + | border-color: | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_bodytable input[type=" | ||
| + | background: var(--fl-accent); | ||
| + | border-color: | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_bodytable input[type=" | ||
| + | content: ''; | ||
| + | position: absolute; | ||
| + | left: 4.5px; | ||
| + | top: 1.5px; | ||
| + | width: 4px; | ||
| + | height: 8px; | ||
| + | border: solid white; | ||
| + | border-width: | ||
| + | transform: rotate(45deg); | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_bodytable input[type=" | ||
| + | outline: none; | ||
| + | box-shadow: 0 0 0 2px var(--fl-accent-light); | ||
| + | } | ||
| + | |||
| + | /* Icon column */ | ||
| + | .plugin__filelisting_cell_icon { | ||
| + | width: 28px; | ||
| + | padding: 10px 8px 10px 0 !important; | ||
| + | } | ||
| + | |||
| + | /* Nested row indentation - icon cell */ | ||
| + | .plugin__filelisting_bodytable tr.fl-nested .plugin__filelisting_cell_icon { | ||
| + | position: relative; | ||
| + | } | ||
| + | |||
| + | /* Tree connector line */ | ||
| + | .plugin__filelisting_bodytable tr.fl-nested .plugin__filelisting_cell_icon:: | ||
| + | content: ''; | ||
| + | position: absolute; | ||
| + | left: -8px; | ||
| + | top: 50%; | ||
| + | width: 10px; | ||
| + | height: 1px; | ||
| + | background: var(--fl-border); | ||
| + | } | ||
| + | |||
| + | /* Folder icons - original SVG styling */ | ||
| + | .plugin__filelisting_cell_icon svg { | ||
| + | width: 18px !important; | ||
| + | height: 18px !important; | ||
| + | fill: var(--fl-folder); | ||
| + | transition: fill var(--fl-transition), | ||
| + | display: block; | ||
| + | } | ||
| + | |||
| + | tr:hover .plugin__filelisting_cell_icon svg { | ||
| + | fill: #f59f00; | ||
| + | } | ||
| + | |||
| + | /* Custom file icon container */ | ||
| + | .fl-file-icon { | ||
| + | width: 18px; | ||
| + | height: 18px; | ||
| + | display: flex; | ||
| + | align-items: | ||
| + | justify-content: | ||
| + | } | ||
| + | |||
| + | .fl-file-icon svg { | ||
| + | width: 18px; | ||
| + | height: 18px; | ||
| + | fill: none; | ||
| + | } | ||
| + | |||
| + | /* Name column */ | ||
| + | .plugin__filelisting_cell_name { | ||
| + | font-weight: | ||
| + | color: var(--fl-text); | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_cell_name a { | ||
| + | color: inherit; | ||
| + | text-decoration: | ||
| + | transition: color var(--fl-transition); | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_cell_name a:hover { | ||
| + | color: var(--fl-accent); | ||
| + | } | ||
| + | |||
| + | /* Hide original nested indicator arrow */ | ||
| + | .plugin__filelisting_cell_name > span { | ||
| + | display: none !important; | ||
| + | } | ||
| + | |||
| + | /* File name styling for nested */ | ||
| + | tr.fl-nested .plugin__filelisting_cell_name a { | ||
| + | font-weight: | ||
| + | font-family: | ||
| + | font-size: 12px; | ||
| + | color: var(--fl-text-secondary); | ||
| + | } | ||
| + | |||
| + | tr.fl-nested: | ||
| + | color: var(--fl-accent); | ||
| + | } | ||
| + | |||
| + | /* Size & Date columns */ | ||
| + | .plugin__filelisting_bodytable td: | ||
| + | .plugin__filelisting_bodytable td: | ||
| + | font-family: | ||
| + | font-size: 11px; | ||
| + | color: var(--fl-text-muted); | ||
| + | font-weight: | ||
| + | } | ||
| + | |||
| + | /* Empty values */ | ||
| + | .plugin__filelisting_bodytable td[data-sort="" | ||
| + | color: var(--fl-border); | ||
| + | } | ||
| + | |||
| + | /* Footer */ | ||
| + | .plugin__filelisting_footer { | ||
| + | padding: 10px 16px; | ||
| + | background: var(--fl-bg); | ||
| + | border-top: 1px solid var(--fl-border); | ||
| + | display: flex; | ||
| + | align-items: | ||
| + | gap: 12px; | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_footer label { | ||
| + | font-size: 11px; | ||
| + | font-weight: | ||
| + | color: var(--fl-text-secondary); | ||
| + | display: flex; | ||
| + | align-items: | ||
| + | gap: 8px; | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_footer input { | ||
| + | padding: 6px 10px; | ||
| + | border: 1px solid var(--fl-border); | ||
| + | border-radius: | ||
| + | font-family: | ||
| + | font-size: 12px; | ||
| + | outline: none; | ||
| + | transition: border-color var(--fl-transition), | ||
| + | background: var(--fl-bg); | ||
| + | width: 180px; | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_footer input:focus { | ||
| + | border-color: | ||
| + | box-shadow: 0 0 0 3px var(--fl-accent-light); | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_footer input:: | ||
| + | color: var(--fl-text-muted); | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_footer button { | ||
| + | padding: 6px 12px; | ||
| + | font-size: 11px; | ||
| + | font-weight: | ||
| + | background: #fff5f5; | ||
| + | color: var(--fl-file-pdf); | ||
| + | border: 1px solid #ffc9c9; | ||
| + | border-radius: | ||
| + | cursor: pointer; | ||
| + | transition: all var(--fl-transition); | ||
| + | font-family: | ||
| + | } | ||
| + | |||
| + | .plugin__filelisting_footer button: | ||
| + | background: #ffe3e3; | ||
| + | border-color: | ||
| + | } | ||
| + | |||
| + | /* Animation for row appearance */ | ||
| + | @keyframes fl-fadeIn { | ||
| + | from { | ||
| + | opacity: 0; | ||
| + | transform: translateY(-4px); | ||
| + | } | ||
| + | to { | ||
| + | opacity: 1; | ||
| + | transform: translateY(0); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | tr.fl-nested { | ||
| + | animation: fl-fadeIn 200ms ease forwards; | ||
| + | } | ||
| + | |||
| + | /* Folder expansion indicator */ | ||
| + | tr[data-namespace].fl-expanded .plugin__filelisting_cell_icon svg { | ||
| + | transform: scale(1.05); | ||
| } | } | ||
| </ | </ | ||
| Line 30: | Line 419: | ||
| < | < | ||
| document.addEventListener(' | document.addEventListener(' | ||
| + | |||
| + | /* ======================================== | ||
| + | SVG Icon Definitions | ||
| + | | ||
| + | const fileIcons = { | ||
| + | pdf: `<svg viewBox=" | ||
| + | <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/> | ||
| + | < | ||
| + | </ | ||
| + | mp4: `<svg viewBox=" | ||
| + | <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/> | ||
| + | < | ||
| + | <polygon points=" | ||
| + | </ | ||
| + | pptx: `<svg viewBox=" | ||
| + | <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/> | ||
| + | < | ||
| + | </ | ||
| + | docx: `<svg viewBox=" | ||
| + | <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/> | ||
| + | < | ||
| + | </ | ||
| + | xlsx: `<svg viewBox=" | ||
| + | <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/> | ||
| + | < | ||
| + | </ | ||
| + | zip: `<svg viewBox=" | ||
| + | <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/> | ||
| + | < | ||
| + | <line x1=" | ||
| + | <line x1=" | ||
| + | </ | ||
| + | default: `<svg viewBox=" | ||
| + | <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/> | ||
| + | < | ||
| + | </ | ||
| + | }; | ||
| + | |||
| + | /* ======================================== | ||
| + | | ||
| + | | ||
| function beautifyName(name) { | function beautifyName(name) { | ||
| return name | return name | ||
| - | .replace(/ | + | .replace(/ |
| .replace(/ | .replace(/ | ||
| - | .replace(/ | + | .replace(/ |
| - | return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); | + | const lowerWords = [' |
| - | }); | + | const lower = word.toLowerCase(); |
| + | return | ||
| + | ? lower | ||
| + | : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); | ||
| + | }) | ||
| + | .replace(/ | ||
| } | } | ||
| - | const nameCells | + | |
| + | Get Icon for File Extension | ||
| + | | ||
| + | function getFileIcon(filename) { | ||
| + | | ||
| + | return fileIcons[ext] || fileIcons.default; | ||
| + | } | ||
| - | | + | |
| - | const link = cell.querySelector(' | + | |
| - | if (link) | + | |
| - | const originalText | + | const rows = document.querySelectorAll(' |
| - | const isFile = /\.\w{2,4}$/.test(originalText); | + | |
| + | rows.forEach((row, index) => { | ||
| + | const nameCell = row.querySelector(' | ||
| + | const iconCell = row.querySelector(' | ||
| + | const link = nameCell?.querySelector(' | ||
| + | | ||
| + | if (!link) return; | ||
| + | |||
| + | | ||
| + | const isFile = /\.\w{2,5}$/.test(text); | ||
| + | const hasNamespace = row.hasAttribute(' | ||
| + | const childOf = row.getAttribute(' | ||
| + | |||
| + | // Determine if this is a nested file (not a folder, but has a parent) | ||
| + | const isNested = !hasNamespace && childOf && childOf.includes(':' | ||
| + | |||
| + | // Beautify folder names only | ||
| + | if (!isFile) { | ||
| + | link.textContent = beautifyName(text); | ||
| + | } | ||
| + | |||
| + | // Mark nested rows and handle their icons | ||
| + | if (isNested) { | ||
| + | row.classList.add(' | ||
| | | ||
| - | if (!isFile) { | + | |
| - | | + | const nextRow = rows[index + 1]; |
| + | const nextChildOf = nextRow? | ||
| + | const nextHasNamespace = nextRow? | ||
| + | |||
| + | | ||
| + | row.classList.add(' | ||
| + | } | ||
| + | |||
| + | // Replace file icons with custom SVG | ||
| + | if (iconCell && | ||
| + | | ||
| + | if (oldIcon) { | ||
| + | const iconWrapper = document.createElement(' | ||
| + | iconWrapper.className = ' | ||
| + | iconWrapper.innerHTML = getFileIcon(text); | ||
| + | oldIcon.replaceWith(iconWrapper); | ||
| + | } | ||
| } | } | ||
| } | } | ||
| }); | }); | ||
| + | |||
| + | /* ======================================== | ||
| + | | ||
| + | | ||
| + | const folderRows = document.querySelectorAll(' | ||
| + | | ||
| + | folderRows.forEach(folder => { | ||
| + | const namespace = folder.getAttribute(' | ||
| + | const childRows = document.querySelectorAll(`tr[data-childof=" | ||
| + | | ||
| + | if (childRows.length === 0) return; | ||
| + | | ||
| + | // Check initial state | ||
| + | const hasVisibleChildren = Array.from(childRows).some( | ||
| + | child => child.style.display !== ' | ||
| + | ); | ||
| + | | ||
| + | if (hasVisibleChildren) { | ||
| + | folder.classList.add(' | ||
| + | } | ||
| + | | ||
| + | // Observe visibility changes | ||
| + | const observer = new MutationObserver(() => { | ||
| + | const visible = Array.from(childRows).some( | ||
| + | child => child.style.display !== ' | ||
| + | ); | ||
| + | folder.classList.toggle(' | ||
| + | }); | ||
| + | | ||
| + | childRows.forEach(child => { | ||
| + | observer.observe(child, | ||
| + | attributes: true, | ||
| + | attributeFilter: | ||
| + | }); | ||
| + | }); | ||
| + | }); | ||
| + | |||
| + | /* ======================================== | ||
| + | | ||
| + | | ||
| + | const filterInput = document.querySelector(' | ||
| + | if (filterInput) { | ||
| + | filterInput.setAttribute(' | ||
| + | } | ||
| + | |||
| }); | }); | ||
| </ | </ | ||