Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Controls/AppTile.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
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}" >
<Button Width="320" Height="180" Padding="0" x: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" Background="{ThemeResource DesktopAcrylicTransparentBrush}">
Expand Down
48 changes: 27 additions & 21 deletions Controls/AppTile.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public sealed partial class AppTile
private string _Publisher;
private string _Version;
private Uri _Logo;

private AppListEntry appListEntry;

private async void HandleUnregister(object sender, SplitButtonClickEventArgs e)
{
Expand Down Expand Up @@ -200,19 +202,19 @@ public AppTile(string familyName)
catch
{
Logger.WriteWarning($"Could not get the applist entries of \"{_Name}\"");
}
AppListEntry firstAppListEntry = appListEntries?.FirstOrDefault() ?? null;
}
appListEntry = appListEntries?.FirstOrDefault() ?? null;

if (firstAppListEntry == null)
if (appListEntry == null)
Logger.WriteWarning($"Could not get the applist entry of \"{_Name}\"");

if (String.IsNullOrEmpty(ss) || !File.Exists(ss))
{
try
{
if (firstAppListEntry != null)
if (appListEntry != null)
{
RandomAccessStreamReference logoStream = firstAppListEntry.DisplayInfo.GetLogo(new Size(320, 180));
RandomAccessStreamReference logoStream = appListEntry.DisplayInfo.GetLogo(new Size(320, 180));
BitmapImage logoImage = new();
using IRandomAccessStream stream = logoStream.OpenReadAsync().GetAwaiter().GetResult();
logoImage.SetSource(stream);
Expand Down Expand Up @@ -275,24 +277,28 @@ public AppTile(string familyName)
rcFlyout.ShowAt(sender as FrameworkElement, e.GetPosition(sender as UIElement));
};

startButton.Tapped += async (s, e) =>
startButton.Tapped += (_, _) => StartApp();
}


public async void StartApp()
{
if (_package.Status.LicenseIssue)
{
if (_package.Status.LicenseIssue)
{
Logger.WriteError($"Could not launch {_Name} due to licensing issue.");
_ = new NoticeDialog($"There is a licensing issue... Do you own this package?", $"Could not launch {_Name}").ShowAsync();
return;
}
Logger.WriteError($"Could not launch {_Name} due to licensing issue.");
_ = new NoticeDialog($"There is a licensing issue... Do you own this package?", $"Could not launch {_Name}").ShowAsync();
return;
}

if (firstAppListEntry == null)
{
_ = new NoticeDialog($"Could not get the applist entry of \"{_Name}\"", $"Could not launch {_Name}").ShowAsync();
return;
}
Logger.WriteInformation($"Launching {_Name}");
if (await firstAppListEntry.LaunchAsync() == false)
_ = new NoticeDialog($"Failed to launch \"{_Name}\"!", $"Could not launch {_Name}").ShowAsync();
};
if (appListEntry == null)
{
_ = new NoticeDialog($"Could not get the applist entry of \"{_Name}\"", $"Could not launch {_Name}").ShowAsync();
return;
}
Logger.WriteInformation($"Launching {_Name}");
if (await appListEntry.LaunchAsync() == false)
_ = new NoticeDialog($"Failed to launch \"{_Name}\"!", $"Could not launch {_Name}").ShowAsync();
}
}

}
13 changes: 11 additions & 2 deletions MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,18 @@ private async void appTitleBar_Loaded(object sender, RoutedEventArgs e)
if (String.IsNullOrEmpty(FSHelper.FindFileOnPath("vcruntime140d.dll")))
missing.Add("Microsoft Visual C++ Redistributable", null);

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 Readme.md in the repo for the todolist.", "Important");
await devNotice.ShowAsync();

if (App.Settings.Settings.ShowDevNotice)
{
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 Readme.md in the repo for the todolist.", "Important");
await devNotice.ShowAsync();

// We only show this notification once from now on
Settings.Set("ShowDevNotice", false);
Settings.Save();
}


if (missing.Count != 0)
{
// todo: properly provide download link
Expand Down
158 changes: 150 additions & 8 deletions Pages/AppsListPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using System.Security.Principal;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.Foundation;
using Windows.Gaming.Input;
using Windows.Management.Deployment;
using Windows.Storage;
using Windows.Storage.Pickers;
Expand All @@ -21,6 +23,12 @@ namespace WinDurango.UI.Pages
{
public sealed partial class AppsListPage : Page
{
private Gamepad gamepad;
private int currentIndex;
private Point currentPoint = new(0, 0);
private bool inputProcessed = true;
private long lastInput;

public async Task InitAppListAsync()
{
appList.Children.Clear();
Expand Down Expand Up @@ -138,14 +146,148 @@ public AppsListPage()
InitializeComponent();
_ = InitAppListAsync();

// All this is useless now basically... because InitAppListAsync now runs asynchronously (not blocking the ui thread)
/*
Stopwatch PlatinumWatch = new Stopwatch();
Logger.WriteDebug("Initializing AppsListPage...");
PlatinumWatch.Start();
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);
*/
Loaded += OnAppListPage_Loaded;
}

private void OnAppListPage_Loaded(object sender, RoutedEventArgs e)
{
Gamepad.GamepadAdded += onGamepadAdded;
Gamepad.GamepadRemoved += OnGamepadRemoved;
}

private void OnGamepadRemoved(object sender, Gamepad e)
{
gamepad = null;
}

private void onGamepadAdded(object sender, Gamepad e)
{
gamepad = e;
ListenGamepadInput();
this.DispatcherQueue.TryEnqueue(() =>
{
if (appList.Children.Count > 0)
{
appList.Children[currentIndex].Focus(FocusState.Keyboard);
}
});
}


private async void ListenGamepadInput()
{
while (gamepad != null)
{
GamepadReading gamepadInput = gamepad.GetCurrentReading();
bool moveRight = gamepadInput.LeftThumbstickX > 0.5 || (gamepadInput.Buttons & GamepadButtons.DPadRight) != 0;
bool moveLeft = gamepadInput.LeftThumbstickX < -0.5 || (gamepadInput.Buttons & GamepadButtons.DPadLeft) != 0;
bool moveUp = gamepadInput.LeftThumbstickY > 0.5 || (gamepadInput.Buttons & GamepadButtons.DPadUp) != 0;
bool moveDown = gamepadInput.LeftThumbstickY < -0.5 || (gamepadInput.Buttons & GamepadButtons.DPadDown) != 0;
bool actionClicked = (gamepadInput.Buttons & GamepadButtons.A) != 0;


if (actionClicked && inputProcessed)
{
inputProcessed = false;
this.DispatcherQueue.TryEnqueue(() =>
{
var appTile = appList.Children[currentIndex] as AppTile;
appTile.StartApp();
inputProcessed = true;
});
}

if ((moveRight || moveLeft || moveUp || moveDown) && inputProcessed)
{
inputProcessed = false;
if (moveRight) this.DispatcherQueue.TryEnqueue(() => MoveFocus(1, 0));
else if (moveLeft) this.DispatcherQueue.TryEnqueue(() => MoveFocus(-1, 0));
else if (moveUp) this.DispatcherQueue.TryEnqueue(() => MoveFocus(0, -1));
else if (moveDown) this.DispatcherQueue.TryEnqueue(() => MoveFocus(0, 1));
}

await Task.Delay(100);
}
}

private void MoveFocus(int xOffset, int yOffset)
{
bool firstInput = lastInput == 0;
if (lastInput > DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - 200)
{
inputProcessed = true;
return;
}
lastInput = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
if (appList.Children.Count == 0)
{
inputProcessed = true;
return;
}

// We only set focus first to the index 0 if ShowDevNotice was shown before as it cancels the initial focus done in Load event
if (firstInput && App.Settings.Settings.ShowDevNotice)
{
appList.Children[0].Focus(FocusState.Keyboard);
inputProcessed = true;
return;
}

int columns = GetColumnCount();
int rows = appList.Children.Count / columns;

int newX = (int)(currentPoint.X + xOffset);
int newY = (int)(currentPoint.Y + yOffset);

newX = Math.Clamp(newX, 0, columns - 1);
newY = Math.Clamp(newY, 0, rows - 1);

if (newX != currentPoint.X || newY != currentPoint.Y)
{
currentPoint = new Point(newX, newY);
currentIndex = newY * columns + newX;

if (currentIndex < appList.Children.Count)
{
appList.Children[currentIndex].Focus(FocusState.Keyboard);
}
}

inputProcessed = true;
}

// We need do this our self as WrapPanel doesn't have internal field or function to get current column amount
private int GetColumnCount()
{
if (appList.Children.Count == 0) return 1;


FrameworkElement firstItem = appList.Children[0] as FrameworkElement;
if (firstItem == null) return 1;


double firstItemTop = firstItem.TransformToVisual(appList).TransformPoint(new Point(0, 0)).Y;
int columnCount = 1;

for (int i = 1; i < appList.Children.Count; i++)
{
var item = appList.Children[i] as FrameworkElement;
if (item == null)
continue;

double itemTop = item.TransformToVisual(appList).TransformPoint(new Point(0, 0)).Y;

if (Math.Abs(itemTop - firstItemTop) < 1)
{
columnCount++;
}
else
{
break;
}
}

return columnCount;
}

private void SearchBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
Expand Down
2 changes: 2 additions & 0 deletions Settings/UiConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public enum PatchSource

public string DownloadedWdVer { get; set; } = String.Empty;
public PatchSource DownloadSource { get; set; } = PatchSource.Release;

public bool ShowDevNotice { get; set; } = true;
}

// TODO: fix type init exception
Expand Down
Loading