FModel/FModel/Views/Resources/Controls/CommitDownloaderControl.xaml.cs
Rob Trame c5bc12e618
fix: address remaining WPF→Avalonia migration gaps (issue #82) (#83)
* fix: address remaining WPF→Avalonia migration gaps (issue #82)

Critical fixes:
- C1: RatioToGridLengthConverter — add missing using Avalonia.Controls
- C2/C3: ApplicationViewModel — remove AdonisUI MessageBox, async ShowDialog,
  IClassicDesktopStyleApplicationLifetime.Shutdown()
- C4: ImageCommand — Avalonia Window, BitmapInterpolationMode, PixelSize
- C5: TabCommand/CopyCommand — Avalonia async clipboard with error logging
- C6: ImGuiController — DPI via screen.PixelDensity
- C7: ClipboardExtensions — Avalonia DataObject with PNG bytes, InvokeAsync

Major fixes:
- M1: Timeclock — full StyledProperty rewrite, UI-thread-safe event handlers
- M2: DictionaryEditor/EndpointEditor — Avalonia Window + AvaloniaEdit
- M3: CommitDownloaderControl — Avalonia UserControl + StyledProperty
- M4: FileButton2/FolderButton2/FolderButton3 — Avalonia XAML, restore
  NumTextures badge and colored separator in FileButton2
- M5: Breadcrumb — Avalonia XAML + pointer events
- M6: CUE4ParseViewModel — Helper.CloseWindow<Window>
- M7: App.xaml.cs — e.RequestCatch replacing e.Handled
- M8: FileContextMenu — Avalonia namespace + IsVisible

Minor/other fixes:
- Enable <Nullable> in csproj
- OnTagDataTemplateSelector stub + SettingsView code-behind template selection
- TiledExplorer/Resources.xaml — full Avalonia rewrite (style selectors,
  WrapPanel, IDataTemplate, attached behaviors, converter-based empty state)
- ListBoxItemBehavior — Avalonia AttachedProperty with 3 behaviors
- TypeDataTemplateSelector — IDataTemplate with FolderContextMenu attachment
- SmoothScroll — Avalonia AttachedProperty + PointerWheelChanged
- Remove dead code-behind from Resources.xaml.cs
- Remove unsupported IsAsync=True from bindings
- Remove duplicate CornerRadius property from Timeclock
- New converters: AssetExtensionToIconConverter, IntGreaterThanZeroConverter,
  IsNullToBoolConverter, ItemsSourceEmptyToBoolConverter
- FolderToGeometryConverter — add bool return for IsVisible bindings

Closes #82

* fix: address PR #83 review comments

- RestartWithWarning: restore user-visible Avalonia dialog before restart
  (matches original WPF MessageBox.Show behavior)
- UpdateProvider: add null guards for nullable AesManager/CUE4Parse
- FolderContextMenu: add .ContinueWith error logging on clipboard write
- SettingsView: replace throwing FindResource with TryFindResource
- SmoothScroll: cache ScrollViewer in ConditionalWeakTable to avoid
  per-event visual tree walks
- ListBoxItemBehavior: replace throwing FindResource with TryFindResource;
  move e.Handled inside success block so it's only set when menu opens

* fix: address correctness review and second round PR comments

- C1: Fix FolderButton3 LinearGradientBrush StartPoint/EndPoint to use
  relative percentage format (0%,0%/0%,100%) instead of absolute pixels
- M1: TypeDataTemplateSelector resolves FolderContextMenu per-control via
  AttachedToVisualTree + TryFindResource instead of shared Application lookup
- M2: Replace 19 unresolvable SystemColors.ControlTextBrushKey references
  with #DAE5F2 in FileContextMenu.xaml and FolderContextMenu.xaml
- M4: RestartWithWarningAsync non-modal fallback awaits dialog.Closed via
  TaskCompletionSource before calling Restart()
- mn1: EndpointEditor adds _isInitialized flag to suppress TextChanged
  during construction (restores WPF IsLoaded guard behavior)
- S1: Timeclock unsubscribes from Source events in OnDetachedFromVisualTree

Second round PR comments:
- Fix SmoothScroll ConditionalWeakTable.AddOrUpdate → Add (API doesn't exist)
- AvoidEmptyGameDirectoryAsync falls back to MainWindow when owner is null
- Remove unused fileName parameter from ClipboardExtensions.SetImage

* Address PR review findings and reviewer comments

Review findings addressed:
- [M1] Wire 5 Settings dialog handlers (OpenCustomVersions, OpenOptions,
  OpenMapStructTypes, OpenAesEndpoint, OpenMappingEndpoint) to actual
  DictionaryEditor/EndpointEditor modal calls instead of no-op stubs
- [M2] Add TODO(P3-perf) comment documenting WrapPanel virtualization tradeoff
- [m1] Add template fallback in SettingsView to clear ContentTemplate on
  failed resource lookup
- [m2] Improve clipboard image format parity by adding PNG and Bitmap formats
- [S1] Replace hardcoded #DAE5F2 icon fills with DynamicResource
  SystemColors.ControlTextBrushKey in both context menus
- [S2] Simplify TypeDataTemplateSelector by removing redundant global guard

PR reviewer comments addressed:
- EndpointEditor: Fix OnTextChanged signature (EventArgs -> TextChangedEventArgs)
- FolderContextMenu: Fix FindAncestor to use GetVisualAncestors() instead of
  unreliable Parent cast chain
- CommitDownloaderControl: Fix button Width binding (.Bounds.Height ->
  .Height) to avoid zero during initial layout
- ApplicationViewModel: Make RestartWithWarningAsync okButton a direct reference
  instead of brittle Children[1] index cast

* Address review findings and PR comments (round 2)

Major fixes:
- M1: ImGuiController now probes Linux font directories (DejaVu Sans,
  Liberation Sans, Noto Sans) instead of hardcoding Windows paths
- M2: ClipboardExtensions.SetImage wraps MemoryStream/Bitmap in using
  statements to prevent native resource leaks
- M3: ImageCommand divides PixelSize by DPI scale for correct HiDPI
  window sizing

Minor fixes:
- m1: Document Timeclock threading contract for CalculateTime
- m2: CommitDownloaderControl uses fixed 32x32 button size instead of
  Bounds-based binding that yields 0 during initial layout
- m3: Resources.xaml reformatted to consistent indentation
- m4: FolderToGeometryConverter adds parentheses for operator precedence

Suggestions applied:
- S1: Extract ClipboardExtensions.SetText helper; update CopyCommand,
  TabCommand, and FolderContextMenu to use it consistently

PR comments addressed:
- FileContextMenu.xaml: Replace fragile $parent[Window].DataContext with
  Opened handler that resolves DataContext from PlacementTarget visual tree
  (new FileContextMenu.xaml.cs code-behind)
- RestartWithWarningAsync: Accept optional Window owner parameter so
  callers (SettingsView) can pass their window for proper modal parenting
- ClipboardExtensions bitmap leak: Fixed (same as M2)

No new build errors introduced (78 pre-existing in unmigrated files).

* fix: address second review findings (M1, M2, m1, m2, S1) and TitleExtra null guard

- Remove [AggressiveInlining] from ResolveFontPaths and cache result
  in static Lazy<> (M1 + S1)
- Remove using disposal on Bitmap/MemoryStream in SetImage to prevent
  ObjectDisposedException on X11 deferred clipboard reads (M2)
- CommitDownloader button now binds Height to sibling grid, restoring
  parent-relative sizing with MinWidth/MinHeight fallback (m1)
- Add Log.Warning when FileContextMenu cannot find Window ancestor (m2)
- Guard TitleExtra against null CurrentDir (unresolved PR comment)

* fix: address third review findings and 3 unresolved PR comments

- ClipboardExtensions.SetImage: dispose MemoryStream after Bitmap
  decoding (Bitmap copies pixel data during construction); keep Bitmap
  alive for X11/Wayland deferred clipboard rendering
- MenuCommand: add null guards for CUE4Parse before dereferencing in
  Directory_Backup, Directory_ArchivesInfo, Views_3dViewer, and
  ToolBox_Collapse_All cases
- CommitDownloaderControl: revert to deterministic Width=32 Height=32
  to avoid Bounds.Height instability during initial layout

* fix: breadcrumb button filter, one-shot context menu, nullable guards

- Breadcrumb: filter PointerReleased by left button only (M2)
- TypeDataTemplateSelector: one-shot AttachedToVisualTree handler (m1)
- DictionaryEditor: initialize properties to empty defaults, null-coalesce
  DeserializeObject results (PR comment)
- Resources.xaml: document SelectionMode mapping (S1)

* fix: CurrentDir NRE guard, discard ExtractAsync, clean up null checks

- ApplicationViewModel: null-safe CurrentDir?.Equals() in AvoidEmptyGameDirectoryAsync (M1)
- ListBoxItemBehavior: explicit discard on fire-and-forget ExtractAsync (S1/PR)
- SettingsView: remove redundant null checks on DictionaryEditor properties (m1)

* fix: add Cancel click handler to DictionaryEditor

Avalonia's IsCancel="True" maps Escape to the button's Click event but
does not auto-close the window like WPF does. Without a handler, the
Cancel button and Escape key left the dialog stuck.
2026-03-16 14:17:00 -06:00

30 lines
709 B
C#

using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using FModel.ViewModels.ApiEndpoints.Models;
namespace FModel.Views.Resources.Controls;
public partial class CommitDownloaderControl : UserControl
{
public CommitDownloaderControl()
{
InitializeComponent();
}
public static readonly StyledProperty<GitHubCommit?> CommitProperty =
AvaloniaProperty.Register<CommitDownloaderControl, GitHubCommit?>(nameof(Commit));
public GitHubCommit? Commit
{
get => GetValue(CommitProperty);
set => SetValue(CommitProperty, value);
}
private void OnDownload(object? sender, RoutedEventArgs e)
{
Commit?.Download();
}
}