1 Commits

Author SHA1 Message Date
google-labs-jules[bot]
a1463dfeb9 Output:
Fix: Correct print scaling for Win2D PDF printing

Issue:
When you're printing pages using Win2D, especially when dealing with PDF documents that are rendered to CanvasBitmaps, you might run into some problems if your Windows display scaling isn't set to 100%. You might find that the edges of your printed PDF page are cut off, or the content might look like it's spilling out of the paper boundaries.

Cause:
The problem was happening because a part of the code, `PdfDocument.GetPage().RenderToStreamAsync()`, was being used without specifying certain rendering options (`PdfPageRenderOptions`). This meant the PDF page was being turned into an image stream using a default resolution (probably assuming 96 DPI for the PDF's original size) and wasn't taking into account the printer's actual DPI or your system's display scaling factor (`RawPixelsPerViewPixel`). Because of this, the `CanvasBitmap` created from this stream had pixel dimensions that didn't accurately match the intended physical size on paper when display scaling was active. This led to an incorrect layout by `CanvasPrintDocument`.

Solution:
I've made changes to the `LoadPDFPageBitmapsAsync` method in `Wino.Core.UWP/Services/PrintService.cs` to address this. Here's what I did:
1. I now get the printer's DPI from the `CanvasPrintDocument` (`sender.Dpi`).
2. I also get your current system display scaling factor (`DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel`).
3. For each page in your PDF, I calculate the target pixel dimensions needed to print the page at its correct physical size, using the printer's DPI.
4. Then, I figure out the necessary `DestinationWidth` and `DestinationHeight` (in DIPs) for `PdfPageRenderOptions` by dividing those target pixel dimensions by the `rawPixelsPerViewPixel`.
5. Finally, I call `PdfPage.RenderToStreamAsync()` using these calculated options.

This makes sure that the `CanvasBitmap` objects are created with pixel dimensions that are right for the printer's resolution and are correctly scaled according to your system's display settings. I ran some checks by simulating how this would work with display scaling at 100%, 125%, and 150%, and it confirmed that the calculations are now correct.
2025-05-20 18:48:21 +00:00
65 changed files with 1104 additions and 739 deletions

View File

@@ -19,7 +19,6 @@
<PackageVersion Include="CommunityToolkit.Uwp.Extensions" Version="8.2.250402" /> <PackageVersion Include="CommunityToolkit.Uwp.Extensions" Version="8.2.250402" />
<PackageVersion Include="CommunityToolkit.Uwp.Controls.Primitives" Version="8.2.250129-preview2" /> <PackageVersion Include="CommunityToolkit.Uwp.Controls.Primitives" Version="8.2.250129-preview2" />
<PackageVersion Include="EmailValidation" Version="1.3.0" /> <PackageVersion Include="EmailValidation" Version="1.3.0" />
<PackageVersion Include="gravatar-dotnet" Version="0.1.3" />
<PackageVersion Include="HtmlAgilityPack" Version="1.12.0" /> <PackageVersion Include="HtmlAgilityPack" Version="1.12.0" />
<PackageVersion Include="Ical.Net" Version="4.3.1" /> <PackageVersion Include="Ical.Net" Version="4.3.1" />
<PackageVersion Include="IsExternalInit" Version="1.0.3" /> <PackageVersion Include="IsExternalInit" Version="1.0.3" />

308
Wino.Calendar.sln Normal file
View File

@@ -0,0 +1,308 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.12.35424.110
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Core.Domain", "Wino.Core.Domain\Wino.Core.Domain.csproj", "{814400B6-5A05-4596-B451-3A116A147DC1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Core.UWP", "Wino.Core.UWP\Wino.Core.UWP.csproj", "{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Core.ViewModels", "Wino.Core.ViewModels\Wino.Core.ViewModels.csproj", "{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Messaging", "Wino.Messages\Wino.Messaging.csproj", "{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Server", "Wino.Server\Wino.Server.csproj", "{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Core", "Wino.Core\Wino.Core.csproj", "{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Calendar", "Wino.Calendar\Wino.Calendar.csproj", "{600F4979-DB7E-409D-B7DA-B60BE4C55C35}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.SourceGenerators", "Wino.SourceGenerators\Wino.SourceGenerators.csproj", "{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}"
EndProject
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Wino.Calendar.Packaging", "Wino.Calendar.Packaging\Wino.Calendar.Packaging.wapproj", "{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Calendar.ViewModels", "Wino.Calendar.ViewModels\Wino.Calendar.ViewModels.csproj", "{CF850F8C-5042-4376-9CBA-C8F2BB554083}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Services", "Wino.Services\Wino.Services.csproj", "{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Authentication", "Wino.Authentication\Wino.Authentication.csproj", "{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{814400B6-5A05-4596-B451-3A116A147DC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{814400B6-5A05-4596-B451-3A116A147DC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{814400B6-5A05-4596-B451-3A116A147DC1}.Debug|ARM.ActiveCfg = Debug|Any CPU
{814400B6-5A05-4596-B451-3A116A147DC1}.Debug|ARM.Build.0 = Debug|Any CPU
{814400B6-5A05-4596-B451-3A116A147DC1}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{814400B6-5A05-4596-B451-3A116A147DC1}.Debug|ARM64.Build.0 = Debug|Any CPU
{814400B6-5A05-4596-B451-3A116A147DC1}.Debug|x64.ActiveCfg = Debug|x64
{814400B6-5A05-4596-B451-3A116A147DC1}.Debug|x64.Build.0 = Debug|x64
{814400B6-5A05-4596-B451-3A116A147DC1}.Debug|x86.ActiveCfg = Debug|x86
{814400B6-5A05-4596-B451-3A116A147DC1}.Debug|x86.Build.0 = Debug|x86
{814400B6-5A05-4596-B451-3A116A147DC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{814400B6-5A05-4596-B451-3A116A147DC1}.Release|Any CPU.Build.0 = Release|Any CPU
{814400B6-5A05-4596-B451-3A116A147DC1}.Release|ARM.ActiveCfg = Release|Any CPU
{814400B6-5A05-4596-B451-3A116A147DC1}.Release|ARM.Build.0 = Release|Any CPU
{814400B6-5A05-4596-B451-3A116A147DC1}.Release|ARM64.ActiveCfg = Release|Any CPU
{814400B6-5A05-4596-B451-3A116A147DC1}.Release|ARM64.Build.0 = Release|Any CPU
{814400B6-5A05-4596-B451-3A116A147DC1}.Release|x64.ActiveCfg = Release|x64
{814400B6-5A05-4596-B451-3A116A147DC1}.Release|x64.Build.0 = Release|x64
{814400B6-5A05-4596-B451-3A116A147DC1}.Release|x86.ActiveCfg = Release|x86
{814400B6-5A05-4596-B451-3A116A147DC1}.Release|x86.Build.0 = Release|x86
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|ARM.ActiveCfg = Debug|Any CPU
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|ARM.Build.0 = Debug|Any CPU
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|ARM64.ActiveCfg = Debug|ARM64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|ARM64.Build.0 = Debug|ARM64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|x64.ActiveCfg = Debug|x64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|x64.Build.0 = Debug|x64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|x86.ActiveCfg = Debug|x86
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|x86.Build.0 = Debug|x86
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|Any CPU.Build.0 = Release|Any CPU
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|ARM.ActiveCfg = Release|Any CPU
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|ARM.Build.0 = Release|Any CPU
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|ARM64.ActiveCfg = Release|ARM64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|ARM64.Build.0 = Release|ARM64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|x64.ActiveCfg = Release|x64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|x64.Build.0 = Release|x64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|x86.ActiveCfg = Release|x86
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|x86.Build.0 = Release|x86
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Debug|ARM.ActiveCfg = Debug|Any CPU
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Debug|ARM.Build.0 = Debug|Any CPU
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Debug|ARM64.Build.0 = Debug|Any CPU
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Debug|x64.ActiveCfg = Debug|x64
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Debug|x64.Build.0 = Debug|x64
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Debug|x86.ActiveCfg = Debug|x86
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Debug|x86.Build.0 = Debug|x86
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Release|Any CPU.Build.0 = Release|Any CPU
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Release|ARM.ActiveCfg = Release|Any CPU
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Release|ARM.Build.0 = Release|Any CPU
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Release|ARM64.ActiveCfg = Release|Any CPU
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Release|ARM64.Build.0 = Release|Any CPU
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Release|x64.ActiveCfg = Release|x64
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Release|x64.Build.0 = Release|x64
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Release|x86.ActiveCfg = Release|x86
{510CD96C-B3FF-4EC9-A67B-845C842E6BEC}.Release|x86.Build.0 = Release|x86
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Debug|ARM.ActiveCfg = Debug|Any CPU
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Debug|ARM.Build.0 = Debug|Any CPU
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Debug|ARM64.Build.0 = Debug|Any CPU
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Debug|x64.ActiveCfg = Debug|x64
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Debug|x64.Build.0 = Debug|x64
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Debug|x86.ActiveCfg = Debug|x86
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Debug|x86.Build.0 = Debug|x86
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Release|Any CPU.Build.0 = Release|Any CPU
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Release|ARM.ActiveCfg = Release|Any CPU
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Release|ARM.Build.0 = Release|Any CPU
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Release|ARM64.ActiveCfg = Release|Any CPU
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Release|ARM64.Build.0 = Release|Any CPU
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Release|x64.ActiveCfg = Release|x64
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Release|x64.Build.0 = Release|x64
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Release|x86.ActiveCfg = Release|x86
{AB588CFD-4B0C-4A1F-B711-1999E3D092D0}.Release|x86.Build.0 = Release|x86
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Debug|Any CPU.ActiveCfg = Debug|x64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Debug|Any CPU.Build.0 = Debug|x64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Debug|ARM.ActiveCfg = Debug|x64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Debug|ARM.Build.0 = Debug|x64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Debug|ARM64.ActiveCfg = Debug|ARM64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Debug|ARM64.Build.0 = Debug|ARM64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Debug|x64.ActiveCfg = Debug|x64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Debug|x64.Build.0 = Debug|x64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Debug|x86.ActiveCfg = Debug|x86
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Debug|x86.Build.0 = Debug|x86
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Release|Any CPU.ActiveCfg = Release|x64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Release|Any CPU.Build.0 = Release|x64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Release|ARM.ActiveCfg = Release|x64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Release|ARM.Build.0 = Release|x64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Release|ARM64.ActiveCfg = Release|ARM64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Release|ARM64.Build.0 = Release|ARM64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Release|x64.ActiveCfg = Release|x64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Release|x64.Build.0 = Release|x64
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Release|x86.ActiveCfg = Release|x86
{92DA33FC-9252-40C5-BF71-67ACB0B56F2B}.Release|x86.Build.0 = Release|x86
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Debug|ARM.ActiveCfg = Debug|Any CPU
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Debug|ARM.Build.0 = Debug|Any CPU
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Debug|ARM64.Build.0 = Debug|Any CPU
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Debug|x64.ActiveCfg = Debug|x64
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Debug|x64.Build.0 = Debug|x64
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Debug|x86.ActiveCfg = Debug|x86
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Debug|x86.Build.0 = Debug|x86
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Release|Any CPU.Build.0 = Release|Any CPU
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Release|ARM.ActiveCfg = Release|Any CPU
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Release|ARM.Build.0 = Release|Any CPU
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Release|ARM64.ActiveCfg = Release|Any CPU
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Release|ARM64.Build.0 = Release|Any CPU
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Release|x64.ActiveCfg = Release|x64
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Release|x64.Build.0 = Release|x64
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Release|x86.ActiveCfg = Release|x86
{87FFCBF4-DC17-4F09-90D6-102CF4C72BAF}.Release|x86.Build.0 = Release|x86
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|Any CPU.ActiveCfg = Debug|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|Any CPU.Build.0 = Debug|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|Any CPU.Deploy.0 = Debug|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|ARM.ActiveCfg = Debug|ARM
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|ARM.Build.0 = Debug|ARM
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|ARM.Deploy.0 = Debug|ARM
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|ARM64.ActiveCfg = Debug|ARM64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|ARM64.Build.0 = Debug|ARM64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|ARM64.Deploy.0 = Debug|ARM64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|x64.ActiveCfg = Debug|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|x64.Build.0 = Debug|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|x64.Deploy.0 = Debug|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|x86.ActiveCfg = Debug|x86
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|x86.Build.0 = Debug|x86
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|x86.Deploy.0 = Debug|x86
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|Any CPU.ActiveCfg = Release|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|Any CPU.Build.0 = Release|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|Any CPU.Deploy.0 = Release|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|ARM.ActiveCfg = Release|ARM
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|ARM.Build.0 = Release|ARM
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|ARM.Deploy.0 = Release|ARM
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|ARM64.ActiveCfg = Release|ARM64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|ARM64.Build.0 = Release|ARM64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|ARM64.Deploy.0 = Release|ARM64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|x64.ActiveCfg = Release|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|x64.Build.0 = Release|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|x64.Deploy.0 = Release|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|x86.ActiveCfg = Release|x86
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|x86.Build.0 = Release|x86
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|x86.Deploy.0 = Release|x86
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Debug|ARM.ActiveCfg = Debug|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Debug|ARM.Build.0 = Debug|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Debug|ARM64.Build.0 = Debug|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Debug|x64.ActiveCfg = Debug|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Debug|x64.Build.0 = Debug|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Debug|x86.ActiveCfg = Debug|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Debug|x86.Build.0 = Debug|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Release|Any CPU.Build.0 = Release|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Release|ARM.ActiveCfg = Release|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Release|ARM.Build.0 = Release|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Release|ARM64.ActiveCfg = Release|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Release|ARM64.Build.0 = Release|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Release|x64.ActiveCfg = Release|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Release|x64.Build.0 = Release|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Release|x86.ActiveCfg = Release|Any CPU
{8A7EB697-D722-4E0F-B20E-9FC88373ADB5}.Release|x86.Build.0 = Release|Any CPU
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|ARM.ActiveCfg = Debug|ARM
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|ARM.Build.0 = Debug|ARM
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|ARM.Deploy.0 = Debug|ARM
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|ARM64.ActiveCfg = Debug|ARM64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|ARM64.Build.0 = Debug|ARM64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|ARM64.Deploy.0 = Debug|ARM64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|x64.ActiveCfg = Debug|x64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|x64.Build.0 = Debug|x64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|x64.Deploy.0 = Debug|x64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|x86.ActiveCfg = Debug|x86
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|x86.Build.0 = Debug|x86
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|x86.Deploy.0 = Debug|x86
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|Any CPU.Build.0 = Release|Any CPU
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|Any CPU.Deploy.0 = Release|Any CPU
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|ARM.ActiveCfg = Release|ARM
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|ARM.Build.0 = Release|ARM
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|ARM.Deploy.0 = Release|ARM
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|ARM64.ActiveCfg = Release|ARM64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|ARM64.Build.0 = Release|ARM64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|ARM64.Deploy.0 = Release|ARM64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x64.ActiveCfg = Release|x64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x64.Build.0 = Release|x64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x64.Deploy.0 = Release|x64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x86.ActiveCfg = Release|x86
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x86.Build.0 = Release|x86
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x86.Deploy.0 = Release|x86
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Debug|ARM.ActiveCfg = Debug|Any CPU
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Debug|ARM.Build.0 = Debug|Any CPU
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Debug|ARM64.Build.0 = Debug|Any CPU
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Debug|x64.ActiveCfg = Debug|x64
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Debug|x64.Build.0 = Debug|x64
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Debug|x86.ActiveCfg = Debug|x86
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Debug|x86.Build.0 = Debug|x86
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Release|Any CPU.Build.0 = Release|Any CPU
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Release|ARM.ActiveCfg = Release|Any CPU
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Release|ARM.Build.0 = Release|Any CPU
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Release|ARM64.ActiveCfg = Release|Any CPU
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Release|ARM64.Build.0 = Release|Any CPU
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Release|x64.ActiveCfg = Release|x64
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Release|x64.Build.0 = Release|x64
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Release|x86.ActiveCfg = Release|x86
{CF850F8C-5042-4376-9CBA-C8F2BB554083}.Release|x86.Build.0 = Release|x86
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Debug|ARM.ActiveCfg = Debug|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Debug|ARM.Build.0 = Debug|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Debug|ARM64.Build.0 = Debug|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Debug|x64.ActiveCfg = Debug|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Debug|x64.Build.0 = Debug|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Debug|x86.ActiveCfg = Debug|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Debug|x86.Build.0 = Debug|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Release|Any CPU.Build.0 = Release|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Release|ARM.ActiveCfg = Release|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Release|ARM.Build.0 = Release|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Release|ARM64.ActiveCfg = Release|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Release|ARM64.Build.0 = Release|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Release|x64.ActiveCfg = Release|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Release|x64.Build.0 = Release|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Release|x86.ActiveCfg = Release|Any CPU
{BBA49030-7277-48CF-B2FE-3D01CB6B6C81}.Release|x86.Build.0 = Release|Any CPU
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Debug|Any CPU.Build.0 = Debug|Any CPU
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Debug|ARM.ActiveCfg = Debug|Any CPU
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Debug|ARM.Build.0 = Debug|Any CPU
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Debug|ARM64.Build.0 = Debug|Any CPU
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Debug|x64.ActiveCfg = Debug|x64
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Debug|x64.Build.0 = Debug|x64
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Debug|x86.ActiveCfg = Debug|x86
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Debug|x86.Build.0 = Debug|x86
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Release|Any CPU.ActiveCfg = Release|Any CPU
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Release|Any CPU.Build.0 = Release|Any CPU
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Release|ARM.ActiveCfg = Release|Any CPU
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Release|ARM.Build.0 = Release|Any CPU
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Release|ARM64.ActiveCfg = Release|Any CPU
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Release|ARM64.Build.0 = Release|Any CPU
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Release|x64.ActiveCfg = Release|x64
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Release|x64.Build.0 = Release|x64
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Release|x86.ActiveCfg = Release|x86
{16A979C2-F308-464F-9B2A-0AF8ED5EDB43}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -1,14 +0,0 @@
using System;
using SQLite;
namespace Wino.Core.Domain.Entities.Shared;
public class Thumbnail
{
[PrimaryKey]
public string Domain { get; set; }
public string Gravatar { get; set; }
public string Favicon { get; set; }
public DateTime LastUpdated { get; set; }
}

View File

@@ -170,5 +170,4 @@ public interface IAccountService
/// <param name="accountId">Account id.</param> /// <param name="accountId">Account id.</param>
/// <returns>Whether the notifications should be created after sync or not.</returns> /// <returns>Whether the notifications should be created after sync or not.</returns>
Task<bool> IsNotificationsEnabled(Guid accountId); Task<bool> IsNotificationsEnabled(Guid accountId);
Task UpdateAccountCustomServerInformationAsync(CustomServerInformation customServerInformation);
} }

View File

@@ -1,12 +1,11 @@
using System; using System;
using System.ComponentModel;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Calendar; using Wino.Core.Domain.Models.Calendar;
using Wino.Core.Domain.Models.Reader; using Wino.Core.Domain.Models.Reader;
namespace Wino.Core.Domain.Interfaces; namespace Wino.Core.Domain.Interfaces;
public interface IPreferencesService: INotifyPropertyChanged public interface IPreferencesService
{ {
/// <summary> /// <summary>
/// When any of the preferences are changed. /// When any of the preferences are changed.
@@ -189,21 +188,6 @@ public interface IPreferencesService: INotifyPropertyChanged
/// </summary> /// </summary>
bool IsMailListActionBarEnabled { get; set; } bool IsMailListActionBarEnabled { get; set; }
/// <summary>
/// Setting: Whether the mail rendering page will show the action labels
/// </summary>
bool IsShowActionLabelsEnabled { get; set; }
/// <summary>
/// Setting: Enable/disable Gravatar for sender avatars.
/// </summary>
bool IsGravatarEnabled { get; set; }
/// <summary>
/// Setting: Enable/disable Favicon for sender avatars.
/// </summary>
bool IsFaviconEnabled { get; set; }
#endregion #endregion
#region Calendar #region Calendar

View File

@@ -1,20 +0,0 @@
using System.Threading.Tasks;
namespace Wino.Core.Domain.Interfaces;
public interface IThumbnailService
{
/// <summary>
/// Clears the thumbnail cache.
/// </summary>
Task ClearCache();
/// <summary>
/// Gets thumbnail
/// </summary>
/// <param name="email">Address for thumbnail</param>
/// <param name="awaitLoad">Force to wait for thumbnail loading.
/// Should be used in non-UI threads or where delay is acceptable
/// </param>
ValueTask<string> GetThumbnailAsync(string email, bool awaitLoad = false);
}

View File

@@ -262,8 +262,6 @@
"IMAPSetupDialog_AccountType": "Account type", "IMAPSetupDialog_AccountType": "Account type",
"IMAPSetupDialog_ValidationSuccess_Title": "Success", "IMAPSetupDialog_ValidationSuccess_Title": "Success",
"IMAPSetupDialog_ValidationSuccess_Message": "Validation successful", "IMAPSetupDialog_ValidationSuccess_Message": "Validation successful",
"IMAPSetupDialog_SaveImapSuccess_Title": "Success",
"IMAPSetupDialog_SaveImapSuccess_Message": "IMAP settings saved successfuly.",
"IMAPSetupDialog_ValidationFailed_Title": "IMAP Server validation failed.", "IMAPSetupDialog_ValidationFailed_Title": "IMAP Server validation failed.",
"IMAPSetupDialog_CertificateAllowanceRequired_Row0": "This server is requesting a SSL handshake to continue. Please confirm the certificate details below.", "IMAPSetupDialog_CertificateAllowanceRequired_Row0": "This server is requesting a SSL handshake to continue. Please confirm the certificate details below.",
"IMAPSetupDialog_CertificateAllowanceRequired_Row1": "Allow the handshake to continue setting up your account.", "IMAPSetupDialog_CertificateAllowanceRequired_Row1": "Allow the handshake to continue setting up your account.",
@@ -521,7 +519,7 @@
"SettingsCustomTheme_Title": "Custom Theme", "SettingsCustomTheme_Title": "Custom Theme",
"SettingsDeleteAccount_Description": "Delete all e-mails and credentials associated with this account.", "SettingsDeleteAccount_Description": "Delete all e-mails and credentials associated with this account.",
"SettingsDeleteAccount_Title": "Delete this account", "SettingsDeleteAccount_Title": "Delete this account",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for comfirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Permanent Delete Protection", "SettingsDeleteProtection_Title": "Permanent Delete Protection",
"SettingsDiagnostics_Description": "For developers", "SettingsDiagnostics_Description": "For developers",
"SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.",
@@ -625,11 +623,6 @@
"SettingsShowPreviewText_Title": "Show Preview Text", "SettingsShowPreviewText_Title": "Show Preview Text",
"SettingsShowSenderPictures_Description": "Hide/show the thumbnail sender pictures.", "SettingsShowSenderPictures_Description": "Hide/show the thumbnail sender pictures.",
"SettingsShowSenderPictures_Title": "Show Sender Avatars", "SettingsShowSenderPictures_Title": "Show Sender Avatars",
"SettingsEnableGravatarAvatars_Title": "Gravatar",
"SettingsEnableGravatarAvatars_Description": "Use gravatar (if available) as sender picture",
"SettingsEnableFavicons_Title": "Domain icons (Favicons)",
"SettingsEnableFavicons_Description": "Use domain favicons (if available) as sender picture",
"SettingsMailList_ClearAvatarsCache_Button": "Clear cached avatars",
"SettingsSignature_AddCustomSignature_Button": "Add signature", "SettingsSignature_AddCustomSignature_Button": "Add signature",
"SettingsSignature_AddCustomSignature_Title": "Add custom signature", "SettingsSignature_AddCustomSignature_Title": "Add custom signature",
"SettingsSignature_DeleteSignature_Title": "Delete signature", "SettingsSignature_DeleteSignature_Title": "Delete signature",
@@ -651,8 +644,6 @@
"SettingsThreads_Title": "Conversation Threading", "SettingsThreads_Title": "Conversation Threading",
"SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.", "SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.",
"SettingsUnlinkAccounts_Title": "Unlink Accounts", "SettingsUnlinkAccounts_Title": "Unlink Accounts",
"SettingsMailRendering_ActionLabels_Title": "Action labels",
"SettingsMailRendering_ActionLabels_Description": "Show action labels.",
"SignatureDeleteDialog_Message": "Are you sure you want to delete \"{0}\" signature?", "SignatureDeleteDialog_Message": "Are you sure you want to delete \"{0}\" signature?",
"SignatureDeleteDialog_Title": "Delete signature", "SignatureDeleteDialog_Title": "Delete signature",
"SignatureEditorDialog_SignatureName_Placeholder": "Name your signature", "SignatureEditorDialog_SignatureName_Placeholder": "Name your signature",

View File

@@ -59,7 +59,7 @@
<Setter Property="ChildrenTransitions"> <Setter Property="ChildrenTransitions">
<Setter.Value> <Setter.Value>
<TransitionCollection> <TransitionCollection>
<EntranceThemeTransition IsStaggeringEnabled="False" /> <EntranceThemeTransition IsStaggeringEnabled="True" />
</TransitionCollection> </TransitionCollection>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@@ -96,19 +96,6 @@
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Style> </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>
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>

View File

@@ -25,7 +25,7 @@ public static class CoreUWPContainerSetup
services.AddSingleton<IPreferencesService, PreferencesService>(); services.AddSingleton<IPreferencesService, PreferencesService>();
services.AddSingleton<IThemeService, ThemeService>(); services.AddSingleton<IThemeService, ThemeService>();
services.AddSingleton<IStatePersistanceService, StatePersistenceService>(); services.AddSingleton<IStatePersistanceService, StatePersistenceService>();
services.AddSingleton<IThumbnailService, ThumbnailService>();
services.AddSingleton<IDialogServiceBase, DialogServiceBase>(); services.AddSingleton<IDialogServiceBase, DialogServiceBase>();
services.AddTransient<IConfigurationService, ConfigurationService>(); services.AddTransient<IConfigurationService, ConfigurationService>();
services.AddTransient<IFileService, FileService>(); services.AddTransient<IFileService, FileService>();

View File

@@ -23,6 +23,6 @@
<StackPanel Spacing="12"> <StackPanel Spacing="12">
<TextBlock x:Name="DialogDescription" TextWrapping="Wrap" /> <TextBlock x:Name="DialogDescription" TextWrapping="Wrap" />
<TextBox x:Name="FolderTextBox" Text="{x:Bind CurrentInput, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> <TextBox x:Name="FolderTextBox" Text="{x:Bind CurrentInput, Mode=TwoWay}" />
</StackPanel> </StackPanel>
</ContentDialog> </ContentDialog>

View File

@@ -45,6 +45,7 @@ public class NativeAppService : INativeAppService
return _mimeMessagesFolder; return _mimeMessagesFolder;
} }
public async Task<string> GetEditorBundlePathAsync() public async Task<string> GetEditorBundlePathAsync()
{ {
if (string.IsNullOrEmpty(_editorBundlePath)) if (string.IsNullOrEmpty(_editorBundlePath))

View File

@@ -11,7 +11,7 @@ using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.MailItem; using Wino.Core.Domain.Models.MailItem;
using System.IO; using Wino.Core.Services;
namespace Wino.Core.UWP.Services; namespace Wino.Core.UWP.Services;
@@ -23,19 +23,16 @@ public class NotificationBuilder : INotificationBuilder
private readonly IAccountService _accountService; private readonly IAccountService _accountService;
private readonly IFolderService _folderService; private readonly IFolderService _folderService;
private readonly IMailService _mailService; private readonly IMailService _mailService;
private readonly IThumbnailService _thumbnailService;
public NotificationBuilder(IUnderlyingThemeService underlyingThemeService, public NotificationBuilder(IUnderlyingThemeService underlyingThemeService,
IAccountService accountService, IAccountService accountService,
IFolderService folderService, IFolderService folderService,
IMailService mailService, IMailService mailService)
IThumbnailService thumbnailService)
{ {
_underlyingThemeService = underlyingThemeService; _underlyingThemeService = underlyingThemeService;
_accountService = accountService; _accountService = accountService;
_folderService = folderService; _folderService = folderService;
_mailService = mailService; _mailService = mailService;
_thumbnailService = thumbnailService;
} }
public async Task CreateNotificationsAsync(Guid inboxFolderId, IEnumerable<IMailItem> downloadedMailItems) public async Task CreateNotificationsAsync(Guid inboxFolderId, IEnumerable<IMailItem> downloadedMailItems)
@@ -86,16 +83,24 @@ public class NotificationBuilder : INotificationBuilder
var builder = new ToastContentBuilder(); var builder = new ToastContentBuilder();
builder.SetToastScenario(ToastScenario.Default); builder.SetToastScenario(ToastScenario.Default);
var avatarThumbnail = await _thumbnailService.GetThumbnailAsync(mailItem.FromAddress, awaitLoad: true); var host = ThumbnailService.GetHost(mailItem.FromAddress);
if (!string.IsNullOrEmpty(avatarThumbnail))
var knownTuple = ThumbnailService.CheckIsKnown(host);
bool isKnown = knownTuple.Item1;
host = knownTuple.Item2;
if (isKnown)
builder.AddAppLogoOverride(new System.Uri(ThumbnailService.GetKnownHostImage(host)), hintCrop: ToastGenericAppLogoCrop.Default);
else
{ {
var tempFile = await Windows.Storage.ApplicationData.Current.TemporaryFolder.CreateFileAsync($"{Guid.NewGuid()}.png", Windows.Storage.CreationCollisionOption.ReplaceExisting); // TODO: https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=toolkit
await using (var stream = await tempFile.OpenStreamForWriteAsync()) // Follow official guides for icons/theme.
{
var bytes = Convert.FromBase64String(avatarThumbnail); bool isOSDarkTheme = _underlyingThemeService.IsUnderlyingThemeDark();
await stream.WriteAsync(bytes); string profileLogoName = isOSDarkTheme ? "profile-dark.png" : "profile-light.png";
}
builder.AddAppLogoOverride(new Uri($"ms-appdata:///temp/{tempFile.Name}"), hintCrop: ToastGenericAppLogoCrop.Default); builder.AddAppLogoOverride(new System.Uri($"ms-appx:///Assets/NotificationIcons/{profileLogoName}"), hintCrop: ToastGenericAppLogoCrop.Circle);
} }
// Override system notification timetamp with received date of the mail. // Override system notification timetamp with received date of the mail.
@@ -109,9 +114,9 @@ public class NotificationBuilder : INotificationBuilder
builder.AddArgument(Constants.ToastMailUniqueIdKey, mailItem.UniqueId.ToString()); builder.AddArgument(Constants.ToastMailUniqueIdKey, mailItem.UniqueId.ToString());
builder.AddArgument(Constants.ToastActionKey, MailOperation.Navigate); builder.AddArgument(Constants.ToastActionKey, MailOperation.Navigate);
builder.AddButton(GetMarkAsReadButton(mailItem.UniqueId)); builder.AddButton(GetMarkedAsRead(mailItem.UniqueId));
builder.AddButton(GetDeleteButton(mailItem.UniqueId)); builder.AddButton(GetDeleteButton(mailItem.UniqueId));
builder.AddButton(GetArchiveButton(mailItem.UniqueId)); builder.AddButton(GetDismissButton());
builder.AddAudio(new ToastAudio() builder.AddAudio(new ToastAudio()
{ {
Src = new Uri("ms-winsoundevent:Notification.Mail") Src = new Uri("ms-winsoundevent:Notification.Mail")
@@ -134,14 +139,6 @@ public class NotificationBuilder : INotificationBuilder
.SetDismissActivation() .SetDismissActivation()
.SetImageUri(new Uri("ms-appx:///Assets/NotificationIcons/dismiss.png")); .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) private ToastButton GetDeleteButton(Guid mailUniqueId)
=> new ToastButton() => new ToastButton()
.SetContent(Translator.MailOperation_Delete) .SetContent(Translator.MailOperation_Delete)
@@ -150,7 +147,7 @@ public class NotificationBuilder : INotificationBuilder
.AddArgument(Constants.ToastActionKey, MailOperation.SoftDelete) .AddArgument(Constants.ToastActionKey, MailOperation.SoftDelete)
.SetBackgroundActivation(); .SetBackgroundActivation();
private static ToastButton GetMarkAsReadButton(Guid mailUniqueId) private ToastButton GetMarkedAsRead(Guid mailUniqueId)
=> new ToastButton() => new ToastButton()
.SetContent(Translator.MailOperation_MarkAsRead) .SetContent(Translator.MailOperation_MarkAsRead)
.SetImageUri(new System.Uri("ms-appx:///Assets/NotificationIcons/markread.png")) .SetImageUri(new System.Uri("ms-appx:///Assets/NotificationIcons/markread.png"))

View File

@@ -13,12 +13,17 @@ using Wino.Services;
namespace Wino.Core.UWP.Services; namespace Wino.Core.UWP.Services;
public class PreferencesService(IConfigurationService configurationService) : ObservableObject, IPreferencesService public class PreferencesService : ObservableObject, IPreferencesService
{ {
private readonly IConfigurationService _configurationService = configurationService; private readonly IConfigurationService _configurationService;
public event EventHandler<string> PreferenceChanged; public event EventHandler<string> PreferenceChanged;
public PreferencesService(IConfigurationService configurationService)
{
_configurationService = configurationService;
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e) protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{ {
base.OnPropertyChanged(e); base.OnPropertyChanged(e);
@@ -74,12 +79,6 @@ public class PreferencesService(IConfigurationService configurationService) : Ob
set => SetPropertyAndSave(nameof(IsMailListActionBarEnabled), value); set => SetPropertyAndSave(nameof(IsMailListActionBarEnabled), value);
} }
public bool IsShowActionLabelsEnabled
{
get => _configurationService.Get(nameof(IsShowActionLabelsEnabled), true);
set => SetPropertyAndSave(nameof(IsShowActionLabelsEnabled), value);
}
public bool IsShowSenderPicturesEnabled public bool IsShowSenderPicturesEnabled
{ {
get => _configurationService.Get(nameof(IsShowSenderPicturesEnabled), true); get => _configurationService.Get(nameof(IsShowSenderPicturesEnabled), true);
@@ -176,18 +175,6 @@ public class PreferencesService(IConfigurationService configurationService) : Ob
set => SetPropertyAndSave(nameof(IsMailkitProtocolLoggerEnabled), value); set => SetPropertyAndSave(nameof(IsMailkitProtocolLoggerEnabled), value);
} }
public bool IsGravatarEnabled
{
get => _configurationService.Get(nameof(IsGravatarEnabled), true);
set => SetPropertyAndSave(nameof(IsGravatarEnabled), value);
}
public bool IsFaviconEnabled
{
get => _configurationService.Get(nameof(IsFaviconEnabled), true);
set => SetPropertyAndSave(nameof(IsFaviconEnabled), value);
}
public Guid? StartupEntityId public Guid? StartupEntityId
{ {
get => _configurationService.Get<Guid?>(nameof(StartupEntityId), null); get => _configurationService.Get<Guid?>(nameof(StartupEntityId), null);

View File

@@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Microsoft.Graphics.Canvas; using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Printing; using Microsoft.Graphics.Canvas.Printing;
using Windows.Data.Pdf; using Windows.Data.Pdf;
using Windows.Graphics.Display;
using Windows.Graphics.Printing; using Windows.Graphics.Printing;
using Windows.Graphics.Printing.OptionDetails; using Windows.Graphics.Printing.OptionDetails;
using Windows.Storage.Streams; using Windows.Storage.Streams;
@@ -135,6 +136,11 @@ public class PrintService : IPrintService
private async void OnDocumentTaskOptionsChanged(CanvasPrintDocument sender, CanvasPrintTaskOptionsChangedEventArgs args) private async void OnDocumentTaskOptionsChanged(CanvasPrintDocument sender, CanvasPrintTaskOptionsChangedEventArgs args)
{ {
System.Diagnostics.Debug.WriteLine("[PrintService] OnDocumentTaskOptionsChanged starting...");
DisplayInformation di = DisplayInformation.GetForCurrentView();
System.Diagnostics.Debug.WriteLine($"[PrintService] DisplayInformation.RawPixelsPerViewPixel: {di.RawPixelsPerViewPixel}");
System.Diagnostics.Debug.WriteLine($"[PrintService] DisplayInformation.LogicalDpi: {di.LogicalDpi}");
var deferral = args.GetDeferral(); var deferral = args.GetDeferral();
try try
@@ -142,6 +148,10 @@ public class PrintService : IPrintService
await LoadPDFPageBitmapsAsync(sender); await LoadPDFPageBitmapsAsync(sender);
var pageDesc = args.PrintTaskOptions.GetPageDescription(1); var pageDesc = args.PrintTaskOptions.GetPageDescription(1);
System.Diagnostics.Debug.WriteLine($"[PrintService] pageDesc.PageSize.Width (DIPs): {pageDesc.PageSize.Width}");
System.Diagnostics.Debug.WriteLine($"[PrintService] pageDesc.PageSize.Height (DIPs): {pageDesc.PageSize.Height}");
System.Diagnostics.Debug.WriteLine($"[PrintService] pageDesc.DpiX: {pageDesc.DpiX}");
System.Diagnostics.Debug.WriteLine($"[PrintService] pageDesc.DpiY: {pageDesc.DpiY}");
var newPageSize = pageDesc.PageSize.ToVector2(); var newPageSize = pageDesc.PageSize.ToVector2();
if (pageSize == newPageSize && pageCount != -1) if (pageSize == newPageSize && pageCount != -1)
@@ -176,6 +186,10 @@ public class PrintService : IPrintService
// Calculate the page count // Calculate the page count
bitmapCount = bitmaps.Count; bitmapCount = bitmaps.Count;
pageCount = (int)Math.Ceiling(bitmapCount / (double)bitmapsPerPage); pageCount = (int)Math.Ceiling(bitmapCount / (double)bitmapsPerPage);
System.Diagnostics.Debug.WriteLine($"[PrintService] Calculated columns: {columns}");
System.Diagnostics.Debug.WriteLine($"[PrintService] Calculated rows: {rows}");
System.Diagnostics.Debug.WriteLine($"[PrintService] Calculated bitmapsPerPage: {bitmapsPerPage}");
System.Diagnostics.Debug.WriteLine($"[PrintService] Calculated pageCount: {pageCount}");
sender.SetPageCount((uint)pageCount); sender.SetPageCount((uint)pageCount);
// Set the preview page to the one that has the item that was currently displayed in the last preview // Set the preview page to the one that has the item that was currently displayed in the last preview
@@ -185,11 +199,31 @@ public class PrintService : IPrintService
{ {
deferral.Complete(); deferral.Complete();
} }
System.Diagnostics.Debug.WriteLine("[PrintService] OnDocumentTaskOptionsChanged finished.");
} }
private async Task LoadPDFPageBitmapsAsync(CanvasPrintDocument sender) private async Task LoadPDFPageBitmapsAsync(CanvasPrintDocument sender)
{ {
System.Diagnostics.Debug.WriteLine("[PrintService] LoadPDFPageBitmapsAsync starting...");
DisplayInformation displayInfo = DisplayInformation.GetForCurrentView();
float rawPixelsPerViewPixel = (float)displayInfo.RawPixelsPerViewPixel;
if (rawPixelsPerViewPixel == 0)
{
System.Diagnostics.Debug.WriteLine($"[PrintService] Warning: RawPixelsPerViewPixel was 0, defaulting to 1.0f");
rawPixelsPerViewPixel = 1.0f; // Sanity check
}
System.Diagnostics.Debug.WriteLine($"[PrintService] DisplayInformation.RawPixelsPerViewPixel: {rawPixelsPerViewPixel}");
System.Diagnostics.Debug.WriteLine($"[PrintService] DisplayInformation.LogicalDpi: {displayInfo.LogicalDpi}");
float printerDpi = sender.Dpi;
if (printerDpi == 0)
{
System.Diagnostics.Debug.WriteLine($"[PrintService] Warning: sender.Dpi (printerDpi) was 0, defaulting to 96.0f");
printerDpi = 96.0f; // Sanity check
}
System.Diagnostics.Debug.WriteLine($"[PrintService] sender.Dpi (CanvasPrintDocument.Dpi, used as PrinterDPI): {printerDpi}");
ClearBitmaps(); ClearBitmaps();
bitmaps ??= new List<CanvasBitmap>(); bitmaps ??= new List<CanvasBitmap>();
@@ -197,10 +231,39 @@ public class PrintService : IPrintService
for (int i = 0; i < pdfDocument.PageCount; i++) for (int i = 0; i < pdfDocument.PageCount; i++)
{ {
var page = pdfDocument.GetPage((uint)i); var page = pdfDocument.GetPage((uint)i);
var stream = new InMemoryRandomAccessStream(); System.Diagnostics.Debug.WriteLine($"[PrintService] Processing page.Index: {page.Index}");
await page.RenderToStreamAsync(stream); System.Diagnostics.Debug.WriteLine($"[PrintService] page.Dimensions.MediaBox.Width (PDF points): {page.Dimensions.MediaBox.Width}");
var bitmap = await CanvasBitmap.LoadAsync(sender, stream); System.Diagnostics.Debug.WriteLine($"[PrintService] page.Dimensions.MediaBox.Height (PDF points): {page.Dimensions.MediaBox.Height}");
bitmaps.Add(bitmap);
double pageWidthInPoints = page.Dimensions.MediaBox.Width;
double pageHeightInPoints = page.Dimensions.MediaBox.Height;
double pageWidthInInches = pageWidthInPoints / 72.0;
double pageHeightInInches = pageHeightInPoints / 72.0;
// Calculate the desired pixel dimensions of the bitmap based on printer DPI
uint targetPixelWidth = (uint)(pageWidthInInches * printerDpi);
uint targetPixelHeight = (uint)(pageHeightInInches * printerDpi);
// Calculate DestinationWidth/Height for PdfPageRenderOptions in DIPs
PdfPageRenderOptions options = new PdfPageRenderOptions();
options.DestinationWidth = (uint)(targetPixelWidth / rawPixelsPerViewPixel);
options.DestinationHeight = (uint)(targetPixelHeight / rawPixelsPerViewPixel);
System.Diagnostics.Debug.WriteLine($"[PrintService] Page {i}, Calculated PdfPageRenderOptions.DestinationWidth (DIPs): {options.DestinationWidth}, DestinationHeight (DIPs): {options.DestinationHeight}");
System.Diagnostics.Debug.WriteLine($"[PrintService] Page {i}, TargetPixelWidth: {targetPixelWidth}, TargetPixelHeight: {targetPixelHeight}");
using (var stream = new InMemoryRandomAccessStream())
{
await page.RenderToStreamAsync(stream, options); // Use the options
var bitmap = await CanvasBitmap.LoadAsync(sender, stream);
System.Diagnostics.Debug.WriteLine($"[PrintService] bitmap.SizeInPixels.Width: {bitmap.SizeInPixels.Width}");
System.Diagnostics.Debug.WriteLine($"[PrintService] bitmap.SizeInPixels.Height: {bitmap.SizeInPixels.Height}");
System.Diagnostics.Debug.WriteLine($"[PrintService] bitmap.Dpi: {bitmap.Dpi}");
bitmaps.Add(bitmap);
}
} }
largestBitmap = Vector2.Zero; largestBitmap = Vector2.Zero;
@@ -210,6 +273,7 @@ public class PrintService : IPrintService
largestBitmap.X = Math.Max(largestBitmap.X, (float)bitmap.Size.Width); largestBitmap.X = Math.Max(largestBitmap.X, (float)bitmap.Size.Width);
largestBitmap.Y = Math.Max(largestBitmap.Y, (float)bitmap.Size.Height); largestBitmap.Y = Math.Max(largestBitmap.Y, (float)bitmap.Size.Height);
} }
System.Diagnostics.Debug.WriteLine("[PrintService] LoadPDFPageBitmapsAsync finished.");
} }
@@ -262,4 +326,153 @@ public class PrintService : IPrintService
} }
} }
} }
// --- START SIMULATION CODE ---
private async Task RunSimulationAsync(float simulatedRawPixelsPerViewPixel, string callingMethodName)
{
// --- Simulate LoadPDFPageBitmapsAsync ---
System.Diagnostics.Debug.WriteLine($"[PrintService] SIMULATING from {callingMethodName} for {simulatedRawPixelsPerViewPixel}");
System.Diagnostics.Debug.WriteLine("[PrintService] LoadPDFPageBitmapsAsync starting...");
// Mock DisplayInformation
float actualRawPixelsPerViewPixel = simulatedRawPixelsPerViewPixel; // Override
if (actualRawPixelsPerViewPixel == 0)
{
System.Diagnostics.Debug.WriteLine($"[PrintService] Warning: actualRawPixelsPerViewPixel was 0, defaulting to 1.0f");
actualRawPixelsPerViewPixel = 1.0f; // Sanity check
}
System.Diagnostics.Debug.WriteLine($"[PrintService] DisplayInformation.RawPixelsPerViewPixel: {actualRawPixelsPerViewPixel}");
// LogicalDpi is not directly used in calculations we are testing, so we can use a placeholder.
System.Diagnostics.Debug.WriteLine($"[PrintService] DisplayInformation.LogicalDpi: 96.0f (Simulated)");
// Mock CanvasPrintDocument sender for DPI
float printerDpi = 300.0f; // As per subtask
System.Diagnostics.Debug.WriteLine($"[PrintService] sender.Dpi (CanvasPrintDocument.Dpi, used as PrinterDPI): {printerDpi}");
// Clear any previous simulation state for bitmaps
// In a real scenario, ClearBitmaps() would be called. Here we just reset relevant fields.
this.bitmaps.Clear(); // Assuming 'bitmaps' is the List<CanvasBitmap>
this.largestBitmap = Vector2.Zero;
// Simulate pdfDocument.PageCount = 1 and loop once
int simulatedPageCount = 1;
for (int i = 0; i < simulatedPageCount; i++)
{
// Mock PdfPage
uint pageIndex = (uint)i;
double pageWidthInPoints = 612.0; // Letter size
double pageHeightInPoints = 792.0; // Letter size
System.Diagnostics.Debug.WriteLine($"[PrintService] Processing page.Index: {pageIndex}");
System.Diagnostics.Debug.WriteLine($"[PrintService] page.Dimensions.MediaBox.Width (PDF points): {pageWidthInPoints}");
System.Diagnostics.Debug.WriteLine($"[PrintService] page.Dimensions.MediaBox.Height (PDF points): {pageHeightInPoints}");
double pageWidthInInches = pageWidthInPoints / 72.0;
double pageHeightInInches = pageHeightInPoints / 72.0;
uint targetPixelWidth = (uint)(pageWidthInInches * printerDpi);
uint targetPixelHeight = (uint)(pageHeightInInches * printerDpi);
PdfPageRenderOptions options = new PdfPageRenderOptions();
options.DestinationWidth = (uint)(targetPixelWidth / actualRawPixelsPerViewPixel);
options.DestinationHeight = (uint)(targetPixelHeight / actualRawPixelsPerViewPixel);
System.Diagnostics.Debug.WriteLine($"[PrintService] Page {i}, Calculated PdfPageRenderOptions.DestinationWidth (DIPs): {options.DestinationWidth}, DestinationHeight (DIPs): {options.DestinationHeight}");
System.Diagnostics.Debug.WriteLine($"[PrintService] Page {i}, TargetPixelWidth: {targetPixelWidth}, TargetPixelHeight: {targetPixelHeight}");
// Mock CanvasBitmap properties (as we can't actually render)
uint mockBitmapSizeInPixelsWidth = targetPixelWidth;
uint mockBitmapSizeInPixelsHeight = targetPixelHeight;
float mockBitmapDpi = printerDpi;
System.Diagnostics.Debug.WriteLine($"[PrintService] bitmap.SizeInPixels.Width: {mockBitmapSizeInPixelsWidth} (Simulated)");
System.Diagnostics.Debug.WriteLine($"[PrintService] bitmap.SizeInPixels.Height: {mockBitmapSizeInPixelsHeight} (Simulated)");
System.Diagnostics.Debug.WriteLine($"[PrintService] bitmap.Dpi: {mockBitmapDpi} (Simulated)");
// Simulate adding to bitmaps list and tracking largest
// We don't add a real CanvasBitmap, just update what's needed for OnDocumentTaskOptionsChanged
this.largestBitmap.X = Math.Max(this.largestBitmap.X, mockBitmapSizeInPixelsWidth);
this.largestBitmap.Y = Math.Max(this.largestBitmap.Y, mockBitmapSizeInPixelsHeight);
// bitmaps.Add(null); // Not adding real bitmaps
}
this.bitmapCount = simulatedPageCount; // Set based on simulation
System.Diagnostics.Debug.WriteLine("[PrintService] LoadPDFPageBitmapsAsync finished.");
// --- Simulate OnDocumentTaskOptionsChanged ---
System.Diagnostics.Debug.WriteLine("[PrintService] OnDocumentTaskOptionsChanged starting...");
// DisplayInformation logs already done in LoadPDFPageBitmapsAsync simulation part
// Mock PageDescription (from PrintTaskOptions)
// For Letter paper (8.5x11 inches) at 300 DPI:
// Pixel size = (8.5*300) x (11*300) = 2550 x 3300 pixels
// DIP size = (PixelSize / rawPixelsPerViewPixel)
float pageDescPageSizeWidth = (2550.0f / actualRawPixelsPerViewPixel);
float pageDescPageSizeHeight = (3300.0f / actualRawPixelsPerViewPixel);
float pageDescDpiX = 300.0f;
float pageDescDpiY = 300.0f;
System.Diagnostics.Debug.WriteLine($"[PrintService] pageDesc.PageSize.Width (DIPs): {pageDescPageSizeWidth} (Simulated)");
System.Diagnostics.Debug.WriteLine($"[PrintService] pageDesc.PageSize.Height (DIPs): {pageDescPageSizeHeight} (Simulated)");
System.Diagnostics.Debug.WriteLine($"[PrintService] pageDesc.DpiX: {pageDescDpiX} (Simulated)");
System.Diagnostics.Debug.WriteLine($"[PrintService] pageDesc.DpiY: {pageDescDpiY} (Simulated)");
this.pageSize = new Vector2(pageDescPageSizeWidth, pageDescPageSizeHeight);
// sender.InvalidatePreview(); // Cannot call
// Calculate the new layout
var printablePageSize = this.pageSize * 0.9f; // Assuming default behavior
this.imagePadding = new Vector2(64, 64); // Default from class
this.cellSize = this.largestBitmap + this.imagePadding;
var cellsPerPage = printablePageSize / this.cellSize;
this.columns = Math.Max(1, (int)Math.Floor(cellsPerPage.X));
this.rows = Math.Max(1, (int)Math.Floor(cellsPerPage.Y));
this.bitmapsPerPage = this.columns * this.rows;
this.pageCount = (int)Math.Ceiling(this.bitmapCount / (double)this.bitmapsPerPage);
System.Diagnostics.Debug.WriteLine($"[PrintService] Calculated columns: {this.columns}");
System.Diagnostics.Debug.WriteLine($"[PrintService] Calculated rows: {this.rows}");
System.Diagnostics.Debug.WriteLine($"[PrintService] Calculated bitmapsPerPage: {this.bitmapsPerPage}");
System.Diagnostics.Debug.WriteLine($"[PrintService] Calculated pageCount: {this.pageCount}");
// sender.SetPageCount((uint)this.pageCount); // Cannot call
System.Diagnostics.Debug.WriteLine("[PrintService] OnDocumentTaskOptionsChanged finished.");
System.Diagnostics.Debug.WriteLine($"[PrintService] SIMULATION END for {simulatedRawPixelsPerViewPixel}");
System.Diagnostics.Debug.WriteLine("---"); // Separator
}
public async Task SimulatePrintScalingAsync()
{
// Temporarily store and clear global state that might interfere
var originalBitmaps = new List<CanvasBitmap>(this.bitmaps);
var originalLargestBitmap = this.largestBitmap;
var originalPageSize = this.pageSize;
var originalCellSize = this.cellSize;
int originalBitmapCount = this.bitmapCount;
int originalColumns = this.columns;
int originalRows = this.rows;
int originalBitmapsPerPage = this.bitmapsPerPage;
int originalPageCount = this.pageCount;
await RunSimulationAsync(1.0f, nameof(SimulatePrintScalingAsync));
await RunSimulationAsync(1.25f, nameof(SimulatePrintScalingAsync));
await RunSimulationAsync(1.5f, nameof(SimulatePrintScalingAsync));
// Restore original state if necessary, though for this task it's just about logs
this.bitmaps = originalBitmaps;
this.largestBitmap = originalLargestBitmap;
this.pageSize = originalPageSize;
this.cellSize = originalCellSize;
this.bitmapCount = originalBitmapCount;
this.columns = originalColumns;
this.rows = originalRows;
this.bitmapsPerPage = originalBitmapsPerPage;
this.pageCount = originalPageCount;
}
// --- END SIMULATION CODE ---
} }

View File

@@ -1,198 +1,63 @@
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Net.Mail; using System.Net.Mail;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Messaging;
using Gravatar;
using Windows.Networking.Connectivity;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
using Wino.Messaging.UI;
using Wino.Services;
namespace Wino.Core.UWP.Services; namespace Wino.Core.UWP.Services;
public class ThumbnailService(IPreferencesService preferencesService, IDatabaseService databaseService) : IThumbnailService public static class ThumbnailService
{ {
private readonly IPreferencesService _preferencesService = preferencesService; private static string[] knownCompanies = new string[]
private readonly IDatabaseService _databaseService = databaseService;
private static readonly HttpClient _httpClient = new();
private bool _isInitialized = false;
private ConcurrentDictionary<string, (string graviton, string favicon)> _cache;
private readonly ConcurrentDictionary<string, Task> _requests = [];
private static readonly List<string> _excludedFaviconDomains = [
"gmail.com",
"outlook.com",
"hotmail.com",
"live.com",
"yahoo.com",
"icloud.com",
"aol.com",
"protonmail.com",
"zoho.com",
"mail.com",
"gmx.com",
"yandex.com",
"yandex.ru",
"tutanota.com",
"mail.ru",
"rediffmail.com"
];
public async ValueTask<string> GetThumbnailAsync(string email, bool awaitLoad = false)
{ {
if (string.IsNullOrWhiteSpace(email)) "microsoft.com", "apple.com", "google.com", "steampowered.com", "airbnb.com", "youtube.com", "uber.com"
return null; };
if (!_preferencesService.IsShowSenderPicturesEnabled) public static bool IsKnown(string mailHost) => !string.IsNullOrEmpty(mailHost) && knownCompanies.Contains(mailHost);
return null;
if (!_isInitialized) public static string GetHost(string address)
{
var thumbnailsList = await _databaseService.Connection.Table<Thumbnail>().ToListAsync();
_cache = new ConcurrentDictionary<string, (string graviton, string favicon)>(
thumbnailsList.ToDictionary(x => x.Domain, x => (x.Gravatar, x.Favicon)));
_isInitialized = true;
}
var sanitizedEmail = email.Trim().ToLowerInvariant();
var (gravatar, favicon) = await GetThumbnailInternal(sanitizedEmail, awaitLoad);
if (_preferencesService.IsGravatarEnabled && !string.IsNullOrEmpty(gravatar))
{
return gravatar;
}
if (_preferencesService.IsFaviconEnabled && !string.IsNullOrEmpty(favicon))
{
return favicon;
}
return null;
}
public async Task ClearCache()
{ {
_cache?.Clear(); if (string.IsNullOrEmpty(address))
_requests.Clear(); return string.Empty;
await _databaseService.Connection.DeleteAllAsync<Thumbnail>();
}
private async ValueTask<(string gravatar, string favicon)> GetThumbnailInternal(string email, bool awaitLoad) if (address.Contains('@'))
{
if (_cache.TryGetValue(email, out var cached))
return cached;
// No network available, skip fetching Gravatar
// Do not cache it, since network can be available later
bool isInternetAvailable = GetIsInternetAvailable();
if (!isInternetAvailable)
return default;
if (!_requests.TryGetValue(email, out var request))
{ {
request = Task.Run(() => RequestNewThumbnail(email)); var splitted = address.Split('@');
_requests[email] = request;
}
if (awaitLoad) if (splitted.Length >= 2 && !string.IsNullOrEmpty(splitted[1]))
{
await request;
_cache.TryGetValue(email, out cached);
return cached;
}
return default;
static bool GetIsInternetAvailable()
{
var connection = NetworkInformation.GetInternetConnectionProfile();
return connection != null && connection.GetNetworkConnectivityLevel() == NetworkConnectivityLevel.InternetAccess;
}
}
private async Task RequestNewThumbnail(string email)
{
var gravatarBase64 = await GetGravatarBase64(email);
var faviconBase64 = await GetFaviconBase64(email);
await _databaseService.Connection.InsertOrReplaceAsync(new Thumbnail
{
Domain = email,
Gravatar = gravatarBase64,
Favicon = faviconBase64,
LastUpdated = DateTime.UtcNow
});
_ = _cache.TryAdd(email, (gravatarBase64, faviconBase64));
WeakReferenceMessenger.Default.Send(new ThumbnailAdded(email));
}
private static async Task<string> GetGravatarBase64(string email)
{
try
{
var gravatarUrl = GravatarHelper.GetAvatarUrl(
email,
size: 128,
defaultValue: GravatarAvatarDefault.Blank,
withFileExtension: false).ToString().Replace("d=blank", "d=404");
var response = await _httpClient.GetAsync(gravatarUrl);
if (response.IsSuccessStatusCode)
{ {
var bytes = response.Content.ReadAsByteArrayAsync().Result; try
return Convert.ToBase64String(bytes); {
return new MailAddress(address).Host;
}
catch (Exception)
{
// TODO: Exceptions are ignored for now.
}
} }
} }
catch { }
return null;
}
private static async Task<string> GetFaviconBase64(string email)
{
try
{
var host = GetHost(email);
if (string.IsNullOrEmpty(host))
return null;
// Do not fetch favicon for specific default domains of major platforms
if (_excludedFaviconDomains.Contains(host, StringComparer.OrdinalIgnoreCase))
return null;
var primaryDomain = string.Join('.', host.Split('.')[^2..]);
var googleFaviconUrl = $"https://www.google.com/s2/favicons?sz=128&domain_url={primaryDomain}";
var response = await _httpClient.GetAsync(googleFaviconUrl);
if (response.IsSuccessStatusCode)
{
var bytes = response.Content.ReadAsByteArrayAsync().Result;
return Convert.ToBase64String(bytes);
}
}
catch { }
return null;
}
private static string GetHost(string email)
{
if (!string.IsNullOrEmpty(email) && email.Contains('@'))
{
var split = email.Split('@');
if (split.Length >= 2 && !string.IsNullOrEmpty(split[1]))
{
try { return new MailAddress(email).Host; } catch { }
}
}
return string.Empty; return string.Empty;
} }
public static Tuple<bool, string> CheckIsKnown(string host)
{
// Check known hosts.
// Apply company logo if available.
try
{
var last = host.Split('.');
if (last.Length > 2)
host = $"{last[last.Length - 2]}.{last[last.Length - 1]}";
}
catch (Exception)
{
return new Tuple<bool, string>(false, host);
}
return new Tuple<bool, string>(IsKnown(host), host);
}
public static string GetKnownHostImage(string host)
=> $"ms-appx:///Assets/Thumbnails/{host}.png";
} }

View File

@@ -85,7 +85,6 @@
<Content Include="BackgroundImages\Snowflake.jpg" /> <Content Include="BackgroundImages\Snowflake.jpg" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="gravatar-dotnet" />
<PackageReference Include="Microsoft.Identity.Client" /> <PackageReference Include="Microsoft.Identity.Client" />
<PackageReference Include="Microsoft.UI.Xaml" /> <PackageReference Include="Microsoft.UI.Xaml" />
<PackageReference Include="CommunityToolkit.Common" /> <PackageReference Include="CommunityToolkit.Common" />

View File

@@ -40,7 +40,6 @@ public abstract class WinoApplication : Application, IRecipient<LanguageChanged>
protected IWinoServerConnectionManager<AppServiceConnection> AppServiceConnectionManager { get; } protected IWinoServerConnectionManager<AppServiceConnection> AppServiceConnectionManager { get; }
public IThemeService ThemeService { get; } public IThemeService ThemeService { get; }
public IUnderlyingThemeService UnderlyingThemeService { get; } public IUnderlyingThemeService UnderlyingThemeService { get; }
public IThumbnailService ThumbnailService { get; }
protected IDatabaseService DatabaseService { get; } protected IDatabaseService DatabaseService { get; }
protected ITranslationService TranslationService { get; } protected ITranslationService TranslationService { get; }
@@ -65,7 +64,6 @@ public abstract class WinoApplication : Application, IRecipient<LanguageChanged>
DatabaseService = Services.GetService<IDatabaseService>(); DatabaseService = Services.GetService<IDatabaseService>();
TranslationService = Services.GetService<ITranslationService>(); TranslationService = Services.GetService<ITranslationService>();
UnderlyingThemeService = Services.GetService<IUnderlyingThemeService>(); UnderlyingThemeService = Services.GetService<IUnderlyingThemeService>();
ThumbnailService = Services.GetService<IThumbnailService>();
// Make sure the paths are setup on app start. // Make sure the paths are setup on app start.
AppConfiguration.ApplicationDataFolderPath = ApplicationData.Current.LocalFolder.Path; AppConfiguration.ApplicationDataFolderPath = ApplicationData.Current.LocalFolder.Path;

View File

@@ -18,6 +18,7 @@ public partial class AppPreferencesPageViewModel : MailBaseViewModel
[ObservableProperty] [ObservableProperty]
private List<string> _appTerminationBehavior; private List<string> _appTerminationBehavior;
[ObservableProperty] [ObservableProperty]
public partial List<string> SearchModes { get; set; } public partial List<string> SearchModes { get; set; }

View File

@@ -129,11 +129,11 @@ public class WinoMailCollection
private async Task HandleExistingThreadAsync(ObservableGroup<object, IMailItem> group, ThreadMailItemViewModel threadViewModel, MailCopy addedItem) private async Task HandleExistingThreadAsync(ObservableGroup<object, IMailItem> group, ThreadMailItemViewModel threadViewModel, MailCopy addedItem)
{ {
var existingGroupKey = GetGroupingKey(threadViewModel); var existingGroupKey = GetGroupingKey(threadViewModel);
await ExecuteUIThread(() => { threadViewModel.AddMailItemViewModel(addedItem); }); await ExecuteUIThread(() => { threadViewModel.AddMailItemViewModel(addedItem); });
var newGroupKey = GetGroupingKey(threadViewModel); var newGroupKey = GetGroupingKey(threadViewModel);
if (!existingGroupKey.Equals(newGroupKey)) if (!existingGroupKey.Equals(newGroupKey))
{ {
await MoveThreadToNewGroupAsync(group, threadViewModel, newGroupKey); await MoveThreadToNewGroupAsync(group, threadViewModel, newGroupKey);
@@ -294,25 +294,6 @@ public class WinoMailCollection
return null; return null;
} }
public void UpdateThumbnails(string address)
{
if (CoreDispatcher == null) return;
CoreDispatcher.ExecuteOnUIThread(() =>
{
foreach (var group in _mailItemSource)
{
foreach (var item in group)
{
if (item is MailItemViewModel mailItemViewModel && mailItemViewModel.MailCopy.FromAddress.Equals(address, StringComparison.OrdinalIgnoreCase))
{
mailItemViewModel.ThumbnailUpdatedEvent = !mailItemViewModel.ThumbnailUpdatedEvent;
}
}
}
});
}
/// <summary> /// <summary>
/// Fins the item container that updated mail copy belongs to and updates it. /// Fins the item container that updated mail copy belongs to and updates it.
/// </summary> /// </summary>

View File

@@ -1,17 +1,10 @@
using System; using Wino.Core.Domain;
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities.Shared; using Wino.Core.Domain.Entities.Shared;
namespace Wino.Mail.ViewModels.Data; namespace Wino.Mail.ViewModels.Data;
public partial class AccountContactViewModel : ObservableObject public class AccountContactViewModel : AccountContact
{ {
public string Address { get; set; }
public string Name { get; set; }
public string Base64ContactPicture { get; set; }
public bool IsRootContact { get; set; }
public AccountContactViewModel(AccountContact contact) public AccountContactViewModel(AccountContact contact)
{ {
Address = contact.Address; Address = contact.Address;
@@ -46,7 +39,4 @@ public partial class AccountContactViewModel : ObservableObject
/// Display name of the contact in a format: Name <Address>. /// Display name of the contact in a format: Name <Address>.
/// </summary> /// </summary>
public string DisplayName => Address == Name || string.IsNullOrWhiteSpace(Name) ? Address.ToLowerInvariant() : $"{Name} <{Address.ToLowerInvariant()}>"; public string DisplayName => Address == Name || string.IsNullOrWhiteSpace(Name) ? Address.ToLowerInvariant() : $"{Name} <{Address.ToLowerInvariant()}>";
[ObservableProperty]
public partial bool ThumbnailUpdatedEvent { get; set; }
} }

View File

@@ -13,7 +13,7 @@ namespace Wino.Mail.ViewModels.Data;
public partial class MailItemViewModel(MailCopy mailCopy) : ObservableObject, IMailItem public partial class MailItemViewModel(MailCopy mailCopy) : ObservableObject, IMailItem
{ {
[ObservableProperty] [ObservableProperty]
public partial MailCopy MailCopy { get; set; } = mailCopy; private MailCopy mailCopy = mailCopy;
public Guid UniqueId => ((IMailItem)MailCopy).UniqueId; public Guid UniqueId => ((IMailItem)MailCopy).UniqueId;
public string ThreadId => ((IMailItem)MailCopy).ThreadId; public string ThreadId => ((IMailItem)MailCopy).ThreadId;
@@ -23,13 +23,10 @@ public partial class MailItemViewModel(MailCopy mailCopy) : ObservableObject, IM
public string InReplyTo => ((IMailItem)MailCopy).InReplyTo; public string InReplyTo => ((IMailItem)MailCopy).InReplyTo;
[ObservableProperty] [ObservableProperty]
public partial bool ThumbnailUpdatedEvent { get; set; } = false; private bool isCustomFocused;
[ObservableProperty] [ObservableProperty]
public partial bool IsCustomFocused { get; set; } private bool isSelected;
[ObservableProperty]
public partial bool IsSelected { get; set; }
public bool IsFlagged public bool IsFlagged
{ {

View File

@@ -98,13 +98,19 @@ public partial class EditAccountDetailsPageViewModel : MailBaseViewModel
Messenger.Send(new BackBreadcrumNavigationRequested()); Messenger.Send(new BackBreadcrumNavigationRequested());
} }
[RelayCommand]
private Task SaveWithoutGoBackAsync()
{
return UpdateAccountAsync();
}
[RelayCommand] [RelayCommand]
private async Task ValidateImapSettingsAsync() private async Task ValidateImapSettingsAsync()
{ {
try try
{ {
await _imapTestService.TestImapConnectionAsync(ServerInformation, true); await _imapTestService.TestImapConnectionAsync(ServerInformation, true);
_mailDialogService.InfoBarMessage(Translator.IMAPSetupDialog_ValidationSuccess_Title, Translator.IMAPSetupDialog_ValidationSuccess_Message, Core.Domain.Enums.InfoBarMessageType.Success); _mailDialogService.InfoBarMessage(Translator.IMAPSetupDialog_ValidationSuccess_Title, Translator.IMAPSetupDialog_ValidationSuccess_Message, Core.Domain.Enums.InfoBarMessageType.Success); ;
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -112,9 +118,12 @@ public partial class EditAccountDetailsPageViewModel : MailBaseViewModel
} }
} }
[RelayCommand] private Task UpdateAccountAsync()
private async Task UpdateCustomServerInformationAsync()
{ {
Account.Name = AccountName;
Account.SenderName = SenderName;
Account.AccountColorHex = SelectedColor == null ? string.Empty : SelectedColor.Hex;
if (ServerInformation != null) if (ServerInformation != null)
{ {
ServerInformation.IncomingAuthenticationMethod = AvailableAuthenticationMethods[SelectedIncomingServerAuthenticationMethodIndex].ImapAuthenticationMethod; ServerInformation.IncomingAuthenticationMethod = AvailableAuthenticationMethods[SelectedIncomingServerAuthenticationMethodIndex].ImapAuthenticationMethod;
@@ -126,17 +135,6 @@ public partial class EditAccountDetailsPageViewModel : MailBaseViewModel
Account.ServerInformation = ServerInformation; Account.ServerInformation = ServerInformation;
} }
await _accountService.UpdateAccountCustomServerInformationAsync(Account.ServerInformation);
_mailDialogService.InfoBarMessage(Translator.IMAPSetupDialog_SaveImapSuccess_Title, Translator.IMAPSetupDialog_SaveImapSuccess_Message, Core.Domain.Enums.InfoBarMessageType.Success);
}
private Task UpdateAccountAsync()
{
Account.Name = AccountName;
Account.SenderName = SenderName;
Account.AccountColorHex = SelectedColor == null ? string.Empty : SelectedColor.Hex;
return _accountService.UpdateAccountAsync(Account); return _accountService.UpdateAccountAsync(Account);
} }

View File

@@ -41,8 +41,7 @@ public partial class MailListPageViewModel : MailBaseViewModel,
IRecipient<AccountSynchronizationCompleted>, IRecipient<AccountSynchronizationCompleted>,
IRecipient<NewMailSynchronizationRequested>, IRecipient<NewMailSynchronizationRequested>,
IRecipient<AccountSynchronizerStateChanged>, IRecipient<AccountSynchronizerStateChanged>,
IRecipient<AccountCacheResetMessage>, IRecipient<AccountCacheResetMessage>
IRecipient<ThumbnailAdded>
{ {
private bool isChangingFolder = false; private bool isChangingFolder = false;
@@ -1141,6 +1140,4 @@ public partial class MailListPageViewModel : MailBaseViewModel,
}); });
} }
} }
public void Receive(ThumbnailAdded message) => MailCollection.UpdateThumbnails(message.Email);
} }

View File

@@ -25,14 +25,12 @@ using Wino.Mail.ViewModels.Data;
using Wino.Mail.ViewModels.Messages; using Wino.Mail.ViewModels.Messages;
using Wino.Messaging.Client.Mails; using Wino.Messaging.Client.Mails;
using Wino.Messaging.Server; using Wino.Messaging.Server;
using Wino.Messaging.UI;
using IMailService = Wino.Core.Domain.Interfaces.IMailService; using IMailService = Wino.Core.Domain.Interfaces.IMailService;
namespace Wino.Mail.ViewModels; namespace Wino.Mail.ViewModels;
public partial class MailRenderingPageViewModel : MailBaseViewModel, public partial class MailRenderingPageViewModel : MailBaseViewModel,
IRecipient<NewMailItemRenderingRequestedEvent>, IRecipient<NewMailItemRenderingRequestedEvent>,
IRecipient<ThumbnailAdded>,
ITransferProgress // For listening IMAP message download progress. ITransferProgress // For listening IMAP message download progress.
{ {
private readonly IMailDialogService _dialogService; private readonly IMailDialogService _dialogService;
@@ -790,27 +788,4 @@ public partial class MailRenderingPageViewModel : MailBaseViewModel,
Log.Error(ex, "Failed to render mail."); Log.Error(ex, "Failed to render mail.");
} }
} }
public void Receive(ThumbnailAdded message)
{
UpdateThumbnails(ToItems, message.Email);
UpdateThumbnails(CcItems, message.Email);
UpdateThumbnails(BccItems, message.Email);
}
private void UpdateThumbnails(ObservableCollection<AccountContactViewModel> items, string email)
{
if (Dispatcher == null || items.Count == 0) return;
Dispatcher.ExecuteOnUIThread(() =>
{
foreach (var item in items)
{
if (item.Address.Equals(email, StringComparison.OrdinalIgnoreCase))
{
item.ThumbnailUpdatedEvent = !item.ThumbnailUpdatedEvent;
}
}
});
}
} }

View File

@@ -1,19 +1,17 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Input;
using Wino.Core.Domain; using Wino.Core.Domain;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
namespace Wino.Mail.ViewModels; namespace Wino.Mail.ViewModels;
public partial class MessageListPageViewModel : MailBaseViewModel public class MessageListPageViewModel : MailBaseViewModel
{ {
public IPreferencesService PreferencesService { get; } public IPreferencesService PreferencesService { get; }
private readonly IThumbnailService _thumbnailService;
private int selectedMarkAsOptionIndex; private int selectedMarkAsOptionIndex;
public int SelectedMarkAsOptionIndex public int SelectedMarkAsOptionIndex
{ {
get => selectedMarkAsOptionIndex; get => selectedMarkAsOptionIndex;
@@ -48,7 +46,9 @@ public partial class MessageListPageViewModel : MailBaseViewModel
]; ];
#region Properties #region Properties
private int leftHoverActionIndex; private int leftHoverActionIndex;
public int LeftHoverActionIndex public int LeftHoverActionIndex
{ {
get => leftHoverActionIndex; get => leftHoverActionIndex;
@@ -61,7 +61,9 @@ public partial class MessageListPageViewModel : MailBaseViewModel
} }
} }
private int centerHoverActionIndex; private int centerHoverActionIndex;
public int CenterHoverActionIndex public int CenterHoverActionIndex
{ {
get => centerHoverActionIndex; get => centerHoverActionIndex;
@@ -75,6 +77,7 @@ public partial class MessageListPageViewModel : MailBaseViewModel
} }
private int rightHoverActionIndex; private int rightHoverActionIndex;
public int RightHoverActionIndex public int RightHoverActionIndex
{ {
get => rightHoverActionIndex; get => rightHoverActionIndex;
@@ -86,21 +89,18 @@ public partial class MessageListPageViewModel : MailBaseViewModel
} }
} }
} }
#endregion #endregion
public MessageListPageViewModel(IPreferencesService preferencesService, IThumbnailService thumbnailService) public MessageListPageViewModel(IMailDialogService dialogService,
IPreferencesService preferencesService)
{ {
PreferencesService = preferencesService; PreferencesService = preferencesService;
_thumbnailService = thumbnailService;
leftHoverActionIndex = availableHoverActions.IndexOf(PreferencesService.LeftHoverAction); leftHoverActionIndex = availableHoverActions.IndexOf(PreferencesService.LeftHoverAction);
centerHoverActionIndex = availableHoverActions.IndexOf(PreferencesService.CenterHoverAction); centerHoverActionIndex = availableHoverActions.IndexOf(PreferencesService.CenterHoverAction);
rightHoverActionIndex = availableHoverActions.IndexOf(PreferencesService.RightHoverAction); rightHoverActionIndex = availableHoverActions.IndexOf(PreferencesService.RightHoverAction);
SelectedMarkAsOptionIndex = Array.IndexOf(Enum.GetValues<MailMarkAsOption>(), PreferencesService.MarkAsPreference); SelectedMarkAsOptionIndex = Array.IndexOf(Enum.GetValues<MailMarkAsOption>(), PreferencesService.MarkAsPreference);
} }
[RelayCommand]
private async Task ClearAvatarsCacheAsync()
{
await _thumbnailService.ClearCache();
}
} }

View File

@@ -30,7 +30,6 @@
<DataTemplate x:Key="ClickableAccountMenuTemplate" x:DataType="menu:AccountMenuItem"> <DataTemplate x:Key="ClickableAccountMenuTemplate" x:DataType="menu:AccountMenuItem">
<controls:AccountNavigationItem <controls:AccountNavigationItem
x:Name="AccountItem" x:Name="AccountItem"
Height="50"
HorizontalContentAlignment="Stretch" HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
BindingData="{x:Bind}" BindingData="{x:Bind}"
@@ -58,12 +57,19 @@
Value="{x:Bind UnreadItemCount, Mode=OneWay}" /> Value="{x:Bind UnreadItemCount, Mode=OneWay}" />
</muxc:NavigationViewItem.InfoBadge> </muxc:NavigationViewItem.InfoBadge>
<Grid> <Grid
MaxHeight="70"
Margin="0,8"
RowSpacing="6">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="2" />
</Grid.RowDefinitions>
<StackPanel VerticalAlignment="Center"> <StackPanel VerticalAlignment="Center">
<TextBlock <TextBlock
x:Name="AccountNameTextblock" x:Name="AccountNameTextblock"
@@ -74,7 +80,8 @@
TextTrimming="CharacterEllipsis" /> TextTrimming="CharacterEllipsis" />
<TextBlock <TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}" FontSize="13"
FontWeight="{x:Bind helpers:XamlHelpers.GetFontWeightByChildSelectedState(IsSelected), Mode=OneWay}"
MaxLines="1" MaxLines="1"
Style="{StaticResource CaptionTextBlockStyle}" Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind Parameter.Address, Mode=OneWay}" Text="{x:Bind Parameter.Address, Mode=OneWay}"
@@ -83,6 +90,8 @@
<PathIcon <PathIcon
x:Name="AttentionIcon" x:Name="AttentionIcon"
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="2" Grid.Column="2"
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center" VerticalAlignment="Center"
@@ -95,6 +104,7 @@
Grid.ColumnSpan="3" Grid.ColumnSpan="3"
Width="10" Width="10"
Height="10" Height="10"
Margin="0,8,0,0"
HorizontalAlignment="Right" HorizontalAlignment="Right"
VerticalAlignment="Center" VerticalAlignment="Center"
Background="{ThemeResource AppBarItemBackgroundThemeBrush}" Background="{ThemeResource AppBarItemBackgroundThemeBrush}"
@@ -159,7 +169,7 @@
<!-- Inbox or any other folders. --> <!-- Inbox or any other folders. -->
<DataTemplate x:Key="FolderMenuTemplate" x:DataType="menu:FolderMenuItem"> <DataTemplate x:Key="FolderMenuTemplate" x:DataType="menu:FolderMenuItem">
<coreControls:WinoNavigationViewItem <coreControls:WinoNavigationViewItem
MinHeight="40" MinHeight="30"
AllowDrop="True" AllowDrop="True"
ContextRequested="MenuItemContextRequested" ContextRequested="MenuItemContextRequested"
DataContext="{x:Bind}" DataContext="{x:Bind}"
@@ -190,7 +200,6 @@
<muxc:NavigationViewItem.Content> <muxc:NavigationViewItem.Content>
<Grid <Grid
x:Name="FolderBackgroundGrid" x:Name="FolderBackgroundGrid"
MaxHeight="36"
Padding="2" Padding="2"
VerticalAlignment="Center"> VerticalAlignment="Center">
<Grid <Grid
@@ -252,7 +261,7 @@
<PathIcon Data="F1 M 8.613281 17.5 C 8.75 17.942709 8.945312 18.359375 9.199219 18.75 L 4.921875 18.75 C 4.433594 18.75 3.966471 18.650717 3.520508 18.452148 C 3.074544 18.25358 2.683919 17.986654 2.348633 17.651367 C 2.013346 17.31608 1.746419 16.925455 1.547852 16.479492 C 1.349284 16.033529 1.25 15.566406 1.25 15.078125 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 15.078125 1.25 C 15.566406 1.25 16.033527 1.349285 16.479492 1.547852 C 16.925455 1.74642 17.31608 2.013348 17.651367 2.348633 C 17.986652 2.68392 18.25358 3.074545 18.452148 3.520508 C 18.650715 3.966473 18.75 4.433594 18.75 4.921875 L 18.75 6.572266 C 18.580729 6.344402 18.390299 6.132813 18.178711 5.9375 C 17.967121 5.742188 17.740885 5.566407 17.5 5.410156 L 17.5 4.951172 C 17.5 4.625651 17.433268 4.314779 17.299805 4.018555 C 17.16634 3.722332 16.987305 3.461914 16.762695 3.237305 C 16.538086 3.012695 16.277668 2.83366 15.981445 2.700195 C 15.685221 2.566732 15.374349 2.5 15.048828 2.5 L 4.951172 2.5 C 4.619141 2.5 4.303385 2.568359 4.003906 2.705078 C 3.704427 2.841797 3.44401 3.02409 3.222656 3.251953 C 3.001302 3.479818 2.825521 3.745117 2.695312 4.047852 C 2.565104 4.350587 2.5 4.66797 2.5 5 L 13.310547 5 C 12.60091 5.266928 11.998697 5.683594 11.503906 6.25 L 2.5 6.25 L 2.5 15.048828 C 2.5 15.38737 2.568359 15.704753 2.705078 16.000977 C 2.841797 16.297201 3.024088 16.55599 3.251953 16.777344 C 3.479818 16.998697 3.745117 17.174479 4.047852 17.304688 C 4.350586 17.434896 4.667969 17.5 5 17.5 Z" /> <PathIcon Data="F1 M 8.613281 17.5 C 8.75 17.942709 8.945312 18.359375 9.199219 18.75 L 4.921875 18.75 C 4.433594 18.75 3.966471 18.650717 3.520508 18.452148 C 3.074544 18.25358 2.683919 17.986654 2.348633 17.651367 C 2.013346 17.31608 1.746419 16.925455 1.547852 16.479492 C 1.349284 16.033529 1.25 15.566406 1.25 15.078125 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 15.078125 1.25 C 15.566406 1.25 16.033527 1.349285 16.479492 1.547852 C 16.925455 1.74642 17.31608 2.013348 17.651367 2.348633 C 17.986652 2.68392 18.25358 3.074545 18.452148 3.520508 C 18.650715 3.966473 18.75 4.433594 18.75 4.921875 L 18.75 6.572266 C 18.580729 6.344402 18.390299 6.132813 18.178711 5.9375 C 17.967121 5.742188 17.740885 5.566407 17.5 5.410156 L 17.5 4.951172 C 17.5 4.625651 17.433268 4.314779 17.299805 4.018555 C 17.16634 3.722332 16.987305 3.461914 16.762695 3.237305 C 16.538086 3.012695 16.277668 2.83366 15.981445 2.700195 C 15.685221 2.566732 15.374349 2.5 15.048828 2.5 L 4.951172 2.5 C 4.619141 2.5 4.303385 2.568359 4.003906 2.705078 C 3.704427 2.841797 3.44401 3.02409 3.222656 3.251953 C 3.001302 3.479818 2.825521 3.745117 2.695312 4.047852 C 2.565104 4.350587 2.5 4.66797 2.5 5 L 13.310547 5 C 12.60091 5.266928 11.998697 5.683594 11.503906 6.25 L 2.5 6.25 L 2.5 15.048828 C 2.5 15.38737 2.568359 15.704753 2.705078 16.000977 C 2.841797 16.297201 3.024088 16.55599 3.251953 16.777344 C 3.479818 16.998697 3.745117 17.174479 4.047852 17.304688 C 4.350586 17.434896 4.667969 17.5 5 17.5 Z" />
</coreControls:WinoNavigationViewItem.Icon> </coreControls:WinoNavigationViewItem.Icon>
<Grid Height="50"> <Grid MinHeight="50">
<StackPanel VerticalAlignment="Center" Spacing="0"> <StackPanel VerticalAlignment="Center" Spacing="0">
<TextBlock <TextBlock
x:Name="AccountNameTextblock" x:Name="AccountNameTextblock"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -1,28 +1,30 @@
using System.Collections; using System.Collections;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Windows.Input; using System.Windows.Input;
using CommunityToolkit.WinUI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Xaml.Interactivity; using Microsoft.Xaml.Interactivity;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Controls.Primitives;
using Wino.Core.Domain.Interfaces; using Wino.Controls;
using Wino.Core.Domain.Models.Menus; using Wino.Core.Domain.Models.Menus;
using Wino.Core.UWP.Controls; using Wino.Core.UWP.Controls;
using Wino.Helpers; using Wino.Helpers;
namespace Wino.Behaviors; namespace Wino.Behaviors;
public partial class BindableCommandBarBehavior : Behavior<CommandBar> public class BindableCommandBarBehavior : Behavior<CommandBar>
{ {
private readonly IPreferencesService _preferencesService = App.Current.Services.GetService<IPreferencesService>();
public static readonly DependencyProperty PrimaryCommandsProperty = DependencyProperty.Register( public static readonly DependencyProperty PrimaryCommandsProperty = DependencyProperty.Register(
"PrimaryCommands", typeof(object), typeof(BindableCommandBarBehavior), "PrimaryCommands", typeof(object), typeof(BindableCommandBarBehavior),
new PropertyMetadata(null, UpdateCommands)); new PropertyMetadata(null, UpdateCommands));
[GeneratedDependencyProperty] public ICommand ItemClickedCommand
public partial ICommand ItemClickedCommand { get; set; } {
get { return (ICommand)GetValue(ItemClickedCommandProperty); }
set { SetValue(ItemClickedCommandProperty, value); }
}
public static readonly DependencyProperty ItemClickedCommandProperty = DependencyProperty.Register(nameof(ItemClickedCommand), typeof(ICommand), typeof(BindableCommandBarBehavior), new PropertyMetadata(null));
public object PrimaryCommands public object PrimaryCommands
{ {
@@ -81,7 +83,7 @@ public partial class BindableCommandBarBehavior : Behavior<CommandBar>
AssociatedObject.PrimaryCommands.Clear(); AssociatedObject.PrimaryCommands.Clear();
AssociatedObject.SecondaryCommands.Clear(); AssociatedObject.SecondaryCommands.Clear();
if (PrimaryCommands is not IEnumerable enumerable) return; if (!(PrimaryCommands is IEnumerable enumerable)) return;
foreach (var command in enumerable) foreach (var command in enumerable)
{ {
@@ -96,26 +98,19 @@ public partial class BindableCommandBarBehavior : Behavior<CommandBar>
else else
{ {
var label = XamlHelpers.GetOperationString(mailOperationMenuItem.Operation); var label = XamlHelpers.GetOperationString(mailOperationMenuItem.Operation);
var labelPosition = string.IsNullOrWhiteSpace(label) || !_preferencesService.IsShowActionLabelsEnabled ?
CommandBarLabelPosition.Collapsed : CommandBarLabelPosition.Default;
menuItem = new AppBarButton menuItem = new AppBarButton
{ {
Width = double.NaN,
MinWidth = 40,
Icon = new WinoFontIcon() { Glyph = ControlConstants.WinoIconFontDictionary[XamlHelpers.GetWinoIconGlyph(mailOperationMenuItem.Operation)] }, Icon = new WinoFontIcon() { Glyph = ControlConstants.WinoIconFontDictionary[XamlHelpers.GetWinoIconGlyph(mailOperationMenuItem.Operation)] },
Label = label, Label = label,
LabelPosition = labelPosition, LabelPosition = string.IsNullOrWhiteSpace(label) ? CommandBarLabelPosition.Collapsed : CommandBarLabelPosition.Default,
DataContext = mailOperationMenuItem, DataContext = mailOperationMenuItem,
}; };
if (!string.IsNullOrWhiteSpace(label)) ToolTip toolTip = new ToolTip
{ {
var toolTip = new ToolTip Content = label
{ };
Content = label ToolTipService.SetToolTip((DependencyObject)menuItem, toolTip);
};
ToolTipService.SetToolTip((DependencyObject)menuItem, toolTip);
}
((AppBarButton)menuItem).Click -= Button_Click; ((AppBarButton)menuItem).Click -= Button_Click;
((AppBarButton)menuItem).Click += Button_Click; ((AppBarButton)menuItem).Click += Button_Click;
@@ -169,7 +164,7 @@ public partial class BindableCommandBarBehavior : Behavior<CommandBar>
private static void UpdateCommands(DependencyObject dependencyObject, private static void UpdateCommands(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{ {
if (dependencyObject is not BindableCommandBarBehavior behavior) return; if (!(dependencyObject is BindableCommandBarBehavior behavior)) return;
if (dependencyPropertyChangedEventArgs.OldValue is INotifyCollectionChanged oldList) if (dependencyPropertyChangedEventArgs.OldValue is INotifyCollectionChanged oldList)
{ {

View File

@@ -43,6 +43,10 @@ public partial class AccountNavigationItem : WinoNavigationViewItem
_itemsRepeater = GetTemplateChild(PART_NavigationViewItemMenuItemsHost) as ItemsRepeater; _itemsRepeater = GetTemplateChild(PART_NavigationViewItemMenuItemsHost) as ItemsRepeater;
_selectionIndicator = GetTemplateChild(PART_SelectionIndicator) as Windows.UI.Xaml.Shapes.Rectangle; _selectionIndicator = GetTemplateChild(PART_SelectionIndicator) as Windows.UI.Xaml.Shapes.Rectangle;
if (_itemsRepeater == null) return;
(_itemsRepeater.Layout as StackLayout).Spacing = 0;
UpdateSelectionBorder(); UpdateSelectionBorder();
} }
@@ -56,6 +60,12 @@ public partial class AccountNavigationItem : WinoNavigationViewItem
{ {
if (_selectionIndicator == null) return; if (_selectionIndicator == null) return;
// Adjsuting Margin in the styles are not possible due to the fact that we use the same tempalte for different types of menu items.
// Account templates listed under merged accounts will have Padding of 44. We must adopt to that.
bool hasParentMenuItem = BindingData is IAccountMenuItem accountMenuItem && accountMenuItem.ParentMenuItem != null;
_selectionIndicator.Margin = !hasParentMenuItem ? new Thickness(-44, 12, 0, 12) : new Thickness(-60, 12, -60, 12);
_selectionIndicator.Scale = IsActiveAccount ? new Vector3(1, 1, 1) : new Vector3(0, 0, 0); _selectionIndicator.Scale = IsActiveAccount ? new Vector3(1, 1, 1) : new Vector3(0, 0, 0);
_selectionIndicator.Visibility = IsActiveAccount ? Visibility.Visible : Visibility.Collapsed; _selectionIndicator.Visibility = IsActiveAccount ? Visibility.Visible : Visibility.Collapsed;
} }

View File

@@ -5,14 +5,13 @@ using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Fernandezja.ColorHashSharp; using Fernandezja.ColorHashSharp;
using Microsoft.Extensions.DependencyInjection;
using Windows.UI; using Windows.UI;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Shapes; using Windows.UI.Xaml.Shapes;
using Wino.Core.Domain.Interfaces; using Wino.Core.UWP.Services;
namespace Wino.Controls; namespace Wino.Controls;
@@ -22,21 +21,12 @@ public partial class ImagePreviewControl : Control
private const string PART_InitialsTextBlock = "InitialsTextBlock"; private const string PART_InitialsTextBlock = "InitialsTextBlock";
private const string PART_KnownHostImage = "KnownHostImage"; private const string PART_KnownHostImage = "KnownHostImage";
private const string PART_Ellipse = "Ellipse"; private const string PART_Ellipse = "Ellipse";
private const string PART_FaviconSquircle = "FaviconSquircle";
private const string PART_FaviconImage = "FaviconImage";
#region Dependency Properties #region Dependency Properties
public static readonly DependencyProperty FromNameProperty = DependencyProperty.Register(nameof(FromName), typeof(string), typeof(ImagePreviewControl), new PropertyMetadata(string.Empty, OnInformationChanged)); public static readonly DependencyProperty FromNameProperty = DependencyProperty.Register(nameof(FromName), typeof(string), typeof(ImagePreviewControl), new PropertyMetadata(string.Empty, OnAddressInformationChanged));
public static readonly DependencyProperty FromAddressProperty = DependencyProperty.Register(nameof(FromAddress), typeof(string), typeof(ImagePreviewControl), new PropertyMetadata(string.Empty, OnInformationChanged)); public static readonly DependencyProperty FromAddressProperty = DependencyProperty.Register(nameof(FromAddress), typeof(string), typeof(ImagePreviewControl), new PropertyMetadata(string.Empty, OnAddressInformationChanged));
public static readonly DependencyProperty SenderContactPictureProperty = DependencyProperty.Register(nameof(SenderContactPicture), typeof(string), typeof(ImagePreviewControl), new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnInformationChanged))); public static readonly DependencyProperty SenderContactPictureProperty = DependencyProperty.Register(nameof(SenderContactPicture), typeof(string), typeof(ImagePreviewControl), new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnAddressInformationChanged)));
public static readonly DependencyProperty ThumbnailUpdatedEventProperty = DependencyProperty.Register(nameof(ThumbnailUpdatedEvent), typeof(bool), typeof(ImagePreviewControl), new PropertyMetadata(false, new PropertyChangedCallback(OnInformationChanged)));
public bool ThumbnailUpdatedEvent
{
get { return (bool)GetValue(ThumbnailUpdatedEventProperty); }
set { SetValue(ThumbnailUpdatedEventProperty, value); }
}
/// <summary> /// <summary>
/// Gets or sets base64 string of the sender contact picture. /// Gets or sets base64 string of the sender contact picture.
@@ -65,8 +55,6 @@ public partial class ImagePreviewControl : Control
private Grid InitialsGrid; private Grid InitialsGrid;
private TextBlock InitialsTextblock; private TextBlock InitialsTextblock;
private Image KnownHostImage; private Image KnownHostImage;
private Border FaviconSquircle;
private Image FaviconImage;
private CancellationTokenSource contactPictureLoadingCancellationTokenSource; private CancellationTokenSource contactPictureLoadingCancellationTokenSource;
public ImagePreviewControl() public ImagePreviewControl()
@@ -82,13 +70,11 @@ public partial class ImagePreviewControl : Control
InitialsTextblock = GetTemplateChild(PART_InitialsTextBlock) as TextBlock; InitialsTextblock = GetTemplateChild(PART_InitialsTextBlock) as TextBlock;
KnownHostImage = GetTemplateChild(PART_KnownHostImage) as Image; KnownHostImage = GetTemplateChild(PART_KnownHostImage) as Image;
Ellipse = GetTemplateChild(PART_Ellipse) as Ellipse; Ellipse = GetTemplateChild(PART_Ellipse) as Ellipse;
FaviconSquircle = GetTemplateChild(PART_FaviconSquircle) as Border;
FaviconImage = GetTemplateChild(PART_FaviconImage) as Image;
UpdateInformation(); UpdateInformation();
} }
private static void OnInformationChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) private static void OnAddressInformationChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{ {
if (obj is ImagePreviewControl control) if (obj is ImagePreviewControl control)
control.UpdateInformation(); control.UpdateInformation();
@@ -96,7 +82,7 @@ public partial class ImagePreviewControl : Control
private async void UpdateInformation() private async void UpdateInformation()
{ {
if ((KnownHostImage == null && FaviconSquircle == null) || InitialsGrid == null || InitialsTextblock == null || (string.IsNullOrEmpty(FromName) && string.IsNullOrEmpty(FromAddress))) if (KnownHostImage == null || InitialsGrid == null || InitialsTextblock == null || (string.IsNullOrEmpty(FromName) && string.IsNullOrEmpty(FromAddress)))
return; return;
// Cancel active image loading if exists. // Cancel active image loading if exists.
@@ -105,100 +91,81 @@ public partial class ImagePreviewControl : Control
contactPictureLoadingCancellationTokenSource.Cancel(); contactPictureLoadingCancellationTokenSource.Cancel();
} }
string contactPicture = SenderContactPicture; var host = ThumbnailService.GetHost(FromAddress);
var isAvatarThumbnail = false; bool isKnownHost = false;
if (string.IsNullOrEmpty(contactPicture) && !string.IsNullOrEmpty(FromAddress)) if (!string.IsNullOrEmpty(host))
{ {
contactPicture = await App.Current.ThumbnailService.GetThumbnailAsync(FromAddress); var tuple = ThumbnailService.CheckIsKnown(host);
isAvatarThumbnail = true;
isKnownHost = tuple.Item1;
host = tuple.Item2;
} }
if (!string.IsNullOrEmpty(contactPicture)) if (isKnownHost)
{ {
if (isAvatarThumbnail && FaviconSquircle != null && FaviconImage != null) // Unrealize others.
{
// Show favicon in squircle
FaviconSquircle.Visibility = Visibility.Visible;
InitialsGrid.Visibility = Visibility.Collapsed;
KnownHostImage.Visibility = Visibility.Collapsed;
var bitmapImage = await GetBitmapImageAsync(contactPicture); KnownHostImage.Visibility = Visibility.Visible;
InitialsGrid.Visibility = Visibility.Collapsed;
if (bitmapImage != null) // Apply company logo.
{ KnownHostImage.Source = new BitmapImage(new Uri(ThumbnailService.GetKnownHostImage(host)));
FaviconImage.Source = bitmapImage; }
} else
} {
else KnownHostImage.Visibility = Visibility.Collapsed;
InitialsGrid.Visibility = Visibility.Visible;
if (!string.IsNullOrEmpty(SenderContactPicture))
{ {
// Show normal avatar (tondo)
FaviconSquircle.Visibility = Visibility.Collapsed;
KnownHostImage.Visibility = Visibility.Collapsed;
InitialsGrid.Visibility = Visibility.Visible;
contactPictureLoadingCancellationTokenSource = new CancellationTokenSource(); contactPictureLoadingCancellationTokenSource = new CancellationTokenSource();
try try
{ {
var brush = await GetContactImageBrushAsync(contactPicture); var brush = await GetContactImageBrushAsync();
if (brush != null) if (!contactPictureLoadingCancellationTokenSource?.Token.IsCancellationRequested ?? false)
{ {
if (!contactPictureLoadingCancellationTokenSource?.Token.IsCancellationRequested ?? false) Ellipse.Fill = brush;
{ InitialsTextblock.Text = string.Empty;
Ellipse.Fill = brush;
InitialsTextblock.Text = string.Empty;
}
} }
} }
catch (Exception) catch (Exception)
{ {
// Log exception.
Debugger.Break(); Debugger.Break();
} }
} }
} else
else {
{ var colorHash = new ColorHash();
FaviconSquircle.Visibility = Visibility.Collapsed; var rgb = colorHash.Rgb(FromAddress);
KnownHostImage.Visibility = Visibility.Collapsed;
InitialsGrid.Visibility = Visibility.Visible;
var colorHash = new ColorHash(); Ellipse.Fill = new SolidColorBrush(Color.FromArgb(rgb.A, rgb.R, rgb.G, rgb.B));
var rgb = colorHash.Rgb(FromAddress); InitialsTextblock.Text = ExtractInitialsFromName(FromName);
}
Ellipse.Fill = new SolidColorBrush(Color.FromArgb(rgb.A, rgb.R, rgb.G, rgb.B));
InitialsTextblock.Text = ExtractInitialsFromName(FromName);
} }
} }
private static async Task<ImageBrush> GetContactImageBrushAsync(string base64) private async Task<ImageBrush> GetContactImageBrushAsync()
{ {
// Load the image from base64 string. // Load the image from base64 string.
var bitmapImage = new BitmapImage();
var bitmapImage = await GetBitmapImageAsync(base64);
if (bitmapImage == null) return null; var imageArray = Convert.FromBase64String(SenderContactPicture);
var imageStream = new MemoryStream(imageArray);
var randomAccessImageStream = imageStream.AsRandomAccessStream();
randomAccessImageStream.Seek(0);
await bitmapImage.SetSourceAsync(randomAccessImageStream);
return new ImageBrush() { ImageSource = bitmapImage }; return new ImageBrush() { ImageSource = bitmapImage };
} }
private static async Task<BitmapImage> GetBitmapImageAsync(string base64)
{
try
{
var bitmapImage = new BitmapImage();
var imageArray = Convert.FromBase64String(base64);
var imageStream = new MemoryStream(imageArray);
var randomAccessImageStream = imageStream.AsRandomAccessStream();
randomAccessImageStream.Seek(0);
await bitmapImage.SetSourceAsync(randomAccessImageStream);
return bitmapImage;
}
catch (Exception) { }
return null;
}
public string ExtractInitialsFromName(string name) public string ExtractInitialsFromName(string name)
{ {
// Change from name to from address in case of name doesn't exists. // Change from name to from address in case of name doesn't exists.

View File

@@ -76,7 +76,6 @@
FromAddress="{x:Bind MailItem.FromAddress, Mode=OneWay}" FromAddress="{x:Bind MailItem.FromAddress, Mode=OneWay}"
FromName="{x:Bind MailItem.FromName, Mode=OneWay}" FromName="{x:Bind MailItem.FromName, Mode=OneWay}"
SenderContactPicture="{x:Bind MailItem.SenderContact.Base64ContactPicture}" SenderContactPicture="{x:Bind MailItem.SenderContact.Base64ContactPicture}"
ThumbnailUpdatedEvent="{x:Bind IsThumbnailUpdated, Mode=OneWay}"
Visibility="{x:Bind IsAvatarVisible, Mode=OneWay}" /> Visibility="{x:Bind IsAvatarVisible, Mode=OneWay}" />
<Grid <Grid

View File

@@ -1,7 +1,6 @@
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using System.Windows.Input; using System.Windows.Input;
using CommunityToolkit.WinUI;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Wino.Core.Domain; using Wino.Core.Domain;
@@ -34,13 +33,6 @@ public sealed partial class MailItemDisplayInformationControl : UserControl
public static readonly DependencyProperty Prefer24HourTimeFormatProperty = DependencyProperty.Register(nameof(Prefer24HourTimeFormat), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(false)); public static readonly DependencyProperty Prefer24HourTimeFormatProperty = DependencyProperty.Register(nameof(Prefer24HourTimeFormat), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(false));
public static readonly DependencyProperty IsThreadExpanderVisibleProperty = DependencyProperty.Register(nameof(IsThreadExpanderVisible), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(false)); public static readonly DependencyProperty IsThreadExpanderVisibleProperty = DependencyProperty.Register(nameof(IsThreadExpanderVisible), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(false));
public static readonly DependencyProperty IsThreadExpandedProperty = DependencyProperty.Register(nameof(IsThreadExpanded), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(false)); public static readonly DependencyProperty IsThreadExpandedProperty = DependencyProperty.Register(nameof(IsThreadExpanded), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(false));
public static readonly DependencyProperty IsThumbnailUpdatedProperty = DependencyProperty.Register(nameof(IsThumbnailUpdated), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(false));
public bool IsThumbnailUpdated
{
get { return (bool)GetValue(IsThumbnailUpdatedProperty); }
set { SetValue(IsThumbnailUpdatedProperty, value); }
}
public bool IsThreadExpanded public bool IsThreadExpanded
{ {

View File

@@ -55,8 +55,7 @@
DefaultLabelPosition="Collapsed" DefaultLabelPosition="Collapsed"
IsOpen="False"> IsOpen="False">
<AppBarButton <AppBarButton
Width="Auto" Width="48"
MinWidth="40"
Click="{x:Bind WebViewEditor.ToggleEditorTheme}" Click="{x:Bind WebViewEditor.ToggleEditorTheme}"
LabelPosition="Collapsed" LabelPosition="Collapsed"
ToolTipService.ToolTip="Light Theme" ToolTipService.ToolTip="Light Theme"
@@ -67,8 +66,7 @@
</AppBarButton> </AppBarButton>
<AppBarButton <AppBarButton
Width="Auto" Width="48"
MinWidth="40"
Click="{x:Bind WebViewEditor.ToggleEditorTheme}" Click="{x:Bind WebViewEditor.ToggleEditorTheme}"
LabelPosition="Collapsed" LabelPosition="Collapsed"
ToolTipService.ToolTip="Dark Theme" ToolTipService.ToolTip="Dark Theme"
@@ -81,8 +79,7 @@
<AppBarSeparator /> <AppBarSeparator />
<AppBarToggleButton <AppBarToggleButton
Width="Auto" Width="48"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorBold, Mode=TwoWay}" IsChecked="{x:Bind WebViewEditor.IsEditorBold, Mode=TwoWay}"
Label="Bold" Label="Bold"
ToolTipService.ToolTip="Bold"> ToolTipService.ToolTip="Bold">
@@ -91,8 +88,7 @@
</AppBarToggleButton.Icon> </AppBarToggleButton.Icon>
</AppBarToggleButton> </AppBarToggleButton>
<AppBarToggleButton <AppBarToggleButton
Width="Auto" Width="48"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorItalic, Mode=TwoWay}" IsChecked="{x:Bind WebViewEditor.IsEditorItalic, Mode=TwoWay}"
Label="Italic" Label="Italic"
ToolTipService.ToolTip="Italic"> ToolTipService.ToolTip="Italic">
@@ -101,8 +97,7 @@
</AppBarToggleButton.Icon> </AppBarToggleButton.Icon>
</AppBarToggleButton> </AppBarToggleButton>
<AppBarToggleButton <AppBarToggleButton
Width="Auto" Width="48"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorUnderline, Mode=TwoWay}" IsChecked="{x:Bind WebViewEditor.IsEditorUnderline, Mode=TwoWay}"
Label="Underline" Label="Underline"
ToolTipService.ToolTip="Underline"> ToolTipService.ToolTip="Underline">
@@ -111,8 +106,7 @@
</AppBarToggleButton.Icon> </AppBarToggleButton.Icon>
</AppBarToggleButton> </AppBarToggleButton>
<AppBarToggleButton <AppBarToggleButton
Width="Auto" Width="48"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorStrikethrough, Mode=TwoWay}" IsChecked="{x:Bind WebViewEditor.IsEditorStrikethrough, Mode=TwoWay}"
Label="Stroke" Label="Stroke"
ToolTipService.ToolTip="Stroke"> ToolTipService.ToolTip="Stroke">
@@ -122,8 +116,7 @@
</AppBarToggleButton> </AppBarToggleButton>
<AppBarSeparator /> <AppBarSeparator />
<AppBarToggleButton <AppBarToggleButton
Width="Auto" Width="48"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorUl, Mode=TwoWay}" IsChecked="{x:Bind WebViewEditor.IsEditorUl, Mode=TwoWay}"
Label="Bullet List" Label="Bullet List"
ToolTipService.ToolTip="Bullet List"> ToolTipService.ToolTip="Bullet List">
@@ -132,8 +125,7 @@
</AppBarToggleButton.Icon> </AppBarToggleButton.Icon>
</AppBarToggleButton> </AppBarToggleButton>
<AppBarToggleButton <AppBarToggleButton
Width="Auto" Width="48"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorOl, Mode=TwoWay}" IsChecked="{x:Bind WebViewEditor.IsEditorOl, Mode=TwoWay}"
Label="Ordered List" Label="Ordered List"
ToolTipService.ToolTip="Ordered List"> ToolTipService.ToolTip="Ordered List">
@@ -145,8 +137,7 @@
<AppBarSeparator /> <AppBarSeparator />
<AppBarButton <AppBarButton
Width="Auto" Width="48"
MinWidth="40"
Click="{x:Bind WebViewEditor.EditorOutdentAsync}" Click="{x:Bind WebViewEditor.EditorOutdentAsync}"
IsEnabled="{x:Bind WebViewEditor.IsEditorOutdentEnabled, Mode=OneWay}" IsEnabled="{x:Bind WebViewEditor.IsEditorOutdentEnabled, Mode=OneWay}"
Label="Decrease Indent" Label="Decrease Indent"
@@ -156,8 +147,7 @@
</AppBarButton.Icon> </AppBarButton.Icon>
</AppBarButton> </AppBarButton>
<AppBarButton <AppBarButton
Width="Auto" Width="48"
MinWidth="40"
Click="{x:Bind WebViewEditor.EditorIndentAsync}" Click="{x:Bind WebViewEditor.EditorIndentAsync}"
IsEnabled="{x:Bind WebViewEditor.IsEditorIndentEnabled, Mode=OneWay}" IsEnabled="{x:Bind WebViewEditor.IsEditorIndentEnabled, Mode=OneWay}"
Label="Increase Indent" Label="Increase Indent"
@@ -167,10 +157,7 @@
</AppBarButton.Icon> </AppBarButton.Icon>
</AppBarButton> </AppBarButton>
<AppBarElementContainer <AppBarElementContainer VerticalAlignment="Center">
Width="Auto"
MinWidth="40"
VerticalAlignment="Center">
<ComboBox <ComboBox
Background="Transparent" Background="Transparent"
BorderBrush="Transparent" BorderBrush="Transparent"
@@ -214,8 +201,7 @@
</AppBarElementContainer> </AppBarElementContainer>
<AppBarSeparator /> <AppBarSeparator />
<AppBarButton <AppBarButton
Width="Auto" Width="48"
MinWidth="40"
Click="{x:Bind WebViewEditor.ShowImagePicker}" Click="{x:Bind WebViewEditor.ShowImagePicker}"
Label="Add Image" Label="Add Image"
ToolTipService.ToolTip="{x:Bind domain:Translator.Photos}"> ToolTipService.ToolTip="{x:Bind domain:Translator.Photos}">
@@ -232,8 +218,7 @@
</AppBarButton.Content> </AppBarButton.Content>
</AppBarButton> </AppBarButton>
<AppBarButton <AppBarButton
Width="Auto" Width="48"
MinWidth="40"
Click="{x:Bind WebViewEditor.ShowEmojiPicker}" Click="{x:Bind WebViewEditor.ShowEmojiPicker}"
Label="Add Emoji" Label="Add Emoji"
ToolTipService.ToolTip="{x:Bind domain:Translator.Emoji}"> ToolTipService.ToolTip="{x:Bind domain:Translator.Emoji}">
@@ -243,8 +228,7 @@
</AppBarButton> </AppBarButton>
<AppBarToggleButton <AppBarToggleButton
Width="Auto" Width="48"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorWebViewEditor, Mode=TwoWay}" IsChecked="{x:Bind WebViewEditor.IsEditorWebViewEditor, Mode=TwoWay}"
Label="Webview ToolBar" Label="Webview ToolBar"
ToolTipService.ToolTip="Webview ToolBar"> ToolTipService.ToolTip="Webview ToolBar">

View File

@@ -1,4 +1,5 @@
using System; using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders; using Wino.Core.Domain.Models.Folders;
@@ -10,11 +11,18 @@ namespace Wino.MenuFlyouts;
public partial class WinoOperationFlyoutItem<TOperationMenuItem> : MenuFlyoutItem, IDisposable where TOperationMenuItem : IMenuOperation public partial class WinoOperationFlyoutItem<TOperationMenuItem> : MenuFlyoutItem, IDisposable where TOperationMenuItem : IMenuOperation
{ {
private const double CustomHeight = 35;
public TOperationMenuItem Operation { get; set; } public TOperationMenuItem Operation { get; set; }
Action<TOperationMenuItem> Clicked { get; set; } Action<TOperationMenuItem> Clicked { get; set; }
public WinoOperationFlyoutItem(TOperationMenuItem operationMenuItem, Action<TOperationMenuItem> clicked) public WinoOperationFlyoutItem(TOperationMenuItem operationMenuItem, Action<TOperationMenuItem> clicked)
{ {
Margin = new Thickness(4, 2, 4, 2);
CornerRadius = new CornerRadius(6, 6, 6, 6);
MinHeight = CustomHeight;
Operation = operationMenuItem; Operation = operationMenuItem;
IsEnabled = operationMenuItem.IsEnabled; IsEnabled = operationMenuItem.IsEnabled;

View File

@@ -28,27 +28,13 @@
Foreground="White" /> Foreground="White" />
</Grid> </Grid>
<!-- Squircle for favicon -->
<Border
x:Name="FaviconSquircle"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Transparent"
CornerRadius="6"
Visibility="Collapsed">
<Image x:Name="FaviconImage" Stretch="Fill" />
</Border>
<Image <Image
x:Name="KnownHostImage" x:Name="KnownHostImage"
Width="{TemplateBinding Width}" Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}" Height="{TemplateBinding Height}"
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center" VerticalAlignment="Center"
Stretch="UniformToFill" Stretch="UniformToFill" />
Visibility="Collapsed" />
</Grid> </Grid>
</ControlTemplate> </ControlTemplate>
</Setter.Value> </Setter.Value>

View File

@@ -90,7 +90,6 @@
<Rectangle <Rectangle
x:Name="CustomSelectionIndicator" x:Name="CustomSelectionIndicator"
Width="3" Width="3"
Margin="-44,12,0,12"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Fill="{ThemeResource NavigationViewSelectionIndicatorForeground}" Fill="{ThemeResource NavigationViewSelectionIndicatorForeground}"
Opacity="1" Opacity="1"
@@ -112,7 +111,7 @@
x:Load="False" x:Load="False"
Visibility="Collapsed"> Visibility="Collapsed">
<muxc:ItemsRepeater.Layout> <muxc:ItemsRepeater.Layout>
<muxc:StackLayout Orientation="Vertical" Spacing="0" /> <muxc:StackLayout Orientation="Vertical" />
</muxc:ItemsRepeater.Layout> </muxc:ItemsRepeater.Layout>
</muxc:ItemsRepeater> </muxc:ItemsRepeater>

View File

@@ -10,16 +10,11 @@
mc:Ignorable="d"> mc:Ignorable="d">
<ScrollViewer> <ScrollViewer>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}"> <StackPanel Spacing="3">
<StackPanel.ChildrenTransitions>
<TransitionCollection>
<RepositionThemeTransition IsStaggeringEnabled="False" />
</TransitionCollection>
</StackPanel.ChildrenTransitions>
<Image <Image
Width="50" Width="50"
Height="50" Height="50"
Source="ms-appx:///Images/StoreLogo.png" /> Source="ms-appx:///Assets/StoreLogo.png" />
<TextBlock <TextBlock
Margin="0,6,0,4" Margin="0,6,0,4"
HorizontalAlignment="Center" HorizontalAlignment="Center"
@@ -172,14 +167,9 @@
</controls:SettingsExpander.Items> </controls:SettingsExpander.Items>
</controls:SettingsExpander> </controls:SettingsExpander>
<controls:SettingsCard Header="Wino Mail"> <TextBlock Margin="0,0,4,0" HorizontalAlignment="Right">
<controls:SettingsCard.HeaderIcon> <Run Text="{x:Bind domain:Translator.SettingsAboutVersion}" /><Run Text="{x:Bind ViewModel.VersionName}" />
<BitmapIcon ShowAsMonochrome="False" UriSource="ms-appx:///Images/StoreLogo.png" /> </TextBlock>
</controls:SettingsCard.HeaderIcon>
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}" IsTextSelectionEnabled="True">
<Run Text="{x:Bind domain:Translator.SettingsAboutVersion}" /><Run Text="{x:Bind ViewModel.VersionName}" />
</TextBlock>
</controls:SettingsCard>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>
</abstract:AboutPageAbstract> </abstract:AboutPageAbstract>

View File

@@ -70,12 +70,6 @@
<ScrollViewer> <ScrollViewer>
<StackPanel Spacing="4"> <StackPanel Spacing="4">
<StackPanel.ChildrenTransitions>
<TransitionCollection>
<RepositionThemeTransition IsStaggeringEnabled="False" />
</TransitionCollection>
</StackPanel.ChildrenTransitions>
<controls:SettingsCard <controls:SettingsCard
Command="{x:Bind ViewModel.EditAccountDetailsCommand}" Command="{x:Bind ViewModel.EditAccountDetailsCommand}"
Description="{x:Bind domain:Translator.SettingsEditAccountDetails_Description}" Description="{x:Bind domain:Translator.SettingsEditAccountDetails_Description}"

View File

@@ -190,8 +190,6 @@
IsDynamicOverflowEnabled="True" IsDynamicOverflowEnabled="True"
OverflowButtonAlignment="Left"> OverflowButtonAlignment="Left">
<AppBarButton <AppBarButton
Width="Auto"
MinWidth="40"
Click="{x:Bind WebViewEditor.ToggleEditorTheme}" Click="{x:Bind WebViewEditor.ToggleEditorTheme}"
LabelPosition="Collapsed" LabelPosition="Collapsed"
ToolTipService.ToolTip="Light Theme" ToolTipService.ToolTip="Light Theme"
@@ -202,8 +200,6 @@
</AppBarButton> </AppBarButton>
<AppBarButton <AppBarButton
Width="Auto"
MinWidth="40"
Click="{x:Bind WebViewEditor.ToggleEditorTheme}" Click="{x:Bind WebViewEditor.ToggleEditorTheme}"
LabelPosition="Collapsed" LabelPosition="Collapsed"
ToolTipService.ToolTip="Dark Theme" ToolTipService.ToolTip="Dark Theme"
@@ -227,38 +223,22 @@
</toolkit:TabbedCommandBar.PaneCustomContent> </toolkit:TabbedCommandBar.PaneCustomContent>
<toolkit:TabbedCommandBar.MenuItems> <toolkit:TabbedCommandBar.MenuItems>
<toolkit:TabbedCommandBarItem DefaultLabelPosition="Collapsed" Header="{x:Bind domain:Translator.EditorToolbarOption_Format}"> <toolkit:TabbedCommandBarItem DefaultLabelPosition="Collapsed" Header="{x:Bind domain:Translator.EditorToolbarOption_Format}">
<AppBarToggleButton <AppBarToggleButton IsChecked="{x:Bind WebViewEditor.IsEditorBold, Mode=TwoWay}" Label="Bold">
Width="Auto"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorBold, Mode=TwoWay}"
Label="Bold">
<AppBarToggleButton.Icon> <AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource BoldPathIcon}" /> <PathIcon Data="{StaticResource BoldPathIcon}" />
</AppBarToggleButton.Icon> </AppBarToggleButton.Icon>
</AppBarToggleButton> </AppBarToggleButton>
<AppBarToggleButton <AppBarToggleButton IsChecked="{x:Bind WebViewEditor.IsEditorItalic, Mode=TwoWay}" Label="Italic">
Width="Auto"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorItalic, Mode=TwoWay}"
Label="Italic">
<AppBarToggleButton.Icon> <AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource ItalicPathIcon}" /> <PathIcon Data="{StaticResource ItalicPathIcon}" />
</AppBarToggleButton.Icon> </AppBarToggleButton.Icon>
</AppBarToggleButton> </AppBarToggleButton>
<AppBarToggleButton <AppBarToggleButton IsChecked="{x:Bind WebViewEditor.IsEditorUnderline, Mode=TwoWay}" Label="Underline">
Width="Auto"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorUnderline, Mode=TwoWay}"
Label="Underline">
<AppBarToggleButton.Icon> <AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource UnderlinePathIcon}" /> <PathIcon Data="{StaticResource UnderlinePathIcon}" />
</AppBarToggleButton.Icon> </AppBarToggleButton.Icon>
</AppBarToggleButton> </AppBarToggleButton>
<AppBarToggleButton <AppBarToggleButton IsChecked="{x:Bind WebViewEditor.IsEditorStrikethrough, Mode=TwoWay}" Label="Stroke">
Width="Auto"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorStrikethrough, Mode=TwoWay}"
Label="Stroke">
<AppBarToggleButton.Icon> <AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource StrikePathIcon}" /> <PathIcon Data="{StaticResource StrikePathIcon}" />
</AppBarToggleButton.Icon> </AppBarToggleButton.Icon>
@@ -266,21 +246,13 @@
<AppBarSeparator /> <AppBarSeparator />
<AppBarToggleButton <AppBarToggleButton IsChecked="{x:Bind WebViewEditor.IsEditorUl, Mode=TwoWay}" Label="Bullet List">
Width="Auto"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorUl, Mode=TwoWay}"
Label="Bullet List">
<AppBarToggleButton.Icon> <AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource BulletedListPathIcon}" /> <PathIcon Data="{StaticResource BulletedListPathIcon}" />
</AppBarToggleButton.Icon> </AppBarToggleButton.Icon>
</AppBarToggleButton> </AppBarToggleButton>
<AppBarToggleButton <AppBarToggleButton IsChecked="{x:Bind WebViewEditor.IsEditorOl, Mode=TwoWay}" Label="Ordered List">
Width="Auto"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorOl, Mode=TwoWay}"
Label="Ordered List">
<AppBarToggleButton.Icon> <AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource OrderedListPathIcon}" /> <PathIcon Data="{StaticResource OrderedListPathIcon}" />
</AppBarToggleButton.Icon> </AppBarToggleButton.Icon>
@@ -289,8 +261,6 @@
<AppBarSeparator /> <AppBarSeparator />
<AppBarButton <AppBarButton
Width="Auto"
MinWidth="40"
Click="{x:Bind WebViewEditor.EditorOutdentAsync}" Click="{x:Bind WebViewEditor.EditorOutdentAsync}"
IsEnabled="{x:Bind WebViewEditor.IsEditorOutdentEnabled, Mode=OneWay}" IsEnabled="{x:Bind WebViewEditor.IsEditorOutdentEnabled, Mode=OneWay}"
Label="Outdent"> Label="Outdent">
@@ -302,8 +272,6 @@
</AppBarButton> </AppBarButton>
<AppBarButton <AppBarButton
Width="Auto"
MinWidth="40"
Click="{x:Bind WebViewEditor.EditorIndentAsync}" Click="{x:Bind WebViewEditor.EditorIndentAsync}"
IsEnabled="{x:Bind WebViewEditor.IsEditorIndentEnabled, Mode=OneWay}" IsEnabled="{x:Bind WebViewEditor.IsEditorIndentEnabled, Mode=OneWay}"
Label="Indent"> Label="Indent">
@@ -314,11 +282,7 @@
</AppBarButton.Content> </AppBarButton.Content>
</AppBarButton> </AppBarButton>
<AppBarElementContainer <AppBarElementContainer HorizontalAlignment="Center" VerticalAlignment="Center">
Width="Auto"
MinWidth="40"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<ComboBox <ComboBox
x:Name="AlignmentListView" x:Name="AlignmentListView"
VerticalAlignment="Center" VerticalAlignment="Center"
@@ -366,8 +330,6 @@
<AppBarSeparator /> <AppBarSeparator />
<AppBarToggleButton <AppBarToggleButton
Width="Auto"
MinWidth="40"
IsChecked="{x:Bind WebViewEditor.IsEditorWebViewEditor, Mode=TwoWay}" IsChecked="{x:Bind WebViewEditor.IsEditorWebViewEditor, Mode=TwoWay}"
Label="{x:Bind domain:Translator.EditorTooltip_WebViewEditor}" Label="{x:Bind domain:Translator.EditorTooltip_WebViewEditor}"
ToolTipService.ToolTip="{x:Bind domain:Translator.EditorTooltip_WebViewEditor}"> ToolTipService.ToolTip="{x:Bind domain:Translator.EditorTooltip_WebViewEditor}">

View File

@@ -52,7 +52,7 @@ public sealed partial class ComposePage : ComposePageAbstract,
if (e.NewFocusedElement == WebViewEditor) if (e.NewFocusedElement == WebViewEditor)
{ {
await WebViewEditor.FocusEditorAsync(true); await WebViewEditor.FocusEditorAsync(false);
} }
} }

View File

@@ -113,7 +113,6 @@
IsAvatarVisible="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsShowSenderPicturesEnabled, Mode=OneWay}" IsAvatarVisible="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsShowSenderPicturesEnabled, Mode=OneWay}"
IsCustomFocused="{x:Bind IsCustomFocused, Mode=OneWay}" IsCustomFocused="{x:Bind IsCustomFocused, Mode=OneWay}"
IsHoverActionsEnabled="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsHoverActionsEnabled, Mode=OneWay}" IsHoverActionsEnabled="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsHoverActionsEnabled, Mode=OneWay}"
IsThumbnailUpdated="{x:Bind ThumbnailUpdatedEvent, Mode=OneWay}"
LeftHoverAction="{Binding ElementName=root, Path=ViewModel.PreferencesService.LeftHoverAction, Mode=OneWay}" LeftHoverAction="{Binding ElementName=root, Path=ViewModel.PreferencesService.LeftHoverAction, Mode=OneWay}"
MailItem="{x:Bind MailCopy, Mode=OneWay}" MailItem="{x:Bind MailCopy, Mode=OneWay}"
Prefer24HourTimeFormat="{Binding ElementName=root, Path=ViewModel.PreferencesService.Prefer24HourTimeFormat, Mode=OneWay}" Prefer24HourTimeFormat="{Binding ElementName=root, Path=ViewModel.PreferencesService.Prefer24HourTimeFormat, Mode=OneWay}"
@@ -137,7 +136,6 @@
IsAvatarVisible="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsShowSenderPicturesEnabled, Mode=OneWay}" IsAvatarVisible="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsShowSenderPicturesEnabled, Mode=OneWay}"
IsCustomFocused="{x:Bind IsCustomFocused, Mode=OneWay}" IsCustomFocused="{x:Bind IsCustomFocused, Mode=OneWay}"
IsHoverActionsEnabled="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsHoverActionsEnabled, Mode=OneWay}" IsHoverActionsEnabled="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsHoverActionsEnabled, Mode=OneWay}"
IsThumbnailUpdated="{x:Bind ThumbnailUpdatedEvent, Mode=OneWay}"
LeftHoverAction="{Binding ElementName=root, Path=ViewModel.PreferencesService.LeftHoverAction, Mode=OneWay}" LeftHoverAction="{Binding ElementName=root, Path=ViewModel.PreferencesService.LeftHoverAction, Mode=OneWay}"
MailItem="{x:Bind MailCopy, Mode=OneWay}" MailItem="{x:Bind MailCopy, Mode=OneWay}"
Prefer24HourTimeFormat="{Binding ElementName=root, Path=ViewModel.PreferencesService.Prefer24HourTimeFormat, Mode=OneWay}" Prefer24HourTimeFormat="{Binding ElementName=root, Path=ViewModel.PreferencesService.Prefer24HourTimeFormat, Mode=OneWay}"

View File

@@ -46,8 +46,7 @@
Height="36" Height="36"
FromAddress="{x:Bind Address}" FromAddress="{x:Bind Address}"
FromName="{x:Bind Name}" FromName="{x:Bind Name}"
SenderContactPicture="{x:Bind Base64ContactPicture}" SenderContactPicture="{x:Bind Base64ContactPicture}" />
ThumbnailUpdatedEvent="{x:Bind ThumbnailUpdatedEvent, Mode=OneWay}" />
<TextBlock Grid.Column="1" Text="{x:Bind Name}" /> <TextBlock Grid.Column="1" Text="{x:Bind Name}" />
@@ -157,11 +156,6 @@
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ChildrenTransitions>
<TransitionCollection>
<RepositionThemeTransition IsStaggeringEnabled="False" />
</TransitionCollection>
</Grid.ChildrenTransitions>
<Border <Border
Background="{ThemeResource WinoContentZoneBackgroud}" Background="{ThemeResource WinoContentZoneBackgroud}"

View File

@@ -51,13 +51,7 @@
</Page.Resources> </Page.Resources>
<ScrollViewer> <ScrollViewer>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}"> <StackPanel Spacing="3">
<StackPanel.ChildrenTransitions>
<TransitionCollection>
<RepositionThemeTransition IsStaggeringEnabled="False" />
</TransitionCollection>
</StackPanel.ChildrenTransitions>
<!-- Accent Color --> <!-- Accent Color -->
<controls:SettingsExpander <controls:SettingsExpander
Description="{x:Bind domain:Translator.SettingsAccentColor_Description}" Description="{x:Bind domain:Translator.SettingsAccentColor_Description}"

View File

@@ -10,7 +10,7 @@
mc:Ignorable="d"> mc:Ignorable="d">
<ScrollViewer> <ScrollViewer>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}"> <StackPanel>
<controls:SettingsCard Description="{x:Bind domain:Translator.SettingsAppPreferences_StartupBehavior_Description}" Header="{x:Bind domain:Translator.SettingsAppPreferences_StartupBehavior_Title}"> <controls:SettingsCard Description="{x:Bind domain:Translator.SettingsAppPreferences_StartupBehavior_Description}" Header="{x:Bind domain:Translator.SettingsAppPreferences_StartupBehavior_Title}">
<ToggleButton <ToggleButton
x:Name="StartupEnabledToggleButton" x:Name="StartupEnabledToggleButton"

View File

@@ -11,17 +11,11 @@
xmlns:helpers="using:Wino.Helpers" xmlns:helpers="using:Wino.Helpers"
xmlns:imapsetup="using:Wino.Views.ImapSetup" xmlns:imapsetup="using:Wino.Views.ImapSetup"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls" xmlns:picker="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d"> mc:Ignorable="d">
<ScrollViewer> <ScrollViewer>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}"> <StackPanel Spacing="3">
<StackPanel.ChildrenTransitions>
<TransitionCollection>
<RepositionThemeTransition IsStaggeringEnabled="False" />
</TransitionCollection>
</StackPanel.ChildrenTransitions>
<controls:SettingsExpander Description="{x:Bind domain:Translator.AccountDetailsPage_Description}" Header="{x:Bind domain:Translator.AccountDetailsPage_Title}"> <controls:SettingsExpander Description="{x:Bind domain:Translator.AccountDetailsPage_Description}" Header="{x:Bind domain:Translator.AccountDetailsPage_Title}">
<controls:SettingsExpander.HeaderIcon> <controls:SettingsExpander.HeaderIcon>
<SymbolIcon Symbol="Contact" /> <SymbolIcon Symbol="Contact" />
@@ -118,7 +112,7 @@
Header="{x:Bind domain:Translator.IMAPSetupDialog_IncomingMailServer}" Header="{x:Bind domain:Translator.IMAPSetupDialog_IncomingMailServer}"
Text="{x:Bind ViewModel.ServerInformation.IncomingServer, Mode=TwoWay}" /> Text="{x:Bind ViewModel.ServerInformation.IncomingServer, Mode=TwoWay}" />
<muxc:NumberBox <picker:NumberBox
Grid.Row="2" Grid.Row="2"
Header="{x:Bind domain:Translator.IMAPSetupDialog_IncomingMailServerPort}" Header="{x:Bind domain:Translator.IMAPSetupDialog_IncomingMailServerPort}"
Maximum="65535" Maximum="65535"
@@ -169,7 +163,7 @@
Header="{x:Bind domain:Translator.IMAPSetupDialog_OutgoingMailServer}" Header="{x:Bind domain:Translator.IMAPSetupDialog_OutgoingMailServer}"
Text="{x:Bind ViewModel.ServerInformation.OutgoingServer, Mode=TwoWay}" /> Text="{x:Bind ViewModel.ServerInformation.OutgoingServer, Mode=TwoWay}" />
<muxc:NumberBox <picker:NumberBox
Grid.Row="2" Grid.Row="2"
Grid.Column="2" Grid.Column="2"
Header="{x:Bind domain:Translator.IMAPSetupDialog_OutgoingMailServerPort}" Header="{x:Bind domain:Translator.IMAPSetupDialog_OutgoingMailServerPort}"
@@ -215,13 +209,13 @@
Orientation="Horizontal" Orientation="Horizontal"
Spacing="12"> Spacing="12">
<muxc:ProgressRing <ProgressRing
Width="20" Width="5"
Height="20" Height="5"
IsActive="{x:Bind ViewModel.ValidateImapSettingsCommand.IsRunning, Mode=OneWay}" /> IsActive="{x:Bind ViewModel.ValidateImapSettingsCommand.IsRunning, Mode=OneWay}" />
<Button Command="{x:Bind ViewModel.ValidateImapSettingsCommand}" Content="Test" /> <Button Command="{x:Bind ViewModel.ValidateImapSettingsCommand}" Content="Test" />
<Button <Button
Command="{x:Bind ViewModel.UpdateCustomServerInformationCommand}" Command="{x:Bind ViewModel.SaveWithoutGoBackCommand}"
Content="{x:Bind domain:Translator.Buttons_Save}" Content="{x:Bind domain:Translator.Buttons_Save}"
Style="{ThemeResource AccentButtonStyle}" /> Style="{ThemeResource AccentButtonStyle}" />
</StackPanel> </StackPanel>

View File

@@ -10,7 +10,7 @@
mc:Ignorable="d"> mc:Ignorable="d">
<ScrollViewer> <ScrollViewer>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}"> <StackPanel>
<controls:SettingsCard <controls:SettingsCard
CommandParameter="Language" CommandParameter="Language"
Description="{x:Bind domain:Translator.SettingsLanguage_Description}" Description="{x:Bind domain:Translator.SettingsLanguage_Description}"

File diff suppressed because one or more lines are too long

View File

@@ -11,14 +11,8 @@
mc:Ignorable="d"> mc:Ignorable="d">
<ScrollViewer> <ScrollViewer>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}"> <StackPanel Spacing="4">
<StackPanel.ChildrenTransitions> <TextBlock FontWeight="SemiBold" Text="{x:Bind domain:Translator.SettingsReader_Title}" />
<TransitionCollection>
<RepositionThemeTransition IsStaggeringEnabled="False" />
</TransitionCollection>
</StackPanel.ChildrenTransitions>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{x:Bind domain:Translator.SettingsReader_Title}" />
<controls:SettingsExpander <controls:SettingsExpander
Description="{x:Bind domain:Translator.SettingsReaderFontFamily_Description}" Description="{x:Bind domain:Translator.SettingsReaderFontFamily_Description}"
Header="{x:Bind domain:Translator.SettingsReaderFont_Title}" Header="{x:Bind domain:Translator.SettingsReaderFont_Title}"
@@ -58,13 +52,6 @@
</controls:SettingsExpander.Items> </controls:SettingsExpander.Items>
</controls:SettingsExpander> </controls:SettingsExpander>
<controls:SettingsCard Description="{x:Bind domain:Translator.SettingsMailRendering_ActionLabels_Description}" Header="{x:Bind domain:Translator.SettingsMailRendering_ActionLabels_Title}">
<controls:SettingsCard.HeaderIcon>
<PathIcon Data="F1 M 0 7.5 C 0 6.822917 0.169271 6.191406 0.507812 5.605469 C 0.839844 5.039062 1.289062 4.589844 1.855469 4.257812 C 2.441406 3.919271 3.072917 3.75 3.75 3.75 L 16.25 3.75 C 16.927082 3.75 17.558594 3.919271 18.144531 4.257812 C 18.710938 4.589844 19.160156 5.039062 19.492188 5.605469 C 19.830729 6.191406 20 6.822917 20 7.5 L 20 11.25 C 20 11.927084 19.830729 12.558594 19.492188 13.144531 C 19.160156 13.710938 18.710938 14.160156 18.144531 14.492188 C 17.558594 14.830729 16.927082 15 16.25 15 L 3.75 15 C 3.072917 15 2.441406 14.830729 1.855469 14.492188 C 1.289062 14.160156 0.839844 13.710938 0.507812 13.144531 C 0.169271 12.558594 0 11.927084 0 11.25 Z M 3.75 5 C 3.294271 5.000001 2.875977 5.112306 2.495117 5.336914 C 2.114258 5.561524 1.811523 5.864259 1.586914 6.245117 C 1.362305 6.625978 1.25 7.044271 1.25 7.5 L 1.25 11.25 C 1.25 11.705729 1.362305 12.124023 1.586914 12.504883 C 1.811523 12.885742 2.114258 13.188477 2.495117 13.413086 C 2.875977 13.637695 3.294271 13.75 3.75 13.75 L 16.25 13.75 C 16.705729 13.75 17.124023 13.637695 17.504883 13.413086 C 17.885742 13.188477 18.188477 12.885742 18.413086 12.504883 C 18.637695 12.124023 18.75 11.705729 18.75 11.25 L 18.75 7.5 C 18.75 7.044271 18.637695 6.625978 18.413086 6.245117 C 18.188477 5.864259 17.885742 5.561524 17.504883 5.336914 C 17.124023 5.112306 16.705729 5.000001 16.25 5 Z M 8.75 9.375 C 8.75 9.199219 8.810221 9.051107 8.930664 8.930664 C 9.051106 8.810222 9.199219 8.75 9.375 8.75 L 15 8.75 C 15.17578 8.75 15.323893 8.810222 15.444336 8.930664 C 15.564778 9.051107 15.625 9.199219 15.625 9.375 C 15.625 9.550781 15.564778 9.698894 15.444336 9.819336 C 15.323893 9.939779 15.17578 10 15 10 L 9.375 10 C 9.199219 10 9.051106 9.939779 8.930664 9.819336 C 8.810221 9.698894 8.75 9.550781 8.75 9.375 Z M 7.5 9.375 C 7.5 9.713542 7.415364 10.026042 7.246094 10.3125 C 7.076823 10.598959 6.848958 10.826823 6.5625 10.996094 C 6.276042 11.165365 5.963542 11.25 5.625 11.25 C 5.286458 11.25 4.973958 11.165365 4.6875 10.996094 C 4.401042 10.826823 4.173177 10.598959 4.003906 10.3125 C 3.834635 10.026042 3.75 9.713542 3.75 9.375 C 3.75 9.036459 3.834635 8.723959 4.003906 8.4375 C 4.173177 8.151042 4.401042 7.923178 4.6875 7.753906 C 4.973958 7.584636 5.286458 7.5 5.625 7.5 C 5.963542 7.5 6.276042 7.584636 6.5625 7.753906 C 6.848958 7.923178 7.076823 8.151042 7.246094 8.4375 C 7.415364 8.723959 7.5 9.036459 7.5 9.375 Z " />
</controls:SettingsCard.HeaderIcon>
<ToggleSwitch IsOn="{x:Bind ViewModel.PreferencesService.IsShowActionLabelsEnabled, Mode=TwoWay}" />
</controls:SettingsCard>
<controls:SettingsExpander Description="{x:Bind domain:Translator.SettingsExternalContent_Description}" Header="{x:Bind domain:Translator.SettingsExternalContent_Title}"> <controls:SettingsExpander Description="{x:Bind domain:Translator.SettingsExternalContent_Description}" Header="{x:Bind domain:Translator.SettingsExternalContent_Title}">
<controls:SettingsExpander.HeaderIcon> <controls:SettingsExpander.HeaderIcon>
<PathIcon Data="F1 M 4.023438 13.75 C 3.476562 13.75 2.958984 13.636068 2.470703 13.408203 C 1.982422 13.180339 1.554362 12.875977 1.186523 12.495117 C 0.818685 12.114258 0.528971 11.674805 0.317383 11.176758 C 0.105794 10.678711 0 10.159506 0 9.619141 C 0 9.065756 0.094401 8.535156 0.283203 8.027344 C 0.472005 7.519531 0.737305 7.068686 1.079102 6.674805 C 1.420898 6.280926 1.829427 5.961915 2.304688 5.717773 C 2.779948 5.473634 3.304036 5.338543 3.876953 5.3125 L 4.189453 5.302734 C 4.261067 4.501953 4.453125 3.776043 4.765625 3.125 C 5.078125 2.473959 5.488281 1.915691 5.996094 1.450195 C 6.503906 0.984701 7.097981 0.626629 7.77832 0.375977 C 8.458658 0.125326 9.199219 0 10 0 C 10.800781 0 11.541341 0.126953 12.22168 0.380859 C 12.902018 0.634766 13.496093 0.99284 14.003906 1.455078 C 14.511718 1.917318 14.921874 2.473959 15.234375 3.125 C 15.546874 3.776043 15.738932 4.501953 15.810547 5.302734 L 15.966797 5.302734 C 16.513672 5.302734 17.032877 5.416667 17.524414 5.644531 C 18.015949 5.872396 18.44401 6.176758 18.808594 6.557617 C 19.173176 6.938477 19.462891 7.379558 19.677734 7.880859 C 19.892578 8.382162 20 8.902995 20 9.443359 L 20 9.667969 C 20 9.700521 20 9.736328 20 9.775391 C 20 9.814453 19.996744 9.850261 19.990234 9.882812 C 19.573566 9.375 19.108072 8.932292 18.59375 8.554688 C 18.489582 8.248698 18.346354 7.972006 18.164062 7.724609 C 17.98177 7.477214 17.770182 7.267253 17.529297 7.094727 C 17.28841 6.922201 17.021484 6.788737 16.728516 6.694336 C 16.435547 6.599936 16.129557 6.552735 15.810547 6.552734 C 15.472005 6.552735 15.192057 6.446941 14.970703 6.235352 C 14.749349 6.023764 14.61263 5.755209 14.560547 5.429688 C 14.527994 5.195312 14.49056 4.967448 14.448242 4.746094 C 14.405924 4.52474 14.342447 4.300131 14.257812 4.072266 C 14.088541 3.603516 13.862304 3.193359 13.579102 2.841797 C 13.295897 2.490234 12.970377 2.195639 12.602539 1.958008 C 12.2347 1.720379 11.831055 1.542969 11.391602 1.425781 C 10.952148 1.308594 10.488281 1.25 10 1.25 C 9.511719 1.25 9.047852 1.308594 8.608398 1.425781 C 8.168945 1.542969 7.765299 1.71875 7.397461 1.953125 C 7.029622 2.1875 6.704102 2.480469 6.420898 2.832031 C 6.137695 3.183594 5.911458 3.59375 5.742188 4.0625 C 5.657552 4.290365 5.594075 4.514975 5.551758 4.736328 C 5.50944 4.957683 5.472005 5.188803 5.439453 5.429688 C 5.38737 5.813803 5.236002 6.097006 4.985352 6.279297 C 4.7347 6.46159 4.423828 6.552735 4.052734 6.552734 C 3.655599 6.552735 3.286133 6.635743 2.944336 6.801758 C 2.602539 6.967774 2.306315 7.189129 2.055664 7.46582 C 1.805013 7.742514 1.608073 8.059896 1.464844 8.417969 C 1.321615 8.776042 1.25 9.147136 1.25 9.53125 C 1.25 9.928386 1.321615 10.30599 1.464844 10.664062 C 1.608073 11.022136 1.806641 11.337891 2.060547 11.611328 C 2.314453 11.884766 2.61556 12.101237 2.963867 12.260742 C 3.312174 12.420248 3.691406 12.5 4.101562 12.5 L 7.431641 12.5 C 7.373047 12.708334 7.327474 12.916667 7.294922 13.125 C 7.26237 13.333334 7.236328 13.541667 7.216797 13.75 Z M 8.75 14.375 C 8.75 13.600261 8.898111 12.871094 9.194336 12.1875 C 9.49056 11.503906 9.892578 10.908203 10.400391 10.400391 C 10.908203 9.892578 11.503906 9.490561 12.1875 9.194336 C 12.871093 8.898112 13.60026 8.75 14.375 8.75 C 14.889322 8.75 15.385741 8.816732 15.864258 8.950195 C 16.342773 9.083659 16.790363 9.272461 17.207031 9.516602 C 17.623697 9.760742 18.004557 10.055339 18.349609 10.400391 C 18.69466 10.745443 18.989258 11.126303 19.233398 11.542969 C 19.477539 11.959636 19.66634 12.407227 19.799805 12.885742 C 19.933268 13.364258 20 13.860678 20 14.375 C 20 15.14974 19.851887 15.878906 19.555664 16.5625 C 19.259439 17.246094 18.857422 17.841797 18.349609 18.349609 C 17.841797 18.857422 17.246094 19.259439 16.5625 19.555664 C 15.878906 19.851889 15.149739 20 14.375 20 C 13.59375 20 12.861328 19.853516 12.177734 19.560547 C 11.494141 19.267578 10.898438 18.867188 10.390625 18.359375 C 9.882812 17.851562 9.482422 17.255859 9.189453 16.572266 C 8.896484 15.888672 8.75 15.15625 8.75 14.375 Z M 14.375 17.578125 C 14.570312 17.578125 14.736328 17.509766 14.873047 17.373047 L 17.373047 14.873047 C 17.509766 14.736328 17.578125 14.570312 17.578125 14.375 C 17.578125 14.179688 17.509766 14.013672 17.373047 13.876953 C 17.236328 13.740234 17.070312 13.671875 16.875 13.671875 C 16.679688 13.671875 16.513672 13.740234 16.376953 13.876953 L 15 15.253906 L 15 11.875 C 14.999999 11.705729 14.93815 11.559245 14.814453 11.435547 C 14.690755 11.31185 14.544271 11.25 14.375 11.25 C 14.205729 11.25 14.059244 11.31185 13.935547 11.435547 C 13.811849 11.559245 13.75 11.705729 13.75 11.875 L 13.75 15.253906 L 12.373047 13.876953 C 12.236328 13.740234 12.070312 13.671875 11.875 13.671875 C 11.679688 13.671875 11.513672 13.740234 11.376953 13.876953 C 11.240234 14.013672 11.171875 14.179688 11.171875 14.375 C 11.171875 14.570312 11.240234 14.736328 11.376953 14.873047 L 13.876953 17.373047 C 14.013672 17.509766 14.179688 17.578125 14.375 17.578125 Z " /> <PathIcon Data="F1 M 4.023438 13.75 C 3.476562 13.75 2.958984 13.636068 2.470703 13.408203 C 1.982422 13.180339 1.554362 12.875977 1.186523 12.495117 C 0.818685 12.114258 0.528971 11.674805 0.317383 11.176758 C 0.105794 10.678711 0 10.159506 0 9.619141 C 0 9.065756 0.094401 8.535156 0.283203 8.027344 C 0.472005 7.519531 0.737305 7.068686 1.079102 6.674805 C 1.420898 6.280926 1.829427 5.961915 2.304688 5.717773 C 2.779948 5.473634 3.304036 5.338543 3.876953 5.3125 L 4.189453 5.302734 C 4.261067 4.501953 4.453125 3.776043 4.765625 3.125 C 5.078125 2.473959 5.488281 1.915691 5.996094 1.450195 C 6.503906 0.984701 7.097981 0.626629 7.77832 0.375977 C 8.458658 0.125326 9.199219 0 10 0 C 10.800781 0 11.541341 0.126953 12.22168 0.380859 C 12.902018 0.634766 13.496093 0.99284 14.003906 1.455078 C 14.511718 1.917318 14.921874 2.473959 15.234375 3.125 C 15.546874 3.776043 15.738932 4.501953 15.810547 5.302734 L 15.966797 5.302734 C 16.513672 5.302734 17.032877 5.416667 17.524414 5.644531 C 18.015949 5.872396 18.44401 6.176758 18.808594 6.557617 C 19.173176 6.938477 19.462891 7.379558 19.677734 7.880859 C 19.892578 8.382162 20 8.902995 20 9.443359 L 20 9.667969 C 20 9.700521 20 9.736328 20 9.775391 C 20 9.814453 19.996744 9.850261 19.990234 9.882812 C 19.573566 9.375 19.108072 8.932292 18.59375 8.554688 C 18.489582 8.248698 18.346354 7.972006 18.164062 7.724609 C 17.98177 7.477214 17.770182 7.267253 17.529297 7.094727 C 17.28841 6.922201 17.021484 6.788737 16.728516 6.694336 C 16.435547 6.599936 16.129557 6.552735 15.810547 6.552734 C 15.472005 6.552735 15.192057 6.446941 14.970703 6.235352 C 14.749349 6.023764 14.61263 5.755209 14.560547 5.429688 C 14.527994 5.195312 14.49056 4.967448 14.448242 4.746094 C 14.405924 4.52474 14.342447 4.300131 14.257812 4.072266 C 14.088541 3.603516 13.862304 3.193359 13.579102 2.841797 C 13.295897 2.490234 12.970377 2.195639 12.602539 1.958008 C 12.2347 1.720379 11.831055 1.542969 11.391602 1.425781 C 10.952148 1.308594 10.488281 1.25 10 1.25 C 9.511719 1.25 9.047852 1.308594 8.608398 1.425781 C 8.168945 1.542969 7.765299 1.71875 7.397461 1.953125 C 7.029622 2.1875 6.704102 2.480469 6.420898 2.832031 C 6.137695 3.183594 5.911458 3.59375 5.742188 4.0625 C 5.657552 4.290365 5.594075 4.514975 5.551758 4.736328 C 5.50944 4.957683 5.472005 5.188803 5.439453 5.429688 C 5.38737 5.813803 5.236002 6.097006 4.985352 6.279297 C 4.7347 6.46159 4.423828 6.552735 4.052734 6.552734 C 3.655599 6.552735 3.286133 6.635743 2.944336 6.801758 C 2.602539 6.967774 2.306315 7.189129 2.055664 7.46582 C 1.805013 7.742514 1.608073 8.059896 1.464844 8.417969 C 1.321615 8.776042 1.25 9.147136 1.25 9.53125 C 1.25 9.928386 1.321615 10.30599 1.464844 10.664062 C 1.608073 11.022136 1.806641 11.337891 2.060547 11.611328 C 2.314453 11.884766 2.61556 12.101237 2.963867 12.260742 C 3.312174 12.420248 3.691406 12.5 4.101562 12.5 L 7.431641 12.5 C 7.373047 12.708334 7.327474 12.916667 7.294922 13.125 C 7.26237 13.333334 7.236328 13.541667 7.216797 13.75 Z M 8.75 14.375 C 8.75 13.600261 8.898111 12.871094 9.194336 12.1875 C 9.49056 11.503906 9.892578 10.908203 10.400391 10.400391 C 10.908203 9.892578 11.503906 9.490561 12.1875 9.194336 C 12.871093 8.898112 13.60026 8.75 14.375 8.75 C 14.889322 8.75 15.385741 8.816732 15.864258 8.950195 C 16.342773 9.083659 16.790363 9.272461 17.207031 9.516602 C 17.623697 9.760742 18.004557 10.055339 18.349609 10.400391 C 18.69466 10.745443 18.989258 11.126303 19.233398 11.542969 C 19.477539 11.959636 19.66634 12.407227 19.799805 12.885742 C 19.933268 13.364258 20 13.860678 20 14.375 C 20 15.14974 19.851887 15.878906 19.555664 16.5625 C 19.259439 17.246094 18.857422 17.841797 18.349609 18.349609 C 17.841797 18.857422 17.246094 19.259439 16.5625 19.555664 C 15.878906 19.851889 15.149739 20 14.375 20 C 13.59375 20 12.861328 19.853516 12.177734 19.560547 C 11.494141 19.267578 10.898438 18.867188 10.390625 18.359375 C 9.882812 17.851562 9.482422 17.255859 9.189453 16.572266 C 8.896484 15.888672 8.75 15.15625 8.75 14.375 Z M 14.375 17.578125 C 14.570312 17.578125 14.736328 17.509766 14.873047 17.373047 L 17.373047 14.873047 C 17.509766 14.736328 17.578125 14.570312 17.578125 14.375 C 17.578125 14.179688 17.509766 14.013672 17.373047 13.876953 C 17.236328 13.740234 17.070312 13.671875 16.875 13.671875 C 16.679688 13.671875 16.513672 13.740234 16.376953 13.876953 L 15 15.253906 L 15 11.875 C 14.999999 11.705729 14.93815 11.559245 14.814453 11.435547 C 14.690755 11.31185 14.544271 11.25 14.375 11.25 C 14.205729 11.25 14.059244 11.31185 13.935547 11.435547 C 13.811849 11.559245 13.75 11.705729 13.75 11.875 L 13.75 15.253906 L 12.373047 13.876953 C 12.236328 13.740234 12.070312 13.671875 11.875 13.671875 C 11.679688 13.671875 11.513672 13.740234 11.376953 13.876953 C 11.240234 14.013672 11.171875 14.179688 11.171875 14.375 C 11.171875 14.570312 11.240234 14.736328 11.376953 14.873047 L 13.876953 17.373047 C 14.013672 17.509766 14.179688 17.578125 14.375 17.578125 Z " />
@@ -84,14 +71,17 @@
</controls:SettingsCard> </controls:SettingsCard>
<controls:SettingsCard Header="{x:Bind domain:Translator.SettingsLoadPlaintextLinks_Title}"> <controls:SettingsCard Header="{x:Bind domain:Translator.SettingsLoadPlaintextLinks_Title}">
<controls:SettingsCard.HeaderIcon> <controls:SettingsCard.HeaderIcon>
<PathIcon Data="{StaticResource AddLinkPathIcon}" /> <PathIcon Data="{StaticResource AddLinkPathIcon}" />
</controls:SettingsCard.HeaderIcon> </controls:SettingsCard.HeaderIcon>
<ToggleSwitch IsOn="{x:Bind ViewModel.PreferencesService.RenderPlaintextLinks, Mode=TwoWay}" /> <ToggleSwitch IsOn="{x:Bind ViewModel.PreferencesService.RenderPlaintextLinks, Mode=TwoWay}" />
</controls:SettingsCard> </controls:SettingsCard>
</controls:SettingsExpander.Items> </controls:SettingsExpander.Items>
</controls:SettingsExpander> </controls:SettingsExpander>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{x:Bind domain:Translator.SettingsComposer_Title}" /> <TextBlock
Margin="0,20,0,0"
FontWeight="SemiBold"
Text="{x:Bind domain:Translator.SettingsComposer_Title}" />
<controls:SettingsExpander <controls:SettingsExpander
Description="{x:Bind domain:Translator.SettingsComposerFontFamily_Description}" Description="{x:Bind domain:Translator.SettingsComposerFontFamily_Description}"
Header="{x:Bind domain:Translator.SettingsComposerFont_Title}" Header="{x:Bind domain:Translator.SettingsComposerFont_Title}"
@@ -132,4 +122,4 @@
</controls:SettingsExpander> </controls:SettingsExpander>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>
</abstract:ReadComposePanePageAbstract> </abstract:ReadComposePanePageAbstract>

View File

@@ -53,7 +53,7 @@
</Page.Resources> </Page.Resources>
<ScrollViewer> <ScrollViewer>
<Grid> <Grid RowSpacing="41">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
@@ -69,8 +69,8 @@
<ToggleSwitch IsOn="{x:Bind ViewModel.IsSignatureEnabled, Mode=TwoWay}" /> <ToggleSwitch IsOn="{x:Bind ViewModel.IsSignatureEnabled, Mode=TwoWay}" />
</controls1:SettingsCard> </controls1:SettingsCard>
<StackPanel Grid.Row="1" Spacing="{StaticResource SettingsCardSpacing}"> <StackPanel Grid.Row="1" Spacing="4">
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{x:Bind domain:Translator.SettingsSignature_SignatureDefaults}" /> <TextBlock FontWeight="SemiBold" Text="{x:Bind domain:Translator.SettingsSignature_SignatureDefaults}" />
<controls1:SettingsCard <controls1:SettingsCard
Header="{x:Bind domain:Translator.SettingsSignature_ForNewMessages_Title}" Header="{x:Bind domain:Translator.SettingsSignature_ForNewMessages_Title}"
IsActionIconVisible="False" IsActionIconVisible="False"
@@ -100,8 +100,8 @@
</controls1:SettingsCard> </controls1:SettingsCard>
</StackPanel> </StackPanel>
<StackPanel Grid.Row="2" Spacing="{StaticResource SettingsCardSpacing}"> <StackPanel Grid.Row="2" Spacing="3">
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{x:Bind domain:Translator.SettingsSignature_Signatures}" /> <TextBlock FontWeight="SemiBold" Text="{x:Bind domain:Translator.SettingsSignature_Signatures}" />
<controls1:SettingsCard <controls1:SettingsCard
Header="{x:Bind domain:Translator.SettingsSignature_AddCustomSignature_Title}" Header="{x:Bind domain:Translator.SettingsSignature_AddCustomSignature_Title}"
IsActionIconVisible="False" IsActionIconVisible="False"

View File

@@ -26,13 +26,19 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="Assets\EML\eml.png" /> <None Remove="Assets\EML\eml.png" />
<None Remove="Assets\NotificationIcons\archive.png" />
<None Remove="Assets\NotificationIcons\delete.png" /> <None Remove="Assets\NotificationIcons\delete.png" />
<None Remove="Assets\NotificationIcons\dismiss.png" /> <None Remove="Assets\NotificationIcons\dismiss.png" />
<None Remove="Assets\NotificationIcons\markread.png" /> <None Remove="Assets\NotificationIcons\markread.png" />
<None Remove="Assets\NotificationIcons\profile-dark.png" /> <None Remove="Assets\NotificationIcons\profile-dark.png" />
<None Remove="Assets\NotificationIcons\profile-light.png" /> <None Remove="Assets\NotificationIcons\profile-light.png" />
<None Remove="Assets\ReleaseNotes\1102.md" /> <None Remove="Assets\ReleaseNotes\1102.md" />
<None Remove="Assets\Thumbnails\airbnb.com.png" />
<None Remove="Assets\Thumbnails\apple.com.png" />
<None Remove="Assets\Thumbnails\google.com.png" />
<None Remove="Assets\Thumbnails\microsoft.com.png" />
<None Remove="Assets\Thumbnails\steampowered.com.png" />
<None Remove="Assets\Thumbnails\uber.com.png" />
<None Remove="Assets\Thumbnails\youtube.com.png" />
<None Remove="JS\editor.html" /> <None Remove="JS\editor.html" />
<None Remove="JS\editor.js" /> <None Remove="JS\editor.js" />
<None Remove="JS\global.css" /> <None Remove="JS\global.css" />
@@ -45,13 +51,19 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Assets\EML\eml.png" /> <Content Include="Assets\EML\eml.png" />
<Content Include="Assets\NotificationIcons\archive.png" />
<Content Include="Assets\NotificationIcons\delete.png" /> <Content Include="Assets\NotificationIcons\delete.png" />
<Content Include="Assets\NotificationIcons\dismiss.png" /> <Content Include="Assets\NotificationIcons\dismiss.png" />
<Content Include="Assets\NotificationIcons\markread.png" /> <Content Include="Assets\NotificationIcons\markread.png" />
<Content Include="Assets\NotificationIcons\profile-dark.png" /> <Content Include="Assets\NotificationIcons\profile-dark.png" />
<Content Include="Assets\NotificationIcons\profile-light.png" /> <Content Include="Assets\NotificationIcons\profile-light.png" />
<Content Include="Assets\ReleaseNotes\1102.md" /> <Content Include="Assets\ReleaseNotes\1102.md" />
<Content Include="Assets\Thumbnails\airbnb.com.png" />
<Content Include="Assets\Thumbnails\apple.com.png" />
<Content Include="Assets\Thumbnails\google.com.png" />
<Content Include="Assets\Thumbnails\microsoft.com.png" />
<Content Include="Assets\Thumbnails\steampowered.com.png" />
<Content Include="Assets\Thumbnails\uber.com.png" />
<Content Include="Assets\Thumbnails\youtube.com.png" />
<Content Include="JS\editor.html" /> <Content Include="JS\editor.html" />
<Content Include="JS\editor.js" /> <Content Include="JS\editor.js" />
<Content Include="JS\global.css" /> <Content Include="JS\global.css" />

View File

@@ -1,4 +0,0 @@
using Wino.Core.Domain.Interfaces;
namespace Wino.Messaging.UI;
public record ThumbnailAdded(string Email): IUIMessage;

View File

@@ -79,7 +79,6 @@ public partial class App : Application
services.AddTransient<INotificationBuilder, NotificationBuilder>(); services.AddTransient<INotificationBuilder, NotificationBuilder>();
services.AddTransient<IUnderlyingThemeService, UnderlyingThemeService>(); services.AddTransient<IUnderlyingThemeService, UnderlyingThemeService>();
services.AddSingleton<IApplicationConfiguration, ApplicationConfiguration>(); services.AddSingleton<IApplicationConfiguration, ApplicationConfiguration>();
services.AddSingleton<IThumbnailService, ThumbnailService>();
// Register server message handler factory. // Register server message handler factory.
var serverMessageHandlerFactory = new ServerMessageHandlerFactory(); var serverMessageHandlerFactory = new ServerMessageHandlerFactory();

View File

@@ -34,12 +34,11 @@
</Resource> </Resource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" /> <PackageReference Include="CommunityToolkit.Mvvm" />
<PackageReference Include="gravatar-dotnet" /> <PackageReference Include="H.NotifyIcon.Wpf" />
<PackageReference Include="H.NotifyIcon.Wpf" /> <PackageReference Include="CommunityToolkit.WinUI.Notifications" />
<PackageReference Include="CommunityToolkit.WinUI.Notifications" /> <PackageReference Include="Microsoft.Identity.Client" />
<PackageReference Include="Microsoft.Identity.Client" /> <PackageReference Include="System.Text.Encoding.CodePages" />
<PackageReference Include="System.Text.Encoding.CodePages" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Wino.Authentication\Wino.Authentication.csproj" /> <ProjectReference Include="..\Wino.Authentication\Wino.Authentication.csproj" />

View File

@@ -408,11 +408,6 @@ public class AccountService : BaseDatabaseService, IAccountService
ReportUIChange(new AccountUpdatedMessage(account)); ReportUIChange(new AccountUpdatedMessage(account));
} }
public async Task UpdateAccountCustomServerInformationAsync(CustomServerInformation customServerInformation)
{
await Connection.UpdateAsync(customServerInformation).ConfigureAwait(false);
}
public async Task UpdateAccountAliasesAsync(Guid accountId, List<MailAccountAlias> aliases) public async Task UpdateAccountAliasesAsync(Guid accountId, List<MailAccountAlias> aliases)
{ {
// Delete existing ones. // Delete existing ones.

View File

@@ -57,8 +57,7 @@ public class DatabaseService : IDatabaseService
typeof(AccountCalendar), typeof(AccountCalendar),
typeof(CalendarEventAttendee), typeof(CalendarEventAttendee),
typeof(CalendarItem), typeof(CalendarItem),
typeof(Reminder), typeof(Reminder)
typeof(Thumbnail)
); );
} }
} }

289
Wino.sln Normal file
View File

@@ -0,0 +1,289 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.32112.339
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Mail", "Wino.Mail\Wino.Mail.csproj", "{68A432B8-C1B7-494C-8D6D-230788EA683E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Core", "Wino.Core\Wino.Core.csproj", "{E6B1632A-8901-41E8-9DDF-6793C7698B0B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Core.UWP", "Wino.Core.UWP\Wino.Core.UWP.csproj", "{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Core.Domain", "Wino.Core.Domain\Wino.Core.Domain.csproj", "{CF3312E5-5DA0-4867-9945-49EA7598AF1F}"
ProjectSection(ProjectDependencies) = postProject
{D4919A19-E70F-4916-83D2-5D5F87BEB949} = {D4919A19-E70F-4916-83D2-5D5F87BEB949}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.BackgroundTasks", "Wino.BackgroundTasks\Wino.BackgroundTasks.csproj", "{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Mail.ViewModels", "Wino.Mail.ViewModels\Wino.Mail.ViewModels.csproj", "{D62F1C03-DA57-4709-A640-0283296A8E66}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Messaging", "Wino.Messages\Wino.Messaging.csproj", "{0C307D7E-256F-448C-8265-5622A812FBCC}"
EndProject
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Wino.Packaging", "Wino.Packaging\Wino.Packaging.wapproj", "{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Server", "Wino.Server\Wino.Server.csproj", "{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.SourceGenerators", "Wino.SourceGenerators\Wino.SourceGenerators.csproj", "{D4919A19-E70F-4916-83D2-5D5F87BEB949}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Core.ViewModels", "Wino.Core.ViewModels\Wino.Core.ViewModels.csproj", "{53723AE8-7E7E-4D54-ADAB-0A6033255CC8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Calendar.ViewModels", "Wino.Calendar.ViewModels\Wino.Calendar.ViewModels.csproj", "{039AFFA8-C1CC-4E3B-8A31-6814D7557F74}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Authentication", "Wino.Authentication\Wino.Authentication.csproj", "{A4DBA01A-F315-49E0-8428-BB99D32B20F9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Calendar", "Wino.Calendar\Wino.Calendar.csproj", "{600F4979-DB7E-409D-B7DA-B60BE4C55C35}"
EndProject
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Wino.Calendar.Packaging", "Wino.Calendar.Packaging\Wino.Calendar.Packaging.wapproj", "{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Services", "Wino.Services\Wino.Services.csproj", "{4000A374-59FE-4400-ACF6-D40473BECD73}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Debug|ARM64.ActiveCfg = Debug|ARM64
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Debug|ARM64.Build.0 = Debug|ARM64
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Debug|ARM64.Deploy.0 = Debug|ARM64
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Debug|x64.ActiveCfg = Debug|x64
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Debug|x64.Build.0 = Debug|x64
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Debug|x64.Deploy.0 = Debug|x64
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Debug|x86.ActiveCfg = Debug|x86
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Debug|x86.Build.0 = Debug|x86
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Debug|x86.Deploy.0 = Debug|x86
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Release|ARM64.ActiveCfg = Release|ARM64
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Release|ARM64.Build.0 = Release|ARM64
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Release|ARM64.Deploy.0 = Release|ARM64
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Release|x64.ActiveCfg = Release|x64
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Release|x64.Build.0 = Release|x64
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Release|x64.Deploy.0 = Release|x64
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Release|x86.ActiveCfg = Release|x86
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Release|x86.Build.0 = Release|x86
{68A432B8-C1B7-494C-8D6D-230788EA683E}.Release|x86.Deploy.0 = Release|x86
{E6B1632A-8901-41E8-9DDF-6793C7698B0B}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{E6B1632A-8901-41E8-9DDF-6793C7698B0B}.Debug|ARM64.Build.0 = Debug|Any CPU
{E6B1632A-8901-41E8-9DDF-6793C7698B0B}.Debug|x64.ActiveCfg = Debug|Any CPU
{E6B1632A-8901-41E8-9DDF-6793C7698B0B}.Debug|x64.Build.0 = Debug|Any CPU
{E6B1632A-8901-41E8-9DDF-6793C7698B0B}.Debug|x86.ActiveCfg = Debug|Any CPU
{E6B1632A-8901-41E8-9DDF-6793C7698B0B}.Debug|x86.Build.0 = Debug|Any CPU
{E6B1632A-8901-41E8-9DDF-6793C7698B0B}.Release|ARM64.ActiveCfg = Release|Any CPU
{E6B1632A-8901-41E8-9DDF-6793C7698B0B}.Release|ARM64.Build.0 = Release|Any CPU
{E6B1632A-8901-41E8-9DDF-6793C7698B0B}.Release|x64.ActiveCfg = Release|x64
{E6B1632A-8901-41E8-9DDF-6793C7698B0B}.Release|x64.Build.0 = Release|x64
{E6B1632A-8901-41E8-9DDF-6793C7698B0B}.Release|x86.ActiveCfg = Release|x86
{E6B1632A-8901-41E8-9DDF-6793C7698B0B}.Release|x86.Build.0 = Release|x86
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|ARM64.ActiveCfg = Debug|ARM64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|ARM64.Build.0 = Debug|ARM64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|x64.ActiveCfg = Debug|x64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|x64.Build.0 = Debug|x64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|x86.ActiveCfg = Debug|x86
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Debug|x86.Build.0 = Debug|x86
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|ARM64.ActiveCfg = Release|ARM64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|ARM64.Build.0 = Release|ARM64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|x64.ActiveCfg = Release|x64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|x64.Build.0 = Release|x64
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|x86.ActiveCfg = Release|x86
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8}.Release|x86.Build.0 = Release|x86
{CF3312E5-5DA0-4867-9945-49EA7598AF1F}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{CF3312E5-5DA0-4867-9945-49EA7598AF1F}.Debug|ARM64.Build.0 = Debug|Any CPU
{CF3312E5-5DA0-4867-9945-49EA7598AF1F}.Debug|x64.ActiveCfg = Debug|Any CPU
{CF3312E5-5DA0-4867-9945-49EA7598AF1F}.Debug|x64.Build.0 = Debug|Any CPU
{CF3312E5-5DA0-4867-9945-49EA7598AF1F}.Debug|x86.ActiveCfg = Debug|Any CPU
{CF3312E5-5DA0-4867-9945-49EA7598AF1F}.Debug|x86.Build.0 = Debug|Any CPU
{CF3312E5-5DA0-4867-9945-49EA7598AF1F}.Release|ARM64.ActiveCfg = Release|Any CPU
{CF3312E5-5DA0-4867-9945-49EA7598AF1F}.Release|ARM64.Build.0 = Release|Any CPU
{CF3312E5-5DA0-4867-9945-49EA7598AF1F}.Release|x64.ActiveCfg = Release|x64
{CF3312E5-5DA0-4867-9945-49EA7598AF1F}.Release|x64.Build.0 = Release|x64
{CF3312E5-5DA0-4867-9945-49EA7598AF1F}.Release|x86.ActiveCfg = Release|x86
{CF3312E5-5DA0-4867-9945-49EA7598AF1F}.Release|x86.Build.0 = Release|x86
{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}.Debug|ARM64.ActiveCfg = Debug|ARM64
{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}.Debug|ARM64.Build.0 = Debug|ARM64
{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}.Debug|x64.ActiveCfg = Debug|x64
{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}.Debug|x64.Build.0 = Debug|x64
{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}.Debug|x86.ActiveCfg = Debug|x86
{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}.Debug|x86.Build.0 = Debug|x86
{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}.Release|ARM64.ActiveCfg = Release|ARM64
{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}.Release|ARM64.Build.0 = Release|ARM64
{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}.Release|x64.ActiveCfg = Release|x64
{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}.Release|x64.Build.0 = Release|x64
{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}.Release|x86.ActiveCfg = Release|x86
{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08}.Release|x86.Build.0 = Release|x86
{D62F1C03-DA57-4709-A640-0283296A8E66}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{D62F1C03-DA57-4709-A640-0283296A8E66}.Debug|ARM64.Build.0 = Debug|Any CPU
{D62F1C03-DA57-4709-A640-0283296A8E66}.Debug|x64.ActiveCfg = Debug|Any CPU
{D62F1C03-DA57-4709-A640-0283296A8E66}.Debug|x64.Build.0 = Debug|Any CPU
{D62F1C03-DA57-4709-A640-0283296A8E66}.Debug|x86.ActiveCfg = Debug|Any CPU
{D62F1C03-DA57-4709-A640-0283296A8E66}.Debug|x86.Build.0 = Debug|Any CPU
{D62F1C03-DA57-4709-A640-0283296A8E66}.Release|ARM64.ActiveCfg = Release|Any CPU
{D62F1C03-DA57-4709-A640-0283296A8E66}.Release|ARM64.Build.0 = Release|Any CPU
{D62F1C03-DA57-4709-A640-0283296A8E66}.Release|x64.ActiveCfg = Release|x64
{D62F1C03-DA57-4709-A640-0283296A8E66}.Release|x64.Build.0 = Release|x64
{D62F1C03-DA57-4709-A640-0283296A8E66}.Release|x86.ActiveCfg = Release|x86
{D62F1C03-DA57-4709-A640-0283296A8E66}.Release|x86.Build.0 = Release|x86
{0C307D7E-256F-448C-8265-5622A812FBCC}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{0C307D7E-256F-448C-8265-5622A812FBCC}.Debug|ARM64.Build.0 = Debug|Any CPU
{0C307D7E-256F-448C-8265-5622A812FBCC}.Debug|x64.ActiveCfg = Debug|Any CPU
{0C307D7E-256F-448C-8265-5622A812FBCC}.Debug|x64.Build.0 = Debug|Any CPU
{0C307D7E-256F-448C-8265-5622A812FBCC}.Debug|x86.ActiveCfg = Debug|Any CPU
{0C307D7E-256F-448C-8265-5622A812FBCC}.Debug|x86.Build.0 = Debug|Any CPU
{0C307D7E-256F-448C-8265-5622A812FBCC}.Release|ARM64.ActiveCfg = Release|Any CPU
{0C307D7E-256F-448C-8265-5622A812FBCC}.Release|ARM64.Build.0 = Release|Any CPU
{0C307D7E-256F-448C-8265-5622A812FBCC}.Release|x64.ActiveCfg = Release|x64
{0C307D7E-256F-448C-8265-5622A812FBCC}.Release|x64.Build.0 = Release|x64
{0C307D7E-256F-448C-8265-5622A812FBCC}.Release|x86.ActiveCfg = Release|x86
{0C307D7E-256F-448C-8265-5622A812FBCC}.Release|x86.Build.0 = Release|x86
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Debug|ARM64.ActiveCfg = Debug|ARM64
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Debug|ARM64.Build.0 = Debug|ARM64
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Debug|ARM64.Deploy.0 = Debug|ARM64
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Debug|x64.ActiveCfg = Debug|x64
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Debug|x64.Build.0 = Debug|x64
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Debug|x64.Deploy.0 = Debug|x64
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Debug|x86.ActiveCfg = Debug|x86
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Debug|x86.Build.0 = Debug|x86
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Debug|x86.Deploy.0 = Debug|x86
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Release|ARM64.ActiveCfg = Release|ARM64
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Release|ARM64.Build.0 = Release|ARM64
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Release|ARM64.Deploy.0 = Release|ARM64
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Release|x64.ActiveCfg = Release|x64
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Release|x64.Build.0 = Release|x64
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Release|x64.Deploy.0 = Release|x64
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Release|x86.ActiveCfg = Release|x86
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Release|x86.Build.0 = Release|x86
{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}.Release|x86.Deploy.0 = Release|x86
{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}.Debug|ARM64.ActiveCfg = Debug|ARM64
{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}.Debug|ARM64.Build.0 = Debug|ARM64
{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}.Debug|x64.ActiveCfg = Debug|x64
{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}.Debug|x64.Build.0 = Debug|x64
{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}.Debug|x86.ActiveCfg = Debug|x86
{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}.Debug|x86.Build.0 = Debug|x86
{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}.Release|ARM64.ActiveCfg = Release|ARM64
{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}.Release|ARM64.Build.0 = Release|ARM64
{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}.Release|x64.ActiveCfg = Release|x64
{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}.Release|x64.Build.0 = Release|x64
{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}.Release|x86.ActiveCfg = Release|x86
{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}.Release|x86.Build.0 = Release|x86
{D4919A19-E70F-4916-83D2-5D5F87BEB949}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{D4919A19-E70F-4916-83D2-5D5F87BEB949}.Debug|ARM64.Build.0 = Debug|Any CPU
{D4919A19-E70F-4916-83D2-5D5F87BEB949}.Debug|x64.ActiveCfg = Debug|Any CPU
{D4919A19-E70F-4916-83D2-5D5F87BEB949}.Debug|x64.Build.0 = Debug|Any CPU
{D4919A19-E70F-4916-83D2-5D5F87BEB949}.Debug|x86.ActiveCfg = Debug|Any CPU
{D4919A19-E70F-4916-83D2-5D5F87BEB949}.Debug|x86.Build.0 = Debug|Any CPU
{D4919A19-E70F-4916-83D2-5D5F87BEB949}.Release|ARM64.ActiveCfg = Release|Any CPU
{D4919A19-E70F-4916-83D2-5D5F87BEB949}.Release|ARM64.Build.0 = Release|Any CPU
{D4919A19-E70F-4916-83D2-5D5F87BEB949}.Release|x64.ActiveCfg = Release|Any CPU
{D4919A19-E70F-4916-83D2-5D5F87BEB949}.Release|x64.Build.0 = Release|Any CPU
{D4919A19-E70F-4916-83D2-5D5F87BEB949}.Release|x86.ActiveCfg = Release|Any CPU
{D4919A19-E70F-4916-83D2-5D5F87BEB949}.Release|x86.Build.0 = Release|Any CPU
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8}.Debug|ARM64.Build.0 = Debug|Any CPU
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8}.Debug|x64.ActiveCfg = Debug|Any CPU
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8}.Debug|x64.Build.0 = Debug|Any CPU
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8}.Debug|x86.ActiveCfg = Debug|Any CPU
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8}.Debug|x86.Build.0 = Debug|Any CPU
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8}.Release|ARM64.ActiveCfg = Release|Any CPU
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8}.Release|ARM64.Build.0 = Release|Any CPU
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8}.Release|x64.ActiveCfg = Release|Any CPU
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8}.Release|x64.Build.0 = Release|Any CPU
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8}.Release|x86.ActiveCfg = Release|Any CPU
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8}.Release|x86.Build.0 = Release|Any CPU
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74}.Debug|ARM64.Build.0 = Debug|Any CPU
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74}.Debug|x64.ActiveCfg = Debug|Any CPU
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74}.Debug|x64.Build.0 = Debug|Any CPU
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74}.Debug|x86.ActiveCfg = Debug|Any CPU
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74}.Debug|x86.Build.0 = Debug|Any CPU
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74}.Release|ARM64.ActiveCfg = Release|Any CPU
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74}.Release|ARM64.Build.0 = Release|Any CPU
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74}.Release|x64.ActiveCfg = Release|Any CPU
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74}.Release|x64.Build.0 = Release|Any CPU
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74}.Release|x86.ActiveCfg = Release|Any CPU
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74}.Release|x86.Build.0 = Release|Any CPU
{A4DBA01A-F315-49E0-8428-BB99D32B20F9}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{A4DBA01A-F315-49E0-8428-BB99D32B20F9}.Debug|ARM64.Build.0 = Debug|Any CPU
{A4DBA01A-F315-49E0-8428-BB99D32B20F9}.Debug|x64.ActiveCfg = Debug|Any CPU
{A4DBA01A-F315-49E0-8428-BB99D32B20F9}.Debug|x64.Build.0 = Debug|Any CPU
{A4DBA01A-F315-49E0-8428-BB99D32B20F9}.Debug|x86.ActiveCfg = Debug|Any CPU
{A4DBA01A-F315-49E0-8428-BB99D32B20F9}.Debug|x86.Build.0 = Debug|Any CPU
{A4DBA01A-F315-49E0-8428-BB99D32B20F9}.Release|ARM64.ActiveCfg = Release|Any CPU
{A4DBA01A-F315-49E0-8428-BB99D32B20F9}.Release|ARM64.Build.0 = Release|Any CPU
{A4DBA01A-F315-49E0-8428-BB99D32B20F9}.Release|x64.ActiveCfg = Release|Any CPU
{A4DBA01A-F315-49E0-8428-BB99D32B20F9}.Release|x64.Build.0 = Release|Any CPU
{A4DBA01A-F315-49E0-8428-BB99D32B20F9}.Release|x86.ActiveCfg = Release|Any CPU
{A4DBA01A-F315-49E0-8428-BB99D32B20F9}.Release|x86.Build.0 = Release|Any CPU
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|ARM64.ActiveCfg = Debug|ARM64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|ARM64.Build.0 = Debug|ARM64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|ARM64.Deploy.0 = Debug|ARM64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|x64.ActiveCfg = Debug|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|x64.Build.0 = Debug|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|x64.Deploy.0 = Debug|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|x86.ActiveCfg = Debug|x86
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|x86.Build.0 = Debug|x86
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Debug|x86.Deploy.0 = Debug|x86
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|ARM64.ActiveCfg = Release|ARM64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|ARM64.Build.0 = Release|ARM64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|ARM64.Deploy.0 = Release|ARM64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|x64.ActiveCfg = Release|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|x64.Build.0 = Release|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|x64.Deploy.0 = Release|x64
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|x86.ActiveCfg = Release|x86
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|x86.Build.0 = Release|x86
{600F4979-DB7E-409D-B7DA-B60BE4C55C35}.Release|x86.Deploy.0 = Release|x86
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|ARM64.ActiveCfg = Debug|ARM64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|ARM64.Build.0 = Debug|ARM64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|ARM64.Deploy.0 = Debug|ARM64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|x64.ActiveCfg = Debug|x64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|x64.Build.0 = Debug|x64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|x64.Deploy.0 = Debug|x64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|x86.ActiveCfg = Debug|x86
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|x86.Build.0 = Debug|x86
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Debug|x86.Deploy.0 = Debug|x86
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|ARM64.ActiveCfg = Release|ARM64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|ARM64.Build.0 = Release|ARM64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|ARM64.Deploy.0 = Release|ARM64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x64.ActiveCfg = Release|x64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x64.Build.0 = Release|x64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x64.Deploy.0 = Release|x64
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x86.ActiveCfg = Release|x86
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x86.Build.0 = Release|x86
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x86.Deploy.0 = Release|x86
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|ARM64.Build.0 = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|x64.ActiveCfg = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|x64.Build.0 = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|x86.ActiveCfg = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|x86.Build.0 = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|ARM64.ActiveCfg = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|ARM64.Build.0 = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|x64.ActiveCfg = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|x64.Build.0 = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|x86.ActiveCfg = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{E6B1632A-8901-41E8-9DDF-6793C7698B0B} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
{395F19BA-1E42-495C-9DB5-1A6F537FCCB8} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
{CF3312E5-5DA0-4867-9945-49EA7598AF1F} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
{D9EF0F59-F5F2-4D6C-A5BA-84043D8F3E08} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
{D62F1C03-DA57-4709-A640-0283296A8E66} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
{0C307D7E-256F-448C-8265-5622A812FBCC} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
{D4919A19-E70F-4916-83D2-5D5F87BEB949} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
{A4DBA01A-F315-49E0-8428-BB99D32B20F9} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
{4000A374-59FE-4400-ACF6-D40473BECD73} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {721F946E-F69F-4987-823A-D084B436FC1E}
EndGlobalSection
EndGlobal