Skip to content

Commit

Permalink
feat: Quick switch button added for switching between games (Jorixon#138
Browse files Browse the repository at this point in the history
)

chore: Redid Date Added sorting logic

fix: Potential fix for crash when navigating to character after mod install

feat: When navigating back from a character page to the character overview, it will now scroll that character into view
  • Loading branch information
Jorixon authored Mar 12, 2024
1 parent 0ab7448 commit ec8adc2
Show file tree
Hide file tree
Showing 14 changed files with 266 additions and 43 deletions.
15 changes: 15 additions & 0 deletions src/GIMI-ModManager.Core/GamesService/GameService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,21 @@ public async Task InitializeAsync(string assetsDirectory, string localSettingsDi
Initialized?.Invoke(this, EventArgs.Empty);
}

public async Task<GameInfo?> GetGameInfoAsync(SupportedGames game)
{
var gameFilePath = Path.Combine(_assetsDirectory.Parent!.FullName, game.ToString(), FileNames.GameSettingsFileName);

if (!File.Exists(gameFilePath))
return null;

var jsonGameInfo = JsonSerializer.Deserialize<JsonGame>(await File.ReadAllTextAsync(gameFilePath));

if (jsonGameInfo is null)
throw new InvalidOperationException($"{gameFilePath} file is empty");

return new GameInfo(jsonGameInfo, new DirectoryInfo(Path.Combine(_assetsDirectory.Parent!.FullName, game.ToString())));
}

public async Task<ICollection<InternalName>> PreInitializedReadModObjectsAsync(string assetsDirectory)
{
if (_initialized)
Expand Down
2 changes: 2 additions & 0 deletions src/GIMI-ModManager.Core/GamesService/IGameService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public interface IGameService

public event EventHandler? Initialized;

public Task<GameInfo?> GetGameInfoAsync(SupportedGames game);

public Task<ICollection<InternalName>> PreInitializedReadModObjectsAsync(string assetsDirectory);

public Task InitializeAsync(string assetsDirectory, string localSettingsDirectory,
Expand Down
29 changes: 29 additions & 0 deletions src/GIMI-ModManager.Core/Helpers/AsyncLock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace GIMI_ModManager.Core.Helpers;

public sealed class AsyncLock : IDisposable
{
private readonly SemaphoreSlim _semaphore = new(1, 1);

public async Task<LockReleaser> LockAsync(int timeout = -1, CancellationToken cancellationToken = default)
{
await _semaphore.WaitAsync(timeout, cancellationToken).ConfigureAwait(false);
return new LockReleaser(Release);
}

private void Release() => _semaphore.Release();

public void Dispose() => _semaphore.Dispose();
}

public readonly struct LockReleaser : IDisposable
{
private readonly Action _release;

internal LockReleaser(Action release)
{
_release = release;
}

public void Dispose() => _release();
public void Release() => _release();
}
25 changes: 25 additions & 0 deletions src/GIMI-ModManager.WinUI/Contracts/Services/INavigationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,29 @@ public interface INavigationService
void SetListDataItemForNextConnectedAnimation(object item);

public ICollection<PageStackEntry> GetBackStackItems();
public IReadOnlyCollection<NavigationHistoryItem> GetNavigationHistory();
}

public record NavigationHistoryItem
{
public NavigationHistoryItem(Type PageType, object? Parameter)
{
this.PageType = PageType;
this.Parameter = Parameter;
}

public NavigationHistoryItem(PageStackEntry pageStackEntry)
{
PageType = pageStackEntry.SourcePageType;
Parameter = pageStackEntry.Parameter;
}

public Type PageType { get; init; }
public object? Parameter { get; init; }

public void Deconstruct(out Type PageType, out object? Parameter)
{
PageType = this.PageType;
Parameter = this.Parameter;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ public async Task<string> GetSelectedGameAsync()
return selectedGame.SelectedGame;
}

public async Task<SupportedGames> GetNotSelectedGameAsync()
{
var selectedGame = await GetSelectedGameAsync();

return selectedGame switch
{
Genshin => SupportedGames.Honkai,
Honkai => SupportedGames.Genshin,
_ => throw new ArgumentOutOfRangeException()
};
}


public Task SaveSelectedGameAsync(string game)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ private async Task RunCheckerAsync(ModCheckOperation modCheckOperation, Cancella
OnUpdateCheckerEvent?.Invoke(this, new UpdateCheckerEvent(Status));

var stopWatch = Stopwatch.StartNew();
await CheckForUpdates(modCheckOperation, cancellationToken: runningCancellationToken).ConfigureAwait(false);
var anyModsChecked = await CheckForUpdates(modCheckOperation, cancellationToken: runningCancellationToken).ConfigureAwait(false);
stopWatch.Stop();

_logger.Debug("Finished checking for mod updates in {Elapsed}", stopWatch.Elapsed);
Expand All @@ -235,7 +235,7 @@ private async Task RunCheckerAsync(ModCheckOperation modCheckOperation, Cancella
$" {modCheckOperation.ModCheckRequest.Characters.First().DisplayName}",
TimeSpan.FromSeconds(4));
}
else
else if (anyModsChecked)
{
_notificationManager.ShowNotification("Finished checking for mod updates",
"Finished checking for mod updates", TimeSpan.FromSeconds(4));
Expand Down Expand Up @@ -269,7 +269,7 @@ private async Task<bool> IsValidForCheckAsync(CharacterSkinEntry skinEntry, bool
return true;
}

private async Task CheckForUpdates(ModCheckOperation modCheckOperation,
private async Task<bool> CheckForUpdates(ModCheckOperation modCheckOperation,
CancellationToken cancellationToken = default)
{
var modEntries = modCheckOperation.ModsToCheck;
Expand Down Expand Up @@ -297,7 +297,7 @@ private async Task CheckForUpdates(ModCheckOperation modCheckOperation,
if (!tasks.Any())
{
_logger.Debug("No mods to check for updates");
return;
return false;
}


Expand Down Expand Up @@ -326,6 +326,7 @@ private async Task CheckForUpdates(ModCheckOperation modCheckOperation,
}

modCheckOperation.RequestFinished();
return true;
}

private Task AddModNotifications(CharacterSkinEntry characterSkinEntry, ModsRetrievedResult result)
Expand Down
12 changes: 12 additions & 0 deletions src/GIMI-ModManager.WinUI/Services/NavigationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class NavigationService : INavigationService
private readonly IPageService _pageService;
private object? _lastParameterUsed;
private Frame? _frame;
private readonly List<NavigationHistoryItem> _navigationHistory = new();

public event NavigatedEventHandler? Navigated;

Expand Down Expand Up @@ -71,12 +72,14 @@ public bool GoForward()
if (CanGoForward)
{
var vmBeforeNavigation = _frame.GetPageViewModel();
var pageStackEntry = _frame.ForwardStack.Last();
_frame.GoForward();
if (vmBeforeNavigation is INavigationAware navigationAware)
{
navigationAware.OnNavigatedFrom();
}

_navigationHistory.Add(new NavigationHistoryItem(pageStackEntry));
return true;
}

Expand All @@ -88,12 +91,14 @@ public bool GoBack()
if (CanGoBack)
{
var vmBeforeNavigation = _frame.GetPageViewModel();
var pageStackEntry = _frame.BackStack.Last();
_frame.GoBack();
if (vmBeforeNavigation is INavigationAware navigationAware)
{
navigationAware.OnNavigatedFrom();
}

_navigationHistory.Add(new NavigationHistoryItem(pageStackEntry));
return true;
}

Expand All @@ -119,6 +124,8 @@ public bool NavigateTo(string pageKey, object? parameter = null, bool clearNavig
}
}

_navigationHistory.Add(new NavigationHistoryItem(pageType, parameter));

return navigated;
}

Expand Down Expand Up @@ -146,6 +153,10 @@ private void OnNavigated(object sender, NavigationEventArgs e)
}
}

if (_navigationHistory.Count > maxBackStackEntries)
{
_navigationHistory.RemoveRange(0, maxBackStackEntries - 1);
}

if (frame.GetPageViewModel() is INavigationAware navigationAware)
{
Expand All @@ -162,4 +173,5 @@ public void SetListDataItemForNextConnectedAnimation(object item) =>
// Get BackStackItems from Frame

public ICollection<PageStackEntry> GetBackStackItems() => Frame?.BackStack ?? Array.Empty<PageStackEntry>();
public IReadOnlyCollection<NavigationHistoryItem> GetNavigationHistory() => _navigationHistory.ToArray();
}
37 changes: 22 additions & 15 deletions src/GIMI-ModManager.WinUI/ViewModels/CharacterDetailsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public partial class CharacterDetailsViewModel : ObservableRecipient, INavigatio
private readonly ElevatorService _elevatorService;

private ICharacterModList _modList = null!;
private ICategory? _category;
public ModListVM ModListVM { get; } = null!;
public ModPaneVM ModPaneVM { get; } = null!;

Expand Down Expand Up @@ -90,17 +91,7 @@ public CharacterDetailsViewModel(IGameService gameService, ILogger logger,
_imageHandlerService = imageHandlerService;
_elevatorService = elevatorService;

_modDragAndDropService.DragAndDropFinished += async (sender, args) =>
{
foreach (var extractResult in args.ExtractResults)
{
var extractedFolderName = new DirectoryInfo(extractResult.ExtractedFolderPath).Name;
await AddNewModAddedNotificationAsync(AttentionType.Added,
extractedFolderName, null);
}
await App.MainWindow.DispatcherQueue.EnqueueAsync(
async () => { await RefreshMods(); }).ConfigureAwait(false);
};
_modDragAndDropService.DragAndDropFinished += OnDragAndDropFinished;

ModdableObjectImage = _imageHandlerService.PlaceholderImageUri;

Expand All @@ -118,6 +109,17 @@ await App.MainWindow.DispatcherQueue.EnqueueAsync(
_modNotificationManager.OnModNotification += OnOnModNotificationHandler;
}

private async void OnDragAndDropFinished(object? sender, ModDragAndDropService.DragAndDropFinishedArgs args)
{
foreach (var extractResult in args.ExtractResults)
{
var extractedFolderName = new DirectoryInfo(extractResult.ExtractedFolderPath).Name;
await AddNewModAddedNotificationAsync(AttentionType.Added, extractedFolderName, null);
}

await App.MainWindow.DispatcherQueue.EnqueueAsync(async () => { await RefreshMods(); }).ConfigureAwait(false);
}

private void OnOnModNotificationHandler(object? sender, ModNotificationManager.ModNotificationEvent e)
{
App.MainWindow.DispatcherQueue.EnqueueAsync(() => RefreshModsCommand.ExecuteAsync(null));
Expand Down Expand Up @@ -220,6 +222,8 @@ public async void OnNavigatedTo(object parameter)
return;
}

_category = moddableObject.ModCategory;

if (moddableObject.ImageUri is not null)
ModdableObjectImage = moddableObject.ImageUri;

Expand Down Expand Up @@ -684,16 +688,15 @@ private async Task OpenNewModsWindowAsync(object? modNotification)
[RelayCommand]
private void GoBackToGrid()
{
var gridLastStack = _navigationService.GetBackStackItems().FirstOrDefault(backStackItem =>
backStackItem.SourcePageType == typeof(CharactersPage));
var gridLastStack = _navigationService.GetBackStackItems().LastOrDefault();

if (gridLastStack is not null)
if (gridLastStack is not null && gridLastStack.SourcePageType == typeof(CharactersPage))
{
_navigationService.GoBack();
return;
}

_navigationService.NavigateTo(typeof(CharactersViewModel).FullName!);
_navigationService.NavigateTo(typeof(CharactersViewModel).FullName!, _category);
}

[RelayCommand]
Expand All @@ -706,6 +709,10 @@ public void OnNavigatedFrom()
{
if (_modList is not null)
_modList.ModsChanged -= ModListOnModsChanged;
if (_modNotificationManager is not null)
_modNotificationManager.OnModNotification -= OnOnModNotificationHandler;
if (_modDragAndDropService is not null)
_modDragAndDropService.DragAndDropFinished -= OnDragAndDropFinished;
}


Expand Down
Loading

0 comments on commit ec8adc2

Please sign in to comment.