Files
AtomUI/docs/releases/6.1.6-api-changes.md
2026-08-29 10:01:32 +08:00

12 KiB

AtomUI 6.1.6 API Change Examples

This document supplements the main 6.1.6 release notes with the breaking API changes and migration examples from 6.1.5. For the authoritative release entries, see the repository root CHANGELOG.md and CHANGELOG.zh-CN.md.

Applications that use Avatar image properties or namespaces, ImagePreviewer source contracts, the former LineEdit : TextBox inheritance relationship, direct OtpLineEditCell styling, or generated Avatar token APIs must migrate before upgrading.

Chinese version: 6.1.6 API 变更示例.

Quick Reference

Area 6.1.5 6.1.6
Avatar control namespace AtomUI.Desktop.Controls.Avatar AtomUI.Controls.Avatar
Avatar base namespace AtomUI.Controls.Commons.AbstractAvatar AtomUI.Controls.AbstractAvatar
Avatar image source Src: string?, BitmapSrc: IImage? Source: ImageLoadSource?, FallbackSource, RequestOptions
Avatar text transform Public TextRenderTransform Internal implementation; use control RenderTransform or a custom template
Avatar generated token namespace AtomUI.Desktop.Controls.DesignTokens AtomUI.Controls.DesignTokens
Card Avatar type CardMetaContent.Avatar: AtomUI.Desktop.Controls.Avatar? CardMetaContent.Avatar: AtomUI.Controls.Avatar?
Preview collection Source, Sources, FallbackSource ItemsSource: IEnumerable<ImagePreviewItem>?
Preview source contracts IImagePreviewSource, UriImagePreviewSource, StreamImagePreviewSource and related loader types ImageLoadSource inside immutable ImagePreviewItem values
Preview concurrency Per-control MaxConcurrentLoads Application UseImageLoading(options => ...)
Preview title resolver ResolveTitle(ImagePreviewTitleResolveContext) and context.Source ResolveTitle(in ImagePreviewTitleResolveContext) and context.Item
Input inheritance LineEdit : AtomUI.Desktop.Controls.TextBox LineEdit, TextBox, TextArea derive from AbstractTextInput
OTP cell surface Public OtpLineEditCell and cell-specific generated tokens Cell implementation and token surface are internal; configure OtpLineEdit

Avatar Migration

Update the namespace and image source properties

Avatar now belongs to the base AtomUI.Controls package and namespace. Src and BitmapSrc are removed in favor of the unified image-loading contracts. String XAML values can still be converted to ImageLoadSource, but C# callers should construct an explicit typed source.

6.1.5

using AtomUI.Desktop.Controls;
using Avalonia.Media;

Avatar CreateRemoteAvatar()
{
    return new Avatar
    {
        Src = "https://cdn.example.com/users/alice.png"
    };
}

Avatar CreateBitmapAvatar(IImage bitmap)
{
    return new Avatar
    {
        BitmapSrc = bitmap
    };
}

6.1.6

using AtomUI.Controls;
using Avalonia.Media;

Avatar CreateRemoteAvatar(IImage fallbackBitmap)
{
    return new Avatar
    {
        Source = ImageLoadSource.FromUri("https://cdn.example.com/users/alice.png"),
        FallbackSource = ImageLoadSource.FromImage(fallbackBitmap),
        RequestOptions = new ImageRequestOptions
        {
            Timeout = TimeSpan.FromSeconds(10),
            CachePartition = "avatars"
        }
    };
}

Avatar CreateBitmapAvatar(IImage bitmap)
{
    return new Avatar
    {
        Source = ImageLoadSource.FromImage(bitmap, cacheKey: "alice-avatar")
    };
}

ImageLoadSource.FromImage borrows the supplied IImage; the loader and Avatar do not dispose it. URI, file, asset, storage-file, byte and repeatable-stream sources are also available from ImageLoadSource.

Replace text-only render transforms

TextRenderTransform is no longer public because text fitting is owned by the Avatar template. Apply a transform to the whole Avatar when that matches the intended result:

using Avalonia.Media;

avatar.RenderTransform = new RotateTransform(5);

There is no direct public replacement for transforming only the generated text presenter. Applications that require a text-only transform must provide a custom Avatar template and transform their own presenter.

Update generated Avatar token namespaces

The generated Avatar token markup extension moves with the control from the desktop package to the base controls package. Applications using AtomUI's shared https://atomui.net XML namespace normally need no AXAML change. Explicit CLR namespace mappings must be updated.

6.1.5

<UserControl
    xmlns:avatarTokens="clr-namespace:AtomUI.Desktop.Controls.DesignTokens;assembly=AtomUI.Desktop.Controls">
    <Border Width="{avatarTokens:AvatarTokenResource ContainerSize}" />
</UserControl>

6.1.6

<UserControl
    xmlns:avatarTokens="clr-namespace:AtomUI.Controls.DesignTokens;assembly=AtomUI.Controls">
    <Border Width="{avatarTokens:AvatarTokenResource ContainerSize}" />
</UserControl>

Update CardMetaContent.Avatar references

The property name is unchanged, but its CLR type now comes from AtomUI.Controls.

6.1.5

using AtomUI.Desktop.Controls;

var content = new CardMetaContent
{
    Avatar = new Avatar { Text = "A" }
};

6.1.6

using AtomUI.Controls;
using AtomUI.Desktop.Controls;

var content = new CardMetaContent
{
    Avatar = new Avatar { Text = "A" }
};

ImagePreviewer Migration

Replace Source and Sources with ItemsSource

ImagePreviewer no longer owns a second image source and loader model. Each item is now an immutable public record that contains the unified source plus optional thumbnail, fallback, request options, title and application tag.

6.1.5

var previewer = new ImagePreviewer
{
    Source = new UriImagePreviewSource("https://cdn.example.com/images/cover.png"),
    Sources =
    [
        new UriImagePreviewSource("https://cdn.example.com/images/one.png"),
        new UriImagePreviewSource("https://cdn.example.com/images/two.png")
    ],
    FallbackSource = new UriImagePreviewSource("avares://Acme.App/Assets/fallback.png"),
    MaxConcurrentLoads = 4
};

6.1.6

using AtomUI.Controls;
using AtomUI.Desktop.Controls;

var fallback = ImageLoadSource.FromAsset(
    new Uri("avares://Acme.App/Assets/fallback.png"));

var previewer = new ImagePreviewer
{
    ItemsSource =
    [
        new ImagePreviewItem(
            ImageLoadSource.FromUri("https://cdn.example.com/images/one.png"))
        {
            ThumbnailSource = ImageLoadSource.FromUri(
                "https://cdn.example.com/images/thumbnails/one.png"),
            FallbackSource = fallback,
            Title = "One"
        },
        new ImagePreviewItem(
            ImageLoadSource.FromUri("https://cdn.example.com/images/two.png"))
        {
            FallbackSource = fallback,
            Title = "Two"
        }
    ]
};

For a single image, provide an ItemsSource collection containing one ImagePreviewItem. Use CurrentIndex and CoverIndex as before to choose the active preview and cover item.

Replace custom stream sources

IImagePreviewSource, IImagePreviewSourceIdentity, UriImagePreviewSource, StreamImagePreviewSource, ImageSourceUri, IImageSourceLoader, DefaultImageSourceLoader, LoadedImageSource and ImagePreviewItemState are removed. Use the corresponding ImageLoadSource factory and application image loader.

6.1.5

var source = new StreamImagePreviewSource(
    cancellationToken => repository.OpenImageAsync(imageId, cancellationToken),
    displayName: "invoice.png",
    contentType: "image/png",
    identity: imageId);

previewer.Source = source;

6.1.6

var source = ImageLoadSource.FromStream(
    cancellationToken => repository.OpenImageAsync(imageId, cancellationToken),
    cacheKey: $"invoice:{imageId}",
    version: imageVersion,
    displayName: "invoice.png");

previewer.ItemsSource = [new ImagePreviewItem(source)];

The stream factory must return a new readable stream for every invocation. The loader owns and closes each returned stream. Supply both cacheKey and version when content needs a stable cross-request identity.

Move concurrency to application configuration

MaxConcurrentLoads is removed from ImagePreviewer. Configure download and decode concurrency once while registering AtomUI:

this.UseAtomUI(builder =>
{
    builder.UseImageLoading(options =>
    {
        options.MaxConcurrentDownloads = 4;
        options.MaxConcurrentDecodes = 4;
    });

    builder.UseDesktopControls();
});

This configuration is application-scoped and is shared by AsyncImage, Avatar, ImagePreviewer and other controls using the image-loading pipeline.

Update custom title resolvers

The resolver receives its context by readonly reference. The context now carries the complete ImagePreviewItem, so custom title logic can use Item.Title, Item.Source.DisplayName or Item.Tag.

6.1.5

public sealed class PreviewTitleResolver : IImagePreviewTitleResolver
{
    public string? ResolveTitle(ImagePreviewTitleResolveContext context)
    {
        return context.Source.DisplayName;
    }
}

6.1.6

public sealed class PreviewTitleResolver : IImagePreviewTitleResolver
{
    public string? ResolveTitle(in ImagePreviewTitleResolveContext context)
    {
        return context.Item.Title
               ?? context.Item.Source.DisplayName
               ?? $"Image {context.CurrentIndex + 1} of {context.Count}";
    }
}

Input Inheritance Migration

In 6.1.5, LineEdit inherited AtomUI's concrete TextBox. In 6.1.6, LineEdit, TextBox and TextArea are sibling controls that inherit the new public AbstractTextInput, which owns their common text-input, validation, size, status, variant, clear-button, count and form-feedback behavior.

6.1.5

using AtomUI.Desktop.Controls;

static void ConfigureAtomInput(TextBox input)
{
    input.IsAllowClear = true;
    input.SizeType = CustomizableSizeType.Large;
}

ConfigureAtomInput(new LineEdit());

6.1.6

using AtomUI.Controls;
using AtomUI.Desktop.Controls;

static void ConfigureAtomInput(AbstractTextInput input)
{
    input.IsAllowClear = true;
    input.SizeType = CustomizableSizeType.Large;
    input.Status = InputControlStatus.Default;
}

ConfigureAtomInput(new LineEdit());
ConfigureAtomInput(new TextBox());
ConfigureAtomInput(new TextArea());

When a helper needs only Avalonia text-editing APIs, accept Avalonia.Controls.TextBox instead. Custom controls that need AtomUI input state and form integration should derive from AbstractTextInput, while code specifically requiring AtomUI TextBox behavior must no longer assume a LineEdit can be passed.

OTP Cell Migration

OtpLineEditCell is an internal template implementation in 6.1.6. Applications must not instantiate it, target it by CLR type, set its former EffectiveStatus/SizeType/StyleVariant properties, or reference generated cell token APIs. Configure the public OtpLineEdit; its template propagates the shared input state to cells.

6.1.5

<UserControl.Styles>
    <Style Selector="atom|OtpLineEditCell">
        <Setter Property="SizeType" Value="Large" />
        <Setter Property="StyleVariant" Value="Filled" />
        <Setter Property="EffectiveStatus" Value="Warning" />
    </Style>
</UserControl.Styles>

6.1.6

<atom:OtpLineEdit
    Length="6"
    SizeType="Large"
    StyleVariant="Filled"
    Status="Warning" />

For deeper visual customization, style the public OtpLineEdit surface and its documented public properties or provide a complete custom OtpLineEdit template. Do not depend on the internal cell control or internal input-frame types.

Rebuild Boundary

The Avatar namespace and assembly ownership, generated token namespaces, ImagePreviewer source model, resolver signature, input inheritance and OTP visibility all change binary contracts. Upgrade all AtomUI packages and AtomUI.Generator together, rebuild application and theme assemblies, and do not mix 6.1.5 generated assets or control assemblies with the 6.1.6 runtime.