noz-cli/NozCli/Repl/NotesCache.cs
kryptomrx 47cc904609 feat(repl): Visual banner, JSON note cache, background refresh, Ctrl+C handling
- Startup banner: FigletText + capabilities panel + note stats with status dots
- JSON cache at ~/.cache/noz/notes.json for instant startup
- Cache-first loading: show REPL immediately, refresh notes in background
- Timestamp in stats line (e.g. 'vor 5 Min.') for data freshness feedback
- Ctrl+C in idle exits REPL gracefully; during command cancels only the request
- Per-command CancellationTokenSource so cancel does not kill the session
- Tab completion: command-aware (cd only suggests folders)
2026-05-16 23:20:39 +02:00

53 lines
1.6 KiB
C#

using System.Text.Json;
using NozCli.Core.Models;
using NozCli.Core.Serialization;
namespace NozCli.Repl;
public static class NotesCache
{
private static string CachePath => Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
".cache", "noz", "notes.json");
public static NotesCacheFile? TryLoad()
{
try
{
if (!File.Exists(CachePath)) return null;
var json = File.ReadAllText(CachePath);
return JsonSerializer.Deserialize(json, NozJsonContext.Default.NotesCacheFile);
}
catch { return null; }
}
public static async Task SaveAsync(List<NoteInfo> notes)
{
try
{
var dir = Path.GetDirectoryName(CachePath)!;
Directory.CreateDirectory(dir);
var cache = new NotesCacheFile(DateTimeOffset.UtcNow, notes);
var json = JsonSerializer.Serialize(cache, NozJsonContext.Default.NotesCacheFile);
// Atomic write: tmp → rename
var tmp = CachePath + ".tmp";
await File.WriteAllTextAsync(tmp, json);
File.Move(tmp, CachePath, overwrite: true);
}
catch { /* cache write failures are non-fatal */ }
}
public static string TimeAgo(DateTimeOffset dt)
{
var diff = DateTimeOffset.UtcNow - dt;
return diff.TotalSeconds switch
{
< 60 => "gerade eben",
< 3600 => $"vor {(int)diff.TotalMinutes} Min.",
< 86400 => $"vor {(int)diff.TotalHours} Std.",
_ => $"vor {(int)diff.TotalDays} Tagen",
};
}
}