diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserContextMenu.java b/app/src/main/java/io/xpipe/app/browser/BrowserContextMenu.java index 15e1c1ed..189ee190 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserContextMenu.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserContextMenu.java @@ -4,9 +4,11 @@ import io.xpipe.app.browser.action.BranchAction; import io.xpipe.app.browser.action.BrowserAction; import io.xpipe.app.browser.action.LeafAction; import io.xpipe.app.core.AppFont; +import io.xpipe.app.util.LicenseProvider; import javafx.scene.control.ContextMenu; import javafx.scene.control.Menu; import javafx.scene.control.SeparatorMenuItem; +import org.kordamp.ikonli.javafx.FontIcon; import java.util.ArrayList; import java.util.List; @@ -78,6 +80,12 @@ final class BrowserContextMenu extends ContextMenu { m.setGraphic(graphic); } m.setDisable(!a.isActive(model, used)); + + if (la.getProFeatureId() != null && !LicenseProvider.get().getFeature(la.getProFeatureId()).isSupported()) { + m.setDisable(true); + m.setGraphic(new FontIcon("mdi2p-professional-hexagon")); + } + getItems().add(m); } } diff --git a/app/src/main/java/io/xpipe/app/browser/OpenFileSystemModel.java b/app/src/main/java/io/xpipe/app/browser/OpenFileSystemModel.java index ee224b1d..2f24f164 100644 --- a/app/src/main/java/io/xpipe/app/browser/OpenFileSystemModel.java +++ b/app/src/main/java/io/xpipe/app/browser/OpenFileSystemModel.java @@ -1,5 +1,6 @@ package io.xpipe.app.browser; +import io.xpipe.app.browser.action.BrowserAction; import io.xpipe.app.comp.base.ModalOverlayComp; import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.storage.DataStorage; @@ -373,7 +374,11 @@ public final class OpenFileSystemModel { this.local = fs.getShell() .map(shellControl -> shellControl.hasLocalSystemAccess()) .orElse(false); + this.cache.init(); + for (BrowserAction b : BrowserAction.ALL) { + b.init(this); + } }); } diff --git a/app/src/main/java/io/xpipe/app/browser/action/BrowserAction.java b/app/src/main/java/io/xpipe/app/browser/action/BrowserAction.java index 7bf8993d..36b107ca 100644 --- a/app/src/main/java/io/xpipe/app/browser/action/BrowserAction.java +++ b/app/src/main/java/io/xpipe/app/browser/action/BrowserAction.java @@ -39,6 +39,12 @@ public interface BrowserAction { .orElseThrow(); } + default void init(OpenFileSystemModel model) throws Exception {} + + default String getProFeatureId() { + return null; + } + default Node getIcon(OpenFileSystemModel model, List entries) { return null; } diff --git a/app/src/main/java/io/xpipe/app/browser/action/LeafAction.java b/app/src/main/java/io/xpipe/app/browser/action/LeafAction.java index bb40daaf..03647c96 100644 --- a/app/src/main/java/io/xpipe/app/browser/action/LeafAction.java +++ b/app/src/main/java/io/xpipe/app/browser/action/LeafAction.java @@ -5,10 +5,12 @@ import io.xpipe.app.browser.OpenFileSystemModel; import io.xpipe.app.fxcomps.impl.FancyTooltipAugment; import io.xpipe.app.fxcomps.util.Shortcuts; import io.xpipe.app.util.BooleanScope; +import io.xpipe.app.util.LicenseProvider; import io.xpipe.app.util.ThreadHelper; import javafx.beans.property.SimpleStringProperty; import javafx.scene.control.Button; import javafx.scene.control.MenuItem; +import org.kordamp.ikonli.javafx.FontIcon; import java.util.List; import java.util.function.UnaryOperator; @@ -48,6 +50,11 @@ public interface LeafAction extends BrowserAction { b.setDisable(!isActive(model, selected)); }); + if (getProFeatureId() != null && !LicenseProvider.get().getFeature(getProFeatureId()).isSupported()) { + b.setDisable(true); + b.setGraphic(new FontIcon("mdi2p-professional-hexagon")); + } + return b; } @@ -70,6 +77,12 @@ public interface LeafAction extends BrowserAction { } mi.setMnemonicParsing(false); mi.setDisable(!isActive(model, selected)); + + if (getProFeatureId() != null && !LicenseProvider.get().getFeature(getProFeatureId()).isSupported()) { + mi.setDisable(true); + mi.setGraphic(new FontIcon("mdi2p-professional-hexagon")); + } + return mi; } diff --git a/app/src/main/java/io/xpipe/app/prefs/ExternalTerminalType.java b/app/src/main/java/io/xpipe/app/prefs/ExternalTerminalType.java index e90cad94..1154479d 100644 --- a/app/src/main/java/io/xpipe/app/prefs/ExternalTerminalType.java +++ b/app/src/main/java/io/xpipe/app/prefs/ExternalTerminalType.java @@ -250,7 +250,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue { .addQuoted(configuration.getTitle()) .add("--") .addFile(configuration.getScriptFile()) - .build(pc); + .buildString(pc); // In order to fix this bug which also affects us: // https://askubuntu.com/questions/1148475/launching-gnome-terminal-from-vscode toExecute = "GNOME_TERMINAL_SCREEN=\"\" nohup " + toExecute + " /dev/null & disown"; @@ -789,7 +789,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue { var toExecute = executable + " " + toCommand(configuration.getTitle(), configuration.getScriptFile()) - .build(pc); + .buildString(pc); if (pc.getOsType().equals(OsType.WINDOWS)) { toExecute = "start \"" + configuration.getTitle() + "\" " + toExecute; } else { diff --git a/app/src/main/java/io/xpipe/app/util/ApplicationHelper.java b/app/src/main/java/io/xpipe/app/util/ApplicationHelper.java index 40236a4c..71fae69a 100644 --- a/app/src/main/java/io/xpipe/app/util/ApplicationHelper.java +++ b/app/src/main/java/io/xpipe/app/util/ApplicationHelper.java @@ -40,6 +40,16 @@ public class ApplicationHelper { processControl.getShellDialect().getWhichCommand(executable)); } + public static boolean isInPathSilent(ShellControl processControl, String executable) { + try { + return processControl.executeSimpleBooleanCommand( + processControl.getShellDialect().getWhichCommand(executable)); + } catch (Exception e) { + ErrorEvent.fromThrowable(e).handle(); + return false; + } + } + public static void checkIsInPath( ShellControl processControl, String executable, String displayName, DataStoreEntry connection) throws Exception { diff --git a/core/src/main/java/io/xpipe/core/process/CommandBuilder.java b/core/src/main/java/io/xpipe/core/process/CommandBuilder.java index 2e537893..a5e25547 100644 --- a/core/src/main/java/io/xpipe/core/process/CommandBuilder.java +++ b/core/src/main/java/io/xpipe/core/process/CommandBuilder.java @@ -131,7 +131,7 @@ public class CommandBuilder { return sub.buildSimple(); } - return sub.build(sc); + return sub.buildString(sc); }); return this; } @@ -188,7 +188,7 @@ public class CommandBuilder { return String.join(" ", list); } - public String build(ShellControl sc) throws Exception { + public String buildString(ShellControl sc) throws Exception { var s = buildBase(sc); LinkedHashMap map = new LinkedHashMap<>(); for (var e : environmentVariables.entrySet()) { @@ -200,7 +200,7 @@ public class CommandBuilder { return sc.getShellDialect().addInlineVariablesToCommand(map, s); } - public CommandControl buildCommand(ShellControl sc) { + public CommandControl build(ShellControl sc) { return sc.command(this); } diff --git a/core/src/main/java/io/xpipe/core/process/ShellControl.java b/core/src/main/java/io/xpipe/core/process/ShellControl.java index 9997c2e3..bf10fc10 100644 --- a/core/src/main/java/io/xpipe/core/process/ShellControl.java +++ b/core/src/main/java/io/xpipe/core/process/ShellControl.java @@ -234,7 +234,7 @@ public interface ShellControl extends ProcessControl { return command(sc-> { var b = CommandBuilder.of(); builder.accept(b); - return b.build(sc); + return b.buildString(sc); }); } @@ -243,7 +243,7 @@ public interface ShellControl extends ProcessControl { } default CommandControl command(CommandBuilder builder) { - return command(shellProcessControl -> builder.build(shellProcessControl)); + return command(shellProcessControl -> builder.buildString(shellProcessControl)); } void exitAndWait() throws IOException;