This commit is contained in:
crschnick
2024-11-01 13:15:34 +00:00
parent 7872da5e51
commit 67fd51f240
21 changed files with 97 additions and 112 deletions
@@ -1,47 +1,14 @@
package io.xpipe.app.browser;
import io.xpipe.app.browser.action.BrowserAction;
import io.xpipe.app.browser.file.BrowserFileListModel;
import io.xpipe.app.browser.file.BrowserFileTransferMode;
import io.xpipe.app.browser.file.BrowserFileTransferOperation;
import io.xpipe.app.browser.file.FileSystemHelper;
import io.xpipe.app.browser.fs.OpenFileSystemCache;
import io.xpipe.app.browser.fs.OpenFileSystemComp;
import io.xpipe.app.browser.fs.OpenFileSystemHistory;
import io.xpipe.app.browser.fs.OpenFileSystemSavedState;
import io.xpipe.app.browser.session.BrowserAbstractSessionModel;
import io.xpipe.app.browser.session.BrowserSessionModel;
import io.xpipe.app.browser.session.BrowserSessionTab;
import io.xpipe.app.comp.base.ModalOverlayComp;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.ext.ProcessControlProvider;
import io.xpipe.app.ext.ShellStore;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.storage.DataColor;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.TerminalLauncher;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.process.ShellControl;
import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.process.ShellOpenFunction;
import io.xpipe.core.store.*;
import io.xpipe.core.util.FailableConsumer;
import io.xpipe.core.util.FailableRunnable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import lombok.Getter;
import lombok.SneakyThrows;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import javafx.beans.property.*;
public final class BrowserHomeModel extends BrowserSessionTab {
@@ -60,14 +27,10 @@ public final class BrowserHomeModel extends BrowserSessionTab {
}
@Override
public void init() throws Exception {
}
public void init() throws Exception {}
@Override
public void close() {
}
public void close() {}
@Override
public String getIcon() {
@@ -43,9 +43,11 @@ public class BrowserTransferComp extends SimpleComp {
.apply(struc -> struc.get().setGraphic(new FontIcon("mdi2d-download-outline")))
.apply(struc -> struc.get().setWrapText(true))
.visible(model.getEmpty());
var backgroundStack =
new StackComp(List.of(background)).grow(true, true)
.styleClass("color-box").styleClass("gray").styleClass("download-background");
var backgroundStack = new StackComp(List.of(background))
.grow(true, true)
.styleClass("color-box")
.styleClass("gray")
.styleClass("download-background");
var binding = new DerivedObservableList<>(model.getItems(), true)
.mapped(item -> item.getBrowserEntry())
@@ -9,7 +9,6 @@ import io.xpipe.app.browser.file.BrowserFileTransferMode;
import io.xpipe.app.browser.file.BrowserFileTransferOperation;
import io.xpipe.app.browser.file.FileSystemHelper;
import io.xpipe.app.browser.session.BrowserAbstractSessionModel;
import io.xpipe.app.browser.session.BrowserSessionTab;
import io.xpipe.app.browser.session.BrowserStoreSessionTab;
import io.xpipe.app.comp.base.ModalOverlayComp;
import io.xpipe.app.ext.ProcessControlProvider;
@@ -57,9 +57,10 @@ public class OpenFileSystemSavedState {
}
static OpenFileSystemSavedState loadForStore(OpenFileSystemModel model) {
var state = AppCache.getNonNull("fs-state-" + model.getEntry().get().getUuid(), OpenFileSystemSavedState.class, () -> {
return new OpenFileSystemSavedState();
});
var state = AppCache.getNonNull(
"fs-state-" + model.getEntry().get().getUuid(), OpenFileSystemSavedState.class, () -> {
return new OpenFileSystemSavedState();
});
state.setModel(model);
return state;
}
@@ -20,10 +20,8 @@ import io.xpipe.app.util.ThreadHelper;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Region;
import javafx.scene.shape.Rectangle;
@@ -70,7 +68,11 @@ public class BrowserSessionComp extends SimpleComp {
var bookmarkTopBar = new BrowserBookmarkHeaderComp();
var bookmarksList = new BrowserBookmarkComp(
BindingsHelper.map(model.getSelectedEntry(), v -> v instanceof BrowserStoreSessionTab<?> st ? st.getEntry().get() : null),
BindingsHelper.map(
model.getSelectedEntry(),
v -> v instanceof BrowserStoreSessionTab<?> st
? st.getEntry().get()
: null),
applicable,
action,
bookmarkTopBar.getCategory(),
@@ -113,8 +115,10 @@ public class BrowserSessionComp extends SimpleComp {
AnchorPane.setRightAnchor(struc.get(), 0.0);
});
vertical.apply(struc -> {
struc.get().paddingProperty().bind(Bindings.createObjectBinding(
() -> new Insets(tabs.getHeaderHeight().get(), 0, 0, 0), tabs.getHeaderHeight()));
struc.get()
.paddingProperty()
.bind(Bindings.createObjectBinding(
() -> new Insets(tabs.getHeaderHeight().get(), 0, 0, 0), tabs.getHeaderHeight()));
});
var loadingIndicator = LoadingOverlayComp.noProgress(Comp.empty(), model.getBusy())
.apply(struc -> {
@@ -2,11 +2,10 @@ package io.xpipe.app.browser.session;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.storage.DataColor;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.core.store.DataStore;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import lombok.Getter;
@Getter
@@ -1,17 +1,13 @@
package io.xpipe.app.browser.session;
import io.xpipe.app.browser.BrowserWelcomeComp;
import io.xpipe.app.comp.base.MultiContentComp;
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;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ContextMenuHelper;
@@ -22,7 +18,6 @@ import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableDoubleValue;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.css.PseudoClass;
import javafx.geometry.Insets;
@@ -47,6 +42,7 @@ public class BrowserSessionTabsComp extends SimpleComp {
private final BrowserSessionModel model;
private final ObservableDoubleValue leftPadding;
@Getter
private final DoubleProperty headerHeight;
@@ -300,7 +296,9 @@ public class BrowserSessionTabsComp extends SimpleComp {
var closeOthers = ContextMenuHelper.item(LabelGraphic.none(), AppI18n.get("closeOtherTabs"));
closeOthers.setOnAction(event -> {
tabs.getTabs()
.removeAll(tabs.getTabs().stream().filter(t -> t != tab && t.isClosable()).toList());
.removeAll(tabs.getTabs().stream()
.filter(t -> t != tab && t.isClosable())
.toList());
event.consume();
});
cm.getItems().add(closeOthers);
@@ -332,9 +330,8 @@ public class BrowserSessionTabsComp extends SimpleComp {
new KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN, KeyCombination.SHIFT_DOWN));
closeAll.setOnAction(event -> {
tabs.getTabs()
.removeAll(tabs.getTabs().stream()
.filter(t -> t.isClosable())
.toList());
.removeAll(
tabs.getTabs().stream().filter(t -> t.isClosable()).toList());
event.consume();
});
cm.getItems().add(closeAll);
@@ -365,9 +362,12 @@ public class BrowserSessionTabsComp extends SimpleComp {
var image = tabModel.getIcon();
var logo = PrettyImageHelper.ofFixedSizeSquare(image, 16).createRegion();
tab.graphicProperty().bind(Bindings.createObjectBinding(() -> {
return tabModel.getBusy().get() ? ring : logo;
}, PlatformThread.sync(tabModel.getBusy())));
tab.graphicProperty()
.bind(Bindings.createObjectBinding(
() -> {
return tabModel.getBusy().get() ? ring : logo;
},
PlatformThread.sync(tabModel.getBusy())));
}
tab.setText(tabModel.getName());
@@ -5,8 +5,7 @@ import io.xpipe.app.storage.DataColor;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.core.store.DataStore;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import lombok.Getter;
@Getter
@@ -15,7 +14,10 @@ public abstract class BrowserStoreSessionTab<T extends DataStore> extends Browse
protected final DataStoreEntryRef<? extends T> entry;
public BrowserStoreSessionTab(BrowserAbstractSessionModel<?> browserModel, DataStoreEntryRef<? extends T> entry) {
super(browserModel, DataStorage.get().getStoreEntryDisplayName(entry.get()), DataStorage.get().getStorePath(entry.getEntry()).toString());
super(
browserModel,
DataStorage.get().getStoreEntryDisplayName(entry.get()),
DataStorage.get().getStorePath(entry.getEntry()).toString());
this.entry = entry;
}
@@ -1,6 +1,5 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.core.AppCache;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.fxcomps.Comp;
@@ -9,17 +8,13 @@ import io.xpipe.app.fxcomps.SimpleCompStructure;
import io.xpipe.app.fxcomps.impl.IconButtonComp;
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;
import io.xpipe.app.update.UpdateAvailableAlert;
import io.xpipe.app.update.XPipeDistributionType;
import io.xpipe.app.util.Hyperlinks;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.css.PseudoClass;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
@@ -27,9 +22,6 @@ import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;
public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
@@ -204,7 +204,8 @@ public class StoreCreationComp extends DialogComp {
null,
prov,
base,
dataStoreProvider -> (category != null && category.equals(dataStoreProvider.getCreationCategory())) || dataStoreProvider.equals(prov),
dataStoreProvider -> (category != null && category.equals(dataStoreProvider.getCreationCategory()))
|| dataStoreProvider.equals(prov),
(e, validated) -> {
try {
DataStorage.get().addStoreEntryIfNotPresent(e);
@@ -52,8 +52,7 @@ public class StoreEntryListComp extends SimpleComp {
@Override
protected Region createSimple() {
var scriptsIntroShowing =
new SimpleBooleanProperty(!AppCache.getBoolean("scriptsIntroCompleted", false));
var scriptsIntroShowing = new SimpleBooleanProperty(!AppCache.getBoolean("scriptsIntroCompleted", false));
var initialCount = 1;
var showIntro = Bindings.createBooleanBinding(
() -> {
@@ -3,6 +3,7 @@ package io.xpipe.app.core;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.JsonConfigHelper;
import io.xpipe.core.util.JacksonMapper;
import org.apache.commons.io.FileUtils;
import java.io.IOException;
@@ -12,6 +12,7 @@ import io.xpipe.app.prefs.CloseBehaviourAlert;
import io.xpipe.app.resources.AppImages;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.process.OsType;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Rectangle2D;
@@ -24,17 +25,18 @@ import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.stage.Screen;
import javafx.stage.Stage;
import lombok.Builder;
import lombok.Getter;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import javax.imageio.ImageIO;
import java.io.IOException;
import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import javax.imageio.ImageIO;
public class AppMainWindow {
@@ -1,6 +1,5 @@
package io.xpipe.app.ext;
import io.xpipe.app.util.LocalShell;
import io.xpipe.core.process.ShellControl;
import io.xpipe.core.process.ShellStoreState;
import io.xpipe.core.store.DataStore;
@@ -372,8 +372,7 @@ public abstract class DataStorage {
return refreshChildren(e, true);
}
public boolean refreshChildren(DataStoreEntry e, boolean throwOnFail)
throws Exception {
public boolean refreshChildren(DataStoreEntry e, boolean throwOnFail) throws Exception {
if (!(e.getStore() instanceof FixedHierarchyStore h)) {
return false;
}
@@ -1,10 +1,11 @@
package io.xpipe.app.test;
import io.xpipe.core.util.FailableSupplier;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Named;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public abstract class TestModule<V> {
@@ -12,6 +13,7 @@ public abstract class TestModule<V> {
private static final Map<Class<?>, Map<String, ?>> values = new LinkedHashMap<>();
@SuppressWarnings({"unchecked", "rawtypes"})
@SneakyThrows
public static <T> Map<String, T> get(Class<T> c, Module module, String... classes) {
if (!values.containsKey(c)) {
List<Class<?>> loadedClasses = Arrays.stream(classes)
@@ -31,8 +33,13 @@ public abstract class TestModule<V> {
});
}
return (Map<String, T>) values.get(c).entrySet().stream()
.collect(Collectors.toMap(o -> o.getKey(), o -> ((Supplier<?>) o.getValue()).get()));
Map<String, Object> map = new HashMap<>();
for (Map.Entry<String, ?> o : values.get(c).entrySet()) {
if (map.put(o.getKey(), ((FailableSupplier<?>) o.getValue()).get()) != null) {
throw new IllegalStateException("Duplicate key");
}
}
return (Map<String, T>) map;
}
public static <T> Stream<Named<T>> getArguments(Class<T> c, Module module, String... classes) {
@@ -43,7 +50,7 @@ public abstract class TestModule<V> {
return argumentBuilder.build();
}
protected abstract void init(Map<String, Supplier<V>> list) throws Exception;
protected abstract void init(Map<String, FailableSupplier<V>> list) throws Exception;
protected abstract Class<V> getValueClass();
}
@@ -3,7 +3,6 @@ package io.xpipe.app.update;
import io.xpipe.app.core.AppLogs;
import io.xpipe.app.core.AppProperties;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.ext.LocalStore;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.terminal.ExternalTerminalType;
import io.xpipe.app.util.LocalShell;
@@ -1,13 +1,6 @@
package io.xpipe.app.util;
import io.xpipe.app.comp.store.StoreEntryWrapper;
import io.xpipe.app.fxcomps.util.BindingsHelper;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.process.ShellStoreState;
import io.xpipe.core.process.ShellTtyState;
import javafx.beans.value.ObservableValue;
import java.util.Arrays;
@@ -8,8 +8,10 @@ import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.process.ShellEnvironmentStoreState;
import io.xpipe.core.process.ShellStoreState;
import io.xpipe.core.process.ShellTtyState;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableValue;
import lombok.Value;
import java.util.Arrays;
@@ -25,33 +27,49 @@ public class ShellStoreFormat {
var s = (ShellEnvironmentStoreState)
section.getWrapper().getPersistentState().getValue();
var def = Boolean.TRUE.equals(s.getSetDefault()) ? AppI18n.get("default") : null;
var name = DataStoreFormatter.join((includeOsName ? formattedOsName(s.getOsName()) : null), s.getShellName());
return new ShellStoreFormat(null,name, new String[]{def}).format();
var name = DataStoreFormatter.join(
(includeOsName ? formattedOsName(s.getOsName()) : null), s.getShellName());
return new ShellStoreFormat(null, name, new String[] {def}).format();
},
AppPrefs.get().language(),
section.getWrapper().getPersistentState());
}
@SuppressWarnings("unchecked")
public static <T extends ShellStoreState>ObservableValue<String> shellStore(StoreSection section, Function<T, String> f) {
public static <T extends ShellStoreState> ObservableValue<String> shellStore(
StoreSection section, Function<T, String> f) {
return BindingsHelper.map(section.getWrapper().getPersistentState(), o -> {
var s = (T) o;
var info = f.apply(s);
if (s.getShellDialect() != null
&& !s.getShellDialect().getDumbMode().supportsAnyPossibleInteraction()) {
if (s.getOsName() != null) {
return new ShellStoreFormat(LicenseProvider.get().checkOsName(s.getOsName()), formattedOsName(s.getOsName()), new String[]{info}).format();
return new ShellStoreFormat(
LicenseProvider.get().checkOsName(s.getOsName()),
formattedOsName(s.getOsName()),
new String[] {info})
.format();
}
if (s.getShellDialect().equals(ShellDialects.NO_INTERACTION)) {
return new ShellStoreFormat(null, null, new String[]{info}).format();
return new ShellStoreFormat(null, null, new String[] {info}).format();
}
return new ShellStoreFormat(LicenseProvider.get().getFeature(s.getShellDialect().getLicenseFeatureId()), s.getShellDialect().getDisplayName(), new String[]{info}).format();
return new ShellStoreFormat(
LicenseProvider.get()
.getFeature(s.getShellDialect().getLicenseFeatureId()),
s.getShellDialect().getDisplayName(),
new String[] {info})
.format();
}
return new ShellStoreFormat(LicenseProvider.get().checkOsName(s.getOsName()), formattedOsName(s.getOsName()),
new String[]{s.getTtyState() != null && s.getTtyState() != ShellTtyState.NONE ? "TTY" : null, info}).format();
return new ShellStoreFormat(
LicenseProvider.get().checkOsName(s.getOsName()),
formattedOsName(s.getOsName()),
new String[] {
s.getTtyState() != null && s.getTtyState() != ShellTtyState.NONE ? "TTY" : null, info
})
.format();
});
}
@@ -60,10 +78,16 @@ public class ShellStoreFormat {
String[] states;
public String format() {
var licenseReq = 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;
var state = getStates() != null
? Arrays.stream(getStates())
.filter(s -> s != null)
.map(s -> "[" + s + "]")
.collect(Collectors.joining(" "))
: null;
if (state != null && state.isEmpty()) {
state = null;
}
@@ -97,11 +97,11 @@
-fx-padding: 0.7em 1px 1em 1em;
}
.root:windows * {
.root:windows .text {
-fx-font-smoothing-type: gray;
}
.root:linux * {
.root:linux .text {
-fx-font-smoothing-type: lcd;
}
@@ -14,7 +14,6 @@ import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.resources.SystemIcons;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.util.DataStoreFormatter;
import io.xpipe.app.util.ShellStoreFormat;
import io.xpipe.app.util.TerminalLauncher;
import io.xpipe.core.process.ShellStoreState;
@@ -73,6 +72,6 @@ public interface ShellStoreProvider extends DataStoreProvider {
@Override
default ObservableValue<String> informationString(StoreSection section) {
return ShellStoreFormat.shellStore(section,state -> null);
return ShellStoreFormat.shellStore(section, state -> null);
}
}