Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c849b1dc3 | ||
|
|
7cc314179f | ||
|
|
9ddb633cca | ||
|
|
448e246689 | ||
|
|
dc7797e50d | ||
|
|
913d370ef2 |
43
CHANGELOG.md
43
CHANGELOG.md
@@ -1,5 +1,48 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Changes 11/8/2025 (v1.8.13)
|
||||||
|
|
||||||
|
release(v1.8.13): ui(dnd): stabilize zones, lock sidebar width, and keep header dock in sync
|
||||||
|
|
||||||
|
- dnd: fix disappearing/overlapping cards when moving between sidebar/top; return to origin on failed drop
|
||||||
|
- layout: placeCardInZone now live-updates top layout, sidebar visibility, and toggle icon
|
||||||
|
- toggle/collapse: move ALL cards to header on collapse, restore saved layout on expand; keep icon state synced; add body.sidebar-hidden for proper file list expansion; emit `zones:collapsed-changed`
|
||||||
|
- header dock: show dock whenever icons exist (and on collapse); hide when empty
|
||||||
|
- responsive: enforceResponsiveZones also updates toggle icon; stash/restore behavior unchanged
|
||||||
|
- sidebar: hard-lock width to 350px (CSS) and remove runtime 280px minWidth; add placeholder when empty to make dropping back easy
|
||||||
|
- CSS: right-align header dock buttons, centered “Drop Zone” label, sensible min-height; dark-mode safe
|
||||||
|
- refactor: small renames/ordering; remove redundant z-index on toggle; minor formatting
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Changes 11/8/2025 (v1.8.12)
|
||||||
|
|
||||||
|
release(v1.8.12): auth UI & DnD polish — show OIDC, auto-SSO, right-aligned header icons
|
||||||
|
|
||||||
|
- auth (public/js/main.js)
|
||||||
|
- Robust login options: tolerate key variants (disableFormLogin/disable_form_login, etc.).
|
||||||
|
- Correctly show/hide wrapper + individual methods (form/OIDC/basic).
|
||||||
|
- Auto-SSO when OIDC is the only enabled method; add opt-out with `?noauto=1`.
|
||||||
|
- Minor cleanup (SW register catch spacing).
|
||||||
|
|
||||||
|
- drag & drop (public/js/dragAndDrop.js)
|
||||||
|
- Reworked zones model: Sidebar / Top (left/right) / Header (icon+modal).
|
||||||
|
- Persist user layout with `userZonesSnapshot.v2` and responsive stash for small screens.
|
||||||
|
- Live UI sync: toggle icon (`material-icons`) updates immediately after moves.
|
||||||
|
- Smarter small-screen behavior: lift sidebar cards ephemerally; restore only what belonged to sidebar.
|
||||||
|
- Cleaner header icon modal plumbing; remove legacy/dead code.
|
||||||
|
|
||||||
|
- styles (public/css/styles.css)
|
||||||
|
- Header drop zone fills remaining space and right-aligns its icons.
|
||||||
|
|
||||||
|
UX:
|
||||||
|
|
||||||
|
- OIDC button reliably appears when form/basic are disabled.
|
||||||
|
- If OIDC is the sole method, users are taken straight to the provider (unless `?noauto=1`).
|
||||||
|
- Header icons sit with the other header actions (right-aligned), and the toggle icon reflects layout changes instantly.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Changes 11/8/2025 (v1.8.11)
|
## Changes 11/8/2025 (v1.8.11)
|
||||||
|
|
||||||
release(v1.8.11): fix(oidc): always send PKCE (S256) and treat empty secret as public client
|
release(v1.8.11): fix(oidc): always send PKCE (S256) and treat empty secret as public client
|
||||||
|
|||||||
@@ -29,8 +29,7 @@ New: Open and edit Office documents — **Word (DOCX)**, **Excel (XLSX)**, **Pow
|
|||||||
|
|
||||||
<https://github.com/user-attachments/assets/a2240300-6348-4de7-b72f-1b85b7da3a08>
|
<https://github.com/user-attachments/assets/a2240300-6348-4de7-b72f-1b85b7da3a08>
|
||||||
|
|
||||||
**Dark mode:**
|

|
||||||

|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,15 @@ body {
|
|||||||
}#userDropdownToggle {
|
}#userDropdownToggle {
|
||||||
border-radius: 4px !important;
|
border-radius: 4px !important;
|
||||||
padding: 6px 10px !important;
|
padding: 6px 10px !important;
|
||||||
}.header-buttons button:hover {
|
}
|
||||||
|
|
||||||
|
#headerDropArea.header-drop-zone{
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end; /* buttons to the right */
|
||||||
|
align-items: center;
|
||||||
|
min-height: 40px; /* so the label has room */
|
||||||
|
}
|
||||||
|
.header-buttons button:hover {
|
||||||
background-color: rgba(255, 255, 255, 0.2);
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@@ -1524,7 +1532,16 @@ body {
|
|||||||
.drag-header.active {
|
.drag-header.active {
|
||||||
width: 350px;
|
width: 350px;
|
||||||
height: 750px;
|
height: 750px;
|
||||||
}.main-column {
|
}
|
||||||
|
/* Fixed-width sidebar (always 350px) */
|
||||||
|
#sidebarDropArea{
|
||||||
|
width: 350px;
|
||||||
|
min-width: 350px;
|
||||||
|
max-width: 350px;
|
||||||
|
flex: 0 0 350px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.main-column {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
transition: margin-left 0.3s ease;
|
transition: margin-left 0.3s ease;
|
||||||
}#uploadFolderRow {
|
}#uploadFolderRow {
|
||||||
@@ -1592,8 +1609,8 @@ body {
|
|||||||
}#sidebarDropArea,
|
}#sidebarDropArea,
|
||||||
#uploadFolderRow {
|
#uploadFolderRow {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
}
|
||||||
}.dark-mode #sidebarDropArea,
|
.dark-mode #sidebarDropArea,
|
||||||
.dark-mode #uploadFolderRow {
|
.dark-mode #uploadFolderRow {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}.dark-mode #sidebarDropArea.highlight,
|
}.dark-mode #sidebarDropArea.highlight,
|
||||||
@@ -1607,8 +1624,6 @@ body {
|
|||||||
border: none !important;
|
border: none !important;
|
||||||
}.dragging:focus {
|
}.dragging:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}#sidebarDropArea > .card {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}.card {
|
}.card {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
color: #000;
|
color: #000;
|
||||||
@@ -1705,8 +1720,9 @@ body {
|
|||||||
border: 2px dashed #555;
|
border: 2px dashed #555;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}.header-drop-zone.drag-active:empty::before {
|
}.header-drop-zone.drag-active:empty::before {
|
||||||
content: "Drop";
|
content: "Drop Zone";
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
|
padding-right: 6px;
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
}/* Disable text selection on rows to prevent accidental copying when shift-clicking */
|
}/* Disable text selection on rows to prevent accidental copying when shift-clicking */
|
||||||
#fileList tbody tr.clickable-row {
|
#fileList tbody tr.clickable-row {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -409,21 +409,39 @@ function bindDarkMode() {
|
|||||||
|
|
||||||
// --- Login options (apply in BOTH phases so login page is correct) ---
|
// --- Login options (apply in BOTH phases so login page is correct) ---
|
||||||
const lo = (cfg && cfg.loginOptions) ? cfg.loginOptions : {};
|
const lo = (cfg && cfg.loginOptions) ? cfg.loginOptions : {};
|
||||||
const disableForm = !!lo.disableFormLogin;
|
|
||||||
const disableOIDC = !!lo.disableOIDCLogin;
|
|
||||||
const disableBasic = !!lo.disableBasicAuth;
|
|
||||||
|
|
||||||
const row = $('#loginForm');
|
|
||||||
if (row) {
|
// be tolerant to key variants just in case
|
||||||
if (disableForm) {
|
const disableForm = !!(lo.disableFormLogin ?? lo.disable_form_login ?? lo.disableForm);
|
||||||
row.setAttribute('hidden', '');
|
const disableOIDC = !!(lo.disableOIDCLogin ?? lo.disable_oidc_login ?? lo.disableOIDC);
|
||||||
row.style.display = ''; // don't leave display:none lying around
|
const disableBasic = !!(lo.disableBasicAuth ?? lo.disable_basic_auth ?? lo.disableBasic);
|
||||||
|
|
||||||
|
const showForm = !disableForm;
|
||||||
|
const showOIDC = !disableOIDC;
|
||||||
|
const showBasic = !disableBasic;
|
||||||
|
|
||||||
|
const loginWrap = $('#loginForm'); // outer wrapper that contains buttons + form
|
||||||
|
const authForm = $('#authForm'); // inner username/password form
|
||||||
|
const oidcBtn = $('#oidcLoginBtn'); // OIDC button
|
||||||
|
const basicLink = document.querySelector('a[href="/api/auth/login_basic.php"]');
|
||||||
|
|
||||||
|
// 1) Show the wrapper if ANY method is enabled (form OR OIDC OR basic)
|
||||||
|
if (loginWrap) {
|
||||||
|
const anyMethod = showForm || showOIDC || showBasic;
|
||||||
|
if (anyMethod) {
|
||||||
|
loginWrap.removeAttribute('hidden'); // remove [hidden], which beats display:
|
||||||
|
loginWrap.style.display = ''; // let CSS decide
|
||||||
} else {
|
} else {
|
||||||
row.removeAttribute('hidden');
|
loginWrap.setAttribute('hidden', '');
|
||||||
row.style.display = '';
|
loginWrap.style.display = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const oidc = $('#oidcLoginBtn'); if (oidc) oidc.style.display = disableOIDC ? 'none' : '';
|
|
||||||
|
// 2) Toggle the pieces inside the wrapper
|
||||||
|
if (authForm) authForm.style.display = showForm ? '' : 'none';
|
||||||
|
if (oidcBtn) oidcBtn.style.display = showOIDC ? '' : 'none';
|
||||||
|
if (basicLink) basicLink.style.display = showBasic ? '' : 'none';
|
||||||
|
const oidc = $('#oidcLoginBtn'); if (oidc) oidc.style.display = disableOIDC ? 'none' : '';
|
||||||
const basic = document.querySelector('a[href="/api/auth/login_basic.php"]');
|
const basic = document.querySelector('a[href="/api/auth/login_basic.php"]');
|
||||||
if (basic) basic.style.display = disableBasic ? 'none' : '';
|
if (basic) basic.style.display = disableBasic ? 'none' : '';
|
||||||
|
|
||||||
@@ -1037,6 +1055,21 @@ function bindDarkMode() {
|
|||||||
if (login) login.style.display = '';
|
if (login) login.style.display = '';
|
||||||
// …wire stuff…
|
// …wire stuff…
|
||||||
applySiteConfig(window.__FR_SITE_CFG__ || {}, { phase: 'final' });
|
applySiteConfig(window.__FR_SITE_CFG__ || {}, { phase: 'final' });
|
||||||
|
// Auto-SSO if OIDC is the only enabled method (add ?noauto=1 to skip)
|
||||||
|
(() => {
|
||||||
|
const lo = (window.__FR_SITE_CFG__ && window.__FR_SITE_CFG__.loginOptions) || {};
|
||||||
|
const disableForm = !!(lo.disableFormLogin ?? lo.disable_form_login ?? lo.disableForm);
|
||||||
|
const disableBasic = !!(lo.disableBasicAuth ?? lo.disable_basic_auth ?? lo.disableBasic);
|
||||||
|
const disableOIDC = !!(lo.disableOIDCLogin ?? lo.disable_oidc_login ?? lo.disableOIDC);
|
||||||
|
|
||||||
|
const onlyOIDC = disableForm && disableBasic && !disableOIDC;
|
||||||
|
const qp = new URLSearchParams(location.search);
|
||||||
|
|
||||||
|
if (onlyOIDC && qp.get('noauto') !== '1') {
|
||||||
|
const btn = document.getElementById('oidcLoginBtn');
|
||||||
|
if (btn) setTimeout(() => btn.click(), 250);
|
||||||
|
}
|
||||||
|
})();
|
||||||
await revealAppAndHideOverlay();
|
await revealAppAndHideOverlay();
|
||||||
const hb = document.querySelector('.header-buttons');
|
const hb = document.querySelector('.header-buttons');
|
||||||
if (hb) hb.style.visibility = 'hidden';
|
if (hb) hb.style.visibility = 'hidden';
|
||||||
@@ -1102,7 +1135,7 @@ function bindDarkMode() {
|
|||||||
const onHttps = location.protocol === 'https:' || location.hostname === 'localhost';
|
const onHttps = location.protocol === 'https:' || location.hostname === 'localhost';
|
||||||
if ('serviceWorker' in navigator && onHttps && !hasCapBridge && !isCapUA) {
|
if ('serviceWorker' in navigator && onHttps && !hasCapBridge && !isCapUA) {
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
navigator.serviceWorker.register(`/js/pwa/sw.js?v=${encodeURIComponent(QVER)}`).catch(() => {});
|
navigator.serviceWorker.register(`/js/pwa/sw.js?v=${encodeURIComponent(QVER)}`).catch(() => { });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
// generated by CI
|
// generated by CI
|
||||||
window.APP_VERSION = 'v1.8.11';
|
window.APP_VERSION = 'v1.8.13';
|
||||||
|
|||||||
Reference in New Issue
Block a user