mirror of
https://github.com/xpipe-io/xpipe.git
synced 2025-04-19 02:33:39 +00:00
Rework
This commit is contained in:
parent
153db64ae0
commit
693b82dab8
17 changed files with 92 additions and 122 deletions
|
@ -20,7 +20,6 @@ public class AppJavaOptionsCheck {
|
|||
.formatted(env)
|
||||
+ " This will forcefully apply all custom JVM options to XPipe and can cause a variety of different issues."
|
||||
+ " Please remove this global environment variable and use local configuration instead for your other JVM programs.")
|
||||
.noDefaultActions()
|
||||
.expected()
|
||||
.handle();
|
||||
AppCache.update("javaOptionsWarningShown", true);
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.xpipe.app.core.check;
|
|||
|
||||
import io.xpipe.app.core.AppProperties;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.util.DocumentationLink;
|
||||
import io.xpipe.app.util.LocalShell;
|
||||
import io.xpipe.core.process.OsType;
|
||||
|
||||
|
@ -27,7 +28,7 @@ public class AppRosettaCheck {
|
|||
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.")
|
||||
.noDefaultActions()
|
||||
.documentationLink(DocumentationLink.MACOS_SETUP)
|
||||
.expected()
|
||||
.handle();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.xpipe.app.ext;
|
||||
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.util.DocumentationLink;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
import io.xpipe.core.process.CommandBuilder;
|
||||
import io.xpipe.core.process.ShellControl;
|
||||
|
@ -57,9 +58,11 @@ public class ConnectionFileSystem implements FileSystem {
|
|||
|
||||
if (!shellControl.getTtyState().isPreservesOutput()
|
||||
|| !shellControl.getTtyState().isSupportsInput()) {
|
||||
throw ErrorEvent.expected(new UnsupportedOperationException(
|
||||
"Shell has a PTY allocated and as a result does not support file system operations. For more information see "
|
||||
+ Hyperlinks.DOCS_TTY));
|
||||
var ex = new UnsupportedOperationException(
|
||||
"Shell has a PTY allocated and as a result does not support file system operations.");
|
||||
ErrorEvent.preconfigure(ErrorEvent.fromThrowable(ex)
|
||||
.documentationLink(DocumentationLink.TTY));
|
||||
throw ex;
|
||||
}
|
||||
|
||||
shellControl.checkLicenseOrThrow();
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package io.xpipe.app.issue;
|
||||
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.util.DocumentationLink;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
|
||||
public interface ErrorAction {
|
||||
|
||||
static ErrorAction openDocumentation(String link) {
|
||||
static ErrorAction openDocumentation(DocumentationLink link) {
|
||||
return new ErrorAction() {
|
||||
@Override
|
||||
public String getName() {
|
||||
|
@ -19,53 +20,12 @@ public interface ErrorAction {
|
|||
|
||||
@Override
|
||||
public boolean handle(ErrorEvent event) {
|
||||
Hyperlinks.open(link);
|
||||
link.open();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static ErrorAction reportOnGithub() {
|
||||
return new ErrorAction() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return AppI18n.get("reportOnGithub");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return AppI18n.get("reportOnGithubDescription");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(ErrorEvent event) {
|
||||
var url = "https://github.com/xpipe-io/xpipe/issues/new";
|
||||
Hyperlinks.open(url);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static ErrorAction automaticallyReport() {
|
||||
return new ErrorAction() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return AppI18n.get("reportError");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return AppI18n.get("reportErrorDescription");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(ErrorEvent event) {
|
||||
UserReportComp.show(event);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static ErrorAction ignore() {
|
||||
return new ErrorAction() {
|
||||
@Override
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.xpipe.app.issue;
|
||||
|
||||
import io.xpipe.app.util.DocumentationLink;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
@ -23,9 +24,6 @@ public class ErrorEvent {
|
|||
@Builder.Default
|
||||
private final boolean reportable = true;
|
||||
|
||||
@Setter
|
||||
private boolean disableDefaultActions;
|
||||
|
||||
private final Throwable throwable;
|
||||
|
||||
@Singular
|
||||
|
@ -43,6 +41,8 @@ public class ErrorEvent {
|
|||
@Singular
|
||||
private List<Path> attachments;
|
||||
|
||||
private DocumentationLink documentationLink;
|
||||
|
||||
private String email;
|
||||
private String userReport;
|
||||
private boolean unhandled;
|
||||
|
@ -162,10 +162,6 @@ public class ErrorEvent {
|
|||
return omit().expected();
|
||||
}
|
||||
|
||||
public ErrorEventBuilder noDefaultActions() {
|
||||
return disableDefaultActions(true);
|
||||
}
|
||||
|
||||
public void handle() {
|
||||
build().handle();
|
||||
}
|
||||
|
|
|
@ -66,22 +66,6 @@ public class ErrorHandlerComp extends SimpleComp {
|
|||
return b.createRegion();
|
||||
}
|
||||
|
||||
private Region createDetails() {
|
||||
var content = new ErrorDetailsComp(event).prefWidth(600).prefHeight(750);
|
||||
var modal = ModalOverlay.of("errorDetails", content);
|
||||
var button = new ButtonComp(
|
||||
null,
|
||||
new SimpleObjectProperty<>(new LabelGraphic.NodeGraphic(() -> {
|
||||
return createActionButtonGraphic(AppI18n.get("showDetails"), AppI18n.get("showDetailsDescription"));
|
||||
})),
|
||||
() -> {
|
||||
modal.show();
|
||||
});
|
||||
var r = button.grow(true, false).createRegion();
|
||||
r.getStyleClass().add("details");
|
||||
return r;
|
||||
}
|
||||
|
||||
private Region createTop() {
|
||||
var desc = event.getDescription();
|
||||
if (desc == null && event.getThrowable() != null) {
|
||||
|
@ -112,10 +96,10 @@ public class ErrorHandlerComp extends SimpleComp {
|
|||
@Override
|
||||
protected Region createSimple() {
|
||||
var top = createTop();
|
||||
var content = new VBox(top, new Separator(Orientation.HORIZONTAL));
|
||||
var content = new VBox(top);
|
||||
var header = new Label(AppI18n.get("possibleActions"));
|
||||
AppFontSizes.xl(header);
|
||||
var actionBox = new VBox(header);
|
||||
var actionBox = new VBox();
|
||||
actionBox.getStyleClass().add("actions");
|
||||
actionBox.setFillWidth(true);
|
||||
|
||||
|
@ -137,7 +121,6 @@ public class ErrorHandlerComp extends SimpleComp {
|
|||
return true;
|
||||
}
|
||||
});
|
||||
event.setDisableDefaultActions(true);
|
||||
}
|
||||
|
||||
var custom = event.getCustomActions();
|
||||
|
@ -147,21 +130,17 @@ public class ErrorHandlerComp extends SimpleComp {
|
|||
actionBox.getChildren().add(ac);
|
||||
}
|
||||
|
||||
if (!event.isDisableDefaultActions()) {
|
||||
for (var action :
|
||||
List.of(ErrorAction.automaticallyReport(), ErrorAction.reportOnGithub(), ErrorAction.ignore())) {
|
||||
var ac = createActionComp(action);
|
||||
actionBox.getChildren().add(ac);
|
||||
}
|
||||
} else if (event.getCustomActions().isEmpty()) {
|
||||
for (var action : List.of(ErrorAction.ignore())) {
|
||||
var ac = createActionComp(action);
|
||||
actionBox.getChildren().add(ac);
|
||||
}
|
||||
if (event.getDocumentationLink() != null) {
|
||||
actionBox.getChildren().add(createActionComp(ErrorAction.openDocumentation(event.getDocumentationLink())));
|
||||
}
|
||||
|
||||
if (actionBox.getChildren().size() > 0) {
|
||||
actionBox.getChildren().addFirst(header);
|
||||
content.getChildren().add(new Separator(Orientation.HORIZONTAL));
|
||||
actionBox.getChildren().get(1).getStyleClass().addAll(BUTTON_OUTLINED);
|
||||
content.getChildren().addAll(actionBox);
|
||||
}
|
||||
actionBox.getChildren().get(1).getStyleClass().addAll(BUTTON_OUTLINED, ACCENT);
|
||||
|
||||
content.getChildren().addAll(actionBox);
|
||||
content.getStyleClass().add("top");
|
||||
content.setFillWidth(true);
|
||||
content.setMinHeight(Region.USE_PREF_SIZE);
|
||||
|
@ -170,13 +149,6 @@ public class ErrorHandlerComp extends SimpleComp {
|
|||
layout.getChildren().add(content);
|
||||
layout.getStyleClass().add("error-handler-comp");
|
||||
|
||||
if (event.getThrowable() != null) {
|
||||
content.getChildren().add(new Separator(Orientation.HORIZONTAL));
|
||||
var details = createDetails();
|
||||
layout.getChildren().add(details);
|
||||
layout.prefHeightProperty().bind(content.heightProperty().add(65).add(details.prefHeightProperty()));
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.xpipe.app.issue;
|
||||
|
||||
import io.xpipe.app.comp.base.ModalButton;
|
||||
import io.xpipe.app.comp.base.ModalOverlay;
|
||||
import io.xpipe.app.core.mode.OperationMode;
|
||||
import io.xpipe.app.core.window.AppDialog;
|
||||
|
@ -44,13 +45,25 @@ public class ErrorHandlerDialog {
|
|||
var comp = new ErrorHandlerComp(event, () -> {
|
||||
AppDialog.closeDialog(modal.get());
|
||||
});
|
||||
comp.prefWidth(550);
|
||||
comp.prefWidth(500);
|
||||
var headerId = event.isTerminal() ? "terminalErrorOccured" : "errorOccured";
|
||||
modal.set(ModalOverlay.of(headerId, comp, new LabelGraphic.NodeGraphic(() -> {
|
||||
var errorModal = ModalOverlay.of(headerId, comp, new LabelGraphic.NodeGraphic(() -> {
|
||||
var graphic = new FontIcon("mdomz-warning");
|
||||
graphic.setIconColor(Color.RED);
|
||||
return graphic;
|
||||
})));
|
||||
}));
|
||||
if (event.getThrowable() != null && event.isReportable()) {
|
||||
errorModal.addButton(new ModalButton("stackTrace", () -> {
|
||||
var content = new ErrorDetailsComp(event).prefWidth(600).prefHeight(750);
|
||||
var detailsModal = ModalOverlay.of("errorDetails", content);
|
||||
detailsModal.show();
|
||||
}, false, false));
|
||||
}
|
||||
errorModal.addButton(new ModalButton("report", () -> {
|
||||
UserReportComp.show(event);
|
||||
}, false, false));
|
||||
errorModal.addButton(ModalButton.ok());
|
||||
modal.set(errorModal);
|
||||
AppDialog.showAndWait(modal.get());
|
||||
if (comp.getTakenAction().getValue() == null) {
|
||||
ErrorAction.ignore().handle(event);
|
||||
|
|
|
@ -8,6 +8,7 @@ import io.xpipe.app.comp.base.VerticalComp;
|
|||
import io.xpipe.app.core.AppDistributionType;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppProperties;
|
||||
import io.xpipe.app.util.DocumentationLink;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
import io.xpipe.app.util.JfxHelper;
|
||||
import io.xpipe.app.util.OptionsBuilder;
|
||||
|
@ -48,7 +49,7 @@ public class AboutCategory extends AppPrefsCategory {
|
|||
null)
|
||||
.addComp(
|
||||
new TileButtonComp("privacy", "privacyDescription", "mdomz-privacy_tip", e -> {
|
||||
Hyperlinks.open(Hyperlinks.DOCS_PRIVACY);
|
||||
DocumentationLink.PRIVACY.open();
|
||||
e.consume();
|
||||
})
|
||||
.grow(true, false),
|
||||
|
@ -64,7 +65,7 @@ public class AboutCategory extends AppPrefsCategory {
|
|||
.grow(true, false))
|
||||
.addComp(
|
||||
new TileButtonComp("eula", "eulaDescription", "mdi2c-card-text-outline", e -> {
|
||||
Hyperlinks.open(Hyperlinks.DOCS_EULA);
|
||||
DocumentationLink.EULA.open();
|
||||
e.consume();
|
||||
})
|
||||
.grow(true, false),
|
||||
|
|
|
@ -4,6 +4,7 @@ import io.xpipe.app.comp.Comp;
|
|||
import io.xpipe.app.comp.base.*;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.storage.DataStorageSyncHandler;
|
||||
import io.xpipe.app.util.DocumentationLink;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
import io.xpipe.app.util.OptionsBuilder;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
@ -53,7 +54,7 @@ public class SyncCategory extends AppPrefsCategory {
|
|||
|
||||
var remoteRepo = new TextFieldComp(prefs.storageGitRemote).hgrow();
|
||||
var helpButton = new ButtonComp(AppI18n.observable("help"), new FontIcon("mdi2h-help-circle-outline"), () -> {
|
||||
Hyperlinks.open(Hyperlinks.DOCS_SYNC);
|
||||
DocumentationLink.SYNC.open();
|
||||
});
|
||||
var remoteRow = new HorizontalComp(List.of(remoteRepo, helpButton)).spacing(10);
|
||||
remoteRow.apply(struc -> struc.get().setAlignment(Pos.CENTER_LEFT));
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.xpipe.app.update;
|
||||
|
||||
import io.xpipe.app.comp.base.ModalButton;
|
||||
import io.xpipe.app.util.DocumentationLink;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -21,7 +22,7 @@ public class WebtopUpdater extends PortableUpdater {
|
|||
return;
|
||||
}
|
||||
|
||||
Hyperlinks.open(Hyperlinks.DOCS_WEBTOP_UPDATE);
|
||||
DocumentationLink.WEBTOP_UPDATE.open();
|
||||
},
|
||||
false,
|
||||
false));
|
||||
|
|
|
@ -17,6 +17,8 @@ import javafx.stage.Modality;
|
|||
import javafx.stage.Stage;
|
||||
import javafx.stage.Window;
|
||||
|
||||
import javax.print.Doc;
|
||||
|
||||
public class AskpassAlert {
|
||||
|
||||
public static SecretQueryResult queryRaw(String prompt, InPlaceSecretValue secretValue) {
|
||||
|
@ -33,7 +35,7 @@ public class AskpassAlert {
|
|||
alert.getButtonTypes().add(type);
|
||||
var button = alert.getDialogPane().lookupButton(type);
|
||||
button.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
|
||||
Hyperlinks.open(Hyperlinks.DOCS_DOUBLE_PROMPT);
|
||||
DocumentationLink.DOUBLE_PROMPT.open();
|
||||
event.consume();
|
||||
});
|
||||
}
|
||||
|
|
32
app/src/main/java/io/xpipe/app/util/DocumentationLink.java
Normal file
32
app/src/main/java/io/xpipe/app/util/DocumentationLink.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
package io.xpipe.app.util;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
public enum DocumentationLink {
|
||||
|
||||
INDEX(""),
|
||||
TTY("troubleshoot/tty"),
|
||||
MACOS_SETUP("guide/installation#macos"),
|
||||
SSH_AGENT("troubleshoot/ssh-agent-socket"),
|
||||
DOUBLE_PROMPT("troubleshoot/two-step-connections"),
|
||||
LICENSE_ACTIVATION("troubleshoot/license-activation"),
|
||||
PRIVACY("legal/privacy"),
|
||||
EULA("legal/eula"),
|
||||
WEBTOP_UPDATE("guide/webtop#updating"),
|
||||
SYNC("guide/sync"),
|
||||
SCRIPTING("guide/scripting"),
|
||||
SSH("guide/ssh");
|
||||
|
||||
|
||||
private final String page;
|
||||
|
||||
DocumentationLink(String page) {this.page = page;}
|
||||
|
||||
public void open() {
|
||||
Hyperlinks.open("https://docs.xpipe.io/" + page);
|
||||
}
|
||||
|
||||
public String getLink() {
|
||||
return "https://docs.xpipe.io/" + page;
|
||||
}
|
||||
}
|
|
@ -5,16 +5,6 @@ import io.xpipe.app.issue.ErrorEvent;
|
|||
public class Hyperlinks {
|
||||
|
||||
public static final String DOCS = "https://docs.xpipe.io";
|
||||
public static final String DOCS_DOUBLE_PROMPT = "https://docs.xpipe.io/troubleshoot/two-step-connections";
|
||||
public static final String DOCS_AGENT_SETUP = "https://docs.xpipe.io/troubleshoot/ssh-agent-socket";
|
||||
public static final String DOCS_TTY = "https://docs.xpipe.io/troubleshoot/tty";
|
||||
public static final String DOCS_LICENSE_ACTIVATION = "https://docs.xpipe.io/troubleshoot/license-activation";
|
||||
public static final String DOCS_PRIVACY = "https://docs.xpipe.io/legal/privacy-policy";
|
||||
public static final String DOCS_EULA = "https://docs.xpipe.io/legal/end-user-license-agreement";
|
||||
public static final String DOCS_SECURITY = "https://docs.xpipe.io/reference/security";
|
||||
public static final String DOCS_WEBTOP_UPDATE = "https://docs.xpipe.io/guide/webtop#updating";
|
||||
public static final String DOCS_SYNC = "https://docs.xpipe.io/guide/sync";
|
||||
public static final String DOCS_SCRIPTING = "https://docs.xpipe.io/guide/scriptin";
|
||||
public static final String GITHUB = "https://github.com/xpipe-io/xpipe";
|
||||
public static final String GITHUB_PTB = "https://github.com/xpipe-io/xpipe-ptb";
|
||||
public static final String GITHUB_LATEST = "https://github.com/xpipe-io/xpipe/releases/latest";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.error-handler-comp .top {
|
||||
-fx-spacing: 1em;
|
||||
-fx-spacing: 0.7em;
|
||||
}
|
||||
|
||||
.error-handler-comp .actions {
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.xpipe.ext.base.identity;
|
|||
import io.xpipe.app.issue.ErrorAction;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.util.CommandSupport;
|
||||
import io.xpipe.app.util.DocumentationLink;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
import io.xpipe.core.process.CommandBuilder;
|
||||
import io.xpipe.core.process.OsType;
|
||||
|
@ -73,7 +74,7 @@ public class SshIdentityStateManager {
|
|||
return true;
|
||||
}
|
||||
};
|
||||
event.customAction(shutdown).noDefaultActions().handle();
|
||||
event.customAction(shutdown).handle();
|
||||
|
||||
if (r.get()) {
|
||||
if (sc.getShellDialect().equals(ShellDialects.CMD)) {
|
||||
|
@ -146,7 +147,7 @@ public class SshIdentityStateManager {
|
|||
var r = c.readStdoutAndStderr();
|
||||
if (c.getExitCode() != 0) {
|
||||
var posixMessage = sc.getOsType() != OsType.WINDOWS
|
||||
? " and the SSH_AUTH_SOCK variable. See " + Hyperlinks.DOCS_AGENT_SETUP + " for details"
|
||||
? " and the SSH_AUTH_SOCK variable."
|
||||
: "";
|
||||
var ex =
|
||||
new IllegalStateException("Unable to list agent identities via command ssh-add -l:\n" + r[0]
|
||||
|
@ -154,9 +155,8 @@ public class SshIdentityStateManager {
|
|||
+ r[1]
|
||||
+ "\nPlease check your SSH agent CLI configuration%s.".formatted(posixMessage));
|
||||
ErrorEvent.preconfigure(ErrorEvent.fromThrowable(ex)
|
||||
.noDefaultActions()
|
||||
.expected()
|
||||
.customAction(ErrorAction.openDocumentation(Hyperlinks.DOCS_AGENT_SETUP)));
|
||||
.documentationLink(DocumentationLink.SSH_AGENT));
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,7 @@ import io.xpipe.app.ext.DataStoreProvider;
|
|||
import io.xpipe.app.ext.EnabledParentStoreProvider;
|
||||
import io.xpipe.app.ext.GuiDialog;
|
||||
import io.xpipe.app.storage.DataStoreEntry;
|
||||
import io.xpipe.app.util.DataStoreFormatter;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
import io.xpipe.app.util.OptionsBuilder;
|
||||
import io.xpipe.app.util.Validator;
|
||||
import io.xpipe.app.util.*;
|
||||
import io.xpipe.core.process.ShellDialect;
|
||||
import io.xpipe.core.process.ShellDialects;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
|
@ -36,7 +33,7 @@ public class SimpleScriptStoreProvider implements EnabledParentStoreProvider, Da
|
|||
|
||||
@Override
|
||||
public String getHelpLink() {
|
||||
return Hyperlinks.DOCS_SCRIPTING;
|
||||
return DocumentationLink.SCRIPTING.getLink();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
2
lang/strings/translations_en.properties
generated
2
lang/strings/translations_en.properties
generated
|
@ -1355,3 +1355,5 @@ connectionsSelected=$NUMBER$ connections selected
|
|||
addConnections=Add connections
|
||||
browseDirectory=Browse directory
|
||||
openTerminal=Open terminal
|
||||
documentation=Documentation
|
||||
report=Report error
|
||||
|
|
Loading…
Add table
Reference in a new issue