diff --git a/Notemark/Services/DocumentService.cs b/Notemark/Services/DocumentService.cs index deac963..8e4781f 100644 --- a/Notemark/Services/DocumentService.cs +++ b/Notemark/Services/DocumentService.cs @@ -7,6 +7,7 @@ namespace Notemark.Services; public partial class DocumentService : IDocumentService { private readonly string _metadataFilePath; + private readonly string _sessionsDirectory; private readonly SemaphoreSlim _lock = new(1, 1); private readonly JsonSerializerOptions _jsonOptions; @@ -31,6 +32,12 @@ public partial class DocumentService : IDocumentService } _metadataFilePath = Path.Combine(baseDataPath, "documents.json"); + _sessionsDirectory = Path.Combine(baseDataPath, "sessions"); + try + { + Directory.CreateDirectory(_sessionsDirectory); + } + catch { } _jsonOptions = new JsonSerializerOptions { @@ -200,6 +207,14 @@ public partial class DocumentService : IDocumentService var docs = await ReadMetadataListInternalAsync(); docs.RemoveAll(d => d.Id.Equals(id, StringComparison.OrdinalIgnoreCase)); await WriteMetadataListInternalAsync(docs); + + // Also delete the physical markdown file from sessions folder + var safeId = string.Concat(id.Where(c => char.IsLetterOrDigit(c) || c == '-' || c == '_')); + var mdPath = Path.Combine(_sessionsDirectory, $"{safeId}.md"); + if (File.Exists(mdPath)) + { + try { File.Delete(mdPath); } catch { } + } } finally { @@ -273,19 +288,87 @@ public partial class DocumentService : IDocumentService private async Task> ReadMetadataListInternalAsync() { - if (!File.Exists(_metadataFilePath)) - return new List(); + var docs = new List(); - try + if (File.Exists(_metadataFilePath)) { - await using var stream = new FileStream(_metadataFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - return await JsonSerializer.DeserializeAsync>(stream, _jsonOptions) ?? new List(); + try + { + await using var stream = new FileStream(_metadataFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + var loaded = await JsonSerializer.DeserializeAsync>(stream, _jsonOptions); + if (loaded != null) + { + docs.AddRange(loaded); + } + } + catch (Exception ex) + { + Console.Error.WriteLine($"[DocumentService Read Error] {_metadataFilePath}: {ex.Message}"); + } } - catch (Exception ex) + + // Auto-discover and index all .md files in the sessions folder + var hasChanges = false; + if (Directory.Exists(_sessionsDirectory)) { - Console.Error.WriteLine($"[DocumentService Read Error] {_metadataFilePath}: {ex.Message}"); - return new List(); + try + { + var mdFiles = Directory.GetFiles(_sessionsDirectory, "*.md"); + var existingIds = new HashSet(docs.Select(d => d.Id), StringComparer.OrdinalIgnoreCase); + + foreach (var filePath in mdFiles) + { + var docId = Path.GetFileNameWithoutExtension(filePath); + if (string.IsNullOrWhiteSpace(docId)) continue; + + if (!existingIds.Contains(docId)) + { + try + { + var content = await File.ReadAllTextAsync(filePath); + var fileInfo = new FileInfo(filePath); + var title = ExtractTitle(content); + var snippet = ExtractSnippet(content); + var tags = ExtractTags(content); + + var doc = new DocumentMetadata + { + Id = docId, + Title = title, + Snippet = snippet, + IsFlagged = false, + Tags = tags, + CreatedAt = fileInfo.CreationTimeUtc, + LastModifiedAt = fileInfo.LastWriteTimeUtc + }; + + docs.Add(doc); + existingIds.Add(docId); + hasChanges = true; + } + catch (Exception ex) + { + Console.Error.WriteLine($"[DocumentService Scan Error] {filePath}: {ex.Message}"); + } + } + } + } + catch (Exception ex) + { + Console.Error.WriteLine($"[DocumentService Sessions Scan Error] {_sessionsDirectory}: {ex.Message}"); + } } + + if (hasChanges) + { + try + { + await WriteMetadataListInternalAsync(docs); + } + catch { } + } + + return docs; } private async Task WriteMetadataListInternalAsync(List list)