Commit Graph
40 Commits
Author SHA1 Message Date
chinboy 6d41a4e2b3 docs: mark issue 1.4 FloatButtonGroupHost lambda as already fixed
The code was already using named methods (OnFloatButtonGroupOpenRequest/
OnFloatButtonGroupCloseRequest) with CompositeDisposable cleanup.
Update tracking doc to reflect actual state.
2026-04-17 15:50:14 +08:00
chinboy cf9a1b5a28 fix: replace lambda with named method in GroupDescription constructors to avoid closure allocation
- AbstractListGroupDescription: lambda -> OnGroupKeysCollectionChanged
- DataGridGroupDescription: lambda -> OnGroupKeysCollectionChanged
- Eliminates closure object that captures 'this', preventing potential
  self-referencing GC issue (GroupKeys.CollectionChanged holds delegate
  -> delegate captures 'this' -> 'this' owns GroupKeys)
- Update issue tracking doc: mark 1.3 as fixed (P9 done)
2026-04-17 15:48:56 +08:00
chinboy 0af89b8de6 fix(1.2): eliminate lambda closures in WindowNotificationManager.Show()
- Add OnClick/OnClose internal properties to NotificationCard to carry
  per-notification callbacks without capturing local variables
- Replace PointerPressed lambda with static OnNotificationPointerPressed
  (zero closure allocation, reads callback from card.OnClick)
- Replace NotificationClosed lambda with instance OnNotificationClosed
  (accesses _items via 'this', no local variable capture)
- Update AtomUI_issues.md: mark 1.2 as fixed, remove from P8 list
2026-04-17 15:08:39 +08:00
chinboy f5ba2e4ebe fix(1.1): remove Closed += lambda closures in MessageBox/Dialog static APIs
Modal methods (ShowMessageBoxModalAsync, ShowMessageModalAsync,
ShowDialogModalAsync x2): OpenAsync() awaits dialog close, so cleanup
is moved after await tsc.Task — no Closed subscription needed.

Non-modal methods (ShowMessageBoxAsync, ShowMessageAsync,
ShowDialogAsync x2): OpenAsync() returns after dialog is shown, so
Closed lambda is retained as the only close notification point.
The lambda is harmless: Closed fires exactly once, dialog is removed
from parent and GC'd immediately after, releasing the closure.

- Update AtomUI_issues.md: mark 1.1 as fixed, remove from P3 list
- Delete performance_memory_leak.md (tracking moved to AtomUI_issues.md)
2026-04-17 15:01:37 +08:00
chinboy ad6a346c30 fix(3.2): prevent memory leaks in DataGridCell by managing event subscriptions - dispose old subscriptions in OnApplyTemplate to avoid accumulation - release subscriptions in OnDetachedFromVisualTree 2026-04-17 13:55:01 +08:00
chinboy 7f3ab08fd4 docs(3.3): mark ColorPicker complex state management as fixed - Update progress to 34/39 (87.2%) - Mark 3.3 ColorPicker OnApplyTemplate event subscription as fixed - ColorPickerInput, AbstractColorPickerView, ColorSliderThumb all use named handlers with remove-before-add pattern - Remove 3.3 from P2 pending list - Medium: 17/19 fixed 2026-04-17 13:24:51 +08:00
chinboy cea4bb8fa9 fix(2.1): implement IDisposable on AbstractNotifiableTransition and dispose at call sites
- INotifyTransitionCompleted interface now extends IDisposable
- AbstractNotifiableTransition<T>.Dispose() disposes Subject<bool> and nulls it
- NotifyTransitionCompleted() guards against null _subject (post-dispose)
- CompletedObservable throws ObjectDisposedException if accessed after Dispose
- AbstractMotion.RunTransitions: dispose all Transitions after await completes
  (covers both normal completion and Task.Delay timeout path)
- AbstractMotion.ConfigureTransitions: dispose existing Transitions before Clear
  to prevent Subject leaks when transitions are rebuilt
- Update performance_memory_leak.md: 32/39 fixed (82.1%), High 8/8 all done
2026-04-17 13:04:41 +08:00
chinboy bd1b270c81 revert(3.4): Form Items.CollectionChanged lambda is a false positive — no fix needed
Items is an internal ItemCollection owned by Form with identical lifetime.
The subscription cannot leak across lifetimes: when Form is GC'd, Items and
its event subscriptions are collected with it. Mark 3.4 as false positive in docs.
2026-04-17 12:56:24 +08:00
chinboy fae2788bc5 fix(3.4): extract Form Items.CollectionChanged lambda to named method HandleItemsCollectionChanged
- Replace anonymous lambda with named method to allow precise -=  unsubscription
- Prevents subscription leak when Items is replaced by an external CollectionView
- Update performance_memory_leak.md: 32/39 fixed (82.1%), Medium 16/19
2026-04-17 12:54:33 +08:00
chinboy ca1c990e7b fix(1.2): replace anonymous lambda with WeakReference forwarder in DataGridCollectionView to eliminate CollectionChanged memory leak
- Mirror the same WeakCollectionChangedForwarder pattern applied to ListCollectionView (29452afe)
- Add IDisposable to DataGridCollectionView class declaration
- Add _collectionChangedForwarder field (WeakCollectionChangedForwarder?)
- Replace anonymous lambda subscription with forwarder in constructor
- Add Dispose() for eager cleanup
- Add WeakCollectionChangedForwarder nested class with self-unsubscribe on GC
- All Critical (P0) issues now fully resolved
- Update performance_memory_leak.md: 31/39 fixed (79.5%), Critical 7/7
2026-04-17 12:48:57 +08:00
chinboy a896c7833e docs(1.1): annotate section title with fix status and commit hash 2026-04-17 12:46:14 +08:00
chinboy ea59ecac29 docs(1.1): fill in commit hash 29452afe and update critical/total fix counts 2026-04-17 12:43:05 +08:00
chinboy 652398a207 fix(1.1): replace anonymous lambda with WeakReference forwarder in ListCollectionView to eliminate CollectionChanged memory leak
- Add WeakCollectionChangedForwarder nested class: source holds strong ref to
  forwarder, forwarder holds WeakReference<ListCollectionView> — prevents the
  source collection from rooting the view
- Self-unsubscribes on next event after view is GC'd; no lingering delegate
- Keep IDisposable.Dispose() for eager cleanup when ItemsSource changes in ListView
- ListView: track _ownsCollectionView flag and call Dispose() on old view only
  when we created it (not user-provided IListCollectionView)
- Remove OnDetachedFromVisualTree disposal to avoid breaking reattach scenarios
  (tab switching, panel rebuilds, etc.) — WeakReference handles lifetime safely
- Update performance_memory_leak.md: mark 1.1 as fixed, progress 30/39 (76.9%)
2026-04-17 12:40:09 +08:00
chinboy 9ec5bc9fa7 fix(Statistic): remove dead code in GenerateRemainingTimeText and use smart default time format 2026-04-17 10:48:35 +08:00
chinboy 87e9a8b572 perf(Tag): replace static Dictionary with FrozenDictionary for PresetColorMap, StatusColorMap and PresetPalettes 2026-04-17 10:41:57 +08:00
chinboy 4d94e60cfc perf(Notification): reduce polling to 200ms, add PollingInterval property, and use HashSet for O(1) cleanup queue dedup 2026-04-17 10:13:16 +08:00
chinboy b18d82e56a docs(MemoryLeak): mark 5.18 as fixed, update progress to 14/39 (35.9%) 2026-04-17 10:06:04 +08:00
chinboy 17575bcfa6 docs(MemoryLeak): mark 5.17 as fixed, update progress to 13/39 (33.3%) 2026-04-17 10:00:04 +08:00
chinboy c48de5f137 docs(MemoryLeak): mark 5.15 and 5.16 as fixed, update progress to 12/39 (30.8%) 2026-04-17 09:58:24 +08:00
chinboy 3204c7a87f fix(FloatButton): replace lambda subscriptions with named handlers in FloatButtonGroupHost to prevent memory leak 2026-04-17 09:51:14 +08:00
chinboy a5ecee5927 fix(5.13): properly clean up old DispatcherTimer in Mentions and AutoComplete
- Always stop, unsubscribe, and null out old _delayTimer before creating new instance
- Prevents event handler accumulation when MinimumPopulateDelay changes
- Unify handling between Mentions and AbstractAutoComplete
- Fixes issue where timer event handlers would accumulate on rapid property changes
2026-04-17 07:58:02 +08:00
chinboy 39064b8bcb fix(5.12): add Dispose call for CancellationTokenSource in AbstractSkeleton
- StartActiveAnimation: dispose old CTS before creating new instance
- StopActiveAnimation: dispose CTS and set to null
- BuildActiveAnimation: dispose CTS before rebuilding animation
- Prevents WaitHandle and unmanaged resources from leaking during repeated animation start/stop cycles
2026-04-17 07:21:05 +08:00
chinboy 2117910517 docs(5.11): update fix status and refactor ColorPicker async methods for clarity
- Mark issue 5.11 (async void methods) as fully fixed (4/4)
- Remove backward compatibility wrapper methods, call async versions directly
- Add Avalonia.VisualTree import to ColorSlider and SelectableTextBlock
- Improve code indentation and readability in ColorSpectrum.CreateBitmapsAndColorMapAsync
- Clean up ColorSpectrum property default values in property definitions
- Update documentation with unified fix pattern for all 4 async void methods
- Remove obsolete void wrapper methods (Copy, UpdateBackground, CopyToClipboard)
2026-04-16 22:58:42 +08:00
chinboy 32b0d9c5f4 fix(5.11): add exception handling to async void methods in ColorPicker and DataGrid
- ColorSpectrum: convert CreateBitmapsAndColorMap to async Task with try-catch
- ColorSlider: convert UpdateBackground to async Task with IsAttachedToVisualTree check
- DataGrid: convert CopyToClipboard to async Task with exception handling
- SelectableTextBlock: convert Copy to async Task with IsAttachedToVisualTree check
- Keep original void methods for backward compatibility (fire-and-forget pattern)
- Add graceful exception handling to prevent app crashes
- Verify control is attached before updating UI after async operations
2026-04-16 22:57:30 +08:00
chinboy a8847c7107 docs(5.10): update fix status for TreeView/CascaderView async load CancellationTokenSource
- Mark 5.10 as fixed with commit 7472c56a
- Document complete lifecycle management implementation
- Add AsyncLoadTimeout property details
- Update fix progress: 10 issues fixed (25.6%)
2026-04-16 21:44:45 +08:00
chinboy 4086b3536e feat(5.10): make async load timeout configurable via AsyncLoadTimeout property
- Add AsyncLoadTimeout property to TreeView (default: 30 seconds)
- Add AsyncLoadTimeout property to CascaderView (default: 30 seconds)
- Replace hardcoded timeout values with property values
- Allows users to customize timeout duration in XAML or code
- Maintains backward compatibility with default 30-second timeout
2026-04-16 18:38:54 +08:00
chinboy 4e2dd770d7 fix(5.9): move glyph PropertyChanged subscription to lifecycle hooks in Watermark
- Move PropertyChanged subscription from constructor to OnAttachedToVisualTree
- Add PropertyChanged unsubscription in OnDetachedFromVisualTree
- Ensure proper lifecycle management when Watermark is reattached to visual tree
- Prevent memory leaks from glyph event handlers

Also update performance_memory_leak.md:
- Mark 5.9 (Watermark glyph.PropertyChanged lambda) as fixed
- Add fix timestamp and implementation details
2026-04-16 18:01:03 +08:00
chinboy 230b8a44ba fix(5.6): replace lambda with named method in ToolTipService timer handler
- Replace anonymous lambda with named method HandleShowTimerTick()
- Call StopTimer() at the beginning of StartShowTimer() to clean up old timer
- Use ValueTuple to safely extract control reference from timer Tag
- Prevent multiple parallel timers when mouse moves quickly

Also update performance_memory_leak.md:
- Mark 5.6 (ToolTip service global event subscription) as fixed
- Add fix timestamp and implementation details
2026-04-16 17:53:18 +08:00
chinboy 8c1f2cd073 fix(5.4): add Dispose call for CancellationTokenSource in MarqueeLabel
- Add Dispose() call in HandleCleanupMarqueeAnimation() to release unmanaged resources
- Set CancellationTokenSource to null after disposal
- Ensure complete lifecycle management of CancellationTokenSource

Also update performance_memory_leak.md:
- Mark 5.4 (MarqueeLabel animation cleanup) as fixed
- Add fix timestamp and implementation details
2026-04-16 17:38:56 +08:00
chinboy 272d480bff fix(3.7): replace delegate fields with private methods in ColorPickerInput
- Remove 8 private event handler delegate fields (_alphaInputValueChangedHandler, etc.)
- Add 8 private methods to replace delegate fields (HandleAlphaInputValueChanged, etc.)
- Update OnApplyTemplate to use method references instead of delegate fields
- Avoid allocating new delegate objects on each OnApplyTemplate call
- Improve code clarity by using private methods for lambdas that don't capture closure variables

Also update performance_memory_leak.md:
- Mark 5.3 (CompositeDisposable) as fixed
- Update 3.7 fix description to reflect the actual implementation using private methods
- Add fix timestamp and details
2026-04-16 17:32:05 +08:00
chinboy a2e352283d fix(5.2): replace lambda with named methods in FlyoutStateHelper timer handlers 2026-04-16 16:08:30 +08:00
chinboy 0995ca48a7 docs: mark section 3.7 ColorPickerInput as fixed
Update documentation to mark section 3.7 (ColorPickerInput OnApplyTemplate Lambda stacking)
as fixed. Investigation shows the code already implements the correct event management pattern:
Implementation details:
- Event handlers stored in class-level fields (lines 80-87)
- All old subscriptions removed at OnApplyTemplate start (lines 127-160)
- New named lambda handlers created and subscribed (lines 179-289)
- Prevents event handler accumulation on template reapplication
Update statistics:
- Fixed issues: 2 → 3
- Progress: 5.1% → 7.7% (3/39)
- Critical problems: 0 → 1 fixed
Update fix log to include 3.7 alongside 4.5 and 4.8 fixes.
2026-04-16 15:58:01 +08:00
chinboy e9d3e85194 docs: update performance_memory_leak.md with fix status for 4.5 and 4.8
Update documentation status:
- Mark section 4.5 (OptionButtonGroup Lambda events) as FIXED
  - Commit: 01ec42d6
  - Details: Convert lambda to named method, subscribe in constructor, unsubscribe in OnDetachedFromVisualTree
- Mark section 4.8 (Async methods CancellationToken support) as FIXED
  - Commits: 76aadb94, 4c9054dd
  - Details: Add CancellationToken support to 7 files (Upload, MessageBox, Popup, MenuItem, FileUploadScheduler, IFileUploadScheduler, IconPackageGenerator)
  - Code changes: +35, -21
Add:
- Modification progress summary at the top (5.1% complete - 2/39 issues fixed)
- Update priority table with fix status
- Update issue statistics with fix counts
- Add detailed fix log at the end with commit hashes and implementation details
Documentation updates: +140, -47
2026-04-16 15:55:56 +08:00
chinboy f4df590d18 fix(WindowNotificationManager): unsubscribe timer Tick events in Dispose and remove over-optimized card handler tracking 2026-04-16 15:15:17 +08:00
chinboy 90a0c6806d fix(MemoryLeak): add cache size limit to IconProviderCache and fix OptionButtonGroup event subscription lifecycle 2026-04-16 14:53:34 +08:00
chinboy 3a57fadf83 fix(Tour): clean up event subscriptions in OnDetachedFromVisualTree 2026-04-16 14:28:14 +08:00
chinboy 6a435bc2be fix: InfoPickerInput OnApplyTemplate lambda 事件叠加 — 改为命名方法并在开头移除旧订阅
- 问题:OnApplyTemplate 中使用匿名 lambda 订阅 DecoratedBox.TemplateApplied、DecoratedBox.PropertyChanged、PickerClearUpButton.ClearRequest 事件
- 每次模板重新应用(主题切换等)都会叠加新的订阅,导致回调数量线性增长
- 影响:所有派生自 InfoPickerInput 的控件(DatePicker、TimePicker 等)

修复方案:
1. 添加字段存储事件处理器引用:_decoratedBoxTemplateAppliedHandler、_decoratedBoxPropertyChangedHandler、_clearRequestHandler
2. 在 OnApplyTemplate 开头先移除旧订阅
3. 将匿名 lambda 改为存储在字段中的委托,确保可以取消订阅

这样每次模板重新应用时,旧订阅会被正确移除,新订阅才会添加,避免叠加。
2026-04-16 13:16:05 +08:00
chinboy f92ab2615d fix: TimerStatistic 定时器泄漏 — 旧定时器未停止/释放
修复 #3.3: BuildTimer() 创建新 DispatcherTimer 时未停止旧定时器,
导致多个定时器并行运行。OnDetachedFromVisualTree 中也未清理定时器。
2026-04-16 13:07:54 +08:00
chinboy c83d294589 fix: SwitchKnob OnDetachedFromVisualTree 调用错误的基类方法
修复 #3.2: OnDetachedFromVisualTree 中调用了 base.OnAttachedToVisualTree(e)
而非 base.OnDetachedFromVisualTree(e),导致基类清理逻辑失效。
2026-04-16 13:04:35 +08:00
chinboy 66aac27789 fix: TransformTrackingHelper DetachedFromVisualTree 事件订阅运算符错误 (-= → +=)
修复 #3.1: SetVisual() 中 DetachedFromVisualTree 使用了 -= 而非 +=,
导致 OnDetachedFromVisualTree 永远不会触发,父级 Visual 链的
PropertyChanged 订阅永久泄漏。
2026-04-16 13:00:44 +08:00