diff --git a/app/src/main/java/io/xpipe/app/browser/action/LeafAction.java b/app/src/main/java/io/xpipe/app/browser/action/LeafAction.java index c5d425066..e0f905ce4 100644 --- a/app/src/main/java/io/xpipe/app/browser/action/LeafAction.java +++ b/app/src/main/java/io/xpipe/app/browser/action/LeafAction.java @@ -24,16 +24,16 @@ public interface LeafAction extends BrowserAction { default Button toButton(Region root, OpenFileSystemModel model, List selected) { var b = new Button(); b.setOnAction(event -> { - if (model == null) { - return; - } - // Only accept shortcut actions in the current tab if (!model.equals(model.getBrowserModel().getSelectedEntry().getValue())) { return; } ThreadHelper.runFailableAsync(() -> { + if (model.getFileSystem() == null) { + return; + } + BooleanScope.executeExclusive(model.getBusy(), () -> { // Start shell in case we exited model.getFileSystem().getShell().orElseThrow().start(); @@ -83,6 +83,10 @@ public interface LeafAction extends BrowserAction { })); mi.setOnAction(event -> { ThreadHelper.runFailableAsync(() -> { + if (model.getFileSystem() == null) { + return; + } + BooleanScope.executeExclusive(model.getBusy(), () -> { // Start shell in case we exited model.getFileSystem().getShell().orElseThrow().start(); diff --git a/app/src/main/java/io/xpipe/app/browser/session/BrowserChooserComp.java b/app/src/main/java/io/xpipe/app/browser/session/BrowserChooserComp.java index d21de2068..9eb4d19ee 100644 --- a/app/src/main/java/io/xpipe/app/browser/session/BrowserChooserComp.java +++ b/app/src/main/java/io/xpipe/app/browser/session/BrowserChooserComp.java @@ -14,6 +14,7 @@ import io.xpipe.app.core.AppLayoutModel; import io.xpipe.app.core.window.AppWindowHelper; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.SimpleComp; +import io.xpipe.app.fxcomps.impl.StackComp; import io.xpipe.app.fxcomps.impl.VerticalComp; import io.xpipe.app.fxcomps.util.BindingsHelper; import io.xpipe.app.fxcomps.util.PlatformThread; @@ -31,6 +32,7 @@ import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; +import javafx.scene.shape.Rectangle; import java.util.List; import java.util.function.BiConsumer; @@ -103,6 +105,17 @@ public class BrowserChooserComp extends SimpleComp { action, bookmarkTopBar.getCategory(), bookmarkTopBar.getFilter()); + var bookmarksContainer = new StackComp(List.of(bookmarksList)).styleClass("bookmarks-container"); + bookmarksContainer + .apply(struc -> { + var rec = new Rectangle(); + rec.widthProperty().bind(struc.get().widthProperty()); + rec.heightProperty().bind(struc.get().heightProperty()); + rec.setArcHeight(7); + rec.setArcWidth(7); + struc.get().getChildren().getFirst().setClip(rec); + }) + .vgrow(); var stack = Comp.of(() -> { var s = new StackPane(); @@ -118,7 +131,7 @@ public class BrowserChooserComp extends SimpleComp { return s; }); - var vertical = new VerticalComp(List.of(bookmarkTopBar, bookmarksList)).styleClass("left"); + var vertical = new VerticalComp(List.of(bookmarkTopBar, bookmarksContainer)).styleClass("left"); var splitPane = new SideSplitPaneComp(vertical, stack) .withInitialWidth(AppLayoutModel.get().getSavedState().getBrowserConnectionsWidth()) .withOnDividerChange(AppLayoutModel.get().getSavedState()::setBrowserConnectionsWidth) @@ -163,6 +176,7 @@ public class BrowserChooserComp extends SimpleComp { var field = new TextField( s.getRawFileEntry().getPath()); field.setEditable(false); + field.getStyleClass().add("chooser-selection"); HBox.setHgrow(field, Priority.ALWAYS); return field; }) diff --git a/app/src/main/java/io/xpipe/app/comp/AppLayoutComp.java b/app/src/main/java/io/xpipe/app/comp/AppLayoutComp.java index 6661ddf39..75eb07a91 100644 --- a/app/src/main/java/io/xpipe/app/comp/AppLayoutComp.java +++ b/app/src/main/java/io/xpipe/app/comp/AppLayoutComp.java @@ -2,6 +2,7 @@ package io.xpipe.app.comp; import io.xpipe.app.comp.base.MultiContentComp; import io.xpipe.app.comp.base.SideMenuBarComp; +import io.xpipe.app.comp.store.StoreViewState; import io.xpipe.app.core.AppFont; import io.xpipe.app.core.AppLayoutModel; import io.xpipe.app.fxcomps.Comp; @@ -52,6 +53,10 @@ public class AppLayoutComp extends Comp> { AppPrefs.get().save(); DataStorage.get().saveAsync(); } + + if (o != null && o.equals(model.getEntries().get(1))) { + StoreViewState.get().updateDisplay(); + } }); pane.addEventHandler(KeyEvent.KEY_PRESSED, event -> { sidebarR.getChildrenUnmodifiable().forEach(node -> { diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryWrapper.java b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryWrapper.java index 6a5cdef10..b521b05c4 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryWrapper.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryWrapper.java @@ -25,6 +25,7 @@ public class StoreEntryWrapper { private final Property name; private final DataStoreEntry entry; private final Property lastAccess; + private final Property lastAccessApplied = new SimpleObjectProperty<>(); private final BooleanProperty disabled = new SimpleBooleanProperty(); private final BooleanProperty busy = new SimpleBooleanProperty(); private final Property validity = new SimpleObjectProperty<>(); @@ -44,6 +45,7 @@ public class StoreEntryWrapper { this.entry = entry; this.name = new SimpleStringProperty(entry.getName()); this.lastAccess = new SimpleObjectProperty<>(entry.getLastAccess().minus(Duration.ofMillis(500))); + this.lastAccessApplied.setValue(lastAccess.getValue()); ActionProvider.ALL.stream() .filter(dataStoreActionProvider -> { return !entry.isDisabled() @@ -62,6 +64,10 @@ public class StoreEntryWrapper { setupListeners(); } + public void applyLastAccess() { + this.lastAccessApplied.setValue(lastAccess.getValue()); + } + public void moveTo(DataStoreCategory category) { ThreadHelper.runAsync(() -> { DataStorage.get().updateCategory(entry, category); diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreSortMode.java b/app/src/main/java/io/xpipe/app/comp/store/StoreSortMode.java index 69fc2b9c8..30db09215 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreSortMode.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreSortMode.java @@ -56,7 +56,7 @@ public interface StoreSortMode { .map(this::representative), Stream.of(s)) .max(Comparator.comparing( - section -> section.getWrapper().getEntry().getLastAccess())) + section -> section.getWrapper().getLastAccessApplied().getValue())) .orElseThrow(); } @@ -68,7 +68,7 @@ public interface StoreSortMode { @Override public Comparator comparator() { return Comparator.comparing(e -> { - return e.getWrapper().getEntry().getLastAccess(); + return e.getWrapper().getLastAccessApplied().getValue(); }); } }; @@ -84,7 +84,7 @@ public interface StoreSortMode { .map(this::representative), Stream.of(s)) .max(Comparator.comparing( - section -> section.getWrapper().getEntry().getLastAccess())) + section -> section.getWrapper().getLastAccessApplied().getValue())) .orElseThrow(); } @@ -96,7 +96,7 @@ public interface StoreSortMode { @Override public Comparator comparator() { return Comparator.comparing(e -> { - return e.getWrapper().getEntry().getLastAccess(); + return e.getWrapper().getLastAccessApplied().getValue(); }) .reversed(); } diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreViewState.java b/app/src/main/java/io/xpipe/app/comp/store/StoreViewState.java index 9dcb38788..110cc51ca 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreViewState.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreViewState.java @@ -121,6 +121,11 @@ public class StoreViewState { .orElseThrow())); } + public void updateDisplay() { + allEntries.getList().forEach(e -> e.applyLastAccess()); + toggleStoreListUpdate(); + } + public void toggleStoreListUpdate() { PlatformThread.runLaterIfNeeded(() -> { entriesListUpdateObservable.set(entriesListUpdateObservable.get() + 1); diff --git a/app/src/main/java/io/xpipe/app/launcher/LauncherCommand.java b/app/src/main/java/io/xpipe/app/launcher/LauncherCommand.java index 0eda2d2fa..e51058109 100644 --- a/app/src/main/java/io/xpipe/app/launcher/LauncherCommand.java +++ b/app/src/main/java/io/xpipe/app/launcher/LauncherCommand.java @@ -17,12 +17,10 @@ import io.xpipe.beacon.api.DaemonOpenExchange; import io.xpipe.core.process.OsType; import io.xpipe.core.util.XPipeDaemonMode; import io.xpipe.core.util.XPipeInstallation; - import lombok.SneakyThrows; import picocli.CommandLine; import java.awt.*; -import java.io.IOException; import java.io.PrintWriter; import java.util.Arrays; import java.util.List; @@ -119,9 +117,9 @@ public class LauncherCommand implements Callable { // there might be another instance running, for example // starting up or listening on another port if (!AppDataLock.lock()) { - throw new IOException( - "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); } } catch (Exception ex) { var cli = XPipeInstallation.getLocalDefaultCliExecutable(); diff --git a/app/src/main/resources/io/xpipe/app/resources/style/bookmark.css b/app/src/main/resources/io/xpipe/app/resources/style/bookmark.css index e34585edd..66eba39ce 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/bookmark.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/bookmark.css @@ -28,8 +28,8 @@ .bookmarks-container { -fx-background-color: -color-border-default, -color-bg-subtle; -fx-background-radius: 4 0 0 4; - -fx-background-insets: 0 8 8 8, 1 9 9 9; - -fx-padding: 1 1 9 9; + -fx-background-insets: 0 7 8 8, 1 8 9 9; + -fx-padding: 1 0 9 9; } .root:pretty .bookmarks-container { @@ -40,5 +40,5 @@ -fx-min-height: 3.5em; -fx-pref-height: 3.5em; -fx-max-height: 3.5em; - -fx-padding: 9 8; + -fx-padding: 9 6 9 8; } diff --git a/app/src/main/resources/io/xpipe/app/resources/style/browser.css b/app/src/main/resources/io/xpipe/app/resources/style/browser.css index 9374639e8..9189e3084 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/browser.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/browser.css @@ -12,7 +12,7 @@ } .transfer { - -fx-padding: 0 8 8 8; + -fx-padding: 0 6 8 8; } .root:pretty .browser .transfer { @@ -178,11 +178,8 @@ -fx-border-color: -color-border-default; } -.chooser-bar { - -fx-border-color: -color-border-default; - -fx-border-width: 1 0 0 0; - -fx-padding: 0.4em 0.7em; - -fx-background-color: -color-neutral-muted; +.browser .chooser-selection { + -fx-background-color: -color-bg-default; } .browser .singular { @@ -257,7 +254,7 @@ .browser .split-pane-divider { -fx-border-color: -color-border-default, -color-bg-inset; - -fx-padding: 0 3; + -fx-padding: 0 2 0 3; -fx-border-width: 2.7em 0 0 0, 2.65em 0 0 0; -fx-opacity: 1.0; -fx-background-color: transparent; diff --git a/core/src/main/java/io/xpipe/core/util/XPipeInstallation.java b/core/src/main/java/io/xpipe/core/util/XPipeInstallation.java index 366eb4fc5..b5557c39a 100644 --- a/core/src/main/java/io/xpipe/core/util/XPipeInstallation.java +++ b/core/src/main/java/io/xpipe/core/util/XPipeInstallation.java @@ -23,7 +23,7 @@ public class XPipeInstallation { .orElse(false); public static int getDefaultBeaconPort() { - var offset = isStaging() ? 2 : 0; + var offset = isStaging() ? 1 : 0; return 21721 + offset; } diff --git a/ext/base/src/main/java/io/xpipe/ext/base/script/RunScriptAction.java b/ext/base/src/main/java/io/xpipe/ext/base/script/RunScriptAction.java index 5a3d15199..f3d8ca2bb 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/script/RunScriptAction.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/script/RunScriptAction.java @@ -55,7 +55,7 @@ public class RunScriptAction implements BrowserAction, BranchAction { continue; } - if (script.assemble(sc) == null) { + if (!script.isCompatible(sc)) { continue; } diff --git a/ext/base/src/main/java/io/xpipe/ext/base/script/SimpleScriptStore.java b/ext/base/src/main/java/io/xpipe/ext/base/script/SimpleScriptStore.java index 924011f09..1896a7328 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/script/SimpleScriptStore.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/script/SimpleScriptStore.java @@ -32,15 +32,20 @@ public class SimpleScriptStore extends ScriptStore implements ShellInitCommand.T private final boolean shellScript; private final boolean fileScript; - public String assemble(ShellControl shellControl) { + public boolean isCompatible(ShellControl shellControl) { var targetType = shellControl.getOriginalShellDialect(); - if (minimumDialect.isCompatibleTo(targetType)) { + return minimumDialect.isCompatibleTo(targetType); + } + + public String assemble(ShellControl shellControl) { + if (isCompatible(shellControl)) { var shebang = commands.startsWith("#"); // Fix new lines and shebang var fixedCommands = commands.lines() .skip(shebang ? 1 : 0) .collect(Collectors.joining( shellControl.getShellDialect().getNewLine().getNewLineString())); + var targetType = shellControl.getOriginalShellDialect(); var script = ScriptHelper.createExecScript(targetType, shellControl, fixedCommands); return targetType.sourceScriptCommand(shellControl, script.toString()); } diff --git a/lang/uacc/strings/translations_da.properties b/lang/uacc/strings/translations_da.properties index 14153bee8..d42a235c0 100644 --- a/lang/uacc/strings/translations_da.properties +++ b/lang/uacc/strings/translations_da.properties @@ -20,7 +20,7 @@ useCommunity=Fortsæt med fællesskab previewDescription=Afprøv nye funktioner i et par uger efter udgivelsen. tryPreview=Aktiver forhåndsvisning af XPipe previewItem1=Fuld adgang til nyligt udgivne professionelle funktioner i 2 uger efter udgivelsen -previewItem2=Indeholder alle funktioner i community-udgaven +previewItem2=Prøv nye funktioner uden nogen forpligtelse licensedTo=Licenseret til #custom email=E-mailadresse diff --git a/lang/uacc/strings/translations_de.properties b/lang/uacc/strings/translations_de.properties index a16c51cf8..9f981451f 100644 --- a/lang/uacc/strings/translations_de.properties +++ b/lang/uacc/strings/translations_de.properties @@ -21,7 +21,7 @@ useCommunity=Weiter mit Community previewDescription=Teste die neuen Funktionen ein paar Wochen lang nach der Veröffentlichung. tryPreview=Aktiviere die XPipe-Vorschau previewItem1=Voller Zugang zu neu veröffentlichten professionellen Funktionen für 2 Wochen nach der Veröffentlichung -previewItem2=Enthält alle Funktionen der Community Edition +previewItem2=Probiere neue Funktionen unverbindlich aus licensedTo=Lizensiert für email=E-Mail Adresse apply=Anwenden diff --git a/lang/uacc/strings/translations_en.properties b/lang/uacc/strings/translations_en.properties index 92aba86d2..c6cdd5243 100644 --- a/lang/uacc/strings/translations_en.properties +++ b/lang/uacc/strings/translations_en.properties @@ -19,7 +19,7 @@ useCommunity=Continue with community previewDescription=Try out new features for a couple of weeks after release. tryPreview=Activate XPipe preview previewItem1=Full access to newly released professional features for 2 weeks after release -previewItem2=Includes all community edition features +previewItem2=Try out new features without any commitment licensedTo=Licensed to email=Email address #context: Apply changes diff --git a/lang/uacc/strings/translations_es.properties b/lang/uacc/strings/translations_es.properties index 671bc1ac8..2e39a95be 100644 --- a/lang/uacc/strings/translations_es.properties +++ b/lang/uacc/strings/translations_es.properties @@ -19,7 +19,7 @@ useCommunity=Continuar con la comunidad previewDescription=Prueba las nuevas funciones durante un par de semanas después del lanzamiento. tryPreview=Activar la vista previa de XPipe previewItem1=Acceso completo a las nuevas funciones profesionales durante 2 semanas después del lanzamiento -previewItem2=Incluye todas las funciones de la edición comunitaria +previewItem2=Prueba nuevas funciones sin compromiso licensedTo=Con licencia email=Dirección de correo electrónico apply=Aplica diff --git a/lang/uacc/strings/translations_fr.properties b/lang/uacc/strings/translations_fr.properties index e57ca4fdb..3a1a6a03f 100644 --- a/lang/uacc/strings/translations_fr.properties +++ b/lang/uacc/strings/translations_fr.properties @@ -19,7 +19,7 @@ useCommunity=Continue avec la communauté previewDescription=Essaie les nouvelles fonctionnalités pendant quelques semaines après leur publication. tryPreview=Activer l'aperçu de XPipe previewItem1=Accès complet aux fonctionnalités professionnelles nouvellement publiées pendant 2 semaines après la sortie de la version -previewItem2=Comprend toutes les fonctionnalités de l'édition communautaire +previewItem2=Essaie les nouvelles fonctions sans t'engager licensedTo=Sous licence email=Adresse électronique apply=Appliquer diff --git a/lang/uacc/strings/translations_it.properties b/lang/uacc/strings/translations_it.properties index 1646462c6..2183db882 100644 --- a/lang/uacc/strings/translations_it.properties +++ b/lang/uacc/strings/translations_it.properties @@ -19,7 +19,7 @@ useCommunity=Continua con la comunità previewDescription=Prova le nuove funzionalità per un paio di settimane dopo il rilascio. tryPreview=Attiva l'anteprima di XPipe previewItem1=Accesso completo alle funzioni professionali appena rilasciate per 2 settimane dal rilascio -previewItem2=Include tutte le funzioni della community edition +previewItem2=Prova nuove funzionalità senza alcun impegno licensedTo=Con licenza di email=Indirizzo e-mail apply=Applicare diff --git a/lang/uacc/strings/translations_ja.properties b/lang/uacc/strings/translations_ja.properties index c44a9e2ea..24a3a1aeb 100644 --- a/lang/uacc/strings/translations_ja.properties +++ b/lang/uacc/strings/translations_ja.properties @@ -19,7 +19,7 @@ useCommunity=コミュニティに続く previewDescription=リリース後数週間は新機能を試す。 tryPreview=XPipeプレビューを有効にする previewItem1=リリース後2週間、新しくリリースされたプロフェッショナル機能にフルアクセスできる -previewItem2=コミュニティ版の全機能を含む +previewItem2=コミットメントなしで新機能を試す licensedTo=ライセンス対象 email=電子メールアドレス apply=適用する diff --git a/lang/uacc/strings/translations_nl.properties b/lang/uacc/strings/translations_nl.properties index b6ada55fe..26512fa8d 100644 --- a/lang/uacc/strings/translations_nl.properties +++ b/lang/uacc/strings/translations_nl.properties @@ -19,7 +19,7 @@ useCommunity=Verder met gemeenschap previewDescription=Probeer nieuwe functies een paar weken na de release uit. tryPreview=XPipe voorvertoning activeren previewItem1=Volledige toegang tot nieuwe professionele functies gedurende 2 weken na de release -previewItem2=Omvat alle community-editie functies +previewItem2=Nieuwe functies uitproberen zonder enige verplichting licensedTo=Gelicentieerd aan email=E-mailadres apply=Toepassen diff --git a/lang/uacc/strings/translations_pt.properties b/lang/uacc/strings/translations_pt.properties index bd5fd4f93..2c0460e30 100644 --- a/lang/uacc/strings/translations_pt.properties +++ b/lang/uacc/strings/translations_pt.properties @@ -19,7 +19,7 @@ useCommunity=Continua com a comunidade previewDescription=Experimenta as novas funcionalidades durante algumas semanas após o lançamento. tryPreview=Ativar a pré-visualização do XPipe previewItem1=Acesso total às novas funcionalidades profissionais durante 2 semanas após o lançamento -previewItem2=Inclui todas as funcionalidades da edição comunitária +previewItem2=Experimenta novas funcionalidades sem qualquer compromisso licensedTo=Licenciado para email=Endereço de correio eletrónico apply=Aplica-te diff --git a/lang/uacc/strings/translations_ru.properties b/lang/uacc/strings/translations_ru.properties index 9395f0b53..3a7574c9a 100644 --- a/lang/uacc/strings/translations_ru.properties +++ b/lang/uacc/strings/translations_ru.properties @@ -19,7 +19,7 @@ useCommunity=Продолжайте общаться previewDescription=Опробуй новые возможности в течение пары недель после релиза. tryPreview=Активировать предварительный просмотр XPipe previewItem1=Полный доступ к новым профессиональным функциям в течение 2 недель после релиза -previewItem2=Включает в себя все возможности community edition +previewItem2=Опробуй новые возможности без каких-либо обязательств licensedTo=Лицензия на email=Адрес электронной почты apply=Применяй diff --git a/lang/uacc/strings/translations_tr.properties b/lang/uacc/strings/translations_tr.properties index 5d2da2716..c7b0b1134 100644 --- a/lang/uacc/strings/translations_tr.properties +++ b/lang/uacc/strings/translations_tr.properties @@ -19,7 +19,7 @@ useCommunity=Topluluk ile devam edin previewDescription=Yayınlandıktan sonra birkaç hafta boyunca yeni özellikleri deneyin. tryPreview=XPipe önizlemesini etkinleştirme previewItem1=Piyasaya sürüldükten sonra 2 hafta boyunca yeni çıkan profesyonel özelliklere tam erişim -previewItem2=Tüm topluluk sürümü özelliklerini içerir +previewItem2=Herhangi bir taahhütte bulunmadan yeni özellikleri deneyin licensedTo=Lisanslı email=E-posta adresi apply=Başvurmak diff --git a/lang/uacc/strings/translations_zh.properties b/lang/uacc/strings/translations_zh.properties index 3f2a0bf67..9234d1e04 100644 --- a/lang/uacc/strings/translations_zh.properties +++ b/lang/uacc/strings/translations_zh.properties @@ -19,7 +19,7 @@ useCommunity=继续社区 previewDescription=新功能发布后试用几周。 tryPreview=激活 XPipe 预览 previewItem1=新发布的专业功能发布后两周内可完全访问 -previewItem2=包括社区版的所有功能 +previewItem2=无需任何承诺即可试用新功能 licensedTo=授权给 email=电子邮件地址 apply=应用 diff --git a/openapi.yaml b/openapi.yaml index ec81c2921..91f40c4a3 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -28,7 +28,7 @@ externalDocs: description: XPipe - Plans and pricing url: https://xpipe.io/pricing servers: - - url: http://localhost:21723 + - url: http://localhost:21721 description: XPipe Daemon API paths: /handshake: diff --git a/version b/version index 84870ec98..ae99ce146 100644 --- a/version +++ b/version @@ -1 +1 @@ -10.0-21 +10.0-22