Save manager (needs improvement)

This commit is contained in:
Dexrn ZacAttack
2025-02-26 05:18:32 -08:00
parent 3535dfd03f
commit c0822f7735
14 changed files with 629 additions and 59 deletions

View File

@@ -83,7 +83,7 @@ namespace WinDurango.UI.Controls
private async void ShowSaveManager(object sender, RoutedEventArgs e)
{
PageDialog pgd = new PageDialog(typeof(NotImplementedPage), null, $"{_package.DisplayName} saves");
PageDialog pgd = new PageDialog(typeof(SaveManagerPage), _familyName, $"{_package.DisplayName} saves");
pgd.XamlRoot = App.MainWindow.Content.XamlRoot;
await pgd.ShowAsync();
}
@@ -117,6 +117,7 @@ namespace WinDurango.UI.Controls
App.MainWindow.ReloadAppList();
}
// BUG: calling second time after failure does not show the failure dialog?
private async void PatchPackage(object sender, RoutedEventArgs args)
{
var progress = new ProgressDialog($"Patching {_Name}...", $"Patching {_Name}", isIndeterminate: true).GetController();

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<UserControl
x:Class="WinDurango.UI.Controls.ContainerInfo"
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">
<ScrollViewer>
<Grid Background="{ThemeResource AcrylicBackgroundFillColorBaseBrush}" Padding="10, 10, 10, 10" CornerRadius="5" Margin="0, 0, 0, 10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Name="containerInfo">
<TextBlock x:Name="name" FontSize="20" TextWrapping="Wrap">Name</TextBlock>
<TextBlock x:Name="folderName">Folder Name</TextBlock>
<TextBlock x:Name="folderSize" Margin="0, 10, 0, 0">0B</TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Column="1">
<Button x:Name="deleteButton" ToolTipService.ToolTip="Delete" Click="DeleteContainer" Margin="10, 0, 0, 10" HorizontalAlignment="Right">
<SymbolIcon Symbol="Delete"></SymbolIcon>
</Button>
<Button x:Name="renameButton" ToolTipService.ToolTip="Rename container" Click="renameButton_Click" Margin="10, 0, 0, 10" HorizontalAlignment="Right">
<SymbolIcon Symbol="Rename"></SymbolIcon>
</Button>
<Button x:Name="folderButton" ToolTipService.ToolTip="View folder" Click="ViewFolder" Margin="10, 0, 0, 10" HorizontalAlignment="Right">
<SymbolIcon Symbol="Folder"></SymbolIcon>
</Button>
</StackPanel>
</Grid>
</ScrollViewer>
</UserControl>

View File

@@ -0,0 +1,201 @@
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 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.Navigation;
using WinDurango.UI.Utils;
using System.Diagnostics;
using WinDurango.UI.Pages.Dialog;
namespace WinDurango.UI.Controls
{
public sealed partial class ContainerInfo : UserControl
{
private string _folder;
private DirectoryInfo _dir;
private string _displayName;
private bool _isContainer;
public ContainerInfo(string folder, string displayName, bool isContainer = false)
{
this.InitializeComponent();
this._isContainer = isContainer;
this._folder = folder;
this._dir = new DirectoryInfo(_folder);
this._displayName = displayName;
// could allow for folders to be renamed but user can do that (not like they can't change the text in the file but atleast it's slightly more user friendly this way)
if (!isContainer)
this.renameButton.Visibility = Visibility.Collapsed;
this.name.Text = _displayName;
string folderName = Path.GetFileName(_folder);
if (folderName == _displayName)
{
this.folderName.Visibility = Visibility.Collapsed;
}
Logger.WriteDebug(folderName);
this.folderName.Text = Path.GetFileName(_folder);
long dirSize = _dir.GetDirectorySize();
// can't wait for the funny inaccuracy as windows probably uses some weird KiB type or whatever
this.folderSize.Text = dirSize.GetSizeString();
ToolTipService.SetToolTip(this.folderName, folderName);
ToolTipService.SetToolTip(this.name, _displayName);
ToolTipService.SetToolTip(this.folderSize, $"{dirSize} bytes");
}
private void DeleteContainer(object sender, RoutedEventArgs e)
{
Flyout flyout = new Flyout();
TextBlock title = new TextBlock { Text = $"Are you sure you want to delete {_displayName}?" };
TextBlock info = new TextBlock { Text = $"This save will be deleted from the disk and may not be recoverable." };
title.Style = (Style)Application.Current.Resources["BaseTextBlockStyle"];
Button button = new Button();
button.Content = "Delete";
button.Margin = new Thickness(0, 10, 0, 0);
button.Click += (s, e) =>
{
flyout.Hide();
var parent = VisualTreeHelper.GetParent(this);
while (parent != null && !(parent is SaveManagerPage))
{
parent = VisualTreeHelper.GetParent(parent);
}
if (parent != null)
{
SaveManagerPage smParent = (SaveManagerPage)parent;
try
{
Directory.Delete(_folder, true);
} catch (Exception ex)
{
smParent.ShowInfo($"Failed to delete {_displayName}", $"{ex.Message}", InfoBarSeverity.Error);
return;
}
smParent.RemoveElement(this);
}
};
flyout.Content = new StackPanel
{
Children =
{
title,
info,
button
}
};
flyout.ShowAt((Button)sender);
}
private void ViewFolder(object sender, RoutedEventArgs e)
{
try
{
FSHelper.OpenFolder(_folder);
}
catch (Exception ex)
{
var parent = VisualTreeHelper.GetParent(this);
while (parent != null && !(parent is SaveManagerPage))
{
parent = VisualTreeHelper.GetParent(parent);
}
if (parent != null)
((SaveManagerPage)parent).ShowInfo($"Couldn't open folder {Path.GetFileName(_folder)}", $"{ex.Message}", InfoBarSeverity.Error);
Logger.WriteError($"Couldn't open container folder path {_folder}");
Logger.WriteException(ex);
}
}
private void RenameContainer(string name)
{
string path = Path.Combine(_folder, "wd_displayname.txt");
if (File.Exists(path))
{
File.WriteAllText(path, name);
this._displayName = name;
this.name.Text = _displayName;
}
}
private void rename(object sender, RoutedEventArgs e)
{
var parent = VisualTreeHelper.GetParent(this);
while (parent != null && !(parent is SaveManagerPage))
{
parent = VisualTreeHelper.GetParent(parent);
}
if (parent != null)
{
SaveManagerPage smParent = (SaveManagerPage)parent;
try
{
RenameContainer(((TextBox)sender).Text);
}
catch (Exception ex)
{
smParent.ShowInfo($"Failed to rename {_displayName}", $"{ex.Message}", InfoBarSeverity.Error);
return;
}
}
}
private void renameButton_Click(object sender, RoutedEventArgs e)
{
Flyout flyout = new Flyout();
TextBlock title = new TextBlock { Text = $"Rename {_displayName}" };
TextBox box = new TextBox();
Button button = new Button();
box.KeyDown += (sender, e) =>
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
flyout.Hide();
rename(sender, e);
}
};
title.Style = (Style)Application.Current.Resources["BaseTextBlockStyle"];
button.Content = "Rename";
button.Margin = new Thickness(0, 10, 0, 0);
button.Click += (sender, e) =>
{
flyout.Hide();
rename(button, new RoutedEventArgs());
};
flyout.Content = new StackPanel
{
Children =
{
title,
new StackPanel
{
Children = {
box,
button
}
}
}
};
flyout.ShowAt((Button)sender);
}
}
}

View File

@@ -5,6 +5,7 @@ using Microsoft.UI.Xaml.Media.Imaging;
using System;
using System.Collections.Generic;
using Windows.ApplicationModel;
using WinDurango.UI.Utils;
using Image = Microsoft.UI.Xaml.Controls.Image;
namespace WinDurango.UI.Dialogs
@@ -44,12 +45,23 @@ namespace WinDurango.UI.Dialogs
Orientation = Orientation.Horizontal
};
// NOTE: DO NOT TOUCH THIS MAGICAL SHIT
// it throws massive error if the image is invalid somehow or whatever...
Uri pkLogo = null;
try
{
pkLogo = pkg.Logo;
} catch (Exception ex) {
Logger.WriteError($"pkg.Logo threw {ex.GetType().ToString()} for {pkg.Id.FamilyName}");
Logger.WriteException(ex);
}
var packageLogo = new Image
{
Width = 64,
Height = 64,
Margin = new Thickness(5),
Source = new BitmapImage(pkg.Logo)
Source = new BitmapImage(pkLogo ?? new Uri("ms-appx:///Assets/testimg.png"))
};
//packageLogo.ImageFailed += LogoFailed;

View File

@@ -1,4 +1,5 @@
using System;
using System.Drawing;
using System.Threading.Tasks;
using WinDurango.UI.Utils;
@@ -46,8 +47,11 @@ namespace WinDurango.UI.Dialogs
_dialog.DispatcherQueue.TryEnqueue(async () =>
{
_dialog.Hide();
NoticeDialog oops = new NoticeDialog(title, reason);
await oops.ShowAsync();
_dialog.Closed += async (sender, e) =>
{
NoticeDialog oops = new NoticeDialog(title, reason);
await oops.ShowAsync();
};
});
}
@@ -58,8 +62,11 @@ namespace WinDurango.UI.Dialogs
_dialog.DispatcherQueue.TryEnqueue(async () =>
{
_dialog.Hide();
NoticeDialog oops = new NoticeDialog(title, ex.Message);
await oops.ShowAsync();
_dialog.Closed += async (sender, e) =>
{
NoticeDialog oops = new NoticeDialog(title, ex.Message);
await oops.ShowAsync();
};
});
}
@@ -86,7 +93,7 @@ namespace WinDurango.UI.Dialogs
public async Task Create(Action action)
{
_dialog.ShowAsync();
_ = _dialog.ShowAsync();
try
{
action();
@@ -102,7 +109,7 @@ namespace WinDurango.UI.Dialogs
public async Task CreateAsync(Func<Task> action)
{
_dialog.ShowAsync();
_ = _dialog.ShowAsync();
try
{
await action();

View File

@@ -29,18 +29,28 @@ namespace WinDurango.UI.Pages
foreach (installedPackage installedPackage in installedPackages)
{
// TODO: add handling for that annoying invalid logo stuff
if (pm.FindPackageForUser(WindowsIdentity.GetCurrent().User?.Value, installedPackage.FullName) != null)
{
Grid outerGrid = new();
AppTile gameContainer = new(installedPackage.FamilyName);
this.DispatcherQueue.TryEnqueue(() =>
try
{
outerGrid.Children.Add(gameContainer);
appList.Children.Add(outerGrid);
});
Logger.WriteDebug($"Added {installedPackage.FamilyName} to the app list");
Grid outerGrid = new();
AppTile gameContainer = new(installedPackage.FamilyName);
this.DispatcherQueue.TryEnqueue(() =>
{
outerGrid.Children.Add(gameContainer);
appList.Children.Add(outerGrid);
});
Logger.WriteDebug($"Added {installedPackage.FamilyName} to the app list");
}
catch (Exception ex)
{
// maybe should have infobar on app list?
Logger.WriteError($"Failed to add {installedPackage.FamilyName} to the app list: {ex.Message}");
Logger.WriteException(ex);
}
}
else
{
@@ -102,7 +112,7 @@ namespace WinDurango.UI.Pages
*/
}
// needs to be fixed
// needs to be cleaned
private async void InstallButton_Tapped(SplitButton sender, SplitButtonClickEventArgs args)
{
var picker = new FolderPicker
@@ -129,7 +139,7 @@ namespace WinDurango.UI.Pages
{
dialog.Hide();
var controller = new ProgressDialog("Starting installation...", $"Installing {Packages.GetPropertiesFromManifest(manifest).DisplayName}", isIndeterminate: false).GetController();
controller.CreateAsync(async () =>
_ = controller.CreateAsync(async () =>
{
await Packages.InstallPackageAsync(new Uri(manifest, UriKind.Absolute), controller,
(bool)addToAppListCheckBox.IsChecked);
@@ -150,7 +160,7 @@ namespace WinDurango.UI.Pages
{
dialog.Hide();
var controller = new ProgressDialog("Starting installation...", "Installing", isIndeterminate: false).GetController();
controller.CreateAsync(async () =>
_ = controller.CreateAsync(async () =>
{
await Packages.InstallXPackageAsync(folder.Path.ToString(), controller,
(bool)addToAppListCheckBox.IsChecked);

View File

@@ -6,22 +6,26 @@
xmlns:local="using:WinDurango.UI.Pages.Dialog"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
mc:Ignorable="d"
xmlns:ct="using:CommunityToolkit.WinUI.Controls">
<Grid>
<ScrollViewer>
<StackPanel>
<StackPanel Name="cModList">
<TextBlock Name="noModsFolder" Visibility="Collapsed">
<ct:DockPanel>
<ScrollViewer ct:DockPanel.Dock="Top" MaxHeight="400">
<StackPanel Name="cModList">
<TextBlock Name="noModsFolder" Visibility="Collapsed">
Mods directory hasn't been created yet.
<LineBreak/>Click "View mods folder" to create one.
</TextBlock>
<TextBlock Name="noMods" Visibility="Collapsed">No mods found.</TextBlock>
<StackPanel Name="modList"></StackPanel>
</StackPanel>
<Button HorizontalAlignment="Right" Margin="0, 5, 0, 0" Content="Open mods folder" Name="openModsFolder" Click="OpenModsFolder"></Button>
<Button HorizontalAlignment="Right" Margin="0, 5, 0, 0" Content="Create mods folder" Name="createModsFolder" Click="CreateModsFolder" Visibility="Collapsed"></Button>
</TextBlock>
<TextBlock Name="noMods" Visibility="Collapsed">No mods found.</TextBlock>
<StackPanel Name="modList"></StackPanel>
</StackPanel>
</ScrollViewer>
<StackPanel ct:DockPanel.Dock="Bottom" HorizontalAlignment="Right" Orientation="Horizontal" Margin="0, 10, 0, 0">
<StackPanel Name="infoBar" ct:DockPanel.Dock="Left" Orientation="Horizontal" Margin="0, 0, 10, 0"/>
<Button Content="Open mods folder" Name="openModsFolder" Click="OpenModsFolder"></Button>
<Button Content="Create mods folder" Name="createModsFolder" Click="CreateModsFolder" Visibility="Collapsed"></Button>
</StackPanel>
</ScrollViewer>
</ct:DockPanel>
</Grid>
</Page>

View File

@@ -5,6 +5,7 @@ using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Windows.ApplicationModel.DataTransfer;
using WinDurango.UI.Controls;
using WinDurango.UI.Utils;
@@ -74,29 +75,40 @@ namespace WinDurango.UI.Pages.Dialog
}
}
private void ShowInfo(string error)
// LATER: make this common
public void ShowInfo(string title, string message, InfoBarSeverity severity = InfoBarSeverity.Informational)
{
Visibility nmLastState = noMods.Visibility;
Visibility nmfLastState = noModsFolder.Visibility;
noMods.Visibility = Visibility.Collapsed;
noModsFolder.Visibility = Visibility.Collapsed;
InfoBar info = new InfoBar();
TextBlock text = new TextBlock();
text.Text = error;
info.IsOpen = true;
info.Content = text;
info.MaxWidth = this.ActualWidth;
text.TextWrapping = TextWrapping.WrapWholeWords;
info.Closed += (InfoBar sender, InfoBarClosedEventArgs args) =>
this.infoBar.Children.Clear();
double width = this.ActualWidth;
if (width == 0)
{
noMods.Visibility = nmLastState;
noModsFolder.Visibility = nmfLastState;
width = this.Frame.ActualWidth;
}
InfoBar infoBar = new InfoBar();
Button copyButton = new Button();
SymbolIcon symbolIcon = new SymbolIcon(Symbol.Copy);
copyButton.Content = symbolIcon;
copyButton.HorizontalAlignment = HorizontalAlignment.Right;
copyButton.Click += (sender, e) =>
{
DataPackage dp = new DataPackage();
dp.SetText(message);
Windows.ApplicationModel.DataTransfer.Clipboard.SetContent(dp);
};
cModList.Children.Insert(0, info);
infoBar.Severity = severity;
infoBar.IsOpen = true;
infoBar.Message = message;
infoBar.Title = title;
infoBar.ActionButton = copyButton;
infoBar.MaxWidth = this.ActualWidth;
Logger.WriteInformation(message);
this.infoBar.Children.Add(infoBar);
}
private void CreateModsFolder(object sender, RoutedEventArgs e)
@@ -117,7 +129,7 @@ namespace WinDurango.UI.Pages.Dialog
}
catch (Exception ex)
{
ShowInfo($"Couldn't create mod folder\n{ex.Message}");
ShowInfo("Couldn't create mod folder", $"{ex.Message}", InfoBarSeverity.Error);
Logger.WriteError($"Couldn't create mod folder {_modsPath}");
Logger.WriteException(ex);
}
@@ -134,7 +146,7 @@ namespace WinDurango.UI.Pages.Dialog
}
catch (Exception ex)
{
ShowInfo($"Couldn't open mod folder\n{ex.Message}");
ShowInfo($"Couldn't open mod folder", $"{ex.Message}", InfoBarSeverity.Error);
Logger.WriteError($"Couldn't open mod folder path {_modsPath}");
Logger.WriteException(ex);
}

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<Page
x:Class="WinDurango.UI.Pages.Dialog.SaveManagerPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WinDurango.UI.Pages.Dialog"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:ct="using:CommunityToolkit.WinUI.Controls">
<Grid>
<ct:DockPanel>
<ScrollViewer ct:DockPanel.Dock="Top" MaxHeight="400">
<StackPanel Name="saveContainer">
<TextBlock Name="noSavesHeader" Text="No saves found." Margin="0, 0, 0, 10" Visibility="Collapsed"></TextBlock>
<TextBlock Name="containerHeader" Text="Containers" FontSize="18" FontWeight="Bold" Margin="0, 0, 0, 10" Visibility="Collapsed"></TextBlock>
<StackPanel Name="containerList">
<TextBlock>Loading...</TextBlock>
</StackPanel>
<TextBlock Name="folderHeader" Text="Folders" FontSize="18" FontWeight="Bold" Margin="0, 0, 0, 10" Visibility="Collapsed"></TextBlock>
<StackPanel Name="folderList">
<TextBlock>Loading...</TextBlock>
</StackPanel>
</StackPanel>
</ScrollViewer>
<ct:DockPanel ct:DockPanel.Dock="Bottom" Name="bottomBar" Margin="0, 10, 0, 0">
<!-- For some reason this pushes the folderList to the side a little -->
<StackPanel Name="infoBar" HorizontalAlignment="Right" ct:DockPanel.Dock="Left" Orientation="Horizontal" Margin="0, 0, 10, 0"/>
<Button Name="viewFolder" ct:DockPanel.Dock="Right" HorizontalAlignment="Right" Click="ViewFolder">
<SymbolIcon Symbol="Folder"></SymbolIcon>
</Button>
</ct:DockPanel>
</ct:DockPanel>
</Grid>
</Page>

View File

@@ -0,0 +1,163 @@
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 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.Navigation;
using Windows.ApplicationModel;
using WinDurango.UI.Utils;
using System.Diagnostics;
using WinDurango.UI.Controls;
using WinDurango.UI.Dialogs;
using Windows.ApplicationModel.DataTransfer;
using CommunityToolkit.WinUI.Controls;
namespace WinDurango.UI.Pages.Dialog
{
public sealed partial class SaveManagerPage : Page
{
private Package _package;
private string _dataDir;
public SaveManagerPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.Parameter is string familyName)
{
_package = Packages.GetPackageByFamilyName(familyName);
this.Loaded += (sender, e) =>
{
Init();
};
}
}
public void ShowInfo(string title, string message, InfoBarSeverity severity = InfoBarSeverity.Informational)
{
this.infoBar.Children.Clear();
double width = this.ActualWidth;
if (width == 0)
{
width = this.Frame.ActualWidth;
}
InfoBar infoBar = new InfoBar();
Button copyButton = new Button();
SymbolIcon symbolIcon = new SymbolIcon(Symbol.Copy);
copyButton.Content = symbolIcon;
copyButton.HorizontalAlignment = HorizontalAlignment.Right;
copyButton.Click += (sender, e) =>
{
DataPackage dp = new DataPackage();
dp.SetText(message);
Windows.ApplicationModel.DataTransfer.Clipboard.SetContent(dp);
};
infoBar.Severity = severity;
infoBar.IsOpen = true;
infoBar.Message = message;
infoBar.Title = title;
infoBar.ActionButton = copyButton;
infoBar.MaxWidth = this.ActualWidth;
Logger.WriteInformation(message);
this.infoBar.Children.Add(infoBar);
}
// TODO: slow
private void Init()
{
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Packages", _package.Id.FamilyName);
if (!Directory.Exists(path))
{
ShowInfo("Error finding package data", $"Could not find path {path}.\nHave you ran this package yet?", InfoBarSeverity.Error);
return;
}
_dataDir = path;
string userStorage = Path.Combine(path, "LocalState", "WinDurango", "UserStorage");
if (!Directory.Exists(userStorage))
{
string msg = $"Could not find WinDurango UserStorage path.\nHave you ran this package yet?";
bool exists = Directory.Exists(Path.Combine(path, "LocalState"));
if (exists)
{
userStorage = Path.Combine(path, "LocalState");
msg += "\n\nUsing LocalState instead.";
}
ShowInfo("Error finding UserStorage", msg, exists ? InfoBarSeverity.Warning : InfoBarSeverity.Error);
if (!exists)
return;
}
containerList.Children.Clear();
folderList.Children.Clear();
foreach (string dir in Directory.GetDirectories(userStorage))
{
// GetFileName returns the name of the file including the extension, alright.
// so then we have GetDirectoryName... what does it do? I thought it would return the folder name, but no... it returns the path.
string dispName = Path.GetFileName(dir);
string dispNameTxt = Path.Combine(dir, "wd_displayname.txt");
bool isContainer = File.Exists(dispNameTxt);
if (isContainer) {
dispName = File.ReadAllText(dispNameTxt);
containerList.Children.Add(new ContainerInfo(dir, dispName, isContainer));
} else
{
folderList.Children.Add(new ContainerInfo(dir, dispName, isContainer));
}
}
if (folderList.Children.Count != 0)
{
folderHeader.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
}
if (containerList.Children.Count != 0)
{
containerHeader.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
}
if (containerList.Children.Count == 0 && folderList.Children.Count == 0)
{
noSavesHeader.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
}
}
public void RemoveElement(ContainerInfo element)
{
folderList.Children.Remove(element);
containerList.Children.Remove(element);
}
private void ViewFolder(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
string dir = _dataDir;
string userStorage = Path.Combine(dir, "LocalState", "WinDurango", "UserStorage");
if (Directory.Exists(userStorage))
{
dir = userStorage;
}
FSHelper.OpenFolder(dir);
}
}
}

View File

@@ -14,16 +14,16 @@ For building you'll need Visual Studio 2022 with the following:
- [X] Patching
- [X] Allow for package removal from UI instead of just completely uninstalling.
- [X] Installation options
- [ ] Save Manager
- [X] Save Manager
- [X] Mod Manager
- [X] Scan for already installed EraOS/XUWP stuff
- [X] Allow for any existing installed package to be added to the applist
- [ ] Built in updater
- [ ] 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)
- [ ] Fix UI load speed when loading a lot of packages on startup
- [X] Applist scrolling
- [X] Fix icon in the titlebar

47
Utils/FSHelper.cs Normal file
View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace WinDurango.UI.Utils
{
public static class FSHelper
{
public static long GetDirectorySize(this DirectoryInfo dir)
{
long size = 0;
foreach (FileInfo file in dir.EnumerateFiles("*", SearchOption.AllDirectories))
{
size += file.Length;
}
return size;
}
public static string GetSizeString(this long size)
{
string[] types = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
int i = 0;
double dSize = size;
while (dSize >= 1024 && i < types.Length - 1)
{
dSize /= 1024;
i++;
}
return $"{dSize:0.00} {types[i]}";
}
public static void OpenFolder(string folder)
{
Process.Start(new ProcessStartInfo(folder) { UseShellExecute = true });
}
}
}

View File

@@ -27,6 +27,9 @@ 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.
/// <summary>
/// Gets all the installed UWP packages on the system
/// </summary>
public static IEnumerable<Package> GetInstalledPackages()
{
var sid = WindowsIdentity.GetCurrent().User?.Value;
@@ -35,6 +38,9 @@ namespace WinDurango.UI.Utils
return pm.FindPackagesForUser(sid);
}
/// <summary>
/// Gets some properties from the provided AppxManifest
/// </summary>
public static ManifestInfo GetPropertiesFromManifest(string manifestPath)
{
ManifestInfo manifestInfo = new();
@@ -61,6 +67,12 @@ namespace WinDurango.UI.Utils
return manifestInfo;
}
/// <summary>
/// Installs an Xbox Package with the folder given to it
/// </summary>
/// <remarks>
/// This is simply meant for being able to pass a folder containing the Mount directory.
/// </remarks>
public static async Task InstallXPackageAsync(string dir, ProgressController controller, bool addInstalledPackage = true)
{
string mountDir = Path.Combine(dir, "Mount");
@@ -74,6 +86,12 @@ namespace WinDurango.UI.Utils
await InstallPackageAsync(new Uri(mountDir + "\\AppxManifest.xml", UriKind.Absolute), controller, addInstalledPackage);
}
/// <summary>
/// Gets a Package's splash screen, if none is found... it returns null.
/// </summary>
/// <remarks>
/// It checks the package's AppxManifest for Package.Applications.Application.VisualElements.SplashScreen.Image
/// </remarks>
public static string GetSplashScreenPath(Package pkg)
{
try
@@ -119,7 +137,9 @@ namespace WinDurango.UI.Utils
}
}
/// <summary>
/// Installs a Package with the provided AppxManifest
/// </summary>
public static async Task<string> InstallPackageAsync(Uri appxManifestUri, ProgressController controller, bool addInstalledPackage = true)
{
string manifestPath = Uri.UnescapeDataString(appxManifestUri.AbsolutePath);
@@ -169,7 +189,7 @@ namespace WinDurango.UI.Utils
controller?.UpdateProgress(60.0);
controller?.UpdateText(GetLocalizedText("/Packages/GettingAppInfo"));
Package recentPkg = GetMostRecentlyInstalledPackage();
Package recentPkg = GetMostRecentInstalledPackage();
if (addInstalledPackage)
{
@@ -198,6 +218,9 @@ namespace WinDurango.UI.Utils
}
}
/// <summary>
/// Uninstalls a package
/// </summary>
public static async Task RemovePackage(Package package, ProgressController controller)
{
Logger.WriteError($"Uninstalling {package.DisplayName}...");
@@ -219,6 +242,9 @@ namespace WinDurango.UI.Utils
}
}
/// <summary>
/// Gets a Package by it's Family Name
/// </summary>
public static Package GetPackageByFamilyName(string familyName)
{
var packageManager = new PackageManager();
@@ -227,7 +253,10 @@ namespace WinDurango.UI.Utils
return packages == null || !packages.Any() ? null : packages.First();
}
public static Package GetMostRecentlyInstalledPackage()
/// <summary>
/// Gets the most recent installed package
/// </summary>
public static Package GetMostRecentInstalledPackage()
{
var sid = WindowsIdentity.GetCurrent().User?.Value;
var pm = new PackageManager();
@@ -240,6 +269,5 @@ namespace WinDurango.UI.Utils
return newestPackage;
}
}
}

View File

@@ -37,6 +37,7 @@
</ItemGroup>
<ItemGroup>
<None Remove="Controls\AppTile.xaml" />
<None Remove="Controls\ContainerInfo.xaml" />
<None Remove="Controls\ContributorInfo.xaml" />
<None Remove="Controls\ModInfo.xaml" />
<None Remove="Dialogs\AppListDialog.xaml" />
@@ -45,6 +46,7 @@
<None Remove="Pages\AboutPage.xaml" />
<None Remove="Pages\AppsListPage.xaml" />
<None Remove="Pages\Dialog\ModManPage.xaml" />
<None Remove="Pages\Dialog\SaveManagerPage.xaml" />
<None Remove="Pages\Dialog\UserManPage.xaml" />
<None Remove="Pages\NotImplementedPage.xaml" />
<None Remove="Pages\SettingsPage.xaml" />
@@ -198,6 +200,18 @@
<PRIResource Remove="Strings\en-US\Ui.resw" />
</ItemGroup>
<ItemGroup>
<Page Update="Controls\ContainerInfo.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Pages\Dialog\SaveManagerPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Pages\Dialog\UserManPage.xaml">
<Generator>MSBuild:Compile</Generator>