diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Collection/AdvancedCollectionView/AdvancedCollectionView.Defer.cs b/src/Snap.Hutao/Snap.Hutao/Control/Collection/AdvancedCollectionView/AdvancedCollectionView.Defer.cs new file mode 100644 index 0000000000..3e84fd0ef6 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Collection/AdvancedCollectionView/AdvancedCollectionView.Defer.cs @@ -0,0 +1,54 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Control.Collection.AdvancedCollectionView; + +/// +/// A collection view implementation that supports filtering, grouping, sorting and incremental loading +/// +internal partial class AdvancedCollectionView +{ + /// + /// Stops refreshing until it is disposed + /// + /// An disposable object + public IDisposable DeferRefresh() + { + return new NotificationDeferrer(this); + } + + /// + /// Notification deferrer helper class + /// +#pragma warning disable CA1063 // Implement IDisposable Correctly + public class NotificationDeferrer : IDisposable +#pragma warning restore CA1063 // Implement IDisposable Correctly + { + private readonly AdvancedCollectionView _acvs; + private readonly object _currentItem; + + /// + /// Initializes a new instance of the class. + /// + /// Source ACVS + public NotificationDeferrer(AdvancedCollectionView acvs) + { + _acvs = acvs; + _currentItem = _acvs.CurrentItem; + _acvs._deferCounter++; + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// 2 +#pragma warning disable CA1063 // Implement IDisposable Correctly + public void Dispose() +#pragma warning restore CA1063 // Implement IDisposable Correctly + { + _acvs.MoveCurrentTo(_currentItem); + _acvs._deferCounter--; + _acvs.Refresh(); + } + } +} diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Collection/AdvancedCollectionView/AdvancedCollectionView.Events.cs b/src/Snap.Hutao/Snap.Hutao/Control/Collection/AdvancedCollectionView/AdvancedCollectionView.Events.cs new file mode 100644 index 0000000000..56d8233e14 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Collection/AdvancedCollectionView/AdvancedCollectionView.Events.cs @@ -0,0 +1,61 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.UI.Xaml.Data; +using Windows.Foundation.Collections; + +namespace Snap.Hutao.Control.Collection.AdvancedCollectionView; + +/// +/// A collection view implementation that supports filtering, grouping, sorting and incremental loading +/// +internal partial class AdvancedCollectionView +{ + /// + /// Currently selected item changing event + /// + /// event args + private void OnCurrentChanging(CurrentChangingEventArgs e) + { + if (_deferCounter > 0) + { + return; + } + + CurrentChanging?.Invoke(this, e); + } + + /// + /// Currently selected item changed event + /// + /// event args + private void OnCurrentChanged(object e) + { + if (_deferCounter > 0) + { + return; + } + + CurrentChanged?.Invoke(this, e); + + // ReSharper disable once ExplicitCallerInfoArgument + OnPropertyChanged(nameof(CurrentItem)); + } + + /// + /// Vector changed event + /// + /// event args + private void OnVectorChanged(IVectorChangedEventArgs e) + { + if (_deferCounter > 0) + { + return; + } + + VectorChanged?.Invoke(this, e); + + // ReSharper disable once ExplicitCallerInfoArgument + OnPropertyChanged(nameof(Count)); + } +} diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Collection/AdvancedCollectionView/AdvancedCollectionView.cs b/src/Snap.Hutao/Snap.Hutao/Control/Collection/AdvancedCollectionView/AdvancedCollectionView.cs new file mode 100644 index 0000000000..58557fd3fa --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Collection/AdvancedCollectionView/AdvancedCollectionView.cs @@ -0,0 +1,816 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using System.Collections; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Reflection; +using System.Runtime.CompilerServices; +using CommunityToolkit.WinUI.Collections; +using CommunityToolkit.WinUI.Helpers; +using Microsoft.UI.Xaml.Data; +using Windows.Foundation; +using Windows.Foundation.Collections; +using NotifyCollectionChangedAction = global::System.Collections.Specialized.NotifyCollectionChangedAction; + +namespace Snap.Hutao.Control.Collection.AdvancedCollectionView; + +/// +/// A collection view implementation that supports filtering, sorting and incremental loading +/// https://github.com/CommunityToolkit/Windows/pull/309 +/// +internal partial class AdvancedCollectionView : IAdvancedCollectionView, INotifyPropertyChanged, ISupportIncrementalLoading, IComparer +{ + private readonly List _view; + + private readonly ObservableCollection _sortDescriptions; + + private readonly Dictionary _sortProperties; + + private readonly bool _liveShapingEnabled; + + private readonly HashSet _observedFilterProperties = new HashSet(); + + private IList _source; + + private Predicate _filter; + private int _deferCounter; + + private WeakEventListener _sourceWeakEventListener; + + /// + /// Initializes a new instance of the class. + /// + public AdvancedCollectionView() + : this(new List(0)) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// source IEnumerable + /// Denotes whether or not this ACV should re-filter/re-sort if a PropertyChanged is raised for an observed property. +#pragma warning disable CS8767 +#pragma warning disable CS8769 +#pragma warning disable CS8622 +#pragma warning disable CS8600 +#pragma warning disable CS8601 +#pragma warning disable CS8604 +#pragma warning disable CS8603 // Possible null reference return. +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public AdvancedCollectionView(IList source, bool isLiveShaping = false) + { + _liveShapingEnabled = isLiveShaping; + _view = new List(); + _sortDescriptions = new ObservableCollection(); + _sortDescriptions.CollectionChanged += SortDescriptions_CollectionChanged; + _sortProperties = new Dictionary(); + Source = source; + } + + /// + /// Gets or sets the source + /// + public IList Source + { + get + { + return _source; + } + + set + { + // ReSharper disable once PossibleUnintendedReferenceComparison + if (_source == value) + { + return; + } + + if (_source != null) + { + DetachPropertyChangedHandler(_source); + } + + _source = value; + AttachPropertyChangedHandler(_source); + + _sourceWeakEventListener?.Detach(); + + if (_source is INotifyCollectionChanged sourceNcc) + { + _sourceWeakEventListener = + new WeakEventListener(this) + { + // Call the actual collection changed event + OnEventAction = (source, changed, arg3) => SourceNcc_CollectionChanged(source, arg3), + + // The source doesn't exist anymore + OnDetachAction = (listener) => sourceNcc.CollectionChanged -= _sourceWeakEventListener!.OnEvent + }; + sourceNcc.CollectionChanged += _sourceWeakEventListener.OnEvent; + } + + HandleSourceChanged(); + OnPropertyChanged(); + } + } + + /// + /// Manually refresh the view + /// + public void Refresh() + { + HandleSourceChanged(); + } + + /// + public void RefreshFilter() + { + HandleFilterChanged(); + } + + /// + public void RefreshSorting() + { + HandleSortChanged(); + } + + /// + public IEnumerator GetEnumerator() => _view.GetEnumerator(); + + /// + IEnumerator IEnumerable.GetEnumerator() => _view.GetEnumerator(); + + /// + public void Add(object item) + { + if (IsReadOnly) + { + throw new NotSupportedException("Collection is read-only."); + } + + _source.Add(item); + } + + /// + public void Clear() + { + if (IsReadOnly) + { + throw new NotSupportedException("Collection is read-only."); + } + + _source.Clear(); + } + + /// + public bool Contains(object item) => _view.Contains(item); + + /// + public void CopyTo(object[] array, int arrayIndex) => _view.CopyTo(array, arrayIndex); + + /// + public bool Remove(object item) + { + if (IsReadOnly) + { + throw new NotSupportedException("Collection is read-only."); + } + + _source.Remove(item); + return true; + } + + /// + public int Count => _view.Count; + + /// + public bool IsReadOnly => _source == null || _source.IsReadOnly; + + /// + public int IndexOf(object item) => _view.IndexOf(item); + + /// + public void Insert(int index, object item) + { + if (IsReadOnly) + { + throw new NotSupportedException("Collection is read-only."); + } + + _source.Insert(index, item); + } + + /// + /// Removes the item at the specified index. + /// + /// The zero-based index of the item to remove. is not a valid index in the .The is read-only. + public void RemoveAt(int index) => Remove(_view[index]); + + /// + /// Gets or sets the element at the specified index. + /// + /// + /// The element at the specified index. + /// + /// The zero-based index of the element to get or set. is not a valid index in the .The property is set and the is read-only. + public object this[int index] + { + get { return _view[index]; } + set { _view[index] = value; } + } + + /// + /// Occurs when the vector changes. + /// + public event Windows.Foundation.Collections.VectorChangedEventHandler VectorChanged; + + /// + /// Move current index to item + /// + /// item + /// success of operation + public bool MoveCurrentTo(object item) => item == CurrentItem || MoveCurrentToIndex(IndexOf(item)); + + /// + /// Moves selected item to position + /// + /// index + /// success of operation + public bool MoveCurrentToPosition(int index) => MoveCurrentToIndex(index); + + /// + /// Move current item to first item + /// + /// success of operation + public bool MoveCurrentToFirst() => MoveCurrentToIndex(0); + + /// + /// Move current item to last item + /// + /// success of operation + public bool MoveCurrentToLast() => MoveCurrentToIndex(_view.Count - 1); + + /// + /// Move current item to next item + /// + /// success of operation + public bool MoveCurrentToNext() => MoveCurrentToIndex(CurrentPosition + 1); + + /// + /// Move current item to previous item + /// + /// success of operation + public bool MoveCurrentToPrevious() => MoveCurrentToIndex(CurrentPosition - 1); + + /// + /// Load more items from the source + /// + /// number of items to load + /// Async operation of LoadMoreItemsResult + /// Not implemented yet... + public IAsyncOperation LoadMoreItemsAsync(uint count) + { + var sil = _source as ISupportIncrementalLoading; + return sil?.LoadMoreItemsAsync(count); + } + + /// + /// Gets the groups in collection + /// + public IObservableVector CollectionGroups => null; + + /// + /// Gets or sets the current item + /// + public object CurrentItem + { + + get { return CurrentPosition > -1 && CurrentPosition < _view.Count ? _view[CurrentPosition] : null; } +#pragma warning restore CS8603 // Possible null reference return. + set { MoveCurrentTo(value); } + } + + /// + /// Gets the position of current item + /// + public int CurrentPosition { get; private set; } + + /// + /// Gets a value indicating whether the source has more items + /// + public bool HasMoreItems => (_source as ISupportIncrementalLoading)?.HasMoreItems ?? false; + + /// + /// Gets a value indicating whether the current item is after the last visible item + /// + public bool IsCurrentAfterLast => CurrentPosition >= _view.Count; + + /// + /// Gets a value indicating whether the current item is before the first visible item + /// + public bool IsCurrentBeforeFirst => CurrentPosition < 0; + + /// + /// Current item changed event handler + /// + public event EventHandler CurrentChanged; + + /// + /// Current item changing event handler + /// + public event CurrentChangingEventHandler CurrentChanging; + + /// + /// Gets a value indicating whether this CollectionView can filter its items + /// + public bool CanFilter => true; + + /// + /// Gets or sets the predicate used to filter the visible items + /// + public Predicate Filter + { + get + { + return _filter; + } + + set + { + if (_filter == value) + { + return; + } + + _filter = value; + HandleFilterChanged(); + } + } + + /// + /// Gets a value indicating whether this CollectionView can sort its items + /// + public bool CanSort => true; + + /// + /// Gets SortDescriptions to sort the visible items + /// + public IList SortDescriptions => _sortDescriptions; + + /* + /// + /// Gets a value indicating whether this CollectionView can group its items + /// + public bool CanGroup => false; + + /// + /// Gets GroupDescriptions to group the visible items + /// + public IList GroupDescriptions => null; + */ + + /// + /// Gets the source collection + /// + public IEnumerable SourceCollection => _source; + + /// + /// IComparer implementation + /// + /// Object A + /// Object B + /// Comparison value +#pragma warning disable CA1033 // Interface methods should be callable by child types + int IComparer.Compare(object x, object y) +#pragma warning restore CA1033 // Interface methods should be callable by child types + { + if (!_sortProperties.Any()) + { + var listType = _source?.GetType(); + Type type; + + if (listType != null && listType.IsGenericType) + { + type = listType.GetGenericArguments()[0]; + } + else + { + type = x.GetType(); + } + + foreach (var sd in _sortDescriptions) + { + if (!string.IsNullOrEmpty(sd.PropertyName)) + { + _sortProperties[sd.PropertyName] = type.GetProperty(sd.PropertyName); + } + } + } + + foreach (var sd in _sortDescriptions) + { + object cx, cy; + + if (string.IsNullOrEmpty(sd.PropertyName)) + { + cx = x; + cy = y; + } + else + { + var pi = _sortProperties[sd.PropertyName]; + + cx = pi.GetValue(x!); + cy = pi.GetValue(y!); + } + + var cmp = sd.Comparer.Compare(cx, cy); + + if (cmp != 0) + { + return sd.Direction == SortDirection.Ascending ? +cmp : -cmp; + } + } + + return 0; + } + + /// + /// Occurs when a property value changes. + /// + public event PropertyChangedEventHandler? PropertyChanged; + + /// + /// Property changed event invoker + /// + /// name of the property that changed + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null!) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + /// + public void ObserveFilterProperty(string propertyName) + { + _observedFilterProperties.Add(propertyName); + } + + /// + public void ClearObservedFilterProperties() + { + _observedFilterProperties.Clear(); + } + + private void ItemOnPropertyChanged(object item, PropertyChangedEventArgs e) + { + if (!_liveShapingEnabled) + { + return; + } + + var filterResult = _filter?.Invoke(item); + + if (filterResult.HasValue && _observedFilterProperties.Contains(e.PropertyName)) + { + var viewIndex = _view.IndexOf(item); + if (viewIndex != -1 && !filterResult.Value) + { + RemoveFromView(viewIndex, item); + } + else if (viewIndex == -1 && filterResult.Value) + { + var index = _source.IndexOf(item); + HandleItemAdded(index, item); + } + } + + if ((filterResult ?? true) && SortDescriptions.Any(sd => sd.PropertyName == e.PropertyName)) + { + var oldIndex = _view.IndexOf(item); + + // Check if item is in view: + if (oldIndex < 0) + { + return; + } + + _view.RemoveAt(oldIndex); + var targetIndex = _view.BinarySearch(item, this); + if (targetIndex < 0) + { + targetIndex = ~targetIndex; + } + + // Only trigger expensive UI updates if the index really changed: + if (targetIndex != oldIndex) + { + OnVectorChanged(new VectorChangedEventArgs(CollectionChange.ItemRemoved, oldIndex, item)); + + _view.Insert(targetIndex, item); + + OnVectorChanged(new VectorChangedEventArgs(CollectionChange.ItemInserted, targetIndex, item)); + } + else + { + _view.Insert(targetIndex, item); + } + } + else if (string.IsNullOrEmpty(e.PropertyName)) + { + HandleSourceChanged(); + } + } + + private void AttachPropertyChangedHandler(IEnumerable items) + { + if (!_liveShapingEnabled || items == null) + { + return; + } + + foreach (var item in items.OfType()) + { + item.PropertyChanged += ItemOnPropertyChanged; + } + } + + private void DetachPropertyChangedHandler(IEnumerable items) + { + if (!_liveShapingEnabled || items == null) + { + return; + } + + foreach (var item in items.OfType()) + { + item.PropertyChanged -= ItemOnPropertyChanged; + } + } + + private void HandleSortChanged() + { + _sortProperties.Clear(); + _view.Sort(this); + _sortProperties.Clear(); + OnVectorChanged(new VectorChangedEventArgs(CollectionChange.Reset)); + } + + private void HandleFilterChanged() + { + if (_filter != null) + { + for (var index = 0; index < _view.Count; index++) + { + var item = _view.ElementAt(index); + if (_filter(item)) + { + continue; + } + + RemoveFromView(index, item); + index--; + } + } + + var viewHash = new HashSet(_view); + var viewIndex = 0; + for (var index = 0; index < _source.Count; index++) + { + var item = _source[index]; + if (viewHash.Contains(item)) + { + viewIndex++; + continue; + } + + if (HandleItemAdded(index, item, viewIndex)) + { + viewIndex++; + } + } + } + + private void HandleSourceChanged() + { + _sortProperties.Clear(); + var currentItem = CurrentItem; + _view.Clear(); + foreach (var item in Source) + { + if (_filter != null && !_filter(item)) + { + continue; + } + + if (_sortDescriptions.Any()) + { + var targetIndex = _view.BinarySearch(item, this); + if (targetIndex < 0) + { + targetIndex = ~targetIndex; + } + + _view.Insert(targetIndex, item); + } + else + { + _view.Add(item); + } + } + + _sortProperties.Clear(); + OnVectorChanged(new VectorChangedEventArgs(CollectionChange.Reset)); + MoveCurrentTo(currentItem); + } + + private void SourceNcc_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + // ReSharper disable once SwitchStatementMissingSomeCases + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + AttachPropertyChangedHandler(e.NewItems); + if (_deferCounter <= 0) + { + if (e.NewItems?.Count == 1) + { + HandleItemAdded(e.NewStartingIndex, e.NewItems[0]); + } + else + { + HandleSourceChanged(); + } + } + + break; + case NotifyCollectionChangedAction.Remove: + DetachPropertyChangedHandler(e.OldItems); + if (_deferCounter <= 0) + { + if (e.OldItems?.Count == 1) + { + HandleItemRemoved(e.OldStartingIndex, e.OldItems[0]); + } + else + { + HandleSourceChanged(); + } + } + + break; + case NotifyCollectionChangedAction.Move: + case NotifyCollectionChangedAction.Replace: + case NotifyCollectionChangedAction.Reset: + if (_deferCounter <= 0) + { + HandleSourceChanged(); + } + + break; + } + } + + private bool HandleItemAdded(int newStartingIndex, object newItem, int? viewIndex = null) + { + if (_filter != null && !_filter(newItem)) + { + return false; + } + + var newViewIndex = _view.Count; + + if (_sortDescriptions.Any()) + { + _sortProperties.Clear(); + newViewIndex = _view.BinarySearch(newItem, this); + if (newViewIndex < 0) + { + newViewIndex = ~newViewIndex; + } + } + else if (_filter != null) + { + if (_source == null) + { + HandleSourceChanged(); + return false; + } + + if (newStartingIndex == 0 || _view.Count == 0) + { + newViewIndex = 0; + } + else if (newStartingIndex == _source.Count - 1) + { + newViewIndex = _view.Count; + } + else if (viewIndex.HasValue) + { + newViewIndex = viewIndex.Value; + } + else + { + for (int i = 0, j = 0; i < _source.Count; i++) + { + if (i == newStartingIndex) + { + newViewIndex = j; + break; + } + + if (_view[j] == _source[i]) + { + j++; + } + } + } + } + + _view.Insert(newViewIndex, newItem); + if (newViewIndex <= CurrentPosition) + { + CurrentPosition++; + } + + var e = new VectorChangedEventArgs(CollectionChange.ItemInserted, newViewIndex, newItem); + OnVectorChanged(e); + return true; + } + + private void HandleItemRemoved(int oldStartingIndex, object oldItem) + { + if (_filter != null && !_filter(oldItem)) + { + return; + } + + if (oldStartingIndex < 0 || oldStartingIndex >= _view.Count || !Equals(_view[oldStartingIndex], oldItem)) + { + oldStartingIndex = _view.IndexOf(oldItem); + } + + if (oldStartingIndex < 0) + { + return; + } + + RemoveFromView(oldStartingIndex, oldItem); + } + + private void RemoveFromView(int itemIndex, object item) + { + _view.RemoveAt(itemIndex); + if (itemIndex <= CurrentPosition) + { + CurrentPosition--; + } + + var e = new VectorChangedEventArgs(CollectionChange.ItemRemoved, itemIndex, item); + OnVectorChanged(e); + } + + private void SortDescriptions_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (_deferCounter > 0) + { + return; + } + + HandleSortChanged(); + } + + private bool MoveCurrentToIndex(int i) + { + if (i < -1 || i >= _view.Count) + { + return false; + } + + if (i == CurrentPosition) + { + return false; + } + + var e = new CurrentChangingEventArgs(); + OnCurrentChanging(e); + if (e.Cancel) + { + return false; + } + + CurrentPosition = i; + OnCurrentChanged(null!); + return true; + } +} + +#pragma warning restore CS8767 +#pragma warning restore CS8769 +#pragma warning restore CS8622 +#pragma warning restore CS8601 +#pragma warning restore CS8600 +#pragma warning restore CS8604 +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. +#pragma warning restore CS8603 // Possible null reference return. diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Collection/AdvancedCollectionView/VectorChangedEventArgs.cs b/src/Snap.Hutao/Snap.Hutao/Control/Collection/AdvancedCollectionView/VectorChangedEventArgs.cs new file mode 100644 index 0000000000..168ca7d9f3 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Collection/AdvancedCollectionView/VectorChangedEventArgs.cs @@ -0,0 +1,40 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Windows.Foundation.Collections; + +namespace Snap.Hutao.Control.Collection.AdvancedCollectionView; + +/// +/// Vector changed EventArgs +/// +internal class VectorChangedEventArgs : IVectorChangedEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// collection change type + /// index of item changed + /// item changed + public VectorChangedEventArgs(CollectionChange cc, int index = -1, object item = null!) + { + CollectionChange = cc; + Index = (uint)index; + } + + /// + /// Gets the type of change that occurred in the vector. + /// + /// + /// The type of change in the vector. + /// + public CollectionChange CollectionChange { get; } + + /// + /// Gets the position where the change occurred in the vector. + /// + /// + /// The zero-based position where the change occurred in the vector, if applicable. + /// + public uint Index { get; } +} diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs index 8c3b69ac22..7bffcb8823 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs @@ -1,8 +1,8 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using CommunityToolkit.WinUI.Collections; using Microsoft.UI.Xaml.Controls; +using Snap.Hutao.Control.Collection.AdvancedCollectionView; using Snap.Hutao.Core.IO; using Snap.Hutao.Core.LifeCycle; using Snap.Hutao.Factory.ContentDialog; @@ -18,6 +18,8 @@ using EntityAchievementArchive = Snap.Hutao.Model.Entity.AchievementArchive; using MetadataAchievement = Snap.Hutao.Model.Metadata.Achievement.Achievement; using MetadataAchievementGoal = Snap.Hutao.Model.Metadata.Achievement.AchievementGoal; +using SortDescription = CommunityToolkit.WinUI.Collections.SortDescription; +using SortDirection = CommunityToolkit.WinUI.Collections.SortDirection; namespace Snap.Hutao.ViewModel.Achievement; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs index db52d5dce2..db6c01909c 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs @@ -1,9 +1,9 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using CommunityToolkit.WinUI.Collections; using Microsoft.Extensions.Caching.Memory; using Microsoft.UI.Windowing; +using Snap.Hutao.Control.Collection.AdvancedCollectionView; using Snap.Hutao.Core; using Snap.Hutao.Core.Database; using Snap.Hutao.Core.Diagnostics.CodeAnalysis; @@ -241,8 +241,6 @@ private async Task DetectGameAccountAsync() { await taskContext.SwitchToMainThreadAsync(); SelectedGameAccount = account; - - await UpdateGameAccountsViewAsync().ConfigureAwait(false); } } catch (UserdataCorruptedException ex) @@ -328,6 +326,18 @@ async ValueTask UpdateGameResourceAsync(LaunchScheme? scheme) GameResource = response.Data; } } + + async ValueTask UpdateGameAccountsViewAsync() + { + gameAccountFilter = new(SelectedScheme?.GetSchemeType()); + ObservableReorderableDbCollection accounts = gameService.GameAccountCollection; + + await taskContext.SwitchToMainThreadAsync(); + GameAccountsView = new(accounts, true) + { + Filter = gameAccountFilter.Filter, + }; + } } [Command("IdentifyMonitorsCommand")] @@ -353,16 +363,4 @@ private async Task IdentifyMonitorsAsync() window.Close(); } } - - private async ValueTask UpdateGameAccountsViewAsync() - { - gameAccountFilter = new(SelectedScheme?.GetSchemeType()); - ObservableReorderableDbCollection accounts = gameService.GameAccountCollection; - - await taskContext.SwitchToMainThreadAsync(); - GameAccountsView = new(accounts, true) - { - Filter = gameAccountFilter.Filter, - }; - } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModelSlim.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModelSlim.cs index a7d2931501..9fbb76c9eb 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModelSlim.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModelSlim.cs @@ -1,7 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using CommunityToolkit.WinUI.Collections; +using Snap.Hutao.Control.Collection.AdvancedCollectionView; using Snap.Hutao.Core.ExceptionService; using Snap.Hutao.Model.Entity; using Snap.Hutao.Service.Game; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs index e0b4bad641..e50fba5c60 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs @@ -1,7 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using CommunityToolkit.WinUI.Collections; +using Snap.Hutao.Control.Collection.AdvancedCollectionView; using Snap.Hutao.Factory.ContentDialog; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Entity.Primitive; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiMonsterViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiMonsterViewModel.cs index cd42acc11b..ace8bf7fe5 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiMonsterViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiMonsterViewModel.cs @@ -1,7 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using CommunityToolkit.WinUI.Collections; +using Snap.Hutao.Control.Collection.AdvancedCollectionView; using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Metadata.Item; using Snap.Hutao.Model.Metadata.Monster; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs index d64196c833..85608aece6 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs @@ -1,7 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using CommunityToolkit.WinUI.Collections; +using Snap.Hutao.Control.Collection.AdvancedCollectionView; using Snap.Hutao.Factory.ContentDialog; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Entity.Primitive;