diff --git a/app/app.js b/app/app.js
index b5a0cb9..e118506 100644
--- a/app/app.js
+++ b/app/app.js
@@ -1,6 +1,6 @@
// ============================================================================
-// LAUNCHER — VERSIONE COMPLETA E OTTIMIZZATA (A) — BLOCCO 1/6
-// Sezione: Variabili globali + Storage + Config + Setup Page
+// LAUNCHER — VERSIONE COMPLETA E OTTIMIZZATA (A)
+// BLOCCO 1/6 — Variabili globali + Storage + Config + Setup Page
// ============================================================================
// ---------------------------------------------------------------------------
@@ -32,6 +32,7 @@ let dragOffsetX = 0;
let dragOffsetY = 0;
let dragStartX = 0;
let dragStartY = 0;
+let placeholderEl = null;
// ---------------------------------------------------------------------------
// CRITTOGRAFIA E STORAGE
@@ -96,30 +97,18 @@ function loadApps() {
}
// ---------------------------------------------------------------------------
-// SETUP PAGE (6 TAP PER APRIRE + AUTOCOMPILAZIONE)
+// SETUP PAGE (6 TAP PER APRIRE + AUTOCOMPILAZIONE + "Aggiorna ora")
// ---------------------------------------------------------------------------
-/*function showSetupPage() {
- const cfg = loadConfig();
- if (cfg) {
- document.getElementById("cfg-url").value = cfg.url;
- document.getElementById("cfg-user").value = cfg.user;
- document.getElementById("cfg-pass").value = cfg.password;
- }
- document.getElementById("setup-page").classList.remove("hidden");
-}*/
-
function showSetupPage() {
const cfg = loadConfig();
if (cfg) {
- // Popola i campi
document.getElementById("cfg-url").value = cfg.url;
document.getElementById("cfg-user").value = cfg.user;
document.getElementById("cfg-pass").value = cfg.password;
- // Mostra il pulsante "Aggiorna ora"
+ // Mostra il pulsante "Aggiorna ora" solo se esiste già una config
document.getElementById("cfg-refresh").style.display = "block";
-
} else {
// Nessuna config → nascondi il pulsante
document.getElementById("cfg-refresh").style.display = "none";
@@ -150,9 +139,10 @@ document.addEventListener("click", () => {
showSetupPage();
}
});
+
// ============================================================================
-// LAUNCHER — VERSIONE COMPLETA E OTTIMIZZATA (A) — BLOCCO 2/6
-// Sezione: API login, getLinks, ordine apps, render, startLauncher
+// LAUNCHER — VERSIONE COMPLETA E OTTIMIZZATA (A)
+// BLOCCO 2/6 — API login, getLinks, ordine apps, render, startLauncher
// ============================================================================
// ---------------------------------------------------------------------------
@@ -280,7 +270,7 @@ function renderApps() {
}
// ---------------------------------------------------------------------------
-// START LAUNCHER (carica locale → render → aggiorna server → init UI)
+// START LAUNCHER (carica locale → render → init UI)
// ---------------------------------------------------------------------------
async function startLauncher() {
@@ -288,7 +278,7 @@ async function startLauncher() {
const saved = loadApps();
if (saved) {
appsData = saved;
- //console.log("Apps caricate da localStorage:", appsData);
+ console.log("Apps caricate da localStorage:", appsData);
}
// 2️⃣ Carica ordine
@@ -297,24 +287,24 @@ async function startLauncher() {
// 3️⃣ Render immediato (istantaneo)
renderApps();
- // 4️⃣ Aggiorna in background dal server
- //getLinks();
+ // ❌ Nessun aggiornamento automatico dal server
+ // getLinks();
- // 5️⃣ Inizializza UI (zoom, drag, wiggle, menu…)
+ // 4️⃣ Inizializza UI (zoom, drag, wiggle, menu…)
initZoomHandlers();
initLongPressHandlers();
initDragHandlers();
initContextMenuActions();
initGlobalCloseHandlers();
}
+
// ============================================================================
-// LAUNCHER — VERSIONE COMPLETA E OTTIMIZZATA (A) — BLOCCO 3/6
-// Sezione: Zoom stile iPhone (pinch, elasticità, wheel)
+// LAUNCHER — VERSIONE COMPLETA E OTTIMIZZATA (A)
+// BLOCCO 3/6 — Zoom stile iPhone (pinch, elasticità, wheel)
// ============================================================================
// ---------------------------------------------------------------------------
// Calcolo dinamico dello zoom massimo
-// (dipende dalla larghezza dello schermo e dalla dimensione delle icone)
// ---------------------------------------------------------------------------
function computeDynamicMaxZoom() {
return Math.min(window.innerWidth / 85, 4.0);
@@ -370,7 +360,7 @@ function initZoomHandlers() {
if (e.touches.length === 2) e.preventDefault();
}, { passive: false });
- // Inizio pinch o doppio tap
+ // Inizio pinch (NO double tap zoom)
document.addEventListener("touchstart", e => {
// Inizio pinch
@@ -379,13 +369,7 @@ function initZoomHandlers() {
if (zoomAnimFrame) cancelAnimationFrame(zoomAnimFrame);
}
- // Doppio tap → zoom rapido
- /*const now = Date.now();
- if (e.touches.length === 1 && now - lastTapTime < 300) {
- zoomMax = computeDynamicMaxZoom();
- applyZoom(Math.min(zoomLevel * 1.15, zoomMax));
- }
- lastTapTime = now;*/
+ // Nessuna azione sul doppio tap
lastTapTime = Date.now();
});
@@ -449,9 +433,10 @@ function initZoomHandlers() {
applyZoom(newZoom);
}, { passive: false });
}
+
// ============================================================================
-// LAUNCHER — VERSIONE COMPLETA E OTTIMIZZATA (A) — BLOCCO 4/6
-// Sezione: Long‑press, Edit Mode, Context Menu, Global Close
+// LAUNCHER — VERSIONE COMPLETA E OTTIMIZZATA (A)
+// BLOCCO 4/6 — Long‑press, Edit Mode, Context Menu, Global Close
// ============================================================================
// ---------------------------------------------------------------------------
@@ -632,9 +617,10 @@ function initGlobalCloseHandlers() {
}
});
}
+
// ============================================================================
-// LAUNCHER — VERSIONE COMPLETA E OTTIMIZZATA (A) — BLOCCO 5/6
-// Sezione: Drag & Drop stile iPhone
+// LAUNCHER — VERSIONE COMPLETA E OTTIMIZZATA (A)
+// BLOCCO 5/6 — Drag & Drop stile iPhone (FIXED)
// ============================================================================
// ---------------------------------------------------------------------------
@@ -658,9 +644,11 @@ function getPointerPosition(e) {
}
// ---------------------------------------------------------------------------
-// Inizio drag: crea icona flottante + placeholder invisibile
+/* Inizio drag: icona flottante + placeholder nel layout */
// ---------------------------------------------------------------------------
function startDrag(icon, pos) {
+ const folderEl = document.getElementById("folder");
+
draggingId = icon.dataset.id;
const r = icon.getBoundingClientRect();
@@ -678,20 +666,22 @@ function startDrag(icon, pos) {
draggingIcon.style.pointerEvents = "none";
draggingIcon.style.transform = "translate3d(0,0,0)";
- // Placeholder invisibile che mantiene lo spazio
- const placeholder = icon.cloneNode(true);
- placeholder.classList.add("placeholder");
- placeholder.style.visibility = "hidden";
- icon.parentNode.insertBefore(placeholder, icon);
+ // Placeholder nel layout (slot vuoto)
+ placeholderEl = document.createElement("div");
+ placeholderEl.className = "app-icon placeholder";
+ placeholderEl.style.visibility = "hidden";
+
+ // Inserisci il placeholder dove stava l’icona
+ folderEl.insertBefore(placeholderEl, icon);
hideContextMenu();
}
// ---------------------------------------------------------------------------
-// Aggiorna posizione dell’icona trascinata + reorder dinamico
+// Aggiorna posizione icona trascinata + posizione placeholder
// ---------------------------------------------------------------------------
function updateDragPosition(pos) {
- if (!draggingIcon) return;
+ if (!draggingIcon || !placeholderEl) return;
const x = pos.pageX - dragOffsetX;
const y = pos.pageY - dragOffsetY;
@@ -699,63 +689,72 @@ function updateDragPosition(pos) {
draggingIcon.style.left = `${x}px`;
draggingIcon.style.top = `${y}px`;
- const elem = document.elementFromPoint(pos.clientX, pos.clientY);
- const targetIcon = elem && elem.closest(".app-icon:not(.dragging):not(.placeholder)");
- if (!targetIcon) return;
+ const centerX = pos.clientX;
+ const centerY = pos.clientY;
- const from = appsOrder.indexOf(draggingId);
- const to = appsOrder.indexOf(targetIcon.dataset.id);
- if (from === -1 || to === -1 || from === to) return;
+ const elem = document.elementFromPoint(centerX, centerY);
+ const targetIcon = elem && elem.closest(".app-icon:not(.dragging)");
+ if (!targetIcon || targetIcon === placeholderEl) return;
- appsOrder.splice(from, 1);
- appsOrder.splice(to, 0, draggingId);
- saveOrder();
+ const folderEl = document.getElementById("folder");
+ const targetRect = targetIcon.getBoundingClientRect();
+ const isBefore = centerY < targetRect.top + targetRect.height / 2;
+
+ if (isBefore) {
+ folderEl.insertBefore(placeholderEl, targetIcon);
+ } else {
+ folderEl.insertBefore(placeholderEl, targetIcon.nextSibling);
+ }
}
// ---------------------------------------------------------------------------
-// Fine drag: drop preciso nella cella corretta
+// Fine drag: aggiorna appsOrder in base alla posizione del placeholder
// ---------------------------------------------------------------------------
function endDrag() {
- if (!draggingIcon) return;
+ if (!draggingIcon || !placeholderEl) {
+ draggingIcon = null;
+ placeholderEl = null;
+ dragStartX = 0;
+ dragStartY = 0;
+ return;
+ }
- const icon = draggingIcon;
- draggingIcon = null;
+ const folderEl = document.getElementById("folder");
- // Rimuovi placeholder
- const placeholder = document.querySelector(".app-icon.placeholder");
- if (placeholder) placeholder.remove();
+ // Tutti i figli, inclusa la placeholder
+ const children = Array.from(folderEl.children);
+ const finalIndex = children.indexOf(placeholderEl);
- // Calcola punto centrale dell’icona trascinata
- const left = parseFloat(icon.style.left) || 0;
- const top = parseFloat(icon.style.top) || 0;
- const dropXClient = left + icon.offsetWidth / 2;
- const dropYClient = top + icon.offsetHeight / 2;
+ // Ripristina icona visuale
+ draggingIcon.classList.remove("dragging");
+ draggingIcon.style.position = "";
+ draggingIcon.style.left = "";
+ draggingIcon.style.top = "";
+ draggingIcon.style.width = "";
+ draggingIcon.style.height = "";
+ draggingIcon.style.zIndex = "";
+ draggingIcon.style.pointerEvents = "";
+ draggingIcon.style.transform = "";
- const elem = document.elementFromPoint(dropXClient, dropYClient);
- const targetIcon = elem && elem.closest(".app-icon:not(.dragging)");
-
- if (targetIcon) {
- const from = appsOrder.indexOf(icon.dataset.id);
- const to = appsOrder.indexOf(targetIcon.dataset.id);
-
- if (from !== -1 && to !== -1 && from !== to) {
- appsOrder.splice(from, 1);
- appsOrder.splice(to, 0, icon.dataset.id);
+ if (finalIndex !== -1) {
+ const currentIndex = appsOrder.indexOf(draggingId);
+ if (currentIndex !== -1 && currentIndex !== finalIndex) {
+ appsOrder.splice(currentIndex, 1);
+ appsOrder.splice(finalIndex, 0, draggingId);
saveOrder();
}
}
- // Ripristina icona
- icon.classList.remove("dragging");
- icon.style.position = "";
- icon.style.left = "";
- icon.style.top = "";
- icon.style.width = "";
- icon.style.height = "";
- icon.style.zIndex = "";
- icon.style.pointerEvents = "";
- icon.style.transform = "";
+ if (placeholderEl && placeholderEl.parentNode) {
+ placeholderEl.parentNode.removeChild(placeholderEl);
+ }
+ draggingIcon = null;
+ placeholderEl = null;
+ dragStartX = 0;
+ dragStartY = 0;
+
+ // Ridisegna in base al nuovo ordine
renderApps();
}
@@ -764,9 +763,7 @@ function endDrag() {
// ---------------------------------------------------------------------------
function initDragHandlers() {
- // ---------------------------------------------------------
- // TOUCH DRAG
- // ---------------------------------------------------------
+ // TOUCH DRAG
document.addEventListener("touchstart", e => {
if (!editMode) return;
if (e.touches.length !== 1) return;
@@ -788,7 +785,6 @@ function initDragHandlers() {
const pos = getPointerPosition(e);
- // Inizio drag
if (!draggingIcon) {
const dx = pos.clientX - dragStartX;
const dy = pos.clientY - dragStartY;
@@ -811,14 +807,17 @@ function initDragHandlers() {
document.addEventListener("touchend", e => {
if (!editMode) return;
- if (draggingIcon && (!e.touches || e.touches.length === 0)) {
+ if (!draggingIcon) {
+ dragStartX = 0;
+ dragStartY = 0;
+ return;
+ }
+ if (!e.touches || e.touches.length === 0) {
endDrag();
}
}, { passive: true });
- // ---------------------------------------------------------
- // MOUSE DRAG
- // ---------------------------------------------------------
+ // MOUSE DRAG
document.addEventListener("mousedown", e => {
if (!editMode) return;
if (e.button !== 0) return;
@@ -862,54 +861,19 @@ function initDragHandlers() {
document.addEventListener("mouseup", () => {
if (!editMode) return;
- dragStartX = 0;
- dragStartY = 0;
- if (draggingIcon) {
- endDrag();
- }
- draggingIcon = null;
- draggingId = null;
- });
-
- document.addEventListener("mousemove", e => {
- if (!editMode) return;
-
- const pos = getPointerPosition(e);
-
if (!draggingIcon) {
- if (!dragStartX && !dragStartY) return;
-
- const dx = pos.clientX - dragStartX;
- const dy = pos.clientY - dragStartY;
- if (Math.hypot(dx, dy) > 10) {
- const icon = e.target.closest(".app-icon");
- if (icon) {
- if (longPressTimer) {
- clearTimeout(longPressTimer);
- longPressTimer = null;
- longPressTarget = null;
- }
- startDrag(icon, pos);
- }
- }
- } else {
- updateDragPosition(pos);
- }
- });
-
- document.addEventListener("mouseup", () => {
- if (!editMode) return;
- dragStartX = 0;
- dragStartY = 0;
- if (draggingIcon) {
- endDrag();
+ dragStartX = 0;
+ dragStartY = 0;
+ return;
}
+ endDrag();
});
}
-// ============================================================================
-// LAUNCHER — VERSIONE COMPLETA E OTTIMIZZATA (A) — BLOCCO 6/6 (FINALE)
-// Sezione: Context Menu Actions + Config Save + Init Globale
+// ============================================================================
+// LAUNCHER — VERSIONE COMPLETA E
+// OTTIMIZZATA (A) BLOCCO 6/6 — Context Menu
+// Actions + Config Save + Init Globale
// ============================================================================
// ---------------------------------------------------------------------------
@@ -970,19 +934,17 @@ function initContextMenuActions() {
// ---------------------------------------------------------------------------
document.getElementById("cfg-refresh").addEventListener("click", async () => {
- // Carica config attuale
const cfg = loadConfig();
if (!cfg) {
alert("Config mancante. Inserisci URL, user e password.");
return;
}
- // Aggiorna apps dal server
const ok = await getLinks();
if (ok) {
hideSetupPage();
- startLauncher(); // Ritorna subito alla schermata principale
+ startLauncher(); // Torna subito alla schermata principale
} else {
alert("Impossibile aggiornare le app dal server.");
}
@@ -996,16 +958,12 @@ document.getElementById("cfg-save").addEventListener("click", async () => {
const user = document.getElementById("cfg-user").value;
const pass = document.getElementById("cfg-pass").value;
- // Salva configurazione
saveConfig(url, user, pass);
- // Scarica apps dal server
const ok = await getLinks();
if (ok) {
hideSetupPage();
-
- // Restart completo del launcher
startLauncher();
}
});
@@ -1017,10 +975,8 @@ document.addEventListener("DOMContentLoaded", () => {
const cfg = loadConfig();
if (!cfg) {
- // Primo avvio → mostra setup
showSetupPage();
} else {
- // Config presente → avvia launcher
hideSetupPage();
startLauncher();
}
diff --git a/app/index.html b/app/index.html
index f946b1d..ba09ee9 100644
--- a/app/index.html
+++ b/app/index.html
@@ -40,9 +40,9 @@
-
-->
+