diff --git a/.gitignore b/.gitignore index 762d6bc..3e76007 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,19 @@ bld/ *.[Cc]ache # but keep track of directories ending in .cache !?*.[Cc]ache/ + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload diff --git a/FolderIconPainter.sln b/FolderIconPainter.sln index 341a160..75cc84a 100644 --- a/FolderIconPainter.sln +++ b/FolderIconPainter.sln @@ -79,22 +79,22 @@ Global {A96C7535-FB23-472C-AB4D-7CA2B52B8043}.Release|x86.ActiveCfg = Release|x86 {A96C7535-FB23-472C-AB4D-7CA2B52B8043}.Release|x86.Build.0 = Release|x86 {A96C7535-FB23-472C-AB4D-7CA2B52B8043}.Release|x86.Deploy.0 = Release|x86 - {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|Any CPU.Build.0 = Debug|Any CPU - {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|ARM64.Build.0 = Debug|Any CPU + {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|Any CPU.ActiveCfg = Debug|x64 + {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|Any CPU.Build.0 = Debug|x64 + {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|ARM64.Build.0 = Debug|ARM64 {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|x64.ActiveCfg = Debug|x64 {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|x64.Build.0 = Debug|x64 - {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|x86.ActiveCfg = Debug|Any CPU - {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|x86.Build.0 = Debug|Any CPU - {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|Any CPU.ActiveCfg = Release|Any CPU - {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|Any CPU.Build.0 = Release|Any CPU - {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|ARM64.ActiveCfg = Release|Any CPU - {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|ARM64.Build.0 = Release|Any CPU + {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|x86.ActiveCfg = Debug|x86 + {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Debug|x86.Build.0 = Debug|x86 + {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|Any CPU.ActiveCfg = Release|x64 + {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|Any CPU.Build.0 = Release|x64 + {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|ARM64.ActiveCfg = Release|ARM64 + {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|ARM64.Build.0 = Release|ARM64 {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|x64.ActiveCfg = Release|x64 {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|x64.Build.0 = Release|x64 - {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|x86.ActiveCfg = Release|Any CPU - {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|x86.Build.0 = Release|Any CPU + {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|x86.ActiveCfg = Release|x86 + {79CBE5DC-9AE0-4182-882E-FC3D832C0156}.Release|x86.Build.0 = Release|x86 {5A8F69B7-F888-8969-85EF-0AA22433D75A}.Debug|Any CPU.ActiveCfg = Debug|x64 {5A8F69B7-F888-8969-85EF-0AA22433D75A}.Debug|Any CPU.Build.0 = Debug|x64 {5A8F69B7-F888-8969-85EF-0AA22433D75A}.Debug|Any CPU.Deploy.0 = Debug|x64 @@ -103,7 +103,6 @@ Global {5A8F69B7-F888-8969-85EF-0AA22433D75A}.Debug|ARM64.Deploy.0 = Debug|ARM64 {5A8F69B7-F888-8969-85EF-0AA22433D75A}.Debug|x64.ActiveCfg = Debug|x64 {5A8F69B7-F888-8969-85EF-0AA22433D75A}.Debug|x64.Build.0 = Debug|x64 - {5A8F69B7-F888-8969-85EF-0AA22433D75A}.Debug|x64.Deploy.0 = Debug|x64 {5A8F69B7-F888-8969-85EF-0AA22433D75A}.Debug|x86.ActiveCfg = Debug|x86 {5A8F69B7-F888-8969-85EF-0AA22433D75A}.Debug|x86.Build.0 = Debug|x86 {5A8F69B7-F888-8969-85EF-0AA22433D75A}.Debug|x86.Deploy.0 = Debug|x86 diff --git a/src/FIP.App/FIP.App (Package)/FIP.App (Package).assets.cache b/src/FIP.App/FIP.App (Package)/FIP.App (Package).assets.cache deleted file mode 100644 index c019b2f..0000000 Binary files a/src/FIP.App/FIP.App (Package)/FIP.App (Package).assets.cache and /dev/null differ diff --git a/src/FIP.App/FIP.App (Package)/FIP.App (Package).wapproj b/src/FIP.App/FIP.App (Package)/FIP.App (Package).wapproj index e26f6f3..d91e51e 100644 --- a/src/FIP.App/FIP.App (Package)/FIP.App (Package).wapproj +++ b/src/FIP.App/FIP.App (Package)/FIP.App (Package).wapproj @@ -43,6 +43,31 @@ $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\ FIP.App\ + False + SHA256 + True + True + x86|x64 + True + 0 + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always @@ -51,6 +76,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + @@ -72,26 +122,26 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + @@ -102,16 +152,17 @@ + True - Properties\PublishProfiles\win10-$(Platform).pubxml + Properties\PublishProfiles\win-$(Platform).pubxml - - + + \ No newline at end of file diff --git a/src/FIP.App/FIP.App (Package)/FIP.App (Package).wapproj.user b/src/FIP.App/FIP.App (Package)/FIP.App (Package).wapproj.user deleted file mode 100644 index cc300d9..0000000 --- a/src/FIP.App/FIP.App (Package)/FIP.App (Package).wapproj.user +++ /dev/null @@ -1,17 +0,0 @@ - - - - A:\bigfiles\FolderIconPainter\src\FIP.App\FIP.App %28Package%29\Images\FIP.ai - A:\bigfiles\FolderIconPainter\src\FIP.App\FIP.App %28Package%29\Images\FIP.ai - A:\bigfiles\FolderIconPainter\src\FIP.App\FIP.App %28Package%29\Images\FIP.ai - A:\bigfiles\FolderIconPainter\src\FIP.App\FIP.App %28Package%29\Images\FIP.ai - A:\bigfiles\FolderIconPainter\src\FIP.App\FIP.App %28Package%29\Images\FIP.ai - A:\bigfiles\FolderIconPainter\src\FIP.App\FIP.App %28Package%29\Images\FIP.ai - A:\bigfiles\FolderIconPainter\src\FIP.App\FIP.App %28Package%29\Images\FIP.ai - A:\bigfiles\FolderIconPainter\src\FIP.App\FIP.App %28Package%29\Images\FIP.ai - - - AppHostLocalDebugger - False - - \ No newline at end of file diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-16.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-lightunplated_targetsize-16.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-16.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-lightunplated_targetsize-16.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-24.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-lightunplated_targetsize-24.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-24.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-lightunplated_targetsize-24.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-256.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-lightunplated_targetsize-256.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-256.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-lightunplated_targetsize-256.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-32.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-lightunplated_targetsize-32.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-32.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-lightunplated_targetsize-32.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-48.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-lightunplated_targetsize-48.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-48.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-lightunplated_targetsize-48.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-unplated_targetsize-16.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-unplated_targetsize-16.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-unplated_targetsize-16.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-unplated_targetsize-16.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-unplated_targetsize-256.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-unplated_targetsize-256.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-unplated_targetsize-256.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-unplated_targetsize-256.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-unplated_targetsize-32.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-unplated_targetsize-32.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-unplated_targetsize-32.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-unplated_targetsize-32.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-unplated_targetsize-48.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-unplated_targetsize-48.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.altform-unplated_targetsize-48.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.altform-unplated_targetsize-48.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.scale-100.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.scale-100.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.scale-100.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.scale-100.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.scale-125.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.scale-125.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.scale-125.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.scale-125.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.scale-150.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.scale-150.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.scale-150.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.scale-150.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.scale-200.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.scale-200.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.scale-200.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.scale-200.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.scale-400.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.scale-400.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.scale-400.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.scale-400.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.targetsize-16.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.targetsize-16.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.targetsize-16.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.targetsize-16.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.targetsize-24.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.targetsize-24.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.targetsize-24.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.targetsize-24.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.targetsize-24_altform-unplated.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.targetsize-24_altform-unplated.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.targetsize-24_altform-unplated.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.targetsize-24_altform-unplated.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.targetsize-256.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.targetsize-256.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.targetsize-256.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.targetsize-256.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.targetsize-32.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.targetsize-32.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.targetsize-32.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.targetsize-32.png diff --git a/src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.targetsize-48.png b/src/FIP.App/FIP.App (Package)/Images/AppIcon.targetsize-48.png similarity index 100% rename from src/FIP.App/FIP.App (Package)/Images/Square44x44Logo.targetsize-48.png rename to src/FIP.App/FIP.App (Package)/Images/AppIcon.targetsize-48.png diff --git a/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-100.png b/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-100.png new file mode 100644 index 0000000..cbf2eaa Binary files /dev/null and b/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-100.png differ diff --git a/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-125.png b/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-125.png new file mode 100644 index 0000000..ed48948 Binary files /dev/null and b/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-125.png differ diff --git a/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-150.png b/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-150.png new file mode 100644 index 0000000..deade6e Binary files /dev/null and b/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-150.png differ diff --git a/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-200.png b/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-200.png new file mode 100644 index 0000000..54aa7f1 Binary files /dev/null and b/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-200.png differ diff --git a/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-400.png b/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-400.png new file mode 100644 index 0000000..e594852 Binary files /dev/null and b/src/FIP.App/FIP.App (Package)/Images/BadgeLogo.scale-400.png differ diff --git a/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-100.png b/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-100.png index c2a916f..fc201b8 100644 Binary files a/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-100.png and b/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-100.png differ diff --git a/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-125.png b/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-125.png index 25c0595..fa9a0ef 100644 Binary files a/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-125.png and b/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-125.png differ diff --git a/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-150.png b/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-150.png index a892e94..37dbdfa 100644 Binary files a/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-150.png and b/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-150.png differ diff --git a/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-200.png b/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-200.png index 94ed3df..2712566 100644 Binary files a/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-200.png and b/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-200.png differ diff --git a/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-400.png b/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-400.png index d672765..f5c55f7 100644 Binary files a/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-400.png and b/src/FIP.App/FIP.App (Package)/Images/StoreLogo.scale-400.png differ diff --git a/src/FIP.App/FIP.App (Package)/Package.appxmanifest b/src/FIP.App/FIP.App (Package)/Package.appxmanifest index b8c9d28..1686883 100644 --- a/src/FIP.App/FIP.App (Package)/Package.appxmanifest +++ b/src/FIP.App/FIP.App (Package)/Package.appxmanifest @@ -7,9 +7,9 @@ IgnorableNamespaces="uap rescap"> + Name="GeorgeRadchuk.FolderIconPainter" + Publisher="CN=456F105E-8C42-4336-90BA-66BA6A287BBA" + Version="1.0.2.0" /> Folder Icon Painter @@ -35,7 +35,7 @@ Description="This program can help you change the color of the default folder icon on Windows 11 and 10." BackgroundColor="transparent" Square150x150Logo="Images\Square150x150Logo.png" - Square44x44Logo="Images\Square44x44Logo.png"> + Square44x44Logo="Images\AppIcon.png"> @@ -44,6 +44,7 @@ + diff --git a/src/FIP.App/FIP.App/App.xaml b/src/FIP.App/FIP.App/App.xaml index 734609a..18ce5fe 100644 --- a/src/FIP.App/FIP.App/App.xaml +++ b/src/FIP.App/FIP.App/App.xaml @@ -42,7 +42,9 @@ - + + Folder Icon Painter + M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z 641 0 diff --git a/src/FIP.App/FIP.App/AppShell.xaml b/src/FIP.App/FIP.App/AppShell.xaml index e68753f..3a8e999 100644 --- a/src/FIP.App/FIP.App/AppShell.xaml +++ b/src/FIP.App/FIP.App/AppShell.xaml @@ -64,7 +64,7 @@ IsHitTestVisible="True" Canvas.ZIndex="1"> - + - - - - + + + + + - @@ -52,8 +52,8 @@ - - + + diff --git a/src/FIP.App/FIP.App/Helpers/EnumHelper.cs b/src/FIP.App/FIP.App/Helpers/EnumHelper.cs new file mode 100644 index 0000000..382b9b8 --- /dev/null +++ b/src/FIP.App/FIP.App/Helpers/EnumHelper.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Reflection; + +namespace FIP.App.Helpers; + +internal static partial class EnumHelper +{ + /// + /// Converts a string into an enum. + /// + /// The output enum type. + /// The input text. + /// The parsed enum. + /// Thrown when the TEnum type is not a enum. + public static TEnum GetEnum(string text) where TEnum : struct + { + if (!typeof(TEnum).GetTypeInfo().IsEnum) + { + throw new InvalidOperationException("Generic parameter 'TEnum' must be an enum."); + } + return (TEnum)Enum.Parse(typeof(TEnum), text); + } +} diff --git a/src/FIP.App/FIP.App/Helpers/ProcessInfoHelper.cs b/src/FIP.App/FIP.App/Helpers/ProcessInfoHelper.cs new file mode 100644 index 0000000..7fa4e5f --- /dev/null +++ b/src/FIP.App/FIP.App/Helpers/ProcessInfoHelper.cs @@ -0,0 +1,70 @@ +using System; +using System.Diagnostics; + +namespace FIP.App.Helpers; + +public static partial class ProcessInfoHelper +{ + private static readonly FileVersionInfo? _fileVersionInfo; + private static readonly Process _process; + + static ProcessInfoHelper() + { + _process = Process.GetCurrentProcess(); + _fileVersionInfo = _process.MainModule?.FileVersionInfo; + } + + /// + /// Returns the version string. + /// + public static string Version => GetVersion()?.ToString() ?? string.Empty; + + /// + /// Returns the version string prefixed with 'v'. + /// + public static string VersionWithPrefix => $"v{Version}"; + + /// + /// Retrieves the product name. If not available, it returns 'Unknown Product'. + /// + public static string ProductName => _fileVersionInfo?.ProductName ?? "Unknown Product"; + + /// + /// Combines the product name and version into a single string. The version includes a prefix. + /// + public static string ProductNameAndVersion => $"{ProductName} {VersionWithPrefix}"; + + /// + /// Returns the company name of the publisher. If not available, it defaults to 'Unknown Publisher'. + /// + public static string Publisher => _fileVersionInfo?.CompanyName ?? "Unknown Publisher"; + + public static Version? GetVersion() + { + return _fileVersionInfo is null + ? null + : new Version( + _fileVersionInfo.FileMajorPart, + _fileVersionInfo.FileMinorPart, + _fileVersionInfo.FileBuildPart, + _fileVersionInfo.FilePrivatePart); + } + + /// + /// Retrieves the file version information for the current assembly. + /// + /// Returns a FileVersionInfo object containing version details. + public static FileVersionInfo? GetFileVersionInfo() + { + return _fileVersionInfo; + } + + /// + /// Retrieves the current process instance. + /// + /// Returns the current Process object. + public static Process GetProcess() + { + return _process; + } +} diff --git a/src/FIP.App/FIP.App/Helpers/Settings/ObservableSettings.cs b/src/FIP.App/FIP.App/Helpers/Settings/ObservableSettings.cs new file mode 100644 index 0000000..90581f5 --- /dev/null +++ b/src/FIP.App/FIP.App/Helpers/Settings/ObservableSettings.cs @@ -0,0 +1,43 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace FIP.App.Helpers.Settings; + +public partial class ObservableSettings : INotifyPropertyChanged +{ + private readonly ISettingsProvider provider; + + public ObservableSettings(ISettingsProvider provider) + { + this.provider = provider; + } + + public event PropertyChangedEventHandler PropertyChanged; + + protected bool Set(T value, [CallerMemberName] string propertyName = null) + { + if (provider.Contains(propertyName)) + { + var currentValue = provider.Get(propertyName); + if (Equals(currentValue, value)) + return false; + } + + provider.Set(propertyName, value); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + return true; + } + + protected T Get([CallerMemberName] string propertyName = null) + { + return provider.Get(propertyName); + } + + protected T GetOrCreateDefault(T defaultValue, [CallerMemberName] string propertyName = null) + { + if (!provider.Contains(propertyName)) + Set(defaultValue, propertyName); + + return Get(propertyName); + } +} diff --git a/src/FIP.App/FIP.App/Helpers/Settings/Providers/ApplicationDataSettingsProvider.cs b/src/FIP.App/FIP.App/Helpers/Settings/Providers/ApplicationDataSettingsProvider.cs new file mode 100644 index 0000000..2669767 --- /dev/null +++ b/src/FIP.App/FIP.App/Helpers/Settings/Providers/ApplicationDataSettingsProvider.cs @@ -0,0 +1,84 @@ +using Microsoft.Windows.Storage; +using System; +using System.Collections.Generic; +using System.Text.Json; + +namespace FIP.App.Helpers.Settings; + +public partial class ApplicationDataSettingsProvider : ISettingsProvider +{ + private readonly ApplicationDataContainer container; + + public ApplicationDataSettingsProvider(ApplicationDataContainer container) + { + this.container = container ?? throw new ArgumentNullException(nameof(container)); + } + + public bool Contains(string key) => container.Values.ContainsKey(key); + + public object Get(string key) => container.Values.TryGetValue(key, out var value) ? value : null; + + public void Set(string key, object value) => container.Values[key] = value; + + public T Get(string key) + { + if (!container.Values.TryGetValue(key, out var value)) + return default; + + if (value is T t) + return t; + + if (value is string str && !IsSimpleType(typeof(T))) + { + try + { + var typeInfo = SettingsJsonContext.Default.GetTypeInfo(typeof(T)); + return (T)JsonSerializer.Deserialize(str, typeInfo); + } + catch (Exception) + { + HandleCorruptedKey(key); + return default; + } + } + + return (T)Convert.ChangeType(value, typeof(T)); + } + + private void HandleCorruptedKey(string key) + { + try + { + container.Values.Remove(key); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"Failed to remove corrupted key '{key}': {ex}"); + } + } + + public void Set(string key, T value) + { + object storedValue = IsSimpleType(typeof(T)) + ? value + : JsonSerializer.Serialize(value, SettingsJsonContext.Default.GetTypeInfo(typeof(T))); + + container.Values[key] = storedValue; + } + + private static readonly HashSet ExtraSimpleTypes = new() + { + typeof(string), + typeof(DateTimeOffset), + typeof(TimeSpan), + typeof(Guid), + typeof(Windows.Foundation.Point), + typeof(Windows.Foundation.Size), + typeof(Windows.Foundation.Rect) + }; + + private static bool IsSimpleType(Type type) + { + return type.IsPrimitive || ExtraSimpleTypes.Contains(type); + } +} diff --git a/src/FIP.App/FIP.App/Helpers/Settings/Providers/ISettingsProvider.cs b/src/FIP.App/FIP.App/Helpers/Settings/Providers/ISettingsProvider.cs new file mode 100644 index 0000000..5df0892 --- /dev/null +++ b/src/FIP.App/FIP.App/Helpers/Settings/Providers/ISettingsProvider.cs @@ -0,0 +1,11 @@ +namespace FIP.App.Helpers.Settings; + +public interface ISettingsProvider +{ + bool Contains(string key); + object Get(string key); + void Set(string key, object value); + + T Get(string key); + void Set(string key, T value); +} diff --git a/src/FIP.App/FIP.App/Helpers/Settings/Providers/JsonSettingsProvider.cs b/src/FIP.App/FIP.App/Helpers/Settings/Providers/JsonSettingsProvider.cs new file mode 100644 index 0000000..c9a8ec3 --- /dev/null +++ b/src/FIP.App/FIP.App/Helpers/Settings/Providers/JsonSettingsProvider.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; + +namespace FIP.App.Helpers.Settings; + +public partial class JsonSettingsProvider : ISettingsProvider +{ + private readonly string filePath; + private Dictionary values = new(); + + public JsonSettingsProvider(string filePath) + { + this.filePath = filePath; + Load(); + } + + public bool Contains(string key) => values.ContainsKey(key); + + public object Get(string key) => values.TryGetValue(key, out var value) ? value : null; + + public void Set(string key, object value) + { + var json = JsonSerializer.SerializeToElement(value, SettingsJsonContext.Default.GetTypeInfo(value.GetType())); + values[key] = json; + Save(); + } + + public T Get(string key) + { + if (!values.TryGetValue(key, out var jsonElement)) + return default; + + try + { + return (T)jsonElement.Deserialize(SettingsJsonContext.Default.GetTypeInfo(typeof(T))); + } + catch (Exception) + { + HandleCorruptedKey(key); + return default; + } + } + + + public void Set(string key, T value) + { + var json = JsonSerializer.SerializeToElement(value, SettingsJsonContext.Default.GetTypeInfo(typeof(T))); + values[key] = json; + Save(); + } + + private void Load() + { + if (!File.Exists(filePath)) + return; + + try + { + var json = File.ReadAllText(filePath); + values = JsonSerializer.Deserialize( + json, + SettingsJsonContext.Default.DictionaryStringJsonElement + ) ?? new(); + } + catch (Exception) + { + HandleCorruptedFile(); + } + } + private void HandleCorruptedFile() + { + try + { + File.Delete(filePath); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"Failed to delete corrupted settings file '{filePath}': {ex}"); + } + + values = new(); + } + + private void HandleCorruptedKey(string key) + { + values.Remove(key); + Save(); + } + + + private void Save() + { + var json = JsonSerializer.Serialize( + values, + SettingsJsonContext.Default.DictionaryStringJsonElement + ); + File.WriteAllText(filePath, json); + } +} diff --git a/src/FIP.App/FIP.App/Helpers/Settings/Providers/SettingsProviderFactory.cs b/src/FIP.App/FIP.App/Helpers/Settings/Providers/SettingsProviderFactory.cs new file mode 100644 index 0000000..f47dc97 --- /dev/null +++ b/src/FIP.App/FIP.App/Helpers/Settings/Providers/SettingsProviderFactory.cs @@ -0,0 +1,27 @@ +using Microsoft.Windows.Storage; +using System; +using System.IO; + +namespace FIP.App.Helpers.Settings; + +public static partial class SettingsProviderFactory +{ + public static ISettingsProvider CreateProvider() + { + if (NativeMethods.IsAppPackaged) + { + return new ApplicationDataSettingsProvider(ApplicationData.GetDefault().LocalSettings); + } + else + { + var folder = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + ProcessInfoHelper.ProductName + ); + + Directory.CreateDirectory(folder); + var filePath = Path.Combine(folder, "AppConfig.json"); + return new JsonSettingsProvider(filePath); + } + } +} diff --git a/src/FIP.App/FIP.App/Helpers/Settings/SettingsHelper.cs b/src/FIP.App/FIP.App/Helpers/Settings/SettingsHelper.cs new file mode 100644 index 0000000..4b302ad --- /dev/null +++ b/src/FIP.App/FIP.App/Helpers/Settings/SettingsHelper.cs @@ -0,0 +1,39 @@ +using Microsoft.UI.Xaml; + +namespace FIP.App.Helpers.Settings; + +public partial class SettingsHelper : ObservableSettings +{ + private static readonly SettingsHelper instance = new(SettingsProviderFactory.CreateProvider()); + public static SettingsHelper Current => instance; + + private SettingsHelper(ISettingsProvider provider) + : base(provider) + { + } + public const int MaxRecentlyVisitedSamples = 7; + + public ElementTheme SelectedAppTheme + { + get => GetOrCreateDefault(ElementTheme.Default); + set => Set(value); + } + + public bool IsLeftMode + { + get => GetOrCreateDefault(true); + set => Set(value); + } + + public bool IsShowCopyLinkTeachingTip + { + get => GetOrCreateDefault(true); + set => Set(value); + } + + public bool IsFirstRun + { + get => GetOrCreateDefault(true); + set => Set(value); + } +} diff --git a/src/FIP.App/FIP.App/Helpers/Settings/SettingsJsonContext.cs b/src/FIP.App/FIP.App/Helpers/Settings/SettingsJsonContext.cs new file mode 100644 index 0000000..b6e3a36 --- /dev/null +++ b/src/FIP.App/FIP.App/Helpers/Settings/SettingsJsonContext.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace FIP.App.Helpers.Settings; + +[JsonSourceGenerationOptions(WriteIndented = true, GenerationMode = JsonSourceGenerationMode.Metadata)] +[JsonSerializable(typeof(Dictionary))] +[JsonSerializable(typeof(SettingsHelper))] +internal partial class SettingsJsonContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/src/FIP.App/FIP.App/Helpers/Settings/ThemeHelper.cs b/src/FIP.App/FIP.App/Helpers/Settings/ThemeHelper.cs new file mode 100644 index 0000000..40ee41b --- /dev/null +++ b/src/FIP.App/FIP.App/Helpers/Settings/ThemeHelper.cs @@ -0,0 +1,78 @@ +using Microsoft.UI.Xaml; + +namespace FIP.App.Helpers.Settings; + +/// +/// Class providing functionality around switching and restoring theme settings +/// +public static partial class ThemeHelper +{ + /// + /// Gets the current actual theme of the app based on the requested theme of the + /// root element, or if that value is Default, the requested theme of the Application. + /// + public static ElementTheme ActualTheme + { + get + { + foreach (Window window in WindowHelper.ActiveWindows) + { + if (window.Content is FrameworkElement rootElement) + { + if (rootElement.RequestedTheme != ElementTheme.Default) + { + return rootElement.RequestedTheme; + } + } + } + + return EnumHelper.GetEnum(App.Current.RequestedTheme.ToString()); + } + } + + /// + /// Gets or sets (with LocalSettings persistence) the RequestedTheme of the root element. + /// + public static ElementTheme RootTheme + { + get + { + foreach (Window window in WindowHelper.ActiveWindows) + { + if (window.Content is FrameworkElement rootElement) + { + return rootElement.RequestedTheme; + } + } + + return ElementTheme.Default; + } + set + { + foreach (Window window in WindowHelper.ActiveWindows) + { + if (window.Content is FrameworkElement rootElement) + { + rootElement.RequestedTheme = value; + } + } + + SettingsHelper.Current.SelectedAppTheme = value; + } + } + + public static void Initialize() + { + RootTheme = SettingsHelper.Current.SelectedAppTheme; + } + + public static bool IsDarkTheme() + { + if (RootTheme == ElementTheme.Default) + { + return Application.Current.RequestedTheme == ApplicationTheme.Dark; + } + return RootTheme == ElementTheme.Dark; + } +} + diff --git a/src/FIP.App/FIP.App/MainWindow.xaml b/src/FIP.App/FIP.App/MainWindow.xaml index 0a4c6a2..7aeabee 100644 --- a/src/FIP.App/FIP.App/MainWindow.xaml +++ b/src/FIP.App/FIP.App/MainWindow.xaml @@ -6,7 +6,9 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> - + + + \ No newline at end of file diff --git a/src/FIP.App/FIP.App/Services/CategoryStorageService.cs b/src/FIP.App/FIP.App/Services/CategoryStorageService.cs index 58960e8..89d5f87 100644 --- a/src/FIP.App/FIP.App/Services/CategoryStorageService.cs +++ b/src/FIP.App/FIP.App/Services/CategoryStorageService.cs @@ -6,7 +6,6 @@ using System.Linq; using Windows.Storage; using FIP.Core.Models; -using CommunityToolkit.WinUI.UI; using FIP.App.Helpers; namespace FIP.App.Services diff --git a/src/FIP.App/FIP.App/Services/FolderIconService.cs b/src/FIP.App/FIP.App/Services/FolderIconService.cs index e71a29d..d690446 100644 --- a/src/FIP.App/FIP.App/Services/FolderIconService.cs +++ b/src/FIP.App/FIP.App/Services/FolderIconService.cs @@ -1,5 +1,4 @@ -using CommunityToolkit.WinUI.Helpers; -using FIP.App.Constants; +using FIP.App.Constants; using FIP.App.Helpers; using FIP.Core.Models; using FIP.Core.Services; @@ -8,7 +7,6 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using Windows.ApplicationModel; using Windows.Storage; using Bitmap = System.Drawing.Bitmap; @@ -194,7 +192,8 @@ public async Task CreateSvgFolderIconAsync(CustomIcon customIcon, s Directory.CreateDirectory(newIconFolderPath); StorageFolder iconsFolder = await StorageFolder.GetFolderFromPathAsync(newIconFolderPath); StorageFile newIconFile = await iconsFolder.CreateFileAsync($"{customIcon.Id}.svg"); - return await iconsFolder.WriteTextToFileAsync(svgString, newIconFile.Name); + await FileIO.WriteTextAsync(newIconFile, svgString); + return newIconFile; } catch (Exception) { diff --git a/src/FIP.App/FIP.App/Views/AllFolderIconsPage.xaml b/src/FIP.App/FIP.App/Views/AllFolderIconsPage.xaml index 6b62bce..37bf4a8 100644 --- a/src/FIP.App/FIP.App/Views/AllFolderIconsPage.xaml +++ b/src/FIP.App/FIP.App/Views/AllFolderIconsPage.xaml @@ -9,7 +9,6 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:usercontrols="using:FIP.App.UserControls" - xmlns:controls="using:CommunityToolkit.WinUI.UI.Controls" xmlns:viewmodels="using:FIP.App.ViewModels" xmlns:models="using:FIP.Core.ViewModels" DataContext="{x:Bind ViewModel, Mode=OneWay}" mc:Ignorable="d"> @@ -95,19 +94,15 @@ - - - + + @@ -118,8 +113,8 @@ - - + + diff --git a/src/FIP.App/FIP.App/Views/CustomIconsPage.xaml b/src/FIP.App/FIP.App/Views/CustomIconsPage.xaml index e6a297c..2f9c27f 100644 --- a/src/FIP.App/FIP.App/Views/CustomIconsPage.xaml +++ b/src/FIP.App/FIP.App/Views/CustomIconsPage.xaml @@ -9,9 +9,6 @@ xmlns:models="using:FIP.Core.ViewModels" xmlns:appVm="using:FIP.App.ViewModels" xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml" - xmlns:interactivity="using:Microsoft.Xaml.Interactivity" - xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" - xmlns:controls="using:CommunityToolkit.WinUI.UI.Controls" x:Name="CustomIconsPageControl" NavigationCacheMode="Enabled" HighContrastAdjustment="None" diff --git a/src/FIP.App/FIP.App/Views/SettingsPage.xaml b/src/FIP.App/FIP.App/Views/SettingsPage.xaml index ba725c2..02b2d9a 100644 --- a/src/FIP.App/FIP.App/Views/SettingsPage.xaml +++ b/src/FIP.App/FIP.App/Views/SettingsPage.xaml @@ -7,10 +7,104 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:FIP.App.Views" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:controls="using:CommunityToolkit.WinUI.UI.Controls" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:controls="using:CommunityToolkit.WinUI.Controls" mc:Ignorable="d"> + + + - - + + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +