This commit is contained in:
Michal Vrba
2026-09-22 13:03:08 +02:00
parent 471c823bf7
commit b0f044446d
+87 -4
View File
@@ -7,6 +7,7 @@ namespace Notemark.Services;
public partial class DocumentService : IDocumentService public partial class DocumentService : IDocumentService
{ {
private readonly string _metadataFilePath; private readonly string _metadataFilePath;
private readonly string _sessionsDirectory;
private readonly SemaphoreSlim _lock = new(1, 1); private readonly SemaphoreSlim _lock = new(1, 1);
private readonly JsonSerializerOptions _jsonOptions; private readonly JsonSerializerOptions _jsonOptions;
@@ -31,6 +32,12 @@ public partial class DocumentService : IDocumentService
} }
_metadataFilePath = Path.Combine(baseDataPath, "documents.json"); _metadataFilePath = Path.Combine(baseDataPath, "documents.json");
_sessionsDirectory = Path.Combine(baseDataPath, "sessions");
try
{
Directory.CreateDirectory(_sessionsDirectory);
}
catch { }
_jsonOptions = new JsonSerializerOptions _jsonOptions = new JsonSerializerOptions
{ {
@@ -200,6 +207,14 @@ public partial class DocumentService : IDocumentService
var docs = await ReadMetadataListInternalAsync(); var docs = await ReadMetadataListInternalAsync();
docs.RemoveAll(d => d.Id.Equals(id, StringComparison.OrdinalIgnoreCase)); docs.RemoveAll(d => d.Id.Equals(id, StringComparison.OrdinalIgnoreCase));
await WriteMetadataListInternalAsync(docs); 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 finally
{ {
@@ -273,21 +288,89 @@ public partial class DocumentService : IDocumentService
private async Task<List<DocumentMetadata>> ReadMetadataListInternalAsync() private async Task<List<DocumentMetadata>> ReadMetadataListInternalAsync()
{ {
if (!File.Exists(_metadataFilePath)) var docs = new List<DocumentMetadata>();
return new List<DocumentMetadata>();
if (File.Exists(_metadataFilePath))
{
try try
{ {
await using var stream = new FileStream(_metadataFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); await using var stream = new FileStream(_metadataFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return await JsonSerializer.DeserializeAsync<List<DocumentMetadata>>(stream, _jsonOptions) ?? new List<DocumentMetadata>(); var loaded = await JsonSerializer.DeserializeAsync<List<DocumentMetadata>>(stream, _jsonOptions);
if (loaded != null)
{
docs.AddRange(loaded);
}
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.Error.WriteLine($"[DocumentService Read Error] {_metadataFilePath}: {ex.Message}"); Console.Error.WriteLine($"[DocumentService Read Error] {_metadataFilePath}: {ex.Message}");
return new List<DocumentMetadata>();
} }
} }
// Auto-discover and index all .md files in the sessions folder
var hasChanges = false;
if (Directory.Exists(_sessionsDirectory))
{
try
{
var mdFiles = Directory.GetFiles(_sessionsDirectory, "*.md");
var existingIds = new HashSet<string>(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<DocumentMetadata> list) private async Task WriteMetadataListInternalAsync(List<DocumentMetadata> list)
{ {
var dataDir = Path.GetDirectoryName(_metadataFilePath); var dataDir = Path.GetDirectoryName(_metadataFilePath);