mirror of
https://github.com/WinDurango/WinDurango.UI.git
synced 2026-01-31 00:55:24 +01:00
Install confirmation + fix existing applist crash + start on localization
This commit is contained in:
39
App.xaml.cs
39
App.xaml.cs
@@ -3,14 +3,21 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using WinDurango.UI.Settings;
|
||||
using WinDurango.UI.Utils;
|
||||
using WinUI3Localizer;
|
||||
|
||||
namespace WinDurango.UI
|
||||
{
|
||||
public partial class App : Application
|
||||
{
|
||||
private static readonly FileVersionInfo Fvi = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
|
||||
// constants
|
||||
public static readonly string DataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "WinDurango");
|
||||
public static readonly string AppDir = AppContext.BaseDirectory;
|
||||
private static readonly FileVersionInfo Fvi = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
|
||||
// versioning
|
||||
public static readonly uint Major = (uint)Fvi.ProductMajorPart;
|
||||
public static readonly uint Minor = (uint)Fvi.ProductMinorPart;
|
||||
public static readonly uint Patch = (uint)Fvi.ProductBuildPart;
|
||||
@@ -19,6 +26,8 @@ namespace WinDurango.UI
|
||||
: "HASHFAIL";
|
||||
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.
|
||||
// other
|
||||
public static readonly WdSettings Settings = new();
|
||||
public static readonly MainWindow MainWindow = new();
|
||||
|
||||
public static (uint major, uint minor, uint patch) UnpackVersion(uint verPacked)
|
||||
@@ -30,13 +39,39 @@ namespace WinDurango.UI
|
||||
return (major, minor, patch);
|
||||
}
|
||||
|
||||
private async Task InitializeLocalizer()
|
||||
{
|
||||
string StringsFolderPath = Path.Combine(AppContext.BaseDirectory, "Strings");
|
||||
StorageFolder stringsFolder = await StorageFolder.GetFolderFromPathAsync(StringsFolderPath);
|
||||
|
||||
ILocalizer localizer = await new LocalizerBuilder()
|
||||
.AddStringResourcesFolderForLanguageDictionaries(StringsFolderPath)
|
||||
.SetOptions(options =>
|
||||
{
|
||||
options.DefaultLanguage = "en-US";
|
||||
})
|
||||
.Build();
|
||||
}
|
||||
|
||||
private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
|
||||
{
|
||||
Logger.WriteException($"{e.Exception.GetType().FullName}: {e.Exception.Message}");
|
||||
}
|
||||
|
||||
public App()
|
||||
{
|
||||
this.UnhandledException += App_UnhandledException;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnLaunched(LaunchActivatedEventArgs args)
|
||||
public static void OnClosed(object sender, WindowEventArgs args)
|
||||
{
|
||||
Logger.WriteInformation("Exiting");
|
||||
}
|
||||
|
||||
protected override async void OnLaunched(LaunchActivatedEventArgs args)
|
||||
{
|
||||
await InitializeLocalizer();
|
||||
Logger.WriteDebug("Showing MainWindow");
|
||||
MainWindow.Activate();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace WinDurango.UI.Controls
|
||||
private string _Name;
|
||||
private string _Publisher;
|
||||
private string _Version;
|
||||
private Uri _Logo;
|
||||
|
||||
private async void HandleUnregister(object sender, SplitButtonClickEventArgs e)
|
||||
{
|
||||
@@ -56,12 +57,27 @@ namespace WinDurango.UI.Controls
|
||||
this.InitializeComponent();
|
||||
|
||||
_package = Packages.GetPackageByFamilyName(_familyName);
|
||||
_Name = _package.DisplayName ?? _package.Id.Name;
|
||||
try
|
||||
{
|
||||
_Name = _package.DisplayName ?? _package.Id.Name;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_Name = _package.Id.Name;
|
||||
}
|
||||
_Publisher = _package.PublisherDisplayName ?? _package.Id.PublisherId;
|
||||
_Version = $"{_package.Id.Version.Major.ToString() ?? "U"}.{_package.Id.Version.Minor.ToString() ?? "U"}.{_package.Id.Version.Build.ToString() ?? "U"}";
|
||||
string ss = Packages.getSplashScreenPath(_package);
|
||||
IReadOnlyList<AppListEntry> appListEntries = _package.GetAppListEntries();
|
||||
AppListEntry firstAppListEntry = appListEntries.FirstOrDefault();
|
||||
_Version = $"{_package.Id.Version.Major.ToString() ?? "U"}.{_package.Id.Version.Minor.ToString() ?? "U"}.{_package.Id.Version.Build.ToString() ?? "U"}.{_package.Id.Version.Revision.ToString() ?? "U"}";
|
||||
_Logo = _package.Logo;
|
||||
string ss = Packages.GetSplashScreenPath(_package);
|
||||
IReadOnlyList<AppListEntry> appListEntries = null;
|
||||
try
|
||||
{
|
||||
appListEntries = _package.GetAppListEntries();
|
||||
} catch
|
||||
{
|
||||
Logger.WriteWarning($"Could not get the applist entries of \"{_Name}\"");
|
||||
}
|
||||
AppListEntry firstAppListEntry = appListEntries?.FirstOrDefault() ?? null;
|
||||
|
||||
if (firstAppListEntry == null)
|
||||
Logger.WriteWarning($"Could not get the applist entry of \"{_Name}\"");
|
||||
@@ -80,13 +96,13 @@ namespace WinDurango.UI.Controls
|
||||
}
|
||||
else
|
||||
{
|
||||
BitmapImage logoImage = new(_package.Logo);
|
||||
BitmapImage logoImage = new(_Logo);
|
||||
appLogo.Source = logoImage;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
BitmapImage logoImage = new(_package.Logo);
|
||||
BitmapImage logoImage = new(_Logo);
|
||||
appLogo.Source = logoImage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,23 +9,7 @@
|
||||
SecondaryButtonText="Cancel"
|
||||
SecondaryButtonClick="hideDialog">
|
||||
<Grid>
|
||||
<ListView Name="appListView" ItemsSource="{x:Bind Pkgs}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<!-- This ups the crash chance by a whole lot.
|
||||
<Image Width="64" Height="64" Margin="5" ImageFailed="logoFailed">
|
||||
<Image.Source>
|
||||
<BitmapImage UriSource="{Binding Logo, TargetNullValue='ms-appx:///Assets/testimg.png', FallbackValue='ms-appx:///Assets/testimg.png'}" />
|
||||
</Image.Source>
|
||||
</Image> -->
|
||||
<StackPanel Orientation="Vertical" Margin="5">
|
||||
<TextBlock Text="{Binding DisplayName, TargetNullValue='Unknown', FallbackValue='Unknown'}" FontWeight="Bold" />
|
||||
<TextBlock Text="{Binding PublisherDisplayName, TargetNullValue='Unknown', FallbackValue='Unknown'}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<ListView x:Name="appListView" Loaded="AppListView_Loaded">
|
||||
</ListView>
|
||||
</Grid>
|
||||
</ContentDialog>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Text;
|
||||
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 WinDurango.UI.Settings;
|
||||
using WinDurango.UI.Utils;
|
||||
@@ -16,8 +18,6 @@ namespace WinDurango.UI.Dialogs
|
||||
|
||||
public AppListDialog(List<Package> packages, bool multiSelect = false)
|
||||
{
|
||||
Logger.WriteWarning($"AppList is very buggy atm, expect a crash.");
|
||||
|
||||
this.Pkgs = packages;
|
||||
|
||||
this.DataContext = this;
|
||||
@@ -30,8 +30,73 @@ namespace WinDurango.UI.Dialogs
|
||||
|
||||
}
|
||||
|
||||
private void AppListView_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var listView = (ListView)sender;
|
||||
|
||||
private void logoFailed(object sender, ExceptionRoutedEventArgs e)
|
||||
foreach (var pkg in Pkgs)
|
||||
{
|
||||
var item = new ListViewItem();
|
||||
item.MinWidth = 200;
|
||||
|
||||
var stackPanel = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal
|
||||
};
|
||||
|
||||
var packageLogo = new Image
|
||||
{
|
||||
Width = 64,
|
||||
Height = 64,
|
||||
Margin = new Thickness(5),
|
||||
Source = new BitmapImage(pkg.Logo ?? new Uri("ms-appx:///Assets/testimg.png"))
|
||||
};
|
||||
packageLogo.ImageFailed += LogoFailed;
|
||||
|
||||
var packageInfo = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Vertical,
|
||||
Margin = new Thickness(5)
|
||||
};
|
||||
|
||||
string displayName;
|
||||
try
|
||||
{
|
||||
displayName = pkg.DisplayName;
|
||||
}
|
||||
catch (System.Runtime.InteropServices.COMException)
|
||||
{
|
||||
displayName = pkg.Id.Name;
|
||||
}
|
||||
|
||||
var packageName = new TextBlock
|
||||
{
|
||||
Text = displayName ?? "Unknown",
|
||||
FontWeight = FontWeights.Bold
|
||||
};
|
||||
|
||||
var publisherName = new TextBlock
|
||||
{
|
||||
Text = pkg.PublisherDisplayName ?? "Unknown"
|
||||
};
|
||||
|
||||
packageInfo.Children.Add(packageName);
|
||||
packageInfo.Children.Add(publisherName);
|
||||
|
||||
stackPanel.Children.Add(packageLogo);
|
||||
stackPanel.Children.Add(packageInfo);
|
||||
|
||||
item.Content = stackPanel;
|
||||
|
||||
item.Tag = pkg;
|
||||
|
||||
listView.Items.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void LogoFailed(object sender, ExceptionRoutedEventArgs e)
|
||||
{
|
||||
var image = sender as Image;
|
||||
image.Source = new BitmapImage(new Uri("ms-appx:///Assets/testimg.png"));
|
||||
@@ -40,12 +105,17 @@ namespace WinDurango.UI.Dialogs
|
||||
|
||||
private void AddToAppList(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
foreach (Package package in appListView.SelectedItems)
|
||||
foreach (ListViewItem listViewItem in appListView.SelectedItems)
|
||||
{
|
||||
if (InstalledPackages.GetInstalledPackage(package.Id.FamilyName) == null)
|
||||
InstalledPackages.AddInstalledPackage(package);
|
||||
App.MainWindow.AppsListPage.InitAppList();
|
||||
var package = listViewItem.Tag as Package;
|
||||
if (package != null && package?.Id?.FamilyName != null)
|
||||
{
|
||||
if (InstalledPackages.GetInstalledPackage(package.Id.FamilyName) == null)
|
||||
InstalledPackages.AddInstalledPackage(package);
|
||||
}
|
||||
}
|
||||
|
||||
App.MainWindow.AppsListPage.InitAppList();
|
||||
}
|
||||
|
||||
private void hideDialog(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
|
||||
22
Dialogs/InstallConfirmationDialog.xaml
Normal file
22
Dialogs/InstallConfirmationDialog.xaml
Normal file
@@ -0,0 +1,22 @@
|
||||
<ContentDialog
|
||||
x:Class="WinDurango.UI.Dialogs.InstallConfirmationDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:WinDurango.UI.Dialogs"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Title="Confirm install"
|
||||
Style="{ThemeResource DefaultContentDialogStyle}"
|
||||
PrimaryButtonText="Install"
|
||||
SecondaryButtonText="Cancel">
|
||||
<Grid>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Name="packageLogo" MaxHeight="128" MaxWidth="128"></Image>
|
||||
<StackPanel Margin="10 0 0 0" Orientation="Vertical">
|
||||
<TextBlock Name="packageName" FontWeight="Bold" FontSize="18" TextWrapping="Wrap" MaxWidth="400"></TextBlock>
|
||||
<TextBlock Name="packagePublisher" TextWrapping="Wrap" MaxWidth="400"></TextBlock>
|
||||
<TextBlock Name="packageVersion" TextWrapping="Wrap" MaxWidth="400"></TextBlock>
|
||||
<TextBlock Name="packageLocation" TextWrapping="Wrap" MaxWidth="400"></TextBlock>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ContentDialog>
|
||||
43
Dialogs/InstallConfirmationDialog.xaml.cs
Normal file
43
Dialogs/InstallConfirmationDialog.xaml.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using WinDurango.UI.Utils;
|
||||
|
||||
namespace WinDurango.UI.Dialogs
|
||||
{
|
||||
public sealed partial class InstallConfirmationDialog : ContentDialog
|
||||
{
|
||||
public InstallConfirmationDialog(string manifest)
|
||||
{
|
||||
var properties = Packages.GetPropertiesFromManifest(manifest);
|
||||
string manifestFolder = manifest.Substring(0, manifest.Length - "AppxManifest.xml".Length);
|
||||
this.InitializeComponent();
|
||||
this.XamlRoot = App.MainWindow.Content.XamlRoot;
|
||||
packageName.Text = properties.DisplayName ?? "Unknown";
|
||||
packagePublisher.Text = properties.PublisherDisplayName ?? "Unknown";
|
||||
packageVersion.Text = "Unknown";
|
||||
packageLocation.Text = manifest;
|
||||
packageLogo.Source = new BitmapImage(new Uri(Path.Combine(manifestFolder, properties.Logo)));
|
||||
}
|
||||
|
||||
private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
}
|
||||
|
||||
private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Localization/Locale.cs
Normal file
16
Localization/Locale.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using WinDurango.UI.Utils;
|
||||
using WinUI3Localizer;
|
||||
|
||||
namespace WinDurango.UI.Localization
|
||||
{
|
||||
public static class Locale
|
||||
{
|
||||
public static string GetLocalizedText(string name, params object[] args)
|
||||
{
|
||||
return string.Format(name.GetLocalizedString(), args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ namespace WinDurango.UI
|
||||
public sealed partial class MainWindow : Window
|
||||
{
|
||||
public readonly string AppName = "WinDurango";
|
||||
public static readonly WdSettings Settings = new();
|
||||
public static readonly WdSettings Settings = App.Settings;
|
||||
public AppsListPage AppsListPage;
|
||||
public SettingsPage SettingsPage;
|
||||
public AboutPage AboutPage;
|
||||
@@ -89,6 +89,7 @@ namespace WinDurango.UI
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
Closed += App.OnClosed;
|
||||
Title = AppName;
|
||||
AppWindow.SetIcon("ms-appx:///Assets/icon.ico");
|
||||
this.Activate();
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
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}">
|
||||
mc:Ignorable="d">
|
||||
|
||||
<StackPanel Orientation="Vertical" Padding="10">
|
||||
<TextBlock Text="Application Info" FontSize="24"/>
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using CommunityToolkit.WinUI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.WebSockets;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Management.Deployment;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Pickers;
|
||||
@@ -12,6 +16,7 @@ using WinDurango.UI.Controls;
|
||||
using WinDurango.UI.Dialogs;
|
||||
using WinDurango.UI.Settings;
|
||||
using WinDurango.UI.Utils;
|
||||
using static WinDurango.UI.Localization.Locale;
|
||||
|
||||
namespace WinDurango.UI.Pages
|
||||
{
|
||||
@@ -43,7 +48,7 @@ namespace WinDurango.UI.Pages
|
||||
|
||||
private async void ShowAppListView(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AppListDialog dl = new(Packages.GetInstalledPackages().ToList());
|
||||
AppListDialog dl = new(Packages.GetInstalledPackages().ToList(), true);
|
||||
dl.Title = "Installed UWP apps";
|
||||
dl.XamlRoot = this.Content.XamlRoot;
|
||||
await dl.ShowAsync();
|
||||
@@ -51,7 +56,7 @@ namespace WinDurango.UI.Pages
|
||||
|
||||
private async void ShowInstalledEraApps(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AppListDialog dl = new(XHandler.getXPackages(Packages.GetInstalledPackages().ToList()), true);
|
||||
AppListDialog dl = new(XHandler.GetXPackages(Packages.GetInstalledPackages().ToList()), true);
|
||||
dl.Title = "Installed Era/XUWP apps";
|
||||
dl.XamlRoot = this.Content.XamlRoot;
|
||||
await dl.ShowAsync();
|
||||
@@ -69,7 +74,15 @@ namespace WinDurango.UI.Pages
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Stopwatch PlatinumWatch = new Stopwatch();
|
||||
|
||||
Logger.WriteDebug("Initializing AppsListPage...");
|
||||
|
||||
PlatinumWatch.Start();
|
||||
InitAppList();
|
||||
PlatinumWatch.Stop();
|
||||
|
||||
Logger.WriteDebug("Initialized AppsListPage in {0:D2}:{1:D2}:{2:D2}.{3:D3}", (int)PlatinumWatch.Elapsed.TotalHours, (int)PlatinumWatch.Elapsed.TotalMinutes, (int)PlatinumWatch.Elapsed.TotalSeconds, (int)PlatinumWatch.Elapsed.TotalMilliseconds);
|
||||
}
|
||||
|
||||
private async void InstallButton_Tapped(SplitButton sender, SplitButtonClickEventArgs args)
|
||||
@@ -93,7 +106,12 @@ namespace WinDurango.UI.Pages
|
||||
|
||||
if (File.Exists(manifest))
|
||||
{
|
||||
_ = await Packages.InstallPackageAsync(new Uri(manifest, UriKind.Absolute), (bool)addToAppListCheckBox.IsChecked);
|
||||
var dialog = new InstallConfirmationDialog(manifest);
|
||||
dialog.PrimaryButtonClick += async (sender, e) =>
|
||||
{
|
||||
_ = await Packages.InstallPackageAsync(new Uri(manifest, UriKind.Absolute), (bool)addToAppListCheckBox.IsChecked);
|
||||
};
|
||||
await dialog.ShowAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -103,19 +121,24 @@ namespace WinDurango.UI.Pages
|
||||
// there IS a mount folder
|
||||
if (File.Exists(Path.Combine(mountFolder + "\\AppxManifest.xml")))
|
||||
{
|
||||
await Packages.InstallXPackageAsync(folder.Path.ToString(), autoSymlinkCheckBox.IsEnabled && (bool)autoSymlinkCheckBox.IsChecked ? Packages.XvdMode.CreateSymlinks : Packages.XvdMode.DontUse, (bool)addToAppListCheckBox.IsChecked);
|
||||
var dialog = new InstallConfirmationDialog(Path.Combine(mountFolder + "\\AppxManifest.xml"));
|
||||
dialog.PrimaryButtonClick += async (sender, e) =>
|
||||
{
|
||||
await Packages.InstallXPackageAsync(folder.Path.ToString(), autoSymlinkCheckBox.IsEnabled && (bool)autoSymlinkCheckBox.IsChecked ? Packages.XvdMode.CreateSymlinks : Packages.XvdMode.DontUse, (bool)addToAppListCheckBox.IsChecked);
|
||||
};
|
||||
await dialog.ShowAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
// there is no AppxManifest inside.
|
||||
Logger.WriteError($"Could not find AppxManifest.xml in {folder.Path} and {mountFolder}");
|
||||
await new NoticeDialog($"AppxManifest does not exist in both {folder.Path} and {mountFolder}", "Error").Show();
|
||||
await new NoticeDialog(GetLocalizedText("ManifestNotFoundMulti", folder.Path, mountFolder), "Error").Show();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.WriteError($"Could not find AppxManifest.xml in {folder.Path} and no Mount folder exists");
|
||||
await new NoticeDialog($"AppxManifest does not exist in {folder.Path} and there is no \"Mount\" folder.", "Error").Show();
|
||||
await new NoticeDialog(GetLocalizedText("ManifestNotFoundNoMount", folder.Path), "Error").Show();
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
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}">
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Padding="10 10 10 10">
|
||||
<StackPanel Grid.Row="1">
|
||||
@@ -28,6 +27,7 @@
|
||||
</DropDownButton.Flyout>
|
||||
</DropDownButton>
|
||||
<TextBlock Margin="0 5 0 5" Text="Other"/>
|
||||
<ToggleSwitch OnContent="Enable debug logging" OffContent="Enable debug logging" Toggled="OnDebugLogToggled" Name="DebugLogToggle" Loaded="OnDebugLogToggleLoaded"/>
|
||||
<Button Name="appdataButton" Margin="0 5 0 5" Click="OpenAppData">Open WinDurango AppData folder</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using WinDurango.UI.Settings;
|
||||
|
||||
namespace WinDurango.UI.Pages
|
||||
@@ -10,36 +11,52 @@ namespace WinDurango.UI.Pages
|
||||
// should probably merge these into one?
|
||||
private async void OnMicaSelected(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await MainWindow.Settings.SetSetting("Theme", WdSettingsData.ThemeSetting.Mica);
|
||||
await App.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);
|
||||
await App.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);
|
||||
await App.Settings.SetSetting("Theme", WdSettingsData.ThemeSetting.Fluent);
|
||||
OnThemeButtonLoaded(sender, e);
|
||||
}
|
||||
|
||||
private async void OnSystemSelected(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await MainWindow.Settings.SetSetting("Theme", WdSettingsData.ThemeSetting.System);
|
||||
await App.Settings.SetSetting("Theme", WdSettingsData.ThemeSetting.System);
|
||||
OnThemeButtonLoaded(sender, e);
|
||||
}
|
||||
|
||||
private async void OnDebugLogToggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await App.Settings.SetSetting("DebugLoggingEnabled", (sender as ToggleSwitch).IsOn);
|
||||
}
|
||||
|
||||
private void OpenAppData(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Process.Start(new ProcessStartInfo(App.DataDir) { UseShellExecute = true });
|
||||
}
|
||||
|
||||
|
||||
private void OnDebugLogToggleLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
(sender as ToggleSwitch).IsEnabled = false;
|
||||
(sender as ToggleSwitch).IsOn = true;
|
||||
(sender as ToggleSwitch).OnContent = "Enable debug logging (currently debugging)";
|
||||
}
|
||||
}
|
||||
|
||||
private void OnThemeButtonLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
switch (MainWindow.Settings.Settings.Theme)
|
||||
switch (App.Settings.Settings.Theme)
|
||||
{
|
||||
case WdSettingsData.ThemeSetting.Fluent:
|
||||
themeButton.Content = "Fluent";
|
||||
|
||||
@@ -14,15 +14,16 @@ GUI for WinDurango, which is planned to allow for easy installing/patching among
|
||||
- [X] Allow for package removal from UI instead of just completely uninstalling.
|
||||
- [X] Installation options
|
||||
- [X] Scan for already installed EraOS/XUWP stuff
|
||||
- [ ] Allow for any existing installed package to be added to the applist
|
||||
- [X] Allow for any existing installed package to be added to the applist
|
||||
- [ ] Resize content to fit to screen
|
||||
- [ ] Allow for search
|
||||
|
||||
## Bugs/Improvements
|
||||
- [X] Make the applist not go offscreen (lol)
|
||||
- [ ] Once we have enough settings in place, make it have pages using a horizontal NavigationView (probably)
|
||||
- [ ] Applist pages
|
||||
- [ ] Fix icon in the titlebar
|
||||
- [ ] Fix UI load speed when loading a lot of packages on startup
|
||||
- [X] Applist scrolling
|
||||
- [X] Fix icon in the titlebar
|
||||
- [ ] Repo contributors on the about screen
|
||||
- [ ] Get Fluent Thin working
|
||||
- [ ] Add versioning to the InstalledPackages json (as in versioning the JSON file itself)
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using WinDurango.UI.Dialogs;
|
||||
using WinDurango.UI.Utils;
|
||||
|
||||
namespace WinDurango.UI.Settings;
|
||||
@@ -20,6 +21,7 @@ public class WdSettingsData
|
||||
|
||||
public uint SaveVersion { get; set; } = App.VerPacked;
|
||||
public ThemeSetting Theme { get; set; } = ThemeSetting.Fluent;
|
||||
public bool DebugLoggingEnabled { get; set; } = false;
|
||||
}
|
||||
|
||||
public class WdSettings
|
||||
@@ -44,8 +46,7 @@ public class WdSettings
|
||||
{
|
||||
if (loadedSettings.SaveVersion > App.VerPacked)
|
||||
{
|
||||
BackupSettings();
|
||||
GenerateSettings();
|
||||
ResetSettings();
|
||||
Logger.WriteInformation($"Settings were reset due to the settings file version being too new. ({loadedSettings.SaveVersion})");
|
||||
}
|
||||
loadedSettings = JsonSerializer.Deserialize<WdSettingsData>(json);
|
||||
@@ -65,6 +66,13 @@ public class WdSettings
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetSettings()
|
||||
{
|
||||
BackupSettings();
|
||||
GenerateSettings();
|
||||
Logger.WriteInformation($"Settings have been reset");
|
||||
}
|
||||
|
||||
private void BackupSettings()
|
||||
{
|
||||
string settingsBackup = _settingsFile + ".old_" + ((DateTimeOffset)DateTime.UtcNow).ToUnixTimeMilliseconds().ToString();
|
||||
|
||||
126
Strings/en-US/Controls.resw
Normal file
126
Strings/en-US/Controls.resw
Normal file
@@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="EDbgLog" xml:space="preserve">
|
||||
<value>Enable debug logging</value>
|
||||
</data>
|
||||
<data name="DDbgLog" xml:space="preserve">
|
||||
<value>Disable debug logging</value>
|
||||
</data>
|
||||
</root>
|
||||
143
Strings/en-US/Errors.resw
Normal file
143
Strings/en-US/Errors.resw
Normal file
@@ -0,0 +1,143 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ManifestNotFoundNoMount" xml:space="preserve">
|
||||
<value>AppxManifest does not exist in {0} and there is no "Mount" folder.</value>
|
||||
<comment>for when AppxManifest.xml is not found and there is no Mount folder to look in</comment>
|
||||
</data>
|
||||
<data name="MountNotFound" xml:space="preserve">
|
||||
<value>{0} was not found.</value>
|
||||
</data>
|
||||
<data name="ManifestNotFoundMulti" xml:space="preserve">
|
||||
<value>AppxManifest does not exist in {0} and {1}</value>
|
||||
<comment>for when it's not found in either the Mount folder or current chosen folder</comment>
|
||||
</data>
|
||||
<data name="NotFound" xml:space="preserve">
|
||||
<value>{0} was not found.</value>
|
||||
</data>
|
||||
<data name="AlreadyInstalled" xml:space="preserve">
|
||||
<value>{0} is already installed.</value>
|
||||
</data>
|
||||
<data name="PackageInstallFailedEx" xml:space="preserve">
|
||||
<value>{0} failed to install: {1}</value>
|
||||
</data>
|
||||
<data name="PackageUninstallFailedEx" xml:space="preserve">
|
||||
<value>Failed to uninstall {0}: {1}</value>
|
||||
</data>
|
||||
</root>
|
||||
144
Strings/en-US/Resources.resw
Normal file
144
Strings/en-US/Resources.resw
Normal file
@@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ReadingManifest" xml:space="preserve">
|
||||
<value>Reading manifest...</value>
|
||||
</data>
|
||||
<data name="CheckingInstallStatus" xml:space="preserve">
|
||||
<value>Checking if {0} is already installed...</value>
|
||||
</data>
|
||||
<data name="InstallingPackage" xml:space="preserve">
|
||||
<value>Installing {0}...</value>
|
||||
</data>
|
||||
<data name="GettingAppInfo" xml:space="preserve">
|
||||
<value>Getting app info...</value>
|
||||
</data>
|
||||
<data name="UpdatingAppList" xml:space="preserve">
|
||||
<value>Updating app list...</value>
|
||||
</data>
|
||||
<data name="PackageInstalled" xml:space="preserve">
|
||||
<value>{0} was installed! :)</value>
|
||||
</data>
|
||||
<data name="UninstallingPackage" xml:space="preserve">
|
||||
<value>Uninstalling {0}...</value>
|
||||
</data>
|
||||
<data name="PackageUninstalled" xml:space="preserve">
|
||||
<value>{0} was uninstalled.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -40,8 +40,16 @@ namespace WinDurango.UI.Utils
|
||||
throw e;
|
||||
}
|
||||
|
||||
public static void WriteException(string str)
|
||||
{
|
||||
Instance.WriteLog(LogLevel.Exception, str);
|
||||
}
|
||||
|
||||
private void WriteLog(LogLevel level, string message)
|
||||
{
|
||||
if (level == LogLevel.Debug && !App.Settings.Settings.DebugLoggingEnabled && !Debugger.IsAttached)
|
||||
return;
|
||||
|
||||
string logEntry = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] [{level.ToString().ToUpper()}] {message}";
|
||||
Debug.WriteLine(logEntry);
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ using Windows.ApplicationModel;
|
||||
using Windows.Management.Deployment;
|
||||
using WinDurango.UI.Dialogs;
|
||||
using WinDurango.UI.Settings;
|
||||
|
||||
using WinUI3Localizer;
|
||||
using static WinDurango.UI.Localization.Locale;
|
||||
|
||||
namespace WinDurango.UI.Utils
|
||||
{
|
||||
@@ -24,6 +25,32 @@ namespace WinDurango.UI.Utils
|
||||
return pm.FindPackagesForUser(sid);
|
||||
}
|
||||
|
||||
public static (string? DisplayName, string? PublisherDisplayName, string? Logo, string? Description) GetPropertiesFromManifest(string manifestPath)
|
||||
{
|
||||
if (!File.Exists(manifestPath))
|
||||
return (null, null, null, 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, null, null, null);
|
||||
|
||||
XElement properties = package.Descendants().FirstOrDefault(e => e.Name.LocalName == "Properties");
|
||||
if (properties == null) return (null, null, null, null);
|
||||
|
||||
string logo = properties?.Descendants().FirstOrDefault(e => e.Name.LocalName == "Logo").Value ?? null;
|
||||
string displayName = properties?.Descendants().FirstOrDefault(e => e.Name.LocalName == "DisplayName").Value ?? null;
|
||||
string publisherDisplayName = properties?.Descendants().FirstOrDefault(e => e.Name.LocalName == "PublisherDisplayName").Value ?? null;
|
||||
string description = properties?.Descendants()?.FirstOrDefault(e => e.Name.LocalName == "Description")?.Value ?? null;
|
||||
return (displayName, publisherDisplayName, logo, description);
|
||||
}
|
||||
|
||||
public enum XvdMode
|
||||
{
|
||||
CreateSymlinks,
|
||||
@@ -39,7 +66,7 @@ namespace WinDurango.UI.Utils
|
||||
|
||||
if (!Directory.Exists(mountDir))
|
||||
{
|
||||
await new NoticeDialog($"{mountDir} was not found.", "Error").Show();
|
||||
await new NoticeDialog(GetLocalizedText($"mountNotFound", mountDir), "Error").Show();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -66,10 +93,9 @@ namespace WinDurango.UI.Utils
|
||||
}
|
||||
}
|
||||
|
||||
public static string getSplashScreenPath(Package pkg)
|
||||
public static string GetSplashScreenPath(Package pkg)
|
||||
{
|
||||
try
|
||||
{
|
||||
try {
|
||||
string installPath = pkg.InstalledPath;
|
||||
string manifestPath = Path.Combine(installPath, "AppxManifest.xml");
|
||||
|
||||
@@ -119,7 +145,7 @@ namespace WinDurango.UI.Utils
|
||||
// TODO: strip UI
|
||||
if (!File.Exists(manifestPath))
|
||||
{
|
||||
await new NoticeDialog($"{manifestPath} was not found.", "Error").Show();
|
||||
await new NoticeDialog(GetLocalizedText("NotFound", manifestPath), "Error").Show();
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -131,7 +157,7 @@ namespace WinDurango.UI.Utils
|
||||
try
|
||||
{
|
||||
Logger.WriteInformation($"Reading manifest...");
|
||||
status.Text = "Reading manifest...";
|
||||
status.Text = "ReadingManifest".GetLocalizedString();
|
||||
string manifest;
|
||||
await using (var stream = File.OpenRead(manifestPath))
|
||||
{
|
||||
@@ -147,7 +173,7 @@ namespace WinDurango.UI.Utils
|
||||
string pkgPublisher = identity.Attribute("Publisher")?.Value;
|
||||
|
||||
status.Progress = 20.0;
|
||||
status.Text = $"Checking if {pkgName} is already installed...";
|
||||
status.Text = GetLocalizedText("CheckingInstallStatus", pkgName);
|
||||
var sid = WindowsIdentity.GetCurrent().User?.Value;
|
||||
var installedPackages = await Task.Run(() => pm.FindPackagesForUser(sid, pkgName, pkgPublisher));
|
||||
|
||||
@@ -155,24 +181,24 @@ namespace WinDurango.UI.Utils
|
||||
{
|
||||
status.Hide();
|
||||
Logger.WriteError($"{pkgName} is already installed.");
|
||||
await new NoticeDialog($"{pkgName} is already installed.", "Error").Show();
|
||||
await new NoticeDialog(GetLocalizedText("AlreadyInstalled", pkgName), "Error").Show();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
status.Progress = 40.0;
|
||||
status.Text = $"Installing {pkgName}...";
|
||||
status.Text = GetLocalizedText("InstallingPackage", pkgName);
|
||||
Logger.WriteInformation($"Registering...");
|
||||
var deployment = await pm.RegisterPackageAsync(appxManifestUri, null, DeploymentOptions.DevelopmentMode);
|
||||
|
||||
status.Progress = 60.0;
|
||||
|
||||
status.Text = $"Getting app info...";
|
||||
status.Text = "GettingAppInfo".GetLocalizedString();
|
||||
var recentPkg = GetMostRecentlyInstalledPackage();
|
||||
|
||||
if (addInstalledPackage)
|
||||
{
|
||||
status.Text = $"Updating app list...";
|
||||
status.Text = $"UpdatingAppList".GetLocalizedString();
|
||||
status.Progress = 80.0;
|
||||
InstalledPackages.AddInstalledPackage(recentPkg);
|
||||
status.Progress = 90.0;
|
||||
@@ -186,7 +212,7 @@ namespace WinDurango.UI.Utils
|
||||
|
||||
status.Hide();
|
||||
Logger.WriteInformation($"{recentPkg.Id.Name} was installed.");
|
||||
await new NoticeDialog($"{recentPkg.Id.Name} was installed! :)").Show();
|
||||
await new NoticeDialog(GetLocalizedText("PackageInstalled", recentPkg.Id.Name)).Show();
|
||||
return recentPkg.Id.FamilyName;
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -195,7 +221,7 @@ namespace WinDurango.UI.Utils
|
||||
status.Hide();
|
||||
Logger.WriteError($"{appxManifestUri} failed to install");
|
||||
Logger.WriteException(e);
|
||||
await new NoticeDialog($"{appxManifestUri} failed to install: {e.Message}", "Error").Show();
|
||||
await new NoticeDialog(GetLocalizedText("PackageInstallFailedEx", appxManifestUri, e.Message), "Error").Show();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -203,7 +229,7 @@ namespace WinDurango.UI.Utils
|
||||
public static async Task RemovePackage(Package package)
|
||||
{
|
||||
Logger.WriteError($"Uninstalling {package.DisplayName}...");
|
||||
var status = new ProgressDialog($"Uninstalling {package.DisplayName}...", "Uninstalling", false);
|
||||
var status = new ProgressDialog(GetLocalizedText("UninstallingPackage", package.DisplayName), "Uninstalling", false);
|
||||
_ = App.MainWindow.DispatcherQueue.TryEnqueue(async () => await status.ShowAsync());
|
||||
PackageManager pm = new();
|
||||
try
|
||||
@@ -214,8 +240,8 @@ namespace WinDurango.UI.Utils
|
||||
InstalledPackages.RemoveInstalledPackage(package);
|
||||
status.Progress = 100.0;
|
||||
status.Hide();
|
||||
Logger.WriteError($"{package.DisplayName} was uninstalled.");
|
||||
await new NoticeDialog($"{package.DisplayName} was uninstalled.").Show();
|
||||
Logger.WriteInformation($"{package.DisplayName} was uninstalled.");
|
||||
await new NoticeDialog(GetLocalizedText("PackageUninstalled", package.DisplayName)).Show();
|
||||
App.MainWindow.ReloadAppList();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -223,7 +249,7 @@ namespace WinDurango.UI.Utils
|
||||
status.Hide();
|
||||
Logger.WriteError($"{package.DisplayName} failed to uninstall");
|
||||
Logger.WriteException(ex);
|
||||
await new NoticeDialog($"{package.DisplayName} failed to uninstall: {ex.Message}", "Error!").Show();
|
||||
await new NoticeDialog(GetLocalizedText("PackageUninstallFailedEx", package.DisplayName, e.Message), "Error!").Show();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Windows.ApplicationModel.DynamicDependency;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
@@ -8,8 +9,55 @@ namespace WinDurango.UI.Utils
|
||||
{
|
||||
public class XHandler
|
||||
{
|
||||
public static List<Package> getXPackages(List<Package> packages)
|
||||
// unused because sucks
|
||||
public static (string? DisplayName, string? Description, string? SplashScreen, string? SmallLogo, string? WideLogo, string? Logo) GetVisualElementsInfo(Package package)
|
||||
{
|
||||
string installPath = package.InstalledPath;
|
||||
string manifestPath = Path.Combine(installPath, "AppxManifest.xml");
|
||||
|
||||
if (!File.Exists(manifestPath))
|
||||
return (null, null, null, null, null, null);
|
||||
|
||||
string manifest;
|
||||
using (var stream = File.OpenRead(manifestPath))
|
||||
{
|
||||
var reader = new StreamReader(stream);
|
||||
manifest = reader.ReadToEnd();
|
||||
}
|
||||
|
||||
XDocument doc = XDocument.Parse(manifest);
|
||||
XElement xmlPackage = doc.Descendants().FirstOrDefault(e => e.Name.LocalName == "Package");
|
||||
XElement application = xmlPackage?.Descendants().LastOrDefault(e => e.Name.LocalName == "Application");
|
||||
XElement visualElements = application?.Descendants().FirstOrDefault(e => e.Name.LocalName == "VisualElements");
|
||||
if (visualElements == null)
|
||||
return (null, null, null, null, null, null);
|
||||
|
||||
XElement ss = visualElements?.Descendants().FirstOrDefault(e => e.Name.LocalName == "SplashScreen") ?? null;
|
||||
XElement defaultTile = visualElements?.Descendants().FirstOrDefault(e => e.Name.LocalName == "DefaultTile") ?? null;
|
||||
|
||||
// holy hell this is ew
|
||||
|
||||
string? DisplayName = visualElements?.Attribute("DisplayName")?.Value ?? null;
|
||||
string? Description = visualElements?.Attribute("Description")?.Value ?? null;
|
||||
string? SplashScreen = ss?.Attribute("SplashScreen")?.Value ?? null;
|
||||
string? SmallLogo = visualElements?.Attribute("SmallLogo")?.Value ?? null;
|
||||
string? WideLogo = defaultTile?.Attribute("WideLogo")?.Value ?? null;
|
||||
string? Logo = visualElements?.Attribute("Logo")?.Value ?? null;
|
||||
|
||||
return (
|
||||
DisplayName == null || DisplayName.StartsWith("ms-resource:") ? null : DisplayName,
|
||||
Description == null || Description.StartsWith("ms-resource:") ? null : Description,
|
||||
SplashScreen == null || SplashScreen.StartsWith("ms-resource:") ? null : SplashScreen,
|
||||
SmallLogo == null || SmallLogo.StartsWith("ms-resource:") ? null : SmallLogo,
|
||||
WideLogo == null || WideLogo.StartsWith("ms-resource:") ? null : WideLogo,
|
||||
Logo == null || Logo.StartsWith("ms-resource:") ? null : Logo
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public static List<Package> GetXPackages(List<Package> packages)
|
||||
{
|
||||
// first try implementation and it worked hell yeah
|
||||
List<Package> result = new();
|
||||
foreach (Package package in packages)
|
||||
{
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
<None Remove="Controls\ContributorInfo.xaml" />
|
||||
<None Remove="Controls\NewFile1.txt" />
|
||||
<None Remove="Dialogs\AppListDialog.xaml" />
|
||||
<None Remove="Dialogs\InstallConfirmationDialog.xaml" />
|
||||
<None Remove="Pages\AboutPage.xaml" />
|
||||
<None Remove="Pages\AppsListPage.xaml" />
|
||||
<None Remove="Pages\SettingsPage.xaml" />
|
||||
@@ -52,6 +53,7 @@
|
||||
<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" />
|
||||
<PackageReference Include="WinUI3Localizer" Version="2.2.0" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -92,10 +94,26 @@
|
||||
<EditorConfigFiles Remove="D:\Projects\Dev\C#\WinDurango.UI\.editorconfig" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Strings\**\*.resw">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="Strings\en-US\Errors.resw" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="D:\Projects\Dev\C#\WinDurango.UI\.editorconfig" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Dialogs\InstallConfirmationDialog.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Dialogs\AppListDialog.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
||||
Reference in New Issue
Block a user