Skip to content

feat: ItemCollectionTransition#22960

Open
MartinZikmund wants to merge 5 commits intomasterfrom
dev/mazi/repeater-collection
Open

feat: ItemCollectionTransition#22960
MartinZikmund wants to merge 5 commits intomasterfrom
dev/mazi/repeater-collection

Conversation

@MartinZikmund
Copy link
Copy Markdown
Member

GitHub Issue: closes #22904

PR Type: ✨ Feature

What is the current behavior? 🤔

Support for ItemCollectionTransition missing

What is the new behavior? 🚀

Support for ItemCollectionTransition added

PR Checklist ✅

Please check if your PR fulfills the following requirements:

Other information ℹ️

Copilot AI review requested due to automatic review settings April 3, 2026 08:12
@MartinZikmund MartinZikmund self-assigned this Apr 3, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR ports WinUI’s ItemCollectionTransition* type system into Uno, adding the core transition descriptor/progress/provider APIs plus a runtime test suite to validate expected add/remove/move transition behavior.

Changes:

  • Added ItemCollectionTransition, related enums, progress type, completed-event args, and the base ItemCollectionTransitionProvider implementation under UI/Xaml/Controls/Repeater/.
  • Updated generated stubs to defer to the new handwritten implementations.
  • Added runtime tests validating provider callbacks, filtering behavior, and TransitionCompleted semantics.

Reviewed changes

Copilot reviewed 7 out of 13 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/Uno.UI/UI/Xaml/Controls/Repeater/ItemCollectionTransitionTriggers.cs Adds [Flags] triggers enum used to describe why transitions occur.
src/Uno.UI/UI/Xaml/Controls/Repeater/ItemCollectionTransitionOperation.cs Adds operation enum (Add/Remove/Move) for transition classification.
src/Uno.UI/UI/Xaml/Controls/Repeater/ItemCollectionTransition.cs Adds transition descriptor object + Start()/HasStarted.
src/Uno.UI/UI/Xaml/Controls/Repeater/ItemCollectionTransitionProgress.cs Adds progress object used to signal completion back to the provider.
src/Uno.UI/UI/Xaml/Controls/Repeater/ItemCollectionTransitionCompletedEventArgs.cs Adds event args for the provider’s TransitionCompleted event.
src/Uno.UI/UI/Xaml/Controls/Repeater/ItemCollectionTransitionProvider.cs Adds provider batching logic using CompositionTarget.Rendering and keep-alive timers.
src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/ItemCollectionTransition*.cs Updates generated stubs to skip members now implemented in Uno sources.
src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_ItemCollectionTransitionProvider.cs Adds runtime tests for transition provider call patterns and completion event behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Member

@morning4coffe-dev morning4coffe-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, lets just recheck with WinUI3 source please

@MartinZikmund MartinZikmund force-pushed the dev/mazi/repeater-collection branch from a51ff01 to a171406 Compare April 6, 2026 09:54
@unodevops
Copy link
Copy Markdown
Contributor

🤖 Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22960/docs/index.html

Copilot AI review requested due to automatic review settings April 6, 2026 10:45
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 23 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +50 to +56
if (usesNewTransitionsBatch)
{
// Allocating a new array of ItemCollectionTransition with animations for this new batch.
_transitionsWithAnimationsMap[_transitionsBatch] = new List<ItemCollectionTransition>();
}

_transitionsWithAnimationsMap[_transitionsBatch].Add(transition);
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QueueTransition can throw KeyNotFoundException when the first transition in a new batch is not animated: _transitionsWithAnimationsMap[_transitionsBatch] is only initialized when usesNewTransitionsBatch is true and the current transition is animated. If the first transition(s) are filtered out by ShouldAnimate, a later animated transition will attempt to .Add into a missing list. Initialize the list on-demand (e.g., TryGetValue/create) before adding, independent of usesNewTransitionsBatch.

Suggested change
if (usesNewTransitionsBatch)
{
// Allocating a new array of ItemCollectionTransition with animations for this new batch.
_transitionsWithAnimationsMap[_transitionsBatch] = new List<ItemCollectionTransition>();
}
_transitionsWithAnimationsMap[_transitionsBatch].Add(transition);
if (!_transitionsWithAnimationsMap.TryGetValue(_transitionsBatch, out var transitionsWithAnimations))
{
// Allocating a new array of ItemCollectionTransition with animations for this batch.
transitionsWithAnimations = new List<ItemCollectionTransition>();
_transitionsWithAnimationsMap[_transitionsBatch] = transitionsWithAnimations;
}
transitionsWithAnimations.Add(transition);

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +19
// Uno does not support cleanup via finalizers; consumers should call Dispose() or stop
// using the provider when done. The timers will be collected when the provider is GC'd.
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The #if HAS_UNO note mentions consumers should call Dispose(), but ItemCollectionTransitionProvider does not implement IDisposable or expose Dispose. This is misleading API guidance; either remove the Dispose() mention or implement deterministic cleanup (stop timers + detach handlers).

Suggested change
// Uno does not support cleanup via finalizers; consumers should call Dispose() or stop
// using the provider when done. The timers will be collected when the provider is GC'd.
// Uno does not support this destructor-style cleanup. When the provider is no longer used,
// any associated timers become eligible for collection when the provider is GC'd.

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +17
private readonly ItemCollectionTransition _transition;

/// <summary>
/// Gets the ItemCollectionTransition whose animations are in progress.
/// </summary>
public ItemCollectionTransition Transition => _transition;
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_transition is declared readonly, so it can never be cleared. This prevents making Complete() single-shot and also means ItemCollectionTransitionProgress will keep the transition/provider/element graph alive as long as the progress object is referenced. If you intend Complete() to be idempotent and release references, _transition needs to be mutable (or guarded via a separate completion flag + clearable reference).

Suggested change
private readonly ItemCollectionTransition _transition;
/// <summary>
/// Gets the ItemCollectionTransition whose animations are in progress.
/// </summary>
public ItemCollectionTransition Transition => _transition;
// The reference is intentionally mutable so completion logic can clear it and release the transition graph.
private ItemCollectionTransition? _transition;
/// <summary>
/// Gets the ItemCollectionTransition whose animations are in progress.
/// </summary>
public ItemCollectionTransition? Transition => _transition;

Copilot uses AI. Check for mistakes.
Comment on lines +36 to +42
public void Complete()
{
if (_transition is not null)
{
var transitionProvider = _transition.OwningProvider();
transitionProvider?.NotifyTransitionCompleted(_transition);
}
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Complete() is not idempotent: calling it multiple times will raise TransitionCompleted multiple times because _transition is never cleared/guarded. Add a single-shot guard (e.g., set the stored transition reference to null after the first call, or track a _completed flag) so completion is raised at most once and references can be released.

Copilot uses AI. Check for mistakes.
@unodevops
Copy link
Copy Markdown
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22960/wasm-skia-net9/index.html

@unodevops
Copy link
Copy Markdown
Contributor

🤖 Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22960/docs/index.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Repeater] Port ItemCollectionTransition type system (new types)

4 participants