mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-08-26 11:16:29 +00:00
Cleanup
This commit is contained in:
@@ -1,19 +1,17 @@
|
||||
package io.xpipe.app.action;
|
||||
|
||||
import io.xpipe.app.browser.action.BrowserAction;
|
||||
import io.xpipe.app.browser.action.BrowserActionProvider;
|
||||
import io.xpipe.app.ext.DataStore;
|
||||
import io.xpipe.app.hub.action.*;
|
||||
import io.xpipe.app.issue.ErrorEventFactory;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.core.JacksonMapper;
|
||||
import io.xpipe.core.UuidHelper;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.xpipe.core.UuidHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -98,14 +96,18 @@ public class ActionJacksonMapper {
|
||||
"Store " + DataStorage.get().getStorePath(entry.get()) + " is incomplete"));
|
||||
}
|
||||
|
||||
if (provider instanceof HubLeafProvider<?> l &&
|
||||
(!l.getApplicableClass().isAssignableFrom(entry.get().getStore().getClass()) || !l.isApplicable(entry.get().ref()))) {
|
||||
if (provider instanceof HubLeafProvider<?> l
|
||||
&& (!l.getApplicableClass()
|
||||
.isAssignableFrom(entry.get().getStore().getClass())
|
||||
|| !l.isApplicable(entry.get().ref()))) {
|
||||
throw ErrorEventFactory.expected(new IllegalArgumentException(
|
||||
"Store " + DataStorage.get().getStorePath(entry.get()) + " is not applicable for action type"));
|
||||
}
|
||||
|
||||
if (provider instanceof BatchHubProvider<?> h &&
|
||||
(!h.getApplicableClass().isAssignableFrom(entry.get().getStore().getClass()) || !h.isApplicable(entry.get().ref()))) {
|
||||
if (provider instanceof BatchHubProvider<?> h
|
||||
&& (!h.getApplicableClass()
|
||||
.isAssignableFrom(entry.get().getStore().getClass())
|
||||
|| !h.isApplicable(entry.get().ref()))) {
|
||||
throw ErrorEventFactory.expected(new IllegalArgumentException(
|
||||
"Store " + DataStorage.get().getStorePath(entry.get()) + " is not applicable for action type"));
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package io.xpipe.app.action;
|
||||
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.core.InPlaceSecretValue;
|
||||
import io.xpipe.core.JacksonMapper;
|
||||
import io.xpipe.core.SecretValue;
|
||||
import io.xpipe.core.UuidHelper;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
@@ -50,7 +47,8 @@ public class ActionUrls {
|
||||
}
|
||||
|
||||
var json = sa.toNode();
|
||||
var parsed = JacksonMapper.getDefault().treeToValue(json, new TypeReference<LinkedHashMap<String, JsonNode>>() {});
|
||||
var parsed =
|
||||
JacksonMapper.getDefault().treeToValue(json, new TypeReference<LinkedHashMap<String, JsonNode>>() {});
|
||||
|
||||
Map<String, List<String>> requestParams = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, JsonNode> e : parsed.entrySet()) {
|
||||
|
||||
@@ -3,10 +3,10 @@ package io.xpipe.app.action;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.util.DataStoreFormatter;
|
||||
import io.xpipe.core.JacksonMapper;
|
||||
import io.xpipe.core.UuidHelper;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.xpipe.core.UuidHelper;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.util.*;
|
||||
@@ -54,15 +54,22 @@ public abstract class SerializableAction extends AbstractAction {
|
||||
}
|
||||
|
||||
var name = DataStoreFormatter.camelCaseToName(property.getKey());
|
||||
name = Arrays.stream(name.split(" ")).filter(s -> !s.equals("Store")).collect(Collectors.joining(" "));
|
||||
name = Arrays.stream(name.split(" "))
|
||||
.filter(s -> !s.equals("Store"))
|
||||
.collect(Collectors.joining(" "));
|
||||
|
||||
if (property.getValue().isTextual()) {
|
||||
var value = property.getValue().textValue();
|
||||
var uuid = UuidHelper.parse(value);
|
||||
if (uuid.isPresent()) {
|
||||
var refName = DataStorage.get().getStoreEntryIfPresent(uuid.get()).map(e -> e.getName()).or(() -> {
|
||||
return DataStorage.get().getStoreCategoryIfPresent(uuid.get()).map(c -> c.getName());
|
||||
});
|
||||
var refName = DataStorage.get()
|
||||
.getStoreEntryIfPresent(uuid.get())
|
||||
.map(e -> e.getName())
|
||||
.or(() -> {
|
||||
return DataStorage.get()
|
||||
.getStoreCategoryIfPresent(uuid.get())
|
||||
.map(c -> c.getName());
|
||||
});
|
||||
map.put(name, refName.orElse(value));
|
||||
} else {
|
||||
map.put(name, value);
|
||||
|
||||
@@ -25,7 +25,6 @@ import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableMap;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@@ -62,12 +62,11 @@ public abstract class BrowserAction extends StoreAction<FileSystemStore> {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void validateAutomatedAction() throws Exception {
|
||||
var bap = (BrowserActionProvider) getProvider();
|
||||
if (!bap.isApplicable(getModel(), getEntries())) {
|
||||
throw ErrorEventFactory.expected(new IllegalArgumentException(
|
||||
"Selection is not applicable for action type"));
|
||||
throw ErrorEventFactory.expected(
|
||||
new IllegalArgumentException("Selection is not applicable for action type"));
|
||||
}
|
||||
|
||||
if (files != null) {
|
||||
@@ -86,7 +85,8 @@ public abstract class BrowserAction extends StoreAction<FileSystemStore> {
|
||||
} else {
|
||||
var dir = files.getFirst();
|
||||
if (!model.getFileSystem().directoryExists(dir)) {
|
||||
throw ErrorEventFactory.expected(new IllegalArgumentException("File or directory does not exist: " + dir));
|
||||
throw ErrorEventFactory.expected(
|
||||
new IllegalArgumentException("File or directory does not exist: " + dir));
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ public class RunCommandInBrowserActionProvider implements BrowserActionProvider
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeImpl() throws Exception {
|
||||
public void executeImpl() {
|
||||
var builder = CommandBuilder.of().add(command);
|
||||
for (BrowserEntry entry : getEntries()) {
|
||||
builder.addFile(entry.getRawFileEntry().getPath());
|
||||
|
||||
@@ -169,7 +169,9 @@ class BrowserFileListNameCell extends TableCell<BrowserEntry, String> {
|
||||
var content = textField.getText();
|
||||
if (content != null && !content.isEmpty()) {
|
||||
var name = FilePath.of(content);
|
||||
var baseNameEnd = item.getRawFileEntry().getKind() == FileKind.DIRECTORY ? content.length() : name.getBaseName().toString().length();
|
||||
var baseNameEnd = item.getRawFileEntry().getKind() == FileKind.DIRECTORY
|
||||
? content.length()
|
||||
: name.getBaseName().toString().length();
|
||||
textField.selectRange(0, baseNameEnd);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -208,7 +208,7 @@ public class BrowserFileOpener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() throws Exception {
|
||||
public void onFinish() {
|
||||
model.refreshFileEntriesSync(List.of(entry));
|
||||
}
|
||||
};
|
||||
@@ -257,7 +257,7 @@ public class BrowserFileOpener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() throws Exception {
|
||||
public void onFinish() {
|
||||
model.refreshFileEntriesSync(List.of(entry));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -112,13 +112,7 @@ public class BrowserFileSystemTabComp extends SimpleComp {
|
||||
rightBox.setFillHeight(true);
|
||||
rightBox.getStyleClass().add("button-bar");
|
||||
|
||||
topBar.getChildren()
|
||||
.setAll(
|
||||
leftBox,
|
||||
new Spacer(6),
|
||||
navBar.get(),
|
||||
new Spacer(6),
|
||||
rightBox);
|
||||
topBar.getChildren().setAll(leftBox, new Spacer(6), navBar.get(), new Spacer(6), rightBox);
|
||||
topBar.setMinWidth(0);
|
||||
|
||||
if (model.getBrowserModel() instanceof BrowserFullSessionModel fullSessionModel) {
|
||||
|
||||
@@ -30,7 +30,6 @@ import javafx.beans.property.*;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
import javafx.scene.control.SelectionMode;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
|
||||
|
||||
@@ -165,7 +165,8 @@ public class BrowserFileTransferOperation {
|
||||
handleSingleOnSameFileSystem(file);
|
||||
} else {
|
||||
// Transfers might change the working directory
|
||||
var currentDir = file.getFileSystem().getShell().orElseThrow().view().pwd();
|
||||
var currentDir =
|
||||
file.getFileSystem().getShell().orElseThrow().view().pwd();
|
||||
handleSingleAcrossFileSystems(file);
|
||||
file.getFileSystem().getShell().orElseThrow().view().cd(currentDir);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.List;
|
||||
|
||||
public interface BrowserMenuLeafProvider extends BrowserMenuItemProvider {
|
||||
|
||||
default void execute(BrowserFileSystemTabModel model, List<BrowserEntry> entries) throws Exception {
|
||||
default void execute(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
|
||||
createAction(model, entries).executeAsync();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.process.CommandBuilder;
|
||||
import io.xpipe.app.process.ShellControl;
|
||||
import io.xpipe.app.util.CommandDialog;
|
||||
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
||||
import javafx.beans.value.ObservableValue;
|
||||
|
||||
import java.util.List;
|
||||
@@ -25,7 +25,7 @@ public abstract class MultiExecuteMenuProvider implements BrowserMenuBranchProvi
|
||||
new BrowserMenuLeafProvider() {
|
||||
|
||||
@Override
|
||||
public void execute(BrowserFileSystemTabModel model, List<BrowserEntry> entries) throws Exception {
|
||||
public void execute(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
|
||||
var sc = model.getFileSystem().getShell().orElseThrow();
|
||||
for (BrowserEntry entry : entries) {
|
||||
var c = createCommand(sc, model, entry);
|
||||
@@ -61,7 +61,7 @@ public abstract class MultiExecuteMenuProvider implements BrowserMenuBranchProvi
|
||||
new BrowserMenuLeafProvider() {
|
||||
|
||||
@Override
|
||||
public void execute(BrowserFileSystemTabModel model, List<BrowserEntry> entries) throws Exception {
|
||||
public void execute(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
|
||||
ThreadHelper.runAsync(() -> {
|
||||
var sc = model.getFileSystem().getShell().orElseThrow();
|
||||
for (BrowserEntry entry : entries) {
|
||||
@@ -86,7 +86,7 @@ public abstract class MultiExecuteMenuProvider implements BrowserMenuBranchProvi
|
||||
new BrowserMenuLeafProvider() {
|
||||
|
||||
@Override
|
||||
public void execute(BrowserFileSystemTabModel model, List<BrowserEntry> entries) throws Exception {
|
||||
public void execute(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
var sc = model.getFileSystem().getShell().orElseThrow();
|
||||
for (BrowserEntry entry : entries) {
|
||||
@@ -95,7 +95,10 @@ public abstract class MultiExecuteMenuProvider implements BrowserMenuBranchProvi
|
||||
continue;
|
||||
}
|
||||
|
||||
sc.command(cmd).withWorkingDirectory(model.getCurrentDirectory().getPath()).execute();
|
||||
sc.command(cmd)
|
||||
.withWorkingDirectory(
|
||||
model.getCurrentDirectory().getPath())
|
||||
.execute();
|
||||
}
|
||||
model.refreshBrowserEntriesSync(entries);
|
||||
});
|
||||
|
||||
@@ -5,8 +5,8 @@ import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
|
||||
import io.xpipe.app.browser.menu.BrowserMenuLeafProvider;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.util.LabelGraphic;
|
||||
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyCodeCombination;
|
||||
|
||||
@@ -5,8 +5,8 @@ import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
|
||||
import io.xpipe.app.browser.menu.BrowserMenuLeafProvider;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.util.LabelGraphic;
|
||||
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyCodeCombination;
|
||||
|
||||
@@ -10,8 +10,8 @@ import io.xpipe.app.browser.menu.FileTypeMenuProvider;
|
||||
import io.xpipe.app.process.CommandBuilder;
|
||||
import io.xpipe.app.process.ShellControl;
|
||||
import io.xpipe.app.util.FileOpener;
|
||||
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
|
||||
@@ -42,12 +42,16 @@ public class JavapMenuProvider
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(BrowserFileSystemTabModel model, List<BrowserEntry> entries) throws Exception {
|
||||
public void execute(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
ShellControl sc = model.getFileSystem().getShell().orElseThrow();
|
||||
for (BrowserEntry entry : entries) {
|
||||
var command = CommandBuilder.of().add("javap", "-c", "-p").addFile(entry.getRawFileEntry().getPath());
|
||||
var out = sc.command(command).withWorkingDirectory(model.getCurrentDirectory().getPath()).readStdoutOrThrow();
|
||||
var command = CommandBuilder.of()
|
||||
.add("javap", "-c", "-p")
|
||||
.addFile(entry.getRawFileEntry().getPath());
|
||||
var out = sc.command(command)
|
||||
.withWorkingDirectory(model.getCurrentDirectory().getPath())
|
||||
.readStdoutOrThrow();
|
||||
FileOpener.openReadOnlyString(out);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,8 +5,8 @@ import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
|
||||
import io.xpipe.app.browser.menu.BrowserMenuLeafProvider;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.util.LabelGraphic;
|
||||
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyCodeCombination;
|
||||
|
||||
@@ -45,9 +45,13 @@ public class AppLayoutComp extends Comp<AppLayoutComp.Structure> {
|
||||
multi.styleClass("background");
|
||||
|
||||
multi.apply(struc -> {
|
||||
struc.get().opacityProperty().bind(Bindings.createDoubleBinding(() -> {
|
||||
return AppPrefs.get().performanceMode().get() ? 1.0 : 0.95;
|
||||
}, AppPrefs.get().performanceMode()));
|
||||
struc.get()
|
||||
.opacityProperty()
|
||||
.bind(Bindings.createDoubleBinding(
|
||||
() -> {
|
||||
return AppPrefs.get().performanceMode().get() ? 1.0 : 0.95;
|
||||
},
|
||||
AppPrefs.get().performanceMode()));
|
||||
});
|
||||
|
||||
var pane = new BorderPane();
|
||||
|
||||
@@ -6,6 +6,7 @@ import io.xpipe.app.core.AppFontSizes;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppLogs;
|
||||
import io.xpipe.app.util.BooleanScope;
|
||||
import io.xpipe.app.util.LabelGraphic;
|
||||
import io.xpipe.app.util.PlatformThread;
|
||||
import io.xpipe.core.OsType;
|
||||
|
||||
@@ -17,7 +18,6 @@ import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.beans.value.ObservableDoubleValue;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.layout.HBox;
|
||||
@@ -182,12 +182,16 @@ public class ModalOverlayComp extends SimpleComp {
|
||||
content.setSpacing(20);
|
||||
|
||||
if (newValue.getTitle() != null) {
|
||||
var l = new Label(
|
||||
var l = new LabelComp(
|
||||
newValue.getTitle().getValue(),
|
||||
newValue.getGraphic() != null ? newValue.getGraphic().createGraphicNode() : null);
|
||||
l.setGraphicTextGap(8);
|
||||
AppFontSizes.xl(l);
|
||||
content.getChildren().addFirst(l);
|
||||
newValue.getGraphic() != null
|
||||
? newValue.getGraphic()
|
||||
: new LabelGraphic.IconGraphic("mdi2i-information-outline"));
|
||||
l.apply(struc -> {
|
||||
struc.get().setGraphicTextGap(8);
|
||||
AppFontSizes.xl(struc.get());
|
||||
});
|
||||
content.getChildren().addFirst(l.createRegion());
|
||||
} else {
|
||||
content.getChildren().addFirst(Comp.vspacer(0).createRegion());
|
||||
}
|
||||
|
||||
@@ -225,7 +225,6 @@ public class OptionsComp extends Comp<CompStructure<VBox>> {
|
||||
.map(Region::getWidth)
|
||||
.filter(aDouble -> aDouble > 0.0)
|
||||
.max(Double::compareTo)
|
||||
.map(d -> d)
|
||||
.orElse(Region.USE_COMPUTED_SIZE);
|
||||
},
|
||||
nameRegions.stream().map(Region::widthProperty).toList().toArray(new Observable[0]));
|
||||
|
||||
@@ -2,7 +2,6 @@ package io.xpipe.app.core;
|
||||
|
||||
import io.xpipe.app.issue.ErrorEventFactory;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.core.OsType;
|
||||
|
||||
import javafx.scene.text.Font;
|
||||
|
||||
|
||||
@@ -5,18 +5,15 @@ import io.xpipe.app.core.mode.OperationMode;
|
||||
import io.xpipe.app.issue.ErrorEventFactory;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
import io.xpipe.beacon.BeaconAuthMethod;
|
||||
import io.xpipe.beacon.BeaconClient;
|
||||
import io.xpipe.beacon.BeaconClientInformation;
|
||||
import io.xpipe.beacon.BeaconServer;
|
||||
import io.xpipe.beacon.api.DaemonFocusExchange;
|
||||
import io.xpipe.beacon.api.DaemonOpenExchange;
|
||||
import io.xpipe.beacon.api.HandshakeExchange;
|
||||
import io.xpipe.core.OsType;
|
||||
import io.xpipe.core.XPipeInstallation;
|
||||
|
||||
import java.awt.*;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -28,12 +25,14 @@ public class AppInstance {
|
||||
|
||||
public static Optional<BeaconClient> tryEstablishConnection(int port) {
|
||||
try {
|
||||
return Optional.of(BeaconClient.establishConnection(port, BeaconClientInformation.Daemon.builder().build()));
|
||||
return Optional.of(BeaconClient.establishConnection(
|
||||
port, BeaconClientInformation.Daemon.builder().build()));
|
||||
} catch (Exception ex) {
|
||||
ErrorEventFactory.fromThrowable(ex).omit().expected().handle();
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkStart(int attemptCounter) {
|
||||
var port = AppBeaconServer.get().getPort();
|
||||
var reachable = BeaconServer.isReachable(port);
|
||||
|
||||
@@ -65,7 +65,9 @@ public class AppTheme {
|
||||
|
||||
AppPrefs.get().theme().subscribe(t -> {
|
||||
Theme.ALL.forEach(theme -> {
|
||||
root.pseudoClassStateChanged(PseudoClass.getPseudoClass(theme.getCssId()), theme.getCssId().equals(t.getCssId()));
|
||||
root.pseudoClassStateChanged(
|
||||
PseudoClass.getPseudoClass(theme.getCssId()),
|
||||
theme.getCssId().equals(t.getCssId()));
|
||||
});
|
||||
if (t == null) {
|
||||
return;
|
||||
|
||||
@@ -31,12 +31,17 @@ public class AppGnomeScaleDialog {
|
||||
return;
|
||||
}
|
||||
|
||||
var content = AppDialog.dialogText("You are running XPipe on a Wayland system."
|
||||
+ " If you are using a high-dpi display, eue to xwayland limitations, this might result in a blurry window. See the documentation for workarounds if you are affected.");
|
||||
var content = AppDialog.dialogText(
|
||||
"You are running XPipe on a Wayland system."
|
||||
+ " If you are using a high-dpi display, eue to xwayland limitations, this might result in a blurry window. See the documentation for workarounds if you are affected.");
|
||||
var modal = ModalOverlay.of("waylandScalingTitle", content);
|
||||
modal.addButton(new ModalButton("docs", () -> {
|
||||
DocumentationLink.GNOME_WAYLAND_SCALING.open();
|
||||
}, false, false));
|
||||
modal.addButton(new ModalButton(
|
||||
"docs",
|
||||
() -> {
|
||||
DocumentationLink.GNOME_WAYLAND_SCALING.open();
|
||||
},
|
||||
false,
|
||||
false));
|
||||
modal.addButton(ModalButton.ok(() -> {
|
||||
AppCache.update("gnomeScaleNoticeShown", true);
|
||||
}));
|
||||
|
||||
@@ -44,7 +44,6 @@ public class DataStoreProviders {
|
||||
return ALL.stream().filter(d -> d.getId().equalsIgnoreCase(id)).findAny();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends DataStoreProvider> Optional<T> byStoreIfPresent(DataStore store) {
|
||||
if (ALL == null) {
|
||||
@@ -57,7 +56,8 @@ public class DataStoreProviders {
|
||||
}
|
||||
|
||||
public static <T extends DataStoreProvider> T byStore(DataStore store) {
|
||||
return DataStoreProviders.<T>byStoreIfPresent(store).orElseThrow(() -> new IllegalArgumentException("Unknown store class"));
|
||||
return DataStoreProviders.<T>byStoreIfPresent(store)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Unknown store class"));
|
||||
}
|
||||
|
||||
public static List<DataStoreProvider> getAll() {
|
||||
|
||||
@@ -29,7 +29,8 @@ public class ShellSession extends Session {
|
||||
shellControl.start();
|
||||
|
||||
var shouldAliveCheck = !shellControl.isLocal();
|
||||
var supportsAliveCheck = shellControl.getShellDialect().getDumbMode().supportsAnyPossibleInteraction();
|
||||
var supportsAliveCheck =
|
||||
shellControl.getShellDialect().getDumbMode().supportsAnyPossibleInteraction();
|
||||
if (shouldAliveCheck && supportsAliveCheck) {
|
||||
startAliveListener();
|
||||
}
|
||||
|
||||
@@ -114,7 +114,8 @@ public class StoreCreationModel {
|
||||
&& store.get().isComplete()
|
||||
&& store.get() instanceof ValidatableStore) {
|
||||
if (existingEntry != null) {
|
||||
return !existingEntry.isFreeze() || !existingEntry.getName().equals(name.getValue());
|
||||
return !existingEntry.isFreeze()
|
||||
|| !existingEntry.getName().equals(name.getValue());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
@@ -175,7 +176,8 @@ public class StoreCreationModel {
|
||||
|
||||
void connect() {
|
||||
var temp = entry.getValue() != null ? entry.getValue() : DataStoreEntry.createTempWrapper(store.getValue());
|
||||
var action = OpenTerminalHubMenuLeafProvider.Action.builder().ref(temp.ref()).build();
|
||||
var action =
|
||||
OpenTerminalHubMenuLeafProvider.Action.builder().ref(temp.ref()).build();
|
||||
action.executeAsync();
|
||||
}
|
||||
|
||||
|
||||
@@ -267,7 +267,8 @@ public class StoreEntryWrapper {
|
||||
} else {
|
||||
return Optional.of(new EditHubLeafProvider());
|
||||
}
|
||||
}).orElse(null);
|
||||
})
|
||||
.orElse(null);
|
||||
this.defaultActionProvider.setValue(defaultProvider);
|
||||
|
||||
var newMajorProviders = ActionProvider.ALL.stream()
|
||||
|
||||
@@ -207,8 +207,8 @@ public class AppPrefs {
|
||||
final BooleanProperty disableSshPinCaching =
|
||||
mapLocal(new SimpleBooleanProperty(false), "disableSshPinCaching", Boolean.class, false);
|
||||
|
||||
final ObjectProperty<SupportedLocale> language = mapLocal(
|
||||
new SimpleObjectProperty<>(SupportedLocale.ENGLISH), "language", SupportedLocale.class, false);
|
||||
final ObjectProperty<SupportedLocale> language =
|
||||
mapLocal(new SimpleObjectProperty<>(SupportedLocale.ENGLISH), "language", SupportedLocale.class, false);
|
||||
|
||||
final BooleanProperty requireDoubleClickForConnections =
|
||||
mapLocal(new SimpleBooleanProperty(false), "requireDoubleClickForConnections", Boolean.class, false);
|
||||
|
||||
@@ -7,7 +7,6 @@ import io.xpipe.core.JacksonMapper;
|
||||
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.fasterxml.jackson.databind.node.TextNode;
|
||||
|
||||
@@ -23,9 +23,9 @@ public class LinksCategory extends AppPrefsCategory {
|
||||
null)
|
||||
.addComp(
|
||||
new TileButtonComp("reddit", "redditDescription", "mdi2r-reddit", e -> {
|
||||
Hyperlinks.open(Hyperlinks.REDDIT);
|
||||
e.consume();
|
||||
})
|
||||
Hyperlinks.open(Hyperlinks.REDDIT);
|
||||
e.consume();
|
||||
})
|
||||
.grow(true, false),
|
||||
null)
|
||||
.addComp(
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import javax.management.MBeanServer;
|
||||
|
||||
public class TroubleshootCategory extends AppPrefsCategory {
|
||||
@@ -159,17 +158,28 @@ public class TroubleshootCategory extends AppPrefsCategory {
|
||||
|
||||
if (OsType.getLocal() == OsType.MACOS && AppDistributionType.get() == AppDistributionType.NATIVE_INSTALLATION) {
|
||||
b.addComp(
|
||||
new TileButtonComp("uninstallApplication", "uninstallApplicationDescription", "mdi2d-dump-truck", e -> {
|
||||
var file = XPipeInstallation.getCurrentInstallationBasePath().resolve("Contents").resolve("Resources").resolve("scripts").resolve("uninstall.sh");
|
||||
OperationMode.executeAfterShutdown(() -> {
|
||||
TerminalLauncher.openDirectFallback("Uninstall", sc -> ShellScript.lines(
|
||||
"echo \"+ sudo " + file.toString() + "\"",
|
||||
"sudo " + file.toString(),
|
||||
ProcessControlProvider.get().getEffectiveLocalDialect().getPauseCommand())
|
||||
);
|
||||
});
|
||||
e.consume();
|
||||
})
|
||||
new TileButtonComp(
|
||||
"uninstallApplication",
|
||||
"uninstallApplicationDescription",
|
||||
"mdi2d-dump-truck",
|
||||
e -> {
|
||||
var file = XPipeInstallation.getCurrentInstallationBasePath()
|
||||
.resolve("Contents")
|
||||
.resolve("Resources")
|
||||
.resolve("scripts")
|
||||
.resolve("uninstall.sh");
|
||||
OperationMode.executeAfterShutdown(() -> {
|
||||
TerminalLauncher.openDirectFallback(
|
||||
"Uninstall",
|
||||
sc -> ShellScript.lines(
|
||||
"echo \"+ sudo " + file + "\"",
|
||||
"sudo " + file,
|
||||
ProcessControlProvider.get()
|
||||
.getEffectiveLocalDialect()
|
||||
.getPauseCommand()));
|
||||
});
|
||||
e.consume();
|
||||
})
|
||||
.grow(true, false),
|
||||
null);
|
||||
}
|
||||
|
||||
@@ -154,7 +154,9 @@ public class ShellView {
|
||||
}
|
||||
|
||||
public FilePath pwd() throws Exception {
|
||||
return FilePath.of(shellControl.command(shellControl.getShellDialect().getPrintWorkingDirectoryCommand()).readStdoutOrThrow());
|
||||
return FilePath.of(shellControl
|
||||
.command(shellControl.getShellDialect().getPrintWorkingDirectoryCommand())
|
||||
.readStdoutOrThrow());
|
||||
}
|
||||
|
||||
public void cd(String directory) throws Exception {
|
||||
|
||||
@@ -71,7 +71,7 @@ public class DataStoreCategory extends StorageElement {
|
||||
DataStoreCategoryConfig.empty());
|
||||
}
|
||||
|
||||
public static Optional<DataStoreCategory> fromDirectory(Path dir) throws Exception {
|
||||
public static Optional<DataStoreCategory> fromDirectory(Path dir) {
|
||||
ObjectMapper mapper = JacksonMapper.getDefault();
|
||||
|
||||
var entryFile = dir.resolve("category.json");
|
||||
|
||||
@@ -112,7 +112,8 @@ public class DataStoreEntry extends StorageElement {
|
||||
this.categoryUuid = categoryUuid;
|
||||
this.store = store;
|
||||
this.storeNode = storeNode;
|
||||
this.provider = store != null ? DataStoreProviders.byStoreIfPresent(store).orElse(null) : null;
|
||||
this.provider =
|
||||
store != null ? DataStoreProviders.byStoreIfPresent(store).orElse(null) : null;
|
||||
this.validity = this.provider != null ? validity : Validity.LOAD_FAILED;
|
||||
this.storePersistentStateNode = storePersistentState;
|
||||
this.notes = notes;
|
||||
@@ -199,7 +200,7 @@ public class DataStoreEntry extends StorageElement {
|
||||
return "icons/" + icon + ".svg";
|
||||
}
|
||||
|
||||
public static Optional<DataStoreEntry> fromDirectory(Path dir) throws Exception {
|
||||
public static Optional<DataStoreEntry> fromDirectory(Path dir) {
|
||||
ObjectMapper mapper = JacksonMapper.getDefault();
|
||||
|
||||
var entryFile = dir.resolve("entry.json");
|
||||
|
||||
@@ -157,11 +157,8 @@ public class StandardStorage extends DataStorage {
|
||||
}
|
||||
|
||||
addStoreCategory(c.get());
|
||||
} catch (IOException ex) {
|
||||
// IO exceptions are not expected
|
||||
exception.set(new IOException("Unable to load data from " + path + ". Is it corrupted?", ex));
|
||||
directoriesToKeep.add(path);
|
||||
} catch (Exception ex) {
|
||||
} // IO exceptions are not expected
|
||||
catch (Exception ex) {
|
||||
// Data corruption and schema changes are expected
|
||||
ErrorEventFactory.fromThrowable(ex)
|
||||
.expected()
|
||||
@@ -214,11 +211,8 @@ public class StandardStorage extends DataStorage {
|
||||
|
||||
laterAddedEntries.add(entry.get());
|
||||
storeEntries.put(entry.get(), entry.get());
|
||||
} catch (IOException ex) {
|
||||
// IO exceptions are not expected
|
||||
exception.set(new IOException("Unable to load data from " + path + ". Is it corrupted?", ex));
|
||||
directoriesToKeep.add(path);
|
||||
} catch (Exception ex) {
|
||||
} // IO exceptions are not expected
|
||||
catch (Exception ex) {
|
||||
// Data corruption and schema changes are expected
|
||||
|
||||
// We only keep invalid entries in developer mode as there's no point in keeping them in
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
package io.xpipe.app.terminal;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
import io.xpipe.app.ext.ProcessControlProvider;
|
||||
import io.xpipe.app.issue.ErrorEventFactory;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.prefs.ExternalApplicationType;
|
||||
import io.xpipe.app.process.CommandBuilder;
|
||||
import io.xpipe.app.process.ShellControl;
|
||||
import io.xpipe.app.process.ShellDialects;
|
||||
import io.xpipe.app.util.CommandSupport;
|
||||
import io.xpipe.app.util.LocalShell;
|
||||
import io.xpipe.app.util.ShellTemp;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
import io.xpipe.core.FilePath;
|
||||
import io.xpipe.core.XPipeInstallation;
|
||||
|
||||
public interface GhosttyTerminalType extends ExternalTerminalType, TrackableTerminalType {
|
||||
|
||||
|
||||
@@ -92,9 +92,7 @@ public class TerminalLaunchConfiguration {
|
||||
Stop-Transcript > $Out-Null
|
||||
echo 'Transcript stopped, output file is "sessions\\%s"'
|
||||
"""
|
||||
.formatted(logFile.getFileName(),
|
||||
logFile,
|
||||
launcherScript, logFile.getFileName());
|
||||
.formatted(logFile.getFileName(), logFile, launcherScript, logFile.getFileName());
|
||||
var config = new TerminalLaunchConfiguration(
|
||||
entry != null ? color : null,
|
||||
adjustedTitle,
|
||||
@@ -104,20 +102,27 @@ public class TerminalLaunchConfiguration {
|
||||
ShellDialects.POWERSHELL);
|
||||
return config;
|
||||
} else {
|
||||
var found = sc.command(sc.getShellDialect().getWhichCommand("script"))
|
||||
.executeAndCheck();
|
||||
var found =
|
||||
sc.command(sc.getShellDialect().getWhichCommand("script")).executeAndCheck();
|
||||
if (!found) {
|
||||
var suffix = sc.getOsType() == OsType.MACOS
|
||||
? "This command is available in the util-linux package which can be installed via homebrew."
|
||||
: "This command is available in the util-linux package.";
|
||||
throw ErrorEventFactory.expected(new IllegalStateException(
|
||||
"Logging requires the script command to be installed. " + suffix));
|
||||
throw ErrorEventFactory.expected(
|
||||
new IllegalStateException("Logging requires the script command to be installed. " + suffix));
|
||||
}
|
||||
|
||||
var launcherScript = ScriptHelper.createExecScript(
|
||||
LocalShell.getShell(), LocalShell.getShell().getShellDialect().terminalLauncherScript(request, adjustedTitle, alwaysPromptRestart));
|
||||
var command = sc == LocalShell.getShell() ? launcherScript :
|
||||
LocalShell.getShell().getShellDialect().getOpenScriptCommand(launcherScript.toString()).buildFull(LocalShell.getShell());
|
||||
LocalShell.getShell(),
|
||||
LocalShell.getShell()
|
||||
.getShellDialect()
|
||||
.terminalLauncherScript(request, adjustedTitle, alwaysPromptRestart));
|
||||
var command = sc == LocalShell.getShell()
|
||||
? launcherScript
|
||||
: LocalShell.getShell()
|
||||
.getShellDialect()
|
||||
.getOpenScriptCommand(launcherScript.toString())
|
||||
.buildFull(LocalShell.getShell());
|
||||
var content = sc.getOsType() == OsType.MACOS || sc.getOsType() == OsType.BSD
|
||||
? """
|
||||
echo "Transcript started, output file is sessions/%s"
|
||||
@@ -126,7 +131,15 @@ public class TerminalLaunchConfiguration {
|
||||
cat "%s" | perl -pe 's/\\e([^\\[\\]]|\\[.*?[a-zA-Z]|\\].*?\\a)/\\n/g' | perl -0 -pe 's/\\n+/\\n/g' | col -b > "%s.new"
|
||||
mv -f "%s.new" "%s"
|
||||
"""
|
||||
.formatted(logFile.getFileName(), logFile, command, logFile.getFileName(), logFile, logFile, logFile, logFile)
|
||||
.formatted(
|
||||
logFile.getFileName(),
|
||||
logFile,
|
||||
command,
|
||||
logFile.getFileName(),
|
||||
logFile,
|
||||
logFile,
|
||||
logFile,
|
||||
logFile)
|
||||
: """
|
||||
echo "Transcript started, output file is sessions/%s"
|
||||
script --quiet --command '%s' "%s"
|
||||
@@ -134,14 +147,17 @@ public class TerminalLaunchConfiguration {
|
||||
cat "%s" | perl -pe 's/\\e([^\\[\\]]|\\[.*?[a-zA-Z]|\\].*?\\a)/\\n/g' | perl -0 -pe 's/\\n+/\\n/g' | col -b > "%s.new"
|
||||
mv -f "%s.new" "%s"
|
||||
"""
|
||||
.formatted(logFile.getFileName(), command, logFile, logFile.getFileName(), logFile, logFile, logFile, logFile);
|
||||
.formatted(
|
||||
logFile.getFileName(),
|
||||
command,
|
||||
logFile,
|
||||
logFile.getFileName(),
|
||||
logFile,
|
||||
logFile,
|
||||
logFile,
|
||||
logFile);
|
||||
var config = new TerminalLaunchConfiguration(
|
||||
entry != null ? color : null,
|
||||
adjustedTitle,
|
||||
cleanTitle,
|
||||
preferTabs,
|
||||
content,
|
||||
sc.getShellDialect());
|
||||
entry != null ? color : null, adjustedTitle, cleanTitle, preferTabs, content, sc.getShellDialect());
|
||||
config.scriptFile = ScriptHelper.createExecScript(sc.getShellDialect(), sc, content);
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -139,8 +139,12 @@ public class TerminalLauncher {
|
||||
}
|
||||
|
||||
public static void open(
|
||||
DataStoreEntry entry, String title, FilePath directory, ProcessControl cc, UUID request, boolean preferTabs)
|
||||
throws Exception {
|
||||
DataStoreEntry entry,
|
||||
String title,
|
||||
FilePath directory,
|
||||
ProcessControl cc,
|
||||
UUID request,
|
||||
boolean preferTabs) {
|
||||
var type = AppPrefs.get().terminalType().getValue();
|
||||
if (type == null) {
|
||||
throw ErrorEventFactory.expected(new IllegalStateException(AppI18n.get("noTerminalSet")));
|
||||
|
||||
@@ -79,7 +79,9 @@ public class AppDownloads {
|
||||
req.put("first", first);
|
||||
req.put("license", LicenseProvider.get().getLicenseId());
|
||||
req.put("dist", AppDistributionType.get().getId());
|
||||
req.put("lang", AppPrefs.get() != null ? AppPrefs.get().language().getValue().getId() : null);
|
||||
req.put(
|
||||
"lang",
|
||||
AppPrefs.get() != null ? AppPrefs.get().language().getValue().getId() : null);
|
||||
var url = URI.create("https://api.xpipe.io/version");
|
||||
|
||||
var builder = HttpRequest.newBuilder();
|
||||
|
||||
@@ -87,8 +87,10 @@ public class DesktopShortcuts {
|
||||
</dict>
|
||||
</plist>
|
||||
""");
|
||||
pc.command("cp \"" + icon + "\" \"" + base + "/Contents/Resources/xpipe.icns\"").execute();
|
||||
pc.command("cp \"" + assets + "\" \"" + base + "/Contents/Resources/Assets.car\"").execute();
|
||||
pc.command("cp \"" + icon + "\" \"" + base + "/Contents/Resources/xpipe.icns\"")
|
||||
.execute();
|
||||
pc.command("cp \"" + assets + "\" \"" + base + "/Contents/Resources/Assets.car\"")
|
||||
.execute();
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
@@ -89,7 +89,8 @@ public enum DocumentationLink {
|
||||
}
|
||||
|
||||
public static String getRoot() {
|
||||
var ptbDocs = AppProperties.get().isDevelopmentEnvironment() || AppProperties.get().isStaging();
|
||||
var ptbDocs = AppProperties.get().isDevelopmentEnvironment()
|
||||
|| AppProperties.get().isStaging();
|
||||
return ptbDocs ? "https://docs-ptb.xpipe.io" : "https://docs.xpipe.io";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package io.xpipe.app.util;
|
||||
|
||||
import io.xpipe.app.issue.ErrorEventFactory;
|
||||
import io.xpipe.core.FailableRunnable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Timer;
|
||||
|
||||
@@ -121,7 +121,8 @@ open module io.xpipe.app {
|
||||
uses ShellDialect;
|
||||
|
||||
provides ActionProvider with
|
||||
XPipeUrlProvider, OpenTerminalHubMenuLeafProvider,
|
||||
XPipeUrlProvider,
|
||||
OpenTerminalHubMenuLeafProvider,
|
||||
EditHubLeafProvider,
|
||||
CloneHubLeafProvider,
|
||||
DownloadMenuProvider,
|
||||
@@ -142,7 +143,8 @@ open module io.xpipe.app {
|
||||
ScanHubLeafProvider,
|
||||
BrowseHubLeafProvider,
|
||||
RefreshActionProvider,
|
||||
ToggleActionProvider, OpenTerminalInDirectoryMenuProvider,
|
||||
ToggleActionProvider,
|
||||
OpenTerminalInDirectoryMenuProvider,
|
||||
OpenNativeFileDetailsMenuProvider,
|
||||
BrowseInNativeManagerActionProvider,
|
||||
ApplyFileEditActionProvider,
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.xpipe.core.FilePath;
|
||||
import io.xpipe.core.OsType;
|
||||
import io.xpipe.core.XPipeDaemonMode;
|
||||
import io.xpipe.core.XPipeInstallation;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@@ -22,7 +23,7 @@ public class BeaconServer {
|
||||
|
||||
@SneakyThrows
|
||||
public static boolean isReachable(int port) {
|
||||
var local = Inet4Address.getByAddress(new byte[]{0x7f, 0x00, 0x00, 0x01});
|
||||
var local = Inet4Address.getByAddress(new byte[] {0x7f, 0x00, 0x00, 0x01});
|
||||
|
||||
try (var socket = new Socket()) {
|
||||
InetSocketAddress adress = new InetSocketAddress(local, port);
|
||||
@@ -36,7 +37,7 @@ public class BeaconServer {
|
||||
// To be sure, check that the socket is indeed occupied
|
||||
try (var ignored = new ServerSocket(port, 0, local)) {
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -110,7 +110,7 @@ browserWelcomeEmptyContent=You can choose on the left which systems to open in t
|
||||
browserWelcomeEmptyButton=Open local file browser
|
||||
browserWelcomeSystems=You were recently connected to the following systems:
|
||||
browserWelcomeDocsHeader=Documentation
|
||||
browserWelcomeDocsContent=If you prefer a more guided approach to familiarizing yourself with XPipe, check out the documentation website.
|
||||
browserWelcomeDocsContent=If you prefer a more guided approach to familiarizing yourself with XPipe, check out the documentation website.
|
||||
browserWelcomeDocsButton=Open documentation
|
||||
hostFeatureUnsupported=$FEATURE$ is not installed on the host
|
||||
missingStore=$NAME$ does not exist
|
||||
|
||||
Reference in New Issue
Block a user