Skip to content
15 changes: 14 additions & 1 deletion StabilityMatrix.Avalonia/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,11 @@ internal static void ConfigurePageViewModels(IServiceCollection services)
provider.GetRequiredService<OutputsPageViewModel>(),
provider.GetRequiredService<WorkflowsPageViewModel>(),
},
FooterPages = { provider.GetRequiredService<SettingsViewModel>() },
FooterPages =
{
provider.GetRequiredService<DocumentationViewModel>(),
provider.GetRequiredService<SettingsViewModel>(),
},
});
}

Expand Down Expand Up @@ -838,6 +842,15 @@ internal static IServiceCollection ConfigureServices(bool disableMessagePipeInte
})
.AddPolicyHandler(retryPolicy);

services
.AddRefitClient<IGitHubContentApi>(defaultRefitSettings)
.ConfigureHttpClient(c =>
{
c.BaseAddress = new Uri("https://api.github.com");
c.Timeout = TimeSpan.FromMinutes(1);
})
.AddPolicyHandler(retryPolicy);

services
.AddRefitClient<IHuggingFaceApi>(defaultRefitSettings) // Assuming defaultRefitSettings is suitable
.ConfigureHttpClient(c =>
Expand Down
80 changes: 80 additions & 0 deletions StabilityMatrix.Avalonia/Controls/DocumentationMarkdownViewer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.Windows.Input;
using Avalonia;
using Markdown.Avalonia;

namespace StabilityMatrix.Avalonia.Controls;

/// <summary>
/// A <see cref="BetterMarkdownScrollViewer"/> that routes hyperlink clicks through a
/// bindable <see cref="LinkCommand"/> (so relative <c>.md</c> links can navigate in-app
/// and external links can open in the browser) and resolves relative image paths against
/// <see cref="ImageBaseUrl"/> via the engine's asset path root.
/// </summary>
public class DocumentationMarkdownViewer : BetterMarkdownScrollViewer
{
/// <summary>
/// Command invoked when a hyperlink is clicked. The command parameter is the raw href string.
/// </summary>
public static readonly StyledProperty<ICommand?> LinkCommandProperty = AvaloniaProperty.Register<
DocumentationMarkdownViewer,
ICommand?
>(nameof(LinkCommand));

/// <summary>
/// Base URL used to resolve relative image paths in the rendered markdown
/// (e.g. the raw URL of the current page's folder).
/// </summary>
public static readonly StyledProperty<string?> ImageBaseUrlProperty = AvaloniaProperty.Register<
DocumentationMarkdownViewer,
string?
>(nameof(ImageBaseUrl));

public ICommand? LinkCommand
{
get => GetValue(LinkCommandProperty);
set => SetValue(LinkCommandProperty, value);
}

public string? ImageBaseUrl
{
get => GetValue(ImageBaseUrlProperty);
set => SetValue(ImageBaseUrlProperty, value);
}

public DocumentationMarkdownViewer()
{
ApplyLinkCommand();
ApplyImageBaseUrl();
}

protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);

if (change.Property == LinkCommandProperty)
{
ApplyLinkCommand();
}
else if (change.Property == ImageBaseUrlProperty)
{
ApplyImageBaseUrl();
}
Comment thread
mohnjiles marked this conversation as resolved.
}

private void ApplyLinkCommand()
{
// The engine (IMarkdownEngine) owns the HyperlinkCommand used for all rendered links.
if (Engine is IMarkdownEngine engine)
{
engine.HyperlinkCommand = LinkCommand;
}
}

private void ApplyImageBaseUrl()
{
// AssetPathRoot flows through to the engine's bitmap loader so relative image
// paths resolve against the raw docs URL.
AssetPathRoot = ImageBaseUrl ?? string.Empty;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using CommunityToolkit.Mvvm.ComponentModel;

namespace StabilityMatrix.Avalonia.ViewModels.Documentation;

/// <summary>
/// A single navigable documentation page entry in the sidebar.
/// </summary>
public partial class DocumentationPageNavItem : ObservableObject
{
/// <summary>Display title, e.g. "Overview".</summary>
public required string Title { get; init; }

/// <summary>Path relative to the docs root, e.g. <c>getting-started/overview.md</c>.</summary>
public required string Path { get; init; }

[ObservableProperty]
private bool isSelected;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Collections.Generic;

namespace StabilityMatrix.Avalonia.ViewModels.Documentation;

/// <summary>
/// A section grouping in the documentation sidebar (e.g. "Getting Started").
/// </summary>
public class DocumentationSectionNavItem
{
/// <summary>Section title. Empty for the root section (renders without a header).</summary>
public required string Title { get; init; }

/// <summary>Whether this section has a visible header (i.e. is not the root section).</summary>
public bool HasHeader => !string.IsNullOrEmpty(Title);

/// <summary>Pages within this section.</summary>
public required IReadOnlyList<DocumentationPageNavItem> Pages { get; init; }
}
Loading
Loading