feat: draggable nav panel with position saved to localStorage

This commit is contained in:
2026-05-04 13:28:10 +00:00
parent 535d71709e
commit 0b37d5245c
+30 -1
View File
@@ -40,8 +40,10 @@ cat > /opt/portal/index.html <<HTML
position:fixed;left:16px;top:64px;z-index:99;display:flex;gap:10px; position:fixed;left:16px;top:64px;z-index:99;display:flex;gap:10px;
background:linear-gradient(180deg,rgba(15,24,36,.78),rgba(9,14,22,.86)); background:linear-gradient(180deg,rgba(15,24,36,.78),rgba(9,14,22,.86));
border:1px solid rgba(255,255,255,.22);backdrop-filter:blur(5px); border:1px solid rgba(255,255,255,.22);backdrop-filter:blur(5px);
box-shadow:0 10px 28px rgba(0,0,0,.36);padding:9px 10px;border-radius:14px box-shadow:0 10px 28px rgba(0,0,0,.36);padding:9px 10px;border-radius:14px;
cursor:grab;user-select:none;touch-action:none
} }
.nav-panel.dragging{cursor:grabbing;opacity:.85}
.nav-btn{ .nav-btn{
border:1px solid rgba(255,255,255,.26);border-radius:999px;padding:9px 14px;cursor:pointer; border:1px solid rgba(255,255,255,.26);border-radius:999px;padding:9px 14px;cursor:pointer;
background:linear-gradient(180deg,#2a8cd6,#1668a6);color:#fff;font:700 13px/1 sans-serif; background:linear-gradient(180deg,#2a8cd6,#1668a6);color:#fff;font:700 13px/1 sans-serif;
@@ -176,6 +178,33 @@ cat > /opt/portal/index.html <<HTML
document.getElementById('btn-home').addEventListener('click', goHome); document.getElementById('btn-home').addEventListener('click', goHome);
document.addEventListener('contextmenu', (e) => e.preventDefault()); document.addEventListener('contextmenu', (e) => e.preventDefault());
(function(){
const p = document.querySelector('.nav-panel');
const SK = 'rdp_nav_pos';
try { const s = JSON.parse(localStorage.getItem(SK)); if(s){p.style.left=s.x+'px';p.style.top=s.y+'px';} } catch(e){}
let ox, oy, dragged = false;
p.addEventListener('pointerdown', e => {
if (e.target.closest('button')) return;
dragged = false;
ox = e.clientX - p.getBoundingClientRect().left;
oy = e.clientY - p.getBoundingClientRect().top;
p.setPointerCapture(e.pointerId);
p.classList.add('dragging');
});
p.addEventListener('pointermove', e => {
if (!p.hasPointerCapture(e.pointerId)) return;
dragged = true;
const x = Math.max(0, Math.min(window.innerWidth - p.offsetWidth, e.clientX - ox));
const y = Math.max(0, Math.min(window.innerHeight - p.offsetHeight, e.clientY - oy));
p.style.left = x + 'px';
p.style.top = y + 'px';
});
p.addEventListener('pointerup', () => {
p.classList.remove('dragging');
if (dragged) try { localStorage.setItem(SK, JSON.stringify({x: parseInt(p.style.left), y: parseInt(p.style.top)})); } catch(e){}
});
})();
connect(); connect();
</script> </script>
</body> </body>