Skip to content

feat: add support for URI activations for coder scheme #72

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 22, 2025
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
25 changes: 24 additions & 1 deletion App/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Coder.Desktop.App.Models;
Expand All @@ -13,6 +14,8 @@
using Microsoft.Extensions.Hosting;
using Microsoft.UI.Xaml;
using Microsoft.Win32;
using Microsoft.Windows.AppLifecycle;
using Windows.ApplicationModel.Activation;

namespace Coder.Desktop.App;

Expand Down Expand Up @@ -82,7 +85,7 @@
Environment.Exit(0);
}

protected override void OnLaunched(LaunchActivatedEventArgs args)
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
// Start connecting to the manager in the background.
var rpcController = _services.GetRequiredService<IRpcController>();
Expand Down Expand Up @@ -138,4 +141,24 @@
trayWindow.AppWindow.Hide();
};
}

public void OnActivated(object? sender, AppActivationArguments args)
{
switch (args.Kind)
{
case ExtendedActivationKind.Protocol:
var protoArgs = args.Data as IProtocolActivatedEventArgs;
HandleURIActivation(protoArgs.Uri);

Check warning on line 151 in App/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.

Check warning on line 151 in App/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.

Check warning on line 151 in App/App.xaml.cs

View workflow job for this annotation

GitHub Actions / test

Dereference of a possibly null reference.

Check warning on line 151 in App/App.xaml.cs

View workflow job for this annotation

GitHub Actions / test

Dereference of a possibly null reference.
break;

default:
// TODO: log
break;
}
}

public void HandleURIActivation(Uri uri)
{
// TODO: handle
}
}
52 changes: 0 additions & 52 deletions App/Package.appxmanifest

This file was deleted.

29 changes: 23 additions & 6 deletions App/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.UI.Dispatching;
Expand Down Expand Up @@ -26,7 +27,23 @@ private static void Main(string[] args)
try
{
ComWrappersSupport.InitializeComWrappers();
if (!CheckSingleInstance()) return;
AppInstance mainInstance = GetMainInstance();
if (!mainInstance.IsCurrent)
{
var activationArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
mainInstance.RedirectActivationToAsync(activationArgs).AsTask().Wait();
return;
}

// Register for URI handling (known as "protocol activation")
#if DEBUG
const string scheme = "coder-debug";
#else
const string scheme = "coder";
#endif
var thisBin = Assembly.GetExecutingAssembly().Location;
ActivationRegistrationManager.RegisterForProtocolActivation(scheme, thisBin + ",1", "Coder Desktop", "");
Comment on lines +38 to +45
Copy link
Member

Choose a reason for hiding this comment

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

Is it typical for apps to register themselves? Or is it more common for it to be registered in the installer (not sure if this is even an option)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The installer could do it, but I'm not sure it provides any advantage.

One advantage of the App registering itself is that you don't need to install to debug, which is nice.

We might want to cosider unregistering in the uninstaller, which I can look into in another PR.


Application.Start(p =>
{
var context = new DispatcherQueueSynchronizationContext(DispatcherQueue.GetForCurrentThread());
Expand All @@ -38,6 +55,9 @@ private static void Main(string[] args)
e.Handled = true;
ShowExceptionAndCrash(e.Exception);
};

// redirections via RedirectActivationToAsync above get routed to the App
mainInstance.Activated += app.OnActivated;
});
}
catch (Exception e)
Expand All @@ -46,20 +66,17 @@ private static void Main(string[] args)
}
}

[STAThread]
private static bool CheckSingleInstance()
private static AppInstance GetMainInstance()
{
#if !DEBUG
const string appInstanceName = "Coder.Desktop.App";
#else
const string appInstanceName = "Coder.Desktop.App.Debug";
#endif

var instance = AppInstance.FindOrRegisterForKey(appInstanceName);
return instance.IsCurrent;
return AppInstance.FindOrRegisterForKey(appInstanceName);
}

[STAThread]
private static void ShowExceptionAndCrash(Exception e)
{
const string title = "Coder Desktop Fatal Error";
Expand Down
Loading