Skip to content
Open
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
1 change: 1 addition & 0 deletions WheelWizard/Features/Settings/ISettingsServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public interface ISettingsProperties
Setting GAME_LOCATION { get; }
Setting FORCE_WIIMOTE { get; }
Setting LAUNCH_WITH_DOLPHIN { get; }
Setting LAUNCH_RR_ON_STARTUP { get; }
Setting PREFERS_MODS_ROW_VIEW { get; }
Setting FOCUSED_USER { get; }
Setting ENABLE_ANIMATIONS { get; }
Expand Down
2 changes: 2 additions & 0 deletions WheelWizard/Features/Settings/SettingsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ IFileSystem fileSystem
GAME_LOCATION = RegisterWhWz("GameLocation", "", value => _fileSystem.File.Exists(value as string ?? string.Empty));
FORCE_WIIMOTE = RegisterWhWz("ForceWiimote", false);
LAUNCH_WITH_DOLPHIN = RegisterWhWz("LaunchWithDolphin", false);
LAUNCH_RR_ON_STARTUP = RegisterWhWz("LaunchRrOnStartup", false);
PREFERS_MODS_ROW_VIEW = RegisterWhWz("PrefersModsRowView", true);
FOCUSED_USER = RegisterWhWz("FavoriteUser", 0, value => (int)(value ?? -1) >= 0 && (int)(value ?? -1) < 4);

Expand Down Expand Up @@ -195,6 +196,7 @@ IFileSystem fileSystem
public Setting GAME_LOCATION { get; }
public Setting FORCE_WIIMOTE { get; }
public Setting LAUNCH_WITH_DOLPHIN { get; }
public Setting LAUNCH_RR_ON_STARTUP { get; }
public Setting PREFERS_MODS_ROW_VIEW { get; }
public Setting FOCUSED_USER { get; }
public Setting ENABLE_ANIMATIONS { get; }
Expand Down
18 changes: 18 additions & 0 deletions WheelWizard/Resources/Languages/Settings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions WheelWizard/Resources/Languages/Settings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
<data name="Option_LaunchWithDolphin" xml:space="preserve">
<value>Launch Game With Dolphin Window</value>
</data>
<data name="Option_LaunchRrOnStartup" xml:space="preserve">
<value>Launch Retro Rewind On Startup</value>
</data>
<data name="Section_Language" xml:space="preserve">
<value>Language</value>
</data>
Expand All @@ -44,6 +47,9 @@
<data name="HelperText_LaunchWithDolphin" xml:space="preserve">
<value>Will launch dolphins main window along with the game</value>
</data>
<data name="HelperText_LaunchRrOnStartup" xml:space="preserve">
<value>Automatically launches Retro Rewind when Wheel Wizard starts</value>
</data>
<data name="HelperText_ForceDisableWiimote" xml:space="preserve">
<value>This setting disables Wiimote ingame, but enables it for the Wii channel</value>
</data>
Expand Down
79 changes: 74 additions & 5 deletions WheelWizard/Views/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using Microsoft.Extensions.Logging;
using WheelWizard.AutoUpdating;
using WheelWizard.MiiRendering.Services;
using WheelWizard.Settings;
using WheelWizard.Services.Launcher;
using WheelWizard.Services;
using WheelWizard.Services.LiveData;
using WheelWizard.Services.UrlProtocol;
Expand All @@ -18,6 +20,12 @@ namespace WheelWizard.Views;

public class App : Application
{
private enum StartupLaunchTarget
{
None,
RetroRewind,
}

/// <summary>
/// Gets the service provider configured for this application.
/// </summary>
Expand Down Expand Up @@ -51,28 +59,89 @@ private void InitializeBehaviorOverrides()
ToolTipBubbleBehavior.Initialize();
}

private static void OpenGameBananaModWindow()
private static string? GetLaunchProtocolArgument()
{
var args = Environment.GetCommandLineArgs();
for (var i = 1; i < args.Length; i++)
{
var argument = args[i];
if (argument.StartsWith("wheelwizard://", StringComparison.OrdinalIgnoreCase))
return argument;
Comment on lines +68 to +69
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Normalize protocol scheme before returning to avoid mixed-case launch failures.

At Line 67, detection is case-insensitive, but the returned value keeps original casing. WheelWizard/Services/UrlProtocol/UrlProtocolManager.cs strips prefix with a case-sensitive replace, so WheelWizard://... will be detected here but fail parsing downstream.

Proposed fix
-            if (argument.StartsWith("wheelwizard://", StringComparison.OrdinalIgnoreCase))
-                return argument;
+            if (argument.StartsWith("wheelwizard://", StringComparison.OrdinalIgnoreCase))
+                return $"wheelwizard://{argument["wheelwizard://".Length..]}";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (argument.StartsWith("wheelwizard://", StringComparison.OrdinalIgnoreCase))
return argument;
if (argument.StartsWith("wheelwizard://", StringComparison.OrdinalIgnoreCase))
return $"wheelwizard://{argument["wheelwizard://".Length..]}";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@WheelWizard/Views/App.axaml.cs` around lines 67 - 68, The argument is
detected case-insensitively in App.axaml.cs using
argument.StartsWith("wheelwizard://", StringComparison.OrdinalIgnoreCase) but
returned with original casing, which breaks the case-sensitive strip in
UrlProtocolManager.cs; modify the return so the protocol scheme is normalized to
the lowercase "wheelwizard://" prefix (e.g., build and return "wheelwizard://" +
the remainder of the original argument after the prefix) so downstream
UrlProtocolManager parsing (case-sensitive Replace) will succeed.

}

return null;
}

private static StartupLaunchTarget GetStartupLaunchTarget()
{
var args = Environment.GetCommandLineArgs();

for (var i = 1; i < args.Length; i++)
{
var argument = args[i];
if (argument.Equals("--launch", StringComparison.OrdinalIgnoreCase) || argument.Equals("-l", StringComparison.OrdinalIgnoreCase))
{
if (i + 1 >= args.Length)
continue;

var launchTarget = args[++i];
if (launchTarget.Equals("rr", StringComparison.OrdinalIgnoreCase) ||
launchTarget.Equals("retrorewind", StringComparison.OrdinalIgnoreCase) ||
launchTarget.Equals("retro-rewind", StringComparison.OrdinalIgnoreCase))
{
return StartupLaunchTarget.RetroRewind;
}

continue;
}

if (!argument.StartsWith("--launch=", StringComparison.OrdinalIgnoreCase))
continue;

var launchTargetFromEquals = argument["--launch=".Length..].Trim();
if (launchTargetFromEquals.Equals("rr", StringComparison.OrdinalIgnoreCase) ||
launchTargetFromEquals.Equals("retrorewind", StringComparison.OrdinalIgnoreCase) ||
launchTargetFromEquals.Equals("retro-rewind", StringComparison.OrdinalIgnoreCase))
{
return StartupLaunchTarget.RetroRewind;
}
}

return StartupLaunchTarget.None;
}

private static bool OpenGameBananaModWindow()
{
ModManager.Instance.ReloadAsync();
if (args.Length <= 1)
return;
var protocolArgument = args[1];
var protocolArgument = GetLaunchProtocolArgument();
if (string.IsNullOrWhiteSpace(protocolArgument))
return false;

_ = UrlProtocolManager.ShowPopupForLaunchUrlAsync(protocolArgument);
return true;
}

private async void OnInitializedAsync()
{
try
{
OpenGameBananaModWindow();
var launchedFromProtocol = OpenGameBananaModWindow();

var updateService = Services.GetRequiredService<IAutoUpdaterSingletonService>();
var whWzDataService = Services.GetRequiredService<IWhWzDataSingletonService>();

await updateService.CheckForUpdatesAsync();
await whWzDataService.LoadBadgesAsync();
InitializeManagers();

var settingsManager = Services.GetRequiredService<ISettingsManager>();
var requestedByCli = GetStartupLaunchTarget() == StartupLaunchTarget.RetroRewind;
var shouldLaunchRrOnStartup = !launchedFromProtocol && settingsManager.Get<bool>(settingsManager.LAUNCH_RR_ON_STARTUP);
if (requestedByCli || shouldLaunchRrOnStartup)
{
var rrLauncher = Services.GetRequiredService<RrLauncher>();
await rrLauncher.Launch();
}
}
catch (Exception e)
{
Expand Down
6 changes: 6 additions & 0 deletions WheelWizard/Views/Pages/Settings/OtherSettings.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@
<components1:FormFieldLabel Text="{x:Static lang:Settings.Option_LaunchWithDolphin}"
TipText="{x:Static lang:Settings.HelperText_LaunchWithDolphin}" />
</CheckBox>
<CheckBox Margin="0,2" IsChecked="False"
Classes="SwitchDark"
x:Name="LaunchRrOnStartup">
<components1:FormFieldLabel Text="{x:Static lang:Settings.Option_LaunchRrOnStartup}"
TipText="{x:Static lang:Settings.HelperText_LaunchRrOnStartup}" />
</CheckBox>
</StackPanel>
</Border>

Expand Down
7 changes: 7 additions & 0 deletions WheelWizard/Views/Pages/Settings/OtherSettings.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ public OtherSettings()
// Attach event handlers after loading settings to avoid unwanted triggers
DisableForce.IsCheckedChanged += ClickForceWiimote;
LaunchWithDolphin.IsCheckedChanged += ClickLaunchWithDolphinWindow;
LaunchRrOnStartup.IsCheckedChanged += ClickLaunchRrOnStartup;
}

private void LoadSettings()
{
// Only loads when the settings are not disabled (aka when the paths are set up correctly)
DisableForce.IsChecked = SettingsService.Get<bool>(SettingsService.FORCE_WIIMOTE);
LaunchWithDolphin.IsChecked = SettingsService.Get<bool>(SettingsService.LAUNCH_WITH_DOLPHIN);
LaunchRrOnStartup.IsChecked = SettingsService.Get<bool>(SettingsService.LAUNCH_RR_ON_STARTUP);
OpenSaveFolderButton.IsEnabled = Directory.Exists(PathManager.SaveFolderPath);
}

Expand All @@ -56,6 +58,11 @@ private void ClickLaunchWithDolphinWindow(object? sender, RoutedEventArgs e)
SettingsService.Set(SettingsService.LAUNCH_WITH_DOLPHIN, LaunchWithDolphin.IsChecked == true);
}

private void ClickLaunchRrOnStartup(object? sender, RoutedEventArgs e)
{
SettingsService.Set(SettingsService.LAUNCH_RR_ON_STARTUP, LaunchRrOnStartup.IsChecked == true);
}

private async void Reinstall_RetroRewind(object sender, RoutedEventArgs e)
{
var progressWindow = new ProgressWindow();
Expand Down