Skip to content

Commit

Permalink
feat: add multi-instance support (#380)
Browse files Browse the repository at this point in the history
* allow to open many app instances

* handle xbox launch

* add settings value to change multi instances behavior

* localize strings
  • Loading branch information
huynhsontung authored May 20, 2024
1 parent 34b9781 commit ea9ccbd
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 18 deletions.
1 change: 1 addition & 0 deletions Screenbox.Core/Services/ISettingsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public interface ISettingsService
int MaxVolume { get; set; }
string GlobalArguments { get; set; }
bool AdvancedMode { get; set; }
bool UseMultipleInstances { get; set; }
MediaPlaybackAutoRepeatMode PersistentRepeatMode { get; set; }
}
}
24 changes: 16 additions & 8 deletions Screenbox.Core/Services/SettingsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Screenbox.Core.Services
{
public sealed class SettingsService : ISettingsService
{
private readonly IPropertySet _settingsStorage = ApplicationData.Current.LocalSettings.Values;
private static IPropertySet SettingsStorage => ApplicationData.Current.LocalSettings.Values;

private const string PlayerAutoResizeKey = "Player/AutoResize";
private const string PlayerVolumeGestureKey = "Player/Gesture/Volume";
Expand All @@ -22,6 +22,7 @@ public sealed class SettingsService : ISettingsService
private const string LibrariesSearchRemovableStorageKey = "Libraries/SearchRemovableStorage";
private const string GeneralShowRecent = "General/ShowRecent";
private const string AdvancedModeKey = "Advanced/IsEnabled";
private const string AdvancedMultipleInstancesKey = "Advanced/MultipleInstances";
private const string GlobalArgumentsKey = "Values/GlobalArguments";
private const string PersistentVolumeKey = "Values/Volume";
private const string MaxVolumeKey = "Values/MaxVolume";
Expand Down Expand Up @@ -99,6 +100,12 @@ public bool AdvancedMode
set => SetValue(AdvancedModeKey, value);
}

public bool UseMultipleInstances
{
get => GetValue<bool>(AdvancedMultipleInstancesKey);
set => SetValue(AdvancedMultipleInstancesKey, value);
}

public SettingsService()
{
SetDefault(PlayerAutoResizeKey, (int)PlayerAutoResizeOption.Always);
Expand All @@ -112,6 +119,7 @@ public SettingsService()
SetDefault(GeneralShowRecent, true);
SetDefault(PersistentRepeatModeKey, (int)MediaPlaybackAutoRepeatMode.None);
SetDefault(AdvancedModeKey, false);
SetDefault(AdvancedMultipleInstancesKey, false);
SetDefault(GlobalArgumentsKey, string.Empty);

// Device family specific overrides
Expand All @@ -124,25 +132,25 @@ public SettingsService()
}
}

private T? GetValue<T>(string key)
private static T? GetValue<T>(string key)
{
if (_settingsStorage.TryGetValue(key, out object value))
if (SettingsStorage.TryGetValue(key, out object value))
{
return (T)value;
}

return default;
}

private void SetValue<T>(string key, T value)
private static void SetValue<T>(string key, T value)
{
_settingsStorage[key] = value;
SettingsStorage[key] = value;
}

private void SetDefault<T>(string key, T value)
private static void SetDefault<T>(string key, T value)
{
if (_settingsStorage.ContainsKey(key) && _settingsStorage[key] is T) return;
_settingsStorage[key] = value;
if (SettingsStorage.ContainsKey(key) && SettingsStorage[key] is T) return;
SettingsStorage[key] = value;
}

private static string SanitizeArguments(string raw)
Expand Down
7 changes: 7 additions & 0 deletions Screenbox.Core/ViewModels/SettingsPageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public sealed partial class SettingsPageViewModel : ObservableRecipient
[ObservableProperty] private bool _showRecent;
[ObservableProperty] private bool _searchRemovableStorage;
[ObservableProperty] private bool _advancedMode;
[ObservableProperty] private bool _useMultipleInstances;
[ObservableProperty] private string _globalArguments;
[ObservableProperty] private bool _isRelaunchRequired;

Expand Down Expand Up @@ -157,6 +158,12 @@ partial void OnAdvancedModeChanged(bool value)
IsRelaunchRequired = CheckForRelaunch();
}

partial void OnUseMultipleInstancesChanged(bool value)
{
_settingsService.UseMultipleInstances = value;
Messenger.Send(new SettingsChangedMessage(nameof(UseMultipleInstances)));
}

partial void OnGlobalArgumentsChanged(string value)
{
// No need to broadcast SettingsChangedMessage for this option
Expand Down
6 changes: 4 additions & 2 deletions Screenbox/Package.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
IgnorableNamespaces="uap mp uap3">
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
IgnorableNamespaces="uap mp uap3 desktop4">

<Identity
Name="Screenbox"
Expand All @@ -32,7 +33,8 @@
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="Screenbox.App">
EntryPoint="Screenbox.App"
desktop4:SupportsMultipleInstances="true">
<uap:VisualElements
DisplayName="[Debug] Screenbox"
Square150x150Logo="Assets\Square150x150Logo.png"
Expand Down
7 changes: 7 additions & 0 deletions Screenbox/Pages/SettingsPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,13 @@

<!-- Advanced section -->
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{strings:Resources Key=SettingsCategoryAdvanced}" />
<ctc:SettingsCard
Margin="{StaticResource SettingsCardMargin}"
Description="{strings:Resources Key=SettingsUseMultipleInstancesDescription}"
Header="{strings:Resources Key=SettingsUseMultipleInstancesHeader}"
HeaderIcon="{ui:FontIcon Glyph=&#xE737;}">
<ToggleSwitch x:Name="UseMultipleInstancesToggleSwitch" IsOn="{x:Bind ViewModel.UseMultipleInstances, Mode=TwoWay}" />
</ctc:SettingsCard>
<ctc:SettingsExpander
Margin="{StaticResource SettingsCardMargin}"
Description="{strings:Resources Key=SettingsAdvancedModeDescription}"
Expand Down
58 changes: 58 additions & 0 deletions Screenbox/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#nullable enable

using Screenbox;
using Screenbox.Core.Helpers;
using Screenbox.Core.Services;
using System;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;

public static class Program
{
// This example code shows how you could implement the required Main method to
// support multi-instance redirection. The minimum requirement is to call
// Application.Start with a new App object. Beyond that, you may delete the
// rest of the example code and replace it with your custom code if you wish.

static void Main(string[] args)
{
// If the Windows shell indicates a recommended instance, then
// the app can choose to redirect this activation to that instance instead.
if (AppInstance.RecommendedInstance != null)
{
AppInstance.RecommendedInstance.RedirectActivationTo();
}
else
{
AppInstance instance;
var settingsService = new SettingsService();
var registeredInstances = AppInstance.GetInstances();
IActivatedEventArgs? activatedArgs = AppInstance.GetActivatedEventArgs(); // This is null on Xbox
bool isFileActivated = activatedArgs?.Kind == ActivationKind.File;
bool isFeatureEnabled = settingsService.UseMultipleInstances;
bool isXbox = SystemInformation.IsXbox;
if ((!isXbox && isFeatureEnabled && isFileActivated) || registeredInstances.Count == 0)
{
string key = Guid.NewGuid().ToString();
instance = AppInstance.FindOrRegisterInstanceForKey(key);
}
else
{
instance = registeredInstances[0];
}

if (instance.IsCurrentInstance)
{
// If we successfully registered this instance, we can now just
// go ahead and do normal XAML initialization.
Windows.UI.Xaml.Application.Start(p => new App());
}
else
{
// Some other instance has registered for this key, so we'll
// redirect this activation to that instance instead.
instance.RedirectActivationTo();
}
}
}
}
17 changes: 9 additions & 8 deletions Screenbox/Screenbox.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
Expand All @@ -42,7 +42,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
Expand All @@ -57,7 +57,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
Expand All @@ -69,7 +69,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
Expand All @@ -84,7 +84,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM64</PlatformTarget>
Expand All @@ -97,7 +97,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM64'">
<OutputPath>bin\ARM64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
Expand All @@ -112,7 +112,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<DefineConstants>TRACE;DEBUG;NETFX_CORE;WINDOWS_UWP;CODE_ANALYSIS;DISABLE_XAML_GENERATED_MAIN</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
Expand All @@ -124,7 +124,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
Expand Down Expand Up @@ -289,6 +289,7 @@
<Compile Include="Pages\VideosPage.xaml.cs">
<DependentUpon>VideosPage.xaml</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Secrets.cs" />
<Compile Include="Services\ResourceService.cs" />
Expand Down
28 changes: 28 additions & 0 deletions Screenbox/Strings/en-US/Resources.generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2559,6 +2559,32 @@ public static string ActiveArguments
}
}
#endregion

#region SettingsUseMultipleInstancesHeader
/// <summary>
/// Looks up a localized string similar to: Allow multiple instances
/// </summary>
public static string SettingsUseMultipleInstancesHeader
{
get
{
return _resourceLoader.GetString("SettingsUseMultipleInstancesHeader");
}
}
#endregion

#region SettingsUseMultipleInstancesDescription
/// <summary>
/// Looks up a localized string similar to: Always open media files in a new instance
/// </summary>
public static string SettingsUseMultipleInstancesDescription
{
get
{
return _resourceLoader.GetString("SettingsUseMultipleInstancesDescription");
}
}
#endregion
}

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("DotNetPlus.ReswPlus", "2.1.3")]
Expand Down Expand Up @@ -2765,6 +2791,8 @@ public enum KeyEnum
SettingsSearchRemovableStorageHeader,
SettingsSearchRemovableStorageDescription,
ActiveArguments,
SettingsUseMultipleInstancesHeader,
SettingsUseMultipleInstancesDescription,
}

private static ResourceLoader _resourceLoader;
Expand Down
6 changes: 6 additions & 0 deletions Screenbox/Strings/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -770,4 +770,10 @@
<data name="ActiveArguments" xml:space="preserve">
<value>Active arguments</value>
</data>
<data name="SettingsUseMultipleInstancesHeader" xml:space="preserve">
<value>Allow multiple instances</value>
</data>
<data name="SettingsUseMultipleInstancesDescription" xml:space="preserve">
<value>Always open media files in a new instance</value>
</data>
</root>

0 comments on commit ea9ccbd

Please sign in to comment.