mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-29 17:22:25 +01:00
feat(editor): harden photo editor security and interactions
This commit is contained in:
@@ -181,7 +181,7 @@ export function buildRightPanel({ controlsHTML, layerPanelHTML, extraPanels = []
|
||||
// entries in a compact `<select>` overlay reachable from a "Panels"
|
||||
// button in the layers header, without touching the peek/expand model.
|
||||
let mobilePanels = null;
|
||||
if (!useDock && Array.isArray(extraPanels) && extraPanels.length) {
|
||||
if (Array.isArray(extraPanels) && extraPanels.length) {
|
||||
const mDock = buildDock({
|
||||
entries: extraPanels,
|
||||
persistKey: 'ge-dock-active',
|
||||
@@ -218,7 +218,9 @@ export function buildRightPanel({ controlsHTML, layerPanelHTML, extraPanels = []
|
||||
overlay.hidden = !overlay.hidden;
|
||||
});
|
||||
hdr.appendChild(panelsBtn);
|
||||
if (useDock) panelsBtn.style.display = 'none';
|
||||
}
|
||||
if (useDock) overlay.style.display = 'none';
|
||||
mobilePanels = overlay;
|
||||
}
|
||||
|
||||
@@ -226,7 +228,7 @@ export function buildRightPanel({ controlsHTML, layerPanelHTML, extraPanels = []
|
||||
// The panels are only re-parented, so every existing selector and
|
||||
// listener keeps working; switching tabs just toggles `hidden`.
|
||||
let dock = null;
|
||||
if (useDock) { rightPanel.classList.add('ge-right-panel--dock');
|
||||
if (Array.isArray(extraPanels) && extraPanels.length) {
|
||||
dock = buildDock({
|
||||
entries: [
|
||||
...(Array.isArray(extraPanels) ? extraPanels : []),
|
||||
@@ -239,11 +241,12 @@ export function buildRightPanel({ controlsHTML, layerPanelHTML, extraPanels = []
|
||||
onCloseGroup,
|
||||
});
|
||||
rightPanel.appendChild(dock.dock);
|
||||
// Layers stays pinned below the dock so the layer list is always
|
||||
// visible while editing (Photoshop-style), regardless of the active
|
||||
// dock tab. Only the tool options + studio panels live in tabs.
|
||||
rightPanel.appendChild(layerPanel);
|
||||
if (!useDock) dock.dock.style.display = 'none';
|
||||
}
|
||||
if (useDock) {
|
||||
rightPanel.classList.add('ge-right-panel--dock');
|
||||
}
|
||||
rightPanel.appendChild(layerPanel);
|
||||
|
||||
// Horizontal drag handle on the LEFT edge of the right panel — drag
|
||||
// left to widen, right to narrow. Persists chosen width in
|
||||
@@ -286,5 +289,5 @@ export function buildRightPanel({ controlsHTML, layerPanelHTML, extraPanels = []
|
||||
} catch {}
|
||||
});
|
||||
|
||||
return { rightPanel, controls, layerPanel, panelResize, dock };
|
||||
return { rightPanel, controls, layerPanel, panelResize, dock, mobilePanels };
|
||||
}
|
||||
|
||||
@@ -242,7 +242,13 @@ export function buildToolbar({ currentTool, onSelectTool, onClearSelection }) {
|
||||
: soft >= 70
|
||||
? '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="6.5" fill="currentColor" opacity="0.3"/><circle cx="12" cy="12" r="6.5"/></svg>'
|
||||
: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><circle cx="12" cy="12" r="6.5" fill="currentColor" opacity="0.65"/><circle cx="12" cy="12" r="6.5"/></svg>';
|
||||
presetItem.insertAdjacentHTML('beforeend', `<span class="ge-tool-icon">${presetIcon}</span><span class="ge-tool-flyout-label">${preset.name}</span>`);
|
||||
const icon = document.createElement('span');
|
||||
icon.className = 'ge-tool-icon';
|
||||
icon.innerHTML = presetIcon;
|
||||
const label = document.createElement('span');
|
||||
label.className = 'ge-tool-flyout-label';
|
||||
label.textContent = preset.name;
|
||||
presetItem.append(icon, label);
|
||||
presetItem.addEventListener('click', (ev) => {
|
||||
ev.stopPropagation();
|
||||
setInner(face, 'brush');
|
||||
|
||||
@@ -535,6 +535,7 @@ export function buildTopbar() {
|
||||
<span class="ge-stacked-glyph">
|
||||
<svg hidden class="ge-save-state-icon ge-save-state-dirty" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 3h12l4 4v14H4z"/><path d="M8 3v6h8V3"/><path d="m16 3 6 6m0-6-6 6" stroke="var(--fg)" stroke-width="3"/></svg>
|
||||
<svg class="ge-save-state-icon ge-save-state-saved" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"/></svg>
|
||||
<svg hidden class="ge-save-state-icon ge-save-state-error" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
|
||||
</span>
|
||||
<span class="ge-stacked-label ge-save-action-label">SAVE</span>
|
||||
<span class="ge-stacked-label ge-save-label" id="ge-draft-status" role="status" aria-live="polite">Saved</span>
|
||||
|
||||
Reference in New Issue
Block a user