diff --git a/app/src/main/java/io/xpipe/app/browser/file/BrowserFileListComp.java b/app/src/main/java/io/xpipe/app/browser/file/BrowserFileListComp.java index e3652b470..83aa20f08 100644 --- a/app/src/main/java/io/xpipe/app/browser/file/BrowserFileListComp.java +++ b/app/src/main/java/io/xpipe/app/browser/file/BrowserFileListComp.java @@ -313,8 +313,10 @@ public final class BrowserFileListComp extends SimpleComp { .filter(browserAction -> browserAction.getShortcut().match(event)) .findAny(); action.ifPresent(browserAction -> { + // Prevent concurrent modification by creating copy on platform thread + var selectionCopy = new ArrayList<>(selected); ThreadHelper.runFailableAsync(() -> { - browserAction.execute(fileList.getFileSystemModel(), selected); + browserAction.execute(fileList.getFileSystemModel(), selectionCopy); }); event.consume(); }); diff --git a/app/src/main/java/io/xpipe/app/browser/session/BrowserSessionComp.java b/app/src/main/java/io/xpipe/app/browser/session/BrowserSessionComp.java index 3bc64788f..1a1103446 100644 --- a/app/src/main/java/io/xpipe/app/browser/session/BrowserSessionComp.java +++ b/app/src/main/java/io/xpipe/app/browser/session/BrowserSessionComp.java @@ -122,7 +122,7 @@ public class BrowserSessionComp extends SimpleComp { AnchorPane.setRightAnchor(struc.get(), 0.0); }) .styleClass("tab-loading-indicator"); - var loadingStack = new AnchorComp(List.of(tabs, loadingIndicator)); + var loadingStack = new AnchorComp(List.of(tabs)); var splitPane = new SideSplitPaneComp(vertical, loadingStack) .withInitialWidth(AppLayoutModel.get().getSavedState().getBrowserConnectionsWidth()) .withOnDividerChange(d -> { @@ -148,18 +148,7 @@ public class BrowserSessionComp extends SimpleComp { } }); }); - - var topBackground = Comp.hspacer().styleClass("top-spacer"); - var stack = new StackComp(List.of(topBackground, splitPane)); - stack.apply(struc -> { - struc.get().setAlignment(Pos.TOP_CENTER); - var spacer = (Region) struc.get().lookup(".top-spacer"); - spacer.prefHeightProperty().bind(tabs.getHeaderHeight()); - spacer.minHeightProperty().bind(spacer.prefHeightProperty()); - spacer.maxHeightProperty().bind(spacer.prefHeightProperty()); - }); - var r = stack.createRegion(); - r.getStyleClass().add("browser"); - return r; + splitPane.styleClass("browser"); + return splitPane.createRegion(); } } diff --git a/app/src/main/java/io/xpipe/app/browser/session/BrowserSessionTabsComp.java b/app/src/main/java/io/xpipe/app/browser/session/BrowserSessionTabsComp.java index 99e631196..a3383677b 100644 --- a/app/src/main/java/io/xpipe/app/browser/session/BrowserSessionTabsComp.java +++ b/app/src/main/java/io/xpipe/app/browser/session/BrowserSessionTabsComp.java @@ -6,6 +6,7 @@ import io.xpipe.app.core.AppI18n; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.SimpleComp; import io.xpipe.app.fxcomps.impl.PrettyImageHelper; +import io.xpipe.app.fxcomps.impl.StackComp; import io.xpipe.app.fxcomps.impl.TooltipAugment; import io.xpipe.app.fxcomps.util.LabelGraphic; import io.xpipe.app.fxcomps.util.PlatformThread; @@ -56,7 +57,18 @@ public class BrowserSessionTabsComp extends SimpleComp { } public Region createSimple() { - return createTabPane(); + var tabs = createTabPane(); + var topBackground = Comp.hspacer().styleClass("top-spacer").createRegion(); + leftPadding.subscribe(number -> { + StackPane.setMargin(topBackground, new Insets(0, 0, 0, -number.doubleValue())); + }); + var stack = new StackPane(topBackground, tabs); + stack.setAlignment(Pos.TOP_CENTER); + topBackground.prefHeightProperty().bind(headerHeight); + topBackground.minHeightProperty().bind(topBackground.prefHeightProperty()); + topBackground.maxHeightProperty().bind(topBackground.prefHeightProperty()); + topBackground.prefWidthProperty().bind(tabs.widthProperty()); + return stack; } private TabPane createTabPane() { @@ -69,9 +81,6 @@ public class BrowserSessionTabsComp extends SimpleComp { Styles.toggleStyleClass(tabs, TabPane.STYLE_CLASS_FLOATING); toggleStyleClass(tabs, DENSE); - var dummy = new Tab(); - tabs.getTabs().add(dummy); - tabs.skinProperty().subscribe(newValue -> { if (newValue != null) { Platform.runLater(() -> { @@ -100,8 +109,6 @@ public class BrowserSessionTabsComp extends SimpleComp { .bind(Bindings.createObjectBinding( () -> new Insets(2, 0, 4, -leftPadding.get() + 2), leftPadding)); headerHeight.bind(headerArea.heightProperty()); - - tabs.getTabs().remove(dummy); }); } }); diff --git a/app/src/main/java/io/xpipe/app/util/ShellStoreFormat.java b/app/src/main/java/io/xpipe/app/util/ShellStoreFormat.java index b6dff5ffa..e735b991b 100644 --- a/app/src/main/java/io/xpipe/app/util/ShellStoreFormat.java +++ b/app/src/main/java/io/xpipe/app/util/ShellStoreFormat.java @@ -60,7 +60,8 @@ public class ShellStoreFormat { String[] states; public String format() { - var lic = licensedFeature != null ? "[" + licensedFeature.getDescriptionSuffix().orElse(null) + "+]" : null; + var licenseReq = licensedFeature != null ? licensedFeature.getDescriptionSuffix().orElse(null) : null; + var lic = licenseReq != null ? "[" + licenseReq + "+]" : null; var name = this.name; var state = getStates() != null ? Arrays.stream(getStates()).filter(s -> s != null).map(s -> "[" + s + "]").collect(Collectors.joining(" ")) : null; if (state != null && state.isEmpty()) { diff --git a/app/src/main/resources/io/xpipe/app/resources/style/browser.css b/app/src/main/resources/io/xpipe/app/resources/style/browser.css index f748fd086..6f41c1e48 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/browser.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/browser.css @@ -232,7 +232,7 @@ -fx-background-insets: 0, 7 0 0 0; -fx-border-width: 1; -fx-border-color: -color-border-default; - -fx-background-color: -color-foreground-base, -color-foreground-base; + -fx-background-color: -color-foreground-base, -color-bg-default; } .browser .browser-content-container { diff --git a/lang/proc/strings/translations_en.properties b/lang/proc/strings/translations_en.properties index a0d06129e..675f5e4b2 100644 --- a/lang/proc/strings/translations_en.properties +++ b/lang/proc/strings/translations_en.properties @@ -403,3 +403,4 @@ addHypervisor=Add hypervisor serialConsole=Serial console interactiveTerminal=Interactive terminal editDomain=Edit domain +libvirt=libvirt domains