style(ui): refactor reader layout grid, fix focus mode layout collapse, fix SVG rendering dots, reorganize intelligence toolbar (#69)

Reorganized the reader toolbar and layout grid to improve visual consistency and layout robustness in Focus Mode. Fixed outline SVG rendering bugs that caused icons to show as solid dots.

Closes #70

---------

Co-authored-by: Marek Jasiński <jasins.marek@gmail.com>
Reviewed-on: #69
Co-authored-by: Antigravity <antigravity@google.com>
Co-committed-by: Antigravity <antigravity@google.com>
This commit was merged in pull request #69.
This commit is contained in:
2026-06-05 09:51:29 +00:00
committed by Marek Jaisński
parent 081c6f7940
commit f18663426b
24 changed files with 2022 additions and 571 deletions
@@ -22,12 +22,21 @@ public sealed partial class KnowledgeCoordinator : IDisposable, IAsyncDisposable
public string CurrentFullPageContent { get; private set; } = string.Empty;
public bool IsLoadingSelectionSummary { get; private set; }
public string? SelectionSummary { get; private set; }
public string? SelectedTextContext { get; private set; }
/// <summary>
/// Raised when the knowledge graph has been updated with new data.
/// Subscribers must return a Task to enable proper async handling.
/// </summary>
public event Func<GraphDataDto, Task>? OnGraphUpdated;
/// <summary>
/// Raised when the selection summary state has changed (loading started, finished, or cleared).
/// </summary>
public event Func<Task>? OnSelectionSummaryStateChanged;
public KnowledgeCoordinator(
IKnowledgeService knowledgeService,
IKnowledgeGraphService graphService,
@@ -205,6 +214,51 @@ public sealed partial class KnowledgeCoordinator : IDisposable, IAsyncDisposable
}
}
public async Task StartSelectionSummaryAsync(string text, string tenantId = "global")
{
if (string.IsNullOrWhiteSpace(text)) return;
IsLoadingSelectionSummary = true;
SelectionSummary = null;
SelectedTextContext = text;
if (OnSelectionSummaryStateChanged != null)
{
await OnSelectionSummaryStateChanged.Invoke();
}
try
{
var result = await RequestSummaryAndQuizAsync(text, tenantId);
if (result.IsSuccess)
{
SelectionSummary = result.Value.Summary;
}
else
{
_logger.LogWarning("[KnowledgeCoordinator] Selection summary request failed: {Errors}", string.Join(", ", result.Errors.Select(e => e.Message)));
}
}
finally
{
IsLoadingSelectionSummary = false;
if (OnSelectionSummaryStateChanged != null)
{
await OnSelectionSummaryStateChanged.Invoke();
}
}
}
public async Task ClearSelectionSummaryAsync()
{
SelectionSummary = null;
SelectedTextContext = null;
IsLoadingSelectionSummary = false;
if (OnSelectionSummaryStateChanged != null)
{
await OnSelectionSummaryStateChanged.Invoke();
}
}
public async Task ClearAsync()
{
CancelAndDisposeCts(ref _graphCts);
@@ -213,6 +267,7 @@ public sealed partial class KnowledgeCoordinator : IDisposable, IAsyncDisposable
CurrentFullPageContent = string.Empty;
await _graphService.Clear();
await _quizService.SetQuiz(null, null);
await ClearSelectionSummaryAsync();
}
public void Dispose()