diff --git a/app/src/main/java/io/xpipe/app/hub/category/StoreCategoryComp.java b/app/src/main/java/io/xpipe/app/hub/category/StoreCategoryComp.java index 313f6daa7..7687fadad 100644 --- a/app/src/main/java/io/xpipe/app/hub/category/StoreCategoryComp.java +++ b/app/src/main/java/io/xpipe/app/hub/category/StoreCategoryComp.java @@ -70,8 +70,13 @@ public class StoreCategoryComp extends SimpleRegionBuilder { }) .build(); - var contextMenu = new ContextMenuWrapper(() -> createContextMenu()); var contextMenuShowing = new SimpleBooleanProperty(); + var contextMenu = new ContextMenuWrapper(() -> { + var cm = createContextMenu(); + contextMenuShowing.unbind(); + contextMenuShowing.bind(cm.showingProperty()); + return cm; + }); var expandIcon = Bindings.createObjectBinding( () -> { diff --git a/app/src/main/java/io/xpipe/app/hub/category/StoreCategoryWrapper.java b/app/src/main/java/io/xpipe/app/hub/category/StoreCategoryWrapper.java index c640ccc73..d4f8eb858 100644 --- a/app/src/main/java/io/xpipe/app/hub/category/StoreCategoryWrapper.java +++ b/app/src/main/java/io/xpipe/app/hub/category/StoreCategoryWrapper.java @@ -191,7 +191,7 @@ public class StoreCategoryWrapper { .equals(storeCategoryWrapper.getCategory().getParentCategory())) .sorted(comparator) .toList()); - parent = category.getParentCategory() != null ? StoreViewState.get().getCategoryWrapper(category.getParentCategory()) : null; + parent = category.getParentCategory() != null ? StoreViewState.get().getCategoryWrapper(category.getParentCategory()).orElse(null) : null; shownChildren.setContent(children.getList().stream() .filter(wrapper -> { var op = StoreViewState.get().getCategoryDragOperation().getValue(); @@ -376,7 +376,7 @@ public class StoreCategoryWrapper { } var first = l.getFirst(); - first.insertSiblingCategory(first, false); + first.insertSiblingCategory(selection, false); } public Property nameProperty() { diff --git a/app/src/main/java/io/xpipe/app/hub/entry/StoreEntryBadge.java b/app/src/main/java/io/xpipe/app/hub/entry/StoreEntryBadge.java index e4d5b2e31..3dd8fc661 100644 --- a/app/src/main/java/io/xpipe/app/hub/entry/StoreEntryBadge.java +++ b/app/src/main/java/io/xpipe/app/hub/entry/StoreEntryBadge.java @@ -201,14 +201,8 @@ public interface StoreEntryBadge { var busy = new SimpleBooleanProperty(); return of("mdi2s-server-network-outline", effective).withAction(new Action() { - private ContextMenu contextMenu; - - private void buildContextMenu(HostAddress has) { - if (contextMenu == null) { - contextMenu = new ContextMenu(); - } - - contextMenu.getItems().clear(); + private ContextMenu buildContextMenu(HostAddress has) { + var contextMenu = new ContextMenu(); for (var a : has.getAvailable()) { var i = new MenuItem(); i.setText(a); @@ -219,6 +213,7 @@ public interface StoreEntryBadge { }); contextMenu.getItems().add(i); } + return contextMenu; } @Override @@ -252,8 +247,7 @@ public interface StoreEntryBadge { Platform.runLater(() -> { var cm = new ContextMenuWrapper(() -> { - buildContextMenu(addr); - return contextMenu; + return buildContextMenu(addr); }); cm.show(b, Side.BOTTOM); }); diff --git a/app/src/main/java/io/xpipe/app/hub/list/StoreViewState.java b/app/src/main/java/io/xpipe/app/hub/list/StoreViewState.java index 3711df8e6..1bd50dc8c 100644 --- a/app/src/main/java/io/xpipe/app/hub/list/StoreViewState.java +++ b/app/src/main/java/io/xpipe/app/hub/list/StoreViewState.java @@ -796,12 +796,11 @@ public class StoreViewState { .orElseThrow(); } - public StoreCategoryWrapper getCategoryWrapper(UUID uuid) { + public Optional getCategoryWrapper(UUID uuid) { return categories.getList().stream() .filter(storeCategoryWrapper -> storeCategoryWrapper.getCategory().getUuid().equals(uuid)) - .findFirst() - .orElseThrow(); + .findFirst(); } public StoreCategoryWrapper getCategoryWrapper(DataStoreCategory entry) { diff --git a/app/src/main/java/io/xpipe/app/rdp/MicrosoftRdpClient.java b/app/src/main/java/io/xpipe/app/rdp/MicrosoftRdpClient.java index 4b77305d9..4ff826c3e 100644 --- a/app/src/main/java/io/xpipe/app/rdp/MicrosoftRdpClient.java +++ b/app/src/main/java/io/xpipe/app/rdp/MicrosoftRdpClient.java @@ -145,7 +145,6 @@ public abstract class MicrosoftRdpClient implements ExternalApplicationType.Inst private final boolean useSystemDisplayScale; private static final int CRED_TYPE_GENERIC = 1; - private static final int CRED_TYPE_DOMAIN_PASSWORD = 2; private static final int CRED_PERSIST_SESSION = 1; private static final Set storedCredentials = new HashSet(); @@ -153,7 +152,7 @@ public abstract class MicrosoftRdpClient implements ExternalApplicationType.Inst public static void reset() { synchronized (storedCredentials) { for (String s : storedCredentials) { - AuthModuleProvider.get().deleteWindowsCredential(s, CRED_PERSIST_SESSION); + AuthModuleProvider.get().deleteWindowsCredential(s, CRED_TYPE_GENERIC); } } } @@ -212,7 +211,7 @@ public abstract class MicrosoftRdpClient implements ExternalApplicationType.Inst for (String storedTarget : storedTargets) { GlobalTimer.delay(() -> { - AuthModuleProvider.get().deleteWindowsCredential(storedTarget, CRED_PERSIST_SESSION); + AuthModuleProvider.get().deleteWindowsCredential(storedTarget, CRED_TYPE_GENERIC); }, Duration.ofSeconds(120)); } synchronized (storedCredentials) { @@ -237,7 +236,7 @@ public abstract class MicrosoftRdpClient implements ExternalApplicationType.Inst return !p.isDialog(); }, ignored -> { for (String storedTarget : storedTargets) { - AuthModuleProvider.get().deleteWindowsCredential(storedTarget, CRED_PERSIST_SESSION); + AuthModuleProvider.get().deleteWindowsCredential(storedTarget, CRED_TYPE_GENERIC); } }); } diff --git a/app/src/main/java/io/xpipe/app/terminal/TerminalLauncherManager.java b/app/src/main/java/io/xpipe/app/terminal/TerminalLauncherManager.java index 608f0f671..3dedfd170 100644 --- a/app/src/main/java/io/xpipe/app/terminal/TerminalLauncherManager.java +++ b/app/src/main/java/io/xpipe/app/terminal/TerminalLauncherManager.java @@ -21,16 +21,16 @@ public class TerminalLauncherManager { TerminalView.get().addListener(new TerminalView.Listener() { @Override public void onSessionClosed(TerminalView.ShellSession session) { - var affectedEntry = entries.values().stream() - .filter(terminalLaunchRequest -> { - return terminalLaunchRequest.getRequest().equals(session.getRequest()); - }) - .findFirst(); - if (affectedEntry.isEmpty()) { - return; - } + synchronized (entries) { + var affectedEntry = entries.values().stream().filter(terminalLaunchRequest -> { + return terminalLaunchRequest.getRequest().equals(session.getRequest()); + }).findFirst(); + if (affectedEntry.isEmpty()) { + return; + } - affectedEntry.get().abort(); + affectedEntry.get().abort(); + } } }); } @@ -95,8 +95,8 @@ public class TerminalLauncherManager { req = entries.get(request); } - if (req.getShellPid() != -1) { - ProcessHandle current = ProcessHandle.of(pid).orElseThrow(); + if (req != null && req.getShellPid() != -1) { + ProcessHandle current = ProcessHandle.of(pid).orElseThrow(() -> new BeaconClientException("Unknown process " + pid)); do { if (current.pid() == req.getShellPid()) { return; diff --git a/app/src/main/java/io/xpipe/app/util/ContextMenuWrapper.java b/app/src/main/java/io/xpipe/app/util/ContextMenuWrapper.java index edb453e49..554aef494 100644 --- a/app/src/main/java/io/xpipe/app/util/ContextMenuWrapper.java +++ b/app/src/main/java/io/xpipe/app/util/ContextMenuWrapper.java @@ -31,7 +31,9 @@ public class ContextMenuWrapper { @Getter private ContextMenu contextMenu; - public ContextMenuWrapper(Supplier contextMenuSupplier) {this.contextMenuSupplier = contextMenuSupplier;} + public ContextMenuWrapper(Supplier contextMenuSupplier) { + this.contextMenuSupplier = contextMenuSupplier; + } public ContextMenuWrapper withCustomKeyHandling() { customKeyHandling = true; @@ -76,14 +78,11 @@ public class ContextMenuWrapper { } } - private ContextMenu getOrCreate() { - if (contextMenu == null) { - contextMenu = contextMenuSupplier.get(); - if (contextMenu != null) { - applyFixes(); - } + private void create() { + contextMenu = contextMenuSupplier.get(); + if (contextMenu != null) { + applyFixes(); } - return contextMenu; } public boolean isHidden() { @@ -98,16 +97,7 @@ public class ContextMenuWrapper { for (ContextMenu cm : allContextMenus) { cm.hide(); } - } - - private void hideOthers(boolean includeSelf) { - for (ContextMenu cm : allContextMenus) { - if (!includeSelf && cm.equals(contextMenu)) { - continue; - } - - cm.hide(); - } + allContextMenus.clear(); } public void hide() { @@ -121,16 +111,17 @@ public class ContextMenuWrapper { return true; } - var cm = getOrCreate(); - if (cm != null) { + create(); + + if (contextMenu != null) { // Prevent NPE in show() if (contextMenu.getScene() == null || r == null || r.getScene() == null) { return false; } - cm.show(r, side, 0, 0); + contextMenu.show(r, side, 0, 0); - allContextMenus.add(cm); + allContextMenus.add(contextMenu); return true; } else { return false; @@ -142,15 +133,16 @@ public class ContextMenuWrapper { return true; } - var cm = getOrCreate(); - if (cm != null) { + create(); + + if (contextMenu != null) { // Prevent NPE in show() if (contextMenu.getScene() == null || r == null || r.getScene() == null) { return false; } - cm.show(r, x, y); - allContextMenus.add(cm); + contextMenu.show(r, x, y); + allContextMenus.add(contextMenu); return true; } else { return false; @@ -168,7 +160,7 @@ public class ContextMenuWrapper { } var showing = isShowing(); - hideOthers(showing); + hideAll(); if (!showing && show(r, side)) { event.consume(); } @@ -178,7 +170,7 @@ public class ContextMenuWrapper { public void installOnMouseClick(Region r, Predicate mouseEventCheck, boolean showAtLocation) { r.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> { if (mouseEventCheck != null && mouseEventCheck.test(event)) { - hideOthers(showAtLocation); + hideAll(); var shown = (showAtLocation && show(r, event.getScreenX(), event.getScreenY())) || (!showAtLocation && show(r, Side.BOTTOM)); if (shown) { event.consume(); @@ -203,7 +195,7 @@ public class ContextMenuWrapper { if (keyEventCheck != null) { if (keyEventCheck.test(event)) { var showing = isShowing(); - hideOthers(showing); + hideAll(); if (!showing && show(r, Side.BOTTOM)) { event.consume(); }