Merge branch 'dev'
This commit is contained in:
commit
d04b38b1c1
|
|
@ -3960,6 +3960,132 @@
|
||||||
syncBottomToolbar();
|
syncBottomToolbar();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ── Recent tools + Favorites (+) menu ──
|
||||||
|
const recentToolsEl = document.getElementById("recent-tools");
|
||||||
|
const recentSep = document.getElementById("recent-sep");
|
||||||
|
const toolPlusMenu = document.getElementById("tool-plus-menu");
|
||||||
|
const toolPlusBtn = document.getElementById("tool-plus");
|
||||||
|
|
||||||
|
// Recent tools: track last 2 sidebar tools used (not basic canvas tools)
|
||||||
|
let recentTools = JSON.parse(localStorage.getItem("rspace_recent_tools") || "[]");
|
||||||
|
// Pinned favorites
|
||||||
|
let pinnedTools = JSON.parse(localStorage.getItem("rspace_pinned_tools") || "[]");
|
||||||
|
|
||||||
|
// Tool registry: maps sidebar button IDs to display info
|
||||||
|
const sidebarToolRegistry = {};
|
||||||
|
document.querySelectorAll("#toolbar .toolbar-dropdown button").forEach(btn => {
|
||||||
|
sidebarToolRegistry[btn.id] = {
|
||||||
|
id: btn.id,
|
||||||
|
label: btn.textContent.trim(),
|
||||||
|
title: btn.title || btn.textContent.trim(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
// Add direct sidebar buttons too
|
||||||
|
["new-feed", "toggle-memory", "toggle-hide-forgotten", "feed-toggle"].forEach(id => {
|
||||||
|
const btn = document.getElementById(id);
|
||||||
|
if (btn) sidebarToolRegistry[id] = { id, label: btn.textContent.trim(), title: btn.title || btn.textContent.trim() };
|
||||||
|
});
|
||||||
|
|
||||||
|
function trackRecentTool(toolId) {
|
||||||
|
if (!toolId || !sidebarToolRegistry[toolId]) return;
|
||||||
|
// Don't track if it's already pinned
|
||||||
|
if (pinnedTools.includes(toolId)) return;
|
||||||
|
recentTools = recentTools.filter(t => t !== toolId);
|
||||||
|
recentTools.unshift(toolId);
|
||||||
|
recentTools = recentTools.slice(0, 2);
|
||||||
|
localStorage.setItem("rspace_recent_tools", JSON.stringify(recentTools));
|
||||||
|
renderRecentTools();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderRecentTools() {
|
||||||
|
recentToolsEl.innerHTML = "";
|
||||||
|
// Show pinned first, then recent (excluding pinned)
|
||||||
|
const shown = [...pinnedTools, ...recentTools.filter(t => !pinnedTools.includes(t))].slice(0, 4);
|
||||||
|
if (shown.length > 0) recentSep.style.display = "";
|
||||||
|
else recentSep.style.display = "none";
|
||||||
|
|
||||||
|
for (const toolId of shown) {
|
||||||
|
const info = sidebarToolRegistry[toolId];
|
||||||
|
if (!info) continue;
|
||||||
|
const btn = document.createElement("button");
|
||||||
|
btn.className = "recent-tool-btn";
|
||||||
|
btn.title = info.title;
|
||||||
|
btn.textContent = info.label.split(" ")[0]; // emoji only
|
||||||
|
btn.addEventListener("click", (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
document.getElementById(toolId)?.click();
|
||||||
|
});
|
||||||
|
recentToolsEl.appendChild(btn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track clicks on sidebar tool buttons
|
||||||
|
document.querySelectorAll("#toolbar .toolbar-dropdown button, #toolbar-panel-body button").forEach(btn => {
|
||||||
|
btn.addEventListener("click", () => trackRecentTool(btn.id));
|
||||||
|
});
|
||||||
|
// Intercept panel button clicks for tracking (cloned dynamically)
|
||||||
|
document.getElementById("toolbar-panel-body")?.addEventListener("click", (e) => {
|
||||||
|
const btn = e.target.closest("button");
|
||||||
|
if (btn && btn.id) trackRecentTool(btn.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// [+] menu: show all sidebar tools, allow pinning
|
||||||
|
toolPlusBtn.addEventListener("click", (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
toolPlusMenu.classList.toggle("open");
|
||||||
|
if (toolPlusMenu.classList.contains("open")) renderPlusMenu();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("click", (e) => {
|
||||||
|
if (!e.target.closest(".tool-plus-wrap")) {
|
||||||
|
toolPlusMenu.classList.remove("open");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function renderPlusMenu() {
|
||||||
|
toolPlusMenu.innerHTML = "";
|
||||||
|
|
||||||
|
// Group tools by their toolbar group
|
||||||
|
const groups = document.querySelectorAll("#toolbar .toolbar-group");
|
||||||
|
for (const group of groups) {
|
||||||
|
const toggle = group.querySelector(".toolbar-group-toggle");
|
||||||
|
const dropdown = group.querySelector(".toolbar-dropdown");
|
||||||
|
if (!toggle || !dropdown) continue;
|
||||||
|
|
||||||
|
const heading = document.createElement("div");
|
||||||
|
heading.className = "menu-heading";
|
||||||
|
heading.textContent = toggle.textContent.trim();
|
||||||
|
toolPlusMenu.appendChild(heading);
|
||||||
|
|
||||||
|
for (const origBtn of dropdown.querySelectorAll("button")) {
|
||||||
|
const toolId = origBtn.id;
|
||||||
|
if (!toolId) continue;
|
||||||
|
const info = sidebarToolRegistry[toolId];
|
||||||
|
if (!info) continue;
|
||||||
|
|
||||||
|
const btn = document.createElement("button");
|
||||||
|
btn.className = pinnedTools.includes(toolId) ? "pinned" : "";
|
||||||
|
btn.innerHTML = `<span>${info.label}</span><span class="pin-icon">📌</span>`;
|
||||||
|
btn.addEventListener("click", (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (pinnedTools.includes(toolId)) {
|
||||||
|
pinnedTools = pinnedTools.filter(t => t !== toolId);
|
||||||
|
} else {
|
||||||
|
pinnedTools.push(toolId);
|
||||||
|
if (pinnedTools.length > 4) pinnedTools.shift();
|
||||||
|
}
|
||||||
|
localStorage.setItem("rspace_pinned_tools", JSON.stringify(pinnedTools));
|
||||||
|
renderRecentTools();
|
||||||
|
renderPlusMenu();
|
||||||
|
});
|
||||||
|
toolPlusMenu.appendChild(btn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial render
|
||||||
|
renderRecentTools();
|
||||||
|
|
||||||
// Whiteboard pointer handlers on the SVG overlay
|
// Whiteboard pointer handlers on the SVG overlay
|
||||||
wbOverlay.addEventListener("pointerdown", (e) => {
|
wbOverlay.addEventListener("pointerdown", (e) => {
|
||||||
if (!wbTool || wbTool === "eraser") {
|
if (!wbTool || wbTool === "eraser") {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue