Fixing WinUI build and bringing Wino.Server basics.

This commit is contained in:
Burak Kaan Köse
2024-07-19 00:57:12 +02:00
parent 3f17a10ad0
commit 0cb39d41e8
40 changed files with 626 additions and 167 deletions

View File

@@ -1,11 +0,0 @@
using System;
using Wino.Core.Domain.Entities;
namespace Wino.Core.Domain.Interfaces
{
public interface IWinoSynchronizerFactory : IInitializeAsync
{
IBaseSynchronizer GetAccountSynchronizer(Guid accountId);
IBaseSynchronizer CreateNewSynchronizer(MailAccount account);
}
}

View File

@@ -521,6 +521,7 @@
"SettingsSignature_AddCustomSignature_Button": "Add signature",
"SettingsSignature_EditSignature_Title": "Edit signature",
"SettingsSignature_DeleteSignature_Title": "Delete signature",
"SettingsSignature_NoneSignatureName": "None"
"SettingsSignature_NoneSignatureName": "None",
"WinoSystemTray_LaunchWino": "Launch Wino",
"WinoSystemTray_QuitWino": "Quit"
}

View File

@@ -56,6 +56,9 @@
<ItemGroup>
<PackageReference Include="MimeKit" Version="4.7.1" />
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
<PackageReference Include="MimeKit" Version="4.7.1" />
<PackageReference Include="MailKit" Version="4.7.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
</Project>

View File

@@ -115,10 +115,11 @@ namespace Wino.Services
private void UpdateAppCoreWindowTitle()
{
var appView = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView();
// TODO: WinUI
//var appView = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView();
if (appView != null)
appView.Title = CoreWindowTitle;
//if (appView != null)
// appView.Title = CoreWindowTitle;
}
}
}

View File

@@ -13,7 +13,7 @@
<PackageReference Include="Google.Apis.Gmail.v1" Version="1.68.0.3427" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.61" />
<PackageReference Include="HtmlKit" Version="1.1.0" />
<PackageReference Include="MailKit" Version="4.7.1" />
<PackageReference Include="MailKit" Version="4.7.1.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Graph" Version="5.56.0" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.61.3" />
@@ -30,6 +30,7 @@
<ItemGroup>
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.NET8.csproj" />
<ProjectReference Include="..\Wino.Messages\Wino.Messaging.NET8.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,124 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Wino.Core.Authenticators;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Integration.Processors;
using Wino.Core.Services;
using Wino.Core.Synchronizers;
namespace Wino.Core
{
/// <summary>
/// Factory that keeps track of all integrator with associated mail accounts.
/// Synchronizer per-account makes sense because re-generating synchronizers are not ideal.
/// Users might interact with multiple accounts in 1 app session.
/// </summary>
public class WinoSynchronizerFactory : IWinoSynchronizerFactory
{
private readonly List<IBaseSynchronizer> synchronizerCache = new List<IBaseSynchronizer>();
private bool isInitialized = false;
private readonly INativeAppService _nativeAppService;
private readonly ITokenService _tokenService;
private readonly IFolderService _folderService;
private readonly IAccountService _accountService;
private readonly IContactService _contactService;
private readonly INotificationBuilder _notificationBuilder;
private readonly ISignatureService _signatureService;
private readonly IDatabaseService _databaseService;
private readonly IMimeFileService _mimeFileService;
private readonly IOutlookChangeProcessor _outlookChangeProcessor;
private readonly IGmailChangeProcessor _gmailChangeProcessor;
private readonly IImapChangeProcessor _imapChangeProcessor;
public WinoSynchronizerFactory(INativeAppService nativeAppService,
ITokenService tokenService,
IFolderService folderService,
IAccountService accountService,
IContactService contactService,
INotificationBuilder notificationBuilder,
ISignatureService signatureService,
IDatabaseService databaseService,
IMimeFileService mimeFileService,
IOutlookChangeProcessor outlookChangeProcessor,
IGmailChangeProcessor gmailChangeProcessor,
IImapChangeProcessor imapChangeProcessor)
{
_contactService = contactService;
_notificationBuilder = notificationBuilder;
_nativeAppService = nativeAppService;
_tokenService = tokenService;
_folderService = folderService;
_accountService = accountService;
_signatureService = signatureService;
_databaseService = databaseService;
_mimeFileService = mimeFileService;
_outlookChangeProcessor = outlookChangeProcessor;
_gmailChangeProcessor = gmailChangeProcessor;
_imapChangeProcessor = imapChangeProcessor;
}
public IBaseSynchronizer GetAccountSynchronizer(Guid accountId)
=> synchronizerCache.Find(a => a.Account.Id == accountId);
private IBaseSynchronizer CreateIntegratorWithDefaultProcessor(MailAccount mailAccount)
{
var providerType = mailAccount.ProviderType;
switch (providerType)
{
case Domain.Enums.MailProviderType.Outlook:
var outlookAuthenticator = new OutlookAuthenticator(_tokenService, _nativeAppService);
return new OutlookSynchronizer(mailAccount, outlookAuthenticator, _outlookChangeProcessor);
case Domain.Enums.MailProviderType.Gmail:
var gmailAuthenticator = new GmailAuthenticator(_tokenService, _nativeAppService);
return new GmailSynchronizer(mailAccount, gmailAuthenticator, _gmailChangeProcessor);
case Domain.Enums.MailProviderType.Office365:
break;
case Domain.Enums.MailProviderType.Yahoo:
break;
case Domain.Enums.MailProviderType.IMAP4:
return new ImapSynchronizer(mailAccount, _imapChangeProcessor);
default:
break;
}
return null;
}
public void DeleteSynchronizer(MailAccount account)
{
var synchronizer = GetAccountSynchronizer(account.Id);
if (synchronizer == null) return;
synchronizerCache.Remove(synchronizer);
}
public async Task InitializeAsync()
{
if (isInitialized) return;
var accounts = await _accountService.GetAccountsAsync();
foreach (var account in accounts)
{
CreateNewSynchronizer(account);
}
isInitialized = true;
}
public IBaseSynchronizer CreateNewSynchronizer(MailAccount account)
{
var synchronizer = CreateIntegratorWithDefaultProcessor(account);
synchronizerCache.Add(synchronizer);
return synchronizer;
}
}
}

View File

@@ -3,7 +3,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Wino.Core;
using Windows.Storage;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Services;
using Wino.Core.WinUI.Services;
@@ -16,6 +16,8 @@ namespace Wino
private WindowEx m_Window;
private Frame m_ShellFrame;
private readonly IApplicationConfiguration _applicationFolderConfiguration;
public App()
{
if (WebAuthenticator.CheckOAuthRedirectionActivation()) return;
@@ -24,6 +26,7 @@ namespace Wino
Services = ConfigureServices();
_applicationFolderConfiguration = Services.GetService<IApplicationConfiguration>();
_logInitializer = Services.GetService<ILogInitializer>();
ConfigureLogger();
@@ -31,10 +34,12 @@ namespace Wino
ConfigurePrelaunch();
ConfigureXbox();
// Make sure the paths are setup on app start.
_applicationFolderConfiguration.ApplicationDataFolderPath = ApplicationData.Current.LocalFolder.Path;
_applicationFolderConfiguration.PublisherSharedFolderPath = ApplicationData.Current.GetPublisherCacheFolder(ApplicationConfiguration.SharedFolderName).Path;
_themeService = Services.GetService<IThemeService>();
_databaseService = Services.GetService<IDatabaseService>();
_appInitializerService = Services.GetService<IAppInitializerService>();
_synchronizerFactory = Services.GetService<IWinoSynchronizerFactory>();
_translationService = Services.GetService<ITranslationService>();
_appShellService = Services.GetService<IAppShellService>();

View File

@@ -14,6 +14,7 @@
<WindowsSdkPackageVersion>10.0.19041.35-preview</WindowsSdkPackageVersion>
<GenerateTemporaryStoreCertificate>True</GenerateTemporaryStoreCertificate>
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
<GenerateAssemblyInfo>True</GenerateAssemblyInfo>
<AppxPackageSigningEnabled>False</AppxPackageSigningEnabled>
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
@@ -107,8 +108,6 @@
<Compile Include="..\Wino.Mail\Services\ApplicationResourceManager.cs" Link="Services\ApplicationResourceManager.cs" />
<Compile Include="..\Wino.Mail\Services\DialogService.cs" Link="Services\DialogService.cs" />
<Compile Include="..\Wino.Mail\Services\LaunchProtocolService.cs" Link="Services\LaunchProtocolService.cs" />
<Compile Include="..\Wino.Mail\Services\PreferencesService.cs" Link="Services\PreferencesService.cs" />
<Compile Include="..\Wino.Mail\Services\StatePersistenceService.cs" Link="Services\StatePersistenceService.cs" />
<Compile Include="..\Wino.Mail\Services\WinoNavigationService.cs" Link="Services\WinoNavigationService.cs" />
<Compile Include="..\Wino.Mail\Styles\CommandBarItems.xaml.cs" Link="Styles\CommandBarItems.xaml.cs" />
<Compile Include="..\Wino.Mail\Views\Account\AccountDetailsPage.xaml.cs" Link="Views\Account\AccountDetailsPage.xaml.cs" />
@@ -199,7 +198,7 @@
<PackageReference Include="Microsoft.AppCenter.Analytics" Version="5.0.5" />
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="5.0.5" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.240701003-experimental2" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240627000" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
<PackageReference Include="WinUIEx" Version="2.3.4" />
<Manifest Include="$(ApplicationManifest)" />

View File

@@ -21,6 +21,8 @@ using Wino.Dialogs;
using Wino.Helpers;
using Wino.Core.WinUI.Services;
using Wino.Messaging.Server;
using Windows.Foundation.Metadata;
#if NET8_0

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>disable</Nullable>
<RootNamespace>Wino.Messaging</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.NET8.csproj" />
</ItemGroup>
</Project>

16
Wino.Server.NET8/App.xaml Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Application
x:Class="Wino.Server.NET8.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Wino.Server.NET8">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@@ -0,0 +1,35 @@
using H.NotifyIcon;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Input;
namespace Wino.Server.NET8
{
public partial class App : Application
{
public TaskbarIcon? TrayIcon { get; private set; }
public Window? Window { get; set; }
public bool HandleClosedEvents { get; set; } = true;
public App()
{
InitializeComponent();
}
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
}
private void InitializeTrayIcon()
{
var showHideWindowCommand = (XamlUICommand)Resources["ShowHideWindowCommand"];
// showHideWindowCommand.ExecuteRequested ;
var exitApplicationCommand = (XamlUICommand)Resources["ExitApplicationCommand"];
//exitApplicationCommand.ExecuteRequested += ExitApplicationCommand_ExecuteRequested;
TrayIcon = (TaskbarIcon)Resources["TrayIcon"];
TrayIcon.ForceCreate();
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 124 KiB

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
<Identity
Name="f7498058-466c-48d4-bc53-0afe4ec4de31"
Publisher="CN=bkaan"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="f7498058-466c-48d4-bc53-0afe4ec4de31" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>Wino.Server.NET8</DisplayName>
<PublisherDisplayName>bkaan</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="Wino.Server.NET8"
Description="Wino.Server.NET8"
BackgroundColor="transparent"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" />
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>

View File

@@ -0,0 +1,97 @@
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.UI.Dispatching;
using Microsoft.Windows.AppLifecycle;
using Wino.Server.NET8;
namespace Wino.Server
{
class Program
{
private const string WinoActivationKey = nameof(WinoActivationKey);
[STAThread]
static void Main(string[] args)
{
WinRT.ComWrappersSupport.InitializeComWrappers();
bool isRedirect = DecideRedirection();
if (!isRedirect)
{
Microsoft.UI.Xaml.Application.Start((p) =>
{
var context = new DispatcherQueueSynchronizationContext(
DispatcherQueue.GetForCurrentThread());
SynchronizationContext.SetSynchronizationContext(context);
new App();
});
}
}
private static bool DecideRedirection()
{
bool isRedirect = false;
AppActivationArguments args = AppInstance.GetCurrent().GetActivatedEventArgs();
ExtendedActivationKind kind = args.Kind;
try
{
AppInstance keyInstance = AppInstance.FindOrRegisterForKey(WinoActivationKey);
if (keyInstance.IsCurrent)
{
keyInstance.Activated += OnActivated;
}
else
{
isRedirect = true;
RedirectActivationTo(args, keyInstance);
}
}
catch (Exception ex)
{
}
return isRedirect;
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName);
[DllImport("kernel32.dll")]
private static extern bool SetEvent(IntPtr hEvent);
[DllImport("ole32.dll")]
private static extern uint CoWaitForMultipleObjects(uint dwFlags, uint dwMilliseconds, ulong nHandles, IntPtr[] pHandles, out uint dwIndex);
private static IntPtr redirectEventHandle = IntPtr.Zero;
// Do the redirection on another thread, and use a non-blocking
// wait method to wait for the redirection to complete.
public static void RedirectActivationTo(
AppActivationArguments args, AppInstance keyInstance)
{
redirectEventHandle = CreateEvent(IntPtr.Zero, true, false, null);
Task.Run(() =>
{
keyInstance.RedirectActivationToAsync(args).AsTask().Wait();
SetEvent(redirectEventHandle);
});
uint CWMO_DEFAULT = 0;
uint INFINITE = 0xFFFFFFFF;
_ = CoWaitForMultipleObjects(CWMO_DEFAULT, INFINITE, 1, new IntPtr[] { redirectEventHandle }, out uint handleIndex);
}
private static void OnActivated(object sender, AppActivationArguments args)
{
ExtendedActivationKind kind = args.Kind;
}
}
}

View File

@@ -0,0 +1,10 @@
{
"profiles": {
"Wino.Server.NET8 (Package)": {
"commandName": "MsixPackage"
},
"Wino.Server.NET8 (Unpackaged)": {
"commandName": "Project"
}
}
}

View File

@@ -0,0 +1,45 @@
<ResourceDictionary
x:Class="Wino.Server.TrayIconResources"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:domain="using:Wino.Core.Domain"
xmlns:tb="using:H.NotifyIcon"
xmlns:local="using:Wino.Server">
<!-- TODO: Localize by Translator. -->
<XamlUICommand
x:Key="LaunchCommand"
Label="Launch"
Description="Activates Wino Mail window.">
<XamlUICommand.IconSource>
<SymbolIconSource Symbol="Accept" />
</XamlUICommand.IconSource>
</XamlUICommand>
<XamlUICommand
x:Key="TerminateCommand"
Label="Quit"
Description="Close Wino Mail completely.">
<XamlUICommand.IconSource>
<SymbolIconSource Symbol="ClosePane" />
</XamlUICommand.IconSource>
</XamlUICommand>
<tb:TaskbarIcon
x:Key="TrayIcon"
Visibility="Visible"
ToolTipText="Wino Mail"
ContextMenuMode="SecondWindow"
LeftClickCommand="{StaticResource LaunchCommand}"
NoLeftClickDelay="True"
IconSource="\Images\Wino_Icon.ico">
<tb:TaskbarIcon.ContextFlyout>
<MenuFlyout>
<MenuFlyoutItem Command="{StaticResource LaunchCommand}" />
<MenuFlyoutItem Command="{StaticResource TerminateCommand}" />
</MenuFlyout>
</tb:TaskbarIcon.ContextFlyout>
</tb:TaskbarIcon>
</ResourceDictionary>

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.UI.Xaml;
namespace Wino.Server
{
partial class TrayIconResources : ResourceDictionary
{
public TrayIconResources()
{
this.InitializeComponent();
}
}
}

View File

@@ -0,0 +1,98 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RootNamespace>Wino.Server</RootNamespace>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Platforms>x86;x64;ARM64</Platforms>
<RuntimeIdentifiers Condition="$([MSBuild]::GetTargetFrameworkVersion('$(TargetFramework)')) &gt;= 8">win-x86;win-x64;win-arm64</RuntimeIdentifiers>
<RuntimeIdentifiers Condition="$([MSBuild]::GetTargetFrameworkVersion('$(TargetFramework)')) &lt; 8">win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
</PropertyGroup>
<!-- Disable XAML generated main to enable single activation. -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DefineConstants>DISABLE_XAML_GENERATED_MAIN</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
<DefineConstants>DISABLE_XAML_GENERATED_MAIN</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
<DefineConstants>DISABLE_XAML_GENERATED_MAIN</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DefineConstants>DISABLE_XAML_GENERATED_MAIN</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|arm64'">
<DefineConstants>DISABLE_XAML_GENERATED_MAIN</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|arm64'">
<DefineConstants>DISABLE_XAML_GENERATED_MAIN</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Content Remove="Assets\Wino_Icon.ico" />
</ItemGroup>
<ItemGroup>
<None Remove="app.manifest" />
<None Remove="TrayIconResources.xaml" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.1.0" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240627000" />
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<!--
Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
Tools extension to be activated for this project even if the Windows App SDK Nuget
package has not yet been restored.
-->
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.NET8.csproj" />
<ProjectReference Include="..\Wino.Core.UWP\Wino.Core.WinUI.csproj" />
<ProjectReference Include="..\Wino.Core\Wino.Core.NET8.csproj" />
<ProjectReference Include="..\Wino.Messages\Wino.Messaging.NET8.csproj" />
</ItemGroup>
<ItemGroup>
<Resource Include="app.manifest">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource>
</ItemGroup>
<ItemGroup>
<Page Update="TrayIconResources.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<!--
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
Explorer "Package and Publish" context menu entry to be enabled for this project even if
the Windows App SDK Nuget package has not yet been restored.
-->
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="Wino.Server.NET8.app"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- The ID below informs the system that this application is compatible with OS features first introduced in Windows 10.
It is necessary to support features in unpackaged applications, for example the custom titlebar implementation.
For more info see https://docs.microsoft.com/windows/apps/windows-app-sdk/use-windows-app-sdk-run-time#declare-os-compatibility-in-your-application-manifest -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
</assembly>

View File

@@ -2,7 +2,6 @@
x:Class="Wino.Server.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ShutdownMode="OnExplicitShutdown"
xmlns:local="clr-namespace:Wino.Server">
<Application.Resources>
<ResourceDictionary Source="TrayIconResources.xaml" />

View File

@@ -1,9 +1,10 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using H.NotifyIcon;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Input;
using Windows.Storage;
using Wino.Core;
using Wino.Core.Domain.Interfaces;
@@ -28,12 +29,17 @@ namespace Wino.Server
public new static App Current => (App)Application.Current;
private TaskbarIcon? notifyIcon;
private TaskbarIcon notifyIcon;
private static Mutex _mutex = null;
private EventWaitHandle _eventWaitHandle;
public IServiceProvider Services { get; private set; }
public App()
{
InitializeComponent();
}
private IServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
@@ -72,8 +78,10 @@ namespace Wino.Server
return serverViewModel;
}
protected override async void OnStartup(StartupEventArgs e)
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
base.OnLaunched(args);
_mutex = new Mutex(true, WinoServerAppName, out bool isCreatedNew);
_eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, WinoServerActiatedName);
@@ -102,7 +110,6 @@ namespace Wino.Server
Services = ConfigureServices();
base.OnStartup(e);
var serverViewModel = await InitializeNewServerAsync();
@@ -117,14 +124,21 @@ namespace Wino.Server
_eventWaitHandle.Set();
// Terminate this instance.
Shutdown();
// Shutdown();
}
}
protected override void OnExit(ExitEventArgs e)
private void InitializeNotifyIcon()
{
notifyIcon?.Dispose();
base.OnExit(e);
var showHideWindowCommand = (XamlUICommand)Resources["ShowHideWindowCommand"];
showHideWindowCommand.ExecuteRequested += ShowHideWindowCommand_ExecuteRequested;
var exitApplicationCommand = (XamlUICommand)Resources["ExitApplicationCommand"];
exitApplicationCommand.ExecuteRequested += ExitApplicationCommand_ExecuteRequested;
notifyIcon = (TaskbarIcon)Resources["TrayIcon"];
notifyIcon.ForceCreate();
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

View File

@@ -0,0 +1,25 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.UI.Dispatching;
namespace Wino.Server.WinUI
{
[STAThread]
static async Task Main(string[] args)
{
WinRT.ComWrappersSupport.InitializeComWrappers();
bool isRedirect = await DecideRedirection();
if (!isRedirect)
{
Microsoft.UI.Xaml.Application.Start((p) =>
{
var context = new DispatcherQueueSynchronizationContext(
DispatcherQueue.GetForCurrentThread());
SynchronizationContext.SetSynchronizationContext(context);
new App();
});
}
return 0;
}
}

View File

@@ -0,0 +1,42 @@
<ResourceDictionary
x:Class="Wino.Server.WinUI.TrayIconResources"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:domain="using:Wino.Core.Domain"
xmlns:tb="using:H.NotifyIcon"
xmlns:local="using:Wino.Server.WinUI">
<XamlUICommand
x:Key="LaunchCommand"
Label="Launch"
Description="Activates Wino Mail window.">
<XamlUICommand.IconSource>
<SymbolIconSource Symbol="Accept" />
</XamlUICommand.IconSource>
</XamlUICommand>
<XamlUICommand
x:Key="TerminateCommand"
Label="Quit"
Description="Close Wino Mail completely.">
<XamlUICommand.IconSource>
<SymbolIconSource Symbol="ClosePane" />
</XamlUICommand.IconSource>
</XamlUICommand>
<tb:TaskbarIcon
x:Key="TrayIcon"
Visibility="Visible"
ToolTipText="Wino Mail"
ContextMenuMode="SecondWindow"
LeftClickCommand="{StaticResource LaunchCommand}"
NoLeftClickDelay="True"
IconSource="\Images\Wino_Icon.ico">
<tb:TaskbarIcon.ContextFlyout>
<MenuFlyout>
<MenuFlyoutItem Command="{StaticResource LaunchCommand}" />
<MenuFlyoutItem Command="{StaticResource TerminateCommand}" />
</MenuFlyout>
</tb:TaskbarIcon.ContextFlyout>
</tb:TaskbarIcon>
</ResourceDictionary>

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.UI.Xaml;
namespace Wino.Server.WinUI
{
partial class TrayIconResources : ResourceDictionary
{
public TrayIconResources()
{
this.InitializeComponent();
}
}
}

View File

@@ -0,0 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows10.0.22621.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RootNamespace>Wino.Server.WinUI</RootNamespace>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Platforms>x86;x64;ARM64</Platforms>
<RuntimeIdentifiers Condition="$([MSBuild]::GetTargetFrameworkVersion('$(TargetFramework)')) &gt;= 8">win-x86;win-x64;win-arm64</RuntimeIdentifiers>
<RuntimeIdentifiers Condition="$([MSBuild]::GetTargetFrameworkVersion('$(TargetFramework)')) &lt; 8">win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
</PropertyGroup>
<PropertyGroup>
<StartupObject>Wino.Server.App</StartupObject>
</PropertyGroup>
<ItemGroup>
<None Remove="Images\Wino_Icon.ico" />
<None Remove="TrayIconResources.xaml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Wino.Core.UWP\Services\ConfigurationService.cs" Link="Services\ConfigurationService.cs" />
<Compile Include="..\Wino.Core.UWP\Services\NativeAppService.cs" Link="Services\NativeAppService.cs" />
<Compile Include="..\Wino.Core.UWP\Services\NotificationBuilder.cs" Link="Services\NotificationBuilder.cs" />
<Compile Include="..\Wino.Core.UWP\Services\PreferencesService.cs" Link="Services\PreferencesService.cs" />
</ItemGroup>
<ItemGroup>
<Resource Include="Images\Wino_Icon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource>
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.NET8.csproj" />
<ProjectReference Include="..\Wino.Core\Wino.Core.NET8.csproj" />
<ProjectReference Include="..\Wino.Messages\Wino.Messaging.NET8.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Services\" />
</ItemGroup>
<ItemGroup>
<Page Update="TrayIconResources.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
</Project>

View File

@@ -1,10 +0,0 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

View File

@@ -13,7 +13,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Core.WinUI", "Wino.Cor
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.BackgroundTasks.NET8", "Wino.BackgroundTasks\Wino.BackgroundTasks.NET8.csproj", "{2C86AF48-F7DD-4EA6-A9A6-610E69287F03}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Mail.WinUI", "Wino.Mail.WinUI\Wino.Mail.WinUI.csproj", "{955936B2-112B-4756-8BC7-67FF12BF9759}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Mail.WinUI", "Wino.Mail.WinUI\Wino.Mail.WinUI.csproj", "{955936B2-112B-4756-8BC7-67FF12BF9759}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Messaging.NET8", "Wino.Messages\Wino.Messaging.NET8.csproj", "{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Server.NET8", "Wino.Server.NET8\Wino.Server.NET8.csproj", "{A3B3BDBB-5946-4058-8038-55A97DBCFB38}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -131,6 +135,46 @@ Global
{955936B2-112B-4756-8BC7-67FF12BF9759}.Release|x86.ActiveCfg = Release|x86
{955936B2-112B-4756-8BC7-67FF12BF9759}.Release|x86.Build.0 = Release|x86
{955936B2-112B-4756-8BC7-67FF12BF9759}.Release|x86.Deploy.0 = Release|x86
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Debug|ARM64.Build.0 = Debug|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Debug|x64.ActiveCfg = Debug|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Debug|x64.Build.0 = Debug|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Debug|x86.ActiveCfg = Debug|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Debug|x86.Build.0 = Debug|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Release|Any CPU.Build.0 = Release|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Release|ARM64.ActiveCfg = Release|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Release|ARM64.Build.0 = Release|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Release|x64.ActiveCfg = Release|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Release|x64.Build.0 = Release|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Release|x86.ActiveCfg = Release|Any CPU
{88A9B1A8-BC59-4852-93D0-37A5D357ABC6}.Release|x86.Build.0 = Release|Any CPU
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Debug|Any CPU.ActiveCfg = Debug|x64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Debug|Any CPU.Build.0 = Debug|x64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Debug|Any CPU.Deploy.0 = Debug|x64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Debug|ARM64.ActiveCfg = Debug|ARM64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Debug|ARM64.Build.0 = Debug|ARM64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Debug|ARM64.Deploy.0 = Debug|ARM64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Debug|x64.ActiveCfg = Debug|x64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Debug|x64.Build.0 = Debug|x64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Debug|x64.Deploy.0 = Debug|x64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Debug|x86.ActiveCfg = Debug|x86
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Debug|x86.Build.0 = Debug|x86
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Debug|x86.Deploy.0 = Debug|x86
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Release|Any CPU.ActiveCfg = Release|x64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Release|Any CPU.Build.0 = Release|x64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Release|Any CPU.Deploy.0 = Release|x64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Release|ARM64.ActiveCfg = Release|ARM64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Release|ARM64.Build.0 = Release|ARM64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Release|ARM64.Deploy.0 = Release|ARM64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Release|x64.ActiveCfg = Release|x64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Release|x64.Build.0 = Release|x64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Release|x64.Deploy.0 = Release|x64
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Release|x86.ActiveCfg = Release|x86
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Release|x86.Build.0 = Release|x86
{A3B3BDBB-5946-4058-8038-55A97DBCFB38}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE