mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
d5e0ff6fe6
* feat: Octarine notes integration + auto-save for all integrations Add Octarine as a third notes app integration alongside Obsidian and Bear. Uses the octarine:// URI scheme to create notes via deep links, following the same x-callback-url pattern as Bear. - New file: packages/ui/utils/octarine.ts (cookie-backed settings) - Server: saveToOctarine() in integrations.ts, wired into /api/approve and /api/save-notes endpoints - UI: Octarine tab in Settings, card in Export > Notes, dropdown button, Cmd+S shortcut support - Parallelize all integration saves with Promise.allSettled (was sequential) - Add auto-save on plan arrival toggle to Bear and Octarine (Obsidian already had this), consolidate into a single effect + single API call Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add YAML frontmatter properties to Octarine notes Prepend Octarine-compatible YAML frontmatter with tags, Status, Author, and Last Edited properties. Uses the same extractTags() as Obsidian for auto-generated tags (project name, title words, code fence languages). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use fresh=true for Octarine saves to prevent content duplication Octarine's create action appends by default. If auto-save fires on plan arrival and the user then approves within the same minute, the same path gets hit twice — doubling the content. Using fresh=true replaces instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: trim workspace and folder in saveToOctarine before building URI The UI checks workspace.trim().length > 0 but the server used raw values. Accidental whitespace in settings would cause Octarine saves to fail. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use isOctarineConfigured() for client-side Octarine guards Auto-save and approve checks used raw workspace truthiness, so whitespace-only workspace would trigger a save attempt that the server rejects. Now uses isOctarineConfigured() which trims before checking. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: prevent Bear duplicate notes and align default-save dropdown gates Bear creates a new note on every save, so skip it on approve when arrival auto-save already succeeded. Gate the default-save dropdown by actual configuration (vault path for Obsidian, workspace for Octarine) instead of just the enabled toggle, matching the shortcut behavior. Self-heal stale defaults back to "ask". Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
54 lines
1.6 KiB
TypeScript
54 lines
1.6 KiB
TypeScript
/**
|
|
* Octarine Notes Integration Utility
|
|
*
|
|
* Manages settings for auto-saving plans to Octarine.
|
|
* Uses octarine:// URI scheme — no vault detection needed.
|
|
*/
|
|
|
|
import { storage } from './storage';
|
|
|
|
const STORAGE_KEY_ENABLED = 'plannotator-octarine-enabled';
|
|
const STORAGE_KEY_WORKSPACE = 'plannotator-octarine-workspace';
|
|
const STORAGE_KEY_FOLDER = 'plannotator-octarine-folder';
|
|
const STORAGE_KEY_AUTOSAVE = 'plannotator-octarine-autosave';
|
|
|
|
/**
|
|
* Octarine integration settings
|
|
*/
|
|
export interface OctarineSettings {
|
|
enabled: boolean;
|
|
workspace: string;
|
|
folder: string;
|
|
autoSave: boolean;
|
|
}
|
|
|
|
/**
|
|
* Get current Octarine settings from storage
|
|
*/
|
|
export function getOctarineSettings(): OctarineSettings {
|
|
return {
|
|
enabled: storage.getItem(STORAGE_KEY_ENABLED) === 'true',
|
|
workspace: storage.getItem(STORAGE_KEY_WORKSPACE) ?? '',
|
|
folder: storage.getItem(STORAGE_KEY_FOLDER) || 'plannotator',
|
|
autoSave: storage.getItem(STORAGE_KEY_AUTOSAVE) === 'true',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Save Octarine settings to storage
|
|
*/
|
|
export function saveOctarineSettings(settings: OctarineSettings): void {
|
|
storage.setItem(STORAGE_KEY_ENABLED, String(settings.enabled));
|
|
storage.setItem(STORAGE_KEY_WORKSPACE, settings.workspace);
|
|
storage.setItem(STORAGE_KEY_FOLDER, settings.folder);
|
|
storage.setItem(STORAGE_KEY_AUTOSAVE, String(settings.autoSave));
|
|
}
|
|
|
|
/**
|
|
* Check if Octarine integration is properly configured
|
|
*/
|
|
export function isOctarineConfigured(): boolean {
|
|
const settings = getOctarineSettings();
|
|
return settings.enabled && settings.workspace.trim().length > 0;
|
|
}
|