# 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 变更示例](6.1.6-api-changes.zh-CN.md). ## 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?` | | 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 ```csharp 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 ```csharp 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: ```csharp 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 ```xml ``` #### 6.1.6 ```xml ``` ### Update `CardMetaContent.Avatar` references The property name is unchanged, but its CLR type now comes from `AtomUI.Controls`. #### 6.1.5 ```csharp using AtomUI.Desktop.Controls; var content = new CardMetaContent { Avatar = new Avatar { Text = "A" } }; ``` #### 6.1.6 ```csharp 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 ```csharp 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 ```csharp 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 ```csharp var source = new StreamImagePreviewSource( cancellationToken => repository.OpenImageAsync(imageId, cancellationToken), displayName: "invoice.png", contentType: "image/png", identity: imageId); previewer.Source = source; ``` #### 6.1.6 ```csharp 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: ```csharp 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 ```csharp public sealed class PreviewTitleResolver : IImagePreviewTitleResolver { public string? ResolveTitle(ImagePreviewTitleResolveContext context) { return context.Source.DisplayName; } } ``` #### 6.1.6 ```csharp 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 ```csharp using AtomUI.Desktop.Controls; static void ConfigureAtomInput(TextBox input) { input.IsAllowClear = true; input.SizeType = CustomizableSizeType.Large; } ConfigureAtomInput(new LineEdit()); ``` #### 6.1.6 ```csharp 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 ```xml ``` #### 6.1.6 ```xml ``` 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.