This commit is contained in:
crschnick
2026-03-20 07:34:47 +00:00
parent fe64b20dd2
commit fc6be847fe
14 changed files with 56 additions and 30 deletions

View File

@@ -4,7 +4,7 @@ import io.xpipe.app.comp.SimpleRegionBuilder;
import io.xpipe.app.comp.base.FilterComp;
import io.xpipe.app.comp.base.HorizontalComp;
import io.xpipe.app.core.AppFontSizes;
import io.xpipe.app.hub.comp.DataStoreCategoryChoiceComp;
import io.xpipe.app.hub.comp.StoreCategoryChoiceComp;
import io.xpipe.app.hub.comp.StoreCategoryWrapper;
import io.xpipe.app.hub.comp.StoreViewState;
import io.xpipe.app.util.ObservableSubscriber;
@@ -28,7 +28,7 @@ public final class BrowserConnectionListFilterComp extends SimpleRegionBuilder {
@Override
protected Region createSimple() {
var category = new DataStoreCategoryChoiceComp(
var category = new StoreCategoryChoiceComp(
StoreViewState.get().getAllConnectionsCategory(),
StoreViewState.get().getActiveCategory(),
this.category,

View File

@@ -590,7 +590,7 @@ public final class BrowserFileSystemTabModel extends BrowserStoreSessionTab<File
}
// If we docked once, we don't want to break it by opening new tabs in maybe still docked tabs
var preferTabs = !wasTerminalDocked && !dock;
var preferTabs = !TerminalDockHubManager.get().getDockModel().isRunning() && !wasTerminalDocked && !dock;
wasTerminalDocked = wasTerminalDocked || dock;
TerminalLaunch.builder()

View File

@@ -3,6 +3,7 @@ package io.xpipe.app.browser.file;
import io.xpipe.app.browser.icon.BrowserIcons;
import io.xpipe.app.comp.base.ModalOverlay;
import io.xpipe.app.core.window.AppDialog;
import io.xpipe.app.core.window.AppMainWindow;
import io.xpipe.app.ext.FileEntry;
import io.xpipe.app.ext.FileKind;
import io.xpipe.app.platform.BooleanAnimationTimer;
@@ -14,6 +15,7 @@ import io.xpipe.app.util.ThreadHelper;
import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ListChangeListener;
import javafx.css.PseudoClass;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.control.ContextMenu;
@@ -264,7 +266,9 @@ public class BrowserQuickAccessContextMenu extends ContextMenu {
}
});
new BooleanAnimationTimer(hover, 100, () -> {
expandDirectoryMenu(empty);
if (!keyBasedNavigation) {
expandDirectoryMenu(empty);
}
})
.start();
}

View File

@@ -34,17 +34,12 @@ public class UnzipActionProvider implements BrowserActionProvider {
public void executeImpl() throws Exception {
var sc = model.getFileSystem().getShell().orElseThrow();
if (sc.getOsType() == OsType.WINDOWS) {
if (ShellDialects.isPowershell(sc)) {
sc.enforceDialect(ShellDialects.POWERSHELL, p -> {
for (BrowserEntry entry : getEntries()) {
runPowershellCommand(sc, model, entry);
runPowershellCommand(p, model, entry);
}
} else {
try (var sub = sc.subShell(ShellDialects.POWERSHELL)) {
for (BrowserEntry entry : getEntries()) {
runPowershellCommand(sub, model, entry);
}
}
}
return null;
});
} else {
for (BrowserEntry entry : getEntries()) {
var command = CommandBuilder.of()

View File

@@ -5,6 +5,7 @@ import io.xpipe.app.browser.action.BrowserActionProvider;
import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.ext.FileKind;
import io.xpipe.app.process.CommandBuilder;
import io.xpipe.app.process.ShellControl;
import io.xpipe.app.process.ShellDialects;
import io.xpipe.core.FilePath;
import io.xpipe.core.OsType;
@@ -53,13 +54,10 @@ public class ZipActionProvider implements BrowserActionProvider {
}
}
if (ShellDialects.isPowershell(sc)) {
sc.command(command).withWorkingDirectory(base).execute();
} else {
try (var sub = sc.subShell(ShellDialects.POWERSHELL)) {
sub.command(command).withWorkingDirectory(base).execute();
}
}
sc.enforceDialect(ShellDialects.POWERSHELL, p -> {
p.command(command).withWorkingDirectory(base).execute();
return null;
});
} else {
var command = CommandBuilder.of().add("zip", "-q", "-y", "-r", "-");
for (BrowserEntry entry : getEntries()) {

View File

@@ -1,6 +1,7 @@
package io.xpipe.app.hub.comp;
import io.xpipe.app.comp.SimpleRegionBuilder;
import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.app.platform.PlatformThread;
import javafx.beans.property.Property;
@@ -15,7 +16,7 @@ import lombok.Value;
import java.util.function.Predicate;
public class DataStoreCategoryChoiceComp extends SimpleRegionBuilder {
public class StoreCategoryChoiceComp extends SimpleRegionBuilder {
private final StoreCategoryWrapper root;
private final Property<StoreCategoryWrapper> external;
@@ -23,7 +24,7 @@ public class DataStoreCategoryChoiceComp extends SimpleRegionBuilder {
private final boolean applyExternalInitially;
private final Predicate<StoreCategoryWrapper> filter;
public DataStoreCategoryChoiceComp(
public StoreCategoryChoiceComp(
StoreCategoryWrapper root,
Property<StoreCategoryWrapper> external,
Property<StoreCategoryWrapper> value,
@@ -57,7 +58,7 @@ public class DataStoreCategoryChoiceComp extends SimpleRegionBuilder {
if (!applyExternalInitially) {
value.setValue(last);
}
var box = new ComboBox<>(StoreViewState.get().getSortedCategories(root, false).filtered(filter).getList());
var box = new ComboBox<>(StoreViewState.get().getSortedCategories(root, true).filtered(filter).getList());
box.setValue(value.getValue());
box.valueProperty().addListener((observable, oldValue, newValue) -> {
value.setValue(newValue);
@@ -83,9 +84,11 @@ public class DataStoreCategoryChoiceComp extends SimpleRegionBuilder {
super.updateItem(w, empty);
textProperty().unbind();
if (w != null) {
setGraphic(PrettyImageHelper.ofFixedSizeSquare(w.getIconFile().getValue(), 16).build());
textProperty().bind(w.getShownName());
setPadding(new Insets(6, 6, 6, 8 + (indent ? w.getDepth() * 8 : 0)));
} else {
setGraphic(null);
setText("None");
}
}

View File

@@ -227,6 +227,8 @@ public class StoreCategoryWrapper {
Optional.ofNullable(getParent()).ifPresent(storeCategoryWrapper -> {
storeCategoryWrapper.update();
});
StoreViewState.get().refreshActiveCategory();
}
private String translatedName(String original) {

View File

@@ -138,7 +138,7 @@ public class StoreChoicePopover<T extends DataStore> {
},
initialExpanded);
var category = new DataStoreCategoryChoiceComp(
var category = new StoreCategoryChoiceComp(
rootCategory != null ? rootCategory.getRoot() : null,
StoreViewState.get().getActiveCategory(),
selectedCategory,

View File

@@ -185,6 +185,20 @@ public class StoreViewState {
return batchModeSelectionSet.contains(entry);
}
public void refreshActiveCategory() {
if (getActiveCategory().getValue().isHierarchyExpanded()) {
return;
}
StoreCategoryWrapper current = getActiveCategory().getValue();
while ((current = current.getParent()) != null) {
if (current.getParent() == null || current.getParent().getExpanded().get()) {
activeCategory.setValue(current);
break;
}
};
}
public void selectBatchMode(StoreSection section) {
var wrapper = section.getWrapper();
if (wrapper != null && wrapper.getEntry().getValidity() == DataStoreEntry.Validity.LOAD_FAILED) {
@@ -380,6 +394,10 @@ public class StoreViewState {
});
}
getActiveCategory().addListener((observable, oldValue, newValue) -> {
refreshActiveCategory();
});
// Watch out for synchronizing all calls to the entries and categories list!
DataStorage.get().addListener(new StorageListener() {

View File

@@ -41,13 +41,16 @@ public class ScriptHelper {
@SneakyThrows
public static FilePath createExecScriptRaw(ShellControl processControl, FilePath file, String content, boolean log) {
if (processControl.view().fileExists(file)) {
var exists = processControl.view().fileExists(file);
if (log) {
TrackEvent.withTrace("Creating exec script").tag("file", file).tag("exists", exists).tag("content", content).handle();
}
if (exists) {
return file;
}
if (log) {
TrackEvent.withTrace("Writing exec script").tag("file", file).tag("content", content).handle();
}
processControl.view().writeScriptFile(file, content);
return file;
}

View File

@@ -147,6 +147,8 @@ public interface ShellDialect {
String runScriptCommand(ShellControl parent, String file);
String runScriptInOtherDialectCommand(ShellControl parent, String file);
String sourceScriptCommand(ShellControl sc, String file);
String executeCommandWithShell(String cmd);

View File

@@ -57,3 +57,4 @@ Furthermore, the container restart action will now properly restart any systemd
- Improve timeout handling for shells to allow for a quicker shell init
- Fix Keeper issues on macOS and add support for Keeper App Store installations
- Fix SSH being broken when a custom alias to a modified ssh command was set in a shell rc file
- Fix shell scripts for mixed environments, e.g. a powershell script in cmd environment, not properly running

View File

@@ -102,7 +102,7 @@ public class ScriptCollectionSourceImportDialog {
stack.prefWidth(600);
stack.prefHeight(650);
var catChoice = new DataStoreCategoryChoiceComp(
var catChoice = new StoreCategoryChoiceComp(
StoreViewState.get().getAllScriptsCategory(),
StoreViewState.get().getActiveCategory(),
targetCategory,

View File

@@ -77,7 +77,7 @@ public class ScriptStore implements SelfReferentialStore, StatefulDataStore<Enab
var canSource = targetType.isSourceCompatibleTo(scriptDialect);
var base = canSource
? targetType.sourceScriptCommand(shellControl, script.toString())
: targetType.runScriptCommand(shellControl, script.toString());
: scriptDialect.runScriptInOtherDialectCommand(shellControl, script.toString());
return base + (args ? " " + targetType.getCatchAllVariable() : "");
}