diff --git a/Filtration.Interface/Filtration.Interface.csproj b/Filtration.Interface/Filtration.Interface.csproj index bc71f57..d383624 100644 --- a/Filtration.Interface/Filtration.Interface.csproj +++ b/Filtration.Interface/Filtration.Interface.csproj @@ -31,9 +31,24 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> + <Reference Include="GalaSoft.MvvmLight, Version=5.3.0.19026, Culture=neutral, PublicKeyToken=e7570ab207bcb616, processorArchitecture=MSIL"> + <HintPath>..\packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.dll</HintPath> + </Reference> + <Reference Include="GalaSoft.MvvmLight.Extras, Version=5.3.0.19032, Culture=neutral, PublicKeyToken=669f0b5e8f868abf, processorArchitecture=MSIL"> + <HintPath>..\packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.Extras.dll</HintPath> + </Reference> + <Reference Include="GalaSoft.MvvmLight.Platform, Version=5.3.0.19032, Culture=neutral, PublicKeyToken=5f873c45e98af8a1, processorArchitecture=MSIL"> + <HintPath>..\packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.Platform.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Practices.ServiceLocation, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll</HintPath> + </Reference> <Reference Include="PresentationCore" /> <Reference Include="System" /> <Reference Include="System.Core" /> + <Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\packages\MvvmLightLibs.5.3.0.0\lib\net45\System.Windows.Interactivity.dll</HintPath> + </Reference> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="Microsoft.CSharp" /> @@ -46,6 +61,9 @@ <Compile Include="IEditableDocument.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> + <ItemGroup> + <None Include="packages.config" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. diff --git a/Filtration.Interface/IDocument.cs b/Filtration.Interface/IDocument.cs index 8f86095..c32a38b 100644 --- a/Filtration.Interface/IDocument.cs +++ b/Filtration.Interface/IDocument.cs @@ -1,4 +1,6 @@ using System.Threading.Tasks; +using System.Windows.Input; +using GalaSoft.MvvmLight.CommandWpf; namespace Filtration.Interface { @@ -7,5 +9,6 @@ namespace Filtration.Interface bool IsScript { get; } bool IsTheme { get; } Task Close(); + RelayCommand CloseCommand { get; } } } diff --git a/Filtration.Interface/packages.config b/Filtration.Interface/packages.config new file mode 100644 index 0000000..946df8d --- /dev/null +++ b/Filtration.Interface/packages.config @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="CommonServiceLocator" version="1.3" targetFramework="net461" /> + <package id="MvvmLightLibs" version="5.3.0.0" targetFramework="net461" /> +</packages> \ No newline at end of file diff --git a/Filtration.sln b/Filtration.sln index e7dc0d1..c72486f 100644 --- a/Filtration.sln +++ b/Filtration.sln @@ -45,6 +45,10 @@ Global Release|ARM = Release|ARM Release|x64 = Release|x64 Release|x86 = Release|x86 + SquirrelReleasify|Any CPU = SquirrelReleasify|Any CPU + SquirrelReleasify|ARM = SquirrelReleasify|ARM + SquirrelReleasify|x64 = SquirrelReleasify|x64 + SquirrelReleasify|x86 = SquirrelReleasify|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {55E0A34C-E039-43D7-A024-A4045401CDDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -63,6 +67,14 @@ Global {55E0A34C-E039-43D7-A024-A4045401CDDA}.Release|x64.Build.0 = Release|Any CPU {55E0A34C-E039-43D7-A024-A4045401CDDA}.Release|x86.ActiveCfg = Release|Any CPU {55E0A34C-E039-43D7-A024-A4045401CDDA}.Release|x86.Build.0 = Release|Any CPU + {55E0A34C-E039-43D7-A024-A4045401CDDA}.SquirrelReleasify|Any CPU.ActiveCfg = Releasify|Any CPU + {55E0A34C-E039-43D7-A024-A4045401CDDA}.SquirrelReleasify|Any CPU.Build.0 = Releasify|Any CPU + {55E0A34C-E039-43D7-A024-A4045401CDDA}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {55E0A34C-E039-43D7-A024-A4045401CDDA}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {55E0A34C-E039-43D7-A024-A4045401CDDA}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {55E0A34C-E039-43D7-A024-A4045401CDDA}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {55E0A34C-E039-43D7-A024-A4045401CDDA}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {55E0A34C-E039-43D7-A024-A4045401CDDA}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {E0693972-72C5-4E05-A9C5-A5943E4015C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E0693972-72C5-4E05-A9C5-A5943E4015C6}.Debug|Any CPU.Build.0 = Debug|Any CPU {E0693972-72C5-4E05-A9C5-A5943E4015C6}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -79,6 +91,14 @@ Global {E0693972-72C5-4E05-A9C5-A5943E4015C6}.Release|x64.Build.0 = Release|Any CPU {E0693972-72C5-4E05-A9C5-A5943E4015C6}.Release|x86.ActiveCfg = Release|Any CPU {E0693972-72C5-4E05-A9C5-A5943E4015C6}.Release|x86.Build.0 = Release|Any CPU + {E0693972-72C5-4E05-A9C5-A5943E4015C6}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {E0693972-72C5-4E05-A9C5-A5943E4015C6}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {E0693972-72C5-4E05-A9C5-A5943E4015C6}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {E0693972-72C5-4E05-A9C5-A5943E4015C6}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {E0693972-72C5-4E05-A9C5-A5943E4015C6}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {E0693972-72C5-4E05-A9C5-A5943E4015C6}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {E0693972-72C5-4E05-A9C5-A5943E4015C6}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {E0693972-72C5-4E05-A9C5-A5943E4015C6}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.Debug|Any CPU.Build.0 = Debug|Any CPU {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -95,6 +115,14 @@ Global {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.Release|x64.Build.0 = Release|Any CPU {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.Release|x86.ActiveCfg = Release|Any CPU {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.Release|x86.Build.0 = Release|Any CPU + {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {4AAC3BEB-1DC1-483E-9D11-0E9334E80227}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {537BE676-2FF6-4995-B05B-9CFACE852EC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {537BE676-2FF6-4995-B05B-9CFACE852EC9}.Debug|Any CPU.Build.0 = Debug|Any CPU {537BE676-2FF6-4995-B05B-9CFACE852EC9}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -111,6 +139,14 @@ Global {537BE676-2FF6-4995-B05B-9CFACE852EC9}.Release|x64.Build.0 = Release|Any CPU {537BE676-2FF6-4995-B05B-9CFACE852EC9}.Release|x86.ActiveCfg = Release|Any CPU {537BE676-2FF6-4995-B05B-9CFACE852EC9}.Release|x86.Build.0 = Release|Any CPU + {537BE676-2FF6-4995-B05B-9CFACE852EC9}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {537BE676-2FF6-4995-B05B-9CFACE852EC9}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {537BE676-2FF6-4995-B05B-9CFACE852EC9}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {537BE676-2FF6-4995-B05B-9CFACE852EC9}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {537BE676-2FF6-4995-B05B-9CFACE852EC9}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {537BE676-2FF6-4995-B05B-9CFACE852EC9}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {537BE676-2FF6-4995-B05B-9CFACE852EC9}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {537BE676-2FF6-4995-B05B-9CFACE852EC9}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.Debug|Any CPU.Build.0 = Debug|Any CPU {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -127,6 +163,14 @@ Global {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.Release|x64.Build.0 = Release|Any CPU {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.Release|x86.ActiveCfg = Release|Any CPU {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.Release|x86.Build.0 = Release|Any CPU + {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {41B8F5C2-65AA-42F0-A20B-6F95B13A9F48}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {450AC313-BF25-4BFD-A066-9F39F026FDCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {450AC313-BF25-4BFD-A066-9F39F026FDCF}.Debug|Any CPU.Build.0 = Debug|Any CPU {450AC313-BF25-4BFD-A066-9F39F026FDCF}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -143,6 +187,14 @@ Global {450AC313-BF25-4BFD-A066-9F39F026FDCF}.Release|x64.Build.0 = Release|Any CPU {450AC313-BF25-4BFD-A066-9F39F026FDCF}.Release|x86.ActiveCfg = Release|Any CPU {450AC313-BF25-4BFD-A066-9F39F026FDCF}.Release|x86.Build.0 = Release|Any CPU + {450AC313-BF25-4BFD-A066-9F39F026FDCF}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {450AC313-BF25-4BFD-A066-9F39F026FDCF}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {450AC313-BF25-4BFD-A066-9F39F026FDCF}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {450AC313-BF25-4BFD-A066-9F39F026FDCF}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {450AC313-BF25-4BFD-A066-9F39F026FDCF}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {450AC313-BF25-4BFD-A066-9F39F026FDCF}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {450AC313-BF25-4BFD-A066-9F39F026FDCF}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {450AC313-BF25-4BFD-A066-9F39F026FDCF}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {0F333344-7695-47B2-B0E6-172E4DE74819}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0F333344-7695-47B2-B0E6-172E4DE74819}.Debug|Any CPU.Build.0 = Debug|Any CPU {0F333344-7695-47B2-B0E6-172E4DE74819}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -159,6 +211,14 @@ Global {0F333344-7695-47B2-B0E6-172E4DE74819}.Release|x64.Build.0 = Release|Any CPU {0F333344-7695-47B2-B0E6-172E4DE74819}.Release|x86.ActiveCfg = Release|Any CPU {0F333344-7695-47B2-B0E6-172E4DE74819}.Release|x86.Build.0 = Release|Any CPU + {0F333344-7695-47B2-B0E6-172E4DE74819}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {0F333344-7695-47B2-B0E6-172E4DE74819}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {0F333344-7695-47B2-B0E6-172E4DE74819}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {0F333344-7695-47B2-B0E6-172E4DE74819}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {0F333344-7695-47B2-B0E6-172E4DE74819}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {0F333344-7695-47B2-B0E6-172E4DE74819}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {0F333344-7695-47B2-B0E6-172E4DE74819}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {0F333344-7695-47B2-B0E6-172E4DE74819}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {8CB44F28-2956-4C2A-9314-72727262EDD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8CB44F28-2956-4C2A-9314-72727262EDD4}.Debug|Any CPU.Build.0 = Debug|Any CPU {8CB44F28-2956-4C2A-9314-72727262EDD4}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -175,6 +235,14 @@ Global {8CB44F28-2956-4C2A-9314-72727262EDD4}.Release|x64.Build.0 = Release|Any CPU {8CB44F28-2956-4C2A-9314-72727262EDD4}.Release|x86.ActiveCfg = Release|Any CPU {8CB44F28-2956-4C2A-9314-72727262EDD4}.Release|x86.Build.0 = Release|Any CPU + {8CB44F28-2956-4C2A-9314-72727262EDD4}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {8CB44F28-2956-4C2A-9314-72727262EDD4}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {8CB44F28-2956-4C2A-9314-72727262EDD4}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {8CB44F28-2956-4C2A-9314-72727262EDD4}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {8CB44F28-2956-4C2A-9314-72727262EDD4}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {8CB44F28-2956-4C2A-9314-72727262EDD4}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {8CB44F28-2956-4C2A-9314-72727262EDD4}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {8CB44F28-2956-4C2A-9314-72727262EDD4}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.Debug|Any CPU.Build.0 = Debug|Any CPU {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -191,6 +259,14 @@ Global {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.Release|x64.Build.0 = Release|Any CPU {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.Release|x86.ActiveCfg = Release|Any CPU {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.Release|x86.Build.0 = Release|Any CPU + {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {1E42A658-45C4-4DD9-83C5-2A10728DBDFA}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.Debug|Any CPU.Build.0 = Debug|Any CPU {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -207,6 +283,14 @@ Global {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.Release|x64.Build.0 = Release|Any CPU {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.Release|x86.ActiveCfg = Release|Any CPU {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.Release|x86.Build.0 = Release|Any CPU + {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {3AB98B6E-05DB-44FA-9DAD-584AA88F0739}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.Debug|Any CPU.Build.0 = Debug|Any CPU {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -223,6 +307,14 @@ Global {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.Release|x64.Build.0 = Release|Any CPU {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.Release|x86.ActiveCfg = Release|Any CPU {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.Release|x86.Build.0 = Release|Any CPU + {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {58CD3B9C-EBBA-4527-A81C-78B7EA9CA298}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.Debug|Any CPU.Build.0 = Debug|Any CPU {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -239,6 +331,14 @@ Global {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.Release|x64.Build.0 = Release|Any CPU {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.Release|x86.ActiveCfg = Release|Any CPU {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.Release|x86.Build.0 = Release|Any CPU + {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {10A7C2BC-EC6F-4A38-BDDA-E35935004C02}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {46383F20-02DF-48B4-B092-9088FA4ACD5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {46383F20-02DF-48B4-B092-9088FA4ACD5A}.Debug|Any CPU.Build.0 = Debug|Any CPU {46383F20-02DF-48B4-B092-9088FA4ACD5A}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -255,6 +355,14 @@ Global {46383F20-02DF-48B4-B092-9088FA4ACD5A}.Release|x64.Build.0 = Release|Any CPU {46383F20-02DF-48B4-B092-9088FA4ACD5A}.Release|x86.ActiveCfg = Release|Any CPU {46383F20-02DF-48B4-B092-9088FA4ACD5A}.Release|x86.Build.0 = Release|Any CPU + {46383F20-02DF-48B4-B092-9088FA4ACD5A}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {46383F20-02DF-48B4-B092-9088FA4ACD5A}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {46383F20-02DF-48B4-B092-9088FA4ACD5A}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {46383F20-02DF-48B4-B092-9088FA4ACD5A}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {46383F20-02DF-48B4-B092-9088FA4ACD5A}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {46383F20-02DF-48B4-B092-9088FA4ACD5A}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {46383F20-02DF-48B4-B092-9088FA4ACD5A}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {46383F20-02DF-48B4-B092-9088FA4ACD5A}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.Debug|Any CPU.Build.0 = Debug|Any CPU {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -271,6 +379,14 @@ Global {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.Release|x64.Build.0 = Release|Any CPU {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.Release|x86.ActiveCfg = Release|Any CPU {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.Release|x86.Build.0 = Release|Any CPU + {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {1F30CF6D-A5BF-4777-B8BA-E34F439FE8E5}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.Debug|Any CPU.Build.0 = Debug|Any CPU {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -287,6 +403,14 @@ Global {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.Release|x64.Build.0 = Release|Any CPU {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.Release|x86.ActiveCfg = Release|Any CPU {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.Release|x86.Build.0 = Release|Any CPU + {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {855B38CC-EEF2-471D-BBBC-EB3E2FF3D387}.SquirrelReleasify|x86.Build.0 = Release|Any CPU {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.Debug|Any CPU.Build.0 = Debug|Any CPU {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -303,8 +427,19 @@ Global {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.Release|x64.Build.0 = Release|Any CPU {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.Release|x86.ActiveCfg = Release|Any CPU {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.Release|x86.Build.0 = Release|Any CPU + {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.SquirrelReleasify|Any CPU.ActiveCfg = Release|Any CPU + {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.SquirrelReleasify|Any CPU.Build.0 = Release|Any CPU + {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.SquirrelReleasify|ARM.ActiveCfg = Release|Any CPU + {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.SquirrelReleasify|ARM.Build.0 = Release|Any CPU + {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.SquirrelReleasify|x64.ActiveCfg = Release|Any CPU + {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.SquirrelReleasify|x64.Build.0 = Release|Any CPU + {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.SquirrelReleasify|x86.ActiveCfg = Release|Any CPU + {7A5720DE-A41B-47EA-AAAB-7C5608FF0C1F}.SquirrelReleasify|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8A170BBA-F99C-4192-9467-A5669B1DE126} + EndGlobalSection EndGlobal diff --git a/Filtration.sln.DotSettings b/Filtration.sln.DotSettings index c6806ba..de2c6b9 100644 --- a/Filtration.sln.DotSettings +++ b/Filtration.sln.DotSettings @@ -2,4 +2,5 @@ <s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/NamespacesWithAnnotations/=Filtration_002EAnnotations/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/NamespacesWithAnnotations/=Filtration_002EObjectModel_002EAnnotations/@EntryIndexedValue">True</s:Boolean> <s:String x:Key="/Default/FilterSettingsManager/AttributeFilterXml/@EntryValue"><data /></s:String> - <s:String x:Key="/Default/FilterSettingsManager/CoverageFilterXml/@EntryValue"><data><IncludeFilters /><ExcludeFilters><Filter ModuleMask="Filtration.ItemFilterPreview.Tests" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /><Filter ModuleMask="Filtration.ObjectModel.Tests" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /><Filter ModuleMask="Filtration.ThemeEditor.Tests" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /><Filter ModuleMask="Filtration.Tests" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /></ExcludeFilters></data></s:String></wpf:ResourceDictionary> \ No newline at end of file + <s:String x:Key="/Default/FilterSettingsManager/CoverageFilterXml/@EntryValue"><data><IncludeFilters /><ExcludeFilters><Filter ModuleMask="Filtration.ItemFilterPreview.Tests" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /><Filter ModuleMask="Filtration.ObjectModel.Tests" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /><Filter ModuleMask="Filtration.ThemeEditor.Tests" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /><Filter ModuleMask="Filtration.Tests" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /></ExcludeFilters></data></s:String> + <s:Boolean x:Key="/Default/UserDictionary/Words/=Prerelease/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> \ No newline at end of file diff --git a/Filtration/App.config b/Filtration/App.config index ebcbc98..4281109 100644 --- a/Filtration/App.config +++ b/Filtration/App.config @@ -31,6 +31,33 @@ <setting name="StaticDataLastUpdated" serializeAs="String"> <value>2016-01-01</value> </setting> + <setting name="DownloadPrereleaseUpdates" serializeAs="String"> + <value>False</value> + </setting> + <setting name="ShowSectionBrowser" serializeAs="String"> + <value>True</value> + </setting> + <setting name="ShowBlockGroupBrowser" serializeAs="String"> + <value>True</value> + </setting> + <setting name="ShowBlockOutputPreview" serializeAs="String"> + <value>True</value> + </setting> + <setting name="ShowAdvanced" serializeAs="String"> + <value>False</value> + </setting> + <setting name="WindowState" serializeAs="String"> + <value>Normal</value> + </setting> + <setting name="WindowWidth" serializeAs="String"> + <value>1200</value> + </setting> + <setting name="WindowHeight" serializeAs="String"> + <value>800</value> + </setting> + <setting name="LastActiveDocument" serializeAs="String"> + <value /> + </setting> </Filtration.Properties.Settings> </userSettings> <runtime> diff --git a/Filtration/App.xaml.cs b/Filtration/App.xaml.cs index 624f22e..692aa95 100644 --- a/Filtration/App.xaml.cs +++ b/Filtration/App.xaml.cs @@ -1,32 +1,23 @@ -using System; -using System.Linq; +using System.Linq; using System.Windows; -using System.Windows.Threading; using AutoMapper; using Castle.Facilities.TypedFactory; using Castle.MicroKernel.ModelBuilder.Inspectors; using Castle.Windsor; using Castle.Windsor.Installer; -using Filtration.ObjectModel; using Filtration.ObjectModel.ThemeEditor; using Filtration.Properties; using Filtration.Services; using Filtration.ThemeEditor.ViewModels; -using Filtration.ViewModels; -using Filtration.Views; -using NLog; namespace Filtration { public partial class App { private IWindsorContainer _container; - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - private void Application_Startup(object sender, StartupEventArgs e) + private async void Application_Startup(object sender, StartupEventArgs e) { - DispatcherUnhandledException += OnDispatcherUnhandledException; - _container = new WindsorContainer(); // Disable property injection @@ -56,26 +47,9 @@ namespace Filtration }); Mapper.AssertConfigurationIsValid(); - - var mainWindow = _container.Resolve<IMainWindow>(); - mainWindow.Show(); - - var updateCheckService = _container.Resolve<IUpdateCheckService>(); - updateCheckService.CheckForUpdates(); - } - - private static void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) - { - Logger.Fatal(e.Exception); - var exception = e.Exception.Message + Environment.NewLine + e.Exception.StackTrace; - var innerException = e.Exception.InnerException != null - ? e.Exception.InnerException.Message + Environment.NewLine + - e.Exception.InnerException.StackTrace - : string.Empty; - - MessageBox.Show( - exception + Environment.NewLine + innerException, - "Unhandled Exception", MessageBoxButton.OK, MessageBoxImage.Error); + + var bootstrapper = _container.Resolve<IBootstrapper>(); + await bootstrapper.GoAsync(); } protected override void OnExit(ExitEventArgs e) diff --git a/Filtration/Filtration.csproj b/Filtration/Filtration.csproj index f2d679c..c87a98b 100644 --- a/Filtration/Filtration.csproj +++ b/Filtration/Filtration.csproj @@ -15,21 +15,6 @@ <WarningLevel>4</WarningLevel> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <TargetFrameworkProfile /> - <PublishUrl>publish\</PublishUrl> - <Install>true</Install> - <InstallFrom>Disk</InstallFrom> - <UpdateEnabled>false</UpdateEnabled> - <UpdateMode>Foreground</UpdateMode> - <UpdateInterval>7</UpdateInterval> - <UpdateIntervalUnits>Days</UpdateIntervalUnits> - <UpdatePeriodically>false</UpdatePeriodically> - <UpdateRequired>false</UpdateRequired> - <MapFileExtensions>true</MapFileExtensions> - <ApplicationRevision>0</ApplicationRevision> - <ApplicationVersion>1.0.0.%2a</ApplicationVersion> - <IsWebBootstrapper>false</IsWebBootstrapper> - <UseApplicationTrust>false</UseApplicationTrust> - <BootstrapperEnabled>true</BootstrapperEnabled> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PlatformTarget>AnyCPU</PlatformTarget> @@ -56,6 +41,16 @@ <PropertyGroup> <ApplicationIcon>Resources\filtration.ico</ApplicationIcon> </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Releasify|AnyCPU'"> + <OutputPath>bin\Releasify\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <Optimize>true</Optimize> + <DebugType>pdbonly</DebugType> + <PlatformTarget>AnyCPU</PlatformTarget> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + <Prefer32Bit>true</Prefer32Bit> + </PropertyGroup> <ItemGroup> <Reference Include="AutoMapper, Version=6.0.2.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL"> <HintPath>..\packages\AutoMapper.6.0.2\lib\net45\AutoMapper.dll</HintPath> @@ -70,6 +65,15 @@ <Reference Include="ControlzEx, Version=2.2.0.4, Culture=neutral, PublicKeyToken=f08b075e934b7045, processorArchitecture=MSIL"> <HintPath>..\packages\ControlzEx.2.2.0.4\lib\net45\ControlzEx.dll</HintPath> </Reference> + <Reference Include="DeltaCompressionDotNet, Version=1.1.0.0, Culture=neutral, PublicKeyToken=1d14d6e5194e7f4a, processorArchitecture=MSIL"> + <HintPath>..\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.dll</HintPath> + </Reference> + <Reference Include="DeltaCompressionDotNet.MsDelta, Version=1.1.0.0, Culture=neutral, PublicKeyToken=46b2138a390abf55, processorArchitecture=MSIL"> + <HintPath>..\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.MsDelta.dll</HintPath> + </Reference> + <Reference Include="DeltaCompressionDotNet.PatchApi, Version=1.1.0.0, Culture=neutral, PublicKeyToken=3e8888ee913ed789, processorArchitecture=MSIL"> + <HintPath>..\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.PatchApi.dll</HintPath> + </Reference> <Reference Include="Fluent, Version=4.0.3.394, Culture=neutral, PublicKeyToken=3e436e32a8c5546f, processorArchitecture=MSIL"> <HintPath>..\packages\Fluent.Ribbon.4.0.3.394\lib\net45\Fluent.dll</HintPath> <Private>True</Private> @@ -91,10 +95,41 @@ <Private>True</Private> </Reference> <Reference Include="Microsoft.CSharp" /> + <Reference Include="Microsoft.WindowsAPICodePack, Version=1.1.2.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>..\packages\WindowsAPICodePack-Core.1.1.2\lib\Microsoft.WindowsAPICodePack.dll</HintPath> + </Reference> + <Reference Include="Microsoft.WindowsAPICodePack.Shell, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>..\packages\WindowsAPICodePack-Shell.1.1.1\lib\Microsoft.WindowsAPICodePack.Shell.dll</HintPath> + </Reference> + <Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL"> + <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.dll</HintPath> + </Reference> + <Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL"> + <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Mdb.dll</HintPath> + </Reference> + <Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL"> + <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Pdb.dll</HintPath> + </Reference> + <Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL"> + <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Rocks.dll</HintPath> + </Reference> <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <HintPath>..\packages\NLog.4.4.9\lib\net45\NLog.dll</HintPath> </Reference> + <Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>..\packages\squirrel.windows.1.8.0\lib\Net45\NuGet.Squirrel.dll</HintPath> + </Reference> + <Reference Include="SharpCompress, Version=0.17.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL"> + <HintPath>..\packages\SharpCompress.0.17.1\lib\net45\SharpCompress.dll</HintPath> + </Reference> + <Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath> + </Reference> + <Reference Include="Squirrel, Version=1.8.0.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>..\packages\squirrel.windows.1.8.0\lib\Net45\Squirrel.dll</HintPath> + </Reference> <Reference Include="System" /> + <Reference Include="System.Configuration" /> <Reference Include="System.Drawing" /> <Reference Include="System.Windows.Controls.Input.Toolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> @@ -113,6 +148,7 @@ <Reference Include="System.Xaml"> <RequiredTargetFramework>4.0</RequiredTargetFramework> </Reference> + <Reference Include="System.Xml.Linq" /> <Reference Include="WindowsBase" /> <Reference Include="PresentationCore" /> <Reference Include="PresentationFramework" /> @@ -170,11 +206,13 @@ <Compile Include="Models\UpdateData.cs" /> <Compile Include="Properties\Annotations.cs" /> <Compile Include="Repositories\ItemFilterScriptRepository.cs" /> + <Compile Include="Services\Bootstrapper.cs" /> <Compile Include="Services\ClipboardService.cs" /> <Compile Include="Services\HTTPService.cs" /> <Compile Include="Services\ItemFilterPersistenceService.cs" /> + <Compile Include="Services\SettingsService.cs" /> <Compile Include="Services\StaticDataService.cs" /> - <Compile Include="Services\UpdateCheckService.cs" /> + <Compile Include="Services\UpdateService.cs" /> <Compile Include="Settings.cs" /> <Compile Include="UserControls\AutoScrollingListBox.cs" /> <Compile Include="UserControls\BlockItemControl.xaml.cs"> @@ -191,10 +229,13 @@ <Compile Include="UserControls\ThemeComponentSelectionControl.xaml.cs"> <DependentUpon>ThemeComponentSelectionControl.xaml</DependentUpon> </Compile> + <Compile Include="ViewModels\DesignTime\DesignTimeSettingsPageViewModel.cs" /> <Compile Include="Views\AttachedProperties\SelectedItemsAttachedProperty.cs" /> <Compile Include="Utility\RoutedCommandHandler.cs" /> <Compile Include="Utility\RoutedCommandHandlers.cs" /> <Compile Include="ViewModels\AvalonDockWorkspaceViewModel.cs" /> + <Compile Include="ViewModels\DesignTime\DesignTimeMainWindowViewModel.cs" /> + <Compile Include="ViewModels\DesignTime\DesignTimeUpdateViewModel.cs" /> <Compile Include="ViewModels\Factories\IItemFilterCommentBlockViewModelFactory.cs" /> <Compile Include="ViewModels\Factories\ItemFilterBlockBaseViewModelFactory.cs" /> <Compile Include="ViewModels\ItemFilterBlockViewModelBase.cs" /> @@ -211,7 +252,7 @@ <Compile Include="ViewModels\ToolPanes\CommentBlockBrowserViewModel.cs" /> <Compile Include="ViewModels\StartPageViewModel.cs" /> <Compile Include="ViewModels\ToolPanes\ToolViewModel.cs" /> - <Compile Include="ViewModels\UpdateAvailableViewModel.cs" /> + <Compile Include="ViewModels\UpdateViewModel.cs" /> <Compile Include="Views\AttachedProperties\SelectingItemAttachedProperty.cs" /> <Compile Include="Views\AvalonDock\AvalonDockWorkspaceView.xaml.cs"> <DependentUpon>AvalonDockWorkspaceView.xaml</DependentUpon> @@ -267,8 +308,11 @@ <Compile Include="Views\ToolPanes\CommentBlockBrowserView.xaml.cs"> <DependentUpon>CommentBlockBrowserView.xaml</DependentUpon> </Compile> - <Compile Include="Views\UpdateAvailableView.xaml.cs"> - <DependentUpon>UpdateAvailableView.xaml</DependentUpon> + <Compile Include="Views\UpdateTabView.xaml.cs"> + <DependentUpon>UpdateTabView.xaml</DependentUpon> + </Compile> + <Compile Include="Views\UpdateView.xaml.cs"> + <DependentUpon>UpdateView.xaml</DependentUpon> </Compile> <Compile Include="WindsorInstallers\RepositoriesInstaller.cs" /> <Compile Include="WindsorInstallers\ServicesInstaller.cs" /> @@ -371,7 +415,11 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> - <Page Include="Views\UpdateAvailableView.xaml"> + <Page Include="Views\UpdateTabView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Views\UpdateView.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> @@ -394,13 +442,16 @@ <EmbeddedResource Include="Properties\Resources.resx"> <Generator>ResXFileCodeGenerator</Generator> <LastGenOutput>Resources.Designer.cs</LastGenOutput> + <SubType>Designer</SubType> </EmbeddedResource> <Content Include="LICENSE.txt"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> <Content Include="NLog.config"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> + <SubType>Designer</SubType> </Content> + <None Include="Filtration.nuspec" /> <None Include="NLog.xsd"> <SubType>Designer</SubType> </None> @@ -580,12 +631,33 @@ </BootstrapperPackage> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <Import Project="$(XamlSpyInstallPath)MSBuild\FirstFloor.XamlSpy.WPF.targets" Condition="'$(XamlSpyInstallPath)' != '' and '$(Configuration)' == 'DEBUG'" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> + <Target Name="AfterBuild" Condition=" '$(Configuration)' == 'Releasify'"> + <GetAssemblyIdentity AssemblyFiles="$(TargetPath)"> + <Output TaskParameter="Assemblies" ItemName="myAssemblyInfo" /> + </GetAssemblyIdentity> + <ReadLinesFromFile File="$(ProjectDir)\Properties\AssemblyInfo.cs"> + <Output TaskParameter="Lines" ItemName="ItemsFromFile" /> + </ReadLinesFromFile> + <ItemGroup> + <!-- If your .NET version is <3.5 and you get build error, move this ItemGroup outside of Target --> + <NuGetExe Include="..\packages\NuGet.CommandLine.*\tools\nuget.exe" /> + <SquirrelExe Include="..\packages\Squirrel.Windows.*\tools\squirrel.exe" /> + </ItemGroup> + <PropertyGroup> + <ReleaseDir>..\Releases\</ReleaseDir> + <!-- Extra optional params for squirrel. can be empty --> + <SquirrelParams>--no-msi</SquirrelParams> + <Pattern>(?<=\[assembly: AssemblyInformationalVersion\(").*?(?="\)\])</Pattern> + <In>@(ItemsFromFile)</In> + <SemVerNumber>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern)))</SemVerNumber> + <!-- <SemVerNumber>$([System.Version]::Parse(%(myAssemblyInfo.Version)).ToString(3))</SemVerNumber> --> + </PropertyGroup> + <!-- Add some nice errors for the next person that comes along --> + <Error Condition="!Exists(%(NuGetExe.FullPath))" Text="You are trying to use the NuGet.CommandLine package, but it is not installed. Please install NuGet.CommandLine from the Package Manager." /> + <Error Condition="!Exists(%(SquirrelExe.FullPath))" Text="You are trying to use the Squirrel.Windows package, but it is not installed. Please install Squirrel.Windows from the Package Manager." /> + <!-- Build nupkg into the project local bin\Release\ directory temporarily --> + <Exec Command=""%(NuGetExe.FullPath)" pack $(TargetName).nuspec -Version $(SemVerNumber) -OutputDirectory $(OutDir) -BasePath $(OutDir)" /> + <!-- Squirrelify into the release dir (usually at solution level. Change the property above for a different location --> + <Exec Command=""%(SquirrelExe.FullPath)" --releasify $(OutDir)Filtration.$(SemVerNumber).nupkg --releaseDir=$(ReleaseDir) $(SquirrelParams)" /> + </Target> </Project> \ No newline at end of file diff --git a/Filtration/Filtration.nuspec b/Filtration/Filtration.nuspec new file mode 100644 index 0000000..f89e215 --- /dev/null +++ b/Filtration/Filtration.nuspec @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> + <metadata> + <id>Filtration</id> + <!-- version will be replaced by MSBuild --> + <version>0.0.0.0</version> + <title>Filtration</title> + <authors>Ben Wallis</authors> + <description>A Path of Exile loot filter script editor</description> + <requireLicenseAcceptance>false</requireLicenseAcceptance> + <copyright>Copyright 2018</copyright> + <releaseNotes>The release notes for 1.0.0 have not been written yet!</releaseNotes> + <dependencies /> + </metadata> + <files> + <file src="*.*" target="lib\net45\" exclude="*.pdb;*.nupkg;*.vshost.*;*.xml"/> + </files> +</package> \ No newline at end of file diff --git a/Filtration/NLog.config b/Filtration/NLog.config index 9c219f8..af4b9bb 100644 --- a/Filtration/NLog.config +++ b/Filtration/NLog.config @@ -10,6 +10,7 @@ layout="${longdate} ${uppercase:${level}} ${message}" /> <target xsi:type="File" name="fDebug" fileName="${basedir}/Filtration_debug_${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" /> + <target xsi:type="Debugger" name="cDebug" layout="${longdate} ${uppercase:${level}} ${message}"/> </targets> <rules> @@ -17,6 +18,7 @@ <!-- Uncomment the Debug line to enable Debug logging --> <!--<logger name="*" minlevel="Debug" writeTo="fDebug" final="true" />--> <logger name="*" minlevel="Error" writeTo="fErrors" /> + <logger name="*" minlevel="Trace" writeTo="cDebug" /> </rules> </nlog> \ No newline at end of file diff --git a/Filtration/Properties/AssemblyInfo.cs b/Filtration/Properties/AssemblyInfo.cs index cc32a0b..395dec4 100644 --- a/Filtration/Properties/AssemblyInfo.cs +++ b/Filtration/Properties/AssemblyInfo.cs @@ -10,7 +10,8 @@ using System.Runtime.CompilerServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("0.21")] +[assembly: AssemblyVersion("1.0.0")] +[assembly: AssemblyInformationalVersion("1.0.0-beta1")] [assembly: InternalsVisibleTo("Filtration.Tests")] [assembly: InternalsVisibleTo("Filtration.ItemFilterPreview.Tests")] diff --git a/Filtration/Properties/Settings.Designer.cs b/Filtration/Properties/Settings.Designer.cs index 49ad864..57a3ddc 100644 --- a/Filtration/Properties/Settings.Designer.cs +++ b/Filtration/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace Filtration.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -121,123 +121,111 @@ namespace Filtration.Properties { return ((string)(this["UpdateDataUrl"])); } } - + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool DownloadPrereleaseUpdates { + get { + return ((bool)(this["DownloadPrereleaseUpdates"])); + } + set { + this["DownloadPrereleaseUpdates"] = value; + } + } + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool ShowSectionBrowser - { - get - { + public bool ShowSectionBrowser { + get { return ((bool)(this["ShowSectionBrowser"])); } - set - { + set { this["ShowSectionBrowser"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool ShowBlockGroupBrowser - { - get - { + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool ShowBlockGroupBrowser { + get { return ((bool)(this["ShowBlockGroupBrowser"])); } - set - { + set { this["ShowBlockGroupBrowser"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool ShowBlockOutputPreview - { - get - { + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool ShowBlockOutputPreview { + get { return ((bool)(this["ShowBlockOutputPreview"])); } - set - { + set { this["ShowBlockOutputPreview"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool ShowAdvanced - { - get - { + public bool ShowAdvanced { + get { return ((bool)(this["ShowAdvanced"])); } - set - { + set { this["ShowAdvanced"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("Normal")] - public global::System.Windows.WindowState WindowState - { - get - { + public global::System.Windows.WindowState WindowState { + get { return ((global::System.Windows.WindowState)(this["WindowState"])); } - set - { + set { this["WindowState"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("960")] - public int WindowWidth - { - get - { + [global::System.Configuration.DefaultSettingValueAttribute("1200")] + public int WindowWidth { + get { return ((int)(this["WindowWidth"])); } - set - { + set { this["WindowWidth"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("720")] - public int WindowHeight - { - get - { + [global::System.Configuration.DefaultSettingValueAttribute("800")] + public int WindowHeight { + get { return ((int)(this["WindowHeight"])); } - set - { + set { this["WindowHeight"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("")] - public string LastActiveDocument - { - get - { + public string LastActiveDocument { + get { return ((string)(this["LastActiveDocument"])); } - set - { + set { this["LastActiveDocument"] = value; } } diff --git a/Filtration/Properties/Settings.settings b/Filtration/Properties/Settings.settings index 79cafbc..802669b 100644 --- a/Filtration/Properties/Settings.settings +++ b/Filtration/Properties/Settings.settings @@ -29,5 +29,32 @@ <Setting Name="UpdateDataUrl" Type="System.String" Scope="Application"> <Value Profile="(Default)">http://ben-wallis.github.io/Filtration/filtration_version.xml</Value> </Setting> + <Setting Name="DownloadPrereleaseUpdates" Type="System.Boolean" Scope="User"> + <Value Profile="(Default)">False</Value> + </Setting> + <Setting Name="ShowSectionBrowser" Type="System.Boolean" Scope="User"> + <Value Profile="(Default)">True</Value> + </Setting> + <Setting Name="ShowBlockGroupBrowser" Type="System.Boolean" Scope="User"> + <Value Profile="(Default)">True</Value> + </Setting> + <Setting Name="ShowBlockOutputPreview" Type="System.Boolean" Scope="User"> + <Value Profile="(Default)">True</Value> + </Setting> + <Setting Name="ShowAdvanced" Type="System.Boolean" Scope="User"> + <Value Profile="(Default)">False</Value> + </Setting> + <Setting Name="WindowState" Type="System.Windows.WindowState" Scope="User"> + <Value Profile="(Default)">Normal</Value> + </Setting> + <Setting Name="WindowWidth" Type="System.Int32" Scope="User"> + <Value Profile="(Default)">1200</Value> + </Setting> + <Setting Name="WindowHeight" Type="System.Int32" Scope="User"> + <Value Profile="(Default)">800</Value> + </Setting> + <Setting Name="LastActiveDocument" Type="System.String" Scope="User"> + <Value Profile="(Default)" /> + </Setting> </Settings> </SettingsFile> \ No newline at end of file diff --git a/Filtration/Services/Bootstrapper.cs b/Filtration/Services/Bootstrapper.cs new file mode 100644 index 0000000..b79b58f --- /dev/null +++ b/Filtration/Services/Bootstrapper.cs @@ -0,0 +1,59 @@ +using System; +using System.Threading.Tasks; +using System.Windows; +using Filtration.Views; +using NLog; + +namespace Filtration.Services +{ + internal interface IBootstrapper + { + Task GoAsync(); + } + + internal class Bootstrapper : IBootstrapper + { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + private readonly IMainWindow _mainWindow; + private readonly ISettingsService _settingsService; + private readonly IUpdateService _updateService; + + public Bootstrapper(IMainWindow mainWindow, + ISettingsService settingsService, + IUpdateService updateService) + { + _mainWindow = mainWindow; + _settingsService = settingsService; + _updateService = updateService; + } + + public async Task GoAsync() + { + AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException; + + // Attempt to restore user settings - this is required because after an update any + // user settings will have been lost due to Squirrel changing the app directory + // with each update + _settingsService.RestoreSettings(); + + _mainWindow.Show(); + + await _updateService.CheckForUpdates(); + } + + private void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs e) + { + var exception = (Exception) e.ExceptionObject; + + Logger.Fatal(exception); + var exceptionMessage = exception.Message + Environment.NewLine + exception.StackTrace; + var innerException = exception.InnerException != null + ? exception.InnerException.Message + Environment.NewLine + + exception.InnerException.StackTrace + : string.Empty; + + MessageBox.Show(exceptionMessage + Environment.NewLine + innerException, "Unhandled Exception", MessageBoxButton.OK, MessageBoxImage.Error); + } + } +} diff --git a/Filtration/Services/SettingsService.cs b/Filtration/Services/SettingsService.cs new file mode 100644 index 0000000..ecfee9a --- /dev/null +++ b/Filtration/Services/SettingsService.cs @@ -0,0 +1,64 @@ +using System; +using System.Configuration; +using System.IO; +using System.Reflection; +using Filtration.Properties; +using NLog; + +namespace Filtration.Services +{ + internal interface ISettingsService + { + void BackupSettings(); + void RestoreSettings(); + } + + internal class SettingsService : ISettingsService + { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public void BackupSettings() + { + var currentUserSettingsFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath; + var backupFile = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\..\\last.config"; + + try + { + File.Copy(currentUserSettingsFile, backupFile, overwrite: true); + } + catch (Exception e) + { + Logger.Error(e); + } + } + + public void RestoreSettings() + { + Settings.Default.Save(); + string currentUserSettingsFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath; + string backupFile = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\..\\last.config"; + + // Check if we have settings that we need to restore + if (!File.Exists(backupFile)) + { + // Nothing we need to do + return; + } + + try + { + // Overwrite the current user settings file with the backed up user settings file + File.Copy(backupFile, currentUserSettingsFile, overwrite: true); + + // Delete backup file + File.Delete(backupFile); + + Settings.Default.Reload(); + } + catch (Exception e) + { + Logger.Error(e); + } + } + } +} diff --git a/Filtration/Services/UpdateCheckService.cs b/Filtration/Services/UpdateCheckService.cs deleted file mode 100644 index cd94bdc..0000000 --- a/Filtration/Services/UpdateCheckService.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Reflection; -using System.Windows; -using System.Xml.Serialization; -using Filtration.Models; -using Filtration.Properties; -using Filtration.ViewModels; -using Filtration.Views; -using NLog; - -namespace Filtration.Services -{ - internal interface IUpdateCheckService - { - void CheckForUpdates(); - } - - internal class UpdateCheckService : IUpdateCheckService - { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - private readonly IHTTPService _httpService; - private readonly IUpdateAvailableViewModel _updateAvailableViewModel; - - public UpdateCheckService(IHTTPService httpService, - IUpdateAvailableViewModel updateAvailableViewModel) - { - _httpService = httpService; - _updateAvailableViewModel = updateAvailableViewModel; - } - - public void CheckForUpdates() - { - var assemblyVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location); - - try - { - var updateData = GetUpdateData(); - updateData.CurrentVersionMajorPart = assemblyVersion.FileMajorPart; - updateData.CurrentVersionMinorPart = assemblyVersion.FileMinorPart; - - if (updateData.LatestVersionMajorPart >= updateData.CurrentVersionMajorPart && - updateData.LatestVersionMinorPart > updateData.CurrentVersionMinorPart) - { - if (Settings.Default.SuppressUpdates == false || LatestVersionIsNewerThanSuppressedVersion(updateData)) - { - Settings.Default.SuppressUpdates = false; - Settings.Default.Save(); - - updateData.UpdateAvailable = true; - } - } - - if (updateData.StaticDataUpdatedDate > Settings.Default.StaticDataLastUpdated) - { - var result = MessageBox.Show("New static data files are available (Item Base Types and Item Classes). Do you wish to download them?", - "Static Data Update Available", MessageBoxButton.YesNo, MessageBoxImage.Question); - - if (result == MessageBoxResult.Yes) - { - try - { - UpdateStaticDataFiles(); - Settings.Default.StaticDataLastUpdated = DateTime.Now; - Settings.Default.Save(); - - MessageBox.Show("Static Data successfully updated!", "Update Success", MessageBoxButton.OK, MessageBoxImage.Information); - } - catch (Exception e) - { - Logger.Error(e); - MessageBox.Show($"An error occurred while updating the static data files {Environment.NewLine}{e.Message}", "Update Error", MessageBoxButton.OK, - MessageBoxImage.Error); - } - } - } - - if (updateData.UpdateAvailable) - { - var updateAvailableView = new UpdateAvailableView { DataContext = _updateAvailableViewModel }; - _updateAvailableViewModel.Initialise(updateData); - _updateAvailableViewModel.OnRequestClose += (s, e) => updateAvailableView.Close(); - updateAvailableView.ShowDialog(); - } - } - catch (Exception e) - { - Logger.Debug(e); - // We don't care if the update check fails, because it could fail for multiple reasons - // including the user blocking Filtration in their firewall. - } - } - - private static bool LatestVersionIsNewerThanSuppressedVersion(UpdateData updateData) - { - return Settings.Default.SuppressUpdatesUpToVersionMajorPart < updateData.LatestVersionMajorPart || - (Settings.Default.SuppressUpdatesUpToVersionMajorPart <= updateData.LatestVersionMajorPart && - Settings.Default.SuppressUpdatesUpToVersionMinorPart < updateData.LatestVersionMinorPart); - } - - private UpdateData GetUpdateData() - { - var updateXml = _httpService.GetContent(Settings.Default.UpdateDataUrl); - return DeserializeUpdateData(updateXml); - } - - private void UpdateStaticDataFiles() - { - var itemClassesStaticData = _httpService.GetContent(Settings.Default.ItemClassesStaticDataUrl); - var itemBaseTypesStaticData = _httpService.GetContent(Settings.Default.ItemBaseTypesStaticDataUrl); - - var appdatapath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\Filtration\"; - Directory.CreateDirectory(appdatapath); - - var itemClassesPath = appdatapath + "ItemClasses.txt"; - var itemBaseTypesPath = appdatapath + "ItemBaseTypes.txt"; - - File.WriteAllText(itemClassesPath, itemClassesStaticData); - File.WriteAllText(itemBaseTypesPath, itemBaseTypesStaticData); - } - - private UpdateData DeserializeUpdateData(string updateDataString) - { - var serializer = new XmlSerializer(typeof(UpdateData)); - object result; - - using (TextReader reader = new StringReader(updateDataString)) - { - result = serializer.Deserialize(reader); - } - - return result as UpdateData; - } - } -} diff --git a/Filtration/Services/UpdateService.cs b/Filtration/Services/UpdateService.cs new file mode 100644 index 0000000..b41e092 --- /dev/null +++ b/Filtration/Services/UpdateService.cs @@ -0,0 +1,258 @@ +using System; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Filtration.Properties; +using NLog; +using Squirrel; + +namespace Filtration.Services +{ + public enum UpdateStatus + { + NoUpdateAvailable, + CheckingForUpdate, + UpdateAvailable, + Downloading, + ReadyToApplyUpdate, + Updating, + UpdateComplete, + Error + } + + internal class UpdateStatusChangedEventArgs : EventArgs + { + public UpdateStatusChangedEventArgs(UpdateStatus updateStatus) + { + UpdateStatus = updateStatus; + } + + public UpdateStatus UpdateStatus { get; } + } + + internal class UpdateProgressChangedEventArgs : EventArgs + { + public UpdateProgressChangedEventArgs(int progress) + { + Progress = progress; + } + + public int Progress { get; } + } + + internal interface IUpdateService + { + event EventHandler<UpdateStatusChangedEventArgs> UpdateStatusChanged; + + event EventHandler<UpdateProgressChangedEventArgs> UpdateProgressChanged; + + UpdateStatus UpdateStatus { get; } + + string LatestReleaseNotes { get; } + + string LatestReleaseVersion { get; } + + Task CheckForUpdates(); + + Task DownloadUpdatesAsync(); + + Task ApplyUpdatesAsync(); + + void RestartAfterUpdate(); + } + + internal class UpdateService : IUpdateService + { + private readonly ISettingsService _settingsService; + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + private const string _localUpdatePath = @"C:\Repos\Filtration\Releases"; + private ReleaseEntry _latestRelease; + private UpdateInfo _updates; + + private UpdateStatus _updateStatus; + + public UpdateService(ISettingsService settingsService) + { + _settingsService = settingsService; + + UpdateStatus = UpdateStatus.NoUpdateAvailable; + } + + public event EventHandler<UpdateStatusChangedEventArgs> UpdateStatusChanged; + public event EventHandler<UpdateProgressChangedEventArgs> UpdateProgressChanged; + + public UpdateStatus UpdateStatus + { + get => _updateStatus; + private set + { + _updateStatus = value; + UpdateStatusChanged?.Invoke(this, new UpdateStatusChangedEventArgs(value)); + } + } + + public string LatestReleaseNotes { get; private set; } + + public string LatestReleaseVersion { get; private set; } + + public async Task CheckForUpdates() + { + if (UpdateStatus != UpdateStatus.NoUpdateAvailable) + { + throw new InvalidOperationException(); + } + + + Logger.Debug("Checking for update..."); + UpdateStatus = UpdateStatus.CheckingForUpdate; + + try + { + bool downloadPrereleaseUpdates; + downloadPrereleaseUpdates = Settings.Default.DownloadPrereleaseUpdates; +#if DEBUG + downloadPrereleaseUpdates = true; +#endif + using (var mgr = await UpdateManager.GitHubUpdateManager("https://github.com/ben-wallis/Filtration", prerelease: downloadPrereleaseUpdates)) + { + _updates = await mgr.CheckForUpdate(progress: progress => UpdateProgressChanged?.Invoke(this, new UpdateProgressChangedEventArgs(progress))); + } + + // Local file update source for testing + //using (var mgr = new UpdateManager(_localUpdatePath)) + //{ + + // _updates = await mgr.CheckForUpdate(progress: progress => UpdateProgressChanged?.Invoke(this, new UpdateProgressChangedEventArgs(progress))); + //} + } + catch (Exception e) + { + Logger.Error(e); + UpdateStatus = UpdateStatus.Error; + return; + } + + + if (_updates.ReleasesToApply.Any()) + { + _latestRelease = _updates.ReleasesToApply.OrderBy(x => x.Version).Last(); + LatestReleaseVersion = _latestRelease.Version.ToString(); + + Logger.Debug($"Update found ({LatestReleaseVersion}), fetching release notes..."); + + try + { + var releaseNotes = _latestRelease.GetReleaseNotes(_localUpdatePath); + LatestReleaseNotes = ProcessReleaseNotes(releaseNotes); + } + catch (Exception e) + { + Logger.Error(e); + UpdateStatus = UpdateStatus.Error; + return; + } + + UpdateStatus = UpdateStatus.UpdateAvailable; + } + else + { + UpdateStatus = UpdateStatus.NoUpdateAvailable; + Logger.Debug("No update available"); + } + } + + private string ProcessReleaseNotes(string rawReleaseNotes) + { + var regex = new Regex(@"<!\[CDATA\[(.*)]]>", RegexOptions.Singleline); + var matches = regex.Match(rawReleaseNotes); + if (matches.Success) + { + var releaseNotes = matches.Groups[1].Value; + return "<font face=\"Segoe UI\" size=\"2\">" + releaseNotes + "</font>"; + } + + return string.Empty; + } + + public async Task DownloadUpdatesAsync() + { + if (_updates == null || UpdateStatus != UpdateStatus.UpdateAvailable) + { + throw new InvalidOperationException(); + } + + UpdateStatus = UpdateStatus.Downloading; + + try + { + using (var updateManager = new UpdateManager(_localUpdatePath)) + { + await updateManager.DownloadReleases(_updates.ReleasesToApply, OnProgressChanged); + } + } + catch (Exception e) + { + Logger.Error(e); + UpdateStatus = UpdateStatus.Error; + return; + } + + UpdateStatus = UpdateStatus.ReadyToApplyUpdate; + } + + + public async Task ApplyUpdatesAsync() + { + if (UpdateStatus != UpdateStatus.ReadyToApplyUpdate) + { + throw new InvalidOperationException(); + } + + UpdateStatus = UpdateStatus.Updating; + + // Back up the current user settings before updating as updating using Squirrel + // wipes out user settings due to the application directory changing with each update + _settingsService.BackupSettings(); + + try + { + using (var updateManager = new UpdateManager(_localUpdatePath)) + { + await updateManager.ApplyReleases(_updates, OnProgressChanged); + } + } + catch (Exception e) + { + Logger.Error(e); + UpdateStatus = UpdateStatus.Error; + return; + } + + UpdateStatus = UpdateStatus.UpdateComplete; + } + + public void RestartAfterUpdate() + { + if (UpdateStatus != UpdateStatus.UpdateComplete) + { + throw new InvalidOperationException(); + } + + try + { + UpdateManager.RestartApp(); + } + catch (Exception e) + { + Logger.Error(e); + UpdateStatus = UpdateStatus.Error; + } + } + + private void OnProgressChanged(int progress) + { + UpdateProgressChanged?.Invoke(this, new UpdateProgressChangedEventArgs(progress)); + } + } +} diff --git a/Filtration/ViewModels/DesignTime/DesignTimeMainWindowViewModel.cs b/Filtration/ViewModels/DesignTime/DesignTimeMainWindowViewModel.cs new file mode 100644 index 0000000..a8cbfef --- /dev/null +++ b/Filtration/ViewModels/DesignTime/DesignTimeMainWindowViewModel.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using GalaSoft.MvvmLight.CommandWpf; + +namespace Filtration.ViewModels.DesignTime +{ + public class DesignTimeMainWindowViewModel : IMainWindowViewModel + { + public RelayCommand OpenScriptCommand { get; } + public RelayCommand NewScriptCommand { get; } + + public int WindowWidth + { + get => 1200; set {} } + + public int WindowHeight + { + get => 800; set { } + } + + public IUpdateViewModel UpdateViewModel => new DesignTimeUpdateViewModel(); + + public Task<bool> CloseAllDocumentsAsync() + { + throw new NotImplementedException(); + } + + public Task OpenDroppedFilesAsync(List<string> filenames) + { + throw new NotImplementedException(); + } + } +} diff --git a/Filtration/ViewModels/DesignTime/DesignTimeSettingsPageViewModel.cs b/Filtration/ViewModels/DesignTime/DesignTimeSettingsPageViewModel.cs new file mode 100644 index 0000000..a4ffea7 --- /dev/null +++ b/Filtration/ViewModels/DesignTime/DesignTimeSettingsPageViewModel.cs @@ -0,0 +1,23 @@ +using GalaSoft.MvvmLight.CommandWpf; + +namespace Filtration.ViewModels.DesignTime +{ + public class DesignTimeSettingsPageViewModel : ISettingsPageViewModel + { + public RelayCommand SetItemFilterScriptDirectoryCommand { get; } + + public string DefaultFilterDirectory + { + get => @"c:\users\longusernamehere\Documents\My Games\Path of Exile"; + set { } + } + + public bool ExtraLineBetweenBlocks + { + get => true; + set { } + } + + public bool DownloadPrereleaseUpdates { get; set; } + } +} diff --git a/Filtration/ViewModels/DesignTime/DesignTimeUpdateViewModel.cs b/Filtration/ViewModels/DesignTime/DesignTimeUpdateViewModel.cs new file mode 100644 index 0000000..fff23b1 --- /dev/null +++ b/Filtration/ViewModels/DesignTime/DesignTimeUpdateViewModel.cs @@ -0,0 +1,49 @@ +using System.Threading.Tasks; +using Filtration.Services; +using GalaSoft.MvvmLight.CommandWpf; + +namespace Filtration.ViewModels.DesignTime +{ + public class DesignTimeUpdateViewModel : IUpdateViewModel + { + public RelayCommand HideUpdateWindowCommand { get; } + + public RelayCommand NextStepCommand { get; } + + public UpdateStatus UpdateStatus => UpdateStatus.Updating; + + public string NextStepButtonText + { + get => "Downloading... (100%)"; set {} } + + public bool Visible => true; + + public bool IsInErrorState { get; } + + public string Version => "1.2.3"; + + public string ReleaseNotes => @"Added support for DisableDropSound filter block items + Added support for GemLevel filter block items + Added support for HasExplicitMod filter block items + Added support for StackSize filter block items + Added support for CustomAlertSound filter block items + Added support for MinimapIcon filter block items + Added support for MapTier filter block items + Added support for PlayEffect filter block items + Added theme support for several filter blocks + Added collapse/expand support for sections + Added support for performing actions on whole sections(copy/move/delete etc) + Added search box to Section Browser + Improved parsing to support different syntaxes + Small bugfixes"; + + public bool IsScript { get; } + public bool IsTheme { get; } + public Task Close() + { + throw new System.NotImplementedException(); + } + + public RelayCommand CloseCommand { get; } + } +} diff --git a/Filtration/ViewModels/MainWindowViewModel.cs b/Filtration/ViewModels/MainWindowViewModel.cs index be5f314..0fd0c99 100644 --- a/Filtration/ViewModels/MainWindowViewModel.cs +++ b/Filtration/ViewModels/MainWindowViewModel.cs @@ -34,6 +34,9 @@ namespace Filtration.ViewModels { RelayCommand OpenScriptCommand { get; } RelayCommand NewScriptCommand { get; } + int WindowWidth { get; set; } + int WindowHeight { get; set; } + IUpdateViewModel UpdateViewModel { get; } Task<bool> CloseAllDocumentsAsync(); Task OpenDroppedFilesAsync(List<string> filenames); } @@ -63,7 +66,8 @@ namespace Filtration.ViewModels IThemeProvider themeProvider, IThemeService themeService, IMessageBoxService messageBoxService, - IClipboardService clipboardService) + IClipboardService clipboardService, + IUpdateViewModel updateViewModel) { _itemFilterScriptRepository = itemFilterScriptRepository; _itemFilterScriptTranslator = itemFilterScriptTranslator; @@ -74,6 +78,8 @@ namespace Filtration.ViewModels _themeService = themeService; _messageBoxService = messageBoxService; _clipboardService = clipboardService; + UpdateViewModel = updateViewModel; + _windowState = Settings.Default.WindowState; _windowWidth = Settings.Default.WindowWidth; _windowHeight = Settings.Default.WindowHeight; @@ -266,13 +272,15 @@ namespace Filtration.ViewModels public IAvalonDockWorkspaceViewModel AvalonDockWorkspaceViewModel => _avalonDockWorkspaceViewModel; public ISettingsPageViewModel SettingsPageViewModel { get; } + public IUpdateViewModel UpdateViewModel { get; } + public string WindowTitle { get { var assembly = Assembly.GetExecutingAssembly(); var fvi = FileVersionInfo.GetVersionInfo(assembly.Location); - return "Filtration v" + fvi.FileMajorPart + "." + fvi.FileMinorPart; + return "Filtration v" + fvi.ProductVersion; } } diff --git a/Filtration/ViewModels/SettingsPageViewModel.cs b/Filtration/ViewModels/SettingsPageViewModel.cs index d30d731..53102b5 100644 --- a/Filtration/ViewModels/SettingsPageViewModel.cs +++ b/Filtration/ViewModels/SettingsPageViewModel.cs @@ -1,16 +1,21 @@ using System.IO; using System.Windows; using Filtration.Common.Services; -using Filtration.Common.ViewModels; using Filtration.Properties; using Filtration.Services; using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.CommandWpf; +using Microsoft.WindowsAPICodePack.Dialogs; namespace Filtration.ViewModels { internal interface ISettingsPageViewModel { + RelayCommand SetItemFilterScriptDirectoryCommand { get; } + + string DefaultFilterDirectory { get; } + bool ExtraLineBetweenBlocks { get; set; } + bool DownloadPrereleaseUpdates { get; set; } } internal class SettingsPageViewModel : ViewModelBase, ISettingsPageViewModel @@ -22,31 +27,44 @@ namespace Filtration.ViewModels { _itemFilterPersistenceService = itemFilterPersistenceService; _messageBoxService = messageBoxService; - SaveCommand = new RelayCommand(OnSaveCommand); - - DefaultFilterDirectory = Settings.Default.DefaultFilterDirectory; - ExtraLineBetweenBlocks = Settings.Default.ExtraLineBetweenBlocks; - SuppressUpdateNotifications = Settings.Default.SuppressUpdates; + SetItemFilterScriptDirectoryCommand = new RelayCommand(OnSetItemFilterScriptDirectoryCommand); } - public RelayCommand SaveCommand { get; private set; } - public string DefaultFilterDirectory { get; set; } - public bool ExtraLineBetweenBlocks { get; set; } - public bool SuppressUpdateNotifications { get; set; } + public RelayCommand SetItemFilterScriptDirectoryCommand { get; } - private void OnSaveCommand() + public string DefaultFilterDirectory => Settings.Default.DefaultFilterDirectory; + + public bool ExtraLineBetweenBlocks { - try - { - _itemFilterPersistenceService.SetItemFilterScriptDirectory(DefaultFilterDirectory); + get => Settings.Default.ExtraLineBetweenBlocks; + set => Settings.Default.ExtraLineBetweenBlocks = value; + } - Settings.Default.ExtraLineBetweenBlocks = ExtraLineBetweenBlocks; - Settings.Default.SuppressUpdates = SuppressUpdateNotifications; - } - catch (DirectoryNotFoundException) + public bool DownloadPrereleaseUpdates + { + get => Settings.Default.DownloadPrereleaseUpdates; + set => Settings.Default.DownloadPrereleaseUpdates = value; + } + + private void OnSetItemFilterScriptDirectoryCommand() + { + using (var dialog = new CommonOpenFileDialog()) { - _messageBoxService.Show("Error", "The entered Default Filter Directory is invalid or does not exist.", - MessageBoxButton.OK, MessageBoxImage.Exclamation); + dialog.IsFolderPicker = true; + var result = dialog.ShowDialog(); + if (result == CommonFileDialogResult.Ok) + { + try + { + _itemFilterPersistenceService.SetItemFilterScriptDirectory(dialog.FileName); + RaisePropertyChanged(nameof(DefaultFilterDirectory)); + } + catch (DirectoryNotFoundException) + { + _messageBoxService.Show("Error", "The entered Default Filter Directory is invalid or does not exist.", + MessageBoxButton.OK, MessageBoxImage.Exclamation); + } + } } } } diff --git a/Filtration/ViewModels/StartPageViewModel.cs b/Filtration/ViewModels/StartPageViewModel.cs index aab59e4..6a896a3 100644 --- a/Filtration/ViewModels/StartPageViewModel.cs +++ b/Filtration/ViewModels/StartPageViewModel.cs @@ -12,7 +12,6 @@ namespace Filtration.ViewModels internal class StartPageViewModel : PaneViewModel, IStartPageViewModel { - public StartPageViewModel() { Title = "Start Page"; @@ -20,8 +19,8 @@ namespace Filtration.ViewModels NewScriptCommand = new RelayCommand(OnNewScriptCommand); } - public RelayCommand OpenScriptCommand { get; private set; } - public RelayCommand NewScriptCommand { get; private set; } + public RelayCommand OpenScriptCommand { get; } + public RelayCommand NewScriptCommand { get; } public bool IsScript => false; public bool IsTheme => false; @@ -31,6 +30,8 @@ namespace Filtration.ViewModels throw new System.NotImplementedException(); } + public RelayCommand CloseCommand { get; } + private static void OnOpenScriptCommand() { Messenger.Default.Send(new NotificationMessage("OpenScript")); diff --git a/Filtration/ViewModels/UpdateAvailableViewModel.cs b/Filtration/ViewModels/UpdateAvailableViewModel.cs deleted file mode 100644 index 90c0bf0..0000000 --- a/Filtration/ViewModels/UpdateAvailableViewModel.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Diagnostics; -using Filtration.Models; -using Filtration.Properties; -using GalaSoft.MvvmLight.CommandWpf; - -namespace Filtration.ViewModels -{ - internal interface IUpdateAvailableViewModel - { - event EventHandler OnRequestClose; - void Initialise(UpdateData updateData); - string CurrentVersion { get; } - string NewVersion { get; } - string ReleaseNotes { get; } - DateTime ReleaseDate { get; } - } - - internal class UpdateAvailableViewModel : IUpdateAvailableViewModel - { - private UpdateData _updateData; - private int _currentVersionMajorPart; - private int _currentVersionMinorPart; - - public UpdateAvailableViewModel() - { - DownloadCommand = new RelayCommand(OnDownloadCommand); - AskLaterCommand = new RelayCommand(OnAskLaterCommand); - NeverAskAgainCommand = new RelayCommand(OnNeverAskAgainCommand); - } - - public event EventHandler OnRequestClose; - - public RelayCommand NeverAskAgainCommand { get; private set; } - public RelayCommand AskLaterCommand { get; private set; } - public RelayCommand DownloadCommand { get; private set; } - - public void Initialise(UpdateData updateData) - { - _currentVersionMajorPart = updateData.CurrentVersionMajorPart; - _currentVersionMinorPart = updateData.CurrentVersionMinorPart; - _updateData = updateData; - } - - public string CurrentVersion => _currentVersionMajorPart + "." + _currentVersionMinorPart; - - public string NewVersion => _updateData.LatestVersionMajorPart + "." + _updateData.LatestVersionMinorPart; - - public string ReleaseNotes => _updateData.ReleaseNotes; - - public DateTime ReleaseDate => _updateData.ReleaseDate; - - private void OnDownloadCommand() - { - Process.Start(_updateData.DownloadUrl); - } - - private void OnNeverAskAgainCommand() - { - Settings.Default.SuppressUpdates = true; - Settings.Default.SuppressUpdatesUpToVersionMajorPart = _updateData.LatestVersionMajorPart; - Settings.Default.SuppressUpdatesUpToVersionMinorPart = _updateData.LatestVersionMinorPart; - Settings.Default.Save(); - CloseWindow(); - } - - private void OnAskLaterCommand() - { - CloseWindow(); - } - - private void CloseWindow() - { - OnRequestClose?.Invoke(this, new EventArgs()); - } - } - -} - diff --git a/Filtration/ViewModels/UpdateViewModel.cs b/Filtration/ViewModels/UpdateViewModel.cs new file mode 100644 index 0000000..6ae0edf --- /dev/null +++ b/Filtration/ViewModels/UpdateViewModel.cs @@ -0,0 +1,203 @@ +using System; +using System.Threading.Tasks; +using Filtration.Common.ViewModels; +using Filtration.Interface; +using Filtration.Services; +using GalaSoft.MvvmLight.CommandWpf; + +namespace Filtration.ViewModels +{ + public interface IUpdateViewModel : IDocument + { + RelayCommand HideUpdateWindowCommand { get; } + + RelayCommand NextStepCommand { get; } + + UpdateStatus UpdateStatus { get; } + + string ReleaseNotes { get; } + + string Version { get; } + + string NextStepButtonText { get; } + + bool Visible { get; } + bool IsInErrorState { get; } + } + + /// <summary> + /// This ViewModel is shared between UpdateView.xaml and UpdateTabView.xaml since they are both + /// parts of the same update process, first the user gets given the opportunity to download the + /// update from the UpdateView box and then once it is ready to install they click Update + /// and are taken to the UpdateTabView tab where they can see the changes and begin the installation + /// of the update. + /// </summary> + internal class UpdateViewModel : PaneViewModel, IUpdateViewModel + { + private readonly IAvalonDockWorkspaceViewModel _avalonDockWorkspaceViewModel; + + private readonly IUpdateService _updateService; + private string _nextStepButtonText; + private bool _visible; + private bool _updateTabShown; + + public UpdateViewModel(IAvalonDockWorkspaceViewModel avalonDockWorkspaceViewModel, + IUpdateService updateService) + { + _avalonDockWorkspaceViewModel = avalonDockWorkspaceViewModel; + _updateService = updateService; + + updateService.UpdateProgressChanged += UpdateServiceOnUpdateProgressChanged; + updateService.UpdateStatusChanged += UpdateServiceOnUpdateStatusChanged; + + + HideUpdateWindowCommand = new RelayCommand(OnHideUpdateWindowCommand, () => UpdateStatus == UpdateStatus.UpdateAvailable || UpdateStatus == UpdateStatus.Error); + NextStepCommand = new RelayCommand(async () => await OnNextStepCommandAsync(), () => NextStepCommandEnabled); + + Title = "Update Available"; + } + + public RelayCommand NextStepCommand { get; } + + public RelayCommand HideUpdateWindowCommand { get; } + + public UpdateStatus UpdateStatus => _updateService.UpdateStatus; + + public bool IsInErrorState => UpdateStatus == UpdateStatus.Error; + + public async Task Close() + { + await Task.FromResult(true); + } + + public RelayCommand CloseCommand { get; } + + public bool IsScript => false; + public bool IsTheme => false; + + public bool Visible + { + get => _visible; + private set + { + _visible = value; + RaisePropertyChanged(); + } + } + + public string ReleaseNotes => _updateService.LatestReleaseNotes; + + public string Version => _updateService.LatestReleaseVersion; + + public string NextStepButtonText + { + get => _nextStepButtonText; + set + { + _nextStepButtonText = value; + RaisePropertyChanged(); + } + } + + private bool NextStepCommandEnabled => UpdateStatus == UpdateStatus.UpdateAvailable || UpdateStatus == UpdateStatus.ReadyToApplyUpdate || UpdateStatus == UpdateStatus.UpdateComplete; + + private async Task OnNextStepCommandAsync() + { + switch (UpdateStatus) + { + case UpdateStatus.UpdateAvailable: + { + await _updateService.DownloadUpdatesAsync(); + break; + } + case UpdateStatus.ReadyToApplyUpdate: + { + if (!_updateTabShown) + { + // When the update has downloaded and is ready to apply, clicking the button + // closes the update popup and shows the update tab. + _avalonDockWorkspaceViewModel.AddDocument(this); + Visible = false; + _updateTabShown = true; + NextStepButtonText = "Update"; + } + else + { + await _updateService.ApplyUpdatesAsync(); + } + + break; + } + case UpdateStatus.UpdateComplete: + { + _updateService.RestartAfterUpdate(); + break; + } + } + } + + private void UpdateServiceOnUpdateStatusChanged(object sender, UpdateStatusChangedEventArgs e) + { + switch (UpdateStatus) + { + case UpdateStatus.UpdateAvailable: + { + Visible = true; + NextStepButtonText = "Download"; + RaisePropertyChanged(nameof(ReleaseNotes)); + RaisePropertyChanged(nameof(Version)); + break; + } + case UpdateStatus.Downloading: + { + HideUpdateWindowCommand.RaiseCanExecuteChanged(); + NextStepButtonText = "Downloading (0%)"; + break; + } + case UpdateStatus.ReadyToApplyUpdate: + { + NextStepButtonText = "Update Ready"; + break; + } + case UpdateStatus.Updating: + { + NextStepButtonText = "Updating (0%)"; + break; + } + case UpdateStatus.UpdateComplete: + { + NextStepButtonText = "Restart"; + break; + } + case UpdateStatus.Error: + { + NextStepButtonText = "Update Error - Check Logs"; + Visible = true; + break; + } + } + + NextStepCommand.RaiseCanExecuteChanged(); + RaisePropertyChanged(nameof(UpdateStatus)); + RaisePropertyChanged(nameof(IsInErrorState)); + + } + + private void UpdateServiceOnUpdateProgressChanged(object sender, UpdateProgressChangedEventArgs e) + { + if (UpdateStatus == UpdateStatus.Downloading) + { + NextStepButtonText = $"Downloading ({e.Progress}%)"; + } + else if (UpdateStatus == UpdateStatus.Updating) + { + NextStepButtonText = $"Updating ({e.Progress}%)"; + } + } + + private void OnHideUpdateWindowCommand() + { + Visible = false; + } + } +} diff --git a/Filtration/Views/AboutWindow.xaml.cs b/Filtration/Views/AboutWindow.xaml.cs index 0facfaa..0a1b2d1 100644 --- a/Filtration/Views/AboutWindow.xaml.cs +++ b/Filtration/Views/AboutWindow.xaml.cs @@ -26,7 +26,7 @@ namespace Filtration.Views { var assembly = Assembly.GetExecutingAssembly(); var fvi = FileVersionInfo.GetVersionInfo(assembly.Location); - return "Version " + fvi.FileMajorPart + "." + fvi.FileMinorPart; + return "Version " + fvi.ProductVersion; } } } diff --git a/Filtration/Views/AvalonDock/AvalonDockWorkspaceView.xaml b/Filtration/Views/AvalonDock/AvalonDockWorkspaceView.xaml index fdd92e3..4cb5f4a 100644 --- a/Filtration/Views/AvalonDock/AvalonDockWorkspaceView.xaml +++ b/Filtration/Views/AvalonDock/AvalonDockWorkspaceView.xaml @@ -61,6 +61,11 @@ <themeEditorViews:ThemeEditorView DataContext="{Binding}" /> </DataTemplate> </viewsAvalonDock:PanesTemplateSelector.ThemeTemplate> + <viewsAvalonDock:PanesTemplateSelector.UpdateTemplate> + <DataTemplate> + <views:UpdateTabView DataContext="{Binding}" /> + </DataTemplate> + </viewsAvalonDock:PanesTemplateSelector.UpdateTemplate> </viewsAvalonDock:PanesTemplateSelector> </xcad:DockingManager.LayoutItemTemplateSelector> diff --git a/Filtration/Views/AvalonDock/PanesTemplateSelector.cs b/Filtration/Views/AvalonDock/PanesTemplateSelector.cs index a256dda..d9f1d09 100644 --- a/Filtration/Views/AvalonDock/PanesTemplateSelector.cs +++ b/Filtration/Views/AvalonDock/PanesTemplateSelector.cs @@ -15,11 +15,10 @@ namespace Filtration.Views.AvalonDock public DataTemplate BlockOutputPreviewTemplate { get; set; } public DataTemplate StartPageTemplate { get; set; } public DataTemplate ThemeTemplate { get; set; } + public DataTemplate UpdateTemplate { get; set; } public override DataTemplate SelectTemplate(object item, DependencyObject container) { - var itemAsLayoutContent = item as LayoutContent; - if (item is ItemFilterScriptViewModel) { return ItemFilterScriptTemplate; @@ -50,6 +49,11 @@ namespace Filtration.Views.AvalonDock return StartPageTemplate; } + if (item is IUpdateViewModel) + { + return UpdateTemplate; + } + return base.SelectTemplate(item, container); } } diff --git a/Filtration/Views/MainWindow.xaml b/Filtration/Views/MainWindow.xaml index 928e347..6da3899 100644 --- a/Filtration/Views/MainWindow.xaml +++ b/Filtration/Views/MainWindow.xaml @@ -10,8 +10,9 @@ xmlns:views="clr-namespace:Filtration.Views" xmlns:gif="http://wpfanimatedgif.codeplex.com" xmlns:utility="clr-namespace:Filtration.Utility" - mc:Ignorable="d" - d:DataContext="{d:DesignInstance Type=viewModels:MainWindowViewModel}" + xmlns:designTime="clr-namespace:Filtration.ViewModels.DesignTime" + mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="800" + d:DataContext="{d:DesignInstance Type=designTime:DesignTimeMainWindowViewModel, IsDesignTimeCreatable=True}" Title="{Binding WindowTitle}" Height="{Binding WindowHeight, Mode=TwoWay}" Width="{Binding WindowWidth, Mode=TwoWay}" IsIconVisible="True" WindowState="{Binding WindowState}" Closing="MainWindow_OnClosing" Drop="MainWindow_OnDrop" AllowDrop="True"> @@ -166,6 +167,7 @@ </Border> </Grid> </Grid> + <views:UpdateView DataContext="{Binding UpdateViewModel}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="4" Height="90" /> </Grid> </DockPanel> </fluent:RibbonWindow> diff --git a/Filtration/Views/SettingsPageView.xaml b/Filtration/Views/SettingsPageView.xaml index a462640..23f8832 100644 --- a/Filtration/Views/SettingsPageView.xaml +++ b/Filtration/Views/SettingsPageView.xaml @@ -3,12 +3,11 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:viewModels="clr-namespace:Filtration.ViewModels" - mc:Ignorable="d" - d:DataContext="{d:DesignInstance Type=viewModels:SettingsPageViewModel}"> - <!--IsMaxRestoreButtonEnabled="False"--> + xmlns:designTime="clr-namespace:Filtration.ViewModels.DesignTime" + mc:Ignorable="d" d:DesignWidth="1200" + d:DataContext="{d:DesignInstance Type=designTime:DesignTimeSettingsPageViewModel, IsDesignTimeCreatable=True}"> <Border BorderBrush="Black" BorderThickness="1"> - <DockPanel Margin="10"> + <DockPanel Margin="10" MaxWidth="600" HorizontalAlignment="Left"> <Grid DockPanel.Dock="Bottom"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> @@ -18,7 +17,7 @@ <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="5" /> - <ColumnDefinition></ColumnDefinition> + <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> @@ -28,22 +27,22 @@ <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> - <TextBlock Grid.Row="0" Grid.Column="0">Default Filter Directory:</TextBlock> - <TextBox Grid.Row="0" Grid.Column="2" Text="{Binding DefaultFilterDirectory}" Width="250" /> + <TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center">Default Filter Directory:</TextBlock> + <Grid Grid.Row="0" Grid.Column="2" Height="40" Width="300"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="40" /> + </Grid.ColumnDefinitions> + <TextBlock Grid.Column="0" Text="{Binding DefaultFilterDirectory}" TextWrapping="Wrap" VerticalAlignment="Center" /> + <Button Grid.Column="1" Margin="5,0,0,0" Width="30" Height="30" Command="{Binding SetItemFilterScriptDirectoryCommand}"> + <ContentControl Content="{StaticResource OpenIcon}" Width="16" Height="16"></ContentControl> + </Button> + </Grid> <TextBlock Grid.Row="2" Grid.Column="0" VerticalAlignment="Center">Add blank line between blocks when saving</TextBlock> <CheckBox Grid.Row="2" Grid.Column="2" IsChecked="{Binding ExtraLineBetweenBlocks}" /> - <TextBlock Grid.Row="4" Grid.Column="0" VerticalAlignment="Center">Suppress update notifications for current version</TextBlock> - <CheckBox Grid.Row="4" Grid.Column="2" IsChecked="{Binding SuppressUpdateNotifications}" /> + <TextBlock Grid.Row="4" Grid.Column="0" VerticalAlignment="Center">Download pre-release updates (use with caution)</TextBlock> + <CheckBox Grid.Row="4" Grid.Column="2" IsChecked="{Binding DownloadPrereleaseUpdates}" /> </Grid> - <StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Right"> - <StackPanel.Resources> - <Style TargetType="{x:Type Button}"> - <Setter Property="Width" Value="80" /> - <Setter Property="Margin" Value="3" /> - </Style> - </StackPanel.Resources> - <Button Command="{Binding SaveCommand}">Save</Button> - </StackPanel> </Grid> </DockPanel> </Border> diff --git a/Filtration/Views/UpdateAvailableView.xaml b/Filtration/Views/UpdateAvailableView.xaml deleted file mode 100644 index 76f58a5..0000000 --- a/Filtration/Views/UpdateAvailableView.xaml +++ /dev/null @@ -1,38 +0,0 @@ -<Window x:Class="Filtration.Views.UpdateAvailableView" - xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:viewModels="clr-namespace:Filtration.ViewModels" - Title="Filtration - New Version Available!" Height="300" Width="500" Icon="../Resources/filtration.ico" - mc:Ignorable="d" - d:DataContext="{d:DesignInstance Type=viewModels:UpdateAvailableViewModel}"> - <Grid Margin="10"> - <Grid.RowDefinitions> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - <RowDefinition Height="*" /> - </Grid.RowDefinitions> - <Grid.ColumnDefinitions> - <ColumnDefinition Width="Auto" /> - <ColumnDefinition Width="5" /> - <ColumnDefinition Width="*"/> - </Grid.ColumnDefinitions> - <TextBlock Grid.Row="0" Text="Current Version:" /> - <TextBlock Grid.Row="0" Grid.Column="2" Text="{Binding CurrentVersion}" /> - <TextBlock Grid.Row="1" Grid.Column="0" Text="New Version:" /> - <TextBlock Grid.Row="1" Grid.Column="2" Text="{Binding NewVersion}" /> - <TextBlock Grid.Row="2" Grid.Column="0" Text="Release Date:" /> - <TextBlock Grid.Row="2" Grid.Column="2" Text="{Binding ReleaseDate, StringFormat={}{0:yyyy-MM-dd}}" /> - <TextBlock Grid.Row="3" Grid.Column="0" Text="Release Notes:" /> - <TextBox MaxHeight="150" IsReadOnly="True" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden" Grid.Row="3" Grid.Column="2" Text="{Binding ReleaseNotes, Mode=OneWay}" TextWrapping="Wrap" /> - - <StackPanel Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="3" Orientation="Horizontal" Height="30" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,5"> - <Button Padding="2" Margin="0,0,5,0" Command="{Binding DownloadCommand}">Download from Filtration homepage</Button> - <Button Padding="2" Margin="0,0,5,0" Command="{Binding AskLaterCommand}">Ask me later</Button> - <Button Padding="2" Margin="0,0,5,0" Command="{Binding NeverAskAgainCommand}">Never ask again for this version</Button> - </StackPanel> - </Grid> -</Window> diff --git a/Filtration/Views/UpdateTabView.xaml b/Filtration/Views/UpdateTabView.xaml new file mode 100644 index 0000000..eb0fea3 --- /dev/null +++ b/Filtration/Views/UpdateTabView.xaml @@ -0,0 +1,39 @@ +<UserControl x:Class="Filtration.Views.UpdateTabView" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:designTime="clr-namespace:Filtration.ViewModels.DesignTime" + mc:Ignorable="d" + d:DesignHeight="650" d:DesignWidth="1024" d:DataContext="{d:DesignInstance designTime:DesignTimeUpdateViewModel, IsDesignTimeCreatable=True}"> + <Grid Margin="16"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="*" /> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="Auto" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Grid Grid.Row="0" Grid.Column="0"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="5" /> + <RowDefinition Height="350" /> + <RowDefinition Height="5" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="*" /> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="Auto" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontSize="18" FontWeight="SemiBold"><Run>Version </Run> <Run Text="{Binding Version, Mode=OneWay}" /></TextBlock> + + <WebBrowser x:Name="ReleaseNotesWebBrowser" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Width="600" /> + <Button Grid.Row="4" Grid.Column="0" Height="40" Width="150" Command="{Binding NextStepCommand}" Content="{Binding NextStepButtonText}" /> + </Grid> + </Grid> + </Grid> +</UserControl> diff --git a/Filtration/Views/UpdateTabView.xaml.cs b/Filtration/Views/UpdateTabView.xaml.cs new file mode 100644 index 0000000..3b3104f --- /dev/null +++ b/Filtration/Views/UpdateTabView.xaml.cs @@ -0,0 +1,21 @@ +using System.Windows; +using Filtration.ViewModels; + +namespace Filtration.Views +{ + public partial class UpdateTabView + { + public UpdateTabView() + { + InitializeComponent(); + + DataContextChanged += OnDataContextChanged; + } + + private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e) + { + var updateViewModel = (UpdateViewModel)DataContext; + ReleaseNotesWebBrowser.NavigateToString(updateViewModel.ReleaseNotes); + } + } +} diff --git a/Filtration/Views/UpdateView.xaml b/Filtration/Views/UpdateView.xaml new file mode 100644 index 0000000..ba21128 --- /dev/null +++ b/Filtration/Views/UpdateView.xaml @@ -0,0 +1,41 @@ +<UserControl x:Class="Filtration.Views.UpdateView" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:designTime="clr-namespace:Filtration.ViewModels.DesignTime" + mc:Ignorable="d" + Visibility="{Binding Visible, Converter={StaticResource BooleanToVisibilityConverter}}" + Height="90" Width="250" + d:DataContext="{d:DesignInstance designTime:DesignTimeUpdateViewModel, IsDesignTimeCreatable=True}" + Background="White"> + <UserControl.RenderTransform> + <TranslateTransform x:Name="UpdatePopupTransform" X="250" /> + </UserControl.RenderTransform> + <UserControl.Triggers> + <!-- This EventTrigger/Storyboard animates the UpdateView so it slides in from the right when it is shown --> + <EventTrigger RoutedEvent="FrameworkElement.Loaded"> + <BeginStoryboard> + <Storyboard> + <DoubleAnimation Storyboard.TargetName="UpdatePopupTransform" Storyboard.TargetProperty="(X)" To="0" Duration="0:0:1.25" /> + </Storyboard> + </BeginStoryboard> + </EventTrigger> + </UserControl.Triggers> + <Border BorderBrush="Black" BorderThickness="1"> + <Grid Margin="4"> + <Grid.RowDefinitions> + <RowDefinition /> + <RowDefinition /> + </Grid.RowDefinitions> + <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Visibility="{Binding IsInErrorState, Converter={StaticResource InverseBooleanVisibilityConverter}}">A new version of Filtration is available!</TextBlock> + <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Red" Visibility="{Binding IsInErrorState, Converter={StaticResource BooleanToVisibilityConverter}}" TextWrapping="Wrap">An error occured while checking for updates</TextBlock> + <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center"> + <Button Command="{Binding NextStepCommand}" Width="160" Height="30"> + <TextBlock Text="{Binding NextStepButtonText}" /> + </Button> + <Button Height="30" Width="50" Margin="10,0,0,0" Command="{Binding HideUpdateWindowCommand}">Cancel</Button> + </StackPanel> + </Grid> + </Border> +</UserControl> diff --git a/Filtration/Views/UpdateAvailableView.xaml.cs b/Filtration/Views/UpdateView.xaml.cs similarity index 55% rename from Filtration/Views/UpdateAvailableView.xaml.cs rename to Filtration/Views/UpdateView.xaml.cs index 4274251..ac56223 100644 --- a/Filtration/Views/UpdateAvailableView.xaml.cs +++ b/Filtration/Views/UpdateView.xaml.cs @@ -1,8 +1,8 @@ namespace Filtration.Views { - public partial class UpdateAvailableView + public partial class UpdateView { - public UpdateAvailableView() + public UpdateView() { InitializeComponent(); } diff --git a/Filtration/WindsorInstallers/ServicesInstaller.cs b/Filtration/WindsorInstallers/ServicesInstaller.cs index d96e5a1..f736c1e 100644 --- a/Filtration/WindsorInstallers/ServicesInstaller.cs +++ b/Filtration/WindsorInstallers/ServicesInstaller.cs @@ -25,14 +25,24 @@ namespace Filtration.WindsorInstallers .LifeStyle.Singleton); container.Register( - Component.For<IUpdateCheckService>() - .ImplementedBy<UpdateCheckService>() + Component.For<IUpdateService>() + .ImplementedBy<UpdateService>() .LifeStyle.Singleton); container.Register( Component.For<IClipboardService>() .ImplementedBy<ClipboardService>() .LifeStyle.Singleton); + + container.Register( + Component.For<IBootstrapper>() + .ImplementedBy<Bootstrapper>() + .LifeStyle.Singleton); + + container.Register( + Component.For<ISettingsService>() + .ImplementedBy<SettingsService>() + .LifeStyle.Singleton); } } } diff --git a/Filtration/WindsorInstallers/ViewModelsInstaller.cs b/Filtration/WindsorInstallers/ViewModelsInstaller.cs index 30afd6e..e4924af 100644 --- a/Filtration/WindsorInstallers/ViewModelsInstaller.cs +++ b/Filtration/WindsorInstallers/ViewModelsInstaller.cs @@ -68,9 +68,9 @@ namespace Filtration.WindsorInstallers .LifeStyle.Transient); container.Register( - Component.For<IUpdateAvailableViewModel>() - .ImplementedBy<UpdateAvailableViewModel>() - .LifeStyle.Transient); + Component.For<IUpdateViewModel>() + .ImplementedBy<UpdateViewModel>() + .LifeStyle.Singleton); container.Register( Component.For<IItemFilterBlockViewModelFactory>().AsFactory()); diff --git a/Filtration/packages.config b/Filtration/packages.config index d24e04a..0b98c5b 100644 --- a/Filtration/packages.config +++ b/Filtration/packages.config @@ -5,13 +5,21 @@ <package id="Castle.Windsor" version="3.4.0" targetFramework="net461" /> <package id="CommonServiceLocator" version="1.3" targetFramework="net451" /> <package id="ControlzEx" version="2.2.0.4" targetFramework="net461" /> + <package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net461" /> <package id="Extended.Wpf.Toolkit" version="2.9" targetFramework="net461" /> <package id="Fluent.Ribbon" version="4.0.3.394" targetFramework="net461" /> <package id="MahApps.Metro" version="1.2.4.0" targetFramework="net461" /> + <package id="Mono.Cecil" version="0.9.6.1" targetFramework="net461" /> <package id="MvvmLightLibs" version="5.3.0.0" targetFramework="net461" /> <package id="NLog" version="4.4.9" targetFramework="net461" /> <package id="NLog.Config" version="4.3.7" targetFramework="net461" /> <package id="NLog.Schema" version="4.4.9" targetFramework="net461" /> + <package id="NuGet.CommandLine" version="4.7.1" targetFramework="net461" developmentDependency="true" /> + <package id="SharpCompress" version="0.17.1" targetFramework="net461" /> + <package id="Splat" version="1.6.2" targetFramework="net461" /> + <package id="squirrel.windows" version="1.8.0" targetFramework="net461" /> + <package id="WindowsAPICodePack-Core" version="1.1.2" targetFramework="net461" /> + <package id="WindowsAPICodePack-Shell" version="1.1.1" targetFramework="net461" /> <package id="WpfAnimatedGif" version="1.4.14" targetFramework="net461" /> <package id="WPFToolkit" version="3.5.50211.1" targetFramework="net451" /> </packages> \ No newline at end of file