From 44af6ae061a5c76de41d3b662822c6f0c10ec3ce Mon Sep 17 00:00:00 2001 From: Kibi Kelburton Date: Sun, 26 Jul 2026 20:45:16 +0200 Subject: [PATCH] mobile default tab selection --- public/s/js/comments.js | 71 +++++++++++++++++++++++++++-------- public/s/js/messages.js | 83 +++++++++++++++++++++++++++++++++++------ 2 files changed, 127 insertions(+), 27 deletions(-) diff --git a/public/s/js/comments.js b/public/s/js/comments.js index 5dfeb0f..e25af9d 100644 --- a/public/s/js/comments.js +++ b/public/s/js/comments.js @@ -4459,20 +4459,71 @@ class CommentSystem { }, { passive: true }); }; - // Helper: reliable touch handling for tab buttons on mobile - const addTabTouch = (btn, cb) => { + // Helper: reliable touch handling for tab buttons on mobile (supports hold-to-action) + let lastHoldTime = 0; + const addTabTouch = (btn, cb, onHold) => { let ts = null; + let holdTimer = null; + let holdFired = false; btn.addEventListener('touchstart', (e) => { + holdFired = false; ts = { x: e.touches[0].clientX, y: e.touches[0].clientY }; + if (onHold) { + holdTimer = setTimeout(() => { + holdFired = true; + lastHoldTime = Date.now(); + try { navigator.vibrate?.(40); } catch(err) {} + onHold(); + }, 500); + } e.stopPropagation(); }, { passive: true }); + + btn.addEventListener('touchmove', (e) => { + if (!ts) return; + const dx = Math.abs(e.touches[0].clientX - ts.x); + const dy = Math.abs(e.touches[0].clientY - ts.y); + if (dx > 10 || dy > 10) { + clearTimeout(holdTimer); + ts = null; + } + }, { passive: true }); + btn.addEventListener('touchend', (e) => { + clearTimeout(holdTimer); + if (holdFired) { + e.preventDefault(); + e.stopPropagation(); + holdFired = false; + ts = null; + return; + } if (!ts) return; const dx = Math.abs(e.changedTouches[0].clientX - ts.x); const dy = Math.abs(e.changedTouches[0].clientY - ts.y); ts = null; if (dx < 10 && dy < 10) { e.preventDefault(); cb(); } }); + + btn.addEventListener('touchcancel', () => { + clearTimeout(holdTimer); + holdFired = false; + ts = null; + }); + }; + + const toggleFavDefault = (tabEl) => { + const KEY = 'f0ck_emoji_default_tab'; + const isDefault = localStorage.getItem(KEY) === '__favs__'; + if (isDefault) { + localStorage.removeItem(KEY); + tabEl.classList.remove('ep-tab-default'); + window._showEmojiToast?.('Favorites unset as default tab'); + } else { + localStorage.setItem(KEY, '__favs__'); + tabEl.classList.add('ep-tab-default'); + window._showEmojiToast?.('Favorites set as default tab'); + } }; // Build tab buttons — Favorites first @@ -4484,23 +4535,13 @@ class CommentSystem { favTab.innerHTML = ''; favTab.addEventListener('mousedown', e => e.preventDefault()); favTab.addEventListener('click', () => showTab('__favs__')); - addTabTouch(favTab, () => showTab('__favs__')); + addTabTouch(favTab, () => showTab('__favs__'), () => toggleFavDefault(favTab)); // Right-click on fav tab → set/unset as default favTab.addEventListener('contextmenu', (e) => { e.preventDefault(); e.stopPropagation(); - if (navigator.maxTouchPoints > 0) return; - const KEY = 'f0ck_emoji_default_tab'; - const isDefault = localStorage.getItem(KEY) === '__favs__'; - if (isDefault) { - localStorage.removeItem(KEY); - favTab.classList.remove('ep-tab-default'); - window._showEmojiToast?.('Favorites unset as default tab'); - } else { - localStorage.setItem(KEY, '__favs__'); - favTab.classList.add('ep-tab-default'); - window._showEmojiToast?.('Favorites set as default tab'); - } + if (Date.now() - lastHoldTime < 1000) return; + toggleFavDefault(favTab); }); // Mark as default if already set if (localStorage.getItem('f0ck_emoji_default_tab') === '__favs__') { diff --git a/public/s/js/messages.js b/public/s/js/messages.js index 47be836..df448eb 100644 --- a/public/s/js/messages.js +++ b/public/s/js/messages.js @@ -1976,6 +1976,73 @@ if (window.__dmLoaded) { dmGridArea = document.createElement('div'); dmGridArea.className = 'emoji-picker-grid'; + // Helper: reliable touch handling for tab buttons on mobile (supports hold-to-action) + let lastDmHoldTime = 0; + const addDmTabTouch = (btn, cb, onHold) => { + let ts = null; + let holdTimer = null; + let holdFired = false; + btn.addEventListener('touchstart', (e) => { + holdFired = false; + ts = { x: e.touches[0].clientX, y: e.touches[0].clientY }; + if (onHold) { + holdTimer = setTimeout(() => { + holdFired = true; + lastDmHoldTime = Date.now(); + try { navigator.vibrate?.(40); } catch(err) {} + onHold(); + }, 500); + } + e.stopPropagation(); + }, { passive: true }); + + btn.addEventListener('touchmove', (e) => { + if (!ts) return; + const dx = Math.abs(e.touches[0].clientX - ts.x); + const dy = Math.abs(e.touches[0].clientY - ts.y); + if (dx > 10 || dy > 10) { + clearTimeout(holdTimer); + ts = null; + } + }, { passive: true }); + + btn.addEventListener('touchend', (e) => { + clearTimeout(holdTimer); + if (holdFired) { + e.preventDefault(); + e.stopPropagation(); + holdFired = false; + ts = null; + return; + } + if (!ts) return; + const dx = Math.abs(e.changedTouches[0].clientX - ts.x); + const dy = Math.abs(e.changedTouches[0].clientY - ts.y); + ts = null; + if (dx < 10 && dy < 10) { e.preventDefault(); cb(); } + }); + + btn.addEventListener('touchcancel', () => { + clearTimeout(holdTimer); + holdFired = false; + ts = null; + }); + }; + + const toggleDmFavDefault = (tabEl) => { + const KEY = 'f0ck_emoji_default_tab'; + const isDefault = localStorage.getItem(KEY) === '__favs__'; + if (isDefault) { + localStorage.removeItem(KEY); + tabEl.classList.remove('ep-tab-default'); + window._showEmojiToast?.('Favorites unset as default tab'); + } else { + localStorage.setItem(KEY, '__favs__'); + tabEl.classList.add('ep-tab-default'); + window._showEmojiToast?.('Favorites set as default tab'); + } + }; + // ── Favorites tab ── const favsTab = document.createElement('button'); favsTab.className = 'ep-tab ep-tab-favs'; @@ -1985,22 +2052,13 @@ if (window.__dmLoaded) { favsTab.innerHTML = ''; favsTab.addEventListener('mousedown', e => e.preventDefault()); favsTab.addEventListener('click', () => showDmTab('__favs__', packs)); + addDmTabTouch(favsTab, () => showDmTab('__favs__', packs), () => toggleDmFavDefault(favsTab)); // Right-click on fav tab → set/unset as default favsTab.addEventListener('contextmenu', (e) => { e.preventDefault(); e.stopPropagation(); - if (navigator.maxTouchPoints > 0) return; - const KEY = 'f0ck_emoji_default_tab'; - const isDefault = localStorage.getItem(KEY) === '__favs__'; - if (isDefault) { - localStorage.removeItem(KEY); - favsTab.classList.remove('ep-tab-default'); - window._showEmojiToast?.('Favorites unset as default tab'); - } else { - localStorage.setItem(KEY, '__favs__'); - favsTab.classList.add('ep-tab-default'); - window._showEmojiToast?.('Favorites set as default tab'); - } + if (Date.now() - lastDmHoldTime < 1000) return; + toggleDmFavDefault(favsTab); }); // Mark as default if already set if (localStorage.getItem('f0ck_emoji_default_tab') === '__favs__') { @@ -2028,6 +2086,7 @@ if (window.__dmLoaded) { } tab.addEventListener('mousedown', e => e.preventDefault()); tab.addEventListener('click', () => showDmTab(pack.id ?? null, packs)); + addDmTabTouch(tab, () => showDmTab(pack.id ?? null, packs)); dmTabBar.appendChild(tab); }); -- 2.50.1