Remove old projects.
@@ -1,34 +0,0 @@
|
||||
using Microsoft.Toolkit.Uwp.Notifications;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.ApplicationModel.Background;
|
||||
|
||||
namespace Wino.BackgroundTasks
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a toast notification to notify user when the Store update happens.
|
||||
/// </summary>
|
||||
public sealed class AppUpdatedTask : IBackgroundTask
|
||||
{
|
||||
public void Run(IBackgroundTaskInstance taskInstance)
|
||||
{
|
||||
var def = taskInstance.GetDeferral();
|
||||
|
||||
var builder = new ToastContentBuilder();
|
||||
builder.SetToastScenario(ToastScenario.Default);
|
||||
|
||||
Package package = Package.Current;
|
||||
PackageId packageId = package.Id;
|
||||
PackageVersion version = packageId.Version;
|
||||
|
||||
var versionText = string.Format("{0}.{1}.{2}.{3}", version.Major, version.Minor, version.Build, version.Revision);
|
||||
|
||||
// TODO: Handle with Translator, but it's not initialized here yet.
|
||||
builder.AddText("Wino Mail is updated!");
|
||||
builder.AddText(string.Format("New version {0} is ready.", versionText));
|
||||
|
||||
builder.Show();
|
||||
|
||||
def.Complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Wino.BackgroundTasks")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Wino.BackgroundTasks")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: ComVisible(false)]
|
||||
@@ -1,129 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}</ProjectGuid>
|
||||
<OutputType>winmdobj</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Wino.BackgroundTasks</RootNamespace>
|
||||
<AssemblyName>Wino.BackgroundTasks</AssemblyName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.22621.0</TargetPlatformVersion>
|
||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<AllowCrossPlatformRetargeting>false</AllowCrossPlatformRetargeting>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>full</DebugType>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM64'">
|
||||
<PlatformTarget>ARM64</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\ARM64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>full</DebugType>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM64'">
|
||||
<PlatformTarget>ARM64</PlatformTarget>
|
||||
<OutputPath>bin\ARM64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>full</DebugType>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AppUpdatedTask.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Identity.Client">
|
||||
<Version>4.66.2</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.2.14</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications">
|
||||
<Version>7.1.3</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.csproj">
|
||||
<Project>{CF3312E5-5DA0-4867-9945-49EA7598AF1F}</Project>
|
||||
<Name>Wino.Core.Domain</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Wino.Core.UWP\Wino.Core.UWP.csproj">
|
||||
<Project>{395f19ba-1e42-495c-9db5-1a6f537fccb8}</Project>
|
||||
<Name>Wino.Core.UWP</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Wino.Core\Wino.Core.csproj">
|
||||
<Project>{e6b1632a-8901-41e8-9ddf-6793c7698b0b}</Project>
|
||||
<Name>Wino.Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<SDKReference Include="WindowsDesktop, Version=10.0.22621.0">
|
||||
<Name>Windows Desktop Extensions for the UWP</Name>
|
||||
</SDKReference>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -1,38 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0-windows10.0.26100.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||
<Platforms>x86;x64;arm64</Platforms>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<Nullable>disable</Nullable>
|
||||
<UseUwp>true</UseUwp>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<IsAotCompatible>true</IsAotCompatible>
|
||||
<DisableRuntimeMarshalling>true</DisableRuntimeMarshalling>
|
||||
<SupportedOSPlatformVersion>10.0.18362.0</SupportedOSPlatformVersion>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="gravatar-dotnet" />
|
||||
<PackageReference Include="Microsoft.Identity.Client" />
|
||||
<PackageReference Include="Microsoft.UI.Xaml" />
|
||||
<PackageReference Include="CommunityToolkit.Common" />
|
||||
<PackageReference Include="CommunityToolkit.Diagnostics" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||
<PackageReference Include="CommunityToolkit.Uwp.Animations" />
|
||||
<PackageReference Include="CommunityToolkit.Uwp.Behaviors" />
|
||||
<PackageReference Include="CommunityToolkit.Uwp.Controls.Segmented" />
|
||||
<PackageReference Include="CommunityToolkit.Uwp.Controls.SettingsControls" />
|
||||
<PackageReference Include="CommunityToolkit.Uwp.Controls.Sizers" />
|
||||
<PackageReference Include="CommunityToolkit.Uwp.Extensions" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Notifications" />
|
||||
<PackageReference Include="CommunityToolkit.Uwp.Controls.TabbedCommandBar" />
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" />
|
||||
<PackageReference Include="Win2D.uwp" />
|
||||
<PackageReference Include="EmailValidation" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.csproj" />
|
||||
<ProjectReference Include="..\Wino.Core.ViewModels\Wino.Core.ViewModels.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,36 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wino.Activation;
|
||||
|
||||
public abstract class ActivationHandler
|
||||
{
|
||||
public abstract bool CanHandle(object args);
|
||||
|
||||
public abstract Task HandleAsync(object args);
|
||||
}
|
||||
|
||||
// Extend this class to implement new ActivationHandlers
|
||||
public abstract class ActivationHandler<T> : ActivationHandler
|
||||
where T : class
|
||||
{
|
||||
// Override this method to add the activation logic in your activation handler
|
||||
protected abstract Task HandleInternalAsync(T args);
|
||||
|
||||
public override async Task HandleAsync(object args)
|
||||
{
|
||||
await HandleInternalAsync(args as T);
|
||||
}
|
||||
|
||||
public override bool CanHandle(object args)
|
||||
{
|
||||
// CanHandle checks the args is of type you have configured
|
||||
return args is T && CanHandleInternal(args as T);
|
||||
}
|
||||
|
||||
// You can override this method to add extra validation on activation args
|
||||
// to determine if your ActivationHandler should handle this activation args
|
||||
protected virtual bool CanHandleInternal(T args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:Microsoft.UI.Xaml.Media"
|
||||
xmlns:xaml="using:Microsoft.UI.Xaml">
|
||||
|
||||
<x:String x:Key="ThemeName">Acrylic</x:String>
|
||||
|
||||
<SolidColorBrush x:Key="AppBarBackgroundColor">Transparent</SolidColorBrush>
|
||||
|
||||
<!-- Acrylic Template -->
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Name="Light">
|
||||
<!-- Reading Page Date/Name Group Header Background -->
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#ecf0f1</SolidColorBrush>
|
||||
|
||||
<local:AcrylicBrush
|
||||
x:Key="WinoApplicationBackgroundColor"
|
||||
FallbackColor="#F9F9F9"
|
||||
TintColor="#FCFCFC"
|
||||
TintOpacity="0.75" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Name="Dark">
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#2C2C2C</SolidColorBrush>
|
||||
|
||||
<local:AcrylicBrush
|
||||
x:Key="WinoApplicationBackgroundColor"
|
||||
FallbackColor="#2C2C2C"
|
||||
TintColor="#2C2C2C"
|
||||
TintOpacity="0.30" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
@@ -1,24 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:xaml="using:Microsoft.UI.Xaml">
|
||||
|
||||
<x:String x:Key="ThemeName">Clouds</x:String>
|
||||
<x:String x:Key="ThemeBackgroundImage">ms-appx:///Wino.Core.WinUI/BackgroundImages/Clouds.jpg</x:String>
|
||||
|
||||
<ImageBrush x:Key="WinoApplicationBackgroundColor" ImageSource="{StaticResource ThemeBackgroundImage}" />
|
||||
<SolidColorBrush x:Key="AppBarBackgroundColor">Transparent</SolidColorBrush>
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Name="Light">
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#b2dffc</SolidColorBrush>
|
||||
|
||||
<SolidColorBrush x:Key="CalendarSeperatorBrush">#222f3e</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Name="Dark">
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#b2dffc</SolidColorBrush>
|
||||
|
||||
<SolidColorBrush x:Key="CalendarSeperatorBrush">#222f3e</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
@@ -1,46 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:xaml="using:Microsoft.UI.Xaml">
|
||||
|
||||
<x:String x:Key="ThemeName">Custom</x:String>
|
||||
<x:String x:Key="ThemeBackgroundImage">ms-appdata:///local/CustomWallpaper.jpg</x:String>
|
||||
|
||||
<ImageBrush
|
||||
x:Key="WinoApplicationBackgroundColor"
|
||||
ImageSource="{StaticResource ThemeBackgroundImage}"
|
||||
Stretch="UniformToFill" />
|
||||
|
||||
<!-- Navigation View Settings -->
|
||||
<xaml:CornerRadius x:Key="NavigationViewContentGridCornerRadius">0,0,0,0</xaml:CornerRadius>
|
||||
<xaml:CornerRadius x:Key="OverlayCornerRadius">0,1,0,0</xaml:CornerRadius>
|
||||
<Thickness x:Key="NavigationViewContentMargin">0,0,0,0</Thickness>
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Name="Light">
|
||||
<!-- Reading Page Date/Name Group Header Background -->
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#ecf0f1</SolidColorBrush>
|
||||
|
||||
<Color x:Key="MainCustomThemeColor">#D9FFFFFF</Color>
|
||||
|
||||
<SolidColorBrush x:Key="AppBarBackgroundColor" Color="{StaticResource MainCustomThemeColor}" />
|
||||
<SolidColorBrush x:Key="NavigationViewContentBackground" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="NavigationViewExpandedPaneBackground" Color="{StaticResource MainCustomThemeColor}" />
|
||||
<SolidColorBrush x:Key="NavigationViewDefaultPaneBackground" Color="{StaticResource MainCustomThemeColor}" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Name="Dark">
|
||||
<!-- Reading Page Date/Name Group Header Background -->
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#1f1f1f</SolidColorBrush>
|
||||
|
||||
<Color x:Key="MainCustomThemeColor">#E61F1F1F</Color>
|
||||
|
||||
<!-- Reading Pane Background -->
|
||||
<SolidColorBrush x:Key="ReadingPaneBackgroundColorBrush" Color="{StaticResource MainCustomThemeColor}" />
|
||||
|
||||
<SolidColorBrush x:Key="AppBarBackgroundColor" Color="{StaticResource MainCustomThemeColor}" />
|
||||
<SolidColorBrush x:Key="NavigationViewContentBackground" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="NavigationViewExpandedPaneBackground" Color="{StaticResource MainCustomThemeColor}" />
|
||||
<SolidColorBrush x:Key="NavigationViewDefaultPaneBackground" Color="{StaticResource MainCustomThemeColor}" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
@@ -1,21 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:xaml="using:Microsoft.UI.Xaml">
|
||||
|
||||
<x:String x:Key="ThemeName">Default</x:String>
|
||||
|
||||
<SolidColorBrush x:Key="WinoApplicationBackgroundColor">Transparent</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="AppBarBackgroundColor">Transparent</SolidColorBrush>
|
||||
|
||||
<!-- Mica Template -->
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Name="Light">
|
||||
<!-- Reading Page Date/Name Group Header Background -->
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#ecf0f1</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Name="Dark">
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#1f1f1f</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
@@ -1,20 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:xaml="using:Microsoft.UI.Xaml">
|
||||
|
||||
<x:String x:Key="ThemeName">Forest</x:String>
|
||||
<x:String x:Key="ThemeBackgroundImage">ms-appx:///Wino.Core.WinUI/BackgroundImages/Forest.jpg</x:String>
|
||||
|
||||
<ImageBrush x:Key="WinoApplicationBackgroundColor" ImageSource="{StaticResource ThemeBackgroundImage}" />
|
||||
<SolidColorBrush x:Key="AppBarBackgroundColor">Transparent</SolidColorBrush>
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Name="Light">
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#A800D608</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Name="Dark">
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#59001C01</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
@@ -1,23 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:xaml="using:Microsoft.UI.Xaml">
|
||||
|
||||
<x:String x:Key="ThemeName">Garden</x:String>
|
||||
<x:String x:Key="ThemeBackgroundImage">ms-appx:///Wino.Core.WinUI/BackgroundImages/Garden.jpg</x:String>
|
||||
|
||||
<ImageBrush x:Key="WinoApplicationBackgroundColor" ImageSource="{StaticResource ThemeBackgroundImage}" />
|
||||
<SolidColorBrush x:Key="AppBarBackgroundColor">Transparent</SolidColorBrush>
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Name="Light">
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#dcfad8</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="CalendarSeperatorBrush">#576574</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
|
||||
<!-- N/A. Light theme only. -->
|
||||
<ResourceDictionary x:Name="Dark">
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#dcfad8</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
@@ -1,22 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:xaml="using:Microsoft.UI.Xaml">
|
||||
|
||||
<x:String x:Key="ThemeName">Nighty</x:String>
|
||||
<x:String x:Key="ThemeBackgroundImage">ms-appx:///Wino.Core.WinUI/BackgroundImages/Nighty.jpg</x:String>
|
||||
|
||||
<ImageBrush x:Key="WinoApplicationBackgroundColor" ImageSource="{StaticResource ThemeBackgroundImage}" />
|
||||
<SolidColorBrush x:Key="AppBarBackgroundColor">Transparent</SolidColorBrush>
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Name="Light">
|
||||
<!-- Brushes -->
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#fdcb6e</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Name="Dark">
|
||||
<!-- Brushes -->
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#5413191F</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
@@ -1,22 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:xaml="using:Microsoft.UI.Xaml">
|
||||
|
||||
<x:String x:Key="ThemeName">Snowflake</x:String>
|
||||
<x:String x:Key="ThemeBackgroundImage">ms-appx:///Wino.Core.WinUI/BackgroundImages/Snowflake.jpg</x:String>
|
||||
|
||||
<ImageBrush x:Key="WinoApplicationBackgroundColor" ImageSource="{StaticResource ThemeBackgroundImage}" />
|
||||
<SolidColorBrush x:Key="AppBarBackgroundColor">Transparent</SolidColorBrush>
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Name="Light">
|
||||
<!-- Brushes -->
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#b0c6dd</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Name="Dark">
|
||||
<!-- Brushes -->
|
||||
<SolidColorBrush x:Key="MailListHeaderBackgroundColor">#b0c6dd</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
@@ -1,22 +0,0 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<x:String x:Key="ThemeName">TestTheme.xaml</x:String>
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Name="Light">
|
||||
<!-- Background Image -->
|
||||
<x:String x:Key="ThemeBackgroundImage">ms-appx:///BackgroundImages/bg6.jpg</x:String>
|
||||
<SolidColorBrush x:Key="ShellTitleBarBackgroundColorBrush">#A3FFFFFF</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ShellNavigationViewBackgroundColorBrush">#A3FFFFFF</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ReadingPaneBackgroundColorBrush">#fdcb6e</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Name="Dark">
|
||||
<!-- Background Image -->
|
||||
<x:String x:Key="ThemeBackgroundImage">ms-appx:///BackgroundImages/bg6.jpg</x:String>
|
||||
|
||||
<SolidColorBrush x:Key="ShellTitleBarBackgroundColorBrush">#A3000000</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ShellNavigationViewBackgroundColorBrush">#A3000000</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ReadingPaneBackgroundColorBrush">#A3262626</SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
Before Width: | Height: | Size: 348 B |
|
Before Width: | Height: | Size: 504 B |
|
Before Width: | Height: | Size: 678 B |
|
Before Width: | Height: | Size: 591 B |
|
Before Width: | Height: | Size: 599 B |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 256 B |
|
Before Width: | Height: | Size: 712 B |
|
Before Width: | Height: | Size: 621 B |
|
Before Width: | Height: | Size: 413 B |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 962 KiB |
|
Before Width: | Height: | Size: 80 KiB |
@@ -1,95 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using Wino.Core.ViewModels;
|
||||
using Wino.Messaging.Client.Shell;
|
||||
|
||||
namespace Wino.Core.WinUI;
|
||||
|
||||
public partial class BasePage : Page, IRecipient<LanguageChanged>
|
||||
{
|
||||
public UIElement ShellContent
|
||||
{
|
||||
get { return (UIElement)GetValue(ShellContentProperty); }
|
||||
set { SetValue(ShellContentProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShellContentProperty = DependencyProperty.Register(nameof(ShellContent), typeof(UIElement), typeof(BasePage), new PropertyMetadata(null));
|
||||
|
||||
public void Receive(LanguageChanged message)
|
||||
{
|
||||
OnLanguageChanged();
|
||||
}
|
||||
|
||||
public virtual void OnLanguageChanged() { }
|
||||
|
||||
/// <summary>
|
||||
/// Register message recipients for this page. Override to register specific message types.
|
||||
/// </summary>
|
||||
protected virtual void RegisterRecipients() { }
|
||||
|
||||
/// <summary>
|
||||
/// Unregister message recipients for this page. Override to unregister specific message types.
|
||||
/// </summary>
|
||||
protected virtual void UnregisterRecipients() { }
|
||||
}
|
||||
|
||||
public abstract class BasePage<T> : BasePage where T : CoreBaseViewModel
|
||||
{
|
||||
public T ViewModel { get; } = WinoApplication.Current.Services.GetService<T>();
|
||||
|
||||
protected BasePage()
|
||||
{
|
||||
ViewModel.Dispatcher = new WinUIDispatcher(DispatcherQueue);
|
||||
|
||||
Loaded += PageLoaded;
|
||||
Unloaded += PageUnloaded;
|
||||
}
|
||||
|
||||
private void PageUnloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Loaded -= PageLoaded;
|
||||
Unloaded -= PageUnloaded;
|
||||
}
|
||||
|
||||
private void PageLoaded(object sender, RoutedEventArgs e) => ViewModel.OnPageLoaded();
|
||||
|
||||
~BasePage() { Debug.WriteLine($"Disposed {GetType().Name}"); }
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
base.OnNavigatedTo(e);
|
||||
|
||||
var mode = GetNavigationMode(e.NavigationMode);
|
||||
var parameter = e.Parameter;
|
||||
|
||||
WeakReferenceMessenger.Default.Register<LanguageChanged>(this);
|
||||
RegisterRecipients();
|
||||
|
||||
ViewModel.OnNavigatedTo(mode, parameter);
|
||||
}
|
||||
|
||||
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
|
||||
{
|
||||
base.OnNavigatingFrom(e);
|
||||
|
||||
var mode = GetNavigationMode(e.NavigationMode);
|
||||
var parameter = e.Parameter;
|
||||
|
||||
WeakReferenceMessenger.Default.Unregister<LanguageChanged>(this);
|
||||
UnregisterRecipients();
|
||||
|
||||
ViewModel.OnNavigatedFrom(mode, parameter);
|
||||
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
private Domain.Models.Navigation.NavigationMode GetNavigationMode(NavigationMode mode)
|
||||
{
|
||||
return (Domain.Models.Navigation.NavigationMode)mode;
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.WinUI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Messaging.UI;
|
||||
|
||||
|
||||
namespace Wino.Core.WinUI.Controls;
|
||||
|
||||
public sealed partial class AccountCreationDialogControl : UserControl, IRecipient<CopyAuthURLRequested>
|
||||
{
|
||||
private string copyClipboardURL;
|
||||
|
||||
public event EventHandler CancelClicked;
|
||||
|
||||
public AccountCreationDialogState State
|
||||
{
|
||||
get { return (AccountCreationDialogState)GetValue(StateProperty); }
|
||||
set { SetValue(StateProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty StateProperty = DependencyProperty.Register(nameof(State), typeof(AccountCreationDialogState), typeof(AccountCreationDialogControl), new PropertyMetadata(AccountCreationDialogState.Idle, new PropertyChangedCallback(OnStateChanged)));
|
||||
|
||||
public AccountCreationDialogControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private static void OnStateChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is AccountCreationDialogControl dialog)
|
||||
{
|
||||
dialog.UpdateVisualStates();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVisualStates() => VisualStateManager.GoToState(this, State.ToString(), false);
|
||||
|
||||
public async void Receive(CopyAuthURLRequested message)
|
||||
{
|
||||
copyClipboardURL = message.AuthURL;
|
||||
|
||||
await Task.Delay(2000);
|
||||
|
||||
await DispatcherQueue.EnqueueAsync(async () =>
|
||||
{
|
||||
AuthHelpDialogButton.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
|
||||
});
|
||||
}
|
||||
|
||||
private void ControlLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
WeakReferenceMessenger.Default.Register(this);
|
||||
}
|
||||
|
||||
private void ControlUnloaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
WeakReferenceMessenger.Default.UnregisterAll(this);
|
||||
}
|
||||
|
||||
private async void CopyClicked(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(copyClipboardURL)) return;
|
||||
|
||||
var clipboardService = WinoApplication.Current.Services.GetService<IClipboardService>();
|
||||
await clipboardService.CopyClipboardAsync(copyClipboardURL);
|
||||
}
|
||||
|
||||
|
||||
private void CancelButtonClicked(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) => CancelClicked?.Invoke(this, null);
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wino.Core.WinUI.Controls;
|
||||
|
||||
public static class ControlConstants
|
||||
{
|
||||
public static Dictionary<WinoIconGlyph, string> WinoIconFontDictionary = new Dictionary<WinoIconGlyph, string>()
|
||||
{
|
||||
{ WinoIconGlyph.None, "\u0020" },
|
||||
{ WinoIconGlyph.Archive, "\uE066" },
|
||||
{ WinoIconGlyph.UnArchive, "\uE06C" },
|
||||
{ WinoIconGlyph.Reply, "\uF176" },
|
||||
{ WinoIconGlyph.ReplyAll, "\uF17A" },
|
||||
{ WinoIconGlyph.Sync, "\uE895" },
|
||||
{ WinoIconGlyph.Send, "\uEA8E" },
|
||||
{ WinoIconGlyph.LightEditor, "\uE1F6" },
|
||||
{ WinoIconGlyph.Delete, "\uEEA6" },
|
||||
{ WinoIconGlyph.DarkEditor, "\uEE44" },
|
||||
{ WinoIconGlyph.Draft, "\uF3BE" },
|
||||
{ WinoIconGlyph.Flag, "\uF40C" },
|
||||
{ WinoIconGlyph.ClearFlag, "\uF40F" },
|
||||
{ WinoIconGlyph.Folder, "\uE643" },
|
||||
{ WinoIconGlyph.Forward, "\uE7AA" },
|
||||
{ WinoIconGlyph.Inbox, "\uF516" },
|
||||
{ WinoIconGlyph.MarkRead, "\uF522" },
|
||||
{ WinoIconGlyph.MarkUnread, "\uF529" },
|
||||
{ WinoIconGlyph.MultiSelect, "\uE84D" },
|
||||
{ WinoIconGlyph.Save, "\uEA43" },
|
||||
{ WinoIconGlyph.CreateFolder, "\uE645" },
|
||||
{ WinoIconGlyph.Pin, "\uF5FF" },
|
||||
{ WinoIconGlyph.UnPin, "\uE985" },
|
||||
{ WinoIconGlyph.Star, "\uE734" },
|
||||
{ WinoIconGlyph.Ignore, "\uF5D0" },
|
||||
{ WinoIconGlyph.Find, "\uEA7D" },
|
||||
{ WinoIconGlyph.Zoom, "\uEE8E" },
|
||||
{ WinoIconGlyph.SpecialFolderInbox, "\uF516" },
|
||||
{ WinoIconGlyph.SpecialFolderStarred, "\uF70D" },
|
||||
{ WinoIconGlyph.SpecialFolderImportant, "\uE2F4" },
|
||||
{ WinoIconGlyph.SpecialFolderSent, "\uEA8E" },
|
||||
{ WinoIconGlyph.SpecialFolderDraft, "\uF3BE" },
|
||||
{ WinoIconGlyph.SpecialFolderArchive, "\uE066" },
|
||||
{ WinoIconGlyph.SpecialFolderDeleted, "\uEEA6" },
|
||||
{ WinoIconGlyph.SpecialFolderJunk, "\uF140" },
|
||||
{ WinoIconGlyph.SpecialFolderChat, "\uE8BD" },
|
||||
{ WinoIconGlyph.SpecialFolderCategory, "\uF599" },
|
||||
{ WinoIconGlyph.SpecialFolderUnread, "\uF529" },
|
||||
{ WinoIconGlyph.SpecialFolderForums, "\uF5B8" },
|
||||
{ WinoIconGlyph.SpecialFolderUpdated, "\uF565" },
|
||||
{ WinoIconGlyph.SpecialFolderPersonal, "\uE25A" },
|
||||
{ WinoIconGlyph.SpecialFolderPromotions, "\uF7B6" },
|
||||
{ WinoIconGlyph.SpecialFolderSocial, "\uEEEB" },
|
||||
{ WinoIconGlyph.SpecialFolderOther, "\uE643" },
|
||||
{ WinoIconGlyph.SpecialFolderMore, "\uF0F4" },
|
||||
{ WinoIconGlyph.Microsoft, "\uE904" },
|
||||
{ WinoIconGlyph.Google, "\uE905" },
|
||||
{ WinoIconGlyph.NewMail, "\uF107" },
|
||||
{ WinoIconGlyph.TurnOfNotifications, "\uF11D" },
|
||||
{ WinoIconGlyph.Rename, "\uF668" },
|
||||
{ WinoIconGlyph.EmptyFolder, "\uE47E" },
|
||||
{ WinoIconGlyph.DontSync, "\uF195" },
|
||||
{ WinoIconGlyph.Move, "\uE7B8" },
|
||||
{ WinoIconGlyph.Mail, "\uF509" },
|
||||
{ WinoIconGlyph.More, "\uE824" },
|
||||
{ WinoIconGlyph.CustomServer, "\uF509" },
|
||||
{ WinoIconGlyph.Print, "\uE922" },
|
||||
{ WinoIconGlyph.Attachment, "\uE723" },
|
||||
{ WinoIconGlyph.SortTextDesc, "\U000F3606" },
|
||||
{ WinoIconGlyph.SortLinesDesc, "\U000F038A" },
|
||||
{ WinoIconGlyph.Certificate, "\uEB95" },
|
||||
{ WinoIconGlyph.OpenInNewWindow, "\uE8A7" },
|
||||
{ WinoIconGlyph.Message, "\uE8BD" },
|
||||
{ WinoIconGlyph.New, "\U000F002A" },
|
||||
{ WinoIconGlyph.Blocked,"\uF140" },
|
||||
{ WinoIconGlyph.IMAP, "\uE715" },
|
||||
{ WinoIconGlyph.Calendar, "\uE912" },
|
||||
{ WinoIconGlyph.CalendarToday, "\uE911" },
|
||||
{ WinoIconGlyph.CalendarDay, "\uE913" },
|
||||
{ WinoIconGlyph.CalendarWeek, "\uE914" },
|
||||
{ WinoIconGlyph.CalendarMonth, "\uE91c" },
|
||||
{ WinoIconGlyph.CalendarYear, "\uE917" },
|
||||
{ WinoIconGlyph.WeatherBlow, "\uE907" },
|
||||
{ WinoIconGlyph.WeatherCloudy, "\uE920" },
|
||||
{ WinoIconGlyph.WeatherSunny, "\uE90e" },
|
||||
{ WinoIconGlyph.WeatherRainy, "\uE908" },
|
||||
{ WinoIconGlyph.WeatherSnowy, "\uE90a" },
|
||||
{ WinoIconGlyph.WeatherSnowShowerAtNight, "\uE90c" },
|
||||
{ WinoIconGlyph.WeatherThunderstorm, "\uE906" },
|
||||
{ WinoIconGlyph.CalendarEventRepeat, "\uE915" },
|
||||
{ WinoIconGlyph.CalendarEventMuiltiDay, "\uE91b" },
|
||||
{ WinoIconGlyph.Reminder, "\uE918" },
|
||||
{ WinoIconGlyph.CalendarAttendee, "\uE91a" },
|
||||
{ WinoIconGlyph.CalendarSync, "\uE91d" },
|
||||
{ WinoIconGlyph.CalendarError, "\uE916" },
|
||||
{ WinoIconGlyph.CalendarAttendees, "\uE929" },
|
||||
{ WinoIconGlyph.EventEditSeries, "\uE92A" },
|
||||
{ WinoIconGlyph.EventTentative, "\uE928" },
|
||||
{ WinoIconGlyph.EventAccept, "\uE925" },
|
||||
{ WinoIconGlyph.EventRespond, "\uE924" },
|
||||
{ WinoIconGlyph.EventReminder, "\uE923" },
|
||||
{ WinoIconGlyph.EventJoinOnline, "\uE926" },
|
||||
{ WinoIconGlyph.ViewMessageSource, "\uE943" },
|
||||
{ WinoIconGlyph.Apple, "\uE92B" },
|
||||
{ WinoIconGlyph.Yahoo, "\uE92C" }
|
||||
};
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Wino.Core.WinUI.Controls
|
||||
{
|
||||
using Windows.Foundation;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace CustomControls
|
||||
{
|
||||
public partial class CustomWrapPanel : Panel
|
||||
{
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
double currentRowWidth = 0;
|
||||
double currentRowHeight = 0;
|
||||
double totalHeight = 0;
|
||||
|
||||
foreach (UIElement child in Children)
|
||||
{
|
||||
child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
|
||||
|
||||
var childDesiredSize = child.DesiredSize;
|
||||
|
||||
if (currentRowWidth + childDesiredSize.Width > availableSize.Width)
|
||||
{
|
||||
// Wrap to the next row
|
||||
totalHeight += currentRowHeight;
|
||||
currentRowWidth = 0;
|
||||
currentRowHeight = 0;
|
||||
}
|
||||
|
||||
currentRowWidth += childDesiredSize.Width;
|
||||
currentRowHeight = Math.Max(currentRowHeight, childDesiredSize.Height);
|
||||
}
|
||||
|
||||
totalHeight += currentRowHeight;
|
||||
|
||||
return new Size(availableSize.Width, totalHeight);
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
double currentRowWidth = 0;
|
||||
double currentRowHeight = 0;
|
||||
double currentY = 0;
|
||||
|
||||
foreach (UIElement child in Children)
|
||||
{
|
||||
var childDesiredSize = child.DesiredSize;
|
||||
|
||||
if (currentRowWidth + childDesiredSize.Width > finalSize.Width)
|
||||
{
|
||||
currentY += currentRowHeight;
|
||||
currentRowWidth = 0;
|
||||
currentRowHeight = 0;
|
||||
}
|
||||
|
||||
child.Arrange(new Rect(new Point(currentRowWidth, currentY), childDesiredSize));
|
||||
|
||||
currentRowWidth += childDesiredSize.Width;
|
||||
currentRowHeight = Math.Max(currentRowHeight, childDesiredSize.Height);
|
||||
}
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
using Windows.Foundation;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Wino.Core.WinUI.Controls;
|
||||
|
||||
public partial class EqualGridPanel : Panel
|
||||
{
|
||||
public int Rows
|
||||
{
|
||||
get { return (int)GetValue(RowsProperty); }
|
||||
set { SetValue(RowsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty RowsProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(Rows),
|
||||
typeof(int),
|
||||
typeof(EqualGridPanel),
|
||||
new PropertyMetadata(1, OnLayoutPropertyChanged));
|
||||
|
||||
public int Columns
|
||||
{
|
||||
get { return (int)GetValue(ColumnsProperty); }
|
||||
set { SetValue(ColumnsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ColumnsProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(Columns),
|
||||
typeof(int),
|
||||
typeof(EqualGridPanel),
|
||||
new PropertyMetadata(1, OnLayoutPropertyChanged));
|
||||
|
||||
private static void OnLayoutPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is EqualGridPanel panel)
|
||||
{
|
||||
panel.InvalidateMeasure();
|
||||
panel.InvalidateArrange();
|
||||
}
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
if (Rows <= 0 || Columns <= 0)
|
||||
{
|
||||
return new Size(0, 0);
|
||||
}
|
||||
|
||||
double cellWidth = availableSize.Width / Columns;
|
||||
double cellHeight = availableSize.Height / Rows;
|
||||
|
||||
foreach (UIElement child in Children)
|
||||
{
|
||||
child.Measure(new Size(cellWidth, cellHeight));
|
||||
}
|
||||
|
||||
return availableSize;
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
if (Rows <= 0 || Columns <= 0)
|
||||
{
|
||||
return new Size(0, 0);
|
||||
}
|
||||
|
||||
double cellWidth = finalSize.Width / Columns;
|
||||
double cellHeight = finalSize.Height / Rows;
|
||||
|
||||
for (int i = 0; i < Children.Count; i++)
|
||||
{
|
||||
int row = i / Columns;
|
||||
int column = i % Columns;
|
||||
|
||||
double x = column * cellWidth;
|
||||
double y = row * cellHeight;
|
||||
|
||||
Rect rect = new Rect(x, y, cellWidth, cellHeight);
|
||||
Children[i].Arrange(rect);
|
||||
}
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Wino.Core.WinUI.Controls;
|
||||
|
||||
public enum WinoIconGlyph
|
||||
{
|
||||
None,
|
||||
NewMail,
|
||||
Google,
|
||||
Microsoft,
|
||||
CustomServer,
|
||||
Archive,
|
||||
UnArchive,
|
||||
Reply,
|
||||
ReplyAll,
|
||||
LightEditor,
|
||||
DarkEditor,
|
||||
Delete,
|
||||
Move,
|
||||
Mail,
|
||||
Draft,
|
||||
Flag,
|
||||
ClearFlag,
|
||||
Folder,
|
||||
Forward,
|
||||
Inbox,
|
||||
MarkRead,
|
||||
MarkUnread,
|
||||
Send,
|
||||
Save,
|
||||
Sync,
|
||||
MultiSelect,
|
||||
Zoom,
|
||||
Pin,
|
||||
UnPin,
|
||||
Ignore,
|
||||
Star,
|
||||
CreateFolder,
|
||||
More,
|
||||
Find,
|
||||
SpecialFolderInbox,
|
||||
SpecialFolderStarred,
|
||||
SpecialFolderImportant,
|
||||
SpecialFolderSent,
|
||||
SpecialFolderDraft,
|
||||
SpecialFolderArchive,
|
||||
SpecialFolderDeleted,
|
||||
SpecialFolderJunk,
|
||||
SpecialFolderChat,
|
||||
SpecialFolderCategory,
|
||||
SpecialFolderUnread,
|
||||
SpecialFolderForums,
|
||||
SpecialFolderUpdated,
|
||||
SpecialFolderPersonal,
|
||||
SpecialFolderPromotions,
|
||||
SpecialFolderSocial,
|
||||
SpecialFolderOther,
|
||||
SpecialFolderMore,
|
||||
TurnOfNotifications,
|
||||
EmptyFolder,
|
||||
Rename,
|
||||
DontSync,
|
||||
Attachment,
|
||||
SortTextDesc,
|
||||
SortLinesDesc,
|
||||
Certificate,
|
||||
OpenInNewWindow,
|
||||
Blocked,
|
||||
Message,
|
||||
New,
|
||||
IMAP,
|
||||
Print,
|
||||
Calendar,
|
||||
CalendarToday,
|
||||
CalendarDay,
|
||||
CalendarWeek,
|
||||
CalendarWorkWeek,
|
||||
CalendarMonth,
|
||||
CalendarYear,
|
||||
WeatherBlow,
|
||||
WeatherCloudy,
|
||||
WeatherSunny,
|
||||
WeatherRainy,
|
||||
WeatherSnowy,
|
||||
WeatherSnowShowerAtNight,
|
||||
WeatherThunderstorm,
|
||||
CalendarEventRepeat,
|
||||
CalendarEventMuiltiDay,
|
||||
CalendarError,
|
||||
Reminder,
|
||||
CalendarAttendee,
|
||||
CalendarAttendees,
|
||||
CalendarSync,
|
||||
EventRespond,
|
||||
EventAccept,
|
||||
EventTentative,
|
||||
EventDecline,
|
||||
EventReminder,
|
||||
EventEditSeries,
|
||||
EventJoinOnline,
|
||||
ViewMessageSource,
|
||||
Apple,
|
||||
Yahoo
|
||||
}
|
||||
|
||||
public partial class WinoFontIcon : FontIcon
|
||||
{
|
||||
public WinoIconGlyph Icon
|
||||
{
|
||||
get { return (WinoIconGlyph)GetValue(IconProperty); }
|
||||
set { SetValue(IconProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(nameof(Icon), typeof(WinoIconGlyph), typeof(WinoFontIcon), new PropertyMetadata(WinoIconGlyph.Flag, OnIconChanged));
|
||||
|
||||
public WinoFontIcon()
|
||||
{
|
||||
FontFamily = new Microsoft.UI.Xaml.Media.FontFamily("/Wino.Core.WinUI/Assets/WinoIcons.ttf#WinoIcons");
|
||||
FontSize = 32;
|
||||
}
|
||||
|
||||
private static void OnIconChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is WinoFontIcon fontIcon)
|
||||
{
|
||||
fontIcon.UpdateGlyph();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGlyph()
|
||||
{
|
||||
Glyph = ControlConstants.WinoIconFontDictionary[Icon];
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Wino.Core.WinUI.Controls;
|
||||
|
||||
namespace Wino.Controls;
|
||||
|
||||
public partial class WinoFontIconSource : Microsoft.UI.Xaml.Controls.FontIconSource
|
||||
{
|
||||
public WinoIconGlyph Icon
|
||||
{
|
||||
get { return (WinoIconGlyph)GetValue(IconProperty); }
|
||||
set { SetValue(IconProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(nameof(Icon), typeof(WinoIconGlyph), typeof(WinoFontIconSource), new PropertyMetadata(WinoIconGlyph.Flag, OnIconChanged));
|
||||
|
||||
public WinoFontIconSource()
|
||||
{
|
||||
FontFamily = new Microsoft.UI.Xaml.Media.FontFamily("ms-appx:///Assets/WinoIcons.ttf#WinoIcons");
|
||||
FontSize = 32;
|
||||
}
|
||||
|
||||
private static void OnIconChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is WinoFontIconSource fontIcon)
|
||||
{
|
||||
fontIcon.UpdateGlyph();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGlyph()
|
||||
{
|
||||
Glyph = ControlConstants.WinoIconFontDictionary[Icon];
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using CommunityToolkit.WinUI.Animations;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.WinUI.Controls;
|
||||
|
||||
public partial class WinoInfoBar : InfoBar
|
||||
{
|
||||
public static readonly DependencyProperty AnimationTypeProperty = DependencyProperty.Register(nameof(AnimationType), typeof(InfoBarAnimationType), typeof(WinoInfoBar), new PropertyMetadata(InfoBarAnimationType.SlideFromRightToLeft));
|
||||
public static readonly DependencyProperty DismissIntervalProperty = DependencyProperty.Register(nameof(DismissInterval), typeof(int), typeof(WinoInfoBar), new PropertyMetadata(5, new PropertyChangedCallback(OnDismissIntervalChanged)));
|
||||
|
||||
public InfoBarAnimationType AnimationType
|
||||
{
|
||||
get { return (InfoBarAnimationType)GetValue(AnimationTypeProperty); }
|
||||
set { SetValue(AnimationTypeProperty, value); }
|
||||
}
|
||||
|
||||
public int DismissInterval
|
||||
{
|
||||
get { return (int)GetValue(DismissIntervalProperty); }
|
||||
set { SetValue(DismissIntervalProperty, value); }
|
||||
}
|
||||
|
||||
private readonly DispatcherTimer _dispatcherTimer = new DispatcherTimer();
|
||||
|
||||
public WinoInfoBar()
|
||||
{
|
||||
RegisterPropertyChangedCallback(IsOpenProperty, IsOpenChanged);
|
||||
|
||||
_dispatcherTimer.Interval = TimeSpan.FromSeconds(DismissInterval);
|
||||
}
|
||||
|
||||
private static void OnDismissIntervalChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is WinoInfoBar bar)
|
||||
{
|
||||
bar.UpdateInterval(bar.DismissInterval);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateInterval(int seconds) => _dispatcherTimer.Interval = TimeSpan.FromSeconds(seconds);
|
||||
|
||||
private async void IsOpenChanged(DependencyObject sender, DependencyProperty dp)
|
||||
{
|
||||
if (sender is WinoInfoBar control)
|
||||
{
|
||||
// Message shown.
|
||||
if (!control.IsOpen) return;
|
||||
|
||||
Opacity = 1;
|
||||
|
||||
_dispatcherTimer.Stop();
|
||||
|
||||
_dispatcherTimer.Tick -= TimerTick;
|
||||
_dispatcherTimer.Tick += TimerTick;
|
||||
|
||||
_dispatcherTimer.Start();
|
||||
|
||||
// Slide from right.
|
||||
if (AnimationType == InfoBarAnimationType.SlideFromRightToLeft)
|
||||
{
|
||||
await AnimationBuilder.Create().Translation(new Vector3(0, 0, 0), new Vector3(150, 0, 0), null, TimeSpan.FromSeconds(0.5)).StartAsync(this);
|
||||
}
|
||||
else if (AnimationType == InfoBarAnimationType.SlideFromBottomToTop)
|
||||
{
|
||||
await AnimationBuilder.Create().Translation(new Vector3(0, 0, 0), new Vector3(0, 50, 0), null, TimeSpan.FromSeconds(0.5)).StartAsync(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void TimerTick(object sender, object e)
|
||||
{
|
||||
_dispatcherTimer.Stop();
|
||||
_dispatcherTimer.Tick -= TimerTick;
|
||||
|
||||
if (AnimationType == InfoBarAnimationType.SlideFromRightToLeft)
|
||||
{
|
||||
await AnimationBuilder.Create().Translation(new Vector3((float)ActualWidth, 0, 0), new Vector3(0, 0, 0), null, TimeSpan.FromSeconds(0.5)).StartAsync(this);
|
||||
}
|
||||
else if (AnimationType == InfoBarAnimationType.SlideFromBottomToTop)
|
||||
{
|
||||
await AnimationBuilder.Create().Translation(new Vector3(0, (float)ActualHeight, 0), new Vector3(0, 0, 0), null, TimeSpan.FromSeconds(0.5)).StartAsync(this);
|
||||
}
|
||||
|
||||
IsOpen = false;
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using System.Numerics;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Hosting;
|
||||
|
||||
namespace Wino.Core.WinUI.Controls;
|
||||
|
||||
public partial class WinoNavigationViewItem : NavigationViewItem
|
||||
{
|
||||
public bool IsDraggingItemOver
|
||||
{
|
||||
get { return (bool)GetValue(IsDraggingItemOverProperty); }
|
||||
set { SetValue(IsDraggingItemOverProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsDraggingItemOverProperty = DependencyProperty.Register(nameof(IsDraggingItemOver), typeof(bool), typeof(WinoNavigationViewItem), new PropertyMetadata(false, OnIsDraggingItemOverChanged));
|
||||
|
||||
private static void OnIsDraggingItemOverChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is WinoNavigationViewItem control)
|
||||
control.UpdateDragEnterState();
|
||||
}
|
||||
|
||||
private void UpdateDragEnterState()
|
||||
{
|
||||
// TODO: Add animation. Maybe after overriding DragUI in shell?
|
||||
|
||||
//if (IsDraggingItemOver)
|
||||
//{
|
||||
// ScaleAnimation(new System.Numerics.Vector3(1.2f, 1.2f, 1.2f));
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// ScaleAnimation(new System.Numerics.Vector3(1f, 1f, 1f));
|
||||
//}
|
||||
}
|
||||
|
||||
private void ScaleAnimation(Vector3 vector)
|
||||
{
|
||||
if (Content is UIElement content)
|
||||
{
|
||||
var visual = ElementCompositionPreview.GetElementVisual(content);
|
||||
visual.Scale = vector;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
namespace Wino.Converters;
|
||||
|
||||
public partial class GridLengthConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is double doubleValue)
|
||||
{
|
||||
return new GridLength(doubleValue);
|
||||
}
|
||||
return new GridLength(1, GridUnitType.Auto);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is GridLength gridLength)
|
||||
{
|
||||
return gridLength.Value;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Windows.UI;
|
||||
|
||||
namespace Wino.Core.WinUI.Converters;
|
||||
|
||||
public partial class HexToColorBrushConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is string hexColor && !string.IsNullOrEmpty(hexColor))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Remove # if present
|
||||
hexColor = hexColor.Replace("#", "");
|
||||
|
||||
// Parse hex to color
|
||||
byte r = byte.Parse(hexColor.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
|
||||
byte g = byte.Parse(hexColor.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
|
||||
byte b = byte.Parse(hexColor.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
|
||||
|
||||
return new SolidColorBrush(Color.FromArgb(255, r, g, b));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return GetDefaultBrush();
|
||||
}
|
||||
}
|
||||
|
||||
return GetDefaultBrush();
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is string hexColor)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Remove # if present
|
||||
hexColor = hexColor.Replace("#", string.Empty);
|
||||
|
||||
// Parse ARGB values
|
||||
byte a = 255; // Default to fully opaque
|
||||
byte r = byte.Parse(hexColor.Substring(0, 2), NumberStyles.HexNumber);
|
||||
byte g = byte.Parse(hexColor.Substring(2, 2), NumberStyles.HexNumber);
|
||||
byte b = byte.Parse(hexColor.Substring(4, 2), NumberStyles.HexNumber);
|
||||
|
||||
// If 8-digit hex (with alpha), parse alpha value
|
||||
if (hexColor.Length == 8)
|
||||
{
|
||||
a = byte.Parse(hexColor.Substring(6, 2), NumberStyles.HexNumber);
|
||||
}
|
||||
|
||||
return Color.FromArgb(a, r, g, b);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return DependencyProperty.UnsetValue;
|
||||
}
|
||||
}
|
||||
|
||||
return DependencyProperty.UnsetValue;
|
||||
}
|
||||
|
||||
private SolidColorBrush GetDefaultBrush()
|
||||
{
|
||||
// Get current theme's foreground brush.
|
||||
// Bug: This should be ThemeResource to react to theme changes, but it's not.
|
||||
// So if user changes the dark/light theme, this won't update.
|
||||
|
||||
if (WinoApplication.Current.UnderlyingThemeService.IsUnderlyingThemeDark())
|
||||
return new SolidColorBrush(Colors.White);
|
||||
else
|
||||
return new SolidColorBrush(Colors.Black);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
namespace Wino.Converters;
|
||||
|
||||
public partial class ReverseBooleanConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is bool boolval)
|
||||
return !boolval;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
namespace Wino.Converters;
|
||||
|
||||
public partial class ReverseBooleanToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return ((bool)value) ? Visibility.Collapsed : Visibility.Visible;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ResourceDictionary
|
||||
x:Class="Wino.Core.WinUI.CoreGeneric"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:coreControls="using:Wino.Core.WinUI.Controls"
|
||||
xmlns:styles="using:Wino.Core.WinUI.Styles">
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
|
||||
<ResourceDictionary Source="Styles/Colors.xaml" />
|
||||
<ResourceDictionary Source="Styles/ContentPresenters.xaml" />
|
||||
<ResourceDictionary Source="Styles/Converters.xaml" />
|
||||
<ResourceDictionary Source="Styles/FontIcons.xaml" />
|
||||
<ResourceDictionary Source="Styles/WinoInfoBar.xaml" />
|
||||
<ResourceDictionary Source="Styles/SharedStyles.xaml" />
|
||||
<ResourceDictionary Source="Styles/IconTemplates.xaml" />
|
||||
|
||||
<styles:CustomMessageDialogStyles />
|
||||
<styles:DataTemplates />
|
||||
|
||||
<ResourceDictionary>
|
||||
<Style TargetType="ScrollViewer">
|
||||
<Setter Property="VerticalScrollBarVisibility" Value="Auto" />
|
||||
</Style>
|
||||
|
||||
<!-- Remove border/backgroud of command bar -->
|
||||
<SolidColorBrush x:Key="CommandBarBackground" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="CommandBarBackgroundOpen" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="CommandBarBorderBrushOpen" Color="Transparent" />
|
||||
<Thickness x:Key="CommandBarBorderThicknessOpen">0</Thickness>
|
||||
|
||||
<!-- Override AppBarToggleButton's checked background color. -->
|
||||
<StaticResource x:Key="AppBarToggleButtonBackgroundChecked" ResourceKey="SystemAccentColor" />
|
||||
<StaticResource x:Key="AppBarToggleButtonBackgroundCheckedPointerOver" ResourceKey="SystemAccentColor" />
|
||||
<StaticResource x:Key="AppBarToggleButtonBackgroundCheckedPressed" ResourceKey="SystemAccentColor" />
|
||||
|
||||
<Thickness x:Key="ImapSetupDialogSubPagePadding">24,24,24,24</Thickness>
|
||||
|
||||
<!-- Border style for each page's root border for separation of zones. -->
|
||||
<Style x:Key="PageRootBorderStyle" TargetType="Border">
|
||||
<Setter Property="Background" Value="{ThemeResource WinoContentZoneBackgroud}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource CardStrokeColorDefaultBrush}" />
|
||||
<Setter Property="CornerRadius" Value="7" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
</Style>
|
||||
|
||||
<!-- Custom Grid style for info panels. -->
|
||||
<Style x:Key="InformationAreaGridStyle" TargetType="Grid">
|
||||
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource DividerStrokeColorDefaultBrush}" />
|
||||
<Setter Property="CornerRadius" Value="8" />
|
||||
<Setter Property="Padding" Value="16" />
|
||||
</Style>
|
||||
|
||||
<!-- Default StackPanel animation. -->
|
||||
<Style TargetType="StackPanel">
|
||||
<Setter Property="ChildrenTransitions">
|
||||
<Setter.Value>
|
||||
<TransitionCollection>
|
||||
<EntranceThemeTransition IsStaggeringEnabled="False" />
|
||||
</TransitionCollection>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!-- Default Style for ContentDialog -->
|
||||
<Style
|
||||
x:Key="WinoDialogStyle"
|
||||
BasedOn="{StaticResource DefaultContentDialogStyle}"
|
||||
TargetType="ContentDialog" />
|
||||
|
||||
<!-- Wino Navigation View Item -->
|
||||
<Style TargetType="coreControls:WinoNavigationViewItem">
|
||||
<Setter Property="ContentTransitions">
|
||||
<Setter.Value>
|
||||
<TransitionCollection>
|
||||
<PopupThemeTransition />
|
||||
</TransitionCollection>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="PageStyle" TargetType="Page">
|
||||
<Setter Property="Margin" Value="-1,0,0,0" />
|
||||
<Setter Property="Padding" Value="12" />
|
||||
<Setter Property="Background" Value="{ThemeResource AppBarBackgroundColor}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Grid Padding="12">
|
||||
<ContentPresenter />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!-- Spacing between cards -->
|
||||
<x:Double x:Key="SettingsCardSpacing">4</x:Double>
|
||||
|
||||
<!-- Style (inc. the correct spacing) of a section header -->
|
||||
<Style
|
||||
x:Key="SettingsSectionHeaderTextBlockStyle"
|
||||
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
|
||||
TargetType="TextBlock">
|
||||
<Style.Setters>
|
||||
<Setter Property="Margin" Value="1,30,0,6" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
|
||||
namespace Wino.Core.WinUI;
|
||||
|
||||
public partial class CoreGeneric : ResourceDictionary
|
||||
{
|
||||
public CoreGeneric() => InitializeComponent();
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.ViewModels;
|
||||
using Wino.Core.WinUI.Services;
|
||||
using Wino.Services;
|
||||
|
||||
namespace Wino.Core.WinUI;
|
||||
|
||||
public static class CoreUWPContainerSetup
|
||||
{
|
||||
public static void RegisterCoreUWPServices(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<IApplicationResourceManager<ResourceDictionary>, ApplicationResourceManager>();
|
||||
|
||||
services.AddSingleton<IUnderlyingThemeService, UnderlyingThemeService>();
|
||||
services.AddSingleton<INativeAppService, NativeAppService>();
|
||||
services.AddSingleton<IStoreManagementService, StoreManagementService>();
|
||||
services.AddSingleton<IPreferencesService, PreferencesService>();
|
||||
services.AddSingleton<INewThemeService, NewThemeService>();
|
||||
services.AddSingleton<IStatePersistanceService, StatePersistenceService>();
|
||||
services.AddSingleton<IThumbnailService, ThumbnailService>();
|
||||
services.AddSingleton<IDialogServiceBase, DialogServiceBase>();
|
||||
services.AddTransient<IConfigurationService, ConfigurationService>();
|
||||
services.AddTransient<IFileService, FileService>();
|
||||
services.AddTransient<IStoreRatingService, StoreRatingService>();
|
||||
services.AddTransient<IKeyPressService, KeyPressService>();
|
||||
services.AddTransient<INotificationBuilder, NotificationBuilder>();
|
||||
services.AddTransient<IClipboardService, ClipboardService>();
|
||||
services.AddTransient<IStartupBehaviorService, StartupBehaviorService>();
|
||||
services.AddSingleton<IPrintService, PrintService>();
|
||||
|
||||
}
|
||||
|
||||
public static void RegisterCoreViewModels(this IServiceCollection services)
|
||||
{
|
||||
services.AddTransient(typeof(SettingsDialogViewModel));
|
||||
services.AddTransient(typeof(PersonalizationPageViewModel));
|
||||
services.AddTransient(typeof(SettingOptionsPageViewModel));
|
||||
services.AddTransient(typeof(AboutPageViewModel));
|
||||
services.AddTransient(typeof(SettingsPageViewModel));
|
||||
services.AddTransient(typeof(ManageAccountsPagePageViewModel));
|
||||
services.AddTransient(typeof(KeyboardShortcutsPageViewModel));
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.AccountCreationDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Wino.Core.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:dialogs="using:Wino.Dialogs"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Closing="DialogClosing"
|
||||
CornerRadius="8"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<!-- ContentDialogs do not support VSM. -->
|
||||
|
||||
<controls:AccountCreationDialogControl
|
||||
VerticalAlignment="Center"
|
||||
CancelClicked="CancelClicked"
|
||||
State="{x:Bind State, Mode=OneWay}" />
|
||||
|
||||
</ContentDialog>
|
||||
@@ -1,70 +0,0 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Dialogs;
|
||||
|
||||
public sealed partial class AccountCreationDialog : ContentDialog, IAccountCreationDialog
|
||||
{
|
||||
private TaskCompletionSource<bool> dialogOpened = new TaskCompletionSource<bool>();
|
||||
public CancellationTokenSource CancellationTokenSource { get; private set; }
|
||||
|
||||
public AccountCreationDialogState State
|
||||
{
|
||||
get { return (AccountCreationDialogState)GetValue(StateProperty); }
|
||||
set { SetValue(StateProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty StateProperty = DependencyProperty.Register(nameof(State), typeof(AccountCreationDialogState), typeof(AccountCreationDialog), new PropertyMetadata(AccountCreationDialogState.Idle));
|
||||
|
||||
public AccountCreationDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
// Prevent users from dismissing it by ESC key.
|
||||
public void DialogClosing(ContentDialog sender, ContentDialogClosingEventArgs args)
|
||||
{
|
||||
if (args.Result == ContentDialogResult.None)
|
||||
{
|
||||
args.Cancel = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Complete(bool cancel)
|
||||
{
|
||||
State = cancel ? AccountCreationDialogState.Canceled : AccountCreationDialogState.Completed;
|
||||
|
||||
// Unregister from closing event.
|
||||
Closing -= DialogClosing;
|
||||
|
||||
if (cancel && !CancellationTokenSource.IsCancellationRequested)
|
||||
{
|
||||
CancellationTokenSource.Cancel();
|
||||
}
|
||||
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void CancelClicked(object sender, System.EventArgs e) => Complete(true);
|
||||
|
||||
public async Task ShowDialogAsync(CancellationTokenSource cancellationTokenSource)
|
||||
{
|
||||
CancellationTokenSource = cancellationTokenSource;
|
||||
|
||||
Opened += DialogOpened;
|
||||
_ = ShowAsync();
|
||||
|
||||
await dialogOpened.Task;
|
||||
}
|
||||
|
||||
private void DialogOpened(ContentDialog sender, ContentDialogOpenedEventArgs args)
|
||||
{
|
||||
Opened -= DialogOpened;
|
||||
|
||||
dialogOpened?.SetResult(true);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.AccountPickerDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Title="{x:Bind domain:Translator.AccountPickerDialog_Title}"
|
||||
PrimaryButtonText="{x:Bind domain:Translator.Buttons_Cancel}"
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<ListView
|
||||
DisplayMemberPath="Address"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="AccountClicked"
|
||||
ItemsSource="{x:Bind AvailableAccounts}"
|
||||
SelectionMode="None" />
|
||||
</ContentDialog>
|
||||
@@ -1,26 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
|
||||
namespace Wino.Dialogs;
|
||||
|
||||
public sealed partial class AccountPickerDialog : ContentDialog
|
||||
{
|
||||
public MailAccount PickedAccount { get; set; }
|
||||
|
||||
public List<MailAccount> AvailableAccounts { get; set; }
|
||||
|
||||
public AccountPickerDialog(List<MailAccount> availableAccounts)
|
||||
{
|
||||
AvailableAccounts = availableAccounts;
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void AccountClicked(object sender, ItemClickEventArgs e)
|
||||
{
|
||||
PickedAccount = e.ClickedItem as MailAccount;
|
||||
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Dialogs;
|
||||
|
||||
public partial class CustomMessageDialogInformationContainer : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
public partial bool IsDontAskChecked { get; set; }
|
||||
|
||||
public CustomMessageDialogInformationContainer(string title, string description, WinoCustomMessageDialogIcon icon, bool isDontAskAgainEnabled)
|
||||
{
|
||||
Title = title;
|
||||
Description = description;
|
||||
Icon = icon;
|
||||
IsDontAskAgainEnabled = isDontAskAgainEnabled;
|
||||
}
|
||||
|
||||
public string Title { get; }
|
||||
public string Description { get; }
|
||||
public WinoCustomMessageDialogIcon Icon { get; }
|
||||
public bool IsDontAskAgainEnabled { get; }
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.CustomThemeBuilderDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:local="using:Wino.Dialogs"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
Title="{x:Bind domain:Translator.CustomThemeBuilder_Title}"
|
||||
DefaultButton="Primary"
|
||||
FullSizeDesired="False"
|
||||
IsPrimaryButtonEnabled="False"
|
||||
PrimaryButtonClick="ApplyClicked"
|
||||
PrimaryButtonText="{x:Bind domain:Translator.Buttons_ApplyTheme}"
|
||||
SecondaryButtonText="{x:Bind domain:Translator.Buttons_Cancel}"
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<ContentDialog.Resources>
|
||||
<x:Double x:Key="ContentDialogMinWidth">600</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxWidth">900</x:Double>
|
||||
<x:Double x:Key="ContentDialogMinHeight">200</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxHeight">756</x:Double>
|
||||
</ContentDialog.Resources>
|
||||
|
||||
<StackPanel Spacing="6">
|
||||
<TextBlock x:Name="ErrorTextBlock" Foreground="Gold" />
|
||||
|
||||
<controls:SettingsCard Description="{x:Bind domain:Translator.CustomThemeBuilder_ThemeNameDescription}" Header="{x:Bind domain:Translator.CustomThemeBuilder_ThemeNameTitle}">
|
||||
<controls:SettingsCard.HeaderIcon>
|
||||
<PathIcon Data="F1 M 10 0.625 C 10 0.45573 10.061849 0.309246 10.185547 0.185547 C 10.309244 0.06185 10.455729 0 10.625 0 L 15.625 0 C 15.79427 0 15.940754 0.06185 16.064453 0.185547 C 16.18815 0.309246 16.25 0.45573 16.25 0.625 C 16.25 0.794271 16.18815 0.940756 16.064453 1.064453 C 15.940754 1.188152 15.79427 1.25 15.625 1.25 L 13.75 1.25 L 13.75 18.75 L 15.625 18.75 C 15.79427 18.75 15.940754 18.81185 16.064453 18.935547 C 16.18815 19.059244 16.25 19.205729 16.25 19.375 C 16.25 19.544271 16.18815 19.690756 16.064453 19.814453 C 15.940754 19.93815 15.79427 20 15.625 20 L 10.625 20 C 10.455729 20 10.309244 19.93815 10.185547 19.814453 C 10.061849 19.690756 10 19.544271 10 19.375 C 10 19.205729 10.061849 19.059244 10.185547 18.935547 C 10.309244 18.81185 10.455729 18.75 10.625 18.75 L 12.5 18.75 L 12.5 1.25 L 10.625 1.25 C 10.455729 1.25 10.309244 1.188152 10.185547 1.064453 C 10.061849 0.940756 10 0.794271 10 0.625 Z M 0 6.25 C 0 5.735678 0.097656 5.250651 0.292969 4.794922 C 0.488281 4.339193 0.756836 3.94043 1.098633 3.598633 C 1.44043 3.256836 1.837565 2.988281 2.290039 2.792969 C 2.742513 2.597656 3.229167 2.5 3.75 2.5 L 11.25 2.5 L 11.25 3.75 L 3.75 3.75 C 3.404948 3.75 3.081055 3.815105 2.77832 3.945312 C 2.475586 4.075521 2.210286 4.254558 1.982422 4.482422 C 1.754557 4.710287 1.575521 4.975587 1.445312 5.27832 C 1.315104 5.581056 1.25 5.904949 1.25 6.25 L 1.25 13.75 C 1.25 14.095053 1.315104 14.418945 1.445312 14.72168 C 1.575521 15.024414 1.754557 15.289714 1.982422 15.517578 C 2.210286 15.745443 2.475586 15.924479 2.77832 16.054688 C 3.081055 16.184896 3.404948 16.25 3.75 16.25 L 11.25 16.25 L 11.25 17.5 L 3.75 17.5 C 3.229167 17.5 2.742513 17.402344 2.290039 17.207031 C 1.837565 17.011719 1.44043 16.743164 1.098633 16.401367 C 0.756836 16.05957 0.488281 15.662436 0.292969 15.209961 C 0.097656 14.757487 0 14.270834 0 13.75 Z M 15 3.75 L 15 2.5 L 16.25 2.5 C 16.764322 2.5 17.249348 2.597656 17.705078 2.792969 C 18.160807 2.988281 18.55957 3.256836 18.901367 3.598633 C 19.243164 3.94043 19.511719 4.339193 19.707031 4.794922 C 19.902344 5.250651 20 5.735678 20 6.25 L 20 13.75 C 20 14.270834 19.902344 14.757487 19.707031 15.209961 C 19.511719 15.662436 19.243164 16.05957 18.901367 16.401367 C 18.55957 16.743164 18.160807 17.011719 17.705078 17.207031 C 17.249348 17.402344 16.764322 17.5 16.25 17.5 L 15 17.5 L 15 16.25 L 16.25 16.25 C 16.595051 16.25 16.918945 16.184896 17.22168 16.054688 C 17.524414 15.924479 17.789713 15.745443 18.017578 15.517578 C 18.245441 15.289714 18.424479 15.024414 18.554688 14.72168 C 18.684895 14.418945 18.75 14.095053 18.75 13.75 L 18.75 6.25 C 18.75 5.904949 18.684895 5.581056 18.554688 5.27832 C 18.424479 4.975587 18.245441 4.710287 18.017578 4.482422 C 17.789713 4.254558 17.524414 4.075521 17.22168 3.945312 C 16.918945 3.815105 16.595051 3.75 16.25 3.75 Z M 7.441406 5.361328 C 7.389323 5.250651 7.312825 5.162761 7.211914 5.097656 C 7.111002 5.032553 6.998697 5.000001 6.875 5 C 6.751302 5.000001 6.638997 5.032553 6.538086 5.097656 C 6.437174 5.162761 6.360677 5.250651 6.308594 5.361328 L 2.871094 12.861328 C 2.799479 13.017578 2.792969 13.177084 2.851562 13.339844 C 2.910156 13.502604 3.017578 13.619792 3.173828 13.691406 C 3.330078 13.763021 3.489583 13.769531 3.652344 13.710938 C 3.815104 13.652344 3.932292 13.544922 4.003906 13.388672 L 4.84375 11.5625 L 8.896484 11.5625 L 8.90625 11.5625 L 9.746094 13.388672 C 9.817708 13.544922 9.934896 13.652344 10.097656 13.710938 C 10.260416 13.769531 10.419922 13.763021 10.576172 13.691406 C 10.732422 13.619792 10.839844 13.502604 10.898438 13.339844 C 10.957031 13.177084 10.950521 13.017578 10.878906 12.861328 Z M 5.410156 10.3125 L 6.875 7.128906 L 8.339844 10.3125 Z " />
|
||||
</controls:SettingsCard.HeaderIcon>
|
||||
<controls:SettingsCard.Content>
|
||||
<TextBox x:Name="ThemeNameBox" />
|
||||
</controls:SettingsCard.Content>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard
|
||||
x:Name="CustomWallpaperCard"
|
||||
Description="{x:Bind domain:Translator.CustomThemeBuilder_WallpaperDescription}"
|
||||
Header="{x:Bind domain:Translator.CustomThemeBuilder_WallpaperTitle}">
|
||||
<controls:SettingsCard.HeaderIcon>
|
||||
<PathIcon Data="F1 M 4.921875 16.25 C 4.433594 16.25 3.966471 16.150717 3.520508 15.952148 C 3.074544 15.753581 2.683919 15.486654 2.348633 15.151367 C 2.013346 14.816081 1.746419 14.425456 1.547852 13.979492 C 1.349284 13.533529 1.25 13.066406 1.25 12.578125 L 1.25 4.921875 C 1.25 4.433594 1.349284 3.966473 1.547852 3.520508 C 1.746419 3.074545 2.013346 2.68392 2.348633 2.348633 C 2.683919 2.013348 3.074544 1.74642 3.520508 1.547852 C 3.966471 1.349285 4.433594 1.25 4.921875 1.25 L 12.578125 1.25 C 13.066406 1.25 13.533528 1.349285 13.979492 1.547852 C 14.425455 1.74642 14.81608 2.013348 15.151367 2.348633 C 15.486653 2.68392 15.75358 3.074545 15.952148 3.520508 C 16.150715 3.966473 16.25 4.433594 16.25 4.921875 L 16.25 12.578125 C 16.25 13.066406 16.150715 13.533529 15.952148 13.979492 C 15.75358 14.425456 15.486653 14.816081 15.151367 15.151367 C 14.81608 15.486654 14.425455 15.753581 13.979492 15.952148 C 13.533528 16.150717 13.066406 16.25 12.578125 16.25 Z M 8.75 8.90625 C 9.082031 8.90625 9.401041 8.969727 9.707031 9.09668 C 10.013021 9.223633 10.283203 9.404297 10.517578 9.638672 L 14.658203 13.769531 C 14.768879 13.580729 14.853515 13.377279 14.912109 13.15918 C 14.970702 12.941081 14.999999 12.721354 15 12.5 L 15 4.951172 C 14.999999 4.625651 14.933268 4.314779 14.799805 4.018555 C 14.666341 3.722332 14.487305 3.461914 14.262695 3.237305 C 14.038086 3.012695 13.777669 2.83366 13.481445 2.700195 C 13.185221 2.566732 12.874348 2.5 12.548828 2.5 L 4.951172 2.5 C 4.625651 2.5 4.314778 2.566732 4.018555 2.700195 C 3.722331 2.83366 3.461914 3.012695 3.237305 3.237305 C 3.012695 3.461914 2.833659 3.722332 2.700195 4.018555 C 2.566732 4.314779 2.5 4.625651 2.5 4.951172 L 2.5 12.5 C 2.5 12.721354 2.529297 12.941081 2.587891 13.15918 C 2.646484 13.377279 2.73112 13.580729 2.841797 13.769531 L 6.982422 9.638672 C 7.216797 9.404297 7.486979 9.223633 7.792969 9.09668 C 8.098958 8.969727 8.417969 8.90625 8.75 8.90625 Z M 10.625 5.625 C 10.625 5.449219 10.657552 5.286459 10.722656 5.136719 C 10.78776 4.98698 10.877278 4.855145 10.991211 4.741211 C 11.105143 4.627279 11.236979 4.537761 11.386719 4.472656 C 11.536458 4.407553 11.699219 4.375 11.875 4.375 C 12.04427 4.375 12.205402 4.407553 12.358398 4.472656 C 12.511393 4.537761 12.644856 4.627279 12.758789 4.741211 C 12.872721 4.855145 12.962239 4.988607 13.027344 5.141602 C 13.092447 5.294597 13.124999 5.455729 13.125 5.625 C 13.124999 5.800781 13.092447 5.963542 13.027344 6.113281 C 12.962239 6.263021 12.872721 6.394857 12.758789 6.508789 C 12.644856 6.622722 12.513021 6.71224 12.363281 6.777344 C 12.213541 6.842449 12.050781 6.875001 11.875 6.875 C 11.699219 6.875001 11.53483 6.842449 11.381836 6.777344 C 11.228841 6.71224 11.097005 6.62435 10.986328 6.513672 C 10.87565 6.402996 10.78776 6.27116 10.722656 6.118164 C 10.657552 5.96517 10.625 5.800781 10.625 5.625 Z M 7.5 18.75 C 6.966146 18.75 6.455078 18.642578 5.966797 18.427734 C 5.478516 18.212891 5.058594 17.903646 4.707031 17.5 L 13.193359 17.5 C 13.785807 17.5 14.344075 17.382812 14.868164 17.148438 C 15.392252 16.914062 15.849609 16.59668 16.240234 16.196289 C 16.630859 15.795898 16.938477 15.332031 17.163086 14.804688 C 17.387695 14.277344 17.5 13.717448 17.5 13.125 L 17.5 4.707031 C 17.903645 5.058595 18.212891 5.478517 18.427734 5.966797 C 18.642578 6.455079 18.75 6.966146 18.75 7.5 L 18.75 13.125 C 18.75 13.89974 18.601887 14.628906 18.305664 15.3125 C 18.009439 15.996094 17.607422 16.591797 17.099609 17.099609 C 16.591797 17.607422 15.996094 18.009439 15.3125 18.305664 C 14.628906 18.601889 13.899739 18.75 13.125 18.75 Z M 12.5 15 C 12.721354 15 12.94108 14.970703 13.15918 14.912109 C 13.377278 14.853516 13.580729 14.768881 13.769531 14.658203 L 9.638672 10.517578 C 9.391275 10.270183 9.095052 10.146484 8.75 10.146484 C 8.404947 10.146484 8.108724 10.270183 7.861328 10.517578 L 3.730469 14.658203 C 3.919271 14.768881 4.122721 14.853516 4.34082 14.912109 C 4.558919 14.970703 4.778646 15 5 15 Z " />
|
||||
</controls:SettingsCard.HeaderIcon>
|
||||
<controls:SettingsCard.Content>
|
||||
<Button Click="BrowseWallpaperClicked" Content="{x:Bind domain:Translator.Buttons_Browse}" />
|
||||
</controls:SettingsCard.Content>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard Description="{x:Bind domain:Translator.CustomThemeBuilder_AccentColorDescription}" Header="{x:Bind domain:Translator.CustomThemeBuilder_AccentColorTitle}">
|
||||
<controls:SettingsCard.HeaderIcon>
|
||||
<PathIcon Data="F1 M 4.921875 16.25 C 4.433594 16.25 3.966471 16.150717 3.520508 15.952148 C 3.074544 15.753581 2.683919 15.486654 2.348633 15.151367 C 2.013346 14.816081 1.746419 14.425456 1.547852 13.979492 C 1.349284 13.533529 1.25 13.066406 1.25 12.578125 L 1.25 4.921875 C 1.25 4.433594 1.349284 3.966473 1.547852 3.520508 C 1.746419 3.074545 2.013346 2.68392 2.348633 2.348633 C 2.683919 2.013348 3.074544 1.74642 3.520508 1.547852 C 3.966471 1.349285 4.433594 1.25 4.921875 1.25 L 12.578125 1.25 C 13.066406 1.25 13.533528 1.349285 13.979492 1.547852 C 14.425455 1.74642 14.81608 2.013348 15.151367 2.348633 C 15.486653 2.68392 15.75358 3.074545 15.952148 3.520508 C 16.150715 3.966473 16.25 4.433594 16.25 4.921875 L 16.25 12.578125 C 16.25 13.066406 16.150715 13.533529 15.952148 13.979492 C 15.75358 14.425456 15.486653 14.816081 15.151367 15.151367 C 14.81608 15.486654 14.425455 15.753581 13.979492 15.952148 C 13.533528 16.150717 13.066406 16.25 12.578125 16.25 Z M 8.75 8.90625 C 9.082031 8.90625 9.401041 8.969727 9.707031 9.09668 C 10.013021 9.223633 10.283203 9.404297 10.517578 9.638672 L 14.658203 13.769531 C 14.768879 13.580729 14.853515 13.377279 14.912109 13.15918 C 14.970702 12.941081 14.999999 12.721354 15 12.5 L 15 4.951172 C 14.999999 4.625651 14.933268 4.314779 14.799805 4.018555 C 14.666341 3.722332 14.487305 3.461914 14.262695 3.237305 C 14.038086 3.012695 13.777669 2.83366 13.481445 2.700195 C 13.185221 2.566732 12.874348 2.5 12.548828 2.5 L 4.951172 2.5 C 4.625651 2.5 4.314778 2.566732 4.018555 2.700195 C 3.722331 2.83366 3.461914 3.012695 3.237305 3.237305 C 3.012695 3.461914 2.833659 3.722332 2.700195 4.018555 C 2.566732 4.314779 2.5 4.625651 2.5 4.951172 L 2.5 12.5 C 2.5 12.721354 2.529297 12.941081 2.587891 13.15918 C 2.646484 13.377279 2.73112 13.580729 2.841797 13.769531 L 6.982422 9.638672 C 7.216797 9.404297 7.486979 9.223633 7.792969 9.09668 C 8.098958 8.969727 8.417969 8.90625 8.75 8.90625 Z M 10.625 5.625 C 10.625 5.449219 10.657552 5.286459 10.722656 5.136719 C 10.78776 4.98698 10.877278 4.855145 10.991211 4.741211 C 11.105143 4.627279 11.236979 4.537761 11.386719 4.472656 C 11.536458 4.407553 11.699219 4.375 11.875 4.375 C 12.04427 4.375 12.205402 4.407553 12.358398 4.472656 C 12.511393 4.537761 12.644856 4.627279 12.758789 4.741211 C 12.872721 4.855145 12.962239 4.988607 13.027344 5.141602 C 13.092447 5.294597 13.124999 5.455729 13.125 5.625 C 13.124999 5.800781 13.092447 5.963542 13.027344 6.113281 C 12.962239 6.263021 12.872721 6.394857 12.758789 6.508789 C 12.644856 6.622722 12.513021 6.71224 12.363281 6.777344 C 12.213541 6.842449 12.050781 6.875001 11.875 6.875 C 11.699219 6.875001 11.53483 6.842449 11.381836 6.777344 C 11.228841 6.71224 11.097005 6.62435 10.986328 6.513672 C 10.87565 6.402996 10.78776 6.27116 10.722656 6.118164 C 10.657552 5.96517 10.625 5.800781 10.625 5.625 Z M 7.5 18.75 C 6.966146 18.75 6.455078 18.642578 5.966797 18.427734 C 5.478516 18.212891 5.058594 17.903646 4.707031 17.5 L 13.193359 17.5 C 13.785807 17.5 14.344075 17.382812 14.868164 17.148438 C 15.392252 16.914062 15.849609 16.59668 16.240234 16.196289 C 16.630859 15.795898 16.938477 15.332031 17.163086 14.804688 C 17.387695 14.277344 17.5 13.717448 17.5 13.125 L 17.5 4.707031 C 17.903645 5.058595 18.212891 5.478517 18.427734 5.966797 C 18.642578 6.455079 18.75 6.966146 18.75 7.5 L 18.75 13.125 C 18.75 13.89974 18.601887 14.628906 18.305664 15.3125 C 18.009439 15.996094 17.607422 16.591797 17.099609 17.099609 C 16.591797 17.607422 15.996094 18.009439 15.3125 18.305664 C 14.628906 18.601889 13.899739 18.75 13.125 18.75 Z M 12.5 15 C 12.721354 15 12.94108 14.970703 13.15918 14.912109 C 13.377278 14.853516 13.580729 14.768881 13.769531 14.658203 L 9.638672 10.517578 C 9.391275 10.270183 9.095052 10.146484 8.75 10.146484 C 8.404947 10.146484 8.108724 10.270183 7.861328 10.517578 L 3.730469 14.658203 C 3.919271 14.768881 4.122721 14.853516 4.34082 14.912109 C 4.558919 14.970703 4.778646 15 5 15 Z " />
|
||||
</controls:SettingsCard.HeaderIcon>
|
||||
<controls:SettingsCard.Content>
|
||||
<Button>
|
||||
<Button.Content>
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<TextBlock Text="{x:Bind domain:Translator.CustomThemeBuilder_PickColor}" />
|
||||
|
||||
<Grid
|
||||
x:Name="PreviewAccentColorGrid"
|
||||
Width="20"
|
||||
Height="20"
|
||||
Background="{ThemeResource SystemAccentColor}" />
|
||||
</StackPanel>
|
||||
</Button.Content>
|
||||
<Button.Flyout>
|
||||
<Flyout Placement="Bottom">
|
||||
<muxc:ColorPicker
|
||||
ColorChanged="PickerColorChanged"
|
||||
ColorSpectrumShape="Box"
|
||||
IsAlphaEnabled="False"
|
||||
IsAlphaSliderVisible="False"
|
||||
IsAlphaTextInputVisible="False"
|
||||
IsColorChannelTextInputVisible="False"
|
||||
IsHexInputVisible="False" />
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</controls:SettingsCard.Content>
|
||||
</controls:SettingsCard>
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
@@ -1,64 +0,0 @@
|
||||
using System;
|
||||
using CommunityToolkit.WinUI.Helpers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.WinUI;
|
||||
|
||||
namespace Wino.Dialogs;
|
||||
|
||||
public sealed partial class CustomThemeBuilderDialog : ContentDialog
|
||||
{
|
||||
public byte[] WallpaperData { get; private set; }
|
||||
public string AccentColor { get; private set; }
|
||||
|
||||
private INewThemeService _themeService;
|
||||
|
||||
public CustomThemeBuilderDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_themeService = WinoApplication.Current.Services.GetService<INewThemeService>();
|
||||
}
|
||||
|
||||
private async void ApplyClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
if (Array.Empty<byte>() == WallpaperData)
|
||||
return;
|
||||
|
||||
var deferal = args.GetDeferral();
|
||||
|
||||
try
|
||||
{
|
||||
await _themeService.CreateNewCustomThemeAsync(ThemeNameBox.Text, AccentColor, WallpaperData);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
ErrorTextBlock.Text = exception.Message;
|
||||
}
|
||||
finally
|
||||
{
|
||||
deferal.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
private async void BrowseWallpaperClicked(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
var dialogService = WinoApplication.Current.Services.GetService<IMailDialogService>();
|
||||
|
||||
var pickedFileData = await dialogService.PickWindowsFileContentAsync(".jpg", ".png");
|
||||
|
||||
if (pickedFileData == Array.Empty<byte>()) return;
|
||||
|
||||
IsPrimaryButtonEnabled = true;
|
||||
|
||||
WallpaperData = pickedFileData;
|
||||
}
|
||||
|
||||
private void PickerColorChanged(Microsoft.UI.Xaml.Controls.ColorPicker sender, Microsoft.UI.Xaml.Controls.ColorChangedEventArgs args)
|
||||
{
|
||||
PreviewAccentColorGrid.Background = new SolidColorBrush(args.NewColor);
|
||||
AccentColor = args.NewColor.ToHex();
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Core.WinUI.Dialogs.NewAccountDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:accounts="using:Wino.Core.Domain.Models.Accounts"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:helpers="using:Wino.Helpers"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
Title="{x:Bind domain:Translator.NewAccountDialog_Title}"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
DefaultButton="Primary"
|
||||
IsPrimaryButtonEnabled="False"
|
||||
Opened="DialogOpened"
|
||||
PrimaryButtonClick="CreateClicked"
|
||||
PrimaryButtonText="{x:Bind domain:Translator.Buttons_CreateAccount}"
|
||||
SecondaryButtonClick="CancelClicked"
|
||||
SecondaryButtonText="{x:Bind domain:Translator.Buttons_Cancel}"
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<ContentDialog.Resources>
|
||||
<DataTemplate x:Key="NewMailProviderTemplate" x:DataType="accounts:ProviderDetail">
|
||||
<Grid Margin="0,8" Padding="6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image
|
||||
Width="35"
|
||||
Height="35"
|
||||
Source="{x:Bind ProviderImage}" />
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
Margin="12,0"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="2">
|
||||
<TextBlock FontWeight="Bold" Text="{x:Bind Name}" />
|
||||
<TextBlock Text="{x:Bind Description}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ContentDialog.Resources>
|
||||
|
||||
<Grid MinWidth="400" RowSpacing="12">
|
||||
<Grid Visibility="{x:Bind IsProviderSelectionVisible, Mode=OneWay}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Account Name -->
|
||||
|
||||
<Grid ColumnSpacing="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox
|
||||
x:Name="AccountNameTextbox"
|
||||
Header="{x:Bind domain:Translator.NewAccountDialog_AccountName}"
|
||||
PlaceholderText="{x:Bind domain:Translator.NewAccountDialog_AccountNamePlaceholder}"
|
||||
TextChanged="InputChanged" />
|
||||
|
||||
<Button Grid.Column="1" VerticalAlignment="Bottom">
|
||||
<Grid>
|
||||
<Ellipse
|
||||
x:Name="SelectedColorEllipse"
|
||||
Width="16"
|
||||
Height="16" />
|
||||
|
||||
<TextBlock x:Name="PickColorTextblock" Text="{x:Bind domain:Translator.CalendarDisplayOptions_Color}" />
|
||||
</Grid>
|
||||
|
||||
<Button.Flyout>
|
||||
<Flyout Placement="TopEdgeAlignedLeft">
|
||||
<GridView
|
||||
Width="150"
|
||||
ItemTemplate="{StaticResource AccountColorTemplate}"
|
||||
ItemsSource="{x:Bind AvailableColors, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind SelectedColor, Mode=TwoWay}" />
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
|
||||
</Grid>
|
||||
|
||||
|
||||
<ListView
|
||||
Grid.Row="2"
|
||||
Margin="0,12"
|
||||
Padding="0"
|
||||
ItemTemplate="{StaticResource NewMailProviderTemplate}"
|
||||
ItemsSource="{x:Bind Providers}"
|
||||
SelectedItem="{x:Bind SelectedMailProvider, Mode=TwoWay}"
|
||||
SelectionMode="Single" />
|
||||
</Grid>
|
||||
|
||||
<!-- Known special IMAP login details. -->
|
||||
<Grid RowSpacing="12" Visibility="{x:Bind IsSpecialImapServerPartVisible, Mode=OneWay}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Button Click="BackClicked">
|
||||
<Button.Content>
|
||||
<Viewbox Width="16">
|
||||
<PathIcon Data="F1 M 20 9.375 C 20 9.544271 19.93815 9.690756 19.814453 9.814453 C 19.690754 9.938151 19.54427 10 19.375 10 L 2.138672 10 L 9.814453 17.685547 C 9.93815 17.809244 10 17.955729 10 18.125 C 10 18.294271 9.93815 18.440756 9.814453 18.564453 C 9.690755 18.68815 9.544271 18.75 9.375 18.75 C 9.205729 18.75 9.059244 18.68815 8.935547 18.564453 L 0.214844 9.84375 C 0.143229 9.772136 0.089518 9.700521 0.053711 9.628906 C 0.017904 9.557292 0 9.472656 0 9.375 C 0 9.277344 0.017904 9.192709 0.053711 9.121094 C 0.089518 9.049479 0.143229 8.977865 0.214844 8.90625 L 8.935547 0.185547 C 9.059244 0.06185 9.205729 0 9.375 0 C 9.544271 0 9.690755 0.06185 9.814453 0.185547 C 9.93815 0.309246 10 0.45573 10 0.625 C 10 0.794271 9.93815 0.940756 9.814453 1.064453 L 2.138672 8.75 L 19.375 8.75 C 19.54427 8.75 19.690754 8.81185 19.814453 8.935547 C 19.93815 9.059245 20 9.205729 20 9.375 Z " />
|
||||
</Viewbox>
|
||||
</Button.Content>
|
||||
</Button>
|
||||
|
||||
<Image
|
||||
Width="150"
|
||||
Height="50"
|
||||
HorizontalAlignment="Center"
|
||||
Source="{x:Bind SelectedMailProvider.ProviderImage, Mode=OneWay}" />
|
||||
|
||||
<TextBox
|
||||
x:Name="DisplayNameTextBox"
|
||||
Grid.Row="1"
|
||||
Header="Display Name"
|
||||
PlaceholderText="eg. John Doe"
|
||||
TextChanged="InputChanged" />
|
||||
|
||||
<TextBox
|
||||
x:Name="SpecialImapAddress"
|
||||
Grid.Row="2"
|
||||
Header="E-mail Address"
|
||||
PlaceholderText="eg. johndoe@testmail.com"
|
||||
TextChanged="InputChanged" />
|
||||
|
||||
<PasswordBox
|
||||
x:Name="AppSpecificPassword"
|
||||
Grid.Row="3"
|
||||
Header="App-Specific Password"
|
||||
PasswordChanged="ImapPasswordChanged" />
|
||||
|
||||
<HyperlinkButton
|
||||
Grid.Row="4"
|
||||
HorizontalAlignment="Right"
|
||||
Click="AppSpecificHelpButtonClicked"
|
||||
Content="How do I get app-specific password?" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ContentDialog>
|
||||
@@ -1,180 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Windows.System;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Accounts;
|
||||
using Wino.Core.ViewModels.Data;
|
||||
using Wino.Helpers;
|
||||
|
||||
namespace Wino.Core.WinUI.Dialogs;
|
||||
|
||||
public sealed partial class NewAccountDialog : ContentDialog
|
||||
{
|
||||
private Dictionary<SpecialImapProvider, string> helpingLinks = new Dictionary<SpecialImapProvider, string>()
|
||||
{
|
||||
{ SpecialImapProvider.iCloud, "https://support.apple.com/en-us/102654" },
|
||||
{ SpecialImapProvider.Yahoo, "http://help.yahoo.com/kb/SLN15241.html" },
|
||||
};
|
||||
|
||||
public static readonly DependencyProperty IsProviderSelectionVisibleProperty = DependencyProperty.Register(nameof(IsProviderSelectionVisible), typeof(bool), typeof(NewAccountDialog), new PropertyMetadata(true));
|
||||
public static readonly DependencyProperty IsSpecialImapServerPartVisibleProperty = DependencyProperty.Register(nameof(IsSpecialImapServerPartVisible), typeof(bool), typeof(NewAccountDialog), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty SelectedMailProviderProperty = DependencyProperty.Register(nameof(SelectedMailProvider), typeof(ProviderDetail), typeof(NewAccountDialog), new PropertyMetadata(null, new PropertyChangedCallback(OnSelectedProviderChanged)));
|
||||
public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register(nameof(SelectedColor), typeof(AppColorViewModel), typeof(NewAccountDialog), new PropertyMetadata(null, new PropertyChangedCallback(OnSelectedColorChanged)));
|
||||
|
||||
|
||||
public AppColorViewModel SelectedColor
|
||||
{
|
||||
get { return (AppColorViewModel)GetValue(SelectedColorProperty); }
|
||||
set { SetValue(SelectedColorProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets current selected mail provider in the dialog.
|
||||
/// </summary>
|
||||
public ProviderDetail SelectedMailProvider
|
||||
{
|
||||
get { return (ProviderDetail)GetValue(SelectedMailProviderProperty); }
|
||||
set { SetValue(SelectedMailProviderProperty, value); }
|
||||
}
|
||||
|
||||
|
||||
public bool IsProviderSelectionVisible
|
||||
{
|
||||
get { return (bool)GetValue(IsProviderSelectionVisibleProperty); }
|
||||
set { SetValue(IsProviderSelectionVisibleProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsSpecialImapServerPartVisible
|
||||
{
|
||||
get { return (bool)GetValue(IsSpecialImapServerPartVisibleProperty); }
|
||||
set { SetValue(IsSpecialImapServerPartVisibleProperty, value); }
|
||||
}
|
||||
|
||||
// List of available mail providers for now.
|
||||
|
||||
public List<IProviderDetail> Providers { get; set; }
|
||||
|
||||
public List<AppColorViewModel> AvailableColors { get; set; }
|
||||
|
||||
|
||||
public AccountCreationDialogResult Result = null;
|
||||
|
||||
public NewAccountDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
var themeService = WinoApplication.Current.NewThemeService.GetAvailableAccountColors();
|
||||
AvailableColors = themeService.Select(a => new AppColorViewModel(a)).ToList();
|
||||
|
||||
UpdateSelectedColor();
|
||||
}
|
||||
|
||||
private static void OnSelectedProviderChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is NewAccountDialog dialog)
|
||||
dialog.Validate();
|
||||
}
|
||||
|
||||
private static void OnSelectedColorChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is NewAccountDialog dialog)
|
||||
dialog.UpdateSelectedColor();
|
||||
}
|
||||
|
||||
private void UpdateSelectedColor()
|
||||
{
|
||||
PickColorTextblock.Visibility = SelectedColor == null ? Visibility.Visible : Visibility.Collapsed;
|
||||
SelectedColorEllipse.Fill = SelectedColor == null ? null : XamlHelpers.GetSolidColorBrushFromHex(SelectedColor.Hex);
|
||||
}
|
||||
|
||||
|
||||
private void CancelClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void CreateClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
if (IsSpecialImapServerPartVisible)
|
||||
{
|
||||
// Special imap detail input.
|
||||
|
||||
var details = new SpecialImapProviderDetails(SpecialImapAddress.Text.Trim(), AppSpecificPassword.Password.Trim(), DisplayNameTextBox.Text.Trim(), SelectedMailProvider.SpecialImapProvider);
|
||||
Result = new AccountCreationDialogResult(SelectedMailProvider.Type, AccountNameTextbox.Text.Trim(), details, SelectedColor?.Hex ?? string.Empty);
|
||||
Hide();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Validate();
|
||||
|
||||
if (IsSecondaryButtonEnabled)
|
||||
{
|
||||
if (SelectedMailProvider.SpecialImapProvider != SpecialImapProvider.None)
|
||||
{
|
||||
// This step requires app-sepcific password login for some providers.
|
||||
args.Cancel = true;
|
||||
|
||||
IsProviderSelectionVisible = false;
|
||||
IsSpecialImapServerPartVisible = true;
|
||||
|
||||
Validate();
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = new AccountCreationDialogResult(SelectedMailProvider.Type, AccountNameTextbox.Text.Trim(), null, SelectedColor?.Hex ?? string.Empty);
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InputChanged(object sender, TextChangedEventArgs e) => Validate();
|
||||
private void SenderNameChanged(object sender, TextChangedEventArgs e) => Validate();
|
||||
|
||||
private void Validate()
|
||||
{
|
||||
ValidateCreateButton();
|
||||
ValidateNames();
|
||||
}
|
||||
|
||||
// Returns whether we can create account or not.
|
||||
private void ValidateCreateButton()
|
||||
{
|
||||
bool shouldEnable = SelectedMailProvider != null
|
||||
&& SelectedMailProvider.IsSupported
|
||||
&& !string.IsNullOrEmpty(AccountNameTextbox.Text)
|
||||
&& (IsSpecialImapServerPartVisible ? (!string.IsNullOrEmpty(AppSpecificPassword.Password)
|
||||
&& !string.IsNullOrEmpty(DisplayNameTextBox.Text)
|
||||
&& EmailValidation.EmailValidator.Validate(SpecialImapAddress.Text)) : true);
|
||||
|
||||
IsPrimaryButtonEnabled = shouldEnable;
|
||||
}
|
||||
|
||||
private void ValidateNames()
|
||||
{
|
||||
AccountNameTextbox.IsEnabled = SelectedMailProvider != null;
|
||||
}
|
||||
|
||||
private void DialogOpened(ContentDialog sender, ContentDialogOpenedEventArgs args) => Validate();
|
||||
|
||||
private void BackClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
IsSpecialImapServerPartVisible = false;
|
||||
IsProviderSelectionVisible = true;
|
||||
|
||||
Validate();
|
||||
}
|
||||
|
||||
private void ImapPasswordChanged(object sender, RoutedEventArgs e) => Validate();
|
||||
|
||||
private async void AppSpecificHelpButtonClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var helpUrl = helpingLinks[SelectedMailProvider.SpecialImapProvider];
|
||||
|
||||
await Launcher.LaunchUriAsync(new Uri(helpUrl));
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Core.WinUI.Dialogs.PrintDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:printing="using:Wino.Core.Domain.Models.Printing"
|
||||
Title="Print Settings"
|
||||
MinWidth="400"
|
||||
MinHeight="300"
|
||||
DefaultButton="Primary"
|
||||
Loaded="PrintDialog_Loaded"
|
||||
PrimaryButtonClick="ContentDialog_PrimaryButtonClick"
|
||||
PrimaryButtonText="Print"
|
||||
SecondaryButtonClick="ContentDialog_SecondaryButtonClick"
|
||||
SecondaryButtonText="Cancel"
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<StackPanel Margin="20" Spacing="16">
|
||||
|
||||
<!-- Printer Selection -->
|
||||
<ComboBox
|
||||
x:Name="PrinterComboBox"
|
||||
HorizontalAlignment="Stretch"
|
||||
Header="Printer"
|
||||
SelectedItem="{x:Bind PrintSettings.PrinterName, Mode=TwoWay}"
|
||||
SelectionChanged="PrinterComboBox_SelectionChanged" />
|
||||
|
||||
<!-- Copies -->
|
||||
<NumberBox
|
||||
Header="Copies"
|
||||
Maximum="999"
|
||||
Minimum="1"
|
||||
SpinButtonPlacementMode="Inline"
|
||||
Value="{x:Bind PrintSettings.Copies, Mode=TwoWay}" />
|
||||
|
||||
<!-- Orientation -->
|
||||
<RadioButtons
|
||||
x:Name="OrientationRadioButtons"
|
||||
Header="Orientation"
|
||||
SelectionChanged="OrientationRadio_SelectionChanged">
|
||||
<RadioButton Content="Portrait" />
|
||||
<RadioButton Content="Landscape" />
|
||||
</RadioButtons>
|
||||
|
||||
<!-- Print Options -->
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="Options" />
|
||||
<CheckBox Content="Print backgrounds" IsChecked="{x:Bind PrintSettings.ShouldPrintBackgrounds, Mode=TwoWay}" />
|
||||
<CheckBox Content="Print headers and footers" IsChecked="{x:Bind PrintSettings.ShouldPrintHeaderAndFooter, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
@@ -1,178 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Printing;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Serilog;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.Printing;
|
||||
|
||||
namespace Wino.Core.WinUI.Dialogs;
|
||||
|
||||
/// <summary>
|
||||
/// Custom print dialog for configuring WebView2 print settings.
|
||||
/// </summary>
|
||||
public sealed partial class PrintDialog : ContentDialog
|
||||
{
|
||||
public WebView2PrintSettingsModel PrintSettings { get; set; } = new WebView2PrintSettingsModel();
|
||||
|
||||
public PrintDialog()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the dialog with existing print settings.
|
||||
/// </summary>
|
||||
/// <param name="printSettings">The initial print settings to load.</param>
|
||||
public PrintDialog(WebView2PrintSettingsModel printSettings = null)
|
||||
{
|
||||
if (printSettings != null) PrintSettings = printSettings;
|
||||
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void PrintDialog_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) => LoadSettingsToUI(PrintSettings);
|
||||
|
||||
private void OrientationRadio_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is RadioButtons radioButtons)
|
||||
{
|
||||
PrintSettings.Orientation = (PrintOrientation)radioButtons.SelectedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
private void PrinterComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is ComboBox comboBox && comboBox.SelectedItem != null)
|
||||
{
|
||||
PrintSettings.PrinterName = comboBox.SelectedItem.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the list of available printers for the dialog.
|
||||
/// </summary>
|
||||
/// <param name="printers">List of available printer names.</param>
|
||||
public void SetAvailablePrinters(IEnumerable<string> printers)
|
||||
{
|
||||
var printerList = printers?.ToList() ?? new List<string>();
|
||||
|
||||
if (this.FindName("PrinterComboBox") is ComboBox printerComboBox)
|
||||
{
|
||||
printerComboBox.ItemsSource = printerList;
|
||||
|
||||
if (printerList.Any())
|
||||
{
|
||||
// Set to first printer or to the one in settings
|
||||
var targetPrinter = !string.IsNullOrEmpty(PrintSettings.PrinterName)
|
||||
? PrintSettings.PrinterName
|
||||
: printerList.First();
|
||||
|
||||
var index = printerList.IndexOf(targetPrinter);
|
||||
printerComboBox.SelectedIndex = index >= 0 ? index : 0;
|
||||
|
||||
// Update the settings model with the selected printer
|
||||
PrintSettings.PrinterName = printerComboBox.SelectedItem?.ToString() ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads available printers asynchronously and sets them in the dialog.
|
||||
/// </summary>
|
||||
public async Task LoadAvailablePrintersAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var printers = await Task.Run(() =>
|
||||
{
|
||||
var printerList = new List<string>();
|
||||
|
||||
// Get all installed printers using System.Drawing.Printing
|
||||
foreach (string printerName in PrinterSettings.InstalledPrinters)
|
||||
{
|
||||
printerList.Add(printerName);
|
||||
}
|
||||
|
||||
return printerList.AsEnumerable();
|
||||
});
|
||||
|
||||
SetAvailablePrinters(printers);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
// Log the exception if logging is available
|
||||
Log.Error(ex, "Error getting available printers");
|
||||
|
||||
// Set empty list if printer discovery fails
|
||||
SetAvailablePrinters(Enumerable.Empty<string>());
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadSettingsToUI(WebView2PrintSettingsModel settings)
|
||||
{
|
||||
if (settings == null) return;
|
||||
|
||||
// Only handle orientation manually since other properties are bound via x:Bind
|
||||
if (this.FindName("OrientationRadioButtons") is RadioButtons orientationRadio)
|
||||
{
|
||||
orientationRadio.SelectedIndex = (int)settings.Orientation;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSettingsFromUI()
|
||||
{
|
||||
// Most properties are bound via x:Bind, only handle orientation manually
|
||||
if (this.FindName("OrientationRadioButtons") is RadioButtons orientationRadio)
|
||||
{
|
||||
PrintSettings.Orientation = (PrintOrientation)orientationRadio.SelectedIndex;
|
||||
}
|
||||
|
||||
// Also update printer name from ComboBox since it uses ItemsSource binding
|
||||
if (this.FindName("PrinterComboBox") is ComboBox printerComboBox &&
|
||||
printerComboBox.SelectedItem != null)
|
||||
{
|
||||
PrintSettings.PrinterName = printerComboBox.SelectedItem.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the current print settings before closing the dialog.
|
||||
/// </summary>
|
||||
/// <returns>True if settings are valid, false otherwise.</returns>
|
||||
private bool ValidateSettings()
|
||||
{
|
||||
// Check if a printer is selected
|
||||
if (this.FindName("PrinterComboBox") is ComboBox printerComboBox &&
|
||||
printerComboBox.SelectedItem == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copies validation is handled by the bound property with validation in the model
|
||||
if (PrintSettings.Copies <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
// Update settings from UI before validation
|
||||
UpdateSettingsFromUI();
|
||||
|
||||
// Validate settings before closing
|
||||
if (!ValidateSettings())
|
||||
{
|
||||
args.Cancel = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
// Cancel was clicked, no validation needed
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.TextInputDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonClick="UpdateOrCreateClicked"
|
||||
SecondaryButtonClick="CancelClicked"
|
||||
SecondaryButtonText="{x:Bind domain:Translator.Buttons_Cancel}"
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<ContentDialog.Resources>
|
||||
<x:Double x:Key="ContentDialogMinWidth">400</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxWidth">400</x:Double>
|
||||
<x:Double x:Key="ContentDialogMinHeight">200</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxHeight">756</x:Double>
|
||||
</ContentDialog.Resources>
|
||||
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock x:Name="DialogDescription" TextWrapping="Wrap" />
|
||||
<TextBox x:Name="FolderTextBox" Text="{x:Bind CurrentInput, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
@@ -1,44 +0,0 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Wino.Dialogs;
|
||||
|
||||
public sealed partial class TextInputDialog : ContentDialog
|
||||
{
|
||||
public bool? HasInput { get; set; }
|
||||
|
||||
public string CurrentInput
|
||||
{
|
||||
get { return (string)GetValue(CurrentInputProperty); }
|
||||
set { SetValue(CurrentInputProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty CurrentInputProperty = DependencyProperty.Register(nameof(CurrentInput), typeof(string), typeof(TextInputDialog), new PropertyMetadata(string.Empty));
|
||||
|
||||
public TextInputDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void SetDescription(string description)
|
||||
{
|
||||
DialogDescription.Text = description;
|
||||
}
|
||||
|
||||
public void SetPrimaryButtonText(string text)
|
||||
{
|
||||
PrimaryButtonText = text;
|
||||
}
|
||||
|
||||
private void CancelClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void UpdateOrCreateClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
HasInput = true;
|
||||
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.WinUI;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Core.WinUI;
|
||||
|
||||
public class WinUIDispatcher : IDispatcher
|
||||
{
|
||||
private readonly DispatcherQueue _coreDispatcher;
|
||||
|
||||
public WinUIDispatcher(DispatcherQueue coreDispatcher)
|
||||
{
|
||||
_coreDispatcher = coreDispatcher;
|
||||
}
|
||||
|
||||
public Task ExecuteOnUIThread(Action action) => _coreDispatcher.EnqueueAsync(action, DispatcherQueuePriority.Normal);
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI.Composition;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
|
||||
namespace Wino.Extensions;
|
||||
|
||||
public static class AnimationExtensions
|
||||
{
|
||||
#region Composition
|
||||
|
||||
public static ScalarKeyFrameAnimation CreateScalarKeyFrameAnimation(this Compositor compositor, float? from, float to,
|
||||
double duration, double delay, CompositionEasingFunction easing, AnimationIterationBehavior iterationBehavior)
|
||||
{
|
||||
var animation = compositor.CreateScalarKeyFrameAnimation();
|
||||
|
||||
animation.Duration = TimeSpan.FromMilliseconds(duration);
|
||||
if (!delay.Equals(0)) animation.DelayTime = TimeSpan.FromMilliseconds(delay);
|
||||
if (from.HasValue) animation.InsertKeyFrame(0.0f, from.Value, easing);
|
||||
animation.InsertKeyFrame(1.0f, to, easing);
|
||||
animation.IterationBehavior = iterationBehavior;
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
||||
public static Vector2KeyFrameAnimation CreateVector2KeyFrameAnimation(this Compositor compositor, Vector2? from, Vector2 to,
|
||||
double duration, double delay, CompositionEasingFunction easing, AnimationIterationBehavior iterationBehavior)
|
||||
{
|
||||
var animation = compositor.CreateVector2KeyFrameAnimation();
|
||||
|
||||
animation.Duration = TimeSpan.FromMilliseconds(duration);
|
||||
animation.DelayTime = TimeSpan.FromMilliseconds(delay);
|
||||
if (from.HasValue) animation.InsertKeyFrame(0.0f, from.Value, easing);
|
||||
animation.InsertKeyFrame(1.0f, to, easing);
|
||||
animation.IterationBehavior = iterationBehavior;
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
||||
public static Vector3KeyFrameAnimation CreateVector3KeyFrameAnimation(this Compositor compositor, Vector2? from, Vector2 to,
|
||||
double duration, double delay, CompositionEasingFunction easing, AnimationIterationBehavior iterationBehavior)
|
||||
{
|
||||
var animation = compositor.CreateVector3KeyFrameAnimation();
|
||||
|
||||
animation.Duration = TimeSpan.FromMilliseconds(duration);
|
||||
animation.DelayTime = TimeSpan.FromMilliseconds(delay);
|
||||
if (from.HasValue) animation.InsertKeyFrame(0.0f, new Vector3(from.Value, 1.0f), easing);
|
||||
animation.InsertKeyFrame(1.0f, new Vector3(to, 1.0f), easing);
|
||||
animation.IterationBehavior = iterationBehavior;
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
||||
public static Vector3KeyFrameAnimation CreateVector3KeyFrameAnimation(this Compositor compositor, Vector3? from, Vector3 to,
|
||||
double duration, double delay, CompositionEasingFunction easing, AnimationIterationBehavior iterationBehavior)
|
||||
{
|
||||
var animation = compositor.CreateVector3KeyFrameAnimation();
|
||||
|
||||
animation.Duration = TimeSpan.FromMilliseconds(duration);
|
||||
animation.DelayTime = TimeSpan.FromMilliseconds(delay);
|
||||
if (from.HasValue) animation.InsertKeyFrame(0.0f, from.Value, easing);
|
||||
animation.InsertKeyFrame(1.0f, to, easing);
|
||||
animation.IterationBehavior = iterationBehavior;
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Xaml Storyboard
|
||||
|
||||
public static void Animate(this DependencyObject target, double? from, double to,
|
||||
string propertyPath, int duration = 400, int startTime = 0,
|
||||
EasingFunctionBase easing = null, Action completed = null, bool enableDependentAnimation = false)
|
||||
{
|
||||
if (easing == null)
|
||||
{
|
||||
easing = new ExponentialEase();
|
||||
}
|
||||
|
||||
var db = new DoubleAnimation
|
||||
{
|
||||
EnableDependentAnimation = enableDependentAnimation,
|
||||
To = to,
|
||||
From = from,
|
||||
EasingFunction = easing,
|
||||
Duration = TimeSpan.FromMilliseconds(duration)
|
||||
};
|
||||
Storyboard.SetTarget(db, target);
|
||||
Storyboard.SetTargetProperty(db, propertyPath);
|
||||
|
||||
var sb = new Storyboard
|
||||
{
|
||||
BeginTime = TimeSpan.FromMilliseconds(startTime)
|
||||
};
|
||||
|
||||
if (completed != null)
|
||||
{
|
||||
sb.Completed += (s, e) =>
|
||||
{
|
||||
completed();
|
||||
};
|
||||
}
|
||||
|
||||
sb.Children.Add(db);
|
||||
sb.Begin();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wino.Extensions;
|
||||
|
||||
public enum TransitionDirection
|
||||
{
|
||||
TopToBottom,
|
||||
BottomToTop,
|
||||
LeftToRight,
|
||||
RightToLeft
|
||||
}
|
||||
|
||||
public enum ClipAnimationDirection
|
||||
{
|
||||
Top,
|
||||
Bottom,
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
|
||||
public enum AnimationAxis
|
||||
{
|
||||
X,
|
||||
Y,
|
||||
Z
|
||||
}
|
||||
|
||||
public enum AnimationType
|
||||
{
|
||||
KeyFrame,
|
||||
Expression
|
||||
}
|
||||
|
||||
public enum FlickDirection
|
||||
{
|
||||
None,
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
|
||||
public enum ViewState
|
||||
{
|
||||
Empty,
|
||||
Small,
|
||||
Big,
|
||||
Full
|
||||
}
|
||||
|
||||
public enum Gesture
|
||||
{
|
||||
Initial,
|
||||
Tap,
|
||||
Swipe
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum VisualPropertyType
|
||||
{
|
||||
None = 0,
|
||||
Opacity = 1 << 0,
|
||||
Offset = 1 << 1,
|
||||
Scale = 1 << 2,
|
||||
Size = 1 << 3,
|
||||
RotationAngleInDegrees = 1 << 4,
|
||||
All = ~0
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Microsoft.UI.Composition;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Hosting;
|
||||
|
||||
namespace Wino.Extensions;
|
||||
|
||||
public static partial class CompositionExtensions
|
||||
{
|
||||
public static void EnableFluidVisibilityAnimation(this UIElement element, AnimationAxis? axis = null,
|
||||
float showFromOffset = 0.0f, float hideToOffset = 0.0f, Vector3? centerPoint = null,
|
||||
float showFromScale = 1.0f, float hideToScale = 1.0f, float showDuration = 800.0f, float hideDuration = 800.0f,
|
||||
int showDelay = 0, int hideDelay = 0, bool animateOpacity = true)
|
||||
{
|
||||
var elementVisual = element.Visual();
|
||||
var compositor = elementVisual.Compositor;
|
||||
ElementCompositionPreview.SetIsTranslationEnabled(element, true);
|
||||
|
||||
ScalarKeyFrameAnimation hideOpacityAnimation = null;
|
||||
ScalarKeyFrameAnimation showOpacityAnimation = null;
|
||||
ScalarKeyFrameAnimation hideOffsetAnimation = null;
|
||||
ScalarKeyFrameAnimation showOffsetAnimation = null;
|
||||
Vector2KeyFrameAnimation hideScaleAnimation = null;
|
||||
Vector2KeyFrameAnimation showeScaleAnimation = null;
|
||||
|
||||
if (animateOpacity)
|
||||
{
|
||||
hideOpacityAnimation = compositor.CreateScalarKeyFrameAnimation();
|
||||
hideOpacityAnimation.InsertKeyFrame(1.0f, 0.0f);
|
||||
hideOpacityAnimation.Duration = TimeSpan.FromMilliseconds(hideDuration);
|
||||
hideOpacityAnimation.DelayTime = TimeSpan.FromMilliseconds(hideDelay);
|
||||
hideOpacityAnimation.Target = "Opacity";
|
||||
}
|
||||
|
||||
if (!hideToOffset.Equals(0.0f))
|
||||
{
|
||||
hideOffsetAnimation = compositor.CreateScalarKeyFrameAnimation();
|
||||
hideOffsetAnimation.InsertKeyFrame(1.0f, hideToOffset);
|
||||
hideOffsetAnimation.Duration = TimeSpan.FromMilliseconds(hideDuration);
|
||||
hideOffsetAnimation.DelayTime = TimeSpan.FromMilliseconds(hideDelay);
|
||||
hideOffsetAnimation.Target = $"Translation.{axis}";
|
||||
}
|
||||
|
||||
if (centerPoint.HasValue)
|
||||
{
|
||||
elementVisual.CenterPoint = centerPoint.Value;
|
||||
}
|
||||
|
||||
if (!hideToScale.Equals(1.0f))
|
||||
{
|
||||
hideScaleAnimation = compositor.CreateVector2KeyFrameAnimation();
|
||||
hideScaleAnimation.InsertKeyFrame(1.0f, new Vector2(hideToScale));
|
||||
hideScaleAnimation.Duration = TimeSpan.FromMilliseconds(hideDuration);
|
||||
hideScaleAnimation.DelayTime = TimeSpan.FromMilliseconds(hideDelay);
|
||||
hideScaleAnimation.Target = "Scale.XY";
|
||||
}
|
||||
|
||||
var hideAnimationGroup = compositor.CreateAnimationGroup();
|
||||
if (hideOpacityAnimation != null)
|
||||
{
|
||||
hideAnimationGroup.Add(hideOpacityAnimation);
|
||||
}
|
||||
if (hideOffsetAnimation != null)
|
||||
{
|
||||
hideAnimationGroup.Add(hideOffsetAnimation);
|
||||
}
|
||||
if (hideScaleAnimation != null)
|
||||
{
|
||||
hideAnimationGroup.Add(hideScaleAnimation);
|
||||
}
|
||||
|
||||
ElementCompositionPreview.SetImplicitHideAnimation(element, hideAnimationGroup);
|
||||
|
||||
if (animateOpacity)
|
||||
{
|
||||
showOpacityAnimation = compositor.CreateScalarKeyFrameAnimation();
|
||||
showOpacityAnimation.InsertKeyFrame(1.0f, 1.0f);
|
||||
showOpacityAnimation.Duration = TimeSpan.FromMilliseconds(showDuration);
|
||||
showOpacityAnimation.DelayTime = TimeSpan.FromMilliseconds(showDelay);
|
||||
showOpacityAnimation.Target = "Opacity";
|
||||
}
|
||||
|
||||
if (!showFromOffset.Equals(0.0f))
|
||||
{
|
||||
showOffsetAnimation = compositor.CreateScalarKeyFrameAnimation();
|
||||
showOffsetAnimation.InsertKeyFrame(0.0f, showFromOffset);
|
||||
showOffsetAnimation.InsertKeyFrame(1.0f, 0.0f);
|
||||
showOffsetAnimation.Duration = TimeSpan.FromMilliseconds(showDuration);
|
||||
showOffsetAnimation.DelayTime = TimeSpan.FromMilliseconds(showDelay);
|
||||
showOffsetAnimation.Target = $"Translation.{axis}";
|
||||
}
|
||||
|
||||
if (!showFromScale.Equals(1.0f))
|
||||
{
|
||||
showeScaleAnimation = compositor.CreateVector2KeyFrameAnimation();
|
||||
showeScaleAnimation.InsertKeyFrame(0.0f, new Vector2(showFromScale));
|
||||
showeScaleAnimation.InsertKeyFrame(1.0f, Vector2.One);
|
||||
showeScaleAnimation.Duration = TimeSpan.FromMilliseconds(showDuration);
|
||||
showeScaleAnimation.DelayTime = TimeSpan.FromMilliseconds(showDelay);
|
||||
showeScaleAnimation.Target = "Scale.XY";
|
||||
}
|
||||
|
||||
var showAnimationGroup = compositor.CreateAnimationGroup();
|
||||
if (showOpacityAnimation != null)
|
||||
{
|
||||
showAnimationGroup.Add(showOpacityAnimation);
|
||||
}
|
||||
if (showOffsetAnimation != null)
|
||||
{
|
||||
showAnimationGroup.Add(showOffsetAnimation);
|
||||
}
|
||||
if (showeScaleAnimation != null)
|
||||
{
|
||||
showAnimationGroup.Add(showeScaleAnimation);
|
||||
}
|
||||
|
||||
ElementCompositionPreview.SetImplicitShowAnimation(element, showAnimationGroup);
|
||||
}
|
||||
|
||||
public static void EnableImplicitAnimation(this UIElement element, VisualPropertyType typeToAnimate,
|
||||
double duration = 800, double delay = 0, CompositionEasingFunction easing = null)
|
||||
{
|
||||
var visual = element.Visual();
|
||||
var compositor = visual.Compositor;
|
||||
|
||||
var animationCollection = compositor.CreateImplicitAnimationCollection();
|
||||
|
||||
foreach (var type in UtilExtensions.GetValues<VisualPropertyType>())
|
||||
{
|
||||
if (!typeToAnimate.HasFlag(type)) continue;
|
||||
|
||||
var animation = CreateAnimationByType(compositor, type, duration, delay, easing);
|
||||
|
||||
if (animation != null)
|
||||
{
|
||||
animationCollection[type.ToString()] = animation;
|
||||
}
|
||||
}
|
||||
|
||||
visual.ImplicitAnimations = animationCollection;
|
||||
}
|
||||
|
||||
public static void EnableImplicitAnimation(this Visual visual, VisualPropertyType typeToAnimate,
|
||||
double duration = 800, double delay = 0, CompositionEasingFunction easing = null)
|
||||
{
|
||||
var compositor = visual.Compositor;
|
||||
|
||||
var animationCollection = compositor.CreateImplicitAnimationCollection();
|
||||
|
||||
foreach (var type in UtilExtensions.GetValues<VisualPropertyType>())
|
||||
{
|
||||
if (!typeToAnimate.HasFlag(type)) continue;
|
||||
|
||||
var animation = CreateAnimationByType(compositor, type, duration, delay, easing);
|
||||
|
||||
if (animation != null)
|
||||
{
|
||||
animationCollection[type.ToString()] = animation;
|
||||
}
|
||||
}
|
||||
|
||||
visual.ImplicitAnimations = animationCollection;
|
||||
}
|
||||
|
||||
private static KeyFrameAnimation CreateAnimationByType(Compositor compositor, VisualPropertyType type,
|
||||
double duration = 800, double delay = 0, CompositionEasingFunction easing = null)
|
||||
{
|
||||
KeyFrameAnimation animation;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case VisualPropertyType.Offset:
|
||||
case VisualPropertyType.Scale:
|
||||
animation = compositor.CreateVector3KeyFrameAnimation();
|
||||
break;
|
||||
case VisualPropertyType.Size:
|
||||
animation = compositor.CreateVector2KeyFrameAnimation();
|
||||
break;
|
||||
case VisualPropertyType.Opacity:
|
||||
case VisualPropertyType.RotationAngleInDegrees:
|
||||
animation = compositor.CreateScalarKeyFrameAnimation();
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
animation.InsertExpressionKeyFrame(1.0f, "this.FinalValue", easing);
|
||||
animation.Duration = TimeSpan.FromMilliseconds(duration);
|
||||
animation.DelayTime = TimeSpan.FromMilliseconds(delay);
|
||||
animation.Target = type.ToString();
|
||||
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.WinUI.Extensions;
|
||||
|
||||
public static class ElementThemeExtensions
|
||||
{
|
||||
public static ApplicationElementTheme ToWinoElementTheme(this ElementTheme elementTheme)
|
||||
{
|
||||
switch (elementTheme)
|
||||
{
|
||||
case ElementTheme.Light:
|
||||
return ApplicationElementTheme.Light;
|
||||
case ElementTheme.Dark:
|
||||
return ApplicationElementTheme.Dark;
|
||||
}
|
||||
|
||||
return ApplicationElementTheme.Default;
|
||||
}
|
||||
|
||||
public static ElementTheme ToWindowsElementTheme(this ApplicationElementTheme elementTheme)
|
||||
{
|
||||
switch (elementTheme)
|
||||
{
|
||||
case ApplicationElementTheme.Light:
|
||||
return ElementTheme.Light;
|
||||
case ApplicationElementTheme.Dark:
|
||||
return ElementTheme.Dark;
|
||||
}
|
||||
|
||||
return ElementTheme.Default;
|
||||
}
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.Printing;
|
||||
|
||||
namespace Wino.Core.WinUI.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods and utilities for converting between Domain print models and CoreWebView2 print settings.
|
||||
/// </summary>
|
||||
public static class PrintSettingsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a Domain PrintOrientation to CoreWebView2PrintOrientation.
|
||||
/// </summary>
|
||||
public static CoreWebView2PrintOrientation ToCoreWebView2Orientation(this PrintOrientation orientation)
|
||||
{
|
||||
return orientation switch
|
||||
{
|
||||
PrintOrientation.Portrait => CoreWebView2PrintOrientation.Portrait,
|
||||
PrintOrientation.Landscape => CoreWebView2PrintOrientation.Landscape,
|
||||
_ => CoreWebView2PrintOrientation.Portrait
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a CoreWebView2PrintOrientation to Domain PrintOrientation.
|
||||
/// </summary>
|
||||
public static PrintOrientation ToDomainOrientation(this CoreWebView2PrintOrientation orientation)
|
||||
{
|
||||
return orientation switch
|
||||
{
|
||||
CoreWebView2PrintOrientation.Portrait => PrintOrientation.Portrait,
|
||||
CoreWebView2PrintOrientation.Landscape => PrintOrientation.Landscape,
|
||||
_ => PrintOrientation.Portrait
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Domain PrintColorMode to CoreWebView2PrintColorMode.
|
||||
/// </summary>
|
||||
public static CoreWebView2PrintColorMode ToCoreWebView2ColorMode(this PrintColorMode colorMode)
|
||||
{
|
||||
return colorMode switch
|
||||
{
|
||||
PrintColorMode.Default => CoreWebView2PrintColorMode.Default,
|
||||
PrintColorMode.Color => CoreWebView2PrintColorMode.Color,
|
||||
PrintColorMode.Grayscale => CoreWebView2PrintColorMode.Grayscale,
|
||||
_ => CoreWebView2PrintColorMode.Default
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a CoreWebView2PrintColorMode to Domain PrintColorMode.
|
||||
/// </summary>
|
||||
public static PrintColorMode ToDomainColorMode(this CoreWebView2PrintColorMode colorMode)
|
||||
{
|
||||
return colorMode switch
|
||||
{
|
||||
CoreWebView2PrintColorMode.Default => PrintColorMode.Default,
|
||||
CoreWebView2PrintColorMode.Color => PrintColorMode.Color,
|
||||
CoreWebView2PrintColorMode.Grayscale => PrintColorMode.Grayscale,
|
||||
_ => PrintColorMode.Default
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Domain PrintCollation to CoreWebView2PrintCollation.
|
||||
/// </summary>
|
||||
public static CoreWebView2PrintCollation ToCoreWebView2Collation(this PrintCollation collation)
|
||||
{
|
||||
return collation switch
|
||||
{
|
||||
PrintCollation.Default => CoreWebView2PrintCollation.Default,
|
||||
PrintCollation.Collated => CoreWebView2PrintCollation.Collated,
|
||||
PrintCollation.Uncollated => CoreWebView2PrintCollation.Uncollated,
|
||||
_ => CoreWebView2PrintCollation.Default
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a CoreWebView2PrintCollation to Domain PrintCollation.
|
||||
/// </summary>
|
||||
public static PrintCollation ToDomainCollation(this CoreWebView2PrintCollation collation)
|
||||
{
|
||||
return collation switch
|
||||
{
|
||||
CoreWebView2PrintCollation.Default => PrintCollation.Default,
|
||||
CoreWebView2PrintCollation.Collated => PrintCollation.Collated,
|
||||
CoreWebView2PrintCollation.Uncollated => PrintCollation.Uncollated,
|
||||
_ => PrintCollation.Default
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Domain PrintDuplex to CoreWebView2PrintDuplex.
|
||||
/// </summary>
|
||||
public static CoreWebView2PrintDuplex ToCoreWebView2Duplex(this PrintDuplex duplex)
|
||||
{
|
||||
// Note: Simplified mapping due to enum value differences
|
||||
return duplex switch
|
||||
{
|
||||
PrintDuplex.Default => CoreWebView2PrintDuplex.Default,
|
||||
_ => CoreWebView2PrintDuplex.Default
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a CoreWebView2PrintDuplex to Domain PrintDuplex.
|
||||
/// </summary>
|
||||
public static PrintDuplex ToDomainDuplex(this CoreWebView2PrintDuplex duplex)
|
||||
{
|
||||
// Note: Simplified mapping due to enum value differences
|
||||
return duplex switch
|
||||
{
|
||||
CoreWebView2PrintDuplex.Default => PrintDuplex.Default,
|
||||
_ => PrintDuplex.Default
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Domain PrintMediaSize to CoreWebView2PrintMediaSize.
|
||||
/// </summary>
|
||||
public static CoreWebView2PrintMediaSize ToCoreWebView2MediaSize(this PrintMediaSize mediaSize)
|
||||
{
|
||||
// Note: Simplified mapping due to enum value differences
|
||||
return mediaSize switch
|
||||
{
|
||||
PrintMediaSize.Default => CoreWebView2PrintMediaSize.Default,
|
||||
_ => CoreWebView2PrintMediaSize.Default
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a CoreWebView2PrintMediaSize to Domain PrintMediaSize.
|
||||
/// </summary>
|
||||
public static PrintMediaSize ToDomainMediaSize(this CoreWebView2PrintMediaSize mediaSize)
|
||||
{
|
||||
// Note: Simplified mapping due to enum value differences
|
||||
return mediaSize switch
|
||||
{
|
||||
CoreWebView2PrintMediaSize.Default => PrintMediaSize.Default,
|
||||
_ => PrintMediaSize.Default
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a CoreWebView2PrintSettings object from a WebView2PrintSettingsModel.
|
||||
/// </summary>
|
||||
/// <param name="model">The domain model containing the print settings.</param>
|
||||
/// <param name="environment">The CoreWebView2Environment to create the settings object.</param>
|
||||
/// <returns>A configured CoreWebView2PrintSettings object.</returns>
|
||||
public static CoreWebView2PrintSettings ToCoreWebView2PrintSettings(
|
||||
this WebView2PrintSettingsModel model,
|
||||
CoreWebView2Environment environment)
|
||||
{
|
||||
var settings = environment.CreatePrintSettings();
|
||||
|
||||
settings.PrinterName = model.PrinterName;
|
||||
settings.Orientation = model.Orientation.ToCoreWebView2Orientation();
|
||||
settings.ColorMode = model.ColorMode.ToCoreWebView2ColorMode();
|
||||
settings.Collation = model.Collation.ToCoreWebView2Collation();
|
||||
settings.Duplex = model.Duplex.ToCoreWebView2Duplex();
|
||||
settings.MediaSize = model.MediaSize.ToCoreWebView2MediaSize();
|
||||
settings.Copies = model.Copies;
|
||||
settings.MarginTop = model.MarginTop;
|
||||
settings.MarginBottom = model.MarginBottom;
|
||||
settings.MarginLeft = model.MarginLeft;
|
||||
settings.MarginRight = model.MarginRight;
|
||||
settings.ShouldPrintBackgrounds = model.ShouldPrintBackgrounds;
|
||||
settings.ShouldPrintSelectionOnly = model.ShouldPrintSelectionOnly;
|
||||
settings.ShouldPrintHeaderAndFooter = model.ShouldPrintHeaderAndFooter;
|
||||
settings.HeaderTitle = model.HeaderTitle;
|
||||
settings.FooterUri = model.FooterUri;
|
||||
settings.ScaleFactor = model.ScaleFactor;
|
||||
settings.PagesPerSide = model.PagesPerSide;
|
||||
settings.PageRanges = model.PageRanges;
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a WebView2PrintSettingsModel from a CoreWebView2PrintSettings object.
|
||||
/// </summary>
|
||||
/// <param name="model">The domain model to update.</param>
|
||||
/// <param name="settings">The source CoreWebView2PrintSettings.</param>
|
||||
public static void FromCoreWebView2PrintSettings(
|
||||
this WebView2PrintSettingsModel model,
|
||||
CoreWebView2PrintSettings settings)
|
||||
{
|
||||
if (settings == null) return;
|
||||
|
||||
model.PrinterName = settings.PrinterName ?? string.Empty;
|
||||
model.Orientation = settings.Orientation.ToDomainOrientation();
|
||||
model.ColorMode = settings.ColorMode.ToDomainColorMode();
|
||||
model.Collation = settings.Collation.ToDomainCollation();
|
||||
model.Duplex = settings.Duplex.ToDomainDuplex();
|
||||
model.MediaSize = settings.MediaSize.ToDomainMediaSize();
|
||||
model.Copies = settings.Copies;
|
||||
model.MarginTop = settings.MarginTop;
|
||||
model.MarginBottom = settings.MarginBottom;
|
||||
model.MarginLeft = settings.MarginLeft;
|
||||
model.MarginRight = settings.MarginRight;
|
||||
model.ShouldPrintBackgrounds = settings.ShouldPrintBackgrounds;
|
||||
model.ShouldPrintSelectionOnly = settings.ShouldPrintSelectionOnly;
|
||||
model.ShouldPrintHeaderAndFooter = settings.ShouldPrintHeaderAndFooter;
|
||||
model.HeaderTitle = settings.HeaderTitle ?? string.Empty;
|
||||
model.FooterUri = settings.FooterUri ?? string.Empty;
|
||||
model.ScaleFactor = settings.ScaleFactor;
|
||||
model.PagesPerSide = settings.PagesPerSide;
|
||||
model.PageRanges = settings.PageRanges ?? string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using Windows.ApplicationModel;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.WinUI.Extensions;
|
||||
|
||||
public static class StartupTaskStateExtensions
|
||||
{
|
||||
public static StartupBehaviorResult AsStartupBehaviorResult(this StartupTaskState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case StartupTaskState.Disabled:
|
||||
case StartupTaskState.DisabledByPolicy:
|
||||
return StartupBehaviorResult.Disabled;
|
||||
case StartupTaskState.DisabledByUser:
|
||||
return StartupBehaviorResult.DisabledByUser;
|
||||
case StartupTaskState.Enabled:
|
||||
case StartupTaskState.EnabledByPolicy:
|
||||
return StartupBehaviorResult.Enabled;
|
||||
default:
|
||||
return StartupBehaviorResult.Fatal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using Wino.Core.Domain.Models.Common;
|
||||
|
||||
namespace Wino.Core.WinUI.Extensions;
|
||||
|
||||
public static class StorageFileExtensions
|
||||
{
|
||||
public static async Task<SharedFile> ToSharedFileAsync(this Windows.Storage.StorageFile storageFile)
|
||||
{
|
||||
var content = await storageFile.ToByteArrayAsync();
|
||||
|
||||
return new SharedFile(storageFile.Path, content);
|
||||
}
|
||||
|
||||
public static async Task<byte[]> ToByteArrayAsync(this StorageFile file)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException(nameof(file));
|
||||
|
||||
using (var stream = await file.OpenReadAsync())
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
await stream.AsStreamForRead().CopyToAsync(memoryStream);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Extensions;
|
||||
|
||||
public static class UIExtensions
|
||||
{
|
||||
public static InfoBarSeverity AsMUXCInfoBarSeverity(this InfoBarMessageType messageType)
|
||||
{
|
||||
return messageType switch
|
||||
{
|
||||
InfoBarMessageType.Error => InfoBarSeverity.Error,
|
||||
InfoBarMessageType.Warning => InfoBarSeverity.Warning,
|
||||
InfoBarMessageType.Information => InfoBarSeverity.Informational,
|
||||
InfoBarMessageType.Success => InfoBarSeverity.Success,
|
||||
_ => InfoBarSeverity.Informational
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.UI.Composition;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Hosting;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Windows.Foundation;
|
||||
|
||||
namespace Wino.Extensions;
|
||||
|
||||
public static class UtilExtensions
|
||||
{
|
||||
public static float ToFloat(this double value) => (float)value;
|
||||
|
||||
public static List<FrameworkElement> Children(this DependencyObject parent)
|
||||
{
|
||||
var list = new List<FrameworkElement>();
|
||||
|
||||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(parent, i);
|
||||
|
||||
if (child is FrameworkElement)
|
||||
{
|
||||
list.Add(child as FrameworkElement);
|
||||
}
|
||||
|
||||
list.AddRange(Children(child));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static T GetChildByName<T>(this DependencyObject parent, string name)
|
||||
{
|
||||
var childControls = Children(parent);
|
||||
var controls = childControls.OfType<FrameworkElement>();
|
||||
|
||||
if (controls == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
|
||||
var control = controls
|
||||
.Where(x => x.Name.Equals(name))
|
||||
.Cast<T>()
|
||||
.First();
|
||||
|
||||
return control;
|
||||
}
|
||||
|
||||
public static Visual Visual(this UIElement element) =>
|
||||
ElementCompositionPreview.GetElementVisual(element);
|
||||
|
||||
public static void SetChildVisual(this UIElement element, Visual childVisual) =>
|
||||
ElementCompositionPreview.SetElementChildVisual(element, childVisual);
|
||||
|
||||
public static Point RelativePosition(this UIElement element, UIElement other) =>
|
||||
element.TransformToVisual(other).TransformPoint(new Point(0, 0));
|
||||
|
||||
public static bool IsFullyVisibile(this FrameworkElement element, FrameworkElement parent)
|
||||
{
|
||||
if (element == null || parent == null)
|
||||
return false;
|
||||
|
||||
if (element.Visibility != Visibility.Visible)
|
||||
return false;
|
||||
|
||||
var elementBounds = element.TransformToVisual(parent).TransformBounds(new Windows.Foundation.Rect(0, 0, element.ActualWidth, element.ActualHeight));
|
||||
var containerBounds = new Windows.Foundation.Rect(0, 0, parent.ActualWidth, parent.ActualHeight);
|
||||
|
||||
var originalElementWidth = elementBounds.Width;
|
||||
var originalElementHeight = elementBounds.Height;
|
||||
|
||||
elementBounds.Intersect(containerBounds);
|
||||
|
||||
var newElementWidth = elementBounds.Width;
|
||||
var newElementHeight = elementBounds.Height;
|
||||
|
||||
return originalElementWidth.Equals(newElementWidth) && originalElementHeight.Equals(newElementHeight);
|
||||
}
|
||||
|
||||
public static void ScrollToElement(this ScrollViewer scrollViewer, FrameworkElement element,
|
||||
bool isVerticalScrolling = true, bool smoothScrolling = true, float? zoomFactor = null, bool bringToTopOrLeft = true, bool addMargin = true)
|
||||
{
|
||||
if (!bringToTopOrLeft && element.IsFullyVisibile(scrollViewer))
|
||||
return;
|
||||
|
||||
var contentArea = (FrameworkElement)scrollViewer.Content;
|
||||
var position = element.RelativePosition(contentArea);
|
||||
|
||||
if (isVerticalScrolling)
|
||||
{
|
||||
// Accomodate for additional header.
|
||||
scrollViewer.ChangeView(null, Math.Max(0, position.Y - (addMargin ? 48 : 0)), zoomFactor, !smoothScrolling);
|
||||
}
|
||||
else
|
||||
{
|
||||
scrollViewer.ChangeView(position.X, null, zoomFactor, !smoothScrolling);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static T[] GetValues<T>() where T : struct, Enum => Enum.GetValues<T>();
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wino.Core.WinUI.Extensions;
|
||||
|
||||
public static class WebViewExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes a script function in the WebView2 control.
|
||||
/// </summary>
|
||||
/// <param name="isChromiumDisposed">Weird parameter that needed in mailRendering page. TODO: should be reconsidered.</param>
|
||||
/// <param name="parameters">Parameters should be serialized to json</param>
|
||||
public static async Task<string> ExecuteScriptFunctionAsync(this Microsoft.UI.Xaml.Controls.WebView2 Chromium, string functionName, bool isChromiumDisposed = false, params string[] parameters)
|
||||
{
|
||||
string script = functionName + "(" + string.Join(", ", parameters) + ");";
|
||||
|
||||
return isChromiumDisposed ? string.Empty : await Chromium.ExecuteScriptAsync(script);
|
||||
}
|
||||
|
||||
public static async Task<string> ExecuteScriptFunctionSafeAsync(this Microsoft.UI.Xaml.Controls.WebView2 Chromium, string functionName, params string[] parameters)
|
||||
{
|
||||
if (Chromium == null) return string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
return await Chromium.ExecuteScriptFunctionAsync(functionName, parameters: parameters);
|
||||
}
|
||||
catch { }
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public static async Task<string> ExecuteScriptSafeAsync(this Microsoft.UI.Xaml.Controls.WebView2 Chromium, string script)
|
||||
{
|
||||
if (Chromium == null) return string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
return await Chromium.ExecuteScriptAsync(script);
|
||||
}
|
||||
catch { }
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
|
||||
namespace Wino.Helpers;
|
||||
|
||||
public static class WinoVisualTreeHelper
|
||||
{
|
||||
public static T GetChildObject<T>(DependencyObject obj, string name) where T : FrameworkElement
|
||||
{
|
||||
DependencyObject child = null;
|
||||
T grandChild = null;
|
||||
|
||||
for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++)
|
||||
{
|
||||
child = VisualTreeHelper.GetChild(obj, i);
|
||||
|
||||
if (child is T && (((T)child).Name == name | string.IsNullOrEmpty(name)))
|
||||
{
|
||||
return (T)child;
|
||||
}
|
||||
else
|
||||
{
|
||||
grandChild = GetChildObject<T>(child, name);
|
||||
}
|
||||
if (grandChild != null)
|
||||
{
|
||||
return grandChild;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> FindDescendants<T>(this DependencyObject depObj) where T : DependencyObject
|
||||
{
|
||||
if (depObj != null)
|
||||
{
|
||||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(depObj, i);
|
||||
if (child != null && child is T)
|
||||
{
|
||||
yield return (T)child;
|
||||
}
|
||||
|
||||
foreach (T childOfChild in FindDescendants<T>(child))
|
||||
{
|
||||
yield return childOfChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,389 +0,0 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.WinUI.Helpers;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Text;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Text;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities.Mail;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.WinUI.Controls;
|
||||
|
||||
namespace Wino.Helpers;
|
||||
|
||||
public static class XamlHelpers
|
||||
{
|
||||
private const string TwentyFourHourTimeFormat = "HH:mm";
|
||||
private const string TwelveHourTimeFormat = "hh:mm tt";
|
||||
|
||||
#region Converters
|
||||
|
||||
public static Thickness GetMailItemControlMargin(bool isDisplayedInThread) => isDisplayedInThread ? new Thickness(40, 0, 6, 0) : new Thickness(6, 0, 6, 0);
|
||||
public static bool IsMultiple(int count) => count > 1;
|
||||
public static bool ReverseIsMultiple(int count) => count < 1;
|
||||
public static PopupPlacementMode GetPlaccementModeForCalendarType(CalendarDisplayType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
CalendarDisplayType.Week => PopupPlacementMode.Right,
|
||||
_ => PopupPlacementMode.Bottom,
|
||||
};
|
||||
}
|
||||
|
||||
public static Visibility ReverseBoolToVisibilityConverter(bool value) => value ? Visibility.Collapsed : Visibility.Visible;
|
||||
public static Visibility ReverseVisibilityConverter(Visibility visibility) => visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
|
||||
public static bool ReverseBoolConverter(bool value) => !value;
|
||||
public static bool ShouldDisplayPreview(string text) => text == null ? false : text.Any(x => char.IsLetter(x));
|
||||
public static bool CountToBooleanConverter(int value) => value > 0;
|
||||
public static bool ObjectEquals(object obj1, object obj2) => object.Equals(obj1, obj2);
|
||||
public static Visibility CountToVisibilityConverter(int value) => value > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||||
public static Visibility CountToVisibilityConverterWithThreshold(int value, int threshold) => value > threshold ? Visibility.Visible : Visibility.Collapsed;
|
||||
public static ListViewSelectionMode BoolToSelectionMode(bool isSelectionMode) => isSelectionMode ? ListViewSelectionMode.Multiple : ListViewSelectionMode.None;
|
||||
public static string BoolToSelectionModeText(bool isSelectionMode) => isSelectionMode ? Translator.Buttons_Cancel : Translator.Buttons_Multiselect;
|
||||
|
||||
public static Microsoft.UI.Xaml.Media.Imaging.BitmapImage Base64ToBitmapImage(string base64String)
|
||||
{
|
||||
if (string.IsNullOrEmpty(base64String))
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
var imageBytes = Convert.FromBase64String(base64String);
|
||||
using var stream = new System.IO.MemoryStream(imageBytes);
|
||||
var bitmap = new Microsoft.UI.Xaml.Media.Imaging.BitmapImage();
|
||||
bitmap.SetSource(stream.AsRandomAccessStream());
|
||||
return bitmap;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static InfoBarSeverity InfoBarSeverityConverter(InfoBarMessageType messageType)
|
||||
{
|
||||
return messageType switch
|
||||
{
|
||||
InfoBarMessageType.Information => InfoBarSeverity.Informational,
|
||||
InfoBarMessageType.Success => InfoBarSeverity.Success,
|
||||
InfoBarMessageType.Warning => InfoBarSeverity.Warning,
|
||||
InfoBarMessageType.Error => InfoBarSeverity.Error,
|
||||
_ => InfoBarSeverity.Informational,
|
||||
};
|
||||
}
|
||||
|
||||
public static SolidColorBrush GetReadableTextColor(string backgroundColor)
|
||||
{
|
||||
if (!backgroundColor.StartsWith("#")) throw new ArgumentException("Hex color must start with #.");
|
||||
|
||||
backgroundColor = backgroundColor.TrimStart('#');
|
||||
|
||||
if (backgroundColor.Length == 6)
|
||||
{
|
||||
var r = int.Parse(backgroundColor.Substring(0, 2), NumberStyles.HexNumber);
|
||||
var g = int.Parse(backgroundColor.Substring(2, 2), NumberStyles.HexNumber);
|
||||
var b = int.Parse(backgroundColor.Substring(4, 2), NumberStyles.HexNumber);
|
||||
|
||||
// Calculate relative luminance
|
||||
double luminance = (0.2126 * GetLinearValue(r)) +
|
||||
(0.7152 * GetLinearValue(g)) +
|
||||
(0.0722 * GetLinearValue(b));
|
||||
|
||||
return luminance > 0.5 ? new SolidColorBrush(Colors.Black) : new SolidColorBrush(Colors.White);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Hex color must be 6 characters long (e.g., #RRGGBB).");
|
||||
}
|
||||
}
|
||||
|
||||
private static double GetLinearValue(int colorComponent)
|
||||
{
|
||||
double sRGB = colorComponent / 255.0;
|
||||
return sRGB <= 0.03928 ? sRGB / 12.92 : Math.Pow((sRGB + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
public static Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode NavigationViewDisplayModeConverter(SplitViewDisplayMode splitViewDisplayMode)
|
||||
{
|
||||
return splitViewDisplayMode switch
|
||||
{
|
||||
SplitViewDisplayMode.CompactOverlay => Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode.Compact,
|
||||
SplitViewDisplayMode.CompactInline => Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode.Minimal,
|
||||
SplitViewDisplayMode.Overlay => Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode.Expanded,
|
||||
SplitViewDisplayMode.Inline => Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode.Expanded,
|
||||
_ => Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode.Minimal,
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetColorFromHex(Color color) => color.ToHex();
|
||||
public static Color GetWindowsColorFromHex(string hex) => hex.ToColor();
|
||||
|
||||
public static SolidColorBrush GetSolidColorBrushFromHex(string colorHex) => string.IsNullOrEmpty(colorHex) ? new SolidColorBrush(Colors.Transparent) : new SolidColorBrush(colorHex.ToColor());
|
||||
public static FontWeight GetFontWeightBySyncState(bool isSyncing) => isSyncing ? FontWeights.SemiBold : FontWeights.Normal;
|
||||
public static FontWeight GetFontWeightByChildSelectedState(bool isChildSelected) => isChildSelected ? FontWeights.SemiBold : FontWeights.Normal;
|
||||
public static FontWeight GetFontWeightByReadState(bool isChildSelected) => isChildSelected ? FontWeights.Normal : FontWeights.SemiBold;
|
||||
public static Visibility StringToVisibilityConverter(string value) => string.IsNullOrWhiteSpace(value) ? Visibility.Collapsed : Visibility.Visible;
|
||||
public static Visibility StringToVisibilityReversedConverter(string value) => string.IsNullOrWhiteSpace(value) ? Visibility.Visible : Visibility.Collapsed;
|
||||
public static string GetMailItemDisplaySummaryForListing(bool isDraft, DateTime receivedDate, bool prefer24HourTime)
|
||||
{
|
||||
if (isDraft)
|
||||
return Translator.Draft;
|
||||
else
|
||||
{
|
||||
var localTime = receivedDate.ToLocalTime();
|
||||
|
||||
return prefer24HourTime ? localTime.ToString(TwentyFourHourTimeFormat) : localTime.ToString(TwelveHourTimeFormat);
|
||||
}
|
||||
}
|
||||
public static string GetCreationDateString(DateTime date, bool prefer24HourTime)
|
||||
{
|
||||
var localTime = date.ToLocalTime();
|
||||
return $"{localTime.ToString("D", CultureInfo.DefaultThreadCurrentUICulture)} {(prefer24HourTime ? localTime.ToString(TwentyFourHourTimeFormat) : localTime.ToString(TwelveHourTimeFormat))}";
|
||||
}
|
||||
public static string GetMailGroupDateString(object groupObject)
|
||||
{
|
||||
if (groupObject is string stringObject)
|
||||
return stringObject;
|
||||
|
||||
object dateObject = null;
|
||||
|
||||
// From regular mail header template
|
||||
if (groupObject is DateTime groupedDate)
|
||||
dateObject = groupedDate;
|
||||
else if (groupObject is IGrouping<object, MailCopy> groupKey)
|
||||
{
|
||||
// From semantic group header.
|
||||
dateObject = groupKey.Key;
|
||||
}
|
||||
|
||||
if (dateObject != null)
|
||||
{
|
||||
if (dateObject is DateTime dateTimeValue)
|
||||
{
|
||||
if (dateTimeValue == DateTime.Today)
|
||||
return Translator.Today;
|
||||
else if (dateTimeValue == DateTime.Today.AddDays(-1))
|
||||
return Translator.Yesterday;
|
||||
else
|
||||
{
|
||||
return dateTimeValue.ToString("D", CultureInfo.DefaultThreadCurrentUICulture);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
return dateObject.ToString();
|
||||
}
|
||||
|
||||
return Translator.UnknownDateHeader;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Wino Font Icon Transformation
|
||||
|
||||
public static WinoIconGlyph GetWinoIconGlyph(FilterOptionType type) => type switch
|
||||
{
|
||||
FilterOptionType.All => WinoIconGlyph.Mail,
|
||||
FilterOptionType.Unread => WinoIconGlyph.MarkUnread,
|
||||
FilterOptionType.Flagged => WinoIconGlyph.Flag,
|
||||
FilterOptionType.Mentions => WinoIconGlyph.NewMail,
|
||||
FilterOptionType.Files => WinoIconGlyph.Attachment,
|
||||
_ => WinoIconGlyph.None,
|
||||
};
|
||||
|
||||
public static WinoIconGlyph GetWinoIconGlyph(SortingOptionType type) => type switch
|
||||
{
|
||||
SortingOptionType.Sender => WinoIconGlyph.SortTextDesc,
|
||||
SortingOptionType.ReceiveDate => WinoIconGlyph.SortLinesDesc,
|
||||
_ => WinoIconGlyph.None,
|
||||
};
|
||||
|
||||
public static WinoIconGlyph GetWinoIconGlyph(MailOperation operation)
|
||||
{
|
||||
return operation switch
|
||||
{
|
||||
MailOperation.None => WinoIconGlyph.None,
|
||||
MailOperation.Archive => WinoIconGlyph.Archive,
|
||||
MailOperation.UnArchive => WinoIconGlyph.UnArchive,
|
||||
MailOperation.SoftDelete => WinoIconGlyph.Delete,
|
||||
MailOperation.HardDelete => WinoIconGlyph.Delete,
|
||||
MailOperation.Move => WinoIconGlyph.Forward,
|
||||
MailOperation.MoveToJunk => WinoIconGlyph.Blocked,
|
||||
MailOperation.MoveToFocused => WinoIconGlyph.None,
|
||||
MailOperation.MoveToOther => WinoIconGlyph.None,
|
||||
MailOperation.AlwaysMoveToOther => WinoIconGlyph.None,
|
||||
MailOperation.AlwaysMoveToFocused => WinoIconGlyph.None,
|
||||
MailOperation.SetFlag => WinoIconGlyph.Flag,
|
||||
MailOperation.ClearFlag => WinoIconGlyph.ClearFlag,
|
||||
MailOperation.MarkAsRead => WinoIconGlyph.MarkRead,
|
||||
MailOperation.MarkAsUnread => WinoIconGlyph.MarkUnread,
|
||||
MailOperation.MarkAsNotJunk => WinoIconGlyph.Blocked,
|
||||
MailOperation.Ignore => WinoIconGlyph.Ignore,
|
||||
MailOperation.Reply => WinoIconGlyph.Reply,
|
||||
MailOperation.ReplyAll => WinoIconGlyph.ReplyAll,
|
||||
MailOperation.Zoom => WinoIconGlyph.Zoom,
|
||||
MailOperation.SaveAs => WinoIconGlyph.Save,
|
||||
MailOperation.Print => WinoIconGlyph.Print,
|
||||
MailOperation.Find => WinoIconGlyph.Find,
|
||||
MailOperation.Forward => WinoIconGlyph.Forward,
|
||||
MailOperation.DarkEditor => WinoIconGlyph.DarkEditor,
|
||||
MailOperation.LightEditor => WinoIconGlyph.LightEditor,
|
||||
MailOperation.ViewMessageSource => WinoIconGlyph.ViewMessageSource,
|
||||
_ => WinoIconGlyph.None,
|
||||
};
|
||||
}
|
||||
|
||||
public static WinoIconGlyph GetPathGeometry(FolderOperation operation)
|
||||
{
|
||||
return operation switch
|
||||
{
|
||||
FolderOperation.None => WinoIconGlyph.None,
|
||||
FolderOperation.Pin => WinoIconGlyph.Pin,
|
||||
FolderOperation.Unpin => WinoIconGlyph.UnPin,
|
||||
FolderOperation.MarkAllAsRead => WinoIconGlyph.MarkRead,
|
||||
FolderOperation.DontSync => WinoIconGlyph.DontSync,
|
||||
FolderOperation.Empty => WinoIconGlyph.EmptyFolder,
|
||||
FolderOperation.Rename => WinoIconGlyph.Rename,
|
||||
FolderOperation.Delete => WinoIconGlyph.Delete,
|
||||
FolderOperation.Move => WinoIconGlyph.Forward,
|
||||
FolderOperation.TurnOffNotifications => WinoIconGlyph.TurnOfNotifications,
|
||||
FolderOperation.CreateSubFolder => WinoIconGlyph.CreateFolder,
|
||||
_ => WinoIconGlyph.None,
|
||||
};
|
||||
}
|
||||
|
||||
public static WinoIconGlyph GetSpecialFolderPathIconGeometry(SpecialFolderType specialFolderType)
|
||||
{
|
||||
return specialFolderType switch
|
||||
{
|
||||
SpecialFolderType.Inbox => WinoIconGlyph.SpecialFolderInbox,
|
||||
SpecialFolderType.Starred => WinoIconGlyph.SpecialFolderStarred,
|
||||
SpecialFolderType.Important => WinoIconGlyph.SpecialFolderImportant,
|
||||
SpecialFolderType.Sent => WinoIconGlyph.SpecialFolderSent,
|
||||
SpecialFolderType.Draft => WinoIconGlyph.SpecialFolderDraft,
|
||||
SpecialFolderType.Archive => WinoIconGlyph.SpecialFolderArchive,
|
||||
SpecialFolderType.Deleted => WinoIconGlyph.SpecialFolderDeleted,
|
||||
SpecialFolderType.Junk => WinoIconGlyph.SpecialFolderJunk,
|
||||
SpecialFolderType.Chat => WinoIconGlyph.SpecialFolderChat,
|
||||
SpecialFolderType.Category => WinoIconGlyph.SpecialFolderCategory,
|
||||
SpecialFolderType.Unread => WinoIconGlyph.SpecialFolderUnread,
|
||||
SpecialFolderType.Forums => WinoIconGlyph.SpecialFolderForums,
|
||||
SpecialFolderType.Updates => WinoIconGlyph.SpecialFolderUpdated,
|
||||
SpecialFolderType.Personal => WinoIconGlyph.SpecialFolderPersonal,
|
||||
SpecialFolderType.Promotions => WinoIconGlyph.SpecialFolderPromotions,
|
||||
SpecialFolderType.Social => WinoIconGlyph.SpecialFolderSocial,
|
||||
SpecialFolderType.Other => WinoIconGlyph.SpecialFolderOther,
|
||||
SpecialFolderType.More => WinoIconGlyph.SpecialFolderMore,
|
||||
_ => WinoIconGlyph.None,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static WinoIconGlyph GetProviderIcon(MailProviderType providerType, SpecialImapProvider specialImapProvider)
|
||||
{
|
||||
if (specialImapProvider == SpecialImapProvider.None)
|
||||
{
|
||||
return providerType switch
|
||||
{
|
||||
MailProviderType.Outlook => WinoIconGlyph.Microsoft,
|
||||
MailProviderType.Gmail => WinoIconGlyph.Google,
|
||||
MailProviderType.IMAP4 => WinoIconGlyph.IMAP,
|
||||
_ => WinoIconGlyph.None,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return specialImapProvider switch
|
||||
{
|
||||
SpecialImapProvider.iCloud => WinoIconGlyph.Apple,
|
||||
SpecialImapProvider.Yahoo => WinoIconGlyph.Yahoo,
|
||||
_ => WinoIconGlyph.None,
|
||||
};
|
||||
}
|
||||
}
|
||||
public static WinoIconGlyph GetProviderIcon(MailAccount account)
|
||||
=> GetProviderIcon(account.ProviderType, account.SpecialImapProvider);
|
||||
|
||||
public static Geometry GetPathGeometry(string pathMarkup)
|
||||
{
|
||||
string xaml =
|
||||
"<Path " +
|
||||
"xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>" +
|
||||
"<Path.Data>" + pathMarkup + "</Path.Data></Path>";
|
||||
var path = XamlReader.Load(xaml) as Microsoft.UI.Xaml.Shapes.Path;
|
||||
|
||||
Geometry geometry = path.Data;
|
||||
path.Data = null;
|
||||
return geometry;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internationalization
|
||||
|
||||
public static string GetOperationString(MailOperation operation)
|
||||
{
|
||||
return operation switch
|
||||
{
|
||||
MailOperation.None => "unknown",
|
||||
MailOperation.Archive => Translator.MailOperation_Archive,
|
||||
MailOperation.UnArchive => Translator.MailOperation_Unarchive,
|
||||
MailOperation.SoftDelete => Translator.MailOperation_Delete,
|
||||
MailOperation.HardDelete => Translator.MailOperation_Delete,
|
||||
MailOperation.Move => Translator.MailOperation_Move,
|
||||
MailOperation.MoveToJunk => Translator.MailOperation_MoveJunk,
|
||||
MailOperation.MoveToFocused => Translator.MailOperation_MoveFocused,
|
||||
MailOperation.MoveToOther => Translator.MailOperation_MoveOther,
|
||||
MailOperation.AlwaysMoveToOther => Translator.MailOperation_AlwaysMoveOther,
|
||||
MailOperation.AlwaysMoveToFocused => Translator.MailOperation_AlwaysMoveFocused,
|
||||
MailOperation.SetFlag => Translator.MailOperation_SetFlag,
|
||||
MailOperation.ClearFlag => Translator.MailOperation_ClearFlag,
|
||||
MailOperation.MarkAsRead => Translator.MailOperation_MarkAsRead,
|
||||
MailOperation.MarkAsUnread => Translator.MailOperation_MarkAsUnread,
|
||||
MailOperation.MarkAsNotJunk => Translator.MailOperation_MarkNotJunk,
|
||||
MailOperation.Seperator => string.Empty,
|
||||
MailOperation.Ignore => Translator.MailOperation_Ignore,
|
||||
MailOperation.Reply => Translator.MailOperation_Reply,
|
||||
MailOperation.ReplyAll => Translator.MailOperation_ReplyAll,
|
||||
MailOperation.Zoom => Translator.MailOperation_Zoom,
|
||||
MailOperation.SaveAs => Translator.MailOperation_SaveAs,
|
||||
MailOperation.Find => Translator.MailOperation_Find,
|
||||
MailOperation.Forward => Translator.MailOperation_Forward,
|
||||
MailOperation.DarkEditor => string.Empty,
|
||||
MailOperation.LightEditor => string.Empty,
|
||||
MailOperation.Print => Translator.MailOperation_Print,
|
||||
MailOperation.ViewMessageSource => Translator.MailOperation_ViewMessageSource,
|
||||
MailOperation.Navigate => Translator.MailOperation_Navigate,
|
||||
_ => "unknown",
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetOperationString(FolderOperation operation)
|
||||
{
|
||||
return operation switch
|
||||
{
|
||||
FolderOperation.None => string.Empty,
|
||||
FolderOperation.Pin => Translator.FolderOperation_Pin,
|
||||
FolderOperation.Unpin => Translator.FolderOperation_Unpin,
|
||||
FolderOperation.MarkAllAsRead => Translator.FolderOperation_MarkAllAsRead,
|
||||
FolderOperation.DontSync => Translator.FolderOperation_DontSync,
|
||||
FolderOperation.Empty => Translator.FolderOperation_Empty,
|
||||
FolderOperation.Rename => Translator.FolderOperation_Rename,
|
||||
FolderOperation.Delete => Translator.FolderOperation_Delete,
|
||||
FolderOperation.Move => Translator.FolderOperation_Move,
|
||||
FolderOperation.CreateSubFolder => Translator.FolderOperation_CreateSubFolder,
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Messaging.UI;
|
||||
|
||||
namespace Wino.Core.WinUI.Interfaces;
|
||||
|
||||
public interface IWinoShellWindow : IRecipient<TitleBarShellContentUpdated>
|
||||
{
|
||||
void HandleAppActivation(LaunchActivatedEventArgs args);
|
||||
TitleBar GetTitleBar();
|
||||
Frame GetMainFrame();
|
||||
FrameworkElement GetRootContent();
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.Personalization;
|
||||
using Wino.Services;
|
||||
|
||||
namespace Wino.Core.WinUI.Models.Personalization;
|
||||
|
||||
/// <summary>
|
||||
/// Custom themes that are generated by users.
|
||||
/// </summary>
|
||||
public class CustomAppTheme : AppThemeBase
|
||||
{
|
||||
public CustomAppTheme(CustomThemeMetadata metadata) : base(metadata.Name, metadata.Id)
|
||||
{
|
||||
AccentColor = metadata.AccentColorHex;
|
||||
}
|
||||
|
||||
public override AppThemeType AppThemeType => AppThemeType.Custom;
|
||||
|
||||
public override string GetBackgroundPreviewImagePath()
|
||||
=> $"ms-appdata:///local/{NewThemeService.CustomThemeFolderName}/{Id}_preview.jpg";
|
||||
|
||||
public override async Task<string> GetThemeResourceDictionaryContentAsync()
|
||||
{
|
||||
var customAppThemeFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Wino.Core.WinUI/AppThemes/Custom.xaml"));
|
||||
return await FileIO.ReadTextAsync(customAppThemeFile);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.Personalization;
|
||||
|
||||
namespace Wino.Core.WinUI.Models.Personalization;
|
||||
|
||||
/// <summary>
|
||||
/// Forest, Nighty, Clouds etc. applies to pre-defined themes in Wino.
|
||||
/// </summary>
|
||||
public class PreDefinedAppTheme : AppThemeBase
|
||||
{
|
||||
public PreDefinedAppTheme(string themeName,
|
||||
Guid id,
|
||||
string accentColor = "",
|
||||
ApplicationElementTheme forcedElementTheme = ApplicationElementTheme.Default) : base(themeName, id)
|
||||
{
|
||||
AccentColor = accentColor;
|
||||
ForceElementTheme = forcedElementTheme;
|
||||
}
|
||||
|
||||
public override AppThemeType AppThemeType => AppThemeType.PreDefined;
|
||||
|
||||
public override string GetBackgroundPreviewImagePath()
|
||||
=> $"ms-appx:///Wino.Core.WinUI/BackgroundImages/{ThemeName}.jpg";
|
||||
|
||||
public override async Task<string> GetThemeResourceDictionaryContentAsync()
|
||||
{
|
||||
var xamlDictionaryFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Wino.Core.WinUI/AppThemes/{ThemeName}.xaml"));
|
||||
return await FileIO.ReadTextAsync(xamlDictionaryFile);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.WinUI.Models.Personalization;
|
||||
|
||||
// Mica - Acrylic.
|
||||
public class SystemAppTheme : PreDefinedAppTheme
|
||||
{
|
||||
public SystemAppTheme(string themeName, Guid id) : base(themeName, id, "") { }
|
||||
|
||||
public override AppThemeType AppThemeType => AppThemeType.System;
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.Printing;
|
||||
|
||||
namespace Wino.Core.WinUI.Dialogs;
|
||||
|
||||
/// <summary>
|
||||
/// ViewModel for the PrintDialog that handles data binding and state management.
|
||||
/// </summary>
|
||||
public class PrintDialogViewModel : INotifyPropertyChanged
|
||||
{
|
||||
private List<string> _availablePrinters = new();
|
||||
private bool _isCustomPageRange = false;
|
||||
private WebView2PrintSettingsModel _printSettings = new();
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public PrintDialogViewModel()
|
||||
{
|
||||
// Initialize default values
|
||||
PrintSettings.PropertyChanged += OnPrintSettingsChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The print settings model that will be configured by the dialog.
|
||||
/// </summary>
|
||||
public WebView2PrintSettingsModel PrintSettings
|
||||
{
|
||||
get => _printSettings;
|
||||
set
|
||||
{
|
||||
if (_printSettings != value)
|
||||
{
|
||||
if (_printSettings != null)
|
||||
_printSettings.PropertyChanged -= OnPrintSettingsChanged;
|
||||
|
||||
_printSettings = value;
|
||||
|
||||
if (_printSettings != null)
|
||||
_printSettings.PropertyChanged += OnPrintSettingsChanged;
|
||||
|
||||
OnPropertyChanged(nameof(PrintSettings));
|
||||
UpdateDerivedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of available printers.
|
||||
/// </summary>
|
||||
public List<string> AvailablePrinters
|
||||
{
|
||||
get => _availablePrinters;
|
||||
set
|
||||
{
|
||||
if (_availablePrinters != value)
|
||||
{
|
||||
_availablePrinters = value ?? new List<string>();
|
||||
OnPropertyChanged(nameof(AvailablePrinters));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Index for the orientation radio buttons.
|
||||
/// </summary>
|
||||
public int OrientationIndex
|
||||
{
|
||||
get => (int)PrintSettings.Orientation;
|
||||
set
|
||||
{
|
||||
if (value >= 0 && value <= 1)
|
||||
{
|
||||
PrintSettings.Orientation = (PrintOrientation)value;
|
||||
OnPropertyChanged(nameof(OrientationIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Index for the color mode radio buttons.
|
||||
/// </summary>
|
||||
public int ColorModeIndex
|
||||
{
|
||||
get => (int)PrintSettings.ColorMode;
|
||||
set
|
||||
{
|
||||
if (value >= 0 && value <= 2)
|
||||
{
|
||||
PrintSettings.ColorMode = (PrintColorMode)value;
|
||||
OnPropertyChanged(nameof(ColorModeIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Index for the collation radio buttons.
|
||||
/// </summary>
|
||||
public int CollationIndex
|
||||
{
|
||||
get => (int)PrintSettings.Collation;
|
||||
set
|
||||
{
|
||||
if (value >= 0 && value <= 2)
|
||||
{
|
||||
PrintSettings.Collation = (PrintCollation)value;
|
||||
OnPropertyChanged(nameof(CollationIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Index for the duplex radio buttons.
|
||||
/// </summary>
|
||||
public int DuplexIndex
|
||||
{
|
||||
get => (int)PrintSettings.Duplex;
|
||||
set
|
||||
{
|
||||
if (value >= 0 && value <= 3)
|
||||
{
|
||||
PrintSettings.Duplex = (PrintDuplex)value;
|
||||
OnPropertyChanged(nameof(DuplexIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Index for the media size combo box.
|
||||
/// </summary>
|
||||
public int MediaSizeIndex
|
||||
{
|
||||
get => (int)PrintSettings.MediaSize;
|
||||
set
|
||||
{
|
||||
if (value >= 0 && value <= 9)
|
||||
{
|
||||
PrintSettings.MediaSize = (PrintMediaSize)value;
|
||||
OnPropertyChanged(nameof(MediaSizeIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Index for the pages per side combo box.
|
||||
/// </summary>
|
||||
public int PagesPerSideIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
var validValues = new[] { 1, 2, 4, 6, 9, 16 };
|
||||
return Array.IndexOf(validValues, PrintSettings.PagesPerSide);
|
||||
}
|
||||
set
|
||||
{
|
||||
var validValues = new[] { 1, 2, 4, 6, 9, 16 };
|
||||
if (value >= 0 && value < validValues.Length)
|
||||
{
|
||||
PrintSettings.PagesPerSide = validValues[value];
|
||||
OnPropertyChanged(nameof(PagesPerSideIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Index for the page range option (0 = All pages, 1 = Custom range).
|
||||
/// </summary>
|
||||
public int PageRangeOptionIndex
|
||||
{
|
||||
get => IsCustomPageRange ? 1 : 0;
|
||||
set
|
||||
{
|
||||
IsCustomPageRange = value == 1;
|
||||
if (!IsCustomPageRange)
|
||||
{
|
||||
PrintSettings.PageRanges = string.Empty;
|
||||
}
|
||||
OnPropertyChanged(nameof(PageRangeOptionIndex));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether custom page range is selected.
|
||||
/// </summary>
|
||||
public bool IsCustomPageRange
|
||||
{
|
||||
get => _isCustomPageRange;
|
||||
private set
|
||||
{
|
||||
if (_isCustomPageRange != value)
|
||||
{
|
||||
_isCustomPageRange = value;
|
||||
OnPropertyChanged(nameof(IsCustomPageRange));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scale factor as percentage text for display.
|
||||
/// </summary>
|
||||
public string ScalePercentageText => $"{(int)(PrintSettings.ScaleFactor * 100)}%";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the dialog with the provided print settings.
|
||||
/// </summary>
|
||||
/// <param name="printSettings">The initial print settings.</param>
|
||||
public void Initialize(WebView2PrintSettingsModel printSettings = null)
|
||||
{
|
||||
if (printSettings != null)
|
||||
{
|
||||
PrintSettings = printSettings;
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintSettings = new WebView2PrintSettingsModel();
|
||||
}
|
||||
|
||||
UpdateDerivedProperties();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the list of available printers.
|
||||
/// </summary>
|
||||
/// <param name="printers">List of printer names.</param>
|
||||
public void SetAvailablePrinters(IEnumerable<string> printers)
|
||||
{
|
||||
AvailablePrinters = printers?.ToList() ?? new List<string>();
|
||||
|
||||
// If current printer is not in the list, select the first one
|
||||
if (AvailablePrinters.Any() && !AvailablePrinters.Contains(PrintSettings.PrinterName))
|
||||
{
|
||||
PrintSettings.PrinterName = AvailablePrinters.First();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPrintSettingsChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(WebView2PrintSettingsModel.ScaleFactor))
|
||||
{
|
||||
OnPropertyChanged(nameof(ScalePercentageText));
|
||||
}
|
||||
else if (e.PropertyName == nameof(WebView2PrintSettingsModel.PageRanges))
|
||||
{
|
||||
// Update custom page range flag based on whether page ranges is empty
|
||||
if (!string.IsNullOrWhiteSpace(PrintSettings.PageRanges))
|
||||
{
|
||||
IsCustomPageRange = true;
|
||||
OnPropertyChanged(nameof(PageRangeOptionIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateDerivedProperties()
|
||||
{
|
||||
OnPropertyChanged(nameof(OrientationIndex));
|
||||
OnPropertyChanged(nameof(ColorModeIndex));
|
||||
OnPropertyChanged(nameof(CollationIndex));
|
||||
OnPropertyChanged(nameof(DuplexIndex));
|
||||
OnPropertyChanged(nameof(MediaSizeIndex));
|
||||
OnPropertyChanged(nameof(PagesPerSideIndex));
|
||||
OnPropertyChanged(nameof(PageRangeOptionIndex));
|
||||
OnPropertyChanged(nameof(ScalePercentageText));
|
||||
|
||||
// Update custom page range based on current page ranges value
|
||||
IsCustomPageRange = !string.IsNullOrWhiteSpace(PrintSettings.PageRanges);
|
||||
}
|
||||
|
||||
protected virtual void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.WinUI.Models.Personalization;
|
||||
|
||||
namespace Wino.Core.WinUI.Selectors;
|
||||
|
||||
public partial class AppThemePreviewTemplateSelector : DataTemplateSelector
|
||||
{
|
||||
public DataTemplate SystemThemeTemplate { get; set; }
|
||||
public DataTemplate PreDefinedThemeTemplate { get; set; }
|
||||
public DataTemplate CustomAppTemplate { get; set; }
|
||||
|
||||
protected override DataTemplate SelectTemplateCore(object item)
|
||||
{
|
||||
if (item is SystemAppTheme)
|
||||
return SystemThemeTemplate;
|
||||
else if (item is PreDefinedAppTheme)
|
||||
return PreDefinedThemeTemplate;
|
||||
else if (item is CustomAppTheme)
|
||||
return CustomAppTemplate;
|
||||
|
||||
return base.SelectTemplateCore(item);
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.WinUI.Selectors;
|
||||
|
||||
public partial class CustomWinoMessageDialogIconSelector : DataTemplateSelector
|
||||
{
|
||||
public DataTemplate InfoIconTemplate { get; set; }
|
||||
public DataTemplate WarningIconTemplate { get; set; }
|
||||
public DataTemplate QuestionIconTemplate { get; set; }
|
||||
public DataTemplate ErrorIconTemplate { get; set; }
|
||||
|
||||
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
|
||||
{
|
||||
if (item == null) return null;
|
||||
|
||||
if (item is WinoCustomMessageDialogIcon icon)
|
||||
{
|
||||
switch (icon)
|
||||
{
|
||||
case WinoCustomMessageDialogIcon.Information:
|
||||
return InfoIconTemplate;
|
||||
case WinoCustomMessageDialogIcon.Warning:
|
||||
return WarningIconTemplate;
|
||||
case WinoCustomMessageDialogIcon.Error:
|
||||
return ErrorIconTemplate;
|
||||
case WinoCustomMessageDialogIcon.Question:
|
||||
return QuestionIconTemplate;
|
||||
default:
|
||||
throw new Exception("Unknown custom message dialog icon.");
|
||||
}
|
||||
}
|
||||
return base.SelectTemplateCore(item, container);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.WinUI.Selectors;
|
||||
|
||||
public partial class FileAttachmentTypeSelector : DataTemplateSelector
|
||||
{
|
||||
public DataTemplate None { get; set; }
|
||||
public DataTemplate Executable { get; set; }
|
||||
public DataTemplate Image { get; set; }
|
||||
public DataTemplate Audio { get; set; }
|
||||
public DataTemplate Video { get; set; }
|
||||
public DataTemplate PDF { get; set; }
|
||||
public DataTemplate HTML { get; set; }
|
||||
public DataTemplate RarArchive { get; set; }
|
||||
public DataTemplate Archive { get; set; }
|
||||
public DataTemplate Other { get; set; }
|
||||
|
||||
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
|
||||
{
|
||||
if (item == null)
|
||||
return None;
|
||||
|
||||
var type = (MailAttachmentType)item;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case MailAttachmentType.None:
|
||||
return None;
|
||||
case MailAttachmentType.Executable:
|
||||
return Executable;
|
||||
case MailAttachmentType.Image:
|
||||
return Image;
|
||||
case MailAttachmentType.Audio:
|
||||
return Audio;
|
||||
case MailAttachmentType.Video:
|
||||
return Video;
|
||||
case MailAttachmentType.PDF:
|
||||
return PDF;
|
||||
case MailAttachmentType.HTML:
|
||||
return HTML;
|
||||
case MailAttachmentType.RarArchive:
|
||||
return RarArchive;
|
||||
case MailAttachmentType.Archive:
|
||||
return Archive;
|
||||
default:
|
||||
return Other;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.MenuItems;
|
||||
|
||||
namespace Wino.Core.WinUI.Selectors;
|
||||
|
||||
public partial class NavigationMenuTemplateSelector : DataTemplateSelector
|
||||
{
|
||||
public DataTemplate MenuItemTemplate { get; set; }
|
||||
public DataTemplate ContactsMenuItemTemplate { get; set; }
|
||||
public DataTemplate AccountManagementTemplate { get; set; }
|
||||
public DataTemplate ClickableAccountMenuTemplate { get; set; }
|
||||
public DataTemplate MergedAccountTemplate { get; set; }
|
||||
public DataTemplate MergedAccountFolderTemplate { get; set; }
|
||||
public DataTemplate MergedAccountMoreExpansionItemTemplate { get; set; }
|
||||
public DataTemplate FolderMenuTemplate { get; set; }
|
||||
public DataTemplate SettingsItemTemplate { get; set; }
|
||||
public DataTemplate MoreItemsFolderTemplate { get; set; }
|
||||
public DataTemplate RatingItemTemplate { get; set; }
|
||||
public DataTemplate CreateNewFolderTemplate { get; set; }
|
||||
public DataTemplate SeperatorTemplate { get; set; }
|
||||
public DataTemplate NewMailTemplate { get; set; }
|
||||
public DataTemplate CategoryItemsTemplate { get; set; }
|
||||
public DataTemplate FixAuthenticationIssueTemplate { get; set; }
|
||||
public DataTemplate FixMissingFolderConfigTemplate { get; set; }
|
||||
|
||||
protected override DataTemplate SelectTemplateCore(object item)
|
||||
{
|
||||
if (item is NewMailMenuItem)
|
||||
return NewMailTemplate;
|
||||
else if (item is ContactsMenuItem)
|
||||
return ContactsMenuItemTemplate;
|
||||
else if (item is SettingsItem)
|
||||
return SettingsItemTemplate;
|
||||
else if (item is SeperatorItem)
|
||||
return SeperatorTemplate;
|
||||
else if (item is AccountMenuItem accountMenuItem)
|
||||
// Merged inbox account menu items must be nested.
|
||||
return ClickableAccountMenuTemplate;
|
||||
else if (item is ManageAccountsMenuItem)
|
||||
return AccountManagementTemplate;
|
||||
else if (item is RateMenuItem)
|
||||
return RatingItemTemplate;
|
||||
else if (item is MergedAccountMenuItem)
|
||||
return MergedAccountTemplate;
|
||||
else if (item is MergedAccountMoreFolderMenuItem)
|
||||
return MergedAccountMoreExpansionItemTemplate;
|
||||
else if (item is MergedAccountFolderMenuItem)
|
||||
return MergedAccountFolderTemplate;
|
||||
else if (item is FolderMenuItem)
|
||||
return FolderMenuTemplate;
|
||||
else if (item is FixAccountIssuesMenuItem fixAccountIssuesMenuItem)
|
||||
return fixAccountIssuesMenuItem.Account.AttentionReason == Domain.Enums.AccountAttentionReason.MissingSystemFolderConfiguration
|
||||
? FixMissingFolderConfigTemplate : FixAuthenticationIssueTemplate;
|
||||
else
|
||||
{
|
||||
var type = item.GetType();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using System.Linq;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.WinUI;
|
||||
|
||||
namespace Wino.Services;
|
||||
|
||||
public class ApplicationResourceManager : IApplicationResourceManager<ResourceDictionary>
|
||||
{
|
||||
public void AddResource(ResourceDictionary resource)
|
||||
=> WinoApplication.Current.Resources.MergedDictionaries.Add(resource);
|
||||
public void RemoveResource(ResourceDictionary resource)
|
||||
=> WinoApplication.Current.Resources.MergedDictionaries.Remove(resource);
|
||||
|
||||
public bool ContainsResourceKey(string resourceKey)
|
||||
=> WinoApplication.Current.Resources.ContainsKey(resourceKey);
|
||||
|
||||
public ResourceDictionary GetLastResource()
|
||||
=> WinoApplication.Current.Resources.MergedDictionaries.LastOrDefault();
|
||||
|
||||
public void ReplaceResource(string resourceKey, object resource)
|
||||
=> WinoApplication.Current.Resources[resourceKey] = resource;
|
||||
|
||||
public TReturnType GetResource<TReturnType>(string resourceKey)
|
||||
=> (TReturnType)WinoApplication.Current.Resources[resourceKey];
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Core.WinUI.Services;
|
||||
|
||||
public class ClipboardService : IClipboardService
|
||||
{
|
||||
public Task CopyClipboardAsync(string text)
|
||||
{
|
||||
var package = new DataPackage();
|
||||
package.SetText(text);
|
||||
|
||||
Clipboard.SetContent(package);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.Storage;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Core.WinUI.Services;
|
||||
|
||||
public class ConfigurationService : IConfigurationService
|
||||
{
|
||||
public T Get<T>(string key, T defaultValue = default)
|
||||
=> GetInternal(key, ApplicationData.Current.LocalSettings.Values, defaultValue);
|
||||
|
||||
public T GetRoaming<T>(string key, T defaultValue = default)
|
||||
=> GetInternal(key, ApplicationData.Current.RoamingSettings.Values, defaultValue);
|
||||
|
||||
public void Set(string key, object value)
|
||||
=> SetInternal(key, value, ApplicationData.Current.LocalSettings.Values);
|
||||
|
||||
public void SetRoaming(string key, object value)
|
||||
=> SetInternal(key, value, ApplicationData.Current.RoamingSettings.Values);
|
||||
|
||||
private static T GetInternal<T>(string key, IPropertySet collection, T defaultValue = default)
|
||||
{
|
||||
if (collection.TryGetValue(key, out object value))
|
||||
{
|
||||
var stringValue = value?.ToString();
|
||||
|
||||
if (typeof(T).IsEnum)
|
||||
return (T)Enum.Parse(typeof(T), stringValue);
|
||||
|
||||
if ((typeof(T) == typeof(Guid?) || typeof(T) == typeof(Guid)) && Guid.TryParse(stringValue, out Guid guidResult))
|
||||
{
|
||||
return (T)(object)guidResult;
|
||||
}
|
||||
|
||||
if (typeof(T) == typeof(TimeSpan))
|
||||
{
|
||||
return (T)(object)TimeSpan.Parse(stringValue);
|
||||
}
|
||||
|
||||
return (T)Convert.ChangeType(stringValue, typeof(T));
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static void SetInternal(string key, object value, IPropertySet collection)
|
||||
=> collection[key] = value?.ToString();
|
||||
}
|
||||
@@ -1,345 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Serilog;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.AccessCache;
|
||||
using Windows.Storage.Pickers;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Accounts;
|
||||
using Wino.Core.Domain.Models.Common;
|
||||
using Wino.Core.Domain.Models.Printing;
|
||||
using Wino.Core.WinUI.Dialogs;
|
||||
using Wino.Core.WinUI.Extensions;
|
||||
using Wino.Dialogs;
|
||||
using Wino.Messaging.Client.Shell;
|
||||
using WinRT.Interop;
|
||||
|
||||
namespace Wino.Core.WinUI.Services;
|
||||
|
||||
public class DialogServiceBase : IDialogServiceBase
|
||||
{
|
||||
private SemaphoreSlim _presentationSemaphore = new SemaphoreSlim(1);
|
||||
|
||||
protected INewThemeService ThemeService { get; }
|
||||
protected IConfigurationService ConfigurationService { get; }
|
||||
|
||||
protected IApplicationResourceManager<ResourceDictionary> ApplicationResourceManager { get; }
|
||||
|
||||
public DialogServiceBase(INewThemeService themeService, IConfigurationService configurationService, IApplicationResourceManager<ResourceDictionary> applicationResourceManager)
|
||||
{
|
||||
ThemeService = themeService;
|
||||
ConfigurationService = configurationService;
|
||||
ApplicationResourceManager = applicationResourceManager;
|
||||
}
|
||||
|
||||
protected XamlRoot GetXamlRoot()
|
||||
{
|
||||
return WinoApplication.MainWindow?.Content?.XamlRoot;
|
||||
}
|
||||
|
||||
public async Task<string> PickFilePathAsync(string saveFileName)
|
||||
{
|
||||
var picker = new FolderPicker()
|
||||
{
|
||||
SuggestedStartLocation = PickerLocationId.Desktop
|
||||
};
|
||||
|
||||
picker.FileTypeFilter.Add("*");
|
||||
|
||||
nint windowHandle = WindowNative.GetWindowHandle(WinoApplication.MainWindow);
|
||||
InitializeWithWindow.Initialize(picker, windowHandle);
|
||||
|
||||
var folder = await picker.PickSingleFolderAsync();
|
||||
if (folder == null) return string.Empty;
|
||||
|
||||
StorageApplicationPermissions.FutureAccessList.Add(folder);
|
||||
|
||||
return folder.Path;
|
||||
|
||||
//var picker = new FileSavePicker
|
||||
//{
|
||||
// SuggestedStartLocation = PickerLocationId.Desktop,
|
||||
// SuggestedFileName = saveFileName
|
||||
//};
|
||||
|
||||
//picker.FileTypeChoices.Add(Translator.FilteringOption_All, [".*"]);
|
||||
|
||||
//var file = await picker.PickSaveFileAsync();
|
||||
//if (file == null) return string.Empty;
|
||||
|
||||
//StorageApplicationPermissions.FutureAccessList.Add(file);
|
||||
|
||||
//return file.Path;
|
||||
}
|
||||
|
||||
public async Task<List<SharedFile>> PickFilesAsync(params object[] typeFilters)
|
||||
{
|
||||
var returnList = new List<SharedFile>();
|
||||
var picker = new FileOpenPicker
|
||||
{
|
||||
ViewMode = PickerViewMode.Thumbnail,
|
||||
SuggestedStartLocation = PickerLocationId.Desktop
|
||||
};
|
||||
|
||||
foreach (var filter in typeFilters)
|
||||
{
|
||||
picker.FileTypeFilter.Add(filter.ToString());
|
||||
}
|
||||
|
||||
nint windowHandle = WindowNative.GetWindowHandle(WinoApplication.MainWindow);
|
||||
InitializeWithWindow.Initialize(picker, windowHandle);
|
||||
|
||||
var files = await picker.PickMultipleFilesAsync();
|
||||
if (files == null) return returnList;
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
StorageApplicationPermissions.FutureAccessList.Add(file);
|
||||
|
||||
var sharedFile = await file.ToSharedFileAsync();
|
||||
returnList.Add(sharedFile);
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
private async Task<StorageFile> PickFileAsync(params object[] typeFilters)
|
||||
{
|
||||
var picker = new FileOpenPicker
|
||||
{
|
||||
ViewMode = PickerViewMode.Thumbnail
|
||||
};
|
||||
|
||||
foreach (var filter in typeFilters)
|
||||
{
|
||||
picker.FileTypeFilter.Add(filter.ToString());
|
||||
}
|
||||
|
||||
nint windowHandle = WindowNative.GetWindowHandle(WinoApplication.MainWindow);
|
||||
InitializeWithWindow.Initialize(picker, windowHandle);
|
||||
|
||||
var file = await picker.PickSingleFileAsync();
|
||||
|
||||
if (file == null) return null;
|
||||
|
||||
StorageApplicationPermissions.FutureAccessList.Add(file);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public virtual IAccountCreationDialog GetAccountCreationDialog(AccountCreationDialogResult accountCreationDialogResult)
|
||||
{
|
||||
return new AccountCreationDialog
|
||||
{
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme(),
|
||||
XamlRoot = GetXamlRoot()
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<byte[]> PickWindowsFileContentAsync(params object[] typeFilters)
|
||||
{
|
||||
var file = await PickFileAsync(typeFilters);
|
||||
|
||||
if (file == null) return [];
|
||||
|
||||
return await file.ToByteArrayAsync();
|
||||
}
|
||||
|
||||
public Task ShowMessageAsync(string message, string title, WinoCustomMessageDialogIcon icon = WinoCustomMessageDialogIcon.Information)
|
||||
=> ShowWinoCustomMessageDialogAsync(title, message, Translator.Buttons_Close, icon);
|
||||
|
||||
public Task<bool> ShowConfirmationDialogAsync(string question, string title, string confirmationButtonTitle)
|
||||
=> ShowWinoCustomMessageDialogAsync(title, question, confirmationButtonTitle, WinoCustomMessageDialogIcon.Question, Translator.Buttons_Cancel, string.Empty);
|
||||
|
||||
public async Task<bool> ShowWinoCustomMessageDialogAsync(string title,
|
||||
string description,
|
||||
string approveButtonText,
|
||||
WinoCustomMessageDialogIcon? icon,
|
||||
string cancelButtonText = "",
|
||||
string dontAskAgainConfigurationKey = "")
|
||||
|
||||
{
|
||||
// This config key has been marked as don't ask again already.
|
||||
// Return immidiate result without presenting the dialog.
|
||||
|
||||
bool isDontAskEnabled = !string.IsNullOrEmpty(dontAskAgainConfigurationKey);
|
||||
|
||||
if (isDontAskEnabled && ConfigurationService.Get(dontAskAgainConfigurationKey, false)) return false;
|
||||
|
||||
var informationContainer = new CustomMessageDialogInformationContainer(title, description, icon.Value, isDontAskEnabled);
|
||||
|
||||
var dialog = new ContentDialog
|
||||
{
|
||||
Style = ApplicationResourceManager.GetResource<Style>("WinoDialogStyle"),
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme(),
|
||||
DefaultButton = ContentDialogButton.Primary,
|
||||
PrimaryButtonText = approveButtonText,
|
||||
ContentTemplate = ApplicationResourceManager.GetResource<DataTemplate>("CustomWinoContentDialogContentTemplate"),
|
||||
Content = informationContainer
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(cancelButtonText))
|
||||
{
|
||||
dialog.SecondaryButtonText = cancelButtonText;
|
||||
}
|
||||
|
||||
var dialogResult = await HandleDialogPresentationAsync(dialog);
|
||||
|
||||
// Mark this key to not ask again if user checked the checkbox.
|
||||
if (informationContainer.IsDontAskChecked)
|
||||
{
|
||||
ConfigurationService.Set(dontAskAgainConfigurationKey, true);
|
||||
}
|
||||
|
||||
return dialogResult == ContentDialogResult.Primary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for PopupRoot to be available before presenting the dialog and returns the result after presentation.
|
||||
/// </summary>
|
||||
/// <param name="dialog">Dialog to present and wait for closing.</param>
|
||||
/// <returns>Dialog result from WinRT.</returns>
|
||||
public async Task<ContentDialogResult> HandleDialogPresentationAsync(ContentDialog dialog)
|
||||
{
|
||||
await _presentationSemaphore.WaitAsync();
|
||||
|
||||
try
|
||||
{
|
||||
dialog.XamlRoot = GetXamlRoot();
|
||||
|
||||
return await dialog.ShowAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, $"Handling dialog service failed. Dialog was {dialog.GetType().Name}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_presentationSemaphore.Release();
|
||||
}
|
||||
|
||||
return ContentDialogResult.None;
|
||||
}
|
||||
|
||||
|
||||
public void InfoBarMessage(string title, string message, InfoBarMessageType messageType)
|
||||
=> WeakReferenceMessenger.Default.Send(new InfoBarMessageRequested(messageType, title, message));
|
||||
|
||||
public void InfoBarMessage(string title, string message, InfoBarMessageType messageType, string actionButtonText, Action action)
|
||||
=> WeakReferenceMessenger.Default.Send(new InfoBarMessageRequested(messageType, title, message, actionButtonText, action));
|
||||
|
||||
public void ShowNotSupportedMessage()
|
||||
=> InfoBarMessage(Translator.Info_UnsupportedFunctionalityTitle,
|
||||
Translator.Info_UnsupportedFunctionalityDescription,
|
||||
InfoBarMessageType.Error);
|
||||
|
||||
public async Task<string> ShowTextInputDialogAsync(string currentInput, string dialogTitle, string dialogDescription, string primaryButtonText)
|
||||
{
|
||||
var inputDialog = new TextInputDialog()
|
||||
{
|
||||
CurrentInput = currentInput,
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme(),
|
||||
Title = dialogTitle
|
||||
};
|
||||
|
||||
inputDialog.SetDescription(dialogDescription);
|
||||
inputDialog.SetPrimaryButtonText(primaryButtonText);
|
||||
|
||||
await HandleDialogPresentationAsync(inputDialog);
|
||||
|
||||
if (inputDialog.HasInput.GetValueOrDefault() && !currentInput.Equals(inputDialog.CurrentInput))
|
||||
return inputDialog.CurrentInput;
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public async Task<string> PickWindowsFolderAsync()
|
||||
{
|
||||
var picker = new FolderPicker
|
||||
{
|
||||
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
|
||||
};
|
||||
|
||||
picker.FileTypeFilter.Add("*");
|
||||
|
||||
nint windowHandle = WindowNative.GetWindowHandle(WinoApplication.MainWindow);
|
||||
InitializeWithWindow.Initialize(picker, windowHandle);
|
||||
|
||||
var pickedFolder = await picker.PickSingleFolderAsync();
|
||||
|
||||
if (pickedFolder != null)
|
||||
{
|
||||
Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.AddOrReplace("FolderPickerToken", pickedFolder);
|
||||
|
||||
return pickedFolder.Path;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public async Task<bool> ShowCustomThemeBuilderDialogAsync()
|
||||
{
|
||||
var themeBuilderDialog = new CustomThemeBuilderDialog()
|
||||
{
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
|
||||
};
|
||||
|
||||
var dialogResult = await HandleDialogPresentationAsync(themeBuilderDialog);
|
||||
|
||||
return dialogResult == ContentDialogResult.Primary;
|
||||
}
|
||||
|
||||
public async Task<AccountCreationDialogResult> ShowAccountProviderSelectionDialogAsync(List<IProviderDetail> availableProviders)
|
||||
{
|
||||
var dialog = new NewAccountDialog
|
||||
{
|
||||
Providers = availableProviders,
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
|
||||
};
|
||||
|
||||
await HandleDialogPresentationAsync(dialog);
|
||||
|
||||
return dialog.Result;
|
||||
}
|
||||
|
||||
public async Task<WebView2PrintSettingsModel> ShowPrintDialogAsync(WebView2PrintSettingsModel initialSettings = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create the print dialog
|
||||
var dialog = initialSettings != null
|
||||
? new PrintDialog(initialSettings)
|
||||
: new PrintDialog();
|
||||
|
||||
// Set the XamlRoot for proper display
|
||||
dialog.XamlRoot = GetXamlRoot();
|
||||
|
||||
// Get available printers asynchronously when the dialog is loaded
|
||||
dialog.Loaded += async (sender, e) =>
|
||||
{
|
||||
await dialog.LoadAvailablePrintersAsync();
|
||||
};
|
||||
|
||||
// Show the dialog
|
||||
var result = await HandleDialogPresentationAsync(dialog);
|
||||
|
||||
// Return the settings if user clicked Print, otherwise null
|
||||
return result == ContentDialogResult.Primary
|
||||
? dialog.PrintSettings
|
||||
: null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log the exception if logging is available
|
||||
Log.Error(ex, "Error showing print dialog");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Core.WinUI.Services;
|
||||
|
||||
public class FileService : IFileService
|
||||
{
|
||||
public async Task<string> CopyFileAsync(string sourceFilePath, string destinationFolderPath)
|
||||
{
|
||||
var fileName = Path.GetFileName(sourceFilePath);
|
||||
|
||||
var sourceFileHandle = await StorageFile.GetFileFromPathAsync(sourceFilePath);
|
||||
var destinationFolder = await StorageFolder.GetFolderFromPathAsync(destinationFolderPath);
|
||||
|
||||
var copiedFile = await sourceFileHandle.CopyAsync(destinationFolder, fileName, NameCollisionOption.GenerateUniqueName);
|
||||
|
||||
return copiedFile.Path;
|
||||
}
|
||||
|
||||
public async Task<string> GetFileContentByApplicationUriAsync(string resourcePath)
|
||||
{
|
||||
var releaseNoteFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri(resourcePath));
|
||||
|
||||
return await FileIO.ReadTextAsync(releaseNoteFile);
|
||||
}
|
||||
|
||||
public async Task<Stream> GetFileStreamAsync(string folderPath, string fileName)
|
||||
{
|
||||
var folder = await StorageFolder.GetFolderFromPathAsync(folderPath);
|
||||
var createdFile = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
|
||||
|
||||
return await createdFile.OpenStreamForWriteAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> SaveLogsToFolderAsync(string logsFolder, string destinationFolder)
|
||||
{
|
||||
var logFiles = Directory.GetFiles(logsFolder, "*.log");
|
||||
|
||||
if (logFiles.Length == 0) return false;
|
||||
|
||||
using var fileStream = await GetFileStreamAsync(destinationFolder, Constants.LogArchiveFileName);
|
||||
using var archive = new ZipArchive(fileStream, ZipArchiveMode.Create, true);
|
||||
|
||||
foreach (var logFile in logFiles)
|
||||
{
|
||||
using FileStream logFileStream = File.Open(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
|
||||
var zipArchiveEntry = archive.CreateEntry(Path.GetFileName(logFile), CompressionLevel.Fastest);
|
||||
using var zipStream = zipArchiveEntry.Open();
|
||||
|
||||
await logFileStream.CopyToAsync(zipStream);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using Microsoft.UI.Input;
|
||||
using Windows.System;
|
||||
using Windows.UI.Core;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Core.WinUI.Services;
|
||||
|
||||
public class KeyPressService : IKeyPressService
|
||||
{
|
||||
public bool IsCtrlKeyPressed()
|
||||
=> InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down);
|
||||
|
||||
public bool IsShiftKeyPressed()
|
||||
=> InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Shift).HasFlag(CoreVirtualKeyStates.Down);
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.Storage;
|
||||
using Windows.System;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
|
||||
|
||||
#if WINDOWS_UWP
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
#endif
|
||||
|
||||
namespace Wino.Services;
|
||||
|
||||
public class NativeAppService : INativeAppService
|
||||
{
|
||||
private string _mimeMessagesFolder;
|
||||
private string _editorBundlePath;
|
||||
|
||||
public Func<IntPtr> GetCoreWindowHwnd { get; set; }
|
||||
|
||||
public string GetWebAuthenticationBrokerUri()
|
||||
{
|
||||
#if WINDOWS_UWP
|
||||
return WebAuthenticationBroker.GetCurrentApplicationCallbackUri().AbsoluteUri;
|
||||
#endif
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public async Task<string> GetMimeMessageStoragePath()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_mimeMessagesFolder))
|
||||
return _mimeMessagesFolder;
|
||||
|
||||
var localFolder = ApplicationData.Current.LocalFolder;
|
||||
var mimeFolder = await localFolder.CreateFolderAsync("Mime", CreationCollisionOption.OpenIfExists);
|
||||
|
||||
_mimeMessagesFolder = mimeFolder.Path;
|
||||
|
||||
return _mimeMessagesFolder;
|
||||
}
|
||||
|
||||
public async Task<string> GetEditorBundlePathAsync()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_editorBundlePath))
|
||||
{
|
||||
var editorFileFromBundle = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///JS/editor.html"))
|
||||
.AsTask()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
_editorBundlePath = editorFileFromBundle.Path;
|
||||
}
|
||||
|
||||
return _editorBundlePath;
|
||||
}
|
||||
|
||||
[Obsolete("This should be removed. There should be no functionality.")]
|
||||
public bool IsAppRunning()
|
||||
{
|
||||
#if WINDOWS_UWP
|
||||
return (Window.Current?.Content as Frame)?.Content != null;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public async Task LaunchFileAsync(string filePath)
|
||||
{
|
||||
var file = await StorageFile.GetFileFromPathAsync(filePath);
|
||||
|
||||
await Launcher.LaunchFileAsync(file);
|
||||
}
|
||||
|
||||
public Task<bool> LaunchUriAsync(Uri uri) => Launcher.LaunchUriAsync(uri).AsTask();
|
||||
|
||||
public string GetFullAppVersion()
|
||||
{
|
||||
Package package = Package.Current;
|
||||
PackageId packageId = package.Id;
|
||||
PackageVersion version = packageId.Version;
|
||||
|
||||
return string.Format("{0}.{1}.{2}.{3}", version.Major, version.Minor, version.Build, version.Revision);
|
||||
}
|
||||
|
||||
[Obsolete("Not supported for Win SDK")]
|
||||
public async Task PinAppToTaskbarAsync()
|
||||
{
|
||||
// If Start screen manager API's aren't present
|
||||
//if (!ApiInformation.IsTypePresent("Windows.UI.Shell.TaskbarManager")) return;
|
||||
|
||||
//// Get the taskbar manager
|
||||
//var taskbarManager = TaskbarManager.GetDefault();
|
||||
|
||||
//// If Taskbar doesn't allow pinning, don't show the tip
|
||||
//if (!taskbarManager.IsPinningAllowed) return;
|
||||
|
||||
//// If already pinned, don't show the tip
|
||||
//if (await taskbarManager.IsCurrentAppPinnedAsync()) return;
|
||||
|
||||
//await taskbarManager.RequestPinCurrentAppAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
|
||||
namespace Wino.Core.WinUI.Services;
|
||||
|
||||
public class NavigationServiceBase
|
||||
{
|
||||
public NavigationTransitionInfo GetNavigationTransitionInfo(NavigationTransitionType transition)
|
||||
{
|
||||
return transition switch
|
||||
{
|
||||
NavigationTransitionType.DrillIn => new DrillInNavigationTransitionInfo(),
|
||||
NavigationTransitionType.Entrance => new EntranceNavigationTransitionInfo(),
|
||||
_ => new SuppressNavigationTransitionInfo(),
|
||||
};
|
||||
}
|
||||
|
||||
public Type GetCurrentFrameType(ref Frame _frame)
|
||||
{
|
||||
if (_frame != null && _frame.Content != null)
|
||||
return _frame.Content.GetType();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,641 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.WinUI;
|
||||
using CommunityToolkit.WinUI.Helpers;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Windows.Storage;
|
||||
using Windows.UI;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Exceptions;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models;
|
||||
using Wino.Core.Domain.Models.Personalization;
|
||||
using Wino.Core.WinUI;
|
||||
using Wino.Core.WinUI.Extensions;
|
||||
using Wino.Core.WinUI.Interfaces;
|
||||
using Wino.Core.WinUI.Models.Personalization;
|
||||
using Wino.Core.WinUI.Services;
|
||||
using Wino.Messaging.Client.Shell;
|
||||
using WinUIEx;
|
||||
|
||||
namespace Wino.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Next-generation theme service with enhanced WinUI support including backdrop management
|
||||
/// </summary>
|
||||
public class NewThemeService : INewThemeService
|
||||
{
|
||||
public const string CustomThemeFolderName = "CustomThemes";
|
||||
|
||||
private static string _defaultThemeId = "00000000-0000-0000-0000-000000000000";
|
||||
private static string _cloudsThemeId = "3b621cc2-e270-4a76-8477-737917cccda0";
|
||||
private static string _forestThemeId = "8bc89b37-a7c5-4049-86e2-de1ae8858dbd";
|
||||
private static string _nightyThemeId = "5b65e04e-fd7e-4c2d-8221-068d3e02d23a";
|
||||
private static string _snowflakeThemeId = "e143ddde-2e28-4846-9d98-dad63d6505f1";
|
||||
private static string _gardenThemeId = "698e4466-f88c-4799-9c61-f0ea1308ed49";
|
||||
|
||||
public event EventHandler<ApplicationElementTheme> ElementThemeChanged;
|
||||
public event EventHandler<string> AccentColorChanged;
|
||||
public event EventHandler<WindowBackdropType> BackdropChanged;
|
||||
|
||||
private const string AccentColorKey = nameof(AccentColorKey);
|
||||
private const string CurrentApplicationThemeKey = nameof(CurrentApplicationThemeKey);
|
||||
private const string WindowBackdropTypeKey = nameof(WindowBackdropTypeKey);
|
||||
|
||||
// Custom theme
|
||||
public const string CustomThemeAccentColorKey = nameof(CustomThemeAccentColorKey);
|
||||
|
||||
// Keep reference so it does not get optimized/garbage collected
|
||||
private readonly UISettings uiSettings = new UISettings();
|
||||
|
||||
private readonly IConfigurationService _configurationService;
|
||||
private readonly IUnderlyingThemeService _underlyingThemeService;
|
||||
private readonly IApplicationResourceManager<ResourceDictionary> _applicationResourceManager;
|
||||
|
||||
private List<AppThemeBase> preDefinedThemes { get; set; } = new List<AppThemeBase>()
|
||||
{
|
||||
new SystemAppTheme("Default", Guid.Parse(_defaultThemeId)),
|
||||
new PreDefinedAppTheme("Nighty", Guid.Parse(_nightyThemeId), "#e1b12c", ApplicationElementTheme.Dark),
|
||||
new PreDefinedAppTheme("Forest", Guid.Parse(_forestThemeId), "#16a085", ApplicationElementTheme.Dark),
|
||||
new PreDefinedAppTheme("Clouds", Guid.Parse(_cloudsThemeId), "#0984e3", ApplicationElementTheme.Light),
|
||||
new PreDefinedAppTheme("Snowflake", Guid.Parse(_snowflakeThemeId), "#4a69bd", ApplicationElementTheme.Light),
|
||||
new PreDefinedAppTheme("Garden", Guid.Parse(_gardenThemeId), "#05c46b", ApplicationElementTheme.Light),
|
||||
};
|
||||
|
||||
public NewThemeService(IConfigurationService configurationService,
|
||||
IUnderlyingThemeService underlyingThemeService,
|
||||
IApplicationResourceManager<ResourceDictionary> applicationResourceManager)
|
||||
{
|
||||
_configurationService = configurationService;
|
||||
_underlyingThemeService = underlyingThemeService;
|
||||
_applicationResourceManager = applicationResourceManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets (with LocalSettings persistence) the RequestedTheme of the root element.
|
||||
/// </summary>
|
||||
public ApplicationElementTheme RootTheme
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetShellRootContent().RequestedTheme.ToWinoElementTheme();
|
||||
}
|
||||
set
|
||||
{
|
||||
GetShellRootContent().RequestedTheme = value.ToWindowsElementTheme();
|
||||
|
||||
_configurationService.Set(UnderlyingThemeService.SelectedAppThemeKey, value);
|
||||
|
||||
UpdateSystemCaptionButtonColors();
|
||||
|
||||
// PopupRoot usually needs to react to changes.
|
||||
NotifyThemeUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private Guid? currentApplicationThemeId;
|
||||
|
||||
public Guid? CurrentApplicationThemeId
|
||||
{
|
||||
get { return currentApplicationThemeId; }
|
||||
set
|
||||
{
|
||||
currentApplicationThemeId = value;
|
||||
|
||||
_configurationService.Set(CurrentApplicationThemeKey, value);
|
||||
|
||||
if (WinoApplication.MainWindow != null)
|
||||
{
|
||||
WinoApplication.MainWindow.DispatcherQueue.TryEnqueue(async () =>
|
||||
{
|
||||
await ApplyCustomThemeAsync(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string accentColor;
|
||||
|
||||
public string AccentColor
|
||||
{
|
||||
get { return accentColor; }
|
||||
set
|
||||
{
|
||||
accentColor = value;
|
||||
|
||||
UpdateAccentColor(value);
|
||||
|
||||
_configurationService.Set(AccentColorKey, value);
|
||||
AccentColorChanged?.Invoke(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
private WindowBackdropType currentBackdropType;
|
||||
|
||||
public WindowBackdropType CurrentBackdropType
|
||||
{
|
||||
get { return currentBackdropType; }
|
||||
set
|
||||
{
|
||||
// Only update if the backdrop type has actually changed
|
||||
if (currentBackdropType == value) return;
|
||||
|
||||
currentBackdropType = value;
|
||||
_configurationService.Set(WindowBackdropTypeKey, (int)value);
|
||||
|
||||
if (WinoApplication.MainWindow != null)
|
||||
{
|
||||
WinoApplication.MainWindow.DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
ApplyBackdrop(value);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsCustomTheme
|
||||
{
|
||||
get
|
||||
{
|
||||
// If no theme is set, it's not a custom theme
|
||||
if (currentApplicationThemeId == null) return false;
|
||||
|
||||
// Check if current theme is not in predefined themes (all themes now are custom or predefined, no system themes)
|
||||
return !preDefinedThemes.Exists(a => a.Id == currentApplicationThemeId);
|
||||
}
|
||||
}
|
||||
|
||||
public FrameworkElement GetShellRootContent() => (WinoApplication.MainWindow as IWinoShellWindow)?.GetRootContent() ?? throw new Exception("No root content found");
|
||||
|
||||
private bool isInitialized = false;
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
// Already initialized. There is no need.
|
||||
if (isInitialized) return;
|
||||
|
||||
RootTheme = _configurationService.Get(UnderlyingThemeService.SelectedAppThemeKey, ApplicationElementTheme.Default);
|
||||
AccentColor = _configurationService.Get(AccentColorKey, string.Empty);
|
||||
|
||||
// Set the current theme id. Don't set a default for backward compatibility.
|
||||
var storedThemeId = _configurationService.Get<Guid?>(CurrentApplicationThemeKey, null);
|
||||
currentApplicationThemeId = storedThemeId;
|
||||
|
||||
// Load backdrop setting, default to Mica
|
||||
currentBackdropType = (WindowBackdropType)_configurationService.Get(WindowBackdropTypeKey, (int)WindowBackdropType.Mica);
|
||||
|
||||
// Apply backdrop first, then theme
|
||||
ApplyBackdrop(currentBackdropType);
|
||||
await ApplyCustomThemeAsync(true);
|
||||
|
||||
// Registering to color changes, thus we notice when user changes theme system wide
|
||||
|
||||
// TODO: WinUI: This event seems to be very unreliable. It causes a crash when the function runs under.
|
||||
//uiSettings.ColorValuesChanged -= UISettingsColorChanged;
|
||||
//uiSettings.ColorValuesChanged += UISettingsColorChanged;
|
||||
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
public void ApplyBackdrop(WindowBackdropType backdropType)
|
||||
{
|
||||
if (WinoApplication.MainWindow is not WindowEx windowEx)
|
||||
{
|
||||
Debug.WriteLine("MainWindow is not WindowEx, cannot apply backdrop");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Microsoft.UI.Xaml.Media.SystemBackdrop backdrop = backdropType switch
|
||||
{
|
||||
WindowBackdropType.Mica => new MicaBackdrop() { Kind = Microsoft.UI.Composition.SystemBackdrops.MicaKind.Base },
|
||||
WindowBackdropType.MicaAlt => new MicaBackdrop() { Kind = Microsoft.UI.Composition.SystemBackdrops.MicaKind.BaseAlt },
|
||||
WindowBackdropType.DesktopAcrylic => new DesktopAcrylicBackdrop(),
|
||||
WindowBackdropType.AcrylicBase => new DesktopAcrylicBackdrop(), // Using DesktopAcrylic as base
|
||||
WindowBackdropType.AcrylicThin => new DesktopAcrylicBackdrop(), // Using DesktopAcrylic as thin
|
||||
WindowBackdropType.None => null,
|
||||
_ => new MicaBackdrop() { Kind = Microsoft.UI.Composition.SystemBackdrops.MicaKind.Base }
|
||||
};
|
||||
|
||||
if (windowEx.SystemBackdrop != backdrop)
|
||||
{
|
||||
windowEx.SystemBackdrop = backdrop;
|
||||
|
||||
BackdropChanged?.Invoke(this, backdropType);
|
||||
|
||||
Debug.WriteLine($"Applied backdrop: {backdropType}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"Failed to apply backdrop {backdropType}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SetAccentColorAsync(string hexColor, bool preserveTheme = true)
|
||||
{
|
||||
if (string.IsNullOrEmpty(hexColor))
|
||||
{
|
||||
// Reset to system accent color
|
||||
hexColor = GetSystemAccentColorHex();
|
||||
}
|
||||
|
||||
if (preserveTheme)
|
||||
{
|
||||
// Just update accent color without changing theme
|
||||
AccentColor = hexColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This might trigger theme changes
|
||||
AccentColor = hexColor;
|
||||
await ApplyCustomThemeAsync(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void NotifyThemeUpdate()
|
||||
{
|
||||
if (GetShellRootContent() is not UIElement rootContent) return;
|
||||
|
||||
_ = rootContent.DispatcherQueue.EnqueueAsync(() =>
|
||||
{
|
||||
ElementThemeChanged?.Invoke(this, RootTheme);
|
||||
WeakReferenceMessenger.Default.Send(new ApplicationThemeChanged(_underlyingThemeService.IsUnderlyingThemeDark()));
|
||||
}, Microsoft.UI.Dispatching.DispatcherQueuePriority.High);
|
||||
}
|
||||
|
||||
private void UISettingsColorChanged(UISettings sender, object args)
|
||||
{
|
||||
NotifyThemeUpdate();
|
||||
}
|
||||
|
||||
public void UpdateSystemCaptionButtonColors()
|
||||
{
|
||||
GetShellRootContent().DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
if (WinoApplication.MainWindow is not WindowEx mainWindow) return;
|
||||
|
||||
var titleBar = mainWindow.AppWindow.TitleBar;
|
||||
if (titleBar == null) return;
|
||||
|
||||
// Determine if current theme is dark
|
||||
bool isDarkTheme = _underlyingThemeService.IsUnderlyingThemeDark();
|
||||
|
||||
// Set button colors based on theme
|
||||
// Normal and inactive backgrounds are transparent, but hover/pressed have subtle backgrounds
|
||||
titleBar.ButtonBackgroundColor = Color.FromArgb(0, 0, 0, 0); // Transparent
|
||||
titleBar.ButtonInactiveBackgroundColor = Color.FromArgb(0, 0, 0, 0); // Transparent
|
||||
|
||||
if (isDarkTheme)
|
||||
{
|
||||
// Dark theme: use light text/icons for better contrast
|
||||
titleBar.ButtonForegroundColor = Color.FromArgb(255, 255, 255, 255); // White
|
||||
titleBar.ButtonInactiveForegroundColor = Color.FromArgb(128, 255, 255, 255); // Semi-transparent white
|
||||
titleBar.ButtonHoverForegroundColor = Color.FromArgb(255, 255, 255, 255); // White
|
||||
titleBar.ButtonPressedForegroundColor = Color.FromArgb(255, 255, 255, 255); // White
|
||||
|
||||
// Subtle hover and pressed backgrounds for dark theme
|
||||
titleBar.ButtonHoverBackgroundColor = Color.FromArgb(20, 255, 255, 255); // Very subtle white overlay
|
||||
titleBar.ButtonPressedBackgroundColor = Color.FromArgb(40, 255, 255, 255); // Slightly more visible white overlay
|
||||
}
|
||||
else
|
||||
{
|
||||
// Light theme: use dark text/icons for better contrast
|
||||
titleBar.ButtonForegroundColor = Color.FromArgb(255, 0, 0, 0); // Black
|
||||
titleBar.ButtonInactiveForegroundColor = Color.FromArgb(128, 0, 0, 0); // Semi-transparent black
|
||||
titleBar.ButtonHoverForegroundColor = Color.FromArgb(255, 0, 0, 0); // Black
|
||||
titleBar.ButtonPressedForegroundColor = Color.FromArgb(255, 0, 0, 0); // Black
|
||||
|
||||
// Subtle hover and pressed backgrounds for light theme
|
||||
titleBar.ButtonHoverBackgroundColor = Color.FromArgb(20, 0, 0, 0); // Very subtle black overlay
|
||||
titleBar.ButtonPressedBackgroundColor = Color.FromArgb(40, 0, 0, 0); // Slightly more visible black overlay
|
||||
}
|
||||
|
||||
Debug.WriteLine($"Updated title bar button colors for {(isDarkTheme ? "dark" : "light")} theme");
|
||||
});
|
||||
}
|
||||
|
||||
public void UpdateAccentColor(string hex)
|
||||
{
|
||||
// Change accent color if specified.
|
||||
if (!string.IsNullOrEmpty(hex))
|
||||
{
|
||||
var color = CommunityToolkit.WinUI.Helpers.ColorHelper.ToColor(hex);
|
||||
var brush = new SolidColorBrush(color);
|
||||
|
||||
if (_applicationResourceManager.ContainsResourceKey("SystemAccentColor"))
|
||||
_applicationResourceManager.ReplaceResource("SystemAccentColor", color);
|
||||
|
||||
if (_applicationResourceManager.ContainsResourceKey("NavigationViewSelectionIndicatorForeground"))
|
||||
_applicationResourceManager.ReplaceResource("NavigationViewSelectionIndicatorForeground", brush);
|
||||
|
||||
if (_applicationResourceManager.ContainsResourceKey("SystemControlBackgroundAccentBrush"))
|
||||
_applicationResourceManager.ReplaceResource("SystemControlBackgroundAccentBrush", brush);
|
||||
|
||||
if (_applicationResourceManager.ContainsResourceKey("SystemColorControlAccentBrush"))
|
||||
_applicationResourceManager.ReplaceResource("SystemColorControlAccentBrush", brush);
|
||||
|
||||
RefreshThemeResource();
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshThemeResource()
|
||||
{
|
||||
var mainApplicationFrame = GetShellRootContent();
|
||||
|
||||
if (mainApplicationFrame == null) return;
|
||||
|
||||
if (mainApplicationFrame.RequestedTheme == ElementTheme.Dark)
|
||||
{
|
||||
mainApplicationFrame.RequestedTheme = ElementTheme.Light;
|
||||
mainApplicationFrame.RequestedTheme = ElementTheme.Dark;
|
||||
}
|
||||
else if (mainApplicationFrame.RequestedTheme == ElementTheme.Light)
|
||||
{
|
||||
mainApplicationFrame.RequestedTheme = ElementTheme.Dark;
|
||||
mainApplicationFrame.RequestedTheme = ElementTheme.Light;
|
||||
}
|
||||
else
|
||||
{
|
||||
var isUnderlyingDark = _underlyingThemeService.IsUnderlyingThemeDark();
|
||||
|
||||
mainApplicationFrame.RequestedTheme = isUnderlyingDark ? ElementTheme.Light : ElementTheme.Dark;
|
||||
mainApplicationFrame.RequestedTheme = ElementTheme.Default;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ApplyCustomThemeAsync(bool isInitializing)
|
||||
{
|
||||
// If no theme ID is set, don't apply any theme (for backward compatibility)
|
||||
if (currentApplicationThemeId == null)
|
||||
{
|
||||
Debug.WriteLine("No theme ID set, skipping theme application");
|
||||
return;
|
||||
}
|
||||
|
||||
AppThemeBase applyingTheme = null;
|
||||
|
||||
var controlThemeList = new List<AppThemeBase>(preDefinedThemes);
|
||||
|
||||
// Don't search for custom themes if applying theme is already in pre-defined templates.
|
||||
// This is important for startup performance because we won't be loading the custom themes on launch.
|
||||
|
||||
bool isApplyingPreDefinedTheme = preDefinedThemes.Exists(a => a.Id == currentApplicationThemeId);
|
||||
|
||||
if (isApplyingPreDefinedTheme)
|
||||
{
|
||||
applyingTheme = preDefinedThemes.Find(a => a.Id == currentApplicationThemeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// User applied custom theme. Load custom themes and find it there.
|
||||
|
||||
var customThemes = await GetCurrentCustomThemesAsync();
|
||||
|
||||
controlThemeList.AddRange(customThemes.Select(a => new CustomAppTheme(a)));
|
||||
|
||||
applyingTheme = controlThemeList.Find(a => a.Id == currentApplicationThemeId);
|
||||
|
||||
// If theme ID is not found in available themes, don't apply any theme (backward compatibility)
|
||||
if (applyingTheme == null)
|
||||
{
|
||||
Debug.WriteLine($"Theme with ID {currentApplicationThemeId} not found, skipping theme application");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var existingThemeDictionary = _applicationResourceManager.GetLastResource();
|
||||
|
||||
if (existingThemeDictionary != null && existingThemeDictionary.TryGetValue("ThemeName", out object themeNameString))
|
||||
{
|
||||
var themeName = themeNameString.ToString();
|
||||
|
||||
// Applying different theme.
|
||||
if (themeName != applyingTheme.ThemeName)
|
||||
{
|
||||
var resourceDictionaryContent = await applyingTheme.GetThemeResourceDictionaryContentAsync();
|
||||
|
||||
var resourceDictionary = XamlReader.Load(resourceDictionaryContent) as ResourceDictionary;
|
||||
|
||||
// Custom themes require special attention for background image because
|
||||
// they share the same base theme resource dictionary.
|
||||
|
||||
if (applyingTheme is CustomAppTheme)
|
||||
{
|
||||
resourceDictionary["ThemeBackgroundImage"] = $"ms-appdata:///local/{CustomThemeFolderName}/{applyingTheme.Id}.jpg";
|
||||
}
|
||||
|
||||
_applicationResourceManager.RemoveResource(existingThemeDictionary);
|
||||
_applicationResourceManager.AddResource(resourceDictionary);
|
||||
|
||||
bool isSystemTheme = applyingTheme is SystemAppTheme || applyingTheme is CustomAppTheme;
|
||||
|
||||
if (isSystemTheme)
|
||||
{
|
||||
// For system themes, set the RootElement theme from saved values.
|
||||
// Potential bug: When we set it to system default, theme is not applied when system and
|
||||
// app element theme is different :)
|
||||
|
||||
var savedElement = _configurationService.Get(UnderlyingThemeService.SelectedAppThemeKey, ApplicationElementTheme.Default);
|
||||
RootTheme = savedElement;
|
||||
|
||||
// Quickly switch theme to apply theme resource changes.
|
||||
RefreshThemeResource();
|
||||
}
|
||||
else
|
||||
RootTheme = applyingTheme.ForceElementTheme;
|
||||
|
||||
// Theme has accent color. Override.
|
||||
if (!isInitializing)
|
||||
{
|
||||
AccentColor = applyingTheme.AccentColor;
|
||||
}
|
||||
}
|
||||
else
|
||||
UpdateSystemCaptionButtonColors();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"Apply theme failed -> {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<AppThemeBase>> GetAvailableThemesAsync()
|
||||
{
|
||||
var availableThemes = new List<AppThemeBase>(preDefinedThemes);
|
||||
|
||||
var customThemes = await GetCurrentCustomThemesAsync();
|
||||
|
||||
availableThemes.AddRange(customThemes.Select(a => new CustomAppTheme(a)));
|
||||
|
||||
return availableThemes;
|
||||
}
|
||||
|
||||
public async Task<CustomThemeMetadata> CreateNewCustomThemeAsync(string themeName, string accentColor, byte[] wallpaperData)
|
||||
{
|
||||
if (wallpaperData == null || wallpaperData.Length == 0)
|
||||
throw new CustomThemeCreationFailedException(Translator.Exception_CustomThemeMissingWallpaper);
|
||||
|
||||
if (string.IsNullOrEmpty(themeName))
|
||||
throw new CustomThemeCreationFailedException(Translator.Exception_CustomThemeMissingName);
|
||||
|
||||
var themes = await GetCurrentCustomThemesAsync();
|
||||
|
||||
if (themes.Exists(a => a.Name == themeName))
|
||||
throw new CustomThemeCreationFailedException(Translator.Exception_CustomThemeExists);
|
||||
|
||||
var newTheme = new CustomThemeMetadata()
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = themeName,
|
||||
AccentColorHex = accentColor
|
||||
};
|
||||
|
||||
// Save wallpaper.
|
||||
// Filename would be the same as metadata id, in jpg format.
|
||||
|
||||
var themeFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(CustomThemeFolderName, CreationCollisionOption.OpenIfExists);
|
||||
|
||||
var wallpaperFile = await themeFolder.CreateFileAsync($"{newTheme.Id}.jpg", CreationCollisionOption.ReplaceExisting);
|
||||
await FileIO.WriteBytesAsync(wallpaperFile, wallpaperData);
|
||||
|
||||
// Generate thumbnail for settings page.
|
||||
|
||||
var thumbnail = await wallpaperFile.GetThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.PicturesView);
|
||||
var thumbnailFile = await themeFolder.CreateFileAsync($"{newTheme.Id}_preview.jpg", CreationCollisionOption.ReplaceExisting);
|
||||
|
||||
using (var readerStream = thumbnail.AsStreamForRead())
|
||||
{
|
||||
byte[] bytes = new byte[readerStream.Length];
|
||||
|
||||
await readerStream.ReadExactlyAsync(bytes);
|
||||
|
||||
var buffer = bytes.AsBuffer();
|
||||
|
||||
await FileIO.WriteBufferAsync(thumbnailFile, buffer);
|
||||
}
|
||||
|
||||
// Save metadata.
|
||||
var metadataFile = await themeFolder.CreateFileAsync($"{newTheme.Id}.json", CreationCollisionOption.ReplaceExisting);
|
||||
|
||||
var serialized = JsonSerializer.Serialize(newTheme, DomainModelsJsonContext.Default.CustomThemeMetadata);
|
||||
await FileIO.WriteTextAsync(metadataFile, serialized);
|
||||
|
||||
return newTheme;
|
||||
}
|
||||
|
||||
public async Task<List<CustomThemeMetadata>> GetCurrentCustomThemesAsync()
|
||||
{
|
||||
var results = new List<CustomThemeMetadata>();
|
||||
|
||||
var themeFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(CustomThemeFolderName, CreationCollisionOption.OpenIfExists);
|
||||
|
||||
var allFiles = await themeFolder.GetFilesAsync();
|
||||
|
||||
var themeMetadatas = allFiles.Where(a => a.FileType == ".json");
|
||||
|
||||
foreach (var theme in themeMetadatas)
|
||||
{
|
||||
var metadata = await GetCustomMetadataAsync(theme).ConfigureAwait(false);
|
||||
|
||||
if (metadata == null) continue;
|
||||
|
||||
results.Add(metadata);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private async Task<CustomThemeMetadata> GetCustomMetadataAsync(IStorageFile file)
|
||||
{
|
||||
var fileContent = await FileIO.ReadTextAsync(file);
|
||||
|
||||
return JsonSerializer.Deserialize(fileContent, DomainModelsJsonContext.Default.CustomThemeMetadata);
|
||||
}
|
||||
|
||||
public string GetSystemAccentColorHex()
|
||||
=> uiSettings.GetColorValue(UIColorType.Accent).ToHex();
|
||||
|
||||
public List<string> GetAvailableAccountColors()
|
||||
{
|
||||
return new List<string>()
|
||||
{
|
||||
"#e74c3c",
|
||||
"#c0392b",
|
||||
"#e53935",
|
||||
"#d81b60",
|
||||
|
||||
// Pinks
|
||||
"#e91e63",
|
||||
"#ec407a",
|
||||
"#ff4081",
|
||||
|
||||
// Purples
|
||||
"#9b59b6",
|
||||
"#8e44ad",
|
||||
"#673ab7",
|
||||
|
||||
// Blues
|
||||
"#3498db",
|
||||
"#2980b9",
|
||||
"#2196f3",
|
||||
"#03a9f4",
|
||||
"#00bcd4",
|
||||
|
||||
// Teals
|
||||
"#009688",
|
||||
"#1abc9c",
|
||||
"#16a085",
|
||||
|
||||
// Greens
|
||||
"#2ecc71",
|
||||
"#27ae60",
|
||||
"#4caf50",
|
||||
"#8bc34a",
|
||||
|
||||
// Yellows & Oranges
|
||||
"#f1c40f",
|
||||
"#f39c12",
|
||||
"#ff9800",
|
||||
"#ff5722",
|
||||
|
||||
// Browns
|
||||
"#795548",
|
||||
"#a0522d",
|
||||
|
||||
// Grays
|
||||
"#9e9e9e",
|
||||
"#607d8b",
|
||||
"#34495e",
|
||||
"#2c3e50",
|
||||
};
|
||||
}
|
||||
|
||||
public List<BackdropTypeWrapper> GetAvailableBackdropTypes()
|
||||
{
|
||||
return new List<BackdropTypeWrapper>
|
||||
{
|
||||
new BackdropTypeWrapper(WindowBackdropType.None, "None"),
|
||||
new BackdropTypeWrapper(WindowBackdropType.Mica, "Mica"),
|
||||
new BackdropTypeWrapper(WindowBackdropType.MicaAlt, "Mica Alt"),
|
||||
new BackdropTypeWrapper(WindowBackdropType.DesktopAcrylic, "Desktop Acrylic"),
|
||||
new BackdropTypeWrapper(WindowBackdropType.AcrylicBase, "Acrylic Base"),
|
||||
new BackdropTypeWrapper(WindowBackdropType.AcrylicThin, "Acrylic Thin")
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.Toolkit.Uwp.Notifications;
|
||||
using Serilog;
|
||||
using Windows.Data.Xml.Dom;
|
||||
using Windows.UI.Notifications;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities.Mail;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Messaging.UI;
|
||||
|
||||
namespace Wino.Core.WinUI.Services;
|
||||
|
||||
public class NotificationBuilder : INotificationBuilder
|
||||
{
|
||||
private readonly IAccountService _accountService;
|
||||
private readonly IFolderService _folderService;
|
||||
private readonly IMailService _mailService;
|
||||
private readonly IThumbnailService _thumbnailService;
|
||||
|
||||
public NotificationBuilder(IAccountService accountService,
|
||||
IFolderService folderService,
|
||||
IMailService mailService,
|
||||
IThumbnailService thumbnailService)
|
||||
{
|
||||
_accountService = accountService;
|
||||
_folderService = folderService;
|
||||
_mailService = mailService;
|
||||
_thumbnailService = thumbnailService;
|
||||
|
||||
WeakReferenceMessenger.Default.Register<MailReadStatusChanged>(this, (r, msg) =>
|
||||
{
|
||||
RemoveNotification(msg.UniqueId);
|
||||
});
|
||||
}
|
||||
|
||||
public async Task CreateNotificationsAsync(IEnumerable<MailCopy> downloadedMailItems)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Filter mails to only include Inbox folder items
|
||||
var inboxMailItems = new List<MailCopy>();
|
||||
|
||||
foreach (var item in downloadedMailItems)
|
||||
{
|
||||
var mailItem = await _mailService.GetSingleMailItemAsync(item.UniqueId);
|
||||
|
||||
//if (mailItem == null || mailItem.AssignedFolder == null)
|
||||
// continue;
|
||||
|
||||
//// Only create notifications for Inbox folder mails
|
||||
//if (mailItem.AssignedFolder.SpecialFolderType != SpecialFolderType.Inbox)
|
||||
// continue;
|
||||
|
||||
//// Skip folders with synchronization disabled
|
||||
//if (!mailItem.AssignedFolder.IsSynchronizationEnabled)
|
||||
// continue;
|
||||
|
||||
//// Skip already read mails
|
||||
//if (mailItem.IsRead)
|
||||
//{
|
||||
// RemoveNotification(mailItem.UniqueId);
|
||||
// continue;
|
||||
//}
|
||||
|
||||
inboxMailItems.Add(mailItem);
|
||||
}
|
||||
|
||||
var mailCount = inboxMailItems.Count;
|
||||
|
||||
if (mailCount == 0)
|
||||
return;
|
||||
|
||||
// If there are more than 3 mails, just display 1 general toast.
|
||||
if (mailCount > 3)
|
||||
{
|
||||
var builder = new ToastContentBuilder();
|
||||
builder.SetToastScenario(ToastScenario.Default);
|
||||
|
||||
builder.AddText(Translator.Notifications_MultipleNotificationsTitle);
|
||||
builder.AddText(string.Format(Translator.Notifications_MultipleNotificationsMessage, mailCount));
|
||||
|
||||
builder.AddButton(GetDismissButton());
|
||||
builder.AddAudio(new ToastAudio()
|
||||
{
|
||||
Src = new Uri("ms-winsoundevent:Notification.Mail")
|
||||
});
|
||||
|
||||
builder.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var mailItem in inboxMailItems)
|
||||
{
|
||||
await CreateSingleNotificationAsync(mailItem);
|
||||
}
|
||||
|
||||
await UpdateTaskbarIconBadgeAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Failed to create notifications.");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CreateSingleNotificationAsync(MailCopy mailItem)
|
||||
{
|
||||
var builder = new ToastContentBuilder();
|
||||
builder.SetToastScenario(ToastScenario.Default);
|
||||
|
||||
var avatarThumbnail = await _thumbnailService.GetThumbnailAsync(mailItem.FromAddress, awaitLoad: true);
|
||||
if (!string.IsNullOrEmpty(avatarThumbnail))
|
||||
{
|
||||
var tempFile = await Windows.Storage.ApplicationData.Current.TemporaryFolder.CreateFileAsync($"{Guid.NewGuid()}.png", Windows.Storage.CreationCollisionOption.ReplaceExisting);
|
||||
await using (var stream = await tempFile.OpenStreamForWriteAsync())
|
||||
{
|
||||
var bytes = Convert.FromBase64String(avatarThumbnail);
|
||||
await stream.WriteAsync(bytes);
|
||||
}
|
||||
builder.AddAppLogoOverride(new Uri($"ms-appdata:///temp/{tempFile.Name}"), hintCrop: ToastGenericAppLogoCrop.Default);
|
||||
}
|
||||
|
||||
// Override system notification timestamp with received date of the mail.
|
||||
builder.AddCustomTimeStamp(mailItem.CreationDate.ToLocalTime());
|
||||
|
||||
builder.AddText(mailItem.FromName);
|
||||
builder.AddText(mailItem.Subject);
|
||||
builder.AddText(mailItem.PreviewText);
|
||||
|
||||
builder.AddArgument(Constants.ToastMailUniqueIdKey, mailItem.UniqueId.ToString());
|
||||
builder.AddArgument(Constants.ToastActionKey, MailOperation.Navigate);
|
||||
|
||||
builder.AddButton(GetMarkAsReadButton(mailItem.UniqueId));
|
||||
builder.AddButton(GetDeleteButton(mailItem.UniqueId));
|
||||
builder.AddButton(GetArchiveButton(mailItem.UniqueId));
|
||||
builder.AddAudio(new ToastAudio()
|
||||
{
|
||||
Src = new Uri("ms-winsoundevent:Notification.Mail")
|
||||
});
|
||||
|
||||
// Use UniqueId as tag to allow removal
|
||||
builder.Show(toast => toast.Tag = mailItem.UniqueId.ToString());
|
||||
}
|
||||
|
||||
private ToastButton GetDismissButton()
|
||||
=> new ToastButton()
|
||||
.SetDismissActivation()
|
||||
.SetImageUri(new Uri("ms-appx:///Assets/NotificationIcons/dismiss.png"));
|
||||
|
||||
private static ToastButton GetArchiveButton(Guid mailUniqueId)
|
||||
=> new ToastButton()
|
||||
.SetContent(Translator.MailOperation_Archive)
|
||||
.SetImageUri(new Uri("ms-appx:///Assets/NotificationIcons/archive.png"))
|
||||
.AddArgument(Constants.ToastMailUniqueIdKey, mailUniqueId.ToString())
|
||||
.AddArgument(Constants.ToastActionKey, MailOperation.Archive)
|
||||
.SetBackgroundActivation();
|
||||
|
||||
private ToastButton GetDeleteButton(Guid mailUniqueId)
|
||||
=> new ToastButton()
|
||||
.SetContent(Translator.MailOperation_Delete)
|
||||
.SetImageUri(new Uri("ms-appx:///Assets/NotificationIcons/delete.png"))
|
||||
.AddArgument(Constants.ToastMailUniqueIdKey, mailUniqueId.ToString())
|
||||
.AddArgument(Constants.ToastActionKey, MailOperation.SoftDelete)
|
||||
.SetBackgroundActivation();
|
||||
|
||||
private static ToastButton GetMarkAsReadButton(Guid mailUniqueId)
|
||||
=> new ToastButton()
|
||||
.SetContent(Translator.MailOperation_MarkAsRead)
|
||||
.SetImageUri(new System.Uri("ms-appx:///Assets/NotificationIcons/markread.png"))
|
||||
.AddArgument(Constants.ToastMailUniqueIdKey, mailUniqueId.ToString())
|
||||
.AddArgument(Constants.ToastActionKey, MailOperation.MarkAsRead)
|
||||
.SetBackgroundActivation();
|
||||
|
||||
public async Task UpdateTaskbarIconBadgeAsync()
|
||||
{
|
||||
int totalUnreadCount = 0;
|
||||
|
||||
try
|
||||
{
|
||||
var badgeUpdater = BadgeUpdateManager.CreateBadgeUpdaterForApplication();
|
||||
var accounts = await _accountService.GetAccountsAsync();
|
||||
|
||||
foreach (var account in accounts)
|
||||
{
|
||||
if (!account.Preferences.IsTaskbarBadgeEnabled) continue;
|
||||
|
||||
var accountInbox = await _folderService.GetSpecialFolderByAccountIdAsync(account.Id, SpecialFolderType.Inbox);
|
||||
|
||||
if (accountInbox == null)
|
||||
continue;
|
||||
|
||||
var inboxUnreadCount = await _folderService.GetFolderNotificationBadgeAsync(accountInbox.Id);
|
||||
|
||||
totalUnreadCount += inboxUnreadCount;
|
||||
}
|
||||
|
||||
if (totalUnreadCount > 0)
|
||||
{
|
||||
// Get the blank badge XML payload for a badge number
|
||||
XmlDocument badgeXml = BadgeUpdateManager.GetTemplateContent(BadgeTemplateType.BadgeNumber);
|
||||
|
||||
// Set the value of the badge in the XML to our number
|
||||
XmlElement badgeElement = badgeXml.SelectSingleNode("/badge") as XmlElement;
|
||||
badgeElement.SetAttribute("value", totalUnreadCount.ToString());
|
||||
|
||||
// Create the badge notification
|
||||
BadgeNotification badge = new BadgeNotification(badgeXml);
|
||||
|
||||
// And update the badge
|
||||
badgeUpdater.Update(badge);
|
||||
}
|
||||
else
|
||||
badgeUpdater.Clear();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Error while updating taskbar badge.");
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveNotification(Guid mailUniqueId)
|
||||
{
|
||||
try
|
||||
{
|
||||
ToastNotificationManager.History.Remove(mailUniqueId.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, $"Failed to remove notification for mail {mailUniqueId}");
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateAttentionRequiredNotification(MailAccount account)
|
||||
{
|
||||
var builder = new ToastContentBuilder();
|
||||
builder.SetToastScenario(ToastScenario.Default);
|
||||
|
||||
builder.AddText(Translator.Exception_AccountNeedsAttention_Title);
|
||||
builder.AddText(string.Format(Translator.Exception_AccountNeedsAttention_Message, account.Name));
|
||||
|
||||
builder.AddButton(GetDismissButton());
|
||||
|
||||
builder.AddArgument(Constants.ToastMailAccountIdKey, account.Id.ToString());
|
||||
builder.AddButton(new ToastButton().SetContent(Translator.Buttons_FixAccount));
|
||||
builder.Show();
|
||||
}
|
||||
}
|
||||