# AtomUI 6.1.3 API Change Examples This document supplements the main `6.1.3` release notes with the most important breaking API changes and migration examples from `6.1.2`. For the authoritative release entries, see the repository root `CHANGELOG.md` and `CHANGELOG.zh-CN.md`. The Avalonia dependency upgrade from `12.1.0` to `12.1.1` does not require AtomUI applications to change source code by itself. This page covers public contract changes in the same AtomUI release across Theme, Localization, Upload, Timeline, Tag, and Separator. Chinese version: [6.1.3 API 变更示例](6.1.3-api-changes.zh-CN.md). ## Quick Reference | Area | 6.1.2 | 6.1.3 | |---|---|---| | Theme algorithms | String algorithm IDs | `ThemeAlgorithm` enum | | Theme control package registration | Register token descriptors and theme providers separately | Generated `ControlPackageRegistration` | | Localization | `LanguageVariant`, `LanguageProvider`, ThemeManager language state | `LanguageTag`, XLIFF 2.1 catalogs, `ILanguageManager` | | Upload file filters | `Accepts` string collection | `AllowedFileTypes` / `FilePickerFileType` | | Upload click and drop input | `Upload.IsOpenFileDialogOnClick`, `UploadDefaultDropArea.FilesDropped` | `UploadDropZone` and `InputBatchCompleted` | | Upload file content | URI and fixed-size `UploadFileInfo` constructors | `IUploadFileSource` opens file streams on demand | | Timeline placement | `Left` / `Right` | `Start` / `End`, plus `Orientation` | | Tag appearance | `IsBordered` | `TagVariant` | | Separator size | `SizeType` | `CustomizableSizeType` | ## Theme Compilation and Registration Migration ### Algorithm strings are now enum values `ThemeConfigBuilder.WithAlgorithms` and `ControlThemeConfigBuilder.WithAlgorithms` no longer accept strings. Algorithm attributes, descriptors, and runtime state now use `ThemeAlgorithm`. #### 6.1.2 ```csharp var themeConfig = new ThemeConfigBuilder() .WithAlgorithms("Default", "Dark") .Build(); ``` #### 6.1.3 ```csharp using AtomUI.Theme.Algorithms; using AtomUI.Theme.Configuration; var themeConfig = new ThemeConfigBuilder() .WithAlgorithms(ThemeAlgorithm.Default, ThemeAlgorithm.Dark) .Build(); ``` Custom algorithm declarations must migrate too: ```csharp // 6.1.2 [ThemeAlgorithmAttribute("Dark", 1, ThemeAppearanceEffect.Dark)] // 6.1.3 [ThemeAlgorithmAttribute(ThemeAlgorithm.Dark, 1, ThemeAppearanceEffect.Dark)] ``` `ThemeAlgorithmAttribute.Id` and `ThemeAlgorithmDescriptor.Id` have been replaced by `Algorithm`. The current algorithm set is closed over `Default`, `Dark`, and `Compact`; arbitrary string algorithm IDs are no longer supported. ### Control packages register as one package Custom control packages should no longer call `IThemeManagerBuilder.AddControlToken()` and `AddControlThemesProvider()` separately. Token descriptors, theme asset descriptors, and the theme provider must be registered as one `ControlPackageRegistration` during `Application.UseAtomUI(...)`, before the theme schema freezes. #### 6.1.2 ```csharp application.UseAtomUI(themeBuilder => { foreach (var descriptor in MyGeneratedThemeSchema.GetControls()) { themeBuilder.AddControlToken(descriptor); } themeBuilder.AddControlThemesProvider(new MyControlThemesProvider()); }); ``` #### 6.1.3 ```csharp application.UseAtomUI(builder => { builder.AddControlPackage(new ControlPackageRegistration( id: "MyCompany.Controls", controls: MyGeneratedThemeSchema.GetControls(), themeAssets: MyGeneratedThemeAssetManifest.GetDescriptors(), controlThemesProvider: new MyControlThemesProvider())); }); ``` The generated type names in the example are owned by the custom control package. Real projects should use the descriptors and asset manifests emitted by AtomUI Generator. Do not scan assemblies or AXAML files at runtime. Theme definition resolvers should also be registered from the root builder stage: ```csharp application.UseAtomUI(builder => { builder.AddThemeDefinitionResolver(new MyThemeDefinitionResolver()); builder.UseDesktopControls(); }); ``` Theme schema, control identity, token schema, and theme asset manifests are frozen before the first theme snapshot is compiled. Applications cannot append control packages or mutate committed `ThemeConfig` collections after startup. ## Generated Localization Catalog Migration ### Removed legacy language APIs The following types and entry points have been removed: ```text LanguageCode LanguageVariant LanguageVariantTypeConverter LanguageProvider ILanguageProvider LanguageProviderAttribute LanguageProviderPool IThemeManagerBuilder.AddLanguageProviders() IThemeManagerBuilder.WithDefaultLanguageVariant() ``` Language state is no longer owned by ThemeManager. Applications should use `LanguageTag`, `ILanguageManager`, `ILocalizer`, and root-level `IAtomUIBuilder.UseLanguages()`. ### Configure supported languages #### 6.1.2 ```csharp application.UseAtomUI(themeBuilder => { themeBuilder.WithDefaultLanguageVariant(LanguageVariant.zh_CN); themeBuilder.AddLanguageProviders(new MyZhCnLanguageProvider()); themeBuilder.UseDesktopControls(); }); ``` #### 6.1.3 ```csharp using AtomUI.Localization; application.UseAtomUI(builder => { builder.UseLanguages( defaultLanguage: LanguageTags.ZhCN, supportedLanguages: [ LanguageTags.EnUS, LanguageTags.ZhCN, LanguageTags.ZhTW ]); builder.UseDesktopControls(); }); ``` Application catalogs, component catalogs, and static language packages are generated and registered from XLIFF 2.1 inputs. `UseLanguages()` only declares the default language and the application-supported language set; it does not accept providers or language package instances. ### Change language at runtime #### 6.1.2 ```csharp themeManager.LanguageVariant = LanguageVariant.zh_TW; ``` #### 6.1.3 ```csharp var languageManager = application.GetLanguageManager() ?? throw new InvalidOperationException("AtomUI localization is not initialized."); languageManager.ChangeLanguage(LanguageTags.ZhTW); ``` Plain C# and ViewModel localization should use `ILocalizer`: ```csharp var localizer = application.GetLocalizer() ?? throw new InvalidOperationException("AtomUI localization is not initialized."); string title = localizer.Get(SettingsLangResourceKind.Title); ``` Existing XAML markup extension usage is preserved: ```xml ``` ### Catalog identity changes Catalog enum member names and XLIFF `unit id` values now form the stable resource key. `LanguageCatalogUnitDescriptor.Id` and `Name` have converged into `Key`, and production catalog `ContractVersion` is now `2`. Applications, components, and static language packages must be rebuilt together. Do not mix 6.1.2 numeric-ID catalog assemblies or language packages with 6.1.3 key-based catalogs. Existing third-party language packages should be re-exported, translated, and repackaged from the new authoritative `en-US.xlf` files. ## Upload Input Contract Migration ### `Accepts` is now `AllowedFileTypes` `Accepts` string patterns and MIME entries have been replaced by Avalonia Storage API `FilePickerFileType`. #### 6.1.2 ```csharp upload.Accepts = ["*.png", "*.jpg", "image/png", "image/jpeg"]; ``` #### 6.1.3 ```csharp using Avalonia.Platform.Storage; upload.AllowedFileTypes = [ new FilePickerFileType("Images") { Patterns = ["*.png", "*.jpg", "*.jpeg"], MimeTypes = ["image/png", "image/jpeg"] } ]; ``` The same `AllowedFileTypes` collection is used by the picker filter and by Upload admission. Programmatic input, expanded directory input, and drop input are validated against the same rules. ### Click-to-select moves to `UploadDropZone` `Upload.IsOpenFileDialogOnClick` has been removed. Click selection is owned by the composable `UploadDropZone`, and `SourceKind` decides whether the zone opens a file picker or a directory picker. #### 6.1.2 ```xml ``` #### 6.1.3 ```xml ``` Use `SourceKind="Directories"` for directory selection. Set `IsOpenFileDialogOnClick="False"` when a zone should accept drops only. ### Drop events are now input batch results `UploadDefaultDropArea.FilesDropped`, `FilesDroppedEvent`, and `UploadFilesDroppedEventArgs` have been removed. `UploadDefaultDropArea` now owns only the default visuals, and `UploadDropZone` is the only DragDrop input surface. Do not handle raw `IStorageFile` collections from the drop area. Use `Upload.InputBatchCompleted` when application code needs input results, rejection reasons, or batch failures: ```csharp private void HandleInputBatchCompleted( object? sender, UploadInputBatchCompletedEventArgs e) { if (e.Status == UploadInputBatchStatus.Failed) { LogInputFailure(e.BatchId, e.FailureReason); return; } foreach (var rejected in e.RejectedItems) { LogRejectedFile(rejected.Name, rejected.Reason, rejected.Message); } } ``` ```xml ``` ### `UploadFileInfo` now uses openable file sources `UploadFileInfo` no longer assumes that every file has an accessible local URI, fixed size, or repeatable file path. Callers must provide an `IUploadFileSource`; each `OpenReadAsync()` call should return a fresh readable stream. #### 6.1.2 ```csharp var file = new UploadFileInfo( name: "report.pdf", filePath: new Uri(filePath), size: new FileInfo(filePath).Length); ``` #### 6.1.3 ```csharp sealed class LocalUploadFileSource(string filePath) : IUploadFileSource { public ValueTask OpenReadAsync( CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); return ValueTask.FromResult(File.OpenRead(filePath)); } } var fileInfo = new FileInfo(filePath); var file = new UploadFileInfo( name: fileInfo.Name, source: new LocalUploadFileSource(filePath), path: new Uri(filePath), size: fileInfo.Length, contentType: "application/pdf"); await upload.EnqueueFilesAsync([file]); ``` If the source owns a temporary file, StorageItem lease, or other disposable resource, ownership is transferred to Upload until the upload exits, the file is removed, or the control is disposed. ### Custom admission policies Implement `IUploadAdmissionPolicy` when application-specific validation is needed. Return decisions through the factory methods: ```csharp sealed class AttachmentAdmissionPolicy : IUploadAdmissionPolicy { public ValueTask EvaluateAsync( UploadAdmissionContext context, CancellationToken cancellationToken = default) { return context.File.Size > 10 * 1024 * 1024 ? ValueTask.FromResult(UploadAdmissionDecision.Reject( "file-too-large", "The file exceeds the 10 MB limit.")) : ValueTask.FromResult(UploadAdmissionDecision.Accept()); } } ``` ```xml ``` ## Timeline Logical Direction Migration `TimelineMode.Left` and `TimelineMode.Right` have been replaced by logical `Start` and `End` values to support RTL and horizontal layouts. | 6.1.2 | 6.1.3 | |---|---| | `TimelineMode.Left` | `TimelineMode.Start` | | `TimelineMode.Right` | `TimelineMode.End` | | `IndicatorLeftModeMargin` | `IndicatorStartModeMargin` | | `IndicatorRightModeMargin` | `IndicatorEndModeMargin` | #### 6.1.2 ```xml ``` #### 6.1.3 ```xml ``` Horizontal timelines use the same logical placement model: ```xml ``` `Orientation` still defaults to `Vertical`. Custom theme or token overrides should migrate to the Start/End resource names too. ## Tag Variant and Checkable Tag Migration ### `IsBordered` is now `TagVariant` `Tag.IsBordered` has been removed. The new `Variant` supports `Filled`, `Solid`, and `Outlined`; the default is `Filled`. #### 6.1.2 ```xml ``` #### 6.1.3 ```xml ``` There is no exact compatibility mode for the old `IsBordered="False"`. In most cases, choose `Filled` for the original visual intent; use `Solid` for a high-contrast solid background. Preset, status, and custom colors are combined with `Variant` to determine background, foreground, and border. ### Checkable scenarios use CheckableTag Regular `Tag` continues to own display, color, and close behavior. Use `CheckableTag` for binary selection and `CheckableTagGroup` for collection selection: ```xml ``` Single selection: ```xml ``` Multiple selection: ```xml ``` `CheckableTag` does not expose regular `Tag` APIs such as `TagColor`, `Variant`, `IsClosable`, or close events. ## Separator Customizable Size Migration `Separator.SizeType` changed from `SizeType` to `CustomizableSizeType`, and Separator now implements `ICustomizableSizeTypeAware`. The XAML names `Small`, `Middle`, and `Large` are unchanged in common markup: ```xml ``` C# code that reads or writes the strongly typed property must be updated: ```csharp // 6.1.2 separator.SizeType = SizeType.Small; // 6.1.3 separator.SizeType = CustomizableSizeType.Small; ``` `Custom` does not apply AtomUI preset block margins. Spacing should be provided by the control instance or its owning style: ```xml ``` Custom methods, interfaces, or ViewModel properties that declared `SizeType` should migrate to `CustomizableSizeType`. Do not rely on implicit enum conversions. ## Upgrade Checklist Before upgrading, search for the old contracts in this order: ```text WithAlgorithms(" AddControlToken AddControlThemesProvider LanguageCode LanguageVariant LanguageProvider AddLanguageProviders Accepts IsOpenFileDialogOnClick FilesDropped UploadFilesDroppedEventArgs TimelineMode.Left TimelineMode.Right IndicatorLeftModeMargin IndicatorRightModeMargin IsBordered Separator.SizeType ``` Typical AtomUI applications without custom Theme, Localization, or Upload pipelines mainly need to check Timeline, Tag, and Separator usage in XAML or C#. If the only change is the Avalonia `12.1.1` dependency patch and the AtomUI public contract changes listed here are not included, no migration from this page is required.