diff --git a/app/src/main/java/io/xpipe/app/browser/file/BrowserFileInput.java b/app/src/main/java/io/xpipe/app/browser/file/BrowserFileInput.java index 7552af4b4..da52a9639 100644 --- a/app/src/main/java/io/xpipe/app/browser/file/BrowserFileInput.java +++ b/app/src/main/java/io/xpipe/app/browser/file/BrowserFileInput.java @@ -47,7 +47,7 @@ public interface BrowserFileInput { return false; } - if (info != null) { + if (info != null && info.getPermissions() != null) { var otherWrite = info.getPermissions().charAt(6) == 'r'; if (otherWrite) { return false; diff --git a/app/src/main/java/io/xpipe/app/comp/base/SecretFieldComp.java b/app/src/main/java/io/xpipe/app/comp/base/SecretFieldComp.java index cebd6a8f9..34a23e81c 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/SecretFieldComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/SecretFieldComp.java @@ -121,7 +121,7 @@ public class SecretFieldComp extends RegionStructureBuilder { - ClipboardHelper.copyPassword(value.getValue()); + ClipboardHelper.copyPassword(value.getValue(), true); }) .describe(d -> d.nameKey("copy")); diff --git a/app/src/main/java/io/xpipe/app/core/window/AppDialog.java b/app/src/main/java/io/xpipe/app/core/window/AppDialog.java index 03bad176e..eec766578 100644 --- a/app/src/main/java/io/xpipe/app/core/window/AppDialog.java +++ b/app/src/main/java/io/xpipe/app/core/window/AppDialog.java @@ -141,6 +141,13 @@ public class AppDialog { .prefWidth(450); } + public static void information(String translationKey) { + var content = dialogTextKey(translationKey + "Content"); + var modal = ModalOverlay.of(translationKey + "Title", content); + modal.addButton(ModalButton.ok()); + show(modal); + } + public static boolean confirm(String translationKey) { var confirmed = new AtomicBoolean(false); var content = dialogTextKey(translationKey + "Content"); diff --git a/app/src/main/java/io/xpipe/app/hub/comp/StoreCreationMenu.java b/app/src/main/java/io/xpipe/app/hub/comp/StoreCreationMenu.java index 1c7f42ad3..7f66f79be 100644 --- a/app/src/main/java/io/xpipe/app/hub/comp/StoreCreationMenu.java +++ b/app/src/main/java/io/xpipe/app/hub/comp/StoreCreationMenu.java @@ -74,13 +74,6 @@ public class StoreCreationMenu { .add(categoryMenu( "addTunnel", "mdi2v-vector-polyline-plus", DataStoreCreationCategory.TUNNEL, "sshLocalTunnel")); - menu.getItems() - .add(categoryMenu( - "addFileSystem", - "mdi2f-folder-plus-outline", - DataStoreCreationCategory.FILE_SYSTEM, - "genericS3Bucket")); - menu.getItems().add(new SeparatorMenuItem()); menu.getItems() @@ -106,6 +99,13 @@ public class StoreCreationMenu { }); actionMenu.getItems().addFirst(item); + menu.getItems() + .add(categoryMenu( + "addFileSystem", + "mdi2f-folder-plus-outline", + DataStoreCreationCategory.FILE_SYSTEM, + "genericS3Bucket")); + menu.getItems().add(categoryMenu("addSerial", "mdi2s-serial-port", DataStoreCreationCategory.SERIAL, "serial")); menu.getItems().add(new SeparatorMenuItem()); diff --git a/app/src/main/java/io/xpipe/app/hub/comp/StoreListChoiceComp.java b/app/src/main/java/io/xpipe/app/hub/comp/StoreListChoiceComp.java index 0af71524b..d0281cd3d 100644 --- a/app/src/main/java/io/xpipe/app/hub/comp/StoreListChoiceComp.java +++ b/app/src/main/java/io/xpipe/app/hub/comp/StoreListChoiceComp.java @@ -117,7 +117,14 @@ public class StoreListChoiceComp extends SimpleRegionBuilde list.add(RegionBuilder.vspacer(5).hide(Bindings.isEmpty(selectedList))); list.add(add); } - var vbox = new VerticalComp(list).apply(struc -> struc.setFillWidth(true)); + var vbox = new VerticalComp(list).apply(struc -> { + struc.setFillWidth(true); + struc.focusedProperty().subscribe(focus -> { + if (focus) { + struc.getChildren().getLast().requestFocus(); + } + }); + }); return vbox.style("data-store-list-choice-comp").build(); } } diff --git a/app/src/main/java/io/xpipe/app/platform/ClipboardHelper.java b/app/src/main/java/io/xpipe/app/platform/ClipboardHelper.java index 91035385c..b22838945 100644 --- a/app/src/main/java/io/xpipe/app/platform/ClipboardHelper.java +++ b/app/src/main/java/io/xpipe/app/platform/ClipboardHelper.java @@ -1,7 +1,9 @@ package io.xpipe.app.platform; +import io.xpipe.app.core.AppCache; import io.xpipe.app.core.AppI18n; import io.xpipe.app.core.AppLayoutModel; +import io.xpipe.app.core.window.AppDialog; import io.xpipe.core.SecretValue; import javafx.animation.PauseTransition; @@ -48,7 +50,7 @@ public class ClipboardHelper { } } - public static void copyPassword(SecretValue pass) { + public static void copyPassword(SecretValue pass, boolean userInitiated) { if (pass == null) { return; } @@ -59,6 +61,14 @@ public class ClipboardHelper { apply(Map.of(DataFormat.PLAIN_TEXT, pass.getSecretValue()), true); + if (!userInitiated) { + var shown = AppCache.getBoolean("clipboardDialogShown", false); + if (!shown) { + AppDialog.information("clipboardNotice"); + AppCache.update("clipboardDialogShown", true); + } + } + var transition = new PauseTransition(Duration.millis(15000)); transition.setOnFinished(e -> { var present = clipboard.getString(); diff --git a/app/src/main/java/io/xpipe/app/prefs/PasswordManagerTestComp.java b/app/src/main/java/io/xpipe/app/prefs/PasswordManagerTestComp.java index c271269a9..cc931f2cc 100644 --- a/app/src/main/java/io/xpipe/app/prefs/PasswordManagerTestComp.java +++ b/app/src/main/java/io/xpipe/app/prefs/PasswordManagerTestComp.java @@ -74,6 +74,11 @@ public class PasswordManagerTestComp extends SimpleRegionBuilder { var vbox = new VerticalComp(List.of(field, testRow)); vbox.spacing(6); + vbox.apply(r -> r.focusedProperty().subscribe(focus -> { + if (focus) { + r.getChildren().getFirst().requestFocus(); + } + })); return vbox.build(); } @@ -120,8 +125,10 @@ public class PasswordManagerTestComp extends SimpleRegionBuilder { elements.add(""); } - if (r.getSshKey() != null) { - elements.add(AppI18n.get("sshKey")); + if (prefs.passwordManager.getValue() != null && prefs.passwordManager.getValue().getKeyConfiguration().useInline()) { + if (r.getSshKey() != null) { + elements.add(AppI18n.get("sshKey")); + } } var formatted = String.join(" / ", elements); diff --git a/app/src/main/java/io/xpipe/app/vnc/ExternalVncClient.java b/app/src/main/java/io/xpipe/app/vnc/ExternalVncClient.java index 44252ae4c..f746437b6 100644 --- a/app/src/main/java/io/xpipe/app/vnc/ExternalVncClient.java +++ b/app/src/main/java/io/xpipe/app/vnc/ExternalVncClient.java @@ -22,7 +22,7 @@ public interface ExternalVncClient extends PrefsValue { if (!client.supportsPasswords() && configuration.hasFixedPassword()) { var pw = configuration.retrievePassword(); if (pw.isPresent()) { - ClipboardHelper.copyPassword(pw.get()); + ClipboardHelper.copyPassword(pw.get(), false); } } diff --git a/app/src/main/resources/io/xpipe/app/resources/style/toggle-switch-comp.css b/app/src/main/resources/io/xpipe/app/resources/style/toggle-switch-comp.css index 7bcd8aa59..c3777b2d6 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/toggle-switch-comp.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/toggle-switch-comp.css @@ -1,5 +1,5 @@ .root:key-navigation .toggle-switch-comp:focused > .thumb-area { - -fx-background-color: -color-neutral-emphasis; + -fx-border-color: -color-accent-emphasis; } .toggle-switch-comp:has-graphic .label { diff --git a/lang/strings/fixed_en.properties b/lang/strings/fixed_en.properties index 27a856fee..85256a3c9 100644 --- a/lang/strings/fixed_en.properties +++ b/lang/strings/fixed_en.properties @@ -164,6 +164,6 @@ neovim=Neovim sms=SMS hashicorpVaultPlaceholder=/path/to/secret:field[,field2] hashicorpVault=Hashicorp Vault -protonPassPasswordPlaceholder= | / +protonPassPasswordPlaceholder=Vault Name/Item name protonPass=Proton Pass diff --git a/lang/strings/translations_en.properties b/lang/strings/translations_en.properties index cd8852643..ca3846f1c 100644 --- a/lang/strings/translations_en.properties +++ b/lang/strings/translations_en.properties @@ -1096,7 +1096,8 @@ connectionInformation=Connection information #context: title connectionInformationDescription=Which system to connect to passwordAuthentication=Password authentication -passwordAuthenticationDescription=The optional password to use to authenticate +#force +passwordAuthenticationDescription=The optional password to use for authentication or sudo sshConfigString.displayName=Config-based SSH connection sshConfigString.displayDescription=Create a customized SSH connection in the SSH config format sshConfigStringContent=Configuration @@ -2054,3 +2055,5 @@ recentQuickConnectionsDescription=Quick connect via string recentUrls=Recent URLs recentUrlsDescription=Quick connect via URLs editContainerUnitFile=Edit container unit file +clipboardNoticeTitle=Password copied +clipboardNoticeContent=Since the target application does not support passing passwords directly, your password has been put into your clipboard for you to paste.