Merge branch 'dev'

This commit is contained in:
Jeff Emmett 2026-03-03 13:24:47 -08:00
commit 9ac80c00eb
1 changed files with 58 additions and 8 deletions

View File

@ -2205,8 +2205,39 @@
}
}
// Non-blocking: check trip availability after page settles
setTimeout(updateTravelToolbarState, 1500);
// ── Notes data cache for toolbar awareness ──
let _notesCache = null; // { notes: [], fetchedAt: 0 }
async function fetchNotesData() {
if (_notesCache && Date.now() - _notesCache.fetchedAt < TRIP_CACHE_TTL) return _notesCache;
try {
const res = await fetch(`/${communitySlug}/rnotes/api/notes?limit=50`);
if (!res.ok) return { notes: [], fetchedAt: Date.now() };
const data = await res.json();
_notesCache = { notes: data.notes || [], fetchedAt: Date.now() };
return _notesCache;
} catch { return { notes: [], fetchedAt: Date.now() }; }
}
const NOTE_BTN_IDS = ["new-markdown", "new-obs-note"];
async function updateNoteToolbarState() {
const data = await fetchNotesData();
const hasNotes = data.notes.length > 0;
for (const id of NOTE_BTN_IDS) {
const btn = document.getElementById(id);
if (btn) {
btn.classList.toggle("toolbar-disabled", !hasNotes);
if (!hasNotes) btn.title = "No notes yet — create notes in rNotes first";
}
}
}
// Non-blocking: check data availability after page settles
setTimeout(() => {
updateTravelToolbarState();
updateNoteToolbarState();
}, 1500);
// Initialize Presence for real-time cursors
const peerId = generatePeerId();
@ -3170,8 +3201,15 @@
installSelectionTransforms();
// Toolbar button handlers — set pending tool for click-to-place
document.getElementById("new-markdown").addEventListener("click", () => {
setPendingTool("folk-markdown", { content: "# New Note\n\nStart typing..." });
document.getElementById("new-markdown").addEventListener("click", async () => {
const data = await fetchNotesData();
if (data.notes.length === 0) {
setPendingTool("folk-markdown", { content: "# New Note\n\nStart typing..." });
return;
}
const note = pickFromList(data.notes, n => n.title || "Untitled", "Select a note");
if (!note) return;
setPendingTool("folk-markdown", { content: note.content || `# ${note.title}\n\n${note.content_plain || ""}` });
});
document.getElementById("new-wrapper").addEventListener("click", () => {
@ -3210,7 +3248,19 @@
document.getElementById("new-prompt").addEventListener("click", () => setPendingTool("folk-prompt"));
document.getElementById("new-transcription").addEventListener("click", () => setPendingTool("folk-transcription"));
document.getElementById("new-video-chat").addEventListener("click", () => setPendingTool("folk-video-chat"));
document.getElementById("new-obs-note").addEventListener("click", () => setPendingTool("folk-obs-note"));
document.getElementById("new-obs-note").addEventListener("click", async () => {
const data = await fetchNotesData();
if (data.notes.length === 0) {
setPendingTool("folk-obs-note");
return;
}
const note = pickFromList(data.notes, n => n.title || "Untitled", "Select a note");
if (!note) return;
setPendingTool("folk-obs-note", {
title: note.title || "Untitled",
content: note.content || note.content_plain || "",
});
});
document.getElementById("new-workflow").addEventListener("click", () => {
setPendingTool("folk-workflow-block", {
blockType: "trigger",
@ -3868,7 +3918,7 @@
}
canvasContent.addEventListener("contextmenu", (e) => {
const shapeEl = e.target.closest("folk-shape, folk-markdown, folk-wrapper, folk-slide, folk-chat, folk-embed, folk-calendar, folk-map, folk-image-gen, folk-video-gen, folk-prompt, folk-zine-gen, folk-transcription, folk-video-chat, folk-obs-note, folk-workflow-block, folk-itinerary, folk-destination, folk-budget, folk-packing-list, folk-booking, folk-token-mint, folk-token-ledger, folk-choice-vote, folk-choice-rank, folk-choice-spider, folk-social-post, folk-rapp, folk-feed, folk-piano, folk-splat, folk-blender, folk-drawfast, folk-freecad, folk-kicad");
const shapeEl = e.target.closest("folk-shape, folk-markdown, folk-wrapper, folk-slide, folk-chat, folk-embed, folk-calendar, folk-map, folk-image-gen, folk-video-gen, folk-prompt, folk-zine-gen, folk-transcription, folk-video-chat, folk-obs-note, folk-workflow-block, folk-itinerary, folk-destination, folk-budget, folk-packing-list, folk-booking, folk-token-mint, folk-token-ledger, folk-choice-vote, folk-choice-rank, folk-choice-spider, folk-choice-conviction, folk-social-post, folk-rapp, folk-feed, folk-piano, folk-splat, folk-blender, folk-drawfast, folk-freecad, folk-kicad");
if (!shapeEl || !shapeEl.id) return;
e.preventDefault();
@ -4004,7 +4054,7 @@
"folk-budget": "💰", "folk-packing-list": "🎒", "folk-booking": "✈️",
"folk-token-mint": "🪙", "folk-token-ledger": "📒",
"folk-choice-vote": "☑", "folk-choice-rank": "📊",
"folk-choice-spider": "🕸", "folk-social-post": "📱",
"folk-choice-spider": "🕸", "folk-choice-conviction": "⏳", "folk-social-post": "📱",
"folk-splat": "🔮", "folk-blender": "🧊", "folk-drawfast": "✏️",
"folk-freecad": "📐", "folk-kicad": "🔌",
"folk-rapp": "📱", "folk-feed": "🔄", "folk-arrow": "↗️",
@ -4717,7 +4767,7 @@
function sortFeedShapes(key) {
const shapes = [...canvasContent.querySelectorAll(
'folk-shape, folk-markdown, folk-wrapper, folk-slide, folk-chat, folk-obs-note, folk-rapp, folk-embed, folk-drawfast, folk-prompt, folk-zine-gen, folk-workflow-block, folk-choice-vote, folk-choice-rank, folk-choice-spider, folk-token, folk-google-item, folk-social-post, folk-calendar, folk-map, folk-piano, folk-splat, folk-video-chat, folk-transcription, folk-image-gen, folk-video-gen, folk-zine-gen, folk-blender, folk-freecad, folk-kicad, folk-itinerary, folk-destination, folk-budget, folk-packing-list, folk-booking'
'folk-shape, folk-markdown, folk-wrapper, folk-slide, folk-chat, folk-obs-note, folk-rapp, folk-embed, folk-drawfast, folk-prompt, folk-zine-gen, folk-workflow-block, folk-choice-vote, folk-choice-rank, folk-choice-spider, folk-choice-conviction, folk-token, folk-google-item, folk-social-post, folk-calendar, folk-map, folk-piano, folk-splat, folk-video-chat, folk-transcription, folk-image-gen, folk-video-gen, folk-zine-gen, folk-blender, folk-freecad, folk-kicad, folk-itinerary, folk-destination, folk-budget, folk-packing-list, folk-booking'
)];
shapes.sort((a, b) => {