Merge branch 'dev'

This commit is contained in:
Jeff Emmett 2026-03-03 14:39:36 -08:00
commit 8085ea3f85
1 changed files with 23 additions and 87 deletions

View File

@ -1809,8 +1809,7 @@
<span class="toolbar-sep"></span>
<button id="new-feed" title="New Feed from another layer">🔄 Feed</button>
<button id="toggle-memory" title="Forgotten rSpaces">💭 Memory</button>
<button id="toggle-memory" title="Recent Changes">💭 Recent Changes</button>
<button id="toggle-hide-forgotten" title="Hide forgotten items">👁 Hide Faded</button>
<button id="feed-toggle" title="Toggle feed view">📋 Feed View</button>
@ -1857,9 +1856,6 @@
<button class="tool-btn" id="tool-text" title="Note (T)">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="4 7 4 4 20 4 20 7"/><line x1="12" y1="4" x2="12" y2="20"/><line x1="8" y1="20" x2="16" y2="20"/></svg>
</button>
<button class="tool-btn" id="tool-arrow" title="Connect (A)">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="19" x2="19" y2="5"/><polyline points="12 5 19 5 19 12"/></svg>
</button>
<span class="tool-sep"></span>
<button class="tool-btn" id="tool-eraser" title="Eraser (E)">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 20H7L3 16a1 1 0 010-1.4l9.6-9.6a1 1 0 011.4 0l7 7a1 1 0 010 1.4L15 20"/><line x1="18" y1="13" x2="11" y2="6"/></svg>
@ -1877,7 +1873,7 @@
<div id="memory-panel">
<div id="memory-panel-header">
<h3>💭 Memory</h3>
<h3>💭 Recent Changes</h3>
<span class="count" id="memory-count">0</span>
</div>
<div id="memory-list"></div>
@ -3359,7 +3355,6 @@
if (pendingTool) clearPendingTool();
if (connectMode) {
connectMode = false;
newArrowBtn?.classList.remove("active");
canvas.classList.remove("connect-mode");
if (connectSource) { connectSource.classList.remove("connect-source"); connectSource = null; }
}
@ -3377,7 +3372,7 @@
else if (key === "c") { document.getElementById("tool-circle")?.click(); }
else if (key === "s") { document.getElementById("tool-sticky")?.click(); }
else if (key === "t") { document.getElementById("tool-text")?.click(); }
else if (key === "a") { document.getElementById("tool-arrow")?.click(); }
else if (key === "a") { toggleConnectMode(); }
else if (key === "e") { document.getElementById("tool-eraser")?.click(); }
});
@ -3733,71 +3728,20 @@
}
// Feed shape — pull live data from another layer/module
document.getElementById("new-feed").addEventListener("click", () => {
// Prompt for source module (simple for now — will get a proper UI)
const modules = ["notes", "funds", "vote", "choices", "wallet", "data", "work", "network", "trips"];
const sourceModule = prompt("Feed from which rApp?\n\n" + modules.join(", "), "notes");
if (!sourceModule || !modules.includes(sourceModule)) return;
// Pick flow kind based on module defaults
const moduleFlowKinds = {
funds: "economic", wallet: "economic", trips: "economic",
vote: "governance", choices: "governance",
network: "trust",
data: "attention",
notes: "data", work: "data",
};
const flowKind = moduleFlowKinds[sourceModule] || "data";
setPendingTool("folk-feed", {
sourceModule,
sourceLayer: "layer-" + sourceModule,
feedId: "",
flowKind,
maxItems: 10,
refreshInterval: 30000,
__postCreate: (shape) => {
// Auto-register a LayerFlow in Automerge if layers exist
if (sync.getLayers) {
const layers = sync.getLayers();
const currentLayer = layers.find(l => l.moduleId === "rspace") || layers[0];
const sourceLayer = layers.find(l => l.moduleId === sourceModule);
if (currentLayer && sourceLayer) {
const flowId = `flow-auto-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
sync.addFlow({
id: flowId,
kind: flowKind,
sourceLayerId: sourceLayer.id,
targetLayerId: currentLayer.id,
targetShapeId: shape.id,
label: sourceModule + " feed",
strength: 0.5,
active: true,
});
}
// Also ensure source module has a layer (add if missing)
if (!sourceLayer) {
sync.addLayer({
id: "layer-" + sourceModule,
moduleId: sourceModule,
label: sourceModule,
order: layers.length,
color: "",
visible: true,
createdAt: Date.now(),
});
}
}
},
});
});
// Arrow connection mode
let connectMode = false;
let connectSource = null;
const newArrowBtn = document.getElementById("tool-arrow");
function toggleConnectMode() {
if (wbTool) setWbTool(null);
if (pendingTool) clearPendingTool();
connectMode = !connectMode;
canvas.classList.toggle("connect-mode", connectMode);
if (!connectMode && connectSource) {
connectSource.classList.remove("connect-source");
connectSource = null;
}
if (typeof syncBottomToolbar === "function") syncBottomToolbar();
}
// Handle shape clicks for connection mode
canvas.addEventListener("click", (e) => {
@ -3830,7 +3774,6 @@
connectSource.classList.remove("connect-source");
connectSource = null;
connectMode = false;
newArrowBtn.classList.remove("active");
canvas.classList.remove("connect-mode");
if (typeof syncBottomToolbar === "function") syncBottomToolbar();
}
@ -3878,7 +3821,7 @@
const map = { pencil: "tool-pencil", line: "tool-line", rect: "tool-rect", circle: "tool-circle", eraser: "tool-eraser" };
document.getElementById(map[wbTool])?.classList.add("active");
} else if (connectMode) {
document.getElementById("tool-arrow")?.classList.add("active");
// Connect mode active (no toolbar button — toggled via 'A' key)
} else if (pendingTool) {
// Check if pending tool maps to a bottom toolbar button
if (pendingTool.tagName === "folk-markdown" && pendingTool.props?.__postCreate) {
@ -3898,7 +3841,6 @@
if (pendingTool) clearPendingTool();
if (connectMode) {
connectMode = false;
newArrowBtn.classList.remove("active");
canvas.classList.remove("connect-mode");
if (connectSource) { connectSource.classList.remove("connect-source"); connectSource = null; }
}
@ -3947,19 +3889,6 @@
syncBottomToolbar();
});
document.getElementById("tool-arrow").addEventListener("click", () => {
if (wbTool) setWbTool(null);
if (pendingTool) clearPendingTool();
connectMode = !connectMode;
newArrowBtn.classList.toggle("active", connectMode);
canvas.classList.toggle("connect-mode", connectMode);
if (!connectMode && connectSource) {
connectSource.classList.remove("connect-source");
connectSource = null;
}
syncBottomToolbar();
});
// ── Recent tools + Favorites (+) menu ──
const recentToolsEl = document.getElementById("recent-tools");
const recentSep = document.getElementById("recent-sep");
@ -3981,7 +3910,7 @@
};
});
// Add direct sidebar buttons too
["new-feed", "toggle-memory", "toggle-hide-forgotten", "feed-toggle"].forEach(id => {
["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() };
});
@ -5130,6 +5059,7 @@
// ── Feed Mode ──
let feedMode = false;
let feedSortKey = 'y';
let feedOriginalOrder = [];
const feedToggleBtn = document.getElementById('feed-toggle');
const feedSortBar = document.getElementById('feed-sort-bar');
const feedSortSelect = document.getElementById('feed-sort');
@ -5140,7 +5070,13 @@
feedToggleBtn.classList.toggle('active', feedMode);
feedSortBar.classList.toggle('hidden', !feedMode);
if (feedMode) {
// Save original DOM order before reordering
feedOriginalOrder = [...canvasContent.children];
sortFeedShapes(feedSortKey);
} else {
// Restore original DOM order
for (const el of feedOriginalOrder) canvasContent.appendChild(el);
feedOriginalOrder = [];
}
}