mirror of
https://github.com/WinDurango/WinDurango.UI.git
synced 2026-01-31 00:55:24 +01:00
Jank incoming!!! (First UI commit)
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -396,3 +396,6 @@ FodyWeavers.xsd
|
||||
|
||||
# JetBrains Rider
|
||||
*.sln.iml
|
||||
.idea
|
||||
|
||||
# Other
|
||||
|
||||
15
App.xaml
Normal file
15
App.xaml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Application
|
||||
x:Class="WinDurango.UI.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:WinDurango.UI"
|
||||
xmlns:controls="using:Microsoft.UI.Xaml.Controls">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
40
App.xaml.cs
Normal file
40
App.xaml.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace WinDurango.UI
|
||||
{
|
||||
public partial class App : Application
|
||||
{
|
||||
private static readonly FileVersionInfo Fvi = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
|
||||
public static readonly string DataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "WinDurango");
|
||||
public static readonly MainWindow MainWindow = new();
|
||||
public static readonly uint Major = (uint)Fvi.ProductMajorPart;
|
||||
public static readonly uint Minor = (uint)Fvi.ProductMinorPart;
|
||||
public static readonly uint Patch = (uint)Fvi.ProductBuildPart;
|
||||
public static readonly string Hash = Fvi.ProductVersion.Split("+")[1].Substring(0, 7);
|
||||
public static readonly uint VerPacked = (Major << 22) | (Minor << 12) | Patch;
|
||||
public static readonly string Version = $"{Fvi.ProductMajorPart}.{Fvi.ProductMinorPart}.{Fvi.ProductBuildPart}_{Hash}"; // 1.0 will be when bugs are squashed and everything works correctly.
|
||||
|
||||
public static (uint major, uint minor, uint patch) UnpackVersion(uint verPacked)
|
||||
{
|
||||
uint major = (verPacked >> 22) & 0x3FF;
|
||||
uint minor = (verPacked >> 12) & 0x3FF;
|
||||
uint patch = verPacked & 0xFFF;
|
||||
|
||||
return (major, minor, patch);
|
||||
}
|
||||
|
||||
public App()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnLaunched(LaunchActivatedEventArgs args)
|
||||
{
|
||||
MainWindow.Activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Assets/icon.ico
Normal file
BIN
Assets/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 168 KiB |
205
Assets/icon.svg
Normal file
205
Assets/icon.svg
Normal file
@@ -0,0 +1,205 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="360mm"
|
||||
height="360mm"
|
||||
viewBox="0 0 360 360"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="WinDurango.svg"
|
||||
inkscape:export-filename="logo\16.png"
|
||||
inkscape:export-xdpi="1.128889"
|
||||
inkscape:export-ydpi="1.128889"
|
||||
inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#22b14c"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="true"
|
||||
inkscape:export-bgcolor="#00000000"
|
||||
inkscape:zoom="0.35355339"
|
||||
inkscape:cx="627.91082"
|
||||
inkscape:cy="640.63874"
|
||||
inkscape:window-width="1600"
|
||||
inkscape:window-height="829"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="163"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1"><inkscape:grid
|
||||
id="grid86"
|
||||
units="mm"
|
||||
originx="0"
|
||||
originy="0"
|
||||
spacingx="7.5000002"
|
||||
spacingy="7.5000002"
|
||||
empcolor="#0099e5"
|
||||
empopacity="0.79215686"
|
||||
color="#0099e5"
|
||||
opacity="0.14901961"
|
||||
empspacing="6"
|
||||
dotted="false"
|
||||
gridanglex="30"
|
||||
gridanglez="30"
|
||||
visible="true" /></sodipodi:namedview><defs
|
||||
id="defs1"><rect
|
||||
x="1339.3906"
|
||||
y="363.3844"
|
||||
width="2062.1841"
|
||||
height="316.93054"
|
||||
id="rect497" /><linearGradient
|
||||
id="swatch83"><stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop83" /></linearGradient><linearGradient
|
||||
id="swatch42"
|
||||
inkscape:swatch="solid"><stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop43" /></linearGradient><filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter481"
|
||||
x="-0.091402709"
|
||||
y="-0.093543364"
|
||||
width="1.1828054"
|
||||
height="1.1870867"><feFlood
|
||||
result="flood"
|
||||
in="SourceGraphic"
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(255,255,255)"
|
||||
id="feFlood480" /><feGaussianBlur
|
||||
result="blur"
|
||||
in="SourceGraphic"
|
||||
stdDeviation="2.000000"
|
||||
id="feGaussianBlur480" /><feOffset
|
||||
result="offset"
|
||||
in="blur"
|
||||
dx="0.000000"
|
||||
dy="0.000000"
|
||||
id="feOffset480" /><feComposite
|
||||
result="comp1"
|
||||
operator="in"
|
||||
in="flood"
|
||||
in2="offset"
|
||||
id="feComposite480" /><feComposite
|
||||
result="comp2"
|
||||
operator="over"
|
||||
in="SourceGraphic"
|
||||
in2="comp1"
|
||||
id="feComposite481" /></filter></defs><g
|
||||
id="layer1"
|
||||
transform="matrix(1.4374998,0,0,1.4374998,-143.03639,-167.25425)"><path
|
||||
id="path5"
|
||||
style="fill:#212121;fill-opacity:1;stroke-width:0.453453"
|
||||
d="m 334.64661,164.23247 -132.92989,-4.1e-4 c 0,0 -6.058,-0.89568 -11.44184,-5.38304 -5.38384,-4.48736 -36.34905,5.38307 -43.97747,11.219 -7.62888,5.83321 -2.31117,8.52565 -9.68202,13.23791 -7.37087,4.71228 -26.66654,69.77965 -26.66654,69.77965 0,0 -21.664127,63.58734 23.20994,72.33717 0,0 7.01674,-1.70344 16.43812,-12.9232 9.42454,-11.21977 27.82092,-27.14947 37.69482,-27.37436 9.65763,-0.21904 45.06787,-0.008 46.61098,0 h 100.7439 c 5.91388,0 10.07439,-4.16052 10.07439,-10.0744 V 174.30687 c 0,-5.91389 -4.16051,-10.07437 -10.07439,-10.0744 z"
|
||||
sodipodi:nodetypes="scscscccccssss" /><path
|
||||
id="rect4"
|
||||
style="fill:#1f2121;fill-opacity:1;stroke:none;stroke-width:1.68373;stroke-linecap:square;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke fill markers"
|
||||
d="m 203.6334,295.29303 v 10.02713 h -12.65245 a 7.4036329,7.40357 0 0 0 -7.40408,7.40403 v 2.62416 h 20.05653 20.05551 20.05549 20.05656 v -2.62416 a 7.4036329,7.40357 0 0 0 -7.4041,-7.40403 H 243.7444 v -10.02713 h -20.05549 z" /><g
|
||||
id="g5"
|
||||
transform="matrix(1.9183886,0,0,1.9633176,93.408043,-126.03525)"
|
||||
style="fill:#ffffff;fill-opacity:1;filter:url(#filter481)"><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="m 119.99665,155.91808 h -9.49801 c -0.27747,0 -0.50247,0.29366 -0.50247,0.65593 0,0.3622 0.225,0.6559 0.50247,0.6559 h 9.49801 c 0.27756,0 0.50249,-0.2937 0.50249,-0.6559 0,-0.36227 -0.22493,-0.65593 -0.50249,-0.65593 z"
|
||||
id="path4-7" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="M 88.487741,158.85938 H 75.990927 c -0.277481,0 -0.502481,0.2936 -0.502481,0.6559 0,0.36221 0.225,0.65591 0.502481,0.65591 h 12.496814 c 0.277481,0 0.502484,-0.2937 0.502484,-0.65591 0,-0.3623 -0.225003,-0.6559 -0.502484,-0.6559 z"
|
||||
id="path5-4" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="M 114.74517,158.85938 H 94.744193 c -0.277478,0 -0.502481,0.2936 -0.502481,0.6559 0,0.36221 0.225003,0.65591 0.502481,0.65591 h 20.000977 c 0.27749,0 0.50249,-0.2937 0.50249,-0.65591 0,-0.3623 -0.225,-0.6559 -0.50249,-0.6559 z"
|
||||
id="path6" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="M 93.359003,161.80055 H 73.738248 c -0.277482,0 -0.502483,0.2937 -0.502483,0.6559 0,0.36231 0.225001,0.65591 0.502483,0.65591 h 19.620755 c 0.277481,0 0.502484,-0.2936 0.502484,-0.65591 0,-0.3622 -0.225003,-0.6559 -0.502484,-0.6559 z"
|
||||
id="path7" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.0990624;stroke-dasharray:none"
|
||||
d="m 114.59617,161.80055 h -14.4515 c -0.359751,0 -0.651472,0.2937 -0.651472,0.6559 0,0.36231 0.291721,0.65591 0.651472,0.65591 h 14.4515 c 0.35976,0 0.65149,-0.2936 0.65149,-0.65591 0,-0.3622 -0.29173,-0.6559 -0.65149,-0.6559 z"
|
||||
id="path8" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="M 87.402862,170.62436 H 73.738248 c -0.277482,0 -0.502483,0.29371 -0.502483,0.6559 0,0.36221 0.225001,0.6559 0.502483,0.6559 h 13.664614 c 0.277482,0 0.502482,-0.29369 0.502482,-0.6559 0,-0.36219 -0.225,-0.6559 -0.502482,-0.6559 z"
|
||||
id="path484" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="M 94.16098,167.68309 H 73.738248 c -0.277482,0 -0.502483,0.2937 -0.502483,0.6559 0,0.36221 0.225001,0.65591 0.502483,0.65591 h 20.422656 c 0.277559,0 0.502483,-0.2937 0.502483,-0.65591 0,-0.3622 -0.224924,-0.6559 -0.502407,-0.6559 z"
|
||||
id="path483" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="M 89.655543,164.74182 H 75.990927 c -0.277481,0 -0.502481,0.2937 -0.502481,0.6559 0,0.36231 0.225,0.6559 0.502481,0.6559 h 13.664616 c 0.277481,0 0.502484,-0.29359 0.502484,-0.6559 0,-0.3622 -0.225003,-0.6559 -0.502484,-0.6559 z"
|
||||
id="path9" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.0822406;stroke-dasharray:none"
|
||||
d="M 100.44288,173.57203 H 79.269506 c -0.250465,0 -0.453432,0.29074 -0.453432,0.64951 0,0.35867 0.202967,0.6495 0.453432,0.6495 h 21.173374 c 0.25045,0 0.45343,-0.29083 0.45343,-0.6495 0,-0.35877 -0.20298,-0.64951 -0.45343,-0.64951 z"
|
||||
id="path10" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="m 89.473043,176.5069 h -8.976677 c -0.277558,0 -0.502481,0.2936 -0.502481,0.6559 0,0.36221 0.224923,0.65591 0.502481,0.65591 h 8.976677 c 0.277557,0 0.502483,-0.2937 0.502483,-0.65591 0,-0.3623 -0.224926,-0.6559 -0.502483,-0.6559 z"
|
||||
id="path486" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="m 123.44599,173.56563 h -6.9065 c -0.27748,0 -0.50248,0.2936 -0.50248,0.65591 0,0.3622 0.225,0.6559 0.50248,0.6559 h 6.9065 c 0.27756,0 0.50248,-0.2937 0.50248,-0.6559 0,-0.36231 -0.22492,-0.65591 -0.50248,-0.65591 z"
|
||||
id="path485" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="m 112.18251,173.56563 h -6.9065 c -0.27749,0 -0.50249,0.2936 -0.50249,0.65591 0,0.3622 0.225,0.6559 0.50249,0.6559 h 6.9065 c 0.27755,0 0.50248,-0.2937 0.50248,-0.6559 0,-0.36231 -0.22493,-0.65591 -0.50248,-0.65591 z"
|
||||
id="path11" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="M 92.807087,179.44807 H 80.496366 c -0.277558,0 -0.502481,0.29371 -0.502481,0.6559 0,0.36231 0.224923,0.6559 0.502481,0.6559 h 12.310721 c 0.277482,0 0.502484,-0.29359 0.502484,-0.6559 0,-0.36219 -0.225002,-0.6559 -0.502484,-0.6559 z"
|
||||
id="path12" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="M 112.18251,179.44807 H 98.517969 c -0.277559,0 -0.502481,0.29371 -0.502481,0.6559 0,0.36231 0.224922,0.6559 0.502481,0.6559 h 13.664541 c 0.27755,0 0.50248,-0.29359 0.50248,-0.6559 0,-0.36219 -0.22493,-0.6559 -0.50248,-0.6559 z"
|
||||
id="path13" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="m 121.64384,179.44807 h -5.10435 c -0.27748,0 -0.50248,0.29371 -0.50248,0.6559 0,0.36231 0.225,0.6559 0.50248,0.6559 h 5.10435 c 0.27749,0 0.50248,-0.29359 0.50248,-0.6559 0,-0.36219 -0.22499,-0.6559 -0.50248,-0.6559 z"
|
||||
id="path14" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.0884533;stroke-dasharray:none"
|
||||
d="M 107.2074,188.27188 H 80.740969 c -0.286909,0 -0.519409,0.29362 -0.519409,0.65591 0,0.3622 0.2325,0.6559 0.519409,0.6559 H 107.2074 c 0.28683,0 0.51941,-0.2937 0.51941,-0.6559 0,-0.36229 -0.23258,-0.65591 -0.51941,-0.65591 z"
|
||||
id="path488" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.0884533;stroke-dasharray:none"
|
||||
d="M 87.880138,185.33061 H 73.755176 c -0.28683,0 -0.519411,0.29371 -0.519411,0.6559 0,0.36221 0.232581,0.65591 0.519411,0.65591 h 14.124962 c 0.28683,0 0.51941,-0.2937 0.51941,-0.65591 0,-0.36219 -0.23258,-0.6559 -0.51941,-0.6559 z"
|
||||
id="path487" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.0884533;stroke-dasharray:none"
|
||||
d="m 82.030718,182.45289 h -8.275542 c -0.28683,0 -0.519411,0.2937 -0.519411,0.65591 0,0.3623 0.232581,0.6559 0.519411,0.6559 h 8.275542 c 0.28683,0 0.519413,-0.2936 0.519413,-0.6559 0,-0.36221 -0.232583,-0.65591 -0.519413,-0.65591 z"
|
||||
id="path15" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="m 125.24813,188.27188 h -15.46668 c -0.27757,0 -0.50249,0.29362 -0.50249,0.65591 0,0.3622 0.22492,0.6559 0.50249,0.6559 h 15.46668 c 0.27755,0 0.50249,-0.2937 0.50249,-0.6559 0,-0.36229 -0.22494,-0.65591 -0.50249,-0.65591 z"
|
||||
id="path16" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="m 88.529164,191.21315 h -8.032798 c -0.277558,0 -0.502481,0.2936 -0.502481,0.6559 0,0.36221 0.224923,0.65592 0.502481,0.65592 h 8.032798 c 0.277557,0 0.502484,-0.29371 0.502484,-0.65592 0,-0.3623 -0.224927,-0.6559 -0.502484,-0.6559 z"
|
||||
id="path17" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="M 87.402862,194.15434 H 73.738248 c -0.277482,0 -0.502483,0.2937 -0.502483,0.65588 0,0.36231 0.225001,0.65592 0.502483,0.65592 h 13.664614 c 0.277482,0 0.502482,-0.29361 0.502482,-0.65592 0,-0.36218 -0.225,-0.65588 -0.502482,-0.65588 z"
|
||||
id="path489" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="m 111.0562,191.21315 h -8.03287 c -0.27749,0 -0.50248,0.2936 -0.50248,0.6559 0,0.36221 0.22499,0.65592 0.50248,0.65592 h 8.03287 c 0.27749,0 0.50248,-0.29371 0.50248,-0.65592 0,-0.3623 -0.225,-0.6559 -0.50248,-0.6559 z"
|
||||
id="path19" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="M 109.35315,197.09561 H 95.688543 c -0.277485,0 -0.502489,0.29368 -0.502489,0.65589 0,0.3623 0.225004,0.6559 0.502489,0.6559 h 13.664607 c 0.27749,0 0.50248,-0.2936 0.50248,-0.6559 0,-0.36221 -0.22499,-0.65589 -0.50248,-0.65589 z"
|
||||
id="path490" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="M 91.908223,197.09561 H 78.243685 c -0.277558,0 -0.502481,0.29368 -0.502481,0.65589 0,0.3623 0.224923,0.6559 0.502481,0.6559 h 13.664538 c 0.277559,0 0.502484,-0.2936 0.502484,-0.6559 0,-0.36221 -0.224925,-0.65589 -0.502484,-0.65589 z"
|
||||
id="path20" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="M 98.995238,200.03686 H 78.243685 c -0.277558,0 -0.502481,0.29371 -0.502481,0.6559 0,0.36221 0.224923,0.65592 0.502481,0.65592 h 20.751553 c 0.277486,0 0.502481,-0.29371 0.502481,-0.65592 0,-0.36219 -0.224995,-0.6559 -0.502481,-0.6559 z"
|
||||
id="path491" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="m 102.59502,202.97815 h -7.217328 c -0.277559,0 -0.502481,0.29368 -0.502481,0.65589 0,0.36221 0.224922,0.6559 0.502481,0.6559 h 7.217328 c 0.27757,0 0.5025,-0.29369 0.5025,-0.6559 0,-0.36221 -0.22493,-0.65589 -0.5025,-0.65589 z"
|
||||
id="path21" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="m 88.116941,202.97815 h -9.873256 c -0.277558,0 -0.502481,0.29368 -0.502481,0.65589 0,0.36221 0.224923,0.6559 0.502481,0.6559 h 9.873256 c 0.277559,0 0.502483,-0.29369 0.502483,-0.6559 0,-0.36221 -0.224924,-0.65589 -0.502483,-0.65589 z"
|
||||
id="path23" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="M 104.2422,155.91808 H 84.241221 c -0.277482,0 -0.502482,0.29366 -0.502482,0.65593 0,0.3622 0.225,0.6559 0.502482,0.6559 H 104.2422 c 0.27756,0 0.50248,-0.2937 0.50248,-0.6559 0,-0.36227 -0.22492,-0.65593 -0.50248,-0.65593 z"
|
||||
id="path493" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="m 77.98477,155.91808 h -4.246521 c -0.277482,0 -0.502484,0.29366 -0.502484,0.65593 0,0.3622 0.225002,0.6559 0.502484,0.6559 h 4.246521 c 0.277482,0 0.502483,-0.2937 0.502483,-0.6559 0,-0.36227 -0.225001,-0.65593 -0.502483,-0.65593 z"
|
||||
id="path492" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="m 83.236257,152.97684 h -9.498009 c -0.277482,0 -0.502483,0.29366 -0.502483,0.6559 0,0.36225 0.225001,0.6559 0.502483,0.6559 h 9.498009 c 0.277482,0 0.502482,-0.29365 0.502482,-0.6559 0,-0.36224 -0.225,-0.6559 -0.502482,-0.6559 z"
|
||||
id="path3" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.087;stroke-dasharray:none"
|
||||
d="m 99.792715,191.21315 h -8.032868 c -0.277481,0 -0.502481,0.2936 -0.502481,0.6559 0,0.36221 0.225,0.65592 0.502481,0.65592 h 8.032868 c 0.277495,0 0.502495,-0.29371 0.502495,-0.65592 0,-0.3623 -0.225,-0.6559 -0.502495,-0.6559 z"
|
||||
id="path18" /></g></g></svg>
|
||||
|
After Width: | Height: | Size: 15 KiB |
34
Controls/AppTile.xaml
Normal file
34
Controls/AppTile.xaml
Normal file
@@ -0,0 +1,34 @@
|
||||
<StackPanel
|
||||
x:Class="WinDurango.UI.Controls.AppTile"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:WinDurango.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Margin="10, 10, 10, 10"
|
||||
>
|
||||
<Button Width="320" Height="180" Padding="0" Name="startButton" CornerRadius="5, 5, 0, 0" BorderThickness="0" Background="{ThemeResource SystemControlAltLowAcrylicElementBrush}" >
|
||||
<Image x:Name="appLogo"/>
|
||||
</Button>
|
||||
<Expander CornerRadius="0, 0, 5, 5" Width="320" Name="infoExpander">
|
||||
<Grid Name="expanderControls" Width="320">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Name="expanderButtons" Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button x:Name="unregisterButton" Grid.Column="0" Content="Unregister" HorizontalAlignment="Center" Click="HandleUnregister"/>
|
||||
<Button x:Name="viewFolderButton" Grid.Column="1" Content="View Folder" HorizontalAlignment="Center" Click="OpenFolder"/>
|
||||
</Grid>
|
||||
<StackPanel Grid.Row="0">
|
||||
<TextBlock x:Name="expanderVersion" Margin="10 0 0 10"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Expander>
|
||||
</StackPanel>
|
||||
|
||||
93
Controls/AppTile.xaml.cs
Normal file
93
Controls/AppTile.xaml.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.Foundation;
|
||||
using Windows.Storage.Streams;
|
||||
using WinDurango.UI.Dialogs;
|
||||
using WinDurango.UI.Settings;
|
||||
using WinDurango.UI.Utils;
|
||||
|
||||
namespace WinDurango.UI.Controls
|
||||
{
|
||||
public sealed partial class AppTile
|
||||
{
|
||||
private Package _package;
|
||||
private readonly string _familyName;
|
||||
|
||||
private async void HandleUnregister(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var confirmation = new Confirmation($"Are you sure you want to uninstall {_package.DisplayName}?", "Uninstall?");
|
||||
Dialog.BtnClicked answer = await confirmation.Show();
|
||||
if (answer == Dialog.BtnClicked.Yes)
|
||||
{
|
||||
if (InstalledPackages.RemoveSymlinks(_familyName))
|
||||
await Packages.RemovePackage(_package);
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenFolder(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Process.Start(new ProcessStartInfo(_package.InstalledPath) { UseShellExecute = true });
|
||||
}
|
||||
|
||||
public AppTile(string familyName)
|
||||
{
|
||||
_familyName = familyName;
|
||||
|
||||
this.InitializeComponent();
|
||||
|
||||
_package = Packages.GetPackageByFamilyName(_familyName);
|
||||
var ss = Packages.getSplashScreenPath(_package);
|
||||
IReadOnlyList<AppListEntry> appListEntries = _package.GetAppListEntries();
|
||||
AppListEntry firstAppListEntry = appListEntries[0];
|
||||
|
||||
if (ss == null)
|
||||
{
|
||||
RandomAccessStreamReference logoStream = firstAppListEntry.DisplayInfo.GetLogo(new Size(320, 180));
|
||||
BitmapImage logoImage = new();
|
||||
|
||||
using IRandomAccessStream stream = logoStream.OpenReadAsync().GetAwaiter().GetResult();
|
||||
logoImage.SetSource(stream);
|
||||
|
||||
appLogo.Source = logoImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
appLogo.Source = new BitmapImage(new Uri(ss));
|
||||
}
|
||||
infoExpander.Header = _package.DisplayName;
|
||||
|
||||
Flyout rcFlyout = new();
|
||||
StackPanel rcOptions = new();
|
||||
Button rcUnregisterButton = new() { Content = "Remove" };
|
||||
|
||||
rcUnregisterButton.Tapped += (s, e) =>
|
||||
{
|
||||
HandleUnregister(s, e);
|
||||
};
|
||||
|
||||
rcOptions.Children.Add(rcUnregisterButton);
|
||||
rcFlyout.Content = rcOptions;
|
||||
|
||||
expanderVersion.Text = $"Version {_package.Id.Version.Major}.{_package.Id.Version.Minor}.{_package.Id.Version.Build}";
|
||||
|
||||
|
||||
RightTapped += (sender, e) =>
|
||||
{
|
||||
rcFlyout.ShowAt(sender as FrameworkElement);
|
||||
};
|
||||
|
||||
startButton.Tapped += async (s, e) =>
|
||||
{
|
||||
var hasLaunched = await firstAppListEntry.LaunchAsync();
|
||||
if (hasLaunched == false)
|
||||
new NoticeDialog($"Failed to launch \"{_package.DisplayName}\"!");
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Controls/ContributorInfo.xaml
Normal file
30
Controls/ContributorInfo.xaml
Normal file
@@ -0,0 +1,30 @@
|
||||
<UserControl
|
||||
x:Class="WinDurango.UI.Controls.ContributorInfo"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:WinDurango.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="400">
|
||||
|
||||
<Grid Height="128" Width="256" Background="{ThemeResource SystemControlAltLowAcrylicElementBrush}" BorderBrush="{ThemeResource ControlElevationBorderBrush}" BorderThickness="1" CornerRadius="5">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="77"></ColumnDefinition>
|
||||
<ColumnDefinition></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<PersonPicture Name="developerPicture" x:FieldModifier="public" Grid.Row="0" Padding="5 0 0 0" Width="64" Height="64" VerticalAlignment="Center" BorderBrush="{ThemeResource ControlElevationBorderBrush}" BorderThickness="1"></PersonPicture>
|
||||
<Grid Grid.Column="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition></RowDefinition>
|
||||
<RowDefinition></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<HyperlinkButton Name="developerName" FontSize="18" x:FieldModifier="public" VerticalAlignment="Bottom" Grid.Row="0" Padding="5 5 5 5" Margin="0 0 0 0"></HyperlinkButton>
|
||||
<TextBlock Name="developerInfo" x:FieldModifier="public" TextWrapping="WrapWholeWords" VerticalAlignment="Top" Grid.Row="1" HorizontalAlignment="Left" Margin="5 0 0 0"></TextBlock>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
13
Controls/ContributorInfo.xaml.cs
Normal file
13
Controls/ContributorInfo.xaml.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace WinDurango.UI.Controls
|
||||
{
|
||||
public sealed partial class ContributorInfo : UserControl
|
||||
{
|
||||
public ContributorInfo()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
75
Dialogs/Confirmation.cs
Normal file
75
Dialogs/Confirmation.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WinDurango.UI.Dialogs
|
||||
{
|
||||
public class Confirmation
|
||||
{
|
||||
private string _content;
|
||||
private string _title;
|
||||
private ContentDialog _confirmationDialog;
|
||||
|
||||
public Confirmation(string content, string title = "Information")
|
||||
{
|
||||
_content = content;
|
||||
_title = title;
|
||||
}
|
||||
|
||||
public async Task<Dialog.BtnClicked> Show()
|
||||
{
|
||||
_confirmationDialog = new ContentDialog
|
||||
{
|
||||
Content = _content,
|
||||
Title = _title,
|
||||
PrimaryButtonText = "Yes",
|
||||
SecondaryButtonText = "No",
|
||||
DefaultButton = ContentDialogButton.Secondary,
|
||||
XamlRoot = App.MainWindow.Content.XamlRoot
|
||||
};
|
||||
|
||||
var result = await _confirmationDialog.ShowAsync();
|
||||
|
||||
return result switch
|
||||
{
|
||||
ContentDialogResult.Primary => Dialog.BtnClicked.Yes,
|
||||
ContentDialogResult.Secondary => Dialog.BtnClicked.No,
|
||||
_ => throw new InvalidOperationException("Unexpected result."),
|
||||
};
|
||||
}
|
||||
|
||||
public string Content
|
||||
{
|
||||
get { return _content; }
|
||||
set
|
||||
{
|
||||
_content = value;
|
||||
UpdateDialog();
|
||||
}
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get { return _title; }
|
||||
set
|
||||
{
|
||||
_title = value;
|
||||
UpdateDialog();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateDialog()
|
||||
{
|
||||
if (_confirmationDialog != null)
|
||||
{
|
||||
_confirmationDialog.Content = _content;
|
||||
_confirmationDialog.Title = _title;
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
_confirmationDialog = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Dialogs/Dialog.cs
Normal file
12
Dialogs/Dialog.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace WinDurango.UI.Dialogs
|
||||
{
|
||||
public static class Dialog
|
||||
{
|
||||
public enum BtnClicked
|
||||
{
|
||||
Yes,
|
||||
No
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
67
Dialogs/Notice.cs
Normal file
67
Dialogs/Notice.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace WinDurango.UI.Dialogs
|
||||
{
|
||||
public class NoticeDialog
|
||||
{
|
||||
private string _content;
|
||||
private string _title;
|
||||
private ContentDialog _messageDialog;
|
||||
|
||||
public NoticeDialog(string content, string title = "Information")
|
||||
{
|
||||
_content = content;
|
||||
_title = title;
|
||||
}
|
||||
|
||||
public async Task Show()
|
||||
{
|
||||
_messageDialog = new ContentDialog
|
||||
{
|
||||
Content = _content,
|
||||
Title = _title,
|
||||
CloseButtonText = "OK",
|
||||
XamlRoot = App.MainWindow.Content.XamlRoot
|
||||
};
|
||||
|
||||
await _messageDialog.ShowAsync();
|
||||
}
|
||||
|
||||
public string Content
|
||||
{
|
||||
get { return _content; }
|
||||
set
|
||||
{
|
||||
_content = value;
|
||||
UpdateDialog();
|
||||
}
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get { return _title; }
|
||||
set
|
||||
{
|
||||
_title = value;
|
||||
UpdateDialog();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateDialog()
|
||||
{
|
||||
if (_messageDialog != null)
|
||||
{
|
||||
_messageDialog.Content = _content;
|
||||
_messageDialog.Title = _title;
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
_messageDialog = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
80
Dialogs/Progress.cs
Normal file
80
Dialogs/Progress.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace WinDurango.UI.Dialogs
|
||||
{
|
||||
public class ProgressDialog : ContentDialog
|
||||
{
|
||||
private string _text;
|
||||
private string _title;
|
||||
private double _progress;
|
||||
private bool _isIndeterminate;
|
||||
private ProgressBar _progressBar;
|
||||
private TextBlock _textBlock;
|
||||
|
||||
public ProgressDialog(string content, string title = "Information", bool isIndeterminate = true)
|
||||
{
|
||||
_text = content;
|
||||
_title = title;
|
||||
_isIndeterminate = isIndeterminate;
|
||||
|
||||
_progressBar = new ProgressBar
|
||||
{
|
||||
IsIndeterminate = _isIndeterminate,
|
||||
Width = 300,
|
||||
Value = _progress
|
||||
};
|
||||
|
||||
_textBlock = new TextBlock
|
||||
{
|
||||
Text = _text,
|
||||
Margin = new Thickness(0, 10, 0, 0)
|
||||
};
|
||||
|
||||
Content = new StackPanel
|
||||
{
|
||||
Children =
|
||||
{
|
||||
_progressBar,
|
||||
_textBlock
|
||||
},
|
||||
XamlRoot = App.MainWindow.Content.XamlRoot
|
||||
};
|
||||
Title = _title;
|
||||
XamlRoot = App.MainWindow.Content.XamlRoot;
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
get { return _text; }
|
||||
set
|
||||
{
|
||||
_text = value;
|
||||
UpdateDialog();
|
||||
}
|
||||
}
|
||||
|
||||
public double Progress
|
||||
{
|
||||
get { return _progress; }
|
||||
set
|
||||
{
|
||||
_progress = value;
|
||||
UpdateDialog();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateDialog()
|
||||
{
|
||||
if (_textBlock != null)
|
||||
{
|
||||
_textBlock.Text = _text;
|
||||
}
|
||||
|
||||
if (_progressBar != null)
|
||||
{
|
||||
_progressBar.Value = _progress;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
55
MainWindow.xaml
Normal file
55
MainWindow.xaml
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Window
|
||||
x:Class="WinDurango.UI.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:WinDurango.UI"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32"/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0" Loaded="appTitleBar_Loaded" SizeChanged="appTitleBar_SizeChanged" x:Name="appTitleBar">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="48" x:Name="leftPaddingColumn"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="0" x:Name="rightPaddingColumn"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border Grid.Column="0" Margin="15 0 0 0" Width="32" Height="32">
|
||||
<Image Width="32" Height="32" Source="ms-appx:///Assets/icon.ico"/>
|
||||
</Border>
|
||||
|
||||
<TextBlock
|
||||
Text="WinDurango"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Margin="28,0,0,0"/>
|
||||
</Grid>
|
||||
<NavigationView
|
||||
Grid.Row="1"
|
||||
IsPaneToggleButtonVisible="true"
|
||||
PaneDisplayMode="LeftCompact"
|
||||
IsPaneOpen="false"
|
||||
IsBackButtonVisible="Collapsed"
|
||||
ItemInvoked="NavigationInvoked"
|
||||
x:Name="navView">
|
||||
<NavigationView.MenuItems>
|
||||
<NavigationViewItem Icon="AllApps" Content="Home" Tag="AppsListPage"/>
|
||||
</NavigationView.MenuItems>
|
||||
<NavigationView.FooterMenuItems>
|
||||
<NavigationViewItem Content="About" Tag="AboutPage">
|
||||
<NavigationViewItem.Icon>
|
||||
<FontIcon Glyph="" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
</NavigationView.FooterMenuItems>
|
||||
<Frame x:Name="contentFrame"/>
|
||||
</NavigationView>
|
||||
</Grid>
|
||||
</Window>
|
||||
117
MainWindow.xaml.cs
Normal file
117
MainWindow.xaml.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using Microsoft.UI.Composition.SystemBackdrops;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using System;
|
||||
using WinDurango.UI.Dialogs;
|
||||
using WinDurango.UI.Pages;
|
||||
using WinDurango.UI.Settings;
|
||||
|
||||
namespace WinDurango.UI
|
||||
{
|
||||
public sealed partial class MainWindow : Window
|
||||
{
|
||||
public static readonly WdSettings Settings = new();
|
||||
public readonly string AppName = "WinDurango";
|
||||
public AppsListPage AppsListPage;
|
||||
public SettingsPage SettingsPage;
|
||||
public AboutPage AboutPage;
|
||||
|
||||
private void NavigationInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
|
||||
{
|
||||
if (args.IsSettingsInvoked == true)
|
||||
{
|
||||
contentFrame.Navigate(typeof(SettingsPage));
|
||||
}
|
||||
else if (args.InvokedItemContainer is NavigationViewItem item)
|
||||
{
|
||||
string tag = item.Tag.ToString();
|
||||
Type pageType = tag switch
|
||||
{
|
||||
"AppsListPage" => typeof(AppsListPage),
|
||||
"AboutPage" => typeof(AboutPage),
|
||||
_ => typeof(AppsListPage)
|
||||
};
|
||||
|
||||
if (contentFrame.Navigate(pageType))
|
||||
{
|
||||
if (contentFrame.Content is AppsListPage appsList)
|
||||
{
|
||||
AppsListPage = appsList;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ReloadAppList()
|
||||
{
|
||||
if (AppsListPage != null)
|
||||
AppsListPage.InitAppList();
|
||||
}
|
||||
|
||||
public void LoadSettings()
|
||||
{
|
||||
switch (Settings.Settings.Theme)
|
||||
{
|
||||
case WdSettingsData.ThemeSetting.Mica:
|
||||
this.SystemBackdrop = new MicaBackdrop() { Kind = MicaKind.Base };
|
||||
break;
|
||||
case WdSettingsData.ThemeSetting.MicaAlt:
|
||||
this.SystemBackdrop = new MicaBackdrop() { Kind = MicaKind.BaseAlt };
|
||||
break;
|
||||
case WdSettingsData.ThemeSetting.Fluent:
|
||||
this.SystemBackdrop = new DesktopAcrylicBackdrop();
|
||||
break;
|
||||
case WdSettingsData.ThemeSetting.FluentThin:
|
||||
this.SystemBackdrop = new DesktopAcrylicBackdrop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
Title = AppName;
|
||||
|
||||
// setup theme and titlebar
|
||||
AppWindow appWindow = this.AppWindow;
|
||||
ExtendsContentIntoTitleBar = true;
|
||||
|
||||
Microsoft.UI.Composition.Compositor compositor = this.Compositor;
|
||||
|
||||
this.Activate();
|
||||
LoadSettings();
|
||||
|
||||
contentFrame.Navigate(typeof(AppsListPage));
|
||||
AppsListPage = (AppsListPage)contentFrame.Content;
|
||||
}
|
||||
|
||||
private async void appTitleBar_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// have to do it here otherwise instance error
|
||||
var devNotice = new NoticeDialog($"This UI is very early in development, and mainly developed by a C# learner... There WILL be bugs, and some things will NOT work...\n\nDevelopers, check MainWindow.xaml.cs for the todolist.", "Important");
|
||||
await devNotice.Show();
|
||||
if (ExtendsContentIntoTitleBar)
|
||||
{
|
||||
SetupTitleBar();
|
||||
}
|
||||
}
|
||||
|
||||
private void appTitleBar_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
if (ExtendsContentIntoTitleBar)
|
||||
{
|
||||
SetupTitleBar();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupTitleBar()
|
||||
{
|
||||
AppWindowTitleBar titleBar = AppWindow.TitleBar;
|
||||
double scaleAdjustment = appTitleBar.XamlRoot.RasterizationScale;
|
||||
rightPaddingColumn.Width = new GridLength(titleBar.RightInset / scaleAdjustment);
|
||||
leftPaddingColumn.Width = new GridLength(titleBar.LeftInset / scaleAdjustment);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Pages/AboutPage.xaml
Normal file
30
Pages/AboutPage.xaml
Normal file
@@ -0,0 +1,30 @@
|
||||
<Page
|
||||
x:Class="WinDurango.UI.Pages.AboutPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:WinDurango.UI.Pages"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:appLocal="using:WinDurango.UI"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:controls="using:WinDurango.UI.Controls" xmlns:svg="using:SVGImage.SVG"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<StackPanel Orientation="Vertical" Padding="10">
|
||||
<TextBlock Text="Application Info" FontSize="24"/>
|
||||
<controls:ContributorInfo Margin="0 10 10 10" x:Name="windurango_Info" HorizontalAlignment="Left"/>
|
||||
<TextBlock Text="UI Lead Developers" FontSize="24"/>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<controls:ContributorInfo Margin="0 10 10 10" x:Name="dexrn_Info" HorizontalAlignment="Left"/>
|
||||
<controls:ContributorInfo Margin="0 10 10 10" x:Name="danilwhale_Info" HorizontalAlignment="Left"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Text="Repo Contributors" FontSize="24"/>
|
||||
<TextBlock>
|
||||
<Run Text="Coming soon (maybe)"/>
|
||||
<LineBreak/>
|
||||
<Run Text="contrib.rocks apparently returns some svg instead of a png..."/>
|
||||
<LineBreak/>
|
||||
<Run Text="which makes it hard for me to use here."/>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Page>
|
||||
33
Pages/AboutPage.xaml.cs
Normal file
33
Pages/AboutPage.xaml.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using System;
|
||||
|
||||
|
||||
namespace WinDurango.UI.Pages
|
||||
{
|
||||
public sealed partial class AboutPage : Page
|
||||
{
|
||||
private string getGitHubPfp(string username)
|
||||
{
|
||||
return $"https://github.com/{username}.png";
|
||||
}
|
||||
|
||||
public AboutPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
dexrn_Info.developerPicture.ProfilePicture = new BitmapImage(new Uri(getGitHubPfp("DexrnZacAttack")));
|
||||
dexrn_Info.developerName.Content = "DexrnZacAttack";
|
||||
dexrn_Info.developerName.NavigateUri = new Uri("https://github.com/DexrnZacAttack");
|
||||
dexrn_Info.developerInfo.Text = "UI design, functionality, learning C#";
|
||||
danilwhale_Info.developerPicture.ProfilePicture = new BitmapImage(new Uri(getGitHubPfp("danilwhale")));
|
||||
danilwhale_Info.developerName.Content = "danilwhale";
|
||||
danilwhale_Info.developerName.NavigateUri = new Uri("https://github.com/danilwhale");
|
||||
danilwhale_Info.developerInfo.Text = "Refactoring, teaching, bug fixing, etc";
|
||||
|
||||
windurango_Info.developerInfo.Text = $"Version {App.Version}";
|
||||
windurango_Info.developerName.Content = "WinDurango.UI";
|
||||
windurango_Info.developerName.NavigateUri = new Uri("https://github.com/WinDurango-project/WinDurango.UI");
|
||||
windurango_Info.developerPicture.ProfilePicture = new BitmapImage(new Uri(getGitHubPfp("WinDurango-project")));
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Pages/AppsListPage.xaml
Normal file
23
Pages/AppsListPage.xaml
Normal file
@@ -0,0 +1,23 @@
|
||||
<Page
|
||||
x:Class="WinDurango.UI.Pages.AppsListPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:WinDurango.UI.Pages"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
mc:Ignorable="d"
|
||||
>
|
||||
<controls:DockPanel>
|
||||
<controls:WrapPanel controls:DockPanel.Dock="Top" x:Name="appList" HorizontalAlignment="Center" />
|
||||
<Button
|
||||
controls:DockPanel.Dock="Bottom"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
Margin="0,0,0,5"
|
||||
Tapped="installButton_Tapped"
|
||||
x:Name="installButton">
|
||||
Install Package
|
||||
</Button>
|
||||
</controls:DockPanel>
|
||||
</Page>
|
||||
95
Pages/AppsListPage.xaml.cs
Normal file
95
Pages/AppsListPage.xaml.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Principal;
|
||||
using Windows.Management.Deployment;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Pickers;
|
||||
using WinDurango.UI.Controls;
|
||||
using WinDurango.UI.Dialogs;
|
||||
using WinDurango.UI.Settings;
|
||||
using WinDurango.UI.Utils;
|
||||
|
||||
namespace WinDurango.UI.Pages
|
||||
{
|
||||
public sealed partial class AppsListPage : Page
|
||||
{
|
||||
public void InitAppList()
|
||||
{
|
||||
appList.Children.Clear();
|
||||
|
||||
Dictionary<string, InstalledPackage> installedPackages = InstalledPackages.GetInstalledPackages();
|
||||
var pm = new PackageManager();
|
||||
|
||||
foreach (var installedPackage in installedPackages)
|
||||
{
|
||||
if (pm.FindPackageForUser(WindowsIdentity.GetCurrent().User?.Value, installedPackage.Value.FullName) != null)
|
||||
{
|
||||
Grid outerGrid = new();
|
||||
AppTile gameContainer = new(installedPackage.Key);
|
||||
outerGrid.Children.Add(gameContainer);
|
||||
appList.Children.Add(outerGrid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AppsListPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
InitAppList();
|
||||
}
|
||||
|
||||
private async void installButton_Tapped(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
var picker = new FolderPicker();
|
||||
picker.SuggestedStartLocation = PickerLocationId.Desktop;
|
||||
picker.FileTypeFilter.Add("*");
|
||||
|
||||
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
|
||||
|
||||
WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);
|
||||
|
||||
StorageFolder folder = await picker.PickSingleFolderAsync();
|
||||
|
||||
if (folder != null)
|
||||
{
|
||||
string manifest = Path.Combine(folder.Path + "\\AppxManifest.xml");
|
||||
string mountFolder = Path.Combine(folder.Path + "\\Mount");
|
||||
|
||||
if (File.Exists(manifest))
|
||||
{
|
||||
await Packages.InstallPackageAsync(new Uri(manifest, UriKind.Absolute));
|
||||
}
|
||||
else
|
||||
{
|
||||
// AppxManifest does not exist in that folder
|
||||
if (Directory.Exists(mountFolder))
|
||||
{
|
||||
// there IS a mount folder
|
||||
if (File.Exists(Path.Combine(mountFolder + "\\AppxManifest.xml")))
|
||||
{
|
||||
// there is an AppxManifest inside.
|
||||
var confirmation = new Confirmation($"There was no AppxManifest found inside the picked folder.\nHowever there was one found inside the Mount folder, would you like to register that?", "Install from Mount?");
|
||||
if (await confirmation.Show() == Dialog.BtnClicked.Yes)
|
||||
await Packages.InstallXPackageAsync((folder.Path).ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// there is no AppxManifest inside.
|
||||
await new NoticeDialog($"AppxManifest does not exist in both {folder.Path} and {mountFolder}", "Error").Show();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await new NoticeDialog($"AppxManifest does not exist in {folder.Path} and there is no \"Mount\" folder.", "Error").Show();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Pages/SettingsPage.xaml
Normal file
30
Pages/SettingsPage.xaml
Normal file
@@ -0,0 +1,30 @@
|
||||
<Page
|
||||
x:Class="WinDurango.UI.Pages.SettingsPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:WinDurango.UI.Pages"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Grid Padding="10 10 10 10">
|
||||
<StackPanel Grid.Row="1">
|
||||
<TextBlock Text="Theme"/>
|
||||
<DropDownButton
|
||||
Loaded="OnThemeButtonLoaded"
|
||||
Name="themeButton"
|
||||
Content="Use Mica"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top" >
|
||||
<DropDownButton.Flyout>
|
||||
<MenuFlyout Placement="Bottom">
|
||||
<MenuFlyoutItem Text="Mica" Click="OnMicaSelected"/>
|
||||
<MenuFlyoutItem Text="Mica Alt" Click="OnMicaAltSelected"/>
|
||||
<MenuFlyoutItem Text="Fluent" Click="OnFluentSelected"/>
|
||||
</MenuFlyout>
|
||||
</DropDownButton.Flyout>
|
||||
</DropDownButton>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Page>
|
||||
51
Pages/SettingsPage.xaml.cs
Normal file
51
Pages/SettingsPage.xaml.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using WinDurango.UI.Settings;
|
||||
|
||||
namespace WinDurango.UI.Pages
|
||||
{
|
||||
public sealed partial class SettingsPage : Page
|
||||
{
|
||||
private async void OnMicaSelected(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await MainWindow.Settings.SetSetting("Theme", WdSettingsData.ThemeSetting.Mica);
|
||||
OnThemeButtonLoaded(sender, e);
|
||||
}
|
||||
|
||||
private async void OnMicaAltSelected(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await MainWindow.Settings.SetSetting("Theme", WdSettingsData.ThemeSetting.MicaAlt);
|
||||
OnThemeButtonLoaded(sender, e);
|
||||
}
|
||||
|
||||
private async void OnFluentSelected(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await MainWindow.Settings.SetSetting("Theme", WdSettingsData.ThemeSetting.Fluent);
|
||||
OnThemeButtonLoaded(sender, e);
|
||||
}
|
||||
|
||||
private void OnThemeButtonLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
switch (MainWindow.Settings.Settings.Theme)
|
||||
{
|
||||
case WdSettingsData.ThemeSetting.Fluent:
|
||||
themeButton.Content = "Fluent";
|
||||
break;
|
||||
case WdSettingsData.ThemeSetting.FluentThin:
|
||||
themeButton.Content = "Fluent (Thin)";
|
||||
break;
|
||||
case WdSettingsData.ThemeSetting.Mica:
|
||||
themeButton.Content = "Mica";
|
||||
break;
|
||||
case WdSettingsData.ThemeSetting.MicaAlt:
|
||||
themeButton.Content = "Mica (Alt)";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public SettingsPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
20
README.md
20
README.md
@@ -1,2 +1,22 @@
|
||||
# WinDurango.UI
|
||||
GUI for WinDurango, which is planned to allow for easy installing/patching among other random stuff I decide lmfao
|
||||
|
||||
> [!NOTE]
|
||||
> This does nothing more than provide a GUI for easily registering and patching packages with WinDurango.
|
||||
> Additionally, I don't know much about C#... so the code is probably very messy.
|
||||
|
||||
## Todo
|
||||
- [X] Make the applist not go offscreen (lol)
|
||||
- [ ] Applist pages
|
||||
- [ ] Fix icon in the titlebar
|
||||
- [ ] Allow for search
|
||||
- [ ] Resize content to fit to screen
|
||||
- [ ] Allow for package removal from UI instead of just completely uninstalling, as well as allowing for any existing installed package to be added
|
||||
- [ ] Compiling the DLLs and patching automatically
|
||||
- [ ] Dropdown button instead of just an install button (so you can install without symlinking dlls, add existing packages, etc)
|
||||
- [ ] Repo contributors on the about screen
|
||||
- [ ] Get Fluent Thin working
|
||||
- [ ] Add versioning to the InstalledPackages json
|
||||
- [ ] Make the Package stuff not rely on UI so much, handle that somewhere else.
|
||||
- [ ] Fix crash when installation errors
|
||||
- [ ] Cleanup, lots and lots of it.
|
||||
|
||||
173
Settings/InstalledPackages.cs
Normal file
173
Settings/InstalledPackages.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security.Policy;
|
||||
using System.Text.Json;
|
||||
using Windows.ApplicationModel;
|
||||
using WinDurango.UI.Utils;
|
||||
|
||||
|
||||
namespace WinDurango.UI.Settings
|
||||
{
|
||||
public class InstalledPackage
|
||||
{
|
||||
public string FullName { get; set; }
|
||||
public List<string> SymlinkedDLLs { get; set; }
|
||||
}
|
||||
|
||||
public abstract class InstalledPackages
|
||||
{
|
||||
|
||||
public static void RemoveInstalledPackage(Package pkg)
|
||||
{
|
||||
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "WinDurango");
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
string filePath = Path.Combine(path, "InstalledPackages.json");
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
Debug.WriteLine("Could not get the list of installed packages!");
|
||||
using (StreamWriter writer = File.CreateText(filePath))
|
||||
{
|
||||
writer.WriteLine("{}");
|
||||
}
|
||||
}
|
||||
|
||||
string json = File.ReadAllText(filePath);
|
||||
var installedPkgs = JsonSerializer.Deserialize<Dictionary<string, InstalledPackage>>(json) ?? new Dictionary<string, InstalledPackage>();
|
||||
|
||||
if (installedPkgs.TryGetValue(pkg.Id.FamilyName, out var package) && package.FullName == pkg.Id.FullName)
|
||||
{
|
||||
installedPkgs.Remove(pkg.Id.FamilyName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine($"Couldn't uninstall {pkg.Id.FamilyName} as it was not found in the package list.");
|
||||
return;
|
||||
}
|
||||
|
||||
string updated = JsonSerializer.Serialize(installedPkgs, new JsonSerializerOptions { WriteIndented = true });
|
||||
File.WriteAllText(filePath, updated);
|
||||
}
|
||||
|
||||
|
||||
public static Dictionary<string, InstalledPackage> GetInstalledPackages()
|
||||
{
|
||||
if (!Directory.Exists(App.DataDir))
|
||||
{
|
||||
Directory.CreateDirectory(App.DataDir);
|
||||
}
|
||||
|
||||
string filePath = Path.Combine(App.DataDir, "InstalledPackages.json");
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
Debug.WriteLine("Could not get the list of installed packages!");
|
||||
using (StreamWriter writer = File.CreateText(filePath))
|
||||
{
|
||||
writer.WriteLine("{}");
|
||||
}
|
||||
}
|
||||
|
||||
string json = File.ReadAllText(filePath);
|
||||
|
||||
Dictionary<string, InstalledPackage> installedPkgs = JsonSerializer.Deserialize<Dictionary<string, InstalledPackage>>(json)
|
||||
?? new Dictionary<string, InstalledPackage>();
|
||||
|
||||
return installedPkgs;
|
||||
}
|
||||
|
||||
public static void SaveInstalledPackages(Dictionary<string, InstalledPackage> installedPkgs)
|
||||
{
|
||||
string json = JsonSerializer.Serialize(installedPkgs, new JsonSerializerOptions { WriteIndented = true });
|
||||
File.WriteAllText(Path.Combine(App.DataDir, "InstalledPackages.json"), json);
|
||||
}
|
||||
|
||||
public static void UpdateInstalledPackage(string familyName, InstalledPackage installedPkg)
|
||||
{
|
||||
Dictionary<string, InstalledPackage> installedPkgs = GetInstalledPackages();
|
||||
|
||||
installedPkgs[familyName] = installedPkg;
|
||||
SaveInstalledPackages(installedPkgs);
|
||||
}
|
||||
|
||||
public static bool RemoveSymlinks(string familyName)
|
||||
{
|
||||
var pkg = GetInstalledPackage(familyName).Value;
|
||||
var pkgMount = Packages.GetPackageByFamilyName(pkg.familyName).EffectivePath;
|
||||
|
||||
if (Directory.Exists(pkgMount))
|
||||
{
|
||||
foreach (var symlink in pkg.installedPackage.SymlinkedDLLs)
|
||||
{
|
||||
string symlinkPath = Path.Combine(pkgMount, symlink);
|
||||
if (File.Exists(symlinkPath))
|
||||
{
|
||||
var attributes = File.GetAttributes(symlinkPath);
|
||||
if (attributes.HasFlag(FileAttributes.ReparsePoint))
|
||||
{
|
||||
File.Delete(symlinkPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static (string familyName, InstalledPackage installedPackage)? GetInstalledPackage(string familyName)
|
||||
{
|
||||
Dictionary<string, InstalledPackage> installedPkgs = GetInstalledPackages();
|
||||
if (installedPkgs.TryGetValue(familyName, out InstalledPackage installedPkg))
|
||||
return (familyName, installedPkg);
|
||||
|
||||
// this should never happen (but in case it does)
|
||||
throw new KeyNotFoundException($"{familyName} was not found in the installed packages list.");
|
||||
}
|
||||
|
||||
public static void AddInstalledPackage(Package package)
|
||||
{
|
||||
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "WinDurango");
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
string filePath = Path.Combine(path, "InstalledPackages.json");
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
Debug.WriteLine("Could not get the list of installed packages!");
|
||||
using (StreamWriter writer = File.CreateText(filePath))
|
||||
{
|
||||
writer.WriteLine("{}");
|
||||
}
|
||||
}
|
||||
|
||||
string json = File.ReadAllText(filePath);
|
||||
var installedPkgs = JsonSerializer.Deserialize<Dictionary<string, InstalledPackage>>(json) ?? new Dictionary<string, InstalledPackage>();
|
||||
|
||||
if (installedPkgs.ContainsKey(package.Id.FamilyName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
installedPkgs[package.Id.FamilyName] = new InstalledPackage
|
||||
{
|
||||
FullName = package.Id.FullName,
|
||||
SymlinkedDLLs = new List<string>()
|
||||
};
|
||||
|
||||
string updated = JsonSerializer.Serialize(installedPkgs, new JsonSerializerOptions { WriteIndented = true });
|
||||
File.WriteAllText(filePath, updated);
|
||||
}
|
||||
}
|
||||
}
|
||||
128
Settings/Settings.cs
Normal file
128
Settings/Settings.cs
Normal file
@@ -0,0 +1,128 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WinDurango.UI.Settings;
|
||||
|
||||
public class WdSettingsData
|
||||
{
|
||||
public enum ThemeSetting
|
||||
{
|
||||
Fluent,
|
||||
FluentThin,
|
||||
Mica,
|
||||
MicaAlt
|
||||
}
|
||||
|
||||
public uint SaveVersion { get; set; }
|
||||
public ThemeSetting Theme { get; set; }
|
||||
}
|
||||
|
||||
public class WdSettings
|
||||
{
|
||||
private readonly string _settingsFile = Path.Combine(App.DataDir, "Settings.json");
|
||||
public WdSettingsData Settings { get; private set; }
|
||||
|
||||
public WdSettings()
|
||||
{
|
||||
if (!Directory.Exists(App.DataDir))
|
||||
Directory.CreateDirectory(App.DataDir);
|
||||
|
||||
if (File.Exists(_settingsFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(_settingsFile);
|
||||
WdSettingsData loadedSettings = JsonSerializer.Deserialize<WdSettingsData>(json);
|
||||
|
||||
if (loadedSettings != null)
|
||||
{
|
||||
if (loadedSettings.SaveVersion > App.VerPacked)
|
||||
{
|
||||
BackupSettings();
|
||||
GenerateSettings();
|
||||
}
|
||||
Settings = loadedSettings;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("Error loading settings: " + ex.Message);
|
||||
BackupSettings();
|
||||
GenerateSettings();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BackupSettings();
|
||||
GenerateSettings();
|
||||
}
|
||||
}
|
||||
|
||||
private void BackupSettings()
|
||||
{
|
||||
File.Move(_settingsFile, _settingsFile + ".old_" + ((DateTimeOffset)DateTime.UtcNow).ToUnixTimeMilliseconds().ToString());
|
||||
}
|
||||
|
||||
private async void GenerateSettings()
|
||||
{
|
||||
WdSettingsData defaultSettings = GetDefaults();
|
||||
Settings = defaultSettings;
|
||||
await SaveSettings();
|
||||
}
|
||||
|
||||
private static WdSettingsData GetDefaults()
|
||||
{
|
||||
return new WdSettingsData
|
||||
{
|
||||
SaveVersion = App.VerPacked,
|
||||
Theme = WdSettingsData.ThemeSetting.Fluent
|
||||
};
|
||||
}
|
||||
|
||||
public void MigrateSettings()
|
||||
{
|
||||
// unused for now
|
||||
}
|
||||
|
||||
public async Task SaveSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
Settings.SaveVersion = App.VerPacked;
|
||||
JsonSerializerOptions options = new() { WriteIndented = true };
|
||||
string json = JsonSerializer.Serialize(Settings, options);
|
||||
await File.WriteAllTextAsync(_settingsFile, json);
|
||||
App.MainWindow.LoadSettings();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("Error saving settings: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SetSetting(string setting, object value)
|
||||
{
|
||||
PropertyInfo property = typeof(WdSettingsData).GetProperty(setting);
|
||||
|
||||
if (property != null && property.CanWrite)
|
||||
{
|
||||
try
|
||||
{
|
||||
property.SetValue(Settings, Convert.ChangeType(value, property.PropertyType));
|
||||
await SaveSettings();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"Error setting {setting}: " + ex.Message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine($"Property {setting} does not exist or is read only.");
|
||||
}
|
||||
}
|
||||
}
|
||||
238
Utils/Packages.cs
Normal file
238
Utils/Packages.cs
Normal file
@@ -0,0 +1,238 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.Management.Deployment;
|
||||
using WinDurango.UI.Dialogs;
|
||||
using WinDurango.UI.Settings;
|
||||
|
||||
|
||||
namespace WinDurango.UI.Utils
|
||||
{
|
||||
public abstract class Packages
|
||||
{
|
||||
// TODO: Make these methods not use the GUI, instead just throw an exception and catch it in the area where the method is actually invoked.
|
||||
public static IEnumerable<Package> GetInstalledPackages()
|
||||
{
|
||||
var sid = WindowsIdentity.GetCurrent().User?.Value;
|
||||
|
||||
var pm = new PackageManager();
|
||||
return pm.FindPackagesForUser(sid);
|
||||
}
|
||||
|
||||
public enum XvdMode
|
||||
{
|
||||
CreateSymlinks,
|
||||
DontUse
|
||||
};
|
||||
|
||||
public static async Task InstallXPackageAsync(string dir, XvdMode mode = XvdMode.CreateSymlinks)
|
||||
{
|
||||
Debug.WriteLine(dir);
|
||||
|
||||
string mountDir = Path.Combine(dir, "Mount");
|
||||
string exvdDir = Path.Combine(dir, "EmbeddedXvd");
|
||||
|
||||
bool hasExvd = Directory.Exists(exvdDir);
|
||||
|
||||
if (!Directory.Exists(mountDir))
|
||||
{
|
||||
await new NoticeDialog($"{mountDir} was not found.", "Error").Show();
|
||||
return;
|
||||
}
|
||||
|
||||
string package = await InstallPackageAsync(new Uri(mountDir + "\\AppxManifest.xml", UriKind.Absolute));
|
||||
var newPackage = InstalledPackages.GetInstalledPackage(package).Value;
|
||||
|
||||
if (hasExvd)
|
||||
{
|
||||
foreach (string filePath in Directory.GetFiles(Path.Combine(exvdDir + "\\Windows\\System32")))
|
||||
{
|
||||
string fileName = Path.GetFileName(filePath);
|
||||
|
||||
if (File.Exists(Path.Combine(mountDir, fileName)))
|
||||
continue;
|
||||
|
||||
FileSystemInfo symlink = File.CreateSymbolicLink(Path.Combine(mountDir, fileName), filePath);
|
||||
newPackage.installedPackage.SymlinkedDLLs.Add(symlink.Name);
|
||||
InstalledPackages.UpdateInstalledPackage(newPackage.familyName, newPackage.installedPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string? getSplashScreenPath(Package pkg)
|
||||
{
|
||||
try
|
||||
{
|
||||
string installPath = pkg.InstalledPath;
|
||||
string manifestPath = Path.Combine(installPath, "AppxManifest.xml");
|
||||
|
||||
if (!File.Exists(manifestPath))
|
||||
return null;
|
||||
|
||||
string manifest;
|
||||
using (var stream = File.OpenRead(manifestPath))
|
||||
{
|
||||
var reader = new StreamReader(stream);
|
||||
manifest = reader.ReadToEnd();
|
||||
}
|
||||
|
||||
XDocument doc = XDocument.Parse(manifest);
|
||||
XElement package = doc.Descendants().FirstOrDefault(e => e.Name.LocalName == "Package");
|
||||
if (package == null) return null;
|
||||
|
||||
XElement applications = package.Descendants().FirstOrDefault(e => e.Name.LocalName == "Applications");
|
||||
if (applications == null) return null;
|
||||
|
||||
XElement application = applications.Descendants().FirstOrDefault(e => e.Name.LocalName == "Application");
|
||||
if (application == null) return null;
|
||||
|
||||
XElement visualElements = application.Descendants().FirstOrDefault(e => e.Name.LocalName == "VisualElements");
|
||||
if (visualElements == null) return null;
|
||||
|
||||
XElement splashScreen = visualElements.Descendants().FirstOrDefault(e => e.Name.LocalName == "SplashScreen");
|
||||
if (splashScreen == null) return null;
|
||||
|
||||
string imagePath = splashScreen.Attribute("Image")?.Value;
|
||||
if (imagePath == null) return null;
|
||||
|
||||
string splashScreenPath = Path.Combine(installPath, imagePath);
|
||||
return splashScreenPath;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static async Task<string?> InstallPackageAsync(Uri appxManifestUri)
|
||||
{
|
||||
// TODO: strip UI
|
||||
if (!File.Exists(appxManifestUri.AbsolutePath))
|
||||
{
|
||||
await new NoticeDialog($"{appxManifestUri.AbsolutePath} was not found.", "Error").Show();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
var status = new ProgressDialog($"Installing package...", "Installing", false);
|
||||
App.MainWindow.DispatcherQueue.TryEnqueue(async () => await status.ShowAsync());
|
||||
PackageManager pm = new PackageManager();
|
||||
try
|
||||
{
|
||||
status.Text = "Reading manifest...";
|
||||
string manifest;
|
||||
await using (var stream = File.OpenRead(appxManifestUri.AbsolutePath))
|
||||
{
|
||||
var reader = new StreamReader(stream);
|
||||
manifest = await reader.ReadToEndAsync();
|
||||
}
|
||||
|
||||
XDocument doc = XDocument.Parse(manifest);
|
||||
XElement package = doc.Descendants().FirstOrDefault(e => e.Name.LocalName == "Package");
|
||||
XElement identity = package?.Descendants().FirstOrDefault(e => e.Name.LocalName == "Identity");
|
||||
|
||||
string pkgName = identity.Attribute("Name")?.Value;
|
||||
string pkgPublisher = identity.Attribute("Publisher")?.Value;
|
||||
|
||||
status.Progress = 20.0;
|
||||
status.Text = $"Checking if {pkgName} is already installed...";
|
||||
var sid = WindowsIdentity.GetCurrent().User?.Value;
|
||||
var installedPackages = await Task.Run(() => pm.FindPackagesForUser(sid, pkgName, pkgPublisher));
|
||||
|
||||
if (installedPackages.Any())
|
||||
{
|
||||
status.Hide();
|
||||
await new NoticeDialog($"{pkgName} is already installed.", "Error").Show();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
status.Progress = 40.0;
|
||||
status.Text = $"Installing {pkgName}...";
|
||||
var deployment = await pm.RegisterPackageAsync(appxManifestUri, null, DeploymentOptions.DevelopmentMode);
|
||||
|
||||
status.Progress = 60.0;
|
||||
|
||||
status.Text = $"Getting app info...";
|
||||
var recentPkg = GetMostRecentlyInstalledPackage();
|
||||
|
||||
status.Text = $"Updating app list...";
|
||||
status.Progress = 80.0;
|
||||
InstalledPackages.AddInstalledPackage(recentPkg);
|
||||
status.Progress = 90.0;
|
||||
App.MainWindow.ReloadAppList();
|
||||
status.Progress = 100.0;
|
||||
|
||||
status.Hide();
|
||||
await new NoticeDialog($"{recentPkg.Id.Name} was installed! :)").Show();
|
||||
return recentPkg.Id.FamilyName;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// we're fucked :(
|
||||
status.Hide();
|
||||
await new NoticeDialog($"{appxManifestUri} failed to install: {e.Message}", "Error").Show();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task RemovePackage(Package package)
|
||||
{
|
||||
var status = new ProgressDialog($"Uninstalling {package.DisplayName}...", "Uninstalling", false);
|
||||
App.MainWindow.DispatcherQueue.TryEnqueue(async () => await status.ShowAsync());
|
||||
PackageManager pm = new PackageManager();
|
||||
try
|
||||
{
|
||||
var undeployment = await pm.RemovePackageAsync(package.Id.FullName, RemovalOptions.PreserveApplicationData);
|
||||
|
||||
status.Progress = 50.0;
|
||||
InstalledPackages.RemoveInstalledPackage(package);
|
||||
status.Progress = 100.0;
|
||||
status.Hide();
|
||||
await new NoticeDialog($"{package.DisplayName} was uninstalled.").Show();
|
||||
App.MainWindow.ReloadAppList();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
status.Hide();
|
||||
await new NoticeDialog($"{package.DisplayName} failed to uninstall: {ex.Message}", "Error!").Show();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public static Package GetPackageByFamilyName(string familyName)
|
||||
{
|
||||
var packageManager = new PackageManager();
|
||||
var packages = packageManager.FindPackagesForUser(null, familyName);
|
||||
|
||||
if (packages == null || !packages.Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return packages.First();
|
||||
}
|
||||
|
||||
public static Package GetMostRecentlyInstalledPackage()
|
||||
{
|
||||
var sid = WindowsIdentity.GetCurrent().User?.Value;
|
||||
var pm = new PackageManager();
|
||||
var packages = pm.FindPackagesForUser(sid);
|
||||
|
||||
if (!packages.Any())
|
||||
return null;
|
||||
|
||||
var newestPackage = packages.Last();
|
||||
|
||||
return newestPackage;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
86
WinDurango.csproj
Normal file
86
WinDurango.csproj
Normal file
@@ -0,0 +1,86 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows10.0.22621.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<RootNamespace>WinDurango.UI</RootNamespace>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<Platforms>x86;x64;ARM64</Platforms>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>True</UseWinUI>
|
||||
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
|
||||
<IncludeSourceRevisionInInformationalVersion>true</IncludeSourceRevisionInInformationalVersion>
|
||||
<XamlDebuggingInformation>True</XamlDebuggingInformation>
|
||||
<DisableXbfLineInfo>False</DisableXbfLineInfo>
|
||||
<ApplicationIcon>Assets\icon.ico</ApplicationIcon>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<Version>0.0.1</Version>
|
||||
<AssemblyVersion>$(Version)</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Theming\**" />
|
||||
<Content Remove="Theming\**" />
|
||||
<EmbeddedResource Remove="Theming\**" />
|
||||
<None Remove="Theming\**" />
|
||||
<Page Remove="Theming\**" />
|
||||
<PRIResource Remove="Theming\**" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="Controls\GameContainer.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="Assets\icon.svg" />
|
||||
<None Remove="Controls\AppTile.xaml" />
|
||||
<None Remove="Controls\ContributorInfo.xaml" />
|
||||
<None Remove="Controls\NewFile1.txt" />
|
||||
<None Remove="Pages\AboutPage.xaml" />
|
||||
<None Remove="Pages\AppsListPage.xaml" />
|
||||
<None Remove="Pages\SettingsPage.xaml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Uwp.Controls.Primitives" Version="8.1.240821" />
|
||||
<PackageReference Include="DotNetProjects.SVGImage" Version="5.2.1" />
|
||||
<PackageReference Include="Microsoft.UI.Xaml" Version="2.8.6" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.756" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240802000" />
|
||||
<PackageReference Include="System.DirectoryServices" Version="8.0.0" />
|
||||
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="8.0.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.8" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="Assets\icon.ico">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\ContributorInfo.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Pages\AboutPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Pages\SettingsPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Pages\AppsListPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\AppTile.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
19
app.manifest
Normal file
19
app.manifest
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="WinDurango.app"/>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- The ID below informs the system that this application is compatible with OS features first introduced in Windows 10.
|
||||
It is necessary to support features in unpackaged applications, for example the custom titlebar implementation.
|
||||
For more info see https://docs.microsoft.com/windows/apps/windows-app-sdk/use-windows-app-sdk-run-time#declare-os-compatibility-in-your-application-manifest -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
Reference in New Issue
Block a user