Skip to content

Commit 5fc09d9

Browse files
committed
添加创建实例快捷方式的功能、本地化快速启动部分提示文字
1 parent 8cbc077 commit 5fc09d9

File tree

12 files changed

+116
-28
lines changed

12 files changed

+116
-28
lines changed

Natsurainko.FluentLauncher/App.xaml.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,16 @@ protected override async void OnLaunched(LaunchActivatedEventArgs args)
9292
Logger.RedirectedActivationFrom(redirectedArgs);
9393
GetService<QuickLaunchService>().LaunchFromActivatedEventArgs(redirectedArgs.Arguments.Split(' '));
9494
}
95+
96+
// Handle the protocolActivated arguments
97+
if (e.Data is Windows.ApplicationModel.Activation.ProtocolActivatedEventArgs protocolActivatedEventArgs)
98+
{
99+
string[] args = [protocolActivatedEventArgs.Uri.OriginalString];
100+
Program.HandleUriCommandParameters(ref args);
101+
102+
Logger.RedirectedActivationFrom(protocolActivatedEventArgs);
103+
GetService<QuickLaunchService>().LaunchFromActivatedEventArgs(args);
104+
}
95105
};
96106

97107
#if ENABLE_LOAD_EXTENSIONS
@@ -298,4 +308,7 @@ internal static partial class AppLoggers
298308

299309
[LoggerMessage(LogLevel.Information, "Redirected activation from the other instance with EventArgs {@eventArgs}")]
300310
public static partial void RedirectedActivationFrom(this ILogger logger, Windows.ApplicationModel.Activation.LaunchActivatedEventArgs eventArgs);
311+
312+
[LoggerMessage(LogLevel.Information, "Redirected activation from the other instance with EventArgs {@eventArgs}")]
313+
public static partial void RedirectedActivationFrom(this ILogger logger, Windows.ApplicationModel.Activation.ProtocolActivatedEventArgs eventArgs);
301314
}
125 KB
Binary file not shown.

Natsurainko.FluentLauncher/Package-Dev.appxmanifest

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
Square44x44Logo="Assets\PackageIcons\Dev\Square44x44Logo.png">
4444
<uap:DefaultTile Wide310x150Logo="Assets\PackageIcons\Dev\Wide310x150Logo.png" Square71x71Logo="Assets\PackageIcons\Dev\SmallTile.png" Square310x310Logo="Assets\PackageIcons\Dev\LargeTile.png" ShortName="Fluent Launcher (Dev)"/>
4545
<uap:SplashScreen Image="Assets\PackageIcons\Dev\SplashScreen.png"/>
46-
4746
</uap:VisualElements>
4847

4948
<Extensions>
@@ -52,6 +51,11 @@
5251
<desktop:Extension Category="windows.toastNotificationActivation">
5352
<desktop:ToastNotificationActivation ToastActivatorCLSID="053EFB0E-6705-4A11-94B9-980C4C9E0047" />
5453
</desktop:Extension>
54+
<uap:Extension Category="windows.protocol">
55+
<uap:Protocol Name="fluent-launcher">
56+
<uap:DisplayName>Fluent Launcher</uap:DisplayName>
57+
</uap:Protocol>
58+
</uap:Extension>
5559

5660
</Extensions>
5761
</Application>

Natsurainko.FluentLauncher/Package-Preview.appxmanifest

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,12 @@
5151
<desktop:Extension Category="windows.toastNotificationActivation">
5252
<desktop:ToastNotificationActivation ToastActivatorCLSID="053EFB0E-6705-4A11-94B9-980C4C9E0047" />
5353
</desktop:Extension>
54-
54+
<uap:Extension Category="windows.protocol">
55+
<uap:Protocol Name="fluent-launcher">
56+
<uap:DisplayName>Fluent Launcher</uap:DisplayName>
57+
</uap:Protocol>
58+
</uap:Extension>
59+
5560
</Extensions>
5661
</Application>
5762
</Applications>

Natsurainko.FluentLauncher/Package-Stable.appxmanifest

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,12 @@
5151
<desktop:Extension Category="windows.toastNotificationActivation">
5252
<desktop:ToastNotificationActivation ToastActivatorCLSID="053EFB0E-6705-4A11-94B9-980C4C9E0047" />
5353
</desktop:Extension>
54-
54+
<uap:Extension Category="windows.protocol">
55+
<uap:Protocol Name="fluent-launcher">
56+
<uap:DisplayName>Fluent Launcher</uap:DisplayName>
57+
</uap:Protocol>
58+
</uap:Extension>
59+
5560
</Extensions>
5661
</Application>
5762
</Applications>

Natsurainko.FluentLauncher/Program.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
using Natsurainko.FluentLauncher.Services.UI.Notification;
1717
using Natsurainko.FluentLauncher.Utils.Extensions;
1818
using System;
19+
using System.Collections.Generic;
1920
using System.CommandLine;
21+
using System.Linq;
22+
using System.Web;
2023
using ViewModels = Natsurainko.FluentLauncher.ViewModels;
2124
using Views = Natsurainko.FluentLauncher.Views;
2225

@@ -167,6 +170,7 @@
167170
var app = builder.Build();
168171
AppHost = app.Host;
169172

173+
HandleUriCommandParameters(ref args);
170174
await BuildRootCommand(app).InvokeAsync(args);
171175

172176
internal partial class Program
@@ -197,13 +201,33 @@ public static Command BuildSubCommand()
197201
var quickLaunchCommand = new Command("quickLaunch");
198202
quickLaunchCommand.AddOption(MinecraftFolderOption);
199203
quickLaunchCommand.AddOption(InstanceIdOption);
204+
quickLaunchCommand.AddAlias("quicklaunch");
200205

201206
quickLaunchCommand.SetHandler(async (folder, instanceId) =>
202207
await AppHost.Services.GetService<QuickLaunchService>()!.LaunchFromArguments(folder, instanceId),
203208
MinecraftFolderOption, InstanceIdOption);
204209

205210
return quickLaunchCommand;
206211
}
212+
213+
public static void HandleUriCommandParameters(ref string[] args)
214+
{
215+
if (args.Length != 1 || !args[0].StartsWith("fluent-launcher://"))
216+
return;
217+
218+
Uri requestUri = new(args[0]);
219+
var collection = HttpUtility.ParseQueryString(requestUri.Query);
220+
221+
List<string> handledArgs = [requestUri.Host];
222+
223+
foreach (var key in collection.Keys.OfType<string>())
224+
{
225+
handledArgs.Add($"--{key}");
226+
handledArgs.Add(collection[key]!);
227+
}
228+
229+
args = [.. handledArgs];
230+
}
207231
}
208232

209233
internal static partial class ProgramLoggers

Natsurainko.FluentLauncher/Services/Launch/QuickLaunchService.cs

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Microsoft.Windows.AppNotifications;
44
using Microsoft.Windows.AppNotifications.Builder;
55
using Natsurainko.FluentLauncher.Services.Settings;
6+
using Natsurainko.FluentLauncher.Utils;
67
using Natsurainko.FluentLauncher.Utils.Extensions;
78
using Natsurainko.FluentLauncher.ViewModels;
89
using Nrk.FluentCore.GameManagement;
@@ -18,22 +19,14 @@
1819

1920
namespace Natsurainko.FluentLauncher.Services.Launch;
2021

21-
internal class QuickLaunchService
22+
internal class QuickLaunchService(
23+
LaunchService launchService,
24+
SettingsService settingsService,
25+
INotificationService notificationService)
2226
{
23-
private readonly LaunchService _launchService;
24-
private readonly SettingsService _settingsService;
25-
private readonly INotificationService _notificationService;
26-
2727
public const string PinnedUri = "ms-resource:///Resources/JumpList__Pinned";
2828
public const string LatestUri = "ms-resource:///Resources/JumpList__Latest";
2929

30-
public QuickLaunchService(LaunchService launchService, SettingsService settingsService, INotificationService notificationService)
31-
{
32-
_launchService = launchService;
33-
_settingsService = settingsService;
34-
_notificationService = notificationService;
35-
}
36-
3730
public void LaunchFromActivatedEventArgs(string[] args)
3831
{
3932
var parseResult = Program.BuildSubCommand().Parse(args);
@@ -51,11 +44,11 @@ public void LaunchFromActivatedEventArgs(string[] args)
5144
.FirstOrDefault(x => (x?.InstanceId.Equals(instanceId)).GetValueOrDefault(false), null)
5245
?? throw new Exception("The target Minecraft instance could not be found");
5346

54-
_launchService.LaunchFromUI(instance);
47+
launchService.LaunchFromUI(instance);
5548
}
5649
catch (Exception ex)
5750
{
58-
_notificationService.LaunchFailed(ex, ex.Message);
51+
notificationService.LaunchFailed(ex, ex.Message);
5952
}
6053
}
6154

@@ -65,7 +58,7 @@ public async Task LaunchFromArguments(string minecraftFolder, string instanceId)
6558
{
6659
var appInstance = AppInstance.GetCurrent();
6760
var appActivationArguments = appInstance.GetActivatedEventArgs();
68-
var mainInstance = AppInstance.FindOrRegisterForKey("Main");
61+
var mainInstance = AppInstance.FindOrRegisterForKey("FluentLauncher.Process.Main");
6962

7063
if (!mainInstance.IsCurrent)
7164
{
@@ -81,15 +74,15 @@ public async Task LaunchFromArguments(string minecraftFolder, string instanceId)
8174
QuickLaunchProgressViewModel progressViewModel = new(instance);
8275
AppNotificationManager.Default.Show(progressViewModel.AppNotification);
8376

84-
using var process = await _launchService.LaunchAsync(instance, progress: progressViewModel);
77+
using var process = await launchService.LaunchAsync(instance, progress: progressViewModel);
8578
await process.Process.WaitForExitAsync();
8679
await AppNotificationManager.Default.RemoveAllAsync();
8780

8881
if (process.Process.ExitCode != 0)
8982
{
9083
AppNotificationManager.Default.Show(new AppNotificationBuilder()
91-
.AddText($"Minecraft: {instance.GetDisplayName} Crashed")
92-
.AddText("Quick Launch cannot provide further error information")
84+
.AddText(LocalizedStrings.Notifications__QuickLaunch_Crashed.Replace("${instance}", instance.GetDisplayName()))
85+
.AddText(LocalizedStrings.Notifications__QuickLaunch_CrashedDescription)
9386
.BuildNotification());
9487
}
9588
}
@@ -121,9 +114,9 @@ public async Task AddLatestMinecraftInstance(MinecraftInstance instance)
121114

122115
GetStartIndexOfGroups(jumpList, out pinStartIndex, out latestStartIndex);
123116

124-
if (jumpList.Items.Count - latestStartIndex > _settingsService.MaxQuickLaunchLatestItem)
117+
if (jumpList.Items.Count - latestStartIndex > settingsService.MaxQuickLaunchLatestItem)
125118
{
126-
jumpList.Items.Skip(_settingsService.MaxQuickLaunchLatestItem)
119+
jumpList.Items.Skip(settingsService.MaxQuickLaunchLatestItem)
127120
.ToList()
128121
.ForEach(item => jumpList.Items.Remove(item));
129122
}

Natsurainko.FluentLauncher/Utils/Extensions/MinecraftInstanceExtensions.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
using Natsurainko.FluentLauncher.Services.Settings;
44
using Nrk.FluentCore.GameManagement.Installer;
55
using Nrk.FluentCore.GameManagement.Instances;
6+
using System;
67
using System.IO;
8+
using System.Web;
9+
using Windows.ApplicationModel;
710

811
namespace Natsurainko.FluentLauncher.Utils.Extensions;
912

@@ -72,4 +75,22 @@ public static string GetDisplayName(this MinecraftInstance instance)
7275
return instance.InstanceId;
7376
}
7477
}
78+
79+
public static void CreateShortcut(this MinecraftInstance instance, string? folder = null)
80+
{
81+
folder ??= Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
82+
83+
string shortcutContent = "[{{000214A0-0000-0000-C000-000000000046}}]\r\n" +
84+
$"""
85+
Prop3=19,0
86+
[InternetShortcut]
87+
IDList=
88+
URL="fluent-launcher://quickLaunch/?minecraftFolder={HttpUtility.UrlEncode(instance.MinecraftFolderPath)}&instanceId={HttpUtility.UrlEncode(instance.InstanceId)}"
89+
IconIndex=0
90+
HotKey=0
91+
IconFile={Path.Combine(Package.Current.InstalledLocation.Path, "Assets\\Icons", "minecraft.ico")}
92+
""";
93+
94+
File.WriteAllText(Path.Combine(folder, $"{instance.GetDisplayName()}.url"), shortcutContent);
95+
}
7596
}

Natsurainko.FluentLauncher/ViewModels/Instances/InstanceViewModel.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using CommunityToolkit.Mvvm.Input;
33
using FluentLauncher.Infra.UI.Dialogs;
44
using FluentLauncher.Infra.UI.Navigation;
5+
using FluentLauncher.Infra.UI.Notification;
56
using Microsoft.UI.Xaml.Controls;
67
using Natsurainko.FluentLauncher.Models.Launch;
78
using Natsurainko.FluentLauncher.Services.Launch;
@@ -18,6 +19,7 @@ namespace Natsurainko.FluentLauncher.ViewModels.Instances;
1819

1920
internal partial class InstanceViewModel(
2021
INavigationService navigationService,
22+
INotificationService notificationService,
2123
QuickLaunchService quickLaunchService,
2224
IDialogActivationService<ContentDialogResult> dialogs) : PageVM, INavigationAware
2325
{
@@ -88,6 +90,19 @@ async void INavigationAware.OnNavigatedTo(object parameter)
8890
[RelayCommand]
8991
void OpenVersionFolder() => ExplorerHelper.OpenFolder(MinecraftInstance.GetGameDirectory());
9092

93+
[RelayCommand]
94+
void CreateShortcut()
95+
{
96+
MinecraftInstance.CreateShortcut();
97+
notificationService.InstanceShortcutCreated();
98+
}
99+
91100
[RelayCommand]
92101
async Task DeleteGame() => await _dialogs.ShowAsync("DeleteInstanceDialog", MinecraftInstance);
93102
}
103+
104+
internal static partial class InstanceViewModelNotifications
105+
{
106+
[Notification<InfoBar>(Title = "Notifications__InstanceShortcutCreated")]
107+
public static partial void InstanceShortcutCreated(this INotificationService notificationService);
108+
}

0 commit comments

Comments
 (0)