This commit is contained in:
crschnick 2024-03-23 06:53:08 +00:00
parent ea7114178f
commit 147e68efe5
34 changed files with 214 additions and 160 deletions

View file

@ -79,12 +79,20 @@ final class BrowserBookmarkComp extends SimpleComp {
}); });
}; };
BiConsumer<StoreSection, Comp<CompStructure<Button>>> augment = (s, comp) -> { BiConsumer<StoreSection, Comp<CompStructure<Button>>> augment = (s, comp) -> {
comp.disable(Bindings.createBooleanBinding(() -> { comp.disable(Bindings.createBooleanBinding(
return busy.get() || !applicable.test(s.getWrapper()); () -> {
}, busy)); return busy.get() || !applicable.test(s.getWrapper());
},
busy));
comp.apply(struc -> { comp.apply(struc -> {
open.addListener((observable, oldValue, newValue) -> { open.addListener((observable, oldValue, newValue) -> {
struc.get().pseudoClassStateChanged(SELECTED, newValue != null && newValue.getEntry().get().equals(s.getWrapper().getEntry())); struc.get()
.pseudoClassStateChanged(
SELECTED,
newValue != null
&& newValue.getEntry()
.get()
.equals(s.getWrapper().getEntry()));
}); });
}); });
}; };

View file

@ -355,7 +355,10 @@ final class BrowserFileListComp extends SimpleComp {
} }
if (fileList.getFileSystemModel().getFileSystem() != null) { if (fileList.getFileSystemModel().getFileSystem() != null) {
var shell = fileList.getFileSystemModel().getFileSystem().getShell().orElseThrow(); var shell = fileList.getFileSystemModel()
.getFileSystem()
.getShell()
.orElseThrow();
var hasAttributes = !OsType.WINDOWS.equals(shell.getOsType()); var hasAttributes = !OsType.WINDOWS.equals(shell.getOsType());
if (!hasAttributes) { if (!hasAttributes) {
table.getColumns().remove(modeCol); table.getColumns().remove(modeCol);

View file

@ -60,8 +60,7 @@ public final class BrowserFileListModel {
var parent = fileSystemModel.getCurrentParentDirectory(); var parent = fileSystemModel.getCurrentParentDirectory();
var l = Stream.concat( var l = Stream.concat(
parent != null ? Stream.of(new BrowserEntry(parent, this, true)) : Stream.of(), parent != null ? Stream.of(new BrowserEntry(parent, this, true)) : Stream.of(),
s.filter(entry -> entry != null) s.filter(entry -> entry != null).map(entry -> new BrowserEntry(entry, this, false)))
.map(entry -> new BrowserEntry(entry, this, false)))
.toList(); .toList();
all.setValue(l); all.setValue(l);
refreshShown(); refreshShown();

View file

@ -76,7 +76,9 @@ public class BrowserNavBar extends SimpleComp {
// Pseudo classes do not apply if set instantly before shown // Pseudo classes do not apply if set instantly before shown
// If we start a new tab with a directory set, we have to set the pseudo class one pulse later // If we start a new tab with a directory set, we have to set the pseudo class one pulse later
Platform.runLater(() -> { Platform.runLater(() -> {
struc.get().pseudoClassStateChanged(INVISIBLE, !val && !struc.get().isFocused()); struc.get()
.pseudoClassStateChanged(
INVISIBLE, !val && !struc.get().isFocused());
}); });
}); });

View file

@ -47,13 +47,9 @@ public class BrowserStatusBarComp extends SimpleComp {
if (p == null || p.done()) { if (p == null || p.done()) {
return null; return null;
} else { } else {
var transferred = HumanReadableFormat.byteCount( var transferred = HumanReadableFormat.byteCount(p.getTransferred(), false);
p.getTransferred(), false); var all = HumanReadableFormat.byteCount(p.getTotal(), true);
var all = HumanReadableFormat.byteCount( var name = (p.getName() != null ? " @ " + p.getName() + " " : "");
p.getTotal(), true);
var name = (p.getName() != null
? " @ " + p.getName() + " "
: "");
return transferred + " / " + all + name; return transferred + " / " + all + name;
} }
}); });

View file

@ -115,7 +115,7 @@ public class StoreCreationComp extends DialogComp {
DataStorage.get().getSelectedCategory().getUuid(), DataStorage.get().getSelectedCategory().getUuid(),
name.getValue(), name.getValue(),
store.getValue()); store.getValue());
var p = DataStorage.get().getDefaultDisplayParent(testE).orElse(null); var p = DataStorage.get().getDefaultDisplayParent(testE).orElse(null);
var targetCategory = p != null var targetCategory = p != null
? p.getCategoryUuid() ? p.getCategoryUuid()
@ -174,7 +174,8 @@ public class StoreCreationComp extends DialogComp {
(e, validated) -> { (e, validated) -> {
try { try {
DataStorage.get().addStoreEntryIfNotPresent(e); DataStorage.get().addStoreEntryIfNotPresent(e);
if (validated && e.getProvider().shouldHaveChildren() if (validated
&& e.getProvider().shouldHaveChildren()
&& AppPrefs.get() && AppPrefs.get()
.openConnectionSearchWindowOnConnectionCreation() .openConnectionSearchWindowOnConnectionCreation()
.get()) { .get()) {

View file

@ -54,8 +54,6 @@ public abstract class StoreEntryComp extends SimpleComp {
this.content = content; this.content = content;
} }
public abstract boolean isFullSize();
public static StoreEntryComp create(StoreEntryWrapper entry, Comp<?> content, boolean preferLarge) { public static StoreEntryComp create(StoreEntryWrapper entry, Comp<?> content, boolean preferLarge) {
var forceCondensed = AppPrefs.get() != null var forceCondensed = AppPrefs.get() != null
&& AppPrefs.get().condenseConnectionDisplay().get(); && AppPrefs.get().condenseConnectionDisplay().get();
@ -79,6 +77,8 @@ public abstract class StoreEntryComp extends SimpleComp {
} }
} }
public abstract boolean isFullSize();
@Override @Override
protected final Region createSimple() { protected final Region createSimple() {
var r = createContent(); var r = createContent();

View file

@ -42,13 +42,14 @@ public class StoreQuickAccessButtonComp extends SimpleComp {
cm.show(anchor, Side.RIGHT, 0, 0); cm.show(anchor, Side.RIGHT, 0, 0);
// App.getApp().getStage().getScene().addEventFilter(MouseEvent.MOUSE_MOVED, event -> { // App.getApp().getStage().getScene().addEventFilter(MouseEvent.MOUSE_MOVED, event -> {
// var stages = Stage.getWindows().stream().filter(window -> window instanceof ContextMenu).toList(); // var stages = Stage.getWindows().stream().filter(window -> window instanceof ContextMenu).toList();
// var hovered = stages.stream().anyMatch(window -> window.getScene().getRoot().hoverProperty().get()); // var hovered = stages.stream().anyMatch(window ->
// if (!hovered) { // window.getScene().getRoot().hoverProperty().get());
// stages.forEach(window -> window.hide()); // if (!hovered) {
// } // stages.forEach(window -> window.hide());
// }); // }
// });
} }
private ContextMenu createMenu() { private ContextMenu createMenu() {
@ -67,11 +68,12 @@ public class StoreQuickAccessButtonComp extends SimpleComp {
private MenuItem recurse(ContextMenu contextMenu, StoreSection section) { private MenuItem recurse(ContextMenu contextMenu, StoreSection section) {
var c = section.getShownChildren(); var c = section.getShownChildren();
var w = section.getWrapper(); var w = section.getWrapper();
var graphic = w.getEntry() var graphic =
.getProvider() w.getEntry().getProvider().getDisplayIconFileName(w.getEntry().getStore());
.getDisplayIconFileName(w.getEntry().getStore());
if (c.isEmpty()) { if (c.isEmpty()) {
var item = new MenuItem(w.getName().getValue(), PrettyImageHelper.ofFixedSquare(graphic, 16).createRegion()); var item = new MenuItem(
w.getName().getValue(),
PrettyImageHelper.ofFixedSquare(graphic, 16).createRegion());
item.setOnAction(event -> { item.setOnAction(event -> {
action.accept(w); action.accept(w);
contextMenu.hide(); contextMenu.hide();
@ -88,7 +90,9 @@ public class StoreQuickAccessButtonComp extends SimpleComp {
items.add(recurse(contextMenu, sub)); items.add(recurse(contextMenu, sub));
} }
var m = new Menu(w.getName().getValue(), PrettyImageHelper.ofFixedSquare(graphic, 16).createRegion()); var m = new Menu(
w.getName().getValue(),
PrettyImageHelper.ofFixedSquare(graphic, 16).createRegion());
m.getItems().setAll(items); m.getItems().setAll(items);
m.setOnAction(event -> { m.setOnAction(event -> {
if (event.getTarget() == m) { if (event.getTarget() == m) {

View file

@ -102,7 +102,7 @@ public class StoreSection {
var matchesSelector = section.anyMatches(entryFilter); var matchesSelector = section.anyMatches(entryFilter);
var sameCategory = category == null var sameCategory = category == null
|| category.getValue() == null || category.getValue() == null
|| inCategory(category.getValue(),section.getWrapper()); || inCategory(category.getValue(), section.getWrapper());
return showFilter && matchesSelector && sameCategory; return showFilter && matchesSelector && sameCategory;
}, },
category, category,
@ -141,7 +141,7 @@ public class StoreSection {
var matchesSelector = section.anyMatches(entryFilter); var matchesSelector = section.anyMatches(entryFilter);
var sameCategory = category == null var sameCategory = category == null
|| category.getValue() == null || category.getValue() == null
|| inCategory(category.getValue(),section.getWrapper()); || inCategory(category.getValue(), section.getWrapper());
// If this entry is already shown as root due to a different category than parent, don't show it // If this entry is already shown as root due to a different category than parent, don't show it
// again here // again here
var notRoot = var notRoot =
@ -153,20 +153,13 @@ public class StoreSection {
return new StoreSection(e, cached, filtered, depth); return new StoreSection(e, cached, filtered, depth);
} }
public boolean shouldShow(String filter) {
return anyMatches(storeEntryWrapper -> storeEntryWrapper.shouldShow(filter));
}
public boolean anyMatches(Predicate<StoreEntryWrapper> c) {
return c == null
|| c.test(wrapper)
|| allChildren.stream().anyMatch(storeEntrySection -> storeEntrySection.anyMatches(c));
}
private static boolean inCategory(StoreCategoryWrapper categoryWrapper, StoreEntryWrapper entryWrapper) { private static boolean inCategory(StoreCategoryWrapper categoryWrapper, StoreEntryWrapper entryWrapper) {
var current = entryWrapper.getCategory().getValue(); var current = entryWrapper.getCategory().getValue();
while (current != null) { while (current != null) {
if (categoryWrapper.getCategory().getUuid().equals(current.getCategory().getUuid())) { if (categoryWrapper
.getCategory()
.getUuid()
.equals(current.getCategory().getUuid())) {
return true; return true;
} }
@ -178,4 +171,14 @@ public class StoreSection {
} }
return false; return false;
} }
public boolean shouldShow(String filter) {
return anyMatches(storeEntryWrapper -> storeEntryWrapper.shouldShow(filter));
}
public boolean anyMatches(Predicate<StoreEntryWrapper> c) {
return c == null
|| c.test(wrapper)
|| allChildren.stream().anyMatch(storeEntrySection -> storeEntrySection.anyMatches(c));
}
} }

View file

@ -56,7 +56,8 @@ public class StoreSectionComp extends Comp<CompStructure<VBox>> {
w.executeDefaultAction(); w.executeDefaultAction();
}); });
}; };
var quickAccessButton = new StoreQuickAccessButtonComp(section, quickAccessAction).vgrow() var quickAccessButton = new StoreQuickAccessButtonComp(section, quickAccessAction)
.vgrow()
.styleClass("quick-access-button") .styleClass("quick-access-button")
.apply(struc -> struc.get().setMinWidth(30)) .apply(struc -> struc.get().setMinWidth(30))
.apply(struc -> struc.get().setPrefWidth(30)) .apply(struc -> struc.get().setPrefWidth(30))

View file

@ -41,7 +41,8 @@ public class StoreSectionMiniComp extends Comp<CompStructure<VBox>> {
public StoreSectionMiniComp( public StoreSectionMiniComp(
StoreSection section, StoreSection section,
BiConsumer<StoreSection, Comp<CompStructure<Button>>> augment, Consumer<StoreEntryWrapper> action, BiConsumer<StoreSection, Comp<CompStructure<Button>>> augment,
Consumer<StoreEntryWrapper> action,
boolean condensedStyle) { boolean condensedStyle) {
this.section = section; this.section = section;
this.augment = augment; this.augment = augment;
@ -112,7 +113,8 @@ public class StoreSectionMiniComp extends Comp<CompStructure<VBox>> {
Consumer<StoreEntryWrapper> quickAccessAction = w -> { Consumer<StoreEntryWrapper> quickAccessAction = w -> {
action.accept(w); action.accept(w);
}; };
var quickAccessButton = new StoreQuickAccessButtonComp(section, quickAccessAction).vgrow() var quickAccessButton = new StoreQuickAccessButtonComp(section, quickAccessAction)
.vgrow()
.styleClass("quick-access-button") .styleClass("quick-access-button")
.maxHeight(100) .maxHeight(100)
.disable(quickAccessDisabled); .disable(quickAccessDisabled);

View file

@ -50,7 +50,8 @@ public interface StoreSortMode {
@Override @Override
public StoreSection representative(StoreSection s) { public StoreSection representative(StoreSection s) {
return Stream.concat(s.getShownChildren().stream().map(this::representative), Stream.of(s)) return Stream.concat(s.getShownChildren().stream().map(this::representative), Stream.of(s))
.max(Comparator.comparing(section -> section.getWrapper().getEntry().getLastAccess())) .max(Comparator.comparing(
section -> section.getWrapper().getEntry().getLastAccess()))
.orElseThrow(); .orElseThrow();
} }
@ -70,7 +71,8 @@ public interface StoreSortMode {
@Override @Override
public StoreSection representative(StoreSection s) { public StoreSection representative(StoreSection s) {
return Stream.concat(s.getShownChildren().stream().map(this::representative), Stream.of(s)) return Stream.concat(s.getShownChildren().stream().map(this::representative), Stream.of(s))
.max(Comparator.comparing(section -> section.getWrapper().getEntry().getLastAccess())) .max(Comparator.comparing(
section -> section.getWrapper().getEntry().getLastAccess()))
.orElseThrow(); .orElseThrow();
} }

View file

@ -80,12 +80,6 @@ public class AppLogs {
hookUpSystemErr(); hookUpSystemErr();
} }
public void flush() {
if (outFileStream != null) {
outFileStream.flush();
}
}
private static boolean shouldWriteLogs() { private static boolean shouldWriteLogs() {
if (System.getProperty(WRITE_LOGS_PROP) != null) { if (System.getProperty(WRITE_LOGS_PROP) != null) {
return Boolean.parseBoolean(System.getProperty(WRITE_LOGS_PROP)); return Boolean.parseBoolean(System.getProperty(WRITE_LOGS_PROP));
@ -192,6 +186,12 @@ public class AppLogs {
return DEFAULT_LOG_LEVEL; return DEFAULT_LOG_LEVEL;
} }
public void flush() {
if (outFileStream != null) {
outFileStream.flush();
}
}
private void close() { private void close() {
if (outFileStream != null) { if (outFileStream != null) {
outFileStream.close(); outFileStream.close();

View file

@ -8,8 +8,7 @@ import java.util.concurrent.TimeUnit;
public class AppCertutilCheck { public class AppCertutilCheck {
private static boolean getResult() { private static boolean getResult() {
var fc = new ProcessBuilder(System.getenv("WINDIR") + "\\System32\\certutil") var fc = new ProcessBuilder(System.getenv("WINDIR") + "\\System32\\certutil").redirectErrorStream(true);
.redirectErrorStream(true);
try { try {
var proc = fc.start(); var proc = fc.start();
var out = new String(proc.getInputStream().readAllBytes()); var out = new String(proc.getInputStream().readAllBytes());

View file

@ -11,18 +11,15 @@ public class AppPtbCheck {
return; return;
} }
AppWindowHelper.showBlockingAlert( AppWindowHelper.showBlockingAlert(alert -> {
alert -> { alert.setAlertType(Alert.AlertType.INFORMATION);
alert.setAlertType(Alert.AlertType.INFORMATION); alert.setHeaderText("Notice for the public test build");
alert.setHeaderText("Notice for the public test build"); alert.getDialogPane()
alert.getDialogPane() .setContent(AppWindowHelper.alertContentText("You are running a PTB build of XPipe."
.setContent( + " This version is unstable and might contain bugs."
AppWindowHelper.alertContentText( + " You should not use it as a daily driver."
"You are running a PTB build of XPipe." + + " It will also not receive regular updates."
" This version is unstable and might contain bugs." + + " You will have to install and launch the normal XPipe release for that."));
" You should not use it as a daily driver." + });
" It will also not receive regular updates." +
" You will have to install and launch the normal XPipe release for that."));
});
} }
} }

View file

@ -13,7 +13,9 @@ public class AppShellCheck {
public static void check() throws Exception { public static void check() throws Exception {
var err = selfTestErrorCheck(); var err = selfTestErrorCheck();
var canFallback = !ProcessControlProvider.get().getEffectiveLocalDialect().equals(ProcessControlProvider.get().getFallbackDialect()); var canFallback = !ProcessControlProvider.get()
.getEffectiveLocalDialect()
.equals(ProcessControlProvider.get().getFallbackDialect());
if (err.isPresent() && canFallback) { if (err.isPresent() && canFallback) {
var msg = formatMessage(err.get()); var msg = formatMessage(err.get());
ErrorEvent.fromThrowable(new IllegalStateException(msg)).handle(); ErrorEvent.fromThrowable(new IllegalStateException(msg)).handle();
@ -28,7 +30,9 @@ public class AppShellCheck {
} }
private static String modifyOutput(String output) { private static String modifyOutput(String output) {
if (OsType.getLocal().equals(OsType.WINDOWS) && output.contains("is not recognized as an internal or external command") && output.contains("exec-")) { if (OsType.getLocal().equals(OsType.WINDOWS)
&& output.contains("is not recognized as an internal or external command")
&& output.contains("exec-")) {
return "Unable to create temporary script files"; return "Unable to create temporary script files";
} }
@ -36,9 +40,12 @@ public class AppShellCheck {
} }
private static String formatMessage(String output) { private static String formatMessage(String output) {
var fallback = !ProcessControlProvider.get().getEffectiveLocalDialect().equals(ProcessControlProvider.get().getFallbackDialect()) ? "XPipe will now attempt to fall back to another shell." : ""; var fallback = !ProcessControlProvider.get()
return .getEffectiveLocalDialect()
""" .equals(ProcessControlProvider.get().getFallbackDialect())
? "XPipe will now attempt to fall back to another shell."
: "";
return """
Shell self-test failed for %s: Shell self-test failed for %s:
%s %s
@ -51,11 +58,10 @@ public class AppShellCheck {
%s %s
""" """
.formatted( .formatted(
ProcessControlProvider.get() ProcessControlProvider.get().getEffectiveLocalDialect().getDisplayName(),
.getEffectiveLocalDialect() modifyOutput(output),
.getDisplayName(), fallback);
modifyOutput(output), fallback);
} }
private static void enableFallback() throws Exception { private static void enableFallback() throws Exception {

View file

@ -186,16 +186,23 @@ public class DataStoreChoiceComp<T extends DataStore> extends SimpleComp {
button.apply(struc -> { button.apply(struc -> {
struc.get().setMaxWidth(2000); struc.get().setMaxWidth(2000);
struc.get().setAlignment(Pos.CENTER_LEFT); struc.get().setAlignment(Pos.CENTER_LEFT);
Comp<?> graphic = PrettyImageHelper.ofSvg(Bindings.createStringBinding(() -> { Comp<?> graphic = PrettyImageHelper.ofSvg(
if (selected.getValue() == null) { Bindings.createStringBinding(
return null; () -> {
} if (selected.getValue() == null) {
return null;
}
return selected.getValue().get().getProvider().getDisplayIconFileName(selected.getValue().getStore()); return selected.getValue()
}, selected), 16, 16); .get()
struc.get() .getProvider()
.setGraphic(graphic .getDisplayIconFileName(
.createRegion()); selected.getValue().getStore());
},
selected),
16,
16);
struc.get().setGraphic(graphic.createRegion());
struc.get().setOnAction(event -> { struc.get().setOnAction(event -> {
getPopover().show(struc.get()); getPopover().show(struc.get());
event.consume(); event.consume();

View file

@ -8,9 +8,6 @@ import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.util.Subscription;
import java.util.concurrent.Flow;
public class LabelComp extends Comp<CompStructure<Label>> { public class LabelComp extends Comp<CompStructure<Label>> {

View file

@ -55,10 +55,10 @@ public class ErrorHandlerComp extends SimpleComp {
// Unhandled platform exceptions usually means that we will have trouble displaying another window // Unhandled platform exceptions usually means that we will have trouble displaying another window
// Let's just hope that this is not the case // Let's just hope that this is not the case
// if (event.isUnhandled() && Platform.isFxApplicationThread()) { // if (event.isUnhandled() && Platform.isFxApplicationThread()) {
// ErrorAction.ignore().handle(event); // ErrorAction.ignore().handle(event);
// return; // return;
// } // }
if (Platform.isFxApplicationThread()) { if (Platform.isFxApplicationThread()) {
showAndWaitWithPlatformThread(event, forceWait); showAndWaitWithPlatformThread(event, forceWait);

View file

@ -50,15 +50,15 @@ public class EventHandlerImpl extends EventHandler {
} }
} }
private void handleOnShutdown(ErrorEvent ee) {
ErrorAction.ignore().handle(ee);
handle(fromErrorEvent(ee));
}
@Override @Override
public void modify(ErrorEvent ee) { public void modify(ErrorEvent ee) {
if (AppLogs.get() != null && AppLogs.get().getSessionLogsDirectory() != null) { if (AppLogs.get() != null && AppLogs.get().getSessionLogsDirectory() != null) {
ee.addAttachment(AppLogs.get().getSessionLogsDirectory()); ee.addAttachment(AppLogs.get().getSessionLogsDirectory());
} }
} }
private void handleOnShutdown(ErrorEvent ee) {
ErrorAction.ignore().handle(ee);
handle(fromErrorEvent(ee));
}
} }

View file

@ -107,22 +107,29 @@ public class AppPrefs {
bindDeveloperTrue(developerDisableGuiRestrictions); bindDeveloperTrue(developerDisableGuiRestrictions);
private final ObjectProperty<SupportedLocale> language = private final ObjectProperty<SupportedLocale> language =
map(new SimpleObjectProperty<>(SupportedLocale.ENGLISH), "language", SupportedLocale.class); map(new SimpleObjectProperty<>(SupportedLocale.ENGLISH), "language", SupportedLocale.class);
@Getter @Getter
private final Property<InPlaceSecretValue> lockPassword = new SimpleObjectProperty<>(); private final Property<InPlaceSecretValue> lockPassword = new SimpleObjectProperty<>();
@Getter @Getter
private final StringProperty lockCrypt = private final StringProperty lockCrypt =
mapVaultSpecific(new SimpleStringProperty(), "workspaceLock", String.class); mapVaultSpecific(new SimpleStringProperty(), "workspaceLock", String.class);
private final IntegerProperty editorReloadTimeout = private final IntegerProperty editorReloadTimeout =
map(new SimpleIntegerProperty(1000), "editorReloadTimeout", Integer.class); map(new SimpleIntegerProperty(1000), "editorReloadTimeout", Integer.class);
private final BooleanProperty confirmDeletions = private final BooleanProperty confirmDeletions =
map(new SimpleBooleanProperty(true), "confirmDeletions", Boolean.class); map(new SimpleBooleanProperty(true), "confirmDeletions", Boolean.class);
@Getter @Getter
private final List<AppPrefsCategory> categories; private final List<AppPrefsCategory> categories;
private final AppPrefsStorageHandler globalStorageHandler = new AppPrefsStorageHandler( private final AppPrefsStorageHandler globalStorageHandler = new AppPrefsStorageHandler(
AppProperties.get().getDataDir().resolve("settings").resolve("preferences.json")); AppProperties.get().getDataDir().resolve("settings").resolve("preferences.json"));
private final Map<Mapping<?>, Comp<?>> customEntries = new LinkedHashMap<>(); private final Map<Mapping<?>, Comp<?>> customEntries = new LinkedHashMap<>();
@Getter @Getter
private final Property<AppPrefsCategory> selectedCategory; private final Property<AppPrefsCategory> selectedCategory;
private final PrefsHandler extensionHandler = new PrefsHandlerImpl(); private final PrefsHandler extensionHandler = new PrefsHandlerImpl();
private AppPrefsStorageHandler vaultStorageHandler; private AppPrefsStorageHandler vaultStorageHandler;

View file

@ -23,7 +23,10 @@ public class AppearanceCategory extends AppPrefsCategory {
.addTitle("uiOptions") .addTitle("uiOptions")
.sub(new OptionsBuilder() .sub(new OptionsBuilder()
.nameAndDescription("theme") .nameAndDescription("theme")
.addComp(ChoiceComp.ofTranslatable(prefs.theme, AppTheme.Theme.ALL, false).styleClass("theme-switcher"), prefs.theme) .addComp(
ChoiceComp.ofTranslatable(prefs.theme, AppTheme.Theme.ALL, false)
.styleClass("theme-switcher"),
prefs.theme)
.nameAndDescription("performanceMode") .nameAndDescription("performanceMode")
.addToggle(prefs.performanceMode) .addToggle(prefs.performanceMode)
.nameAndDescription("uiScale") .nameAndDescription("uiScale")

View file

@ -65,10 +65,17 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
.addFile(configuration.getScriptFile()); .addFile(configuration.getScriptFile());
} }
return CommandBuilder.of().add("-ExecutionPolicy", "Bypass").add("-EncodedCommand").add(sc -> { return CommandBuilder.of()
var base64 = Base64.getEncoder().encodeToString(configuration.getDialectLaunchCommand().buildCommandBase(sc).getBytes(StandardCharsets.UTF_16LE)); .add("-ExecutionPolicy", "Bypass")
return "\"" + base64 + "\""; .add("-EncodedCommand")
}); .add(sc -> {
var base64 = Base64.getEncoder()
.encodeToString(configuration
.getDialectLaunchCommand()
.buildCommandBase(sc)
.getBytes(StandardCharsets.UTF_16LE));
return "\"" + base64 + "\"";
});
} }
}; };
@ -86,12 +93,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
@Override @Override
protected CommandBuilder toCommand(LaunchConfiguration configuration) { protected CommandBuilder toCommand(LaunchConfiguration configuration) {
return CommandBuilder.of().add("-ExecutionPolicy", "Bypass").add("-EncodedCommand").add(sc -> { return CommandBuilder.of()
// Fix for https://github.com/PowerShell/PowerShell/issues/18530#issuecomment-1325691850 .add("-ExecutionPolicy", "Bypass")
var c = "$env:PSModulePath=\"\";" + configuration.getDialectLaunchCommand().buildCommandBase(sc); .add("-EncodedCommand")
var base64 = Base64.getEncoder().encodeToString(c.getBytes(StandardCharsets.UTF_16LE)); .add(sc -> {
return "\"" + base64 + "\""; // Fix for https://github.com/PowerShell/PowerShell/issues/18530#issuecomment-1325691850
}); var c = "$env:PSModulePath=\"\";"
+ configuration.getDialectLaunchCommand().buildCommandBase(sc);
var base64 = Base64.getEncoder().encodeToString(c.getBytes(StandardCharsets.UTF_16LE));
return "\"" + base64 + "\"";
});
} }
}; };
@ -503,7 +514,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
} }
}; };
ExternalTerminalType WARP = new MacOsType("app.warp", "Warp") { ExternalTerminalType WARP = new MacOsType("app.warp", "Warp") {
@Override @Override
public boolean supportsTabs() { public boolean supportsTabs() {
return true; return true;
@ -678,7 +689,8 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
static ExternalTerminalType determineDefault(ExternalTerminalType existing) { static ExternalTerminalType determineDefault(ExternalTerminalType existing) {
// Check for incompatibility with fallback shell // Check for incompatibility with fallback shell
if (ExternalTerminalType.CMD.equals(existing) && !ProcessControlProvider.get().getEffectiveLocalDialect().equals(ShellDialects.CMD)) { if (ExternalTerminalType.CMD.equals(existing)
&& !ProcessControlProvider.get().getEffectiveLocalDialect().equals(ShellDialects.CMD)) {
return ExternalTerminalType.POWERSHELL; return ExternalTerminalType.POWERSHELL;
} }
@ -817,5 +829,4 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
protected abstract CommandBuilder toCommand(LaunchConfiguration configuration) throws Exception; protected abstract CommandBuilder toCommand(LaunchConfiguration configuration) throws Exception;
} }
} }

View file

@ -10,43 +10,42 @@ import java.nio.file.Path;
public class WindowsTerminalType { public class WindowsTerminalType {
public static final ExternalTerminalType WINDOWS_TERMINAL =
new ExternalTerminalType.SimplePathType("app.windowsTerminal", "wt.exe") {
public static final ExternalTerminalType WINDOWS_TERMINAL = new ExternalTerminalType.SimplePathType("app.windowsTerminal", "wt.exe") { @Override
protected CommandBuilder toCommand(LaunchConfiguration configuration) throws Exception {
return WindowsTerminalType.toCommand(configuration);
}
@Override @Override
protected CommandBuilder toCommand(LaunchConfiguration configuration) throws Exception { public boolean supportsTabs() {
return WindowsTerminalType.toCommand(configuration); return true;
} }
@Override @Override
public boolean supportsTabs() { public boolean supportsColoredTitle() {
return true; return false;
} }
};
@Override
public boolean supportsColoredTitle() {
return false;
}
};
public static final ExternalTerminalType WINDOWS_TERMINAL_PREVIEW = new ExternalTerminalType() { public static final ExternalTerminalType WINDOWS_TERMINAL_PREVIEW = new ExternalTerminalType() {
@Override
public boolean supportsColoredTitle() {
return false;
}
@Override @Override
public boolean supportsTabs() { public boolean supportsTabs() {
return true; return true;
} }
@Override
public boolean supportsColoredTitle() {
return false;
}
@Override @Override
public void launch(ExternalTerminalType.LaunchConfiguration configuration) throws Exception { public void launch(ExternalTerminalType.LaunchConfiguration configuration) throws Exception {
LocalShell.getShell() LocalShell.getShell()
.executeSimpleCommand(CommandBuilder.of() .executeSimpleCommand(
.addFile(getPath().toString()) CommandBuilder.of().addFile(getPath().toString()).add(toCommand(configuration)));
.add(toCommand(configuration)));
} }
private Path getPath() { private Path getPath() {
@ -72,9 +71,11 @@ public class WindowsTerminalType {
// So just remove that slash // So just remove that slash
var fixedName = FileNames.removeTrailingSlash(configuration.getColoredTitle()); var fixedName = FileNames.removeTrailingSlash(configuration.getColoredTitle());
var toExec = !ShellDialects.isPowershell(LocalShell.getShell()) ? var toExec = !ShellDialects.isPowershell(LocalShell.getShell())
CommandBuilder.of().addFile(configuration.getScriptFile()) : ? CommandBuilder.of().addFile(configuration.getScriptFile())
CommandBuilder.of().add("powershell", "-ExecutionPolicy", "Bypass", "-File").addQuoted(configuration.getScriptFile()); : CommandBuilder.of()
.add("powershell", "-ExecutionPolicy", "Bypass", "-File")
.addQuoted(configuration.getScriptFile());
var cmd = CommandBuilder.of().add("-w", "1", "nt"); var cmd = CommandBuilder.of().add("-w", "1", "nt");
if (configuration.getColor() != null) { if (configuration.getColor() != null) {

View file

@ -41,7 +41,8 @@ public class ApplicationHelper {
var script = ScriptHelper.createExecScript(pc, command); var script = ScriptHelper.createExecScript(pc, command);
return String.format( return String.format(
"Start-Process -FilePath %s -ArgumentList \"-NoProfile\", \"-File\", %s", "Start-Process -FilePath %s -ArgumentList \"-NoProfile\", \"-File\", %s",
pc.getShellDialect().getExecutableName(), pc.getShellDialect().fileArgument(script)); pc.getShellDialect().getExecutableName(),
pc.getShellDialect().fileArgument(script));
} }
if (pc.getOsType().equals(OsType.WINDOWS)) { if (pc.getOsType().equals(OsType.WINDOWS)) {

View file

@ -1,12 +1,12 @@
package io.xpipe.app.util; package io.xpipe.app.util;
import io.xpipe.app.storage.DataStorage; import io.xpipe.app.storage.DataStorage;
import io.xpipe.core.util.NewLine;
import io.xpipe.core.util.StreamCharset;
import io.xpipe.core.dialog.Dialog; import io.xpipe.core.dialog.Dialog;
import io.xpipe.core.dialog.QueryConverter; import io.xpipe.core.dialog.QueryConverter;
import io.xpipe.core.store.*; import io.xpipe.core.store.*;
import io.xpipe.core.util.NewLine;
import io.xpipe.core.util.SecretValue; import io.xpipe.core.util.SecretValue;
import io.xpipe.core.util.StreamCharset;
import lombok.Value; import lombok.Value;
public class DialogHelper { public class DialogHelper {

View file

@ -73,7 +73,8 @@ public enum PlatformState {
// The headless check is not needed though but still done // The headless check is not needed though but still done
GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
// Catch more than just the headless exception in case the graphics environment initialization completely fails // Catch more than just the headless exception in case the graphics environment initialization completely
// fails
} catch (Throwable t) { } catch (Throwable t) {
TrackEvent.warn(t.getMessage()); TrackEvent.warn(t.getMessage());
PlatformState.setCurrent(PlatformState.EXITED); PlatformState.setCurrent(PlatformState.EXITED);

View file

@ -41,7 +41,8 @@ public class ShellTemp {
base = FileNames.join("/tmp", "xpipe"); base = FileNames.join("/tmp", "xpipe");
// We have to make sure that also other users can create files here // We have to make sure that also other users can create files here
// This command should work in all shells on unix systems // This command should work in all shells on unix systems
proc.command("chmod 777 " + proc.getShellDialect().fileArgument(base)).executeAndCheck(); proc.command("chmod 777 " + proc.getShellDialect().fileArgument(base))
.executeAndCheck();
// Use user-specific directories on anything else than macOS as that one already has that // Use user-specific directories on anything else than macOS as that one already has that
if (!proc.getOsType().equals(OsType.MACOS)) { if (!proc.getOsType().equals(OsType.MACOS)) {
var user = proc.getShellDialect().printUsernameCommand(proc).readStdoutOrThrow(); var user = proc.getShellDialect().printUsernameCommand(proc).readStdoutOrThrow();

View file

@ -3,9 +3,9 @@ package io.xpipe.app.util;
import io.xpipe.app.core.AppI18n; import io.xpipe.app.core.AppI18n;
import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.prefs.AppPrefs; import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.terminal.ExternalTerminalType;
import io.xpipe.app.storage.DataStorage; import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry; import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.terminal.ExternalTerminalType;
import io.xpipe.core.process.ProcessControl; import io.xpipe.core.process.ProcessControl;
import io.xpipe.core.process.ProcessControlProvider; import io.xpipe.core.process.ProcessControlProvider;
import io.xpipe.core.process.ShellControl; import io.xpipe.core.process.ShellControl;

View file

@ -27,7 +27,7 @@ public class TerminalLauncherManager {
return null; return null;
} }
if (!sc.getShellDialect().directoryExists(sc,directory).executeAndCheck()) { if (!sc.getShellDialect().directoryExists(sc, directory).executeAndCheck()) {
return null; return null;
} }
@ -35,8 +35,7 @@ public class TerminalLauncherManager {
}; };
try { try {
var file = ScriptHelper.createLocalExecScript( var file = ScriptHelper.createLocalExecScript(processControl.prepareTerminalOpen(config, workingDirectory));
processControl.prepareTerminalOpen(config, workingDirectory));
entry.setResult(new ResultSuccess(Path.of(file))); entry.setResult(new ResultSuccess(Path.of(file)));
} catch (Exception e) { } catch (Exception e) {
entry.setResult(new ResultFailure(e)); entry.setResult(new ResultFailure(e));

View file

@ -1,8 +1,8 @@
package io.xpipe.core.dialog; package io.xpipe.core.dialog;
import io.xpipe.core.util.NewLine; import io.xpipe.core.util.NewLine;
import io.xpipe.core.util.StreamCharset;
import io.xpipe.core.util.SecretValue; import io.xpipe.core.util.SecretValue;
import io.xpipe.core.util.StreamCharset;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;

View file

@ -1,10 +1,10 @@
package io.xpipe.core.process; package io.xpipe.core.process;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.xpipe.core.util.NewLine;
import io.xpipe.core.util.StreamCharset;
import io.xpipe.core.store.FileSystem; import io.xpipe.core.store.FileSystem;
import io.xpipe.core.util.NewLine;
import io.xpipe.core.util.SecretValue; import io.xpipe.core.util.SecretValue;
import io.xpipe.core.util.StreamCharset;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.List; import java.util.List;

View file

@ -10,10 +10,14 @@ public interface ShellDialectAskpass {
String prepareFixedContent(ShellControl sc, String fileName, List<String> s) throws Exception; String prepareFixedContent(ShellControl sc, String fileName, List<String> s) throws Exception;
String elevateDumbCommand( String elevateDumbCommand(
ShellControl shellControl, UUID requestId, ElevationHandler handler, CountDown countDown, String message, CommandConfiguration command ShellControl shellControl,
) UUID requestId,
ElevationHandler handler,
CountDown countDown,
String message,
CommandConfiguration command)
throws Exception; throws Exception;
String elevateTerminalCommandWithPreparedAskpass(ShellControl shellControl, ElevationHandler handler, String command, String prefix) String elevateTerminalCommandWithPreparedAskpass(
throws Exception; ShellControl shellControl, ElevationHandler handler, String command, String prefix) throws Exception;
} }

View file

@ -37,9 +37,8 @@ public class RunAction extends MultiExecuteAction {
return true; return true;
} }
if (ShellDialects.isPowershell(shell.get())
if (ShellDialects.isPowershell(shell.get()) && Stream.of("ps1") && Stream.of("ps1").anyMatch(s -> e.getPath().endsWith(s))) {
.anyMatch(s -> e.getPath().endsWith(s))) {
return true; return true;
} }