mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-24 08:30:27 +00:00
Reformat
This commit is contained in:
parent
54f27a274f
commit
17069267da
95 changed files with 618 additions and 383 deletions
|
@ -122,7 +122,8 @@ public class AppBeaconServer {
|
|||
var file = XPipeInstallation.getLocalBeaconAuthFile();
|
||||
try {
|
||||
Files.delete(file);
|
||||
} catch (IOException ignored) {}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private void start() throws IOException {
|
||||
|
|
|
@ -108,7 +108,7 @@ public class BeaconRequestHandler<T> implements HttpHandler {
|
|||
// Make deserialization error message more readable
|
||||
var message = ex.getMessage()
|
||||
.replace("$RequestBuilder", "")
|
||||
.replace("Exchange$Request","Request")
|
||||
.replace("Exchange$Request", "Request")
|
||||
.replace("at [Source: UNKNOWN; byte offset: #UNKNOWN]", "")
|
||||
.replaceAll("(\\w+) is marked non-null but is null", "field $1 is missing from object")
|
||||
.trim();
|
||||
|
@ -125,8 +125,12 @@ public class BeaconRequestHandler<T> implements HttpHandler {
|
|||
var emptyResponseClass = beaconInterface.getResponseClass().getDeclaredFields().length == 0;
|
||||
if (!emptyResponseClass && response != null) {
|
||||
TrackEvent.trace("Sending response:\n" + response);
|
||||
TrackEvent.trace("Sending raw response:\n" + JacksonMapper.getCensored().valueToTree(response).toPrettyString());
|
||||
var bytes = JacksonMapper.getDefault().valueToTree(response).toPrettyString().getBytes(StandardCharsets.UTF_8);
|
||||
TrackEvent.trace("Sending raw response:\n"
|
||||
+ JacksonMapper.getCensored().valueToTree(response).toPrettyString());
|
||||
var bytes = JacksonMapper.getDefault()
|
||||
.valueToTree(response)
|
||||
.toPrettyString()
|
||||
.getBytes(StandardCharsets.UTF_8);
|
||||
exchange.sendResponseHeaders(200, bytes.length);
|
||||
try (OutputStream os = exchange.getResponseBody()) {
|
||||
os.write(bytes);
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package io.xpipe.app.beacon.impl;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.storage.DataStoreEntry;
|
||||
import io.xpipe.beacon.api.ConnectionAddExchange;
|
||||
import io.xpipe.core.util.ValidationException;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
|
||||
public class ConnectionAddExchangeImpl extends ConnectionAddExchange {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package io.xpipe.app.beacon.impl;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import io.xpipe.app.browser.session.BrowserSessionModel;
|
||||
import io.xpipe.app.core.AppLayoutModel;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
|
@ -8,6 +7,8 @@ import io.xpipe.beacon.BeaconClientException;
|
|||
import io.xpipe.beacon.api.ConnectionBrowseExchange;
|
||||
import io.xpipe.core.store.FileSystemStore;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
|
||||
public class ConnectionBrowseExchangeImpl extends ConnectionBrowseExchange {
|
||||
|
||||
@Override
|
||||
|
@ -18,7 +19,8 @@ public class ConnectionBrowseExchangeImpl extends ConnectionBrowseExchange {
|
|||
if (!(e.getStore() instanceof FileSystemStore)) {
|
||||
throw new BeaconClientException("Not a file system connection");
|
||||
}
|
||||
BrowserSessionModel.DEFAULT.openFileSystemSync(e.ref(),msg.getDirectory() != null ? ignored -> msg.getDirectory() : null,null);
|
||||
BrowserSessionModel.DEFAULT.openFileSystemSync(
|
||||
e.ref(), msg.getDirectory() != null ? ignored -> msg.getDirectory() : null, null);
|
||||
AppLayoutModel.get().selectBrowser();
|
||||
return Response.builder().build();
|
||||
}
|
||||
|
|
|
@ -28,9 +28,16 @@ public class ConnectionInfoExchangeImpl extends ConnectionInfoExchange {
|
|||
.orElseThrow())
|
||||
.getNames();
|
||||
var cat = new StorePath(names.subList(1, names.size()));
|
||||
var cache = e.getStoreCache().entrySet().stream().filter(stringObjectEntry -> {
|
||||
return stringObjectEntry.getValue() != null && (ClassUtils.isPrimitiveOrWrapper(stringObjectEntry.getValue().getClass()) || stringObjectEntry.getValue() instanceof String);
|
||||
}).collect(Collectors.toMap(stringObjectEntry -> stringObjectEntry.getKey(),stringObjectEntry -> stringObjectEntry.getValue()));
|
||||
var cache = e.getStoreCache().entrySet().stream()
|
||||
.filter(stringObjectEntry -> {
|
||||
return stringObjectEntry.getValue() != null
|
||||
&& (ClassUtils.isPrimitiveOrWrapper(
|
||||
stringObjectEntry.getValue().getClass())
|
||||
|| stringObjectEntry.getValue() instanceof String);
|
||||
})
|
||||
.collect(Collectors.toMap(
|
||||
stringObjectEntry -> stringObjectEntry.getKey(),
|
||||
stringObjectEntry -> stringObjectEntry.getValue()));
|
||||
|
||||
var apply = InfoResponse.builder()
|
||||
.lastModified(e.getLastModified())
|
||||
|
@ -50,27 +57,17 @@ public class ConnectionInfoExchangeImpl extends ConnectionInfoExchange {
|
|||
}
|
||||
|
||||
private Class<?> toWrapper(Class<?> clazz) {
|
||||
if (!clazz.isPrimitive())
|
||||
return clazz;
|
||||
if (!clazz.isPrimitive()) return clazz;
|
||||
|
||||
if (clazz == Integer.TYPE)
|
||||
return Integer.class;
|
||||
if (clazz == Long.TYPE)
|
||||
return Long.class;
|
||||
if (clazz == Boolean.TYPE)
|
||||
return Boolean.class;
|
||||
if (clazz == Byte.TYPE)
|
||||
return Byte.class;
|
||||
if (clazz == Character.TYPE)
|
||||
return Character.class;
|
||||
if (clazz == Float.TYPE)
|
||||
return Float.class;
|
||||
if (clazz == Double.TYPE)
|
||||
return Double.class;
|
||||
if (clazz == Short.TYPE)
|
||||
return Short.class;
|
||||
if (clazz == Void.TYPE)
|
||||
return Void.class;
|
||||
if (clazz == Integer.TYPE) return Integer.class;
|
||||
if (clazz == Long.TYPE) return Long.class;
|
||||
if (clazz == Boolean.TYPE) return Boolean.class;
|
||||
if (clazz == Byte.TYPE) return Byte.class;
|
||||
if (clazz == Character.TYPE) return Character.class;
|
||||
if (clazz == Float.TYPE) return Float.class;
|
||||
if (clazz == Double.TYPE) return Double.class;
|
||||
if (clazz == Short.TYPE) return Short.class;
|
||||
if (clazz == Void.TYPE) return Void.class;
|
||||
|
||||
return clazz;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package io.xpipe.app.beacon.impl;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.util.FixedHierarchyStore;
|
||||
import io.xpipe.beacon.BeaconClientException;
|
||||
import io.xpipe.beacon.api.ConnectionRefreshExchange;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
|
||||
public class ConnectionRefreshExchangeImpl extends ConnectionRefreshExchange {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package io.xpipe.app.beacon.impl;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.storage.DataStoreEntry;
|
||||
import io.xpipe.beacon.BeaconClientException;
|
||||
import io.xpipe.beacon.api.ConnectionRemoveExchange;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package io.xpipe.app.beacon.impl;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.util.TerminalLauncher;
|
||||
import io.xpipe.beacon.BeaconClientException;
|
||||
import io.xpipe.beacon.api.ConnectionTerminalExchange;
|
||||
import io.xpipe.core.store.ShellStore;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
|
||||
public class ConnectionTerminalExchangeImpl extends ConnectionTerminalExchange {
|
||||
|
||||
@Override
|
||||
|
@ -18,7 +19,7 @@ public class ConnectionTerminalExchangeImpl extends ConnectionTerminalExchange {
|
|||
throw new BeaconClientException("Not a shell connection");
|
||||
}
|
||||
try (var sc = shellStore.control().start()) {
|
||||
TerminalLauncher.open(e,e.getName(),msg.getDirectory(),sc);
|
||||
TerminalLauncher.open(e, e.getName(), msg.getDirectory(), sc);
|
||||
}
|
||||
return Response.builder().build();
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package io.xpipe.app.beacon.impl;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.beacon.BeaconClientException;
|
||||
import io.xpipe.beacon.api.ConnectionToggleExchange;
|
||||
import io.xpipe.core.store.SingletonSessionStore;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
|
||||
public class ConnectionToggleExchangeImpl extends ConnectionToggleExchange {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -35,9 +35,13 @@ public final class BrowserBookmarkHeaderComp extends SimpleComp {
|
|||
.apply(struc -> {
|
||||
AppFont.medium(struc.get());
|
||||
});
|
||||
var filter = new FilterComp(this.filter).styleClass(Styles.RIGHT_PILL).minWidth(0).hgrow().apply(struc -> {
|
||||
AppFont.medium(struc.get());
|
||||
});
|
||||
var filter = new FilterComp(this.filter)
|
||||
.styleClass(Styles.RIGHT_PILL)
|
||||
.minWidth(0)
|
||||
.hgrow()
|
||||
.apply(struc -> {
|
||||
AppFont.medium(struc.get());
|
||||
});
|
||||
|
||||
var top = new HorizontalComp(List.of(category, filter))
|
||||
.apply(struc -> struc.get().setFillHeight(true))
|
||||
|
|
|
@ -12,10 +12,12 @@ import io.xpipe.app.fxcomps.impl.HorizontalComp;
|
|||
import io.xpipe.app.fxcomps.impl.LabelComp;
|
||||
import io.xpipe.app.fxcomps.util.BindingsHelper;
|
||||
import io.xpipe.app.util.HumanReadableFormat;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.input.MouseButton;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
|
||||
|
@ -37,8 +39,7 @@ public class BrowserStatusBarComp extends SimpleComp {
|
|||
createProgressEstimateStatus(),
|
||||
Comp.hspacer(),
|
||||
createClipboardStatus(),
|
||||
createSelectionStatus()
|
||||
));
|
||||
createSelectionStatus()));
|
||||
bar.spacing(15);
|
||||
bar.styleClass("status-bar");
|
||||
|
||||
|
@ -58,12 +59,16 @@ public class BrowserStatusBarComp extends SimpleComp {
|
|||
return null;
|
||||
} else {
|
||||
var expected = p.expectedTimeRemaining();
|
||||
var show = p.elapsedTime().compareTo(Duration.of(200, ChronoUnit.MILLIS)) > 0 && (p.getTotal() > 50_000_000 || expected.toMillis() > 5000);
|
||||
var show = p.elapsedTime().compareTo(Duration.of(200, ChronoUnit.MILLIS)) > 0
|
||||
&& (p.getTotal() > 50_000_000 || expected.toMillis() > 5000);
|
||||
var time = show ? HumanReadableFormat.duration(p.expectedTimeRemaining()) : "";
|
||||
return time;
|
||||
}
|
||||
});
|
||||
var progressComp = new LabelComp(text).styleClass("progress").apply(struc -> struc.get().setAlignment(Pos.CENTER_LEFT)).prefWidth(90);
|
||||
var progressComp = new LabelComp(text)
|
||||
.styleClass("progress")
|
||||
.apply(struc -> struc.get().setAlignment(Pos.CENTER_LEFT))
|
||||
.prefWidth(90);
|
||||
return progressComp;
|
||||
}
|
||||
|
||||
|
@ -77,7 +82,10 @@ public class BrowserStatusBarComp extends SimpleComp {
|
|||
return transferred + " / " + all;
|
||||
}
|
||||
});
|
||||
var progressComp = new LabelComp(text).styleClass("progress").apply(struc -> struc.get().setAlignment(Pos.CENTER_LEFT)).prefWidth(150);
|
||||
var progressComp = new LabelComp(text)
|
||||
.styleClass("progress")
|
||||
.apply(struc -> struc.get().setAlignment(Pos.CENTER_LEFT))
|
||||
.prefWidth(150);
|
||||
return progressComp;
|
||||
}
|
||||
|
||||
|
@ -89,7 +97,10 @@ public class BrowserStatusBarComp extends SimpleComp {
|
|||
return p.getName();
|
||||
}
|
||||
});
|
||||
var progressComp = new LabelComp(text).styleClass("progress").apply(struc -> struc.get().setAlignment(Pos.CENTER_LEFT)).prefWidth(180);
|
||||
var progressComp = new LabelComp(text)
|
||||
.styleClass("progress")
|
||||
.apply(struc -> struc.get().setAlignment(Pos.CENTER_LEFT))
|
||||
.prefWidth(180);
|
||||
return progressComp;
|
||||
}
|
||||
|
||||
|
@ -160,7 +171,6 @@ public class BrowserStatusBarComp extends SimpleComp {
|
|||
emptyEntry.onDragDone(event);
|
||||
});
|
||||
|
||||
|
||||
// Use status bar as an extension of file list
|
||||
new ContextMenuAugment<>(
|
||||
mouseEvent -> mouseEvent.getButton() == MouseButton.SECONDARY,
|
||||
|
|
|
@ -9,6 +9,7 @@ import io.xpipe.app.fxcomps.augment.DragOverPseudoClassAugment;
|
|||
import io.xpipe.app.fxcomps.impl.*;
|
||||
import io.xpipe.app.fxcomps.util.DerivedObservableList;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
|
@ -19,6 +20,7 @@ import javafx.scene.input.ClipboardContent;
|
|||
import javafx.scene.input.Dragboard;
|
||||
import javafx.scene.input.TransferMode;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -47,25 +49,29 @@ public class BrowserTransferComp extends SimpleComp {
|
|||
var binding = new DerivedObservableList<>(model.getItems(), true)
|
||||
.mapped(item -> item.getBrowserEntry())
|
||||
.getList();
|
||||
var list = new BrowserSelectionListComp(
|
||||
binding,
|
||||
entry -> {
|
||||
var sourceItem = model.getCurrentItems().stream()
|
||||
.filter(item -> item.getBrowserEntry() == entry)
|
||||
.findAny();
|
||||
if (sourceItem.isEmpty()) {
|
||||
return new SimpleStringProperty("?");
|
||||
}
|
||||
synchronized (sourceItem.get().getProgress()) {
|
||||
return Bindings.createStringBinding(() -> {
|
||||
var list = new BrowserSelectionListComp(binding, entry -> {
|
||||
var sourceItem = model.getCurrentItems().stream()
|
||||
.filter(item -> item.getBrowserEntry() == entry)
|
||||
.findAny();
|
||||
if (sourceItem.isEmpty()) {
|
||||
return new SimpleStringProperty("?");
|
||||
}
|
||||
synchronized (sourceItem.get().getProgress()) {
|
||||
return Bindings.createStringBinding(
|
||||
() -> {
|
||||
var p = sourceItem.get().getProgress().getValue();
|
||||
var progressSuffix = p == null || sourceItem.get().downloadFinished().get() ?
|
||||
"" :
|
||||
" " + (p.getTransferred() * 100 / p.getTotal()) + "%";
|
||||
var progressSuffix = p == null
|
||||
|| sourceItem
|
||||
.get()
|
||||
.downloadFinished()
|
||||
.get()
|
||||
? ""
|
||||
: " " + (p.getTransferred() * 100 / p.getTotal()) + "%";
|
||||
return entry.getFileName() + progressSuffix;
|
||||
}, sourceItem.get().getProgress());
|
||||
}
|
||||
})
|
||||
},
|
||||
sourceItem.get().getProgress());
|
||||
}
|
||||
})
|
||||
.grow(false, true);
|
||||
var dragNotice = new LabelComp(AppI18n.observable("dragLocalFiles"))
|
||||
.apply(struc -> struc.get().setGraphic(new FontIcon("mdi2h-hand-left")))
|
||||
|
@ -74,111 +80,110 @@ public class BrowserTransferComp extends SimpleComp {
|
|||
.hide(model.getEmpty());
|
||||
|
||||
var clearButton = new IconButtonComp("mdi2c-close", () -> {
|
||||
ThreadHelper.runAsync(() -> {
|
||||
model.clear(true);
|
||||
});
|
||||
ThreadHelper.runAsync(() -> {
|
||||
model.clear(true);
|
||||
});
|
||||
})
|
||||
.hide(model.getEmpty())
|
||||
.tooltipKey("clearTransferDescription");
|
||||
|
||||
var downloadButton = new IconButtonComp("mdi2f-folder-move-outline", () -> {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
model.transferToDownloads();
|
||||
});
|
||||
})
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
model.transferToDownloads();
|
||||
});
|
||||
})
|
||||
.hide(model.getEmpty())
|
||||
.tooltipKey("downloadStageDescription");
|
||||
|
||||
var bottom =
|
||||
new HorizontalComp(List.of(Comp.hspacer(), dragNotice, Comp.hspacer(), downloadButton, Comp.hspacer(4), clearButton));
|
||||
var bottom = new HorizontalComp(
|
||||
List.of(Comp.hspacer(), dragNotice, Comp.hspacer(), downloadButton, Comp.hspacer(4), clearButton));
|
||||
var listBox = new VerticalComp(List.of(list, bottom))
|
||||
.spacing(5)
|
||||
.padding(new Insets(10, 10, 5, 10))
|
||||
.apply(struc -> struc.get().setMinHeight(200))
|
||||
.apply(struc -> struc.get().setMaxHeight(200));
|
||||
var stack = new StackComp(List.of(backgroundStack, listBox))
|
||||
.apply(DragOverPseudoClassAugment.create())
|
||||
.apply(struc -> {
|
||||
struc.get().setOnDragOver(event -> {
|
||||
// Accept drops from inside the app window
|
||||
if (event.getGestureSource() != null && event.getGestureSource() != struc.get()) {
|
||||
event.acceptTransferModes(TransferMode.ANY);
|
||||
event.consume();
|
||||
}
|
||||
});
|
||||
struc.get().setOnDragDropped(event -> {
|
||||
// Accept drops from inside the app window
|
||||
if (event.getGestureSource() != null) {
|
||||
var drag = BrowserClipboard.retrieveDrag(event.getDragboard());
|
||||
if (drag == null) {
|
||||
return;
|
||||
.apply(DragOverPseudoClassAugment.create())
|
||||
.apply(struc -> {
|
||||
struc.get().setOnDragOver(event -> {
|
||||
// Accept drops from inside the app window
|
||||
if (event.getGestureSource() != null && event.getGestureSource() != struc.get()) {
|
||||
event.acceptTransferModes(TransferMode.ANY);
|
||||
event.consume();
|
||||
}
|
||||
});
|
||||
struc.get().setOnDragDropped(event -> {
|
||||
// Accept drops from inside the app window
|
||||
if (event.getGestureSource() != null) {
|
||||
var drag = BrowserClipboard.retrieveDrag(event.getDragboard());
|
||||
if (drag == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(model.getBrowserSessionModel()
|
||||
.getSelectedEntry()
|
||||
.getValue()
|
||||
instanceof OpenFileSystemModel fileSystemModel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var files = drag.getEntries();
|
||||
model.drop(fileSystemModel, files);
|
||||
event.setDropCompleted(true);
|
||||
event.consume();
|
||||
}
|
||||
});
|
||||
struc.get().setOnDragDetected(event -> {
|
||||
var items = model.getCurrentItems();
|
||||
var selected = items.stream()
|
||||
.map(item -> item.getBrowserEntry())
|
||||
.toList();
|
||||
var files = items.stream()
|
||||
.filter(item -> item.downloadFinished().get())
|
||||
.map(item -> {
|
||||
try {
|
||||
var file = item.getLocalFile();
|
||||
if (!Files.exists(file)) {
|
||||
return Optional.<File>empty();
|
||||
}
|
||||
|
||||
return Optional.of(file.toRealPath().toFile());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
})
|
||||
.flatMap(Optional::stream)
|
||||
.toList();
|
||||
if (files.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(model.getBrowserSessionModel()
|
||||
.getSelectedEntry()
|
||||
.getValue()
|
||||
instanceof OpenFileSystemModel fileSystemModel)) {
|
||||
return;
|
||||
}
|
||||
var cc = new ClipboardContent();
|
||||
cc.putFiles(files);
|
||||
Dragboard db = struc.get().startDragAndDrop(TransferMode.COPY);
|
||||
db.setContent(cc);
|
||||
|
||||
var files = drag.getEntries();
|
||||
model.drop(fileSystemModel, files);
|
||||
event.setDropCompleted(true);
|
||||
event.consume();
|
||||
}
|
||||
});
|
||||
struc.get().setOnDragDetected(event -> {
|
||||
var items = model.getCurrentItems();
|
||||
var selected = items.stream()
|
||||
.map(item -> item.getBrowserEntry())
|
||||
.toList();
|
||||
var files = items.stream()
|
||||
.filter(item -> item.downloadFinished().get())
|
||||
.map(item -> {
|
||||
try {
|
||||
var file = item.getLocalFile();
|
||||
if (!Files.exists(file)) {
|
||||
return Optional.<File>empty();
|
||||
}
|
||||
Image image = BrowserSelectionListComp.snapshot(FXCollections.observableList(selected));
|
||||
db.setDragView(image, -20, 15);
|
||||
|
||||
return Optional.of(
|
||||
file.toRealPath().toFile());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
})
|
||||
.flatMap(Optional::stream)
|
||||
.toList();
|
||||
if (files.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
event.setDragDetect(true);
|
||||
event.consume();
|
||||
});
|
||||
struc.get().setOnDragDone(event -> {
|
||||
if (!event.isAccepted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var cc = new ClipboardContent();
|
||||
cc.putFiles(files);
|
||||
Dragboard db = struc.get().startDragAndDrop(TransferMode.COPY);
|
||||
db.setContent(cc);
|
||||
|
||||
Image image = BrowserSelectionListComp.snapshot(FXCollections.observableList(selected));
|
||||
db.setDragView(image, -20, 15);
|
||||
|
||||
event.setDragDetect(true);
|
||||
event.consume();
|
||||
});
|
||||
struc.get().setOnDragDone(event -> {
|
||||
if (!event.isAccepted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The files might not have been transferred yet
|
||||
// We can't listen to this, so just don't delete them
|
||||
model.clear(false);
|
||||
event.consume();
|
||||
});
|
||||
});
|
||||
// The files might not have been transferred yet
|
||||
// We can't listen to this, so just don't delete them
|
||||
model.clear(false);
|
||||
event.consume();
|
||||
});
|
||||
});
|
||||
|
||||
stack.apply(struc -> {
|
||||
model.getBrowserSessionModel().getDraggingFiles().addListener((observable, oldValue, newValue) -> {
|
||||
struc.get().pseudoClassStateChanged(PseudoClass.getPseudoClass("highlighted"),newValue);
|
||||
struc.get().pseudoClassStateChanged(PseudoClass.getPseudoClass("highlighted"), newValue);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -10,12 +10,14 @@ import io.xpipe.app.issue.ErrorEvent;
|
|||
import io.xpipe.app.util.DesktopHelper;
|
||||
import io.xpipe.app.util.ShellTemp;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.value.ObservableBooleanValue;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
import lombok.Value;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
|
@ -38,17 +40,19 @@ public class BrowserTransferModel {
|
|||
|
||||
public BrowserTransferModel(BrowserSessionModel browserSessionModel) {
|
||||
this.browserSessionModel = browserSessionModel;
|
||||
var thread = ThreadHelper.createPlatformThread("file downloader", true,() -> {
|
||||
while (true) {
|
||||
Optional<Item> toDownload;
|
||||
synchronized (items) {
|
||||
toDownload = items.stream().filter(item -> !item.downloadFinished().get()).findFirst();
|
||||
}
|
||||
if (toDownload.isPresent()) {
|
||||
downloadSingle(toDownload.get());
|
||||
}
|
||||
ThreadHelper.sleep(20);
|
||||
}
|
||||
var thread = ThreadHelper.createPlatformThread("file downloader", true, () -> {
|
||||
while (true) {
|
||||
Optional<Item> toDownload;
|
||||
synchronized (items) {
|
||||
toDownload = items.stream()
|
||||
.filter(item -> !item.downloadFinished().get())
|
||||
.findFirst();
|
||||
}
|
||||
if (toDownload.isPresent()) {
|
||||
downloadSingle(toDownload.get());
|
||||
}
|
||||
ThreadHelper.sleep(20);
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
|
@ -78,7 +82,8 @@ public class BrowserTransferModel {
|
|||
public void clear(boolean delete) {
|
||||
List<Item> toClear;
|
||||
synchronized (items) {
|
||||
toClear = items.stream().filter(item -> item.downloadFinished().get()).toList();
|
||||
toClear =
|
||||
items.stream().filter(item -> item.downloadFinished().get()).toList();
|
||||
if (toClear.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -114,40 +119,41 @@ public class BrowserTransferModel {
|
|||
return;
|
||||
}
|
||||
|
||||
if (item.downloadFinished().get()) {
|
||||
return;
|
||||
}
|
||||
if (item.downloadFinished().get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.getOpenFileSystemModel() != null
|
||||
&& item.getOpenFileSystemModel().isClosed()) {
|
||||
return;
|
||||
}
|
||||
if (item.getOpenFileSystemModel() != null
|
||||
&& item.getOpenFileSystemModel().isClosed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var op = new BrowserFileTransferOperation(
|
||||
LocalFileSystem.getLocalFileEntry(TEMP),
|
||||
List.of(item.getBrowserEntry().getRawFileEntry()),
|
||||
BrowserFileTransferMode.COPY,
|
||||
false,
|
||||
progress -> {
|
||||
synchronized (item.getProgress()) {
|
||||
item.getProgress().setValue(progress);
|
||||
}
|
||||
item.getOpenFileSystemModel().getProgress().setValue(progress);
|
||||
});
|
||||
op.execute();
|
||||
} catch (Throwable t) {
|
||||
ErrorEvent.fromThrowable(t).handle();
|
||||
synchronized (items) {
|
||||
items.remove(item);
|
||||
}
|
||||
try {
|
||||
var op = new BrowserFileTransferOperation(
|
||||
LocalFileSystem.getLocalFileEntry(TEMP),
|
||||
List.of(item.getBrowserEntry().getRawFileEntry()),
|
||||
BrowserFileTransferMode.COPY,
|
||||
false,
|
||||
progress -> {
|
||||
synchronized (item.getProgress()) {
|
||||
item.getProgress().setValue(progress);
|
||||
}
|
||||
item.getOpenFileSystemModel().getProgress().setValue(progress);
|
||||
});
|
||||
op.execute();
|
||||
} catch (Throwable t) {
|
||||
ErrorEvent.fromThrowable(t).handle();
|
||||
synchronized (items) {
|
||||
items.remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void transferToDownloads() throws Exception {
|
||||
List<Item> toMove;
|
||||
synchronized (items) {
|
||||
toMove = items.stream().filter(item -> item.downloadFinished().get()).toList();
|
||||
toMove =
|
||||
items.stream().filter(item -> item.downloadFinished().get()).toList();
|
||||
if (toMove.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package io.xpipe.app.browser;
|
||||
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import io.xpipe.app.browser.session.BrowserSessionModel;
|
||||
import io.xpipe.app.comp.base.ButtonComp;
|
||||
import io.xpipe.app.comp.base.ListBoxViewComp;
|
||||
|
@ -18,6 +16,7 @@ import io.xpipe.app.fxcomps.util.BindingsHelper;
|
|||
import io.xpipe.app.fxcomps.util.DerivedObservableList;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
|
@ -31,6 +30,9 @@ import javafx.scene.layout.Priority;
|
|||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.base.theme.Styles;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BrowserWelcomeComp extends SimpleComp {
|
||||
|
|
|
@ -80,7 +80,10 @@ public class BrowserAlerts {
|
|||
private static String getSelectedElementsString(List<FileSystem.FileEntry> source) {
|
||||
var namesHeader = AppI18n.get("selectedElements");
|
||||
var names = namesHeader + "\n"
|
||||
+ source.stream().limit(10).map(entry -> "- " + new FilePath(entry.getPath()).getFileName()).collect(Collectors.joining("\n"));
|
||||
+ source.stream()
|
||||
.limit(10)
|
||||
.map(entry -> "- " + new FilePath(entry.getPath()).getFileName())
|
||||
.collect(Collectors.joining("\n"));
|
||||
if (source.size() > 10) {
|
||||
names += "\n+ " + (source.size() - 10) + " ...";
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package io.xpipe.app.browser.file;
|
||||
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import io.xpipe.app.browser.action.BrowserAction;
|
||||
import io.xpipe.app.comp.base.LazyTextFieldComp;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
|
@ -13,6 +11,7 @@ import io.xpipe.core.process.OsType;
|
|||
import io.xpipe.core.store.FileKind;
|
||||
import io.xpipe.core.store.FileNames;
|
||||
import io.xpipe.core.store.FileSystem;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.*;
|
||||
|
@ -33,6 +32,9 @@ import javafx.scene.layout.HBox;
|
|||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.base.theme.Styles;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
|
@ -133,15 +135,18 @@ public final class BrowserFileListComp extends SimpleComp {
|
|||
|
||||
private void prepareTypedSelectionModel(TableView<BrowserEntry> table) {
|
||||
AtomicReference<Instant> lastFail = new AtomicReference<>();
|
||||
table.addEventHandler(KeyEvent.KEY_PRESSED,event -> {
|
||||
table.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
|
||||
var typed = event.getText();
|
||||
if (typed.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var updated = typedSelection.get() + typed;
|
||||
var find = fileList.getShown().getValue().stream().filter(browserEntry -> browserEntry.getFileName().toLowerCase().startsWith(updated.toLowerCase())).findFirst();
|
||||
if (find.isEmpty()) {
|
||||
var found = fileList.getShown().getValue().stream()
|
||||
.filter(browserEntry ->
|
||||
browserEntry.getFileName().toLowerCase().startsWith(updated.toLowerCase()))
|
||||
.findFirst();
|
||||
if (found.isEmpty()) {
|
||||
if (lastFail.get() == null) {
|
||||
lastFail.set(Instant.now());
|
||||
}
|
||||
|
@ -161,8 +166,9 @@ public final class BrowserFileListComp extends SimpleComp {
|
|||
|
||||
lastFail.set(null);
|
||||
typedSelection.set(updated);
|
||||
table.scrollTo(find.get());
|
||||
table.getSelectionModel().clearAndSelect(fileList.getShown().getValue().indexOf(find.get()));
|
||||
table.scrollTo(found.get());
|
||||
table.getSelectionModel()
|
||||
.clearAndSelect(fileList.getShown().getValue().indexOf(found.get()));
|
||||
event.consume();
|
||||
});
|
||||
|
||||
|
@ -176,7 +182,7 @@ public final class BrowserFileListComp extends SimpleComp {
|
|||
lastFail.set(null);
|
||||
});
|
||||
|
||||
table.addEventFilter(KeyEvent.KEY_PRESSED,event -> {
|
||||
table.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||
if (event.getCode() == KeyCode.ESCAPE) {
|
||||
typedSelection.set("");
|
||||
lastFail.set(null);
|
||||
|
@ -269,7 +275,6 @@ public final class BrowserFileListComp extends SimpleComp {
|
|||
emptyEntry.onDragDone(event);
|
||||
});
|
||||
|
||||
|
||||
// Don't let the list view see this event
|
||||
// otherwise it unselects everything as it doesn't understand shift clicks
|
||||
table.addEventFilter(MouseEvent.MOUSE_CLICKED, t -> {
|
||||
|
@ -350,7 +355,6 @@ public final class BrowserFileListComp extends SimpleComp {
|
|||
listEntry.get().onDragDone(event);
|
||||
});
|
||||
|
||||
|
||||
return row;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ public class BrowserFileListCompEntry {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void onMouseShiftClick(MouseEvent t) {
|
||||
if (t.getButton() != MouseButton.PRIMARY) {
|
||||
return;
|
||||
|
|
|
@ -104,19 +104,23 @@ public final class BrowserFileListModel {
|
|||
|
||||
// This check will fail on case-insensitive file systems when changing the case of the file
|
||||
// So skip it in this case
|
||||
var skipExistCheck = fileSystemModel.getFileSystem().getShell().orElseThrow().getOsType() == OsType.WINDOWS && old.getFileName()
|
||||
.equalsIgnoreCase(newName);
|
||||
var skipExistCheck =
|
||||
fileSystemModel.getFileSystem().getShell().orElseThrow().getOsType() == OsType.WINDOWS
|
||||
&& old.getFileName().equalsIgnoreCase(newName);
|
||||
if (!skipExistCheck) {
|
||||
boolean exists;
|
||||
try {
|
||||
exists = fileSystemModel.getFileSystem().fileExists(newFullPath) || fileSystemModel.getFileSystem().directoryExists(newFullPath);
|
||||
exists = fileSystemModel.getFileSystem().fileExists(newFullPath)
|
||||
|| fileSystemModel.getFileSystem().directoryExists(newFullPath);
|
||||
} catch (Exception e) {
|
||||
ErrorEvent.fromThrowable(e).handle();
|
||||
return old;
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
ErrorEvent.fromMessage("Target " + newFullPath + " does already exist").expected().handle();
|
||||
ErrorEvent.fromMessage("Target " + newFullPath + " does already exist")
|
||||
.expected()
|
||||
.handle();
|
||||
fileSystemModel.refresh();
|
||||
return old;
|
||||
}
|
||||
|
|
|
@ -224,7 +224,13 @@ public class BrowserFileTransferOperation {
|
|||
updateProgress(BrowserTransferProgress.finished(source.getName(), totalSize.get()));
|
||||
}
|
||||
|
||||
private void transfer(FileSystem.FileEntry sourceFile, String targetFile, AtomicLong transferred, AtomicLong totalSize, Instant start) throws Exception {
|
||||
private void transfer(
|
||||
FileSystem.FileEntry sourceFile,
|
||||
String targetFile,
|
||||
AtomicLong transferred,
|
||||
AtomicLong totalSize,
|
||||
Instant start)
|
||||
throws Exception {
|
||||
InputStream inputStream = null;
|
||||
OutputStream outputStream = null;
|
||||
try {
|
||||
|
|
|
@ -24,8 +24,10 @@ import io.xpipe.core.process.ShellDialects;
|
|||
import io.xpipe.core.process.ShellOpenFunction;
|
||||
import io.xpipe.core.store.*;
|
||||
import io.xpipe.core.util.FailableConsumer;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.*;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
|
@ -113,7 +115,8 @@ public final class OpenFileSystemModel extends BrowserSessionTab<FileSystemStore
|
|||
&& savedState != null
|
||||
&& current != null) {
|
||||
savedState.cd(current.getPath(), false);
|
||||
BrowserSavedStateImpl.get().add(new BrowserSavedState.Entry(getEntry().get().getUuid(), current.getPath()));
|
||||
BrowserSavedStateImpl.get()
|
||||
.add(new BrowserSavedState.Entry(getEntry().get().getUuid(), current.getPath()));
|
||||
}
|
||||
try {
|
||||
fileSystem.close();
|
||||
|
|
|
@ -82,22 +82,24 @@ public class OpenFileSystemSavedState {
|
|||
|
||||
if (delay) {
|
||||
// After 10 seconds
|
||||
TIMEOUT_TIMER.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Synchronize with platform thread
|
||||
Platform.runLater(() -> {
|
||||
if (model.isClosed()) {
|
||||
return;
|
||||
}
|
||||
TIMEOUT_TIMER.schedule(
|
||||
new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Synchronize with platform thread
|
||||
Platform.runLater(() -> {
|
||||
if (model.isClosed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Objects.equals(lastDirectory, dir)) {
|
||||
updateRecent(dir);
|
||||
save();
|
||||
if (Objects.equals(lastDirectory, dir)) {
|
||||
updateRecent(dir);
|
||||
save();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 10000);
|
||||
},
|
||||
10000);
|
||||
} else {
|
||||
updateRecent(dir);
|
||||
save();
|
||||
|
|
|
@ -2,12 +2,14 @@ package io.xpipe.app.browser.session;
|
|||
|
||||
import io.xpipe.app.util.BooleanScope;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
|
|
|
@ -65,7 +65,6 @@ public class BrowserFileChooserModel extends BrowserAbstractSessionModel<OpenFil
|
|||
onFinish.accept(stores);
|
||||
}
|
||||
|
||||
|
||||
public void finishWithoutChoice() {
|
||||
synchronized (BrowserFileChooserModel.this) {
|
||||
var open = selectedEntry.getValue();
|
||||
|
|
|
@ -16,6 +16,7 @@ import io.xpipe.app.fxcomps.util.BindingsHelper;
|
|||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
import io.xpipe.core.store.ShellStore;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
|
@ -103,16 +104,15 @@ public class BrowserSessionComp extends SimpleComp {
|
|||
new VerticalComp(List.of(bookmarkTopBar, bookmarksContainer, localDownloadStage)).styleClass("left");
|
||||
|
||||
var split = new SimpleDoubleProperty();
|
||||
var tabs = new BrowserSessionTabsComp(model, split)
|
||||
.apply(struc -> {
|
||||
struc.get().setViewOrder(1);
|
||||
struc.get().setPickOnBounds(false);
|
||||
AnchorPane.setTopAnchor(struc.get(), 0.0);
|
||||
AnchorPane.setBottomAnchor(struc.get(), 0.0);
|
||||
AnchorPane.setLeftAnchor(struc.get(), 0.0);
|
||||
AnchorPane.setRightAnchor(struc.get(), 0.0);
|
||||
});
|
||||
var loadingIndicator = LoadingOverlayComp.noProgress(Comp.empty(),model.getBusy())
|
||||
var tabs = new BrowserSessionTabsComp(model, split).apply(struc -> {
|
||||
struc.get().setViewOrder(1);
|
||||
struc.get().setPickOnBounds(false);
|
||||
AnchorPane.setTopAnchor(struc.get(), 0.0);
|
||||
AnchorPane.setBottomAnchor(struc.get(), 0.0);
|
||||
AnchorPane.setLeftAnchor(struc.get(), 0.0);
|
||||
AnchorPane.setRightAnchor(struc.get(), 0.0);
|
||||
});
|
||||
var loadingIndicator = LoadingOverlayComp.noProgress(Comp.empty(), model.getBusy())
|
||||
.apply(struc -> {
|
||||
AnchorPane.setTopAnchor(struc.get(), 0.0);
|
||||
AnchorPane.setRightAnchor(struc.get(), 0.0);
|
||||
|
|
|
@ -80,7 +80,8 @@ public class BrowserSessionModel extends BrowserAbstractSessionModel<BrowserSess
|
|||
public void openFileSystemSync(
|
||||
DataStoreEntryRef<? extends FileSystemStore> store,
|
||||
FailableFunction<OpenFileSystemModel, String, Exception> path,
|
||||
BooleanProperty externalBusy) throws Exception {
|
||||
BooleanProperty externalBusy)
|
||||
throws Exception {
|
||||
if (store == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package io.xpipe.app.browser.session;
|
||||
|
||||
import atlantafx.base.controls.RingProgressIndicator;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import io.xpipe.app.browser.BrowserWelcomeComp;
|
||||
import io.xpipe.app.comp.base.MultiContentComp;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
|
@ -15,6 +13,7 @@ import io.xpipe.app.storage.DataStorage;
|
|||
import io.xpipe.app.util.BooleanScope;
|
||||
import io.xpipe.app.util.ContextMenuHelper;
|
||||
import io.xpipe.app.util.InputHelper;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
|
@ -32,6 +31,9 @@ import javafx.scene.input.KeyCombination;
|
|||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.StackPane;
|
||||
|
||||
import atlantafx.base.controls.RingProgressIndicator;
|
||||
import atlantafx.base.theme.Styles;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static atlantafx.base.theme.Styles.DENSE;
|
||||
|
@ -50,11 +52,10 @@ public class BrowserSessionTabsComp extends SimpleComp {
|
|||
|
||||
public Region createSimple() {
|
||||
var map = new LinkedHashMap<Comp<?>, ObservableValue<Boolean>>();
|
||||
map.put(Comp.hspacer().styleClass("top-spacer"),
|
||||
new SimpleBooleanProperty(true));
|
||||
map.put(Comp.of(() -> createTabPane()),
|
||||
Bindings.isNotEmpty(model.getSessionEntries()));
|
||||
map.put(new BrowserWelcomeComp(model).apply(struc -> StackPane.setAlignment(struc.get(), Pos.CENTER_LEFT)),
|
||||
map.put(Comp.hspacer().styleClass("top-spacer"), new SimpleBooleanProperty(true));
|
||||
map.put(Comp.of(() -> createTabPane()), Bindings.isNotEmpty(model.getSessionEntries()));
|
||||
map.put(
|
||||
new BrowserWelcomeComp(model).apply(struc -> StackPane.setAlignment(struc.get(), Pos.CENTER_LEFT)),
|
||||
Bindings.createBooleanBinding(
|
||||
() -> {
|
||||
return model.getSessionEntries().size() == 0;
|
||||
|
@ -227,7 +228,8 @@ public class BrowserSessionTabsComp extends SimpleComp {
|
|||
|
||||
var forward = new KeyCodeCombination(KeyCode.TAB, KeyCombination.CONTROL_DOWN);
|
||||
if (forward.match(keyEvent)) {
|
||||
var next = (tabs.getSelectionModel().getSelectedIndex() + 1) % tabs.getTabs().size();
|
||||
var next = (tabs.getSelectionModel().getSelectedIndex() + 1)
|
||||
% tabs.getTabs().size();
|
||||
tabs.getSelectionModel().select(next);
|
||||
keyEvent.consume();
|
||||
return;
|
||||
|
@ -235,7 +237,8 @@ public class BrowserSessionTabsComp extends SimpleComp {
|
|||
|
||||
var back = new KeyCodeCombination(KeyCode.TAB, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN);
|
||||
if (back.match(keyEvent)) {
|
||||
var previous = (tabs.getTabs().size() + tabs.getSelectionModel().getSelectedIndex() - 1) % tabs.getTabs().size();
|
||||
var previous = (tabs.getTabs().size() + tabs.getSelectionModel().getSelectedIndex() - 1)
|
||||
% tabs.getTabs().size();
|
||||
tabs.getSelectionModel().select(previous);
|
||||
keyEvent.consume();
|
||||
return;
|
||||
|
@ -249,12 +252,18 @@ public class BrowserSessionTabsComp extends SimpleComp {
|
|||
var cm = ContextMenuHelper.create();
|
||||
|
||||
var select = ContextMenuHelper.item(LabelGraphic.none(), AppI18n.get("selectTab"));
|
||||
select.acceleratorProperty().bind(Bindings.createObjectBinding(() -> {
|
||||
var start = KeyCode.F1.getCode();
|
||||
var index = tabs.getTabs().indexOf(tab);
|
||||
var keyCode = Arrays.stream(KeyCode.values()).filter(code -> code.getCode() == start + index).findAny().orElse(null);
|
||||
return keyCode != null ? new KeyCodeCombination(keyCode) : null;
|
||||
}, tabs.getTabs()));
|
||||
select.acceleratorProperty()
|
||||
.bind(Bindings.createObjectBinding(
|
||||
() -> {
|
||||
var start = KeyCode.F1.getCode();
|
||||
var index = tabs.getTabs().indexOf(tab);
|
||||
var keyCode = Arrays.stream(KeyCode.values())
|
||||
.filter(code -> code.getCode() == start + index)
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
return keyCode != null ? new KeyCodeCombination(keyCode) : null;
|
||||
},
|
||||
tabs.getTabs()));
|
||||
select.setOnAction(event -> {
|
||||
tabs.getSelectionModel().select(tab);
|
||||
event.consume();
|
||||
|
@ -263,7 +272,7 @@ public class BrowserSessionTabsComp extends SimpleComp {
|
|||
|
||||
cm.getItems().add(new SeparatorMenuItem());
|
||||
|
||||
var close = ContextMenuHelper.item(LabelGraphic.none(), AppI18n.get("closeTab" ));
|
||||
var close = ContextMenuHelper.item(LabelGraphic.none(), AppI18n.get("closeTab"));
|
||||
close.setAccelerator(new KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN));
|
||||
close.setOnAction(event -> {
|
||||
tabs.getTabs().remove(tab);
|
||||
|
@ -273,7 +282,8 @@ 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).toList());
|
||||
tabs.getTabs()
|
||||
.removeAll(tabs.getTabs().stream().filter(t -> t != tab).toList());
|
||||
event.consume();
|
||||
});
|
||||
cm.getItems().add(closeOthers);
|
||||
|
@ -281,7 +291,10 @@ public class BrowserSessionTabsComp extends SimpleComp {
|
|||
var closeLeft = ContextMenuHelper.item(LabelGraphic.none(), AppI18n.get("closeLeftTabs"));
|
||||
closeLeft.setOnAction(event -> {
|
||||
var index = tabs.getTabs().indexOf(tab);
|
||||
tabs.getTabs().removeAll(tabs.getTabs().stream().filter(t -> tabs.getTabs().indexOf(t) < index).toList());
|
||||
tabs.getTabs()
|
||||
.removeAll(tabs.getTabs().stream()
|
||||
.filter(t -> tabs.getTabs().indexOf(t) < index)
|
||||
.toList());
|
||||
event.consume();
|
||||
});
|
||||
cm.getItems().add(closeLeft);
|
||||
|
@ -289,13 +302,17 @@ public class BrowserSessionTabsComp extends SimpleComp {
|
|||
var closeRight = ContextMenuHelper.item(LabelGraphic.none(), AppI18n.get("closeRightTabs"));
|
||||
closeRight.setOnAction(event -> {
|
||||
var index = tabs.getTabs().indexOf(tab);
|
||||
tabs.getTabs().removeAll(tabs.getTabs().stream().filter(t -> tabs.getTabs().indexOf(t) > index).toList());
|
||||
tabs.getTabs()
|
||||
.removeAll(tabs.getTabs().stream()
|
||||
.filter(t -> tabs.getTabs().indexOf(t) > index)
|
||||
.toList());
|
||||
event.consume();
|
||||
});
|
||||
cm.getItems().add(closeRight);
|
||||
|
||||
var closeAll = ContextMenuHelper.item(LabelGraphic.none(), AppI18n.get("closeAllTabs"));
|
||||
closeAll.setAccelerator(new KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN, KeyCombination.SHIFT_DOWN));
|
||||
closeAll.setAccelerator(
|
||||
new KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN, KeyCombination.SHIFT_DOWN));
|
||||
closeAll.setOnAction(event -> {
|
||||
tabs.getTabs().clear();
|
||||
event.consume();
|
||||
|
|
|
@ -10,6 +10,7 @@ import io.xpipe.app.fxcomps.CompStructure;
|
|||
import io.xpipe.app.fxcomps.SimpleCompStructure;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.scene.control.ButtonBase;
|
||||
|
|
|
@ -11,6 +11,7 @@ import io.xpipe.app.fxcomps.impl.TooltipAugment;
|
|||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||
import io.xpipe.app.update.UpdateAvailableAlert;
|
||||
import io.xpipe.app.update.XPipeDistributionType;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.Property;
|
||||
|
@ -41,14 +42,14 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
|
|||
var selectedBorder = Bindings.createObjectBinding(
|
||||
() -> {
|
||||
var c = Platform.getPreferences().getAccentColor().desaturate();
|
||||
return new Background(new BackgroundFill(c,new CornerRadii(8), new Insets(10, 1, 10, 2)));
|
||||
return new Background(new BackgroundFill(c, new CornerRadii(8), new Insets(10, 1, 10, 2)));
|
||||
},
|
||||
Platform.getPreferences().accentColorProperty());
|
||||
|
||||
var hoverBorder = Bindings.createObjectBinding(
|
||||
() -> {
|
||||
var c = Platform.getPreferences().getAccentColor().darker().desaturate();
|
||||
return new Background(new BackgroundFill(c,new CornerRadii(8), new Insets(10, 1, 10, 2)));
|
||||
return new Background(new BackgroundFill(c, new CornerRadii(8), new Insets(10, 1, 10, 2)));
|
||||
},
|
||||
Platform.getPreferences().accentColorProperty());
|
||||
|
||||
|
@ -86,7 +87,8 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
|
|||
b.accessibleText(e.name());
|
||||
|
||||
var indicator = Comp.empty().styleClass("indicator");
|
||||
var stack = new StackComp(List.of(indicator, b)).apply(struc -> struc.get().setAlignment(Pos.CENTER_RIGHT));
|
||||
var stack = new StackComp(List.of(indicator, b))
|
||||
.apply(struc -> struc.get().setAlignment(Pos.CENTER_RIGHT));
|
||||
stack.apply(struc -> {
|
||||
var indicatorRegion = (Region) struc.get().getChildren().getFirst();
|
||||
indicatorRegion.setMaxWidth(7);
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.xpipe.app.comp.store;
|
|||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.augment.GrowAugment;
|
||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.geometry.HPos;
|
||||
|
@ -30,7 +31,9 @@ public class DenseStoreEntryComp extends StoreEntryComp {
|
|||
: Comp.empty();
|
||||
information.setGraphic(state.createRegion());
|
||||
|
||||
var info = getWrapper().getEntry().getProvider() != null ? getWrapper().getEntry().getProvider().informationString(section) : new SimpleStringProperty();
|
||||
var info = getWrapper().getEntry().getProvider() != null
|
||||
? getWrapper().getEntry().getProvider().informationString(section)
|
||||
: new SimpleStringProperty();
|
||||
var summary = getWrapper().getSummary();
|
||||
if (getWrapper().getEntry().getProvider() != null) {
|
||||
information
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.xpipe.app.comp.store;
|
|||
import io.xpipe.app.core.AppFont;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.core.process.OsType;
|
||||
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
|
|
|
@ -58,7 +58,7 @@ public abstract class StoreEntryComp extends SimpleComp {
|
|||
this.section = section;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
|
||||
public StoreEntryWrapper getWrapper() {
|
||||
return section.getWrapper();
|
||||
}
|
||||
|
@ -80,9 +80,7 @@ public abstract class StoreEntryComp extends SimpleComp {
|
|||
} else {
|
||||
var forceCondensed = AppPrefs.get() != null
|
||||
&& AppPrefs.get().condenseConnectionDisplay().get();
|
||||
return forceCondensed
|
||||
? new DenseStoreEntryComp(e, true, null)
|
||||
: new StandardStoreEntryComp(e, null);
|
||||
return forceCondensed ? new DenseStoreEntryComp(e, true, null) : new StandardStoreEntryComp(e, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,7 +135,9 @@ public abstract class StoreEntryComp extends SimpleComp {
|
|||
var loading = LoadingOverlayComp.noProgress(
|
||||
Comp.of(() -> button),
|
||||
getWrapper().getEntry().getValidity().isUsable()
|
||||
? getWrapper().getBusy().or(getWrapper().getEntry().getProvider().busy(getWrapper()))
|
||||
? getWrapper()
|
||||
.getBusy()
|
||||
.or(getWrapper().getEntry().getProvider().busy(getWrapper()))
|
||||
: getWrapper().getBusy());
|
||||
AppFont.normal(button);
|
||||
return loading.createRegion();
|
||||
|
@ -194,7 +194,8 @@ public abstract class StoreEntryComp extends SimpleComp {
|
|||
protected Node createIcon(int w, int h) {
|
||||
var img = getWrapper().disabledProperty().get()
|
||||
? "disabled_icon.png"
|
||||
: getWrapper().getEntry()
|
||||
: getWrapper()
|
||||
.getEntry()
|
||||
.getProvider()
|
||||
.getDisplayIconFileName(getWrapper().getEntry().getStore());
|
||||
var imageComp = PrettyImageHelper.ofFixedSize(img, w, h);
|
||||
|
@ -252,8 +253,11 @@ public abstract class StoreEntryComp extends SimpleComp {
|
|||
leaf != null
|
||||
? () -> {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
getWrapper().runAction(
|
||||
leaf.createAction(getWrapper().getEntry().ref()), leaf.showBusy());
|
||||
getWrapper()
|
||||
.runAction(
|
||||
leaf.createAction(
|
||||
getWrapper().getEntry().ref()),
|
||||
leaf.showBusy());
|
||||
});
|
||||
}
|
||||
: null);
|
||||
|
@ -323,8 +327,8 @@ public abstract class StoreEntryComp extends SimpleComp {
|
|||
|
||||
if (AppPrefs.get().developerMode().getValue()) {
|
||||
var browse = new MenuItem(AppI18n.get("browseInternalStorage"), new FontIcon("mdi2f-folder-open-outline"));
|
||||
browse.setOnAction(
|
||||
event -> DesktopHelper.browsePathLocal(getWrapper().getEntry().getDirectory()));
|
||||
browse.setOnAction(event ->
|
||||
DesktopHelper.browsePathLocal(getWrapper().getEntry().getDirectory()));
|
||||
contextMenu.getItems().add(browse);
|
||||
|
||||
var copyId = new MenuItem(AppI18n.get("copyId"), new FontIcon("mdi2c-content-copy"));
|
||||
|
@ -466,19 +470,23 @@ public abstract class StoreEntryComp extends SimpleComp {
|
|||
run.textProperty().bind(AppI18n.observable("base.execute"));
|
||||
run.setOnAction(event -> {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
getWrapper().runAction(leaf.createAction(getWrapper().getEntry().ref()), leaf.showBusy());
|
||||
getWrapper()
|
||||
.runAction(leaf.createAction(getWrapper().getEntry().ref()), leaf.showBusy());
|
||||
});
|
||||
});
|
||||
menu.getItems().add(run);
|
||||
|
||||
var sc = new MenuItem(null, new FontIcon("mdi2c-code-greater-than"));
|
||||
var url = "xpipe://action/" + p.getId() + "/" + getWrapper().getEntry().getUuid();
|
||||
var url = "xpipe://action/" + p.getId() + "/"
|
||||
+ getWrapper().getEntry().getUuid();
|
||||
sc.textProperty().bind(AppI18n.observable("base.createShortcut"));
|
||||
sc.setOnAction(event -> {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
DesktopShortcuts.create(
|
||||
url,
|
||||
DataStorage.get().getStoreEntryDisplayName(getWrapper().getEntry()) + " ("
|
||||
DataStorage.get()
|
||||
.getStoreEntryDisplayName(
|
||||
getWrapper().getEntry()) + " ("
|
||||
+ p.getLeafDataStoreCallSite()
|
||||
.getName(getWrapper().getEntry().ref())
|
||||
.getValue() + ")");
|
||||
|
|
|
@ -151,7 +151,8 @@ public class StoreEntryWrapper {
|
|||
summary.setValue(null);
|
||||
} else {
|
||||
try {
|
||||
summary.setValue(entry.getProvider() != null ? entry.getProvider().summaryString(this) : null);
|
||||
summary.setValue(
|
||||
entry.getProvider() != null ? entry.getProvider().summaryString(this) : null);
|
||||
} catch (Exception ex) {
|
||||
// Summary creation might fail or have a bug
|
||||
ErrorEvent.fromThrowable(ex).handle();
|
||||
|
@ -167,8 +168,8 @@ public class StoreEntryWrapper {
|
|||
.filter(e -> entry.getStore() != null
|
||||
&& e.getDefaultDataStoreCallSite() != null
|
||||
&& e.getDefaultDataStoreCallSite()
|
||||
.getApplicableClass()
|
||||
.isAssignableFrom(entry.getStore().getClass())
|
||||
.getApplicableClass()
|
||||
.isAssignableFrom(entry.getStore().getClass())
|
||||
&& e.getDefaultDataStoreCallSite().isApplicable(entry.ref()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package io.xpipe.app.comp.store;
|
||||
|
||||
import atlantafx.base.controls.Popover;
|
||||
import io.xpipe.app.comp.base.ButtonComp;
|
||||
import io.xpipe.app.comp.base.DialogComp;
|
||||
import io.xpipe.app.comp.base.MarkdownEditorComp;
|
||||
|
@ -11,6 +10,7 @@ import io.xpipe.app.fxcomps.CompStructure;
|
|||
import io.xpipe.app.fxcomps.impl.IconButtonComp;
|
||||
import io.xpipe.app.fxcomps.util.BindingsHelper;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
|
@ -18,6 +18,8 @@ import javafx.event.ActionEvent;
|
|||
import javafx.scene.control.Button;
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
import atlantafx.base.controls.Popover;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
|
|
|
@ -45,8 +45,7 @@ public class StoreQuickAccessButtonComp extends Comp<CompStructure<Button>> {
|
|||
w.getEntry().getProvider().getDisplayIconFileName(w.getEntry().getStore());
|
||||
if (c.getList().isEmpty()) {
|
||||
var item = ContextMenuHelper.item(
|
||||
new LabelGraphic.ImageGraphic(graphic, 16),
|
||||
w.getName().getValue());
|
||||
new LabelGraphic.ImageGraphic(graphic, 16), w.getName().getValue());
|
||||
item.setOnAction(event -> {
|
||||
action.accept(section);
|
||||
contextMenu.hide();
|
||||
|
|
|
@ -65,8 +65,7 @@ public interface StoreSortMode {
|
|||
.isUsable())
|
||||
.map(this::representative),
|
||||
Stream.of(s))
|
||||
.max(Comparator.comparing(
|
||||
section -> date(section)))
|
||||
.max(Comparator.comparing(section -> date(section)))
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
|
@ -103,8 +102,7 @@ public interface StoreSortMode {
|
|||
.isUsable())
|
||||
.map(this::representative),
|
||||
Stream.of(s))
|
||||
.max(Comparator.comparing(
|
||||
section -> date(section)))
|
||||
.max(Comparator.comparing(section -> date(section)))
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,11 @@ import io.xpipe.app.issue.TrackEvent;
|
|||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.update.XPipeDistributionType;
|
||||
import io.xpipe.app.util.LicenseProvider;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
|
|
|
@ -105,8 +105,9 @@ public class AppExtensionManager {
|
|||
var sourceVersion = AppVersion.parse(sv)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Invalid source version: " + sv));
|
||||
if (AppProperties.get().isLocatorVersionCheck() && !installVersion.equals(sourceVersion)) {
|
||||
throw new IllegalStateException("Incompatible development version. Source: " + iv + ", Installation: "
|
||||
+ sv + "\n\nPlease try to check out the matching release version in the repository. See https://github.com/xpipe-io/xpipe/blob/master/CONTRIBUTING.md#development-setup");
|
||||
throw new IllegalStateException(
|
||||
"Incompatible development version. Source: " + iv + ", Installation: " + sv
|
||||
+ "\n\nPlease try to check out the matching release version in the repository. See https://github.com/xpipe-io/xpipe/blob/master/CONTRIBUTING.md#development-setup");
|
||||
}
|
||||
|
||||
var extensions = XPipeInstallation.getLocalExtensionsDirectory(p);
|
||||
|
|
|
@ -128,5 +128,6 @@ public class AppLayoutModel {
|
|||
double browserConnectionsWidth;
|
||||
}
|
||||
|
||||
public record Entry(ObservableValue<String> name, String icon, Comp<?> comp, Runnable action, KeyCombination combination) {}
|
||||
public record Entry(
|
||||
ObservableValue<String> name, String icon, Comp<?> comp, Runnable action, KeyCombination combination) {}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,10 @@ public class AppTheme {
|
|||
|
||||
public static void initThemeHandlers(Stage stage) {
|
||||
Runnable r = () -> {
|
||||
stage.getScene().getRoot().pseudoClassStateChanged(PseudoClass.getPseudoClass(OsType.getLocal().getId()), true);
|
||||
stage.getScene()
|
||||
.getRoot()
|
||||
.pseudoClassStateChanged(
|
||||
PseudoClass.getPseudoClass(OsType.getLocal().getId()), true);
|
||||
if (AppPrefs.get() == null) {
|
||||
var def = Theme.getDefaultLightTheme();
|
||||
stage.getScene().getRoot().getStyleClass().add(def.getCssId());
|
||||
|
@ -207,7 +210,6 @@ public class AppTheme {
|
|||
Application.setUserAgentStylesheet(Styles.toDataURI(builder.toString()));
|
||||
}
|
||||
|
||||
|
||||
public List<String> getAdditionalStylesheets() {
|
||||
return List.of();
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@ import io.xpipe.app.core.mode.OperationMode;
|
|||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.core.process.OsType;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URL;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
public class AppTrayIcon {
|
||||
|
||||
|
|
|
@ -18,9 +18,9 @@ public class AppRosettaCheck {
|
|||
|
||||
var ret = LocalShell.getShell().executeSimpleStringCommand("sysctl -n sysctl.proc_translated");
|
||||
if (ret.equals("1")) {
|
||||
ErrorEvent.fromMessage("You are running the Intel version of XPipe on an Apple Silicon system." +
|
||||
" There is a native build available that comes with much better performance." +
|
||||
" Please install that one instead.");
|
||||
ErrorEvent.fromMessage("You are running the Intel version of XPipe on an Apple Silicon system."
|
||||
+ " There is a native build available that comes with much better performance."
|
||||
+ " Please install that one instead.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import io.xpipe.app.util.LocalShell;
|
|||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.process.ProcessControlProvider;
|
||||
import io.xpipe.core.process.ProcessOutputException;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.Optional;
|
||||
|
|
|
@ -16,7 +16,9 @@ import io.xpipe.app.util.XPipeSession;
|
|||
import io.xpipe.core.util.FailableRunnable;
|
||||
import io.xpipe.core.util.XPipeDaemonMode;
|
||||
import io.xpipe.core.util.XPipeInstallation;
|
||||
|
||||
import javafx.application.Platform;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -97,7 +99,9 @@ public abstract class OperationMode {
|
|||
Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> {
|
||||
// It seems like a few exceptions are thrown in the quantum renderer
|
||||
// when in shutdown. We can ignore these
|
||||
if (OperationMode.isInShutdown() && Platform.isFxApplicationThread() && ex instanceof NullPointerException) {
|
||||
if (OperationMode.isInShutdown()
|
||||
&& Platform.isFxApplicationThread()
|
||||
&& ex instanceof NullPointerException) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import io.xpipe.app.prefs.AppPrefs;
|
|||
import io.xpipe.app.update.UpdateAvailableAlert;
|
||||
import io.xpipe.app.util.PlatformState;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
||||
import javafx.application.Application;
|
||||
|
||||
public abstract class PlatformMode extends OperationMode {
|
||||
|
|
|
@ -11,6 +11,7 @@ import io.xpipe.app.prefs.AppPrefs;
|
|||
import io.xpipe.app.prefs.CloseBehaviourAlert;
|
||||
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;
|
||||
|
@ -21,17 +22,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 {
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import io.xpipe.app.prefs.AppPrefs;
|
|||
import io.xpipe.app.util.InputHelper;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
import io.xpipe.core.process.OsType;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.css.PseudoClass;
|
||||
|
@ -25,7 +26,6 @@ import javafx.scene.paint.Color;
|
|||
import javafx.scene.text.Text;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.StageStyle;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.xpipe.app.core.window;
|
|||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.core.process.OsType;
|
||||
|
||||
import javafx.animation.PauseTransition;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.ListChangeListener;
|
||||
|
@ -12,6 +13,7 @@ import javafx.stage.Stage;
|
|||
import javafx.stage.StageStyle;
|
||||
import javafx.stage.Window;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
public class ModifiedStage extends Stage {
|
||||
|
@ -55,8 +57,10 @@ public class ModifiedStage extends Stage {
|
|||
return;
|
||||
}
|
||||
|
||||
var applyToStage = (OsType.getLocal() == OsType.WINDOWS) ||
|
||||
(OsType.getLocal() == OsType.MACOS && AppMainWindow.getInstance() != null && AppMainWindow.getInstance().getStage() == stage);
|
||||
var applyToStage = (OsType.getLocal() == OsType.WINDOWS)
|
||||
|| (OsType.getLocal() == OsType.MACOS
|
||||
&& AppMainWindow.getInstance() != null
|
||||
&& AppMainWindow.getInstance().getStage() == stage);
|
||||
if (!applyToStage || AppPrefs.get() == null || AppPrefs.get().theme.getValue() == null) {
|
||||
stage.getScene().getRoot().pseudoClassStateChanged(PseudoClass.getPseudoClass("seamless-frame"), false);
|
||||
stage.getScene().getRoot().pseudoClassStateChanged(PseudoClass.getPseudoClass("separate-frame"), true);
|
||||
|
@ -64,14 +68,19 @@ public class ModifiedStage extends Stage {
|
|||
}
|
||||
|
||||
switch (OsType.getLocal()) {
|
||||
case OsType.Linux linux -> {
|
||||
}
|
||||
case OsType.Linux linux -> {}
|
||||
case OsType.MacOs macOs -> {
|
||||
var ctrl = new NativeMacOsWindowControl(stage);
|
||||
var seamlessFrame = !AppPrefs.get().performanceMode().get() && mergeFrame();
|
||||
var seamlessFrameApplied = ctrl.setAppearance(seamlessFrame, AppPrefs.get().theme.getValue().isDark()) && seamlessFrame;
|
||||
stage.getScene().getRoot().pseudoClassStateChanged(PseudoClass.getPseudoClass("seamless-frame"), seamlessFrameApplied);
|
||||
stage.getScene().getRoot().pseudoClassStateChanged(PseudoClass.getPseudoClass("separate-frame"), !seamlessFrameApplied);
|
||||
var seamlessFrameApplied = ctrl.setAppearance(
|
||||
seamlessFrame, AppPrefs.get().theme.getValue().isDark())
|
||||
&& seamlessFrame;
|
||||
stage.getScene()
|
||||
.getRoot()
|
||||
.pseudoClassStateChanged(PseudoClass.getPseudoClass("seamless-frame"), seamlessFrameApplied);
|
||||
stage.getScene()
|
||||
.getRoot()
|
||||
.pseudoClassStateChanged(PseudoClass.getPseudoClass("separate-frame"), !seamlessFrameApplied);
|
||||
}
|
||||
case OsType.Windows windows -> {
|
||||
var ctrl = new NativeWinWindowControl(stage);
|
||||
|
@ -84,8 +93,12 @@ public class ModifiedStage extends Stage {
|
|||
} else {
|
||||
seamlessFrame = ctrl.setWindowBackdrop(NativeWinWindowControl.DwmSystemBackDropType.MICA_ALT);
|
||||
}
|
||||
stage.getScene().getRoot().pseudoClassStateChanged(PseudoClass.getPseudoClass("seamless-frame"), seamlessFrame);
|
||||
stage.getScene().getRoot().pseudoClassStateChanged(PseudoClass.getPseudoClass("separate-frame"), !seamlessFrame);
|
||||
stage.getScene()
|
||||
.getRoot()
|
||||
.pseudoClassStateChanged(PseudoClass.getPseudoClass("seamless-frame"), seamlessFrame);
|
||||
stage.getScene()
|
||||
.getRoot()
|
||||
.pseudoClassStateChanged(PseudoClass.getPseudoClass("separate-frame"), !seamlessFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package io.xpipe.app.core.window;
|
||||
|
||||
import com.sun.jna.NativeLong;
|
||||
import io.xpipe.app.core.AppProperties;
|
||||
import io.xpipe.app.util.NativeBridge;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
import io.xpipe.core.util.ModuleHelper;
|
||||
|
||||
import javafx.stage.Window;
|
||||
|
||||
import com.sun.jna.NativeLong;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
|
|
|
@ -145,9 +145,16 @@ public interface ActionProvider {
|
|||
.map(actionProviderProvider -> actionProviderProvider.get())
|
||||
.toList());
|
||||
|
||||
var menuProviders = ALL.stream().map(actionProvider -> actionProvider.getBranchDataStoreCallSite() != null ?
|
||||
actionProvider.getBranchDataStoreCallSite().getChildren() : List.of()).flatMap(List::stream).toList();
|
||||
ALL_STANDALONE.addAll(ALL.stream().filter(actionProvider -> menuProviders.stream().noneMatch(menuItem -> menuItem.getClass().equals(actionProvider.getClass()))).toList());
|
||||
var menuProviders = ALL.stream()
|
||||
.map(actionProvider -> actionProvider.getBranchDataStoreCallSite() != null
|
||||
? actionProvider.getBranchDataStoreCallSite().getChildren()
|
||||
: List.of())
|
||||
.flatMap(List::stream)
|
||||
.toList();
|
||||
ALL_STANDALONE.addAll(ALL.stream()
|
||||
.filter(actionProvider -> menuProviders.stream()
|
||||
.noneMatch(menuItem -> menuItem.getClass().equals(actionProvider.getClass())))
|
||||
.toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import io.xpipe.app.issue.ErrorEvent;
|
|||
import io.xpipe.app.storage.DataStoreEntry;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import io.xpipe.core.util.JacksonizedValue;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.Property;
|
||||
|
|
|
@ -68,7 +68,10 @@ public class DataStoreProviders {
|
|||
throw new IllegalStateException("Not initialized");
|
||||
}
|
||||
|
||||
return (T) ALL.stream().filter(d -> d.getStoreClasses().contains(store.getClass())).findAny().orElseThrow(() -> new IllegalArgumentException("Unknown store class"));
|
||||
return (T) ALL.stream()
|
||||
.filter(d -> d.getStoreClasses().contains(store.getClass()))
|
||||
.findAny()
|
||||
.orElseThrow(() -> new IllegalArgumentException("Unknown store class"));
|
||||
}
|
||||
|
||||
public static List<DataStoreProvider> getAll() {
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.xpipe.app.fxcomps.impl;
|
|||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.CompStructure;
|
||||
import io.xpipe.app.fxcomps.SimpleCompStructure;
|
||||
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
|
||||
import java.util.List;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package io.xpipe.app.fxcomps.impl;
|
||||
|
||||
import atlantafx.base.controls.Popover;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import io.xpipe.app.comp.base.ButtonComp;
|
||||
import io.xpipe.app.comp.store.*;
|
||||
import io.xpipe.app.core.AppFont;
|
||||
|
@ -15,6 +13,7 @@ import io.xpipe.app.util.DataStoreCategoryChoiceComp;
|
|||
import io.xpipe.core.store.DataStore;
|
||||
import io.xpipe.core.store.LocalStore;
|
||||
import io.xpipe.core.store.ShellStore;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
|
@ -26,6 +25,9 @@ import javafx.scene.control.MenuButton;
|
|||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import atlantafx.base.controls.Popover;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
package io.xpipe.app.fxcomps.impl;
|
||||
|
||||
import atlantafx.base.controls.CustomTextField;
|
||||
import io.xpipe.app.core.AppActionLinkDetector;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.CompStructure;
|
||||
import io.xpipe.app.fxcomps.SimpleCompStructure;
|
||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.input.MouseButton;
|
||||
|
||||
import atlantafx.base.controls.CustomTextField;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
import java.util.Objects;
|
||||
|
@ -39,9 +41,16 @@ public class FilterComp extends Comp<CompStructure<CustomTextField>> {
|
|||
filter.setMaxHeight(2000);
|
||||
filter.getStyleClass().add("filter-comp");
|
||||
filter.promptTextProperty().bind(AppI18n.observable("searchFilter"));
|
||||
filter.rightProperty().bind(Bindings.createObjectBinding(() -> {
|
||||
return filter.isFocused() || (filter.getText() != null && !filter.getText().isEmpty()) ? clear : fi;
|
||||
}, filter.focusedProperty()));
|
||||
filter.rightProperty()
|
||||
.bind(Bindings.createObjectBinding(
|
||||
() -> {
|
||||
return filter.isFocused()
|
||||
|| (filter.getText() != null
|
||||
&& !filter.getText().isEmpty())
|
||||
? clear
|
||||
: fi;
|
||||
},
|
||||
filter.focusedProperty()));
|
||||
filter.setAccessibleText("Filter");
|
||||
|
||||
filterText.subscribe(val -> {
|
||||
|
|
|
@ -2,7 +2,9 @@ package io.xpipe.app.fxcomps.util;
|
|||
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
|
||||
|
||||
import javafx.scene.Node;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
@ -33,7 +35,6 @@ public abstract class LabelGraphic {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Value
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public static class ImageGraphic extends LabelGraphic {
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.xpipe.app.fxcomps.util;
|
|||
import io.xpipe.app.core.mode.OperationMode;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.util.PlatformState;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.InvalidationListener;
|
||||
import javafx.beans.Observable;
|
||||
|
@ -11,6 +12,7 @@ import javafx.beans.value.ChangeListener;
|
|||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.util.*;
|
||||
|
|
|
@ -98,9 +98,11 @@ public class LauncherCommand implements Callable<Integer> {
|
|||
}
|
||||
} catch (Exception ex) {
|
||||
var cli = XPipeInstallation.getLocalDefaultCliExecutable();
|
||||
ErrorEvent.fromThrowable("Unable to connect to existing running daemon instance as it did not respond."
|
||||
+ " Either try to kill the process xpiped manually or use the command \"" + cli
|
||||
+ "\" daemon stop --force.", ex)
|
||||
ErrorEvent.fromThrowable(
|
||||
"Unable to connect to existing running daemon instance as it did not respond."
|
||||
+ " Either try to kill the process xpiped manually or use the command \"" + cli
|
||||
+ "\" daemon stop --force.",
|
||||
ex)
|
||||
.term()
|
||||
.expected()
|
||||
.handle();
|
||||
|
@ -127,9 +129,8 @@ public class LauncherCommand implements Callable<Integer> {
|
|||
// there might be another instance running, for example
|
||||
// starting up or listening on another port
|
||||
if (!AppDataLock.lock()) {
|
||||
TrackEvent.info(
|
||||
"Data directory " + AppProperties.get().getDataDir().toString()
|
||||
+ " is already locked. Is another instance running?");
|
||||
TrackEvent.info("Data directory " + AppProperties.get().getDataDir().toString()
|
||||
+ " is already locked. Is another instance running?");
|
||||
OperationMode.halt(1);
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,8 @@ public interface ExternalEditorType extends PrefsChoiceValue {
|
|||
List.of(VSCODIUM_WINDOWS, VSCODE_INSIDERS_WINDOWS, VSCODE_WINDOWS, NOTEPADPLUSPLUS, NOTEPAD);
|
||||
List<LinuxPathType> LINUX_EDITORS =
|
||||
List.of(VSCODIUM_LINUX, VSCODE_LINUX, ZED_LINUX, KATE, GEDIT, PLUMA, LEAFPAD, MOUSEPAD, GNOME);
|
||||
List<ExternalEditorType> MACOS_EDITORS = List.of(BBEDIT, VSCODIUM_MACOS, VSCODE_MACOS, SUBLIME_MACOS, ZED_MACOS, TEXT_EDIT);
|
||||
List<ExternalEditorType> MACOS_EDITORS =
|
||||
List.of(BBEDIT, VSCODIUM_MACOS, VSCODE_MACOS, SUBLIME_MACOS, ZED_MACOS, TEXT_EDIT);
|
||||
List<ExternalEditorType> CROSS_PLATFORM_EDITORS = List.of(FLEET, INTELLIJ, PYCHARM, WEBSTORM, CLION);
|
||||
|
||||
@SuppressWarnings("TrivialFunctionalExpressionUsage")
|
||||
|
|
|
@ -22,9 +22,13 @@ public class SyncCategory extends AppPrefsCategory {
|
|||
.sub(new OptionsBuilder()
|
||||
.name("enableGitStorage")
|
||||
.description(
|
||||
AppProperties.get().isStaging() && !prefs.developerMode().getValue() ? "enableGitStoragePtbDisabled" : "enableGitStorageDescription")
|
||||
AppProperties.get().isStaging()
|
||||
&& !prefs.developerMode().getValue()
|
||||
? "enableGitStoragePtbDisabled"
|
||||
: "enableGitStorageDescription")
|
||||
.addToggle(prefs.enableGitStorage)
|
||||
.disable(AppProperties.get().isStaging() && !prefs.developerMode().getValue())
|
||||
.disable(AppProperties.get().isStaging()
|
||||
&& !prefs.developerMode().getValue())
|
||||
.nameAndDescription("storageGitRemote")
|
||||
.addString(prefs.storageGitRemote, true)
|
||||
.disable(prefs.enableGitStorage.not())
|
||||
|
|
|
@ -10,7 +10,9 @@ import io.xpipe.core.store.FixedChildStore;
|
|||
import io.xpipe.core.store.LocalStore;
|
||||
import io.xpipe.core.store.StorePath;
|
||||
import io.xpipe.core.util.UuidHelper;
|
||||
|
||||
import javafx.util.Pair;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
|
@ -339,7 +341,7 @@ public abstract class DataStorage {
|
|||
|
||||
@SneakyThrows
|
||||
public boolean refreshChildren(DataStoreEntry e) {
|
||||
return refreshChildren(e,false);
|
||||
return refreshChildren(e, false);
|
||||
}
|
||||
|
||||
public boolean refreshChildren(DataStoreEntry e, boolean throwOnFail) throws Exception {
|
||||
|
@ -350,7 +352,9 @@ public abstract class DataStorage {
|
|||
e.incrementBusyCounter();
|
||||
List<? extends DataStoreEntryRef<? extends FixedChildStore>> newChildren;
|
||||
try {
|
||||
newChildren = h.listChildren(e).stream().filter(dataStoreEntryRef -> dataStoreEntryRef != null && dataStoreEntryRef.get() != null).toList();
|
||||
newChildren = h.listChildren(e).stream()
|
||||
.filter(dataStoreEntryRef -> dataStoreEntryRef != null && dataStoreEntryRef.get() != null)
|
||||
.toList();
|
||||
} catch (Exception ex) {
|
||||
if (throwOnFail) {
|
||||
throw ex;
|
||||
|
|
|
@ -101,9 +101,7 @@ public class DataStoreEntry extends StorageElement {
|
|||
this.expanded = expanded;
|
||||
this.color = color;
|
||||
this.explicitOrder = explicitOrder;
|
||||
this.provider = store != null
|
||||
? DataStoreProviders.byStore(store)
|
||||
: null;
|
||||
this.provider = store != null ? DataStoreProviders.byStore(store) : null;
|
||||
this.storePersistentStateNode = storePersistentState;
|
||||
this.notes = notes;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package io.xpipe.app.storage;
|
||||
|
||||
import com.fasterxml.jackson.core.JacksonException;
|
||||
import io.xpipe.app.ext.DataStorageExtensionProvider;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.store.LocalStore;
|
||||
|
||||
import io.xpipe.core.util.JacksonMapper;
|
||||
|
||||
import com.fasterxml.jackson.core.JacksonException;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
|
@ -53,19 +53,27 @@ public class StandardStorage extends DataStorage {
|
|||
try {
|
||||
FileUtils.forceMkdir(dir.toFile());
|
||||
} catch (Exception e) {
|
||||
ErrorEvent.fromThrowable("Unable to create vault directory", e).terminal(true).build().handle();
|
||||
ErrorEvent.fromThrowable("Unable to create vault directory", e)
|
||||
.terminal(true)
|
||||
.build()
|
||||
.handle();
|
||||
}
|
||||
|
||||
try {
|
||||
initSystemInfo();
|
||||
} catch (Exception e) {
|
||||
ErrorEvent.fromThrowable("Unable to load vault system info", e).build().handle();
|
||||
ErrorEvent.fromThrowable("Unable to load vault system info", e)
|
||||
.build()
|
||||
.handle();
|
||||
}
|
||||
|
||||
try {
|
||||
initVaultKey();
|
||||
} catch (Exception e) {
|
||||
ErrorEvent.fromThrowable("Unable to load vault key file", e).terminal(true).build().handle();
|
||||
ErrorEvent.fromThrowable("Unable to load vault key file", e)
|
||||
.terminal(true)
|
||||
.build()
|
||||
.handle();
|
||||
}
|
||||
|
||||
var storesDir = getStoresDir();
|
||||
|
@ -76,7 +84,10 @@ public class StandardStorage extends DataStorage {
|
|||
FileUtils.forceMkdir(categoriesDir.toFile());
|
||||
FileUtils.forceMkdir(dataDir.toFile());
|
||||
} catch (Exception e) {
|
||||
ErrorEvent.fromThrowable("Unable to create vault directory", e).terminal(true).build().handle();
|
||||
ErrorEvent.fromThrowable("Unable to create vault directory", e)
|
||||
.terminal(true)
|
||||
.build()
|
||||
.handle();
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package io.xpipe.app.update;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import io.xpipe.app.core.AppLogs;
|
||||
import io.xpipe.app.core.AppProperties;
|
||||
import io.xpipe.app.core.mode.OperationMode;
|
||||
|
@ -17,6 +14,10 @@ import io.xpipe.core.store.FileNames;
|
|||
import io.xpipe.core.store.LocalStore;
|
||||
import io.xpipe.core.util.FailableRunnable;
|
||||
import io.xpipe.core.util.XPipeInstallation;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.nio.file.Files;
|
||||
|
@ -85,7 +86,8 @@ public class AppInstaller {
|
|||
.toString();
|
||||
var logsDir =
|
||||
AppLogs.get().getSessionLogsDirectory().getParent().toString();
|
||||
var logFile = FileNames.join(logsDir, "installer_" + file.getFileName().toString() + ".log");
|
||||
var logFile = FileNames.join(
|
||||
logsDir, "installer_" + file.getFileName().toString() + ".log");
|
||||
var command = LocalShell.getShell().getShellDialect().equals(ShellDialects.CMD)
|
||||
? getCmdCommand(file.toString(), logFile, exec)
|
||||
: getPowershellCommand(file.toString(), logFile, exec);
|
||||
|
@ -138,7 +140,9 @@ public class AppInstaller {
|
|||
|
||||
@Override
|
||||
public void installLocal(Path file) throws Exception {
|
||||
var start = AppPrefs.get() != null && AppPrefs.get().terminalType().getValue() != null && AppPrefs.get().terminalType().getValue().isAvailable();
|
||||
var start = AppPrefs.get() != null
|
||||
&& AppPrefs.get().terminalType().getValue() != null
|
||||
&& AppPrefs.get().terminalType().getValue().isAvailable();
|
||||
if (!start) {
|
||||
return;
|
||||
}
|
||||
|
@ -174,7 +178,9 @@ public class AppInstaller {
|
|||
|
||||
@Override
|
||||
public void installLocal(Path file) throws Exception {
|
||||
var start = AppPrefs.get() != null && AppPrefs.get().terminalType().getValue() != null && AppPrefs.get().terminalType().getValue().isAvailable();
|
||||
var start = AppPrefs.get() != null
|
||||
&& AppPrefs.get().terminalType().getValue() != null
|
||||
&& AppPrefs.get().terminalType().getValue().isAvailable();
|
||||
if (!start) {
|
||||
return;
|
||||
}
|
||||
|
@ -210,7 +216,9 @@ public class AppInstaller {
|
|||
|
||||
@Override
|
||||
public void installLocal(Path file) throws Exception {
|
||||
var start = AppPrefs.get() != null && AppPrefs.get().terminalType().getValue() != null && AppPrefs.get().terminalType().getValue().isAvailable();
|
||||
var start = AppPrefs.get() != null
|
||||
&& AppPrefs.get().terminalType().getValue() != null
|
||||
&& AppPrefs.get().terminalType().getValue().isAvailable();
|
||||
if (!start) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ package io.xpipe.app.update;
|
|||
import io.xpipe.app.core.AppCache;
|
||||
import io.xpipe.app.core.AppProperties;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
import org.kohsuke.github.GHRelease;
|
||||
|
||||
import java.nio.file.Files;
|
||||
|
|
|
@ -7,11 +7,13 @@ import io.xpipe.app.issue.TrackEvent;
|
|||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.util.BooleanScope;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Value;
|
||||
|
@ -70,7 +72,9 @@ public abstract class UpdateHandler {
|
|||
}
|
||||
|
||||
// Check if file has been deleted
|
||||
if (preparedUpdate.getValue() != null && preparedUpdate.getValue().getFile() != null && !Files.exists(preparedUpdate.getValue().getFile())) {
|
||||
if (preparedUpdate.getValue() != null
|
||||
&& preparedUpdate.getValue().getFile() != null
|
||||
&& !Files.exists(preparedUpdate.getValue().getFile())) {
|
||||
preparedUpdate.setValue(null);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.xpipe.app.util;
|
||||
|
||||
import io.xpipe.app.fxcomps.util.LabelGraphic;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Side;
|
||||
import javafx.scene.Node;
|
||||
|
|
|
@ -5,6 +5,7 @@ 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 javafx.beans.value.ObservableValue;
|
||||
|
||||
public class DataStoreFormatter {
|
||||
|
|
|
@ -31,9 +31,11 @@ public class DesktopHelper {
|
|||
public static Path getDownloadsDirectory() throws Exception {
|
||||
if (OsType.getLocal() == OsType.WINDOWS) {
|
||||
return Path.of(LocalShell.getLocalPowershell()
|
||||
.executeSimpleStringCommand("(New-Object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path"));
|
||||
.executeSimpleStringCommand(
|
||||
"(New-Object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path"));
|
||||
} else if (OsType.getLocal() == OsType.LINUX) {
|
||||
try (var cmd = LocalShell.getShell().command("xdg-user-dir DOWNLOAD").start()) {
|
||||
try (var cmd =
|
||||
LocalShell.getShell().command("xdg-user-dir DOWNLOAD").start()) {
|
||||
var read = cmd.readStdoutDiscardErr();
|
||||
var exit = cmd.getExitCode();
|
||||
if (exit == 0) {
|
||||
|
|
|
@ -249,9 +249,12 @@ public class FileBridge {
|
|||
var newDate = getLastModified();
|
||||
// The size check is intended for cases in which editors first clear a file prior to writing it
|
||||
// In that case, multiple watch events are sent. If these happened very fast, it might be possible that
|
||||
// the modified time is the same for both write operations due to the file system modified time resolution being limited
|
||||
// We then can't identify changes purely based on the modified time, so the file size is the next best option
|
||||
// This might result in double change detection in rare cases, but that is irrelevant as it prevents files from being blanked
|
||||
// the modified time is the same for both write operations due to the file system modified time resolution
|
||||
// being limited
|
||||
// We then can't identify changes purely based on the modified time, so the file size is the next best
|
||||
// option
|
||||
// This might result in double change detection in rare cases, but that is irrelevant as it prevents files
|
||||
// from being blanked
|
||||
var changed = !newDate.equals(lastModified) || newSize > lastSize;
|
||||
lastSize = newSize;
|
||||
lastModified = newDate;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package io.xpipe.app.util;
|
||||
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.core.util.XPipeInstallation;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.NativeLong;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.core.util.XPipeInstallation;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
@ -17,8 +18,15 @@ public class NativeBridge {
|
|||
public static Optional<MacOsLibrary> getMacOsLibrary() {
|
||||
if (macOsLibrary == null && !loadingFailed) {
|
||||
try {
|
||||
System.setProperty("jna.library.path", XPipeInstallation.getCurrentInstallationBasePath()
|
||||
.resolve("Contents").resolve("runtime").resolve("Contents").resolve("Home").resolve("lib").toString());
|
||||
System.setProperty(
|
||||
"jna.library.path",
|
||||
XPipeInstallation.getCurrentInstallationBasePath()
|
||||
.resolve("Contents")
|
||||
.resolve("runtime")
|
||||
.resolve("Contents")
|
||||
.resolve("Home")
|
||||
.resolve("lib")
|
||||
.toString());
|
||||
var l = Native.load("xpipe_bridge", MacOsLibrary.class, Map.of());
|
||||
macOsLibrary = l;
|
||||
} catch (Throwable t) {
|
||||
|
|
|
@ -6,7 +6,9 @@ import io.xpipe.app.issue.ErrorEvent;
|
|||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.core.process.OsType;
|
||||
|
||||
import javafx.application.Platform;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
@ -121,7 +123,8 @@ public enum PlatformState {
|
|||
}
|
||||
|
||||
if (SystemUtils.IS_OS_WINDOWS && ModifiedStage.mergeFrame()) {
|
||||
// This is primarily intended to fix Windows unified stage transparency issues (https://bugs.openjdk.org/browse/JDK-8329382)
|
||||
// This is primarily intended to fix Windows unified stage transparency issues
|
||||
// (https://bugs.openjdk.org/browse/JDK-8329382)
|
||||
System.setProperty("prism.forceUploadingPainter", "true");
|
||||
}
|
||||
|
||||
|
@ -152,7 +155,7 @@ public enum PlatformState {
|
|||
// Platform initialization has failed in this case
|
||||
PlatformState.setCurrent(PlatformState.EXITED);
|
||||
TrackEvent.error(t.getMessage());
|
||||
lastError =t;
|
||||
lastError = t;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.xpipe.beacon.api;
|
|||
|
||||
import io.xpipe.beacon.BeaconInterface;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.xpipe.beacon.api;
|
||||
|
||||
import io.xpipe.beacon.BeaconInterface;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.xpipe.beacon.api;
|
||||
|
||||
import io.xpipe.beacon.BeaconInterface;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.xpipe.beacon.api;
|
||||
|
||||
import io.xpipe.beacon.BeaconInterface;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.xpipe.beacon.api;
|
||||
|
||||
import io.xpipe.beacon.BeaconInterface;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.xpipe.beacon.api;
|
||||
|
||||
import io.xpipe.beacon.BeaconInterface;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
|
|
@ -26,12 +26,16 @@ public class DaemonVersionExchange extends BeaconInterface<DaemonVersionExchange
|
|||
|
||||
@NonNull
|
||||
String version;
|
||||
|
||||
@NonNull
|
||||
String canonicalVersion;
|
||||
|
||||
@NonNull
|
||||
String buildVersion;
|
||||
|
||||
@NonNull
|
||||
String jvmVersion;
|
||||
|
||||
@NonNull
|
||||
Boolean pro;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package io.xpipe.core.store;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.xpipe.core.process.CommandBuilder;
|
||||
import io.xpipe.core.process.ShellControl;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
|
|
@ -60,7 +60,8 @@ public interface NetworkTunnelStore extends DataStore {
|
|||
|
||||
default NetworkTunnelSession sessionChain(int local, int remotePort) throws Exception {
|
||||
if (!isLocallyTunneable()) {
|
||||
throw new IllegalStateException("Unable to create tunnel chain as one intermediate system does not support tunneling");
|
||||
throw new IllegalStateException(
|
||||
"Unable to create tunnel chain as one intermediate system does not support tunneling");
|
||||
}
|
||||
|
||||
var running = new AtomicBoolean();
|
||||
|
|
|
@ -1,13 +1,5 @@
|
|||
package io.xpipe.core.util;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.jsontype.NamedType;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import io.xpipe.core.dialog.BaseQueryElement;
|
||||
import io.xpipe.core.dialog.BusyElement;
|
||||
import io.xpipe.core.dialog.ChoiceElement;
|
||||
|
@ -19,6 +11,15 @@ import io.xpipe.core.store.FilePath;
|
|||
import io.xpipe.core.store.LocalStore;
|
||||
import io.xpipe.core.store.StorePath;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.jsontype.NamedType;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
|
|
|
@ -3,8 +3,8 @@ package io.xpipe.core.util;
|
|||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.Module;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
import com.fasterxml.jackson.databind.Module;
|
||||
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import lombok.Getter;
|
||||
|
@ -91,7 +91,6 @@ public class JacksonMapper {
|
|||
return INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
public static ObjectMapper getCensored() {
|
||||
if (!JacksonMapper.isInit()) {
|
||||
return BASE;
|
||||
|
@ -103,13 +102,18 @@ public class JacksonMapper {
|
|||
public void setupModule(SetupContext context) {
|
||||
addSerializer(SecretValue.class, new JsonSerializer<>() {
|
||||
@Override
|
||||
public void serialize(SecretValue value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
public void serialize(SecretValue value, JsonGenerator gen, SerializerProvider serializers)
|
||||
throws IOException {
|
||||
gen.writeString("<secret>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWithType(SecretValue value, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws
|
||||
IOException {
|
||||
public void serializeWithType(
|
||||
SecretValue value,
|
||||
JsonGenerator gen,
|
||||
SerializerProvider serializers,
|
||||
TypeSerializer typeSer)
|
||||
throws IOException {
|
||||
gen.writeString("<secret>");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -48,6 +48,7 @@ public class OpenFileDefaultAction implements LeafAction {
|
|||
|
||||
@Override
|
||||
public boolean isApplicable(OpenFileSystemModel model, List<BrowserEntry> entries) {
|
||||
return model.getFileList().getEditing().getValue() == null && entries.stream().allMatch(entry -> entry.getRawFileEntry().getKind() == FileKind.FILE);
|
||||
return model.getFileList().getEditing().getValue() == null
|
||||
&& entries.stream().allMatch(entry -> entry.getRawFileEntry().getKind() == FileKind.FILE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,8 @@ public class RunScriptAction implements BrowserAction, BranchAction {
|
|||
var content = e.getValue().assemble(sc);
|
||||
var script = ScriptHelper.createExecScript(sc, content);
|
||||
try {
|
||||
sc.executeSimpleCommand(sc.getShellDialect().runScriptCommand(sc, script.toString()) + " " + args);
|
||||
sc.executeSimpleCommand(
|
||||
sc.getShellDialect().runScriptCommand(sc, script.toString()) + " " + args);
|
||||
} catch (Exception ex) {
|
||||
throw ErrorEvent.expected(ex);
|
||||
}
|
||||
|
|
|
@ -78,7 +78,8 @@ public class ScriptGroupStoreProvider implements EnabledStoreProvider, DataStore
|
|||
|
||||
@Override
|
||||
public ObservableValue<String> informationString(StoreSection section) {
|
||||
ScriptGroupStore scriptStore = section.getWrapper().getEntry().getStore().asNeeded();
|
||||
ScriptGroupStore scriptStore =
|
||||
section.getWrapper().getEntry().getStore().asNeeded();
|
||||
return new SimpleStringProperty(scriptStore.getDescription());
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,8 @@ public abstract class ScriptStore extends JacksonizedValue implements DataStore,
|
|||
}
|
||||
return pc;
|
||||
} catch (StackOverflowError t) {
|
||||
throw ErrorEvent.expected(new RuntimeException("Unable to set up scripts. Is there a circular script dependency?", t));
|
||||
throw ErrorEvent.expected(
|
||||
new RuntimeException("Unable to set up scripts. Is there a circular script dependency?", t));
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Unable to set up scripts", t);
|
||||
}
|
||||
|
|
|
@ -208,7 +208,8 @@ public class SimpleScriptStoreProvider implements EnabledParentStoreProvider, Da
|
|||
|
||||
@Override
|
||||
public ObservableValue<String> informationString(StoreSection section) {
|
||||
SimpleScriptStore scriptStore = section.getWrapper().getEntry().getStore().asNeeded();
|
||||
SimpleScriptStore scriptStore =
|
||||
section.getWrapper().getEntry().getStore().asNeeded();
|
||||
return new SimpleStringProperty((scriptStore.getMinimumDialect() != null
|
||||
? scriptStore.getMinimumDialect().getDisplayName() + " "
|
||||
: "")
|
||||
|
|
|
@ -67,16 +67,22 @@ public abstract class AbstractServiceGroupStoreProvider implements DataStoreProv
|
|||
|
||||
@Override
|
||||
public ObservableValue<String> informationString(StoreSection section) {
|
||||
return Bindings.createStringBinding(() -> {
|
||||
var all = section.getAllChildren().getList();
|
||||
var shown = section.getShownChildren().getList();
|
||||
if (shown.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return Bindings.createStringBinding(
|
||||
() -> {
|
||||
var all = section.getAllChildren().getList();
|
||||
var shown = section.getShownChildren().getList();
|
||||
if (shown.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var string = all.size() == shown.size() ? all.size() : shown.size() + "/" + all.size();
|
||||
return all.size() > 0 ? (all.size() == 1 ? AppI18n.get("hasService", string) : AppI18n.get("hasServices", string)) : AppI18n.get("noServices");
|
||||
}, section.getShownChildren().getList(), section.getAllChildren().getList(), AppPrefs.get().language());
|
||||
var string = all.size() == shown.size() ? all.size() : shown.size() + "/" + all.size();
|
||||
return all.size() > 0
|
||||
? (all.size() == 1 ? AppI18n.get("hasService", string) : AppI18n.get("hasServices", string))
|
||||
: AppI18n.get("noServices");
|
||||
},
|
||||
section.getShownChildren().getList(),
|
||||
section.getAllChildren().getList(),
|
||||
AppPrefs.get().language());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,5 +22,4 @@ public class CustomServiceGroupStore extends AbstractServiceGroupStore<NetworkTu
|
|||
super.checkComplete();
|
||||
Validators.isType(getParent(), NetworkTunnelStore.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package io.xpipe.ext.base.service;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import io.xpipe.app.storage.DataStoreEntry;
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
import io.xpipe.app.util.FixedHierarchyStore;
|
||||
import io.xpipe.app.util.Validators;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import io.xpipe.core.store.FixedChildStore;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
@ -26,7 +27,7 @@ public class FixedServiceGroupStore extends AbstractServiceGroupStore<FixedServi
|
|||
@Override
|
||||
public void checkComplete() throws Throwable {
|
||||
super.checkComplete();
|
||||
Validators.isType(getParent(),FixedServiceCreatorStore.class);
|
||||
Validators.isType(getParent(), FixedServiceCreatorStore.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.xpipe.ext.base.service;
|
|||
import io.xpipe.app.comp.store.StoreSection;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.storage.DataStoreEntry;
|
||||
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import io.xpipe.app.core.AppI18n;
|
|||
import io.xpipe.app.ext.ActionProvider;
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
|
||||
import javafx.beans.value.ObservableValue;
|
||||
|
||||
import java.util.List;
|
||||
|
|
|
@ -4,7 +4,9 @@ import io.xpipe.app.core.AppI18n;
|
|||
import io.xpipe.app.ext.ActionProvider;
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
|
||||
import javafx.beans.value.ObservableValue;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
public class ServiceOpenHttpAction implements ActionProvider {
|
||||
|
@ -44,7 +46,7 @@ public class ServiceOpenHttpAction implements ActionProvider {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Value
|
||||
static class Action implements ActionProvider.Action {
|
||||
|
||||
|
|
|
@ -4,7 +4,9 @@ import io.xpipe.app.core.AppI18n;
|
|||
import io.xpipe.app.ext.ActionProvider;
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
|
||||
import javafx.beans.value.ObservableValue;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
public class ServiceOpenHttpsAction implements ActionProvider {
|
||||
|
@ -44,7 +46,7 @@ public class ServiceOpenHttpsAction implements ActionProvider {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Value
|
||||
static class Action implements ActionProvider.Action {
|
||||
|
||||
|
|
|
@ -62,7 +62,10 @@ open module io.xpipe.ext.base {
|
|||
UnzipAction,
|
||||
JavapAction,
|
||||
JarAction;
|
||||
provides ActionProvider with StoreStopAction, StoreStartAction, StorePauseAction,
|
||||
provides ActionProvider with
|
||||
StoreStopAction,
|
||||
StoreStartAction,
|
||||
StorePauseAction,
|
||||
ServiceOpenAction,
|
||||
ServiceOpenHttpAction,
|
||||
ServiceOpenHttpsAction,
|
||||
|
|
Loading…
Reference in a new issue