Skip to content

Commit bc3572b

Browse files
Feature: Added an option to change the default IDE (#16730)
Co-authored-by: Yair <[email protected]>
1 parent 2382d81 commit bc3572b

File tree

13 files changed

+540
-127
lines changed

13 files changed

+540
-127
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
namespace Files.App.Actions
5+
{
6+
internal sealed partial class OpenInIDEAction : ObservableObject, IAction
7+
{
8+
private readonly IDevToolsSettingsService _devToolsSettingsService;
9+
10+
private readonly IContentPageContext _context;
11+
12+
public string Label
13+
=> string.Format(
14+
"OpenInIDE".GetLocalizedResource(),
15+
_devToolsSettingsService.IDEName);
16+
17+
public string Description
18+
=> string.Format(
19+
"OpenInIDEDescription".GetLocalizedResource(),
20+
_devToolsSettingsService.IDEName);
21+
22+
public bool IsExecutable =>
23+
_context.Folder is not null &&
24+
!string.IsNullOrWhiteSpace(_devToolsSettingsService.IDEPath);
25+
26+
public OpenInIDEAction()
27+
{
28+
_devToolsSettingsService = Ioc.Default.GetRequiredService<IDevToolsSettingsService>();
29+
_context = Ioc.Default.GetRequiredService<IContentPageContext>();
30+
_context.PropertyChanged += Context_PropertyChanged;
31+
_devToolsSettingsService.PropertyChanged += DevSettings_PropertyChanged;
32+
}
33+
34+
public async Task ExecuteAsync(object? parameter = null)
35+
{
36+
var res = await Win32Helper.RunPowershellCommandAsync(
37+
$"& \'{_devToolsSettingsService.IDEPath}\' \'{_context.ShellPage?.ShellViewModel.WorkingDirectory}\'",
38+
PowerShellExecutionOptions.Hidden
39+
);
40+
41+
if (!res)
42+
await DynamicDialogFactory.ShowFor_IDEErrorDialog(_devToolsSettingsService.IDEName);
43+
}
44+
45+
private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
46+
{
47+
if (e.PropertyName == nameof(IContentPageContext.Folder))
48+
OnPropertyChanged(nameof(IsExecutable));
49+
}
50+
51+
private void DevSettings_PropertyChanged(object? sender, PropertyChangedEventArgs e)
52+
{
53+
if (e.PropertyName == nameof(IDevToolsSettingsService.IDEPath))
54+
{
55+
OnPropertyChanged(nameof(IsExecutable));
56+
}
57+
else if (e.PropertyName == nameof(IDevToolsSettingsService.IDEName))
58+
{
59+
OnPropertyChanged(nameof(Label));
60+
OnPropertyChanged(nameof(Description));
61+
}
62+
}
63+
}
64+
}

src/Files.App/Actions/Open/OpenInVSCodeAction.cs

Lines changed: 0 additions & 44 deletions
This file was deleted.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
namespace Files.App.Actions
5+
{
6+
internal sealed partial class OpenRepoInIDEAction : ObservableObject, IAction
7+
{
8+
private readonly IDevToolsSettingsService _devToolsSettingsService;
9+
10+
private readonly IContentPageContext _context;
11+
12+
public string Label
13+
=> string.Format("OpenRepoInIDE".GetLocalizedResource(), _devToolsSettingsService.IDEName);
14+
15+
public string Description
16+
=> string.Format("OpenRepoInIDEDescription".GetLocalizedResource(), _devToolsSettingsService.IDEName);
17+
18+
public bool IsExecutable =>
19+
_context.Folder is not null &&
20+
_context.ShellPage!.InstanceViewModel.IsGitRepository &&
21+
!string.IsNullOrWhiteSpace(_devToolsSettingsService.IDEPath);
22+
23+
public OpenRepoInIDEAction()
24+
{
25+
_context = Ioc.Default.GetRequiredService<IContentPageContext>();
26+
_devToolsSettingsService = Ioc.Default.GetRequiredService<IDevToolsSettingsService>();
27+
_context.PropertyChanged += Context_PropertyChanged;
28+
_devToolsSettingsService.PropertyChanged += DevSettings_PropertyChanged;
29+
}
30+
31+
public async Task ExecuteAsync(object? parameter = null)
32+
{
33+
var res = await Win32Helper.RunPowershellCommandAsync(
34+
$"& \'{_devToolsSettingsService.IDEPath}\' \'{_context.ShellPage!.InstanceViewModel.GitRepositoryPath}\'",
35+
PowerShellExecutionOptions.Hidden
36+
);
37+
38+
if (!res)
39+
await DynamicDialogFactory.ShowFor_IDEErrorDialog(_devToolsSettingsService.IDEName);
40+
}
41+
42+
private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
43+
{
44+
if (e.PropertyName == nameof(IContentPageContext.Folder))
45+
OnPropertyChanged(nameof(IsExecutable));
46+
}
47+
48+
private void DevSettings_PropertyChanged(object? sender, PropertyChangedEventArgs e)
49+
{
50+
if (e.PropertyName == nameof(IDevToolsSettingsService.IDEPath))
51+
{
52+
OnPropertyChanged(nameof(IsExecutable));
53+
}
54+
else if (e.PropertyName == nameof(IDevToolsSettingsService.IDEName))
55+
{
56+
OnPropertyChanged(nameof(Label));
57+
OnPropertyChanged(nameof(Description));
58+
}
59+
}
60+
}
61+
}

src/Files.App/Actions/Open/OpenRepoInVSCodeAction.cs

Lines changed: 0 additions & 45 deletions
This file was deleted.

src/Files.App/Data/Commands/Manager/CommandCodes.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ public enum CommandCodes
112112
RotateRight,
113113

114114
// Open
115-
OpenInVSCode,
116-
OpenRepoInVSCode,
115+
OpenInIDE,
116+
OpenRepoInIDE,
117117
OpenProperties,
118118
OpenReleaseNotes,
119119
OpenClassicProperties,

src/Files.App/Data/Commands/Manager/CommandManager.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ public IRichCommand this[HotKey hotKey]
113113
public IRichCommand OpenItem => commands[CommandCodes.OpenItem];
114114
public IRichCommand OpenItemWithApplicationPicker => commands[CommandCodes.OpenItemWithApplicationPicker];
115115
public IRichCommand OpenParentFolder => commands[CommandCodes.OpenParentFolder];
116-
public IRichCommand OpenInVSCode => commands[CommandCodes.OpenInVSCode];
117-
public IRichCommand OpenRepoInVSCode => commands[CommandCodes.OpenRepoInVSCode];
116+
public IRichCommand OpenInVSCode => commands[CommandCodes.OpenInIDE];
117+
public IRichCommand OpenRepoInVSCode => commands[CommandCodes.OpenRepoInIDE];
118118
public IRichCommand OpenProperties => commands[CommandCodes.OpenProperties];
119119
public IRichCommand OpenReleaseNotes => commands[CommandCodes.OpenReleaseNotes];
120120
public IRichCommand OpenClassicProperties => commands[CommandCodes.OpenClassicProperties];
@@ -317,8 +317,8 @@ public IEnumerator<IRichCommand> GetEnumerator() =>
317317
[CommandCodes.OpenItem] = new OpenItemAction(),
318318
[CommandCodes.OpenItemWithApplicationPicker] = new OpenItemWithApplicationPickerAction(),
319319
[CommandCodes.OpenParentFolder] = new OpenParentFolderAction(),
320-
[CommandCodes.OpenInVSCode] = new OpenInVSCodeAction(),
321-
[CommandCodes.OpenRepoInVSCode] = new OpenRepoInVSCodeAction(),
320+
[CommandCodes.OpenInIDE] = new OpenInIDEAction(),
321+
[CommandCodes.OpenRepoInIDE] = new OpenRepoInIDEAction(),
322322
[CommandCodes.OpenProperties] = new OpenPropertiesAction(),
323323
[CommandCodes.OpenReleaseNotes] = new OpenReleaseNotesAction(),
324324
[CommandCodes.OpenClassicProperties] = new OpenClassicPropertiesAction(),
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
// Copyright (c) Files Community
22
// Licensed under the MIT License.
33

4-
using Microsoft.UI.Xaml;
5-
using Microsoft.UI.Xaml.Media;
6-
74
namespace Files.App.Data.Contracts
85
{
96
public interface IDevToolsSettingsService : IBaseSettingsService, INotifyPropertyChanged
@@ -12,5 +9,15 @@ public interface IDevToolsSettingsService : IBaseSettingsService, INotifyPropert
129
/// Gets or sets a value when the Open in IDE button should be displayed on the status bar.
1310
/// </summary>
1411
OpenInIDEOption OpenInIDEOption { get; set; }
12+
13+
/// <summary>
14+
/// Gets or sets the path of the chosen IDE.
15+
/// </summary>
16+
string IDEPath { get; set; }
17+
18+
/// <summary>
19+
/// Gets or sets the name of the chosen IDE.
20+
/// </summary>
21+
string IDEName { get; set; }
1522
}
1623
}

src/Files.App/Helpers/Dialog/DynamicDialogFactory.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,5 +404,25 @@ public static DynamicDialog GetFor_CreateAlternateDataStreamDialog()
404404

405405
return dialog;
406406
}
407+
408+
public static async Task ShowFor_IDEErrorDialog(string friendlyName)
409+
{
410+
var commands = Ioc.Default.GetRequiredService<ICommandManager>();
411+
var dialog = new DynamicDialog(new DynamicDialogViewModel()
412+
{
413+
TitleText = Strings.IDENotLocatedTitle.GetLocalizedResource(),
414+
SubtitleText = string.Format(Strings.IDENotLocatedContent.GetLocalizedResource(), friendlyName),
415+
PrimaryButtonText = Strings.OpenSettings.GetLocalizedResource(),
416+
SecondaryButtonText = Strings.Close.GetLocalizedResource(),
417+
DynamicButtons = DynamicDialogButtons.Primary | DynamicDialogButtons.Secondary,
418+
});
419+
420+
await dialog.TryShowAsync();
421+
422+
if (dialog.DynamicResult is DynamicDialogResult.Primary)
423+
await commands.OpenSettings.ExecuteAsync(
424+
new SettingsNavigationParams() { PageKind = SettingsPageKind.DevToolsPage }
425+
);
426+
}
407427
}
408428
}

src/Files.App/Helpers/Environment/SoftwareHelpers.cs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@ namespace Files.App.Helpers
99
internal static class SoftwareHelpers
1010
{
1111
private const string UninstallRegistryKey = @"Software\Microsoft\Windows\CurrentVersion\Uninstall";
12-
private const string VsRegistryKey = @"SOFTWARE\Microsoft\VisualStudio";
1312

1413
private const string VsCodeName = "Microsoft Visual Studio Code";
1514

16-
1715
public static bool IsVSCodeInstalled()
1816
{
1917
try
@@ -29,25 +27,6 @@ public static bool IsVSCodeInstalled()
2927
}
3028
}
3129

32-
public static bool IsVSInstalled()
33-
{
34-
try
35-
{
36-
var key = Registry.LocalMachine.OpenSubKey(VsRegistryKey);
37-
if (key is null)
38-
return false;
39-
40-
key.Close();
41-
42-
return true;
43-
}
44-
catch (SecurityException)
45-
{
46-
// Handle edge case where OpenSubKey results in SecurityException
47-
return false;
48-
}
49-
}
50-
5130
private static bool ContainsName(RegistryKey? key, string find)
5231
{
5332
if (key is null)

src/Files.App/Services/Settings/DevToolsSettingsService.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@ public OpenInIDEOption OpenInIDEOption
1818
set => Set(value);
1919
}
2020

21+
/// <inheritdoc/>
22+
public string IDEPath
23+
{
24+
get => Get(SoftwareHelpers.IsVSCodeInstalled() ? "code" : string.Empty) ?? string.Empty;
25+
set => Set(value);
26+
}
27+
28+
/// <inheritdoc/>
29+
public string IDEName
30+
{
31+
get => Get(SoftwareHelpers.IsVSCodeInstalled() ? Strings.VisualStudioCode.GetLocalizedResource() : string.Empty) ?? string.Empty;
32+
set => Set(value);
33+
}
34+
2135
protected override void RaiseOnSettingChangedEvent(object sender, SettingChangedEventArgs e)
2236
{
2337
base.RaiseOnSettingChangedEvent(sender, e);

0 commit comments

Comments
 (0)