From 5e1363bf84782fd0484101a651e9a824cb3e5e6b Mon Sep 17 00:00:00 2001 From: Dion Date: Wed, 21 Feb 2024 17:00:58 +0100 Subject: [PATCH] add check && change menu item desktop app --- .../Service/OpenEditorDesktopService.cs | 9 ++- .../IOpenApplicationNativeService.cs | 23 ++++++- .../OpenApplicationNativeService.cs | 51 ++++++++++++++- .../FakeIOpenApplicationNativeService.cs | 10 ++- .../Service/OpenEditorDesktopServiceTest.cs | 25 +++++++- .../OpenApplicationNativeServiceTest.cs | 64 ++++++++++++++++++- starskydesktop/src/app/menu/app-menu.ts | 17 ++--- 7 files changed, 175 insertions(+), 24 deletions(-) diff --git a/starsky/starsky.feature.desktop/Service/OpenEditorDesktopService.cs b/starsky/starsky.feature.desktop/Service/OpenEditorDesktopService.cs index 9af8c1443c..9579cd2b1a 100644 --- a/starsky/starsky.feature.desktop/Service/OpenEditorDesktopService.cs +++ b/starsky/starsky.feature.desktop/Service/OpenEditorDesktopService.cs @@ -42,8 +42,13 @@ public OpenEditorDesktopService(AppSettings appSettings, return ( null, "UseLocalDesktop feature toggle is disabled", [] ); } - var subPathAndImageFormatList = - await _openEditorPreflight.PreflightAsync(subPaths, collections); + if ( !_openApplicationNativeService.DetectToUseOpenApplication() ) + { + return ( null, "OpenEditor is not supported on this configuration", [] ); + } + + var subPathAndImageFormatList = await _openEditorPreflight + .PreflightAsync(subPaths, collections); if ( subPathAndImageFormatList.Count == 0 ) { diff --git a/starsky/starsky.foundation.native/OpenApplicationNative/Interfaces/IOpenApplicationNativeService.cs b/starsky/starsky.foundation.native/OpenApplicationNative/Interfaces/IOpenApplicationNativeService.cs index d8fdb0ff2e..76c6ea6831 100644 --- a/starsky/starsky.foundation.native/OpenApplicationNative/Interfaces/IOpenApplicationNativeService.cs +++ b/starsky/starsky.foundation.native/OpenApplicationNative/Interfaces/IOpenApplicationNativeService.cs @@ -2,7 +2,26 @@ namespace starsky.foundation.native.OpenApplicationNative.Interfaces; public interface IOpenApplicationNativeService { - bool? OpenApplicationAtUrl(List<(string, string)> fullPathAndApplicationUrl); - bool? OpenApplicationAtUrl(List fullPaths, string applicationUrl); + /// + /// Check if the system is supported to open a file + /// Not all configurations are supported + /// + /// true is supported and false is not supported + bool DetectToUseOpenApplication(); + + /// + /// Open with Default Editor + /// Please check DetectToUseOpenApplication() before using this method + /// + /// List first item is fullFilePath, second is ApplicationUrl + /// open = true, null is unsupported + bool? OpenApplicationAtUrl(List<(string fullFilePath, string applicationUrl)> fullPathAndApplicationUrl); + + /// + /// Open with Default Editor + /// Please check DetectToUseOpenApplication() before using this method + /// + /// Paths on disk + /// open = true, null is unsupported bool? OpenDefault(List fullPaths); } diff --git a/starsky/starsky.foundation.native/OpenApplicationNative/OpenApplicationNativeService.cs b/starsky/starsky.foundation.native/OpenApplicationNative/OpenApplicationNativeService.cs index b379ab0ba7..0ce2cc0d12 100644 --- a/starsky/starsky.foundation.native/OpenApplicationNative/OpenApplicationNativeService.cs +++ b/starsky/starsky.foundation.native/OpenApplicationNative/OpenApplicationNativeService.cs @@ -1,3 +1,4 @@ +using System.Runtime.InteropServices; using starsky.foundation.injection; using starsky.foundation.native.Helpers; using starsky.foundation.native.OpenApplicationNative.Helpers; @@ -8,12 +9,56 @@ namespace starsky.foundation.native.OpenApplicationNative; [Service(typeof(IOpenApplicationNativeService), InjectionLifetime = InjectionLifetime.Scoped)] public class OpenApplicationNativeService : IOpenApplicationNativeService { + /// + /// Is Open File supported on this configuration + /// + /// true if supported, false if not supported + public bool DetectToUseOpenApplication() + { + return DetectToUseOpenApplicationInternal(RuntimeInformation.IsOSPlatform, + Environment.UserInteractive); + } + + /// + /// Use to overwrite the RuntimeInformation.IsOSPlatform + /// + internal delegate bool IsOsPlatformDelegate(OSPlatform osPlatform); + + /// + /// Is Open File supported on this configuration + /// + /// RuntimeInformation.IsOSPlatform + /// Environment.UserInteractive + /// true if supported, false if not supported + internal static bool DetectToUseOpenApplicationInternal( + IsOsPlatformDelegate runtimeInformationIsOsPlatform, + bool environmentUserInteractive) + { + // Linux is not supported yet + if ( runtimeInformationIsOsPlatform(OSPlatform.Linux) || + runtimeInformationIsOsPlatform(OSPlatform.FreeBSD) ) + { + return false; + } + + // When running in Windows as Service it does not open the application + // On Mac OS it does open the application + if ( !environmentUserInteractive && runtimeInformationIsOsPlatform(OSPlatform.Windows) ) + { + return false; + } + + return true; + } + + /// /// Open file with specified application /// /// List first item is fullFilePath, second is ApplicationUrl /// true is operation succeed, false failed | null is platform unsupported - public bool? OpenApplicationAtUrl(List<(string, string)> fullPathAndApplicationUrl) + public bool? OpenApplicationAtUrl( + List<(string fullFilePath, string applicationUrl)> fullPathAndApplicationUrl) { if ( fullPathAndApplicationUrl.Count == 0 ) { @@ -42,7 +87,7 @@ public class OpenApplicationNativeService : IOpenApplicationNativeService /// full path style /// applicationUrl /// true is operation succeed, false failed | null is platform unsupported - public bool? OpenApplicationAtUrl(List fullPaths, string applicationUrl) + internal static bool? OpenApplicationAtUrl(List fullPaths, string applicationUrl) { var currentPlatform = OperatingSystemHelper.GetPlatform(); var macOsOpenResult = MacOsOpenUrl.OpenApplicationAtUrl(fullPaths, @@ -55,7 +100,7 @@ public class OpenApplicationNativeService : IOpenApplicationNativeService } internal static List<(List, string)> SortToOpenFilesByApplicationPath( - List<(string, string)> fullPathAndApplicationUrl) + List<(string fullFilePath, string applicationUrl)> fullPathAndApplicationUrl) { // Group applications by their names var groupedApplications = fullPathAndApplicationUrl.GroupBy(x => x.Item2).ToList(); diff --git a/starsky/starskytest/FakeMocks/FakeIOpenApplicationNativeService.cs b/starsky/starskytest/FakeMocks/FakeIOpenApplicationNativeService.cs index df44559387..92dc55a5dc 100644 --- a/starsky/starskytest/FakeMocks/FakeIOpenApplicationNativeService.cs +++ b/starsky/starskytest/FakeMocks/FakeIOpenApplicationNativeService.cs @@ -8,11 +8,14 @@ public class FakeIOpenApplicationNativeService : IOpenApplicationNativeService { private readonly List _fullFilePaths; private readonly string _applicationUrl; + private readonly bool _isSupported; - public FakeIOpenApplicationNativeService(List fullPaths, string applicationUrl) + public FakeIOpenApplicationNativeService(List fullPaths, string applicationUrl, + bool isSupported = true) { _fullFilePaths = fullPaths; _applicationUrl = applicationUrl; + _isSupported = isSupported; } public string FindPath(List fullPaths) @@ -30,6 +33,11 @@ public string FindPath(List fullPaths) return fullFilePath; } + public bool DetectToUseOpenApplication() + { + return _isSupported; + } + public bool? OpenApplicationAtUrl(List<(string, string)> fullPathAndApplicationUrl) { var filesByApplicationPath = diff --git a/starsky/starskytest/starsky.feature.desktop/Service/OpenEditorDesktopServiceTest.cs b/starsky/starskytest/starsky.feature.desktop/Service/OpenEditorDesktopServiceTest.cs index 61a24064bd..1c44104412 100644 --- a/starsky/starskytest/starsky.feature.desktop/Service/OpenEditorDesktopServiceTest.cs +++ b/starsky/starskytest/starsky.feature.desktop/Service/OpenEditorDesktopServiceTest.cs @@ -59,8 +59,8 @@ public async Task OpenAsync_stringInput_HappyFlow() Assert.AreEqual("/test.jpg", list[0].SubPath); Assert.AreEqual("test", list[0].AppPath); } - - + + [TestMethod] public async Task OpenAsync_ListInput_HappyFlow() { @@ -149,4 +149,25 @@ public async Task OpenAsync_ListInput_UseLocalDesktop_Null() Assert.AreEqual("UseLocalDesktop feature toggle is disabled", status); Assert.AreEqual(0, list.Count); } + + [TestMethod] + public async Task OpenAsync_ListInput_UnSupportedPlatform() + { + var fakeService = + new FakeIOpenApplicationNativeService(new List(), string.Empty, false); + + var appSettings = new AppSettings { UseLocalDesktop = true }; + + var preflight = new FakeIOpenEditorPreflight(new List()); + + var service = + new OpenEditorDesktopService(appSettings, fakeService, preflight); + + var (success, status, list) = + ( await service.OpenAsync(new List { "/test.jpg" }, true) ); + + Assert.IsNull(success); + Assert.AreEqual("OpenEditor is not supported on this configuration", status); + Assert.AreEqual(0, list.Count); + } } diff --git a/starsky/starskytest/starsky.foundation.native/OpenApplicationNative/OpenApplicationNativeServiceTest.cs b/starsky/starskytest/starsky.foundation.native/OpenApplicationNative/OpenApplicationNativeServiceTest.cs index 4e9a948723..26ecc336fa 100644 --- a/starsky/starskytest/starsky.foundation.native/OpenApplicationNative/OpenApplicationNativeServiceTest.cs +++ b/starsky/starskytest/starsky.foundation.native/OpenApplicationNative/OpenApplicationNativeServiceTest.cs @@ -10,6 +10,7 @@ using starsky.foundation.native.OpenApplicationNative.Helpers; using starsky.foundation.platform.Models; using starskytest.FakeCreateAn.CreateFakeStarskyExe; +using starskytest.starsky.foundation.native.Helpers; namespace starskytest.starsky.foundation.native.OpenApplicationNative; @@ -105,7 +106,7 @@ public async Task Service_OpenDefault_HappyFlow__WindowsOnly() [TestMethod] public void OpenApplicationAtUrl_ZeroItems_SoFalse() { - var result = new OpenApplicationNativeService().OpenApplicationAtUrl([], "app"); + var result = OpenApplicationNativeService.OpenApplicationAtUrl([], "app"); // Linux and FreeBSD are not supported if ( OperatingSystemHelper.GetPlatform() == OSPlatform.Linux || @@ -234,4 +235,65 @@ public void SortToOpenFilesByApplicationPath_MultipleApplications_ReturnsMultipl Assert.IsTrue(result.Exists(x => x.Item2 == "app2")); Assert.IsTrue(result.Exists(x => x.Item2 == "app3")); } + + [TestMethod] + public void DetectToUseOpenApplication_Default() + { + var result = new OpenApplicationNativeService().DetectToUseOpenApplication(); + + // Depending on the environment + if ( !Environment.UserInteractive && new AppSettings().IsWindows ) + { + Assert.IsFalse(result); + return; + } + + // Linux and FreeBSD are not supported + if ( OperatingSystemHelper.GetPlatform() == OSPlatform.Linux || + OperatingSystemHelper.GetPlatform() == OSPlatform.FreeBSD ) + { + Assert.IsFalse(result); + return; + } + + Assert.IsTrue(result); + } + + [TestMethod] + public void DetectToUseOpenApplicationInternal_Windows_AsWindowsService_InteractiveFalse() + { + var result = + OpenApplicationNativeService.DetectToUseOpenApplicationInternal( + FakeOsOverwrite.IsWindows, + false); + Assert.IsFalse(result); + } + + [TestMethod] + public void DetectToUseOpenApplicationInternal_MacOS_AsLaunchService_InteractiveTrue() + { + var result = + OpenApplicationNativeService.DetectToUseOpenApplicationInternal(FakeOsOverwrite.IsMacOs, + false); + Assert.IsTrue(result); + } + + [TestMethod] + public void DetectToUseOpenApplicationInternal_MacOS_Interactive_InteractiveTrue() + { + var result = + OpenApplicationNativeService.DetectToUseOpenApplicationInternal(FakeOsOverwrite.IsMacOs, + true); + Assert.IsTrue(result); + } + + + [TestMethod] + public void DetectToUseOpenApplicationInternal_Linux_Interactive_Interactive_False() + { + var result = + OpenApplicationNativeService.DetectToUseOpenApplicationInternal(FakeOsOverwrite.IsLinux, + true); + Assert.IsFalse(result); + } } diff --git a/starskydesktop/src/app/menu/app-menu.ts b/starskydesktop/src/app/menu/app-menu.ts index 0b20d221a7..eca298102c 100644 --- a/starskydesktop/src/app/menu/app-menu.ts +++ b/starskydesktop/src/app/menu/app-menu.ts @@ -151,9 +151,7 @@ function AppMenu() { label: "Open in browser", // eslint-disable-next-line @typescript-eslint/no-misused-promises click: async () => { - await shell.openExternal( - BrowserWindow.getFocusedWindow().webContents.getURL() - ); + await shell.openExternal(BrowserWindow.getFocusedWindow().webContents.getURL()); }, }, ], @@ -189,12 +187,7 @@ function AppMenu() { }, { role: "zoom" }, ...(isMac - ? [ - { type: "separator" }, - { role: "front" }, - { type: "separator" }, - { role: "window" }, - ] + ? [{ type: "separator" }, { role: "front" }, { type: "separator" }, { role: "window" }] : [{ role: "close" }]), ], }, @@ -205,7 +198,7 @@ function AppMenu() { label: "Documentation website", // eslint-disable-next-line @typescript-eslint/no-misused-promises click: async () => { - await shell.openExternal("https://docs.qdraw.nl/download"); + await shell.openExternal("https://docs.qdraw.nl/docs/getting-started/first-steps"); }, }, { @@ -213,9 +206,7 @@ function AppMenu() { // Referenced from HealthCheckForUpdates // eslint-disable-next-line @typescript-eslint/no-misused-promises click: async () => { - await shell.openExternal( - "https://github.com/qdraw/starsky/releases/latest" - ); + await shell.openExternal("https://github.com/qdraw/starsky/releases/latest"); }, }, ],