diff --git a/CLAUDE.md b/AGENTS.md similarity index 84% rename from CLAUDE.md rename to AGENTS.md index f8986df3..a3d40d5f 100644 --- a/CLAUDE.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ -# CLAUDE.md +# AGENTS.md -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +This file provides guidance to AI agent when working with code in this repository. ## Project Overview @@ -12,14 +12,14 @@ Wino Mail is a native Windows mail client (Windows 10 1809+ / Windows 11) replac # Open solution # WinoMail.slnx is the main solution file (VS 2022+) -# Build from command line -dotnet build WinoMail.slnx -c Debug +# Build WinUI project (Debug x64) +dotnet restore Wino.Mail.WinUI/Wino.Mail.WinUI.csproj --configfile nuget.config -p:Platform=x64 -p:RuntimeIdentifier=win-x64 && dotnet build Wino.Mail.WinUI/Wino.Mail.WinUI.csproj -c Debug --no-restore /p:Platform=x64 /p:RuntimeIdentifier=win-x64 /p:GenerateAppxPackageOnBuild=false /p:AppxPackageSigningEnabled=false -# Run tests -dotnet test Wino.Core.Tests/Wino.Core.Tests.csproj +# Run tests (Debug x64) +dotnet test Wino.Core.Tests/Wino.Core.Tests.csproj -c Debug /p:Platform=x64 -# Build specific platform -dotnet build WinoMail.slnx -c Debug /p:Platform=x64 +# Copilot CLI build command (Debug x64) +dotnet restore Wino.Mail.WinUI/Wino.Mail.WinUI.csproj --configfile nuget.config -p:Platform=x64 -p:RuntimeIdentifier=win-x64 && dotnet build Wino.Mail.WinUI/Wino.Mail.WinUI.csproj -c Debug --no-restore /p:Platform=x64 /p:RuntimeIdentifier=win-x64 /p:GenerateAppxPackageOnBuild=false /p:AppxPackageSigningEnabled=false ``` **Prerequisites:** Visual Studio 2022+ with ".NET desktop development" workload, .NET SDK 10+ @@ -130,3 +130,5 @@ private string searchQuery = string.Empty; - Wrap async operations in try-catch - Log errors via IWinoLogger - In ViewModels, update all UI-bound properties/collections via `ExecuteUIThread(...)` (especially after awaited calls and any use of `ConfigureAwait(false)`). + + diff --git a/Wino.Core/Synchronizers/GmailSynchronizer.cs b/Wino.Core/Synchronizers/GmailSynchronizer.cs index 8ba7e1f8..a8d0de33 100644 --- a/Wino.Core/Synchronizers/GmailSynchronizer.cs +++ b/Wino.Core/Synchronizers/GmailSynchronizer.cs @@ -96,6 +96,7 @@ public class GmailSynchronizer : WinoSynchronizer User might've already have another special folder for Archive. // We must remove that type assignment. @@ -703,6 +712,11 @@ public class GmailSynchronizer : WinoSynchronizer a.SpecialFolderType == SpecialFolderType.Archive && a.Id != archiveFolderId.Value).ToList(); + if (otherArchiveFolders.Any()) + { + _isFolderStructureChanged = true; + } + foreach (var otherArchiveFolder in otherArchiveFolders) { otherArchiveFolder.SpecialFolderType = SpecialFolderType.Other; @@ -803,7 +817,7 @@ public class GmailSynchronizer : WinoSynchronizer DeserializeGraphBatchResponseAsync(BatchResponseContentCollection collection, string requestId, CancellationToken cancellationToken = default) where T : IParsable, new() diff --git a/Wino.Mail.ViewModels/MailAppShellViewModel.cs b/Wino.Mail.ViewModels/MailAppShellViewModel.cs index 55af6fa0..2aa65413 100644 --- a/Wino.Mail.ViewModels/MailAppShellViewModel.cs +++ b/Wino.Mail.ViewModels/MailAppShellViewModel.cs @@ -969,6 +969,35 @@ public partial class MailAppShellViewModel : MailBaseViewModel, } } + private bool IsAccountCurrentlyLoaded(Guid accountId) + { + return latestSelectedAccountMenuItem?.HoldingAccounts?.Any(a => a.Id == accountId) == true; + } + + private async Task RefreshLoadedAccountFolderStructureAsync(Guid accountId) + { + if (!IsAccountCurrentlyLoaded(accountId) || latestSelectedAccountMenuItem == null) + return; + + var selectedFolderId = (SelectedMenuItem as IBaseFolderMenuItem)?.HandlingFolders + ?.FirstOrDefault(a => a.MailAccountId == accountId)?.Id; + + var folders = await _folderService.GetAccountFoldersForDisplayAsync(latestSelectedAccountMenuItem); + + await MenuItems.ReplaceFoldersAsync(folders); + await UpdateUnreadItemCountAsync(); + + if (selectedFolderId.HasValue && + MenuItems.TryGetFolderMenuItem(selectedFolderId.Value, out IBaseFolderMenuItem selectedFolderMenuItem)) + { + await NavigateFolderAsync(selectedFolderMenuItem); + } + else + { + await NavigateInboxAsync(latestSelectedAccountMenuItem); + } + } + public async void Receive(RefreshUnreadCountsMessage message) => await UpdateUnreadItemCountAsync(); @@ -980,13 +1009,7 @@ public partial class MailAppShellViewModel : MailBaseViewModel, public async void Receive(AccountFolderConfigurationUpdated message) { - // Reloading of folders is needed to re-create folder tree if the account is loaded. - - if (MenuItems.TryGetAccountMenuItem(message.AccountId, out IAccountMenuItem accountMenuItem) && - latestSelectedAccountMenuItem == accountMenuItem) - { - await ChangeLoadedAccountAsync(accountMenuItem, true); - } + await RefreshLoadedAccountFolderStructureAsync(message.AccountId); } public async void Receive(MergedInboxRenamed message) @@ -1055,7 +1078,10 @@ public partial class MailAppShellViewModel : MailBaseViewModel, if (wasSelected && latestSelectedAccountMenuItem != null) { await NavigateInboxAsync(latestSelectedAccountMenuItem); + return; } + + await RefreshLoadedAccountFolderStructureAsync(folder.MailAccountId); } protected override void OnFolderSynchronizationEnabled(IMailItemFolder mailItemFolder)