using System.IO; using System.Text; namespace TeamsISO.App.Services; /// /// Append-only show-notes log. Each call writes a timestamped line to a daily /// markdown file at %LOCALAPPDATA%\TeamsISO\Notes\<YYYY-MM-DD>.md. /// Operators stamp notes via the REST POST /notes endpoint or the OSC /// /teamsiso/notes "..." address — typically wired to a Stream Deck /// button so a note can be left without leaving the show. /// /// We deliberately don't surface the notes inside the WPF UI: the file is /// trivial to open in any editor, and inline note-taking would be a much /// bigger feature (textarea, scrollback, autosave). The endpoint is the /// minimum-viable affordance for live note capture. /// public static class NotesService { private static readonly object _gate = new(); private static string NotesDirectory => Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "TeamsISO", "Notes"); /// Today's notes file path (created lazily on first append). public static string TodayPath => Path.Combine(NotesDirectory, $"{DateTimeOffset.Now:yyyy-MM-dd}.md"); /// /// Append a single timestamped line. Concurrent callers serialize through /// the static gate so we don't end up with interleaved writes from the /// REST handler thread vs. the OSC dispatcher. /// public static bool Append(string text) { if (string.IsNullOrWhiteSpace(text)) return false; try { lock (_gate) { Directory.CreateDirectory(NotesDirectory); var path = TodayPath; var line = $"- **{DateTimeOffset.Now:HH:mm:ss}** — {text.Trim()}{Environment.NewLine}"; if (!File.Exists(path)) { var header = $"# TeamsISO show notes — {DateTimeOffset.Now:yyyy-MM-dd}{Environment.NewLine}{Environment.NewLine}"; File.WriteAllText(path, header, Encoding.UTF8); } File.AppendAllText(path, line, Encoding.UTF8); } return true; } catch { return false; } } }