Various fixes

This commit is contained in:
crschnick
2024-12-27 22:54:19 +00:00
parent e67e9ceb25
commit 345cc8f404
26 changed files with 157 additions and 21 deletions
@@ -29,10 +29,7 @@ import atlantafx.base.theme.Styles;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Objects;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import static io.xpipe.app.util.HumanReadableFormat.byteCount;
@@ -283,12 +280,20 @@ public final class BrowserFileListComp extends SimpleComp {
}
try (var ignored = updateFromModel) {
fileList.getSelection().setAll(c.getList());
// Attempt to preserve ordering. Works at least when selecting single entries
var existing = new HashSet<>(fileList.getSelection());
c.getList().forEach(browserEntry -> {
if (!existing.contains(browserEntry)) {
fileList.getSelection().add(browserEntry);
}
});
}
});
fileList.getSelection().addListener((ListChangeListener<? super BrowserEntry>) c -> {
if (c.getList().equals(table.getSelectionModel().getSelectedItems())) {
var existing = new HashSet<>(fileList.getSelection());
var toApply = new HashSet<>(c.getList());
if (existing.equals(toApply)) {
return;
}
@@ -97,7 +97,9 @@ public abstract class Comp<S extends CompStructure<?>> {
onSceneAssign(struc -> {
Platform.runLater(() -> {
Platform.runLater(() -> {
struc.get().requestFocus();
Platform.runLater(() -> {
struc.get().requestFocus();
});
});
});
});
@@ -48,7 +48,7 @@ public class AppMainWindowContentComp extends SimpleComp {
loadingIcon.setImage(AppImages.loadImage(path.resolve("loading.png")));
});
var version = new LabelComp("XPipe " + AppProperties.get().getVersion());
var version = new LabelComp((AppProperties.get().isStaging() ? "XPipe PTB" : "XPipe") + " " + AppProperties.get().getVersion());
version.apply(struc -> {
AppFont.setSize(struc.get(), 1);
struc.get().setOpacity(0.6);
@@ -178,11 +178,13 @@ public abstract class StoreEntryComp extends SimpleComp {
protected Comp<?> createUserIcon() {
var button = new IconButtonComp("mdi2a-account");
button.disable(new SimpleBooleanProperty(true));
button.hide(Bindings.createBooleanBinding(() -> {
var cat = getWrapper().getCategory().getValue();
return cat.getRoot().equals(StoreViewState.get().getAllIdentitiesCategory()) || !getWrapper().getEntry().isPerUserStore();
},getWrapper().getStore()));
button.styleClass("user-icon");
button.tooltipKey("personalConnection");
button.apply(struc -> {
AppFont.medium(struc.get());
struc.get().setOpacity(1.0);
});
button.hide(getWrapper().getPerUser());
return button;
}
@@ -52,6 +52,7 @@ public class StoreEntryWrapper {
private final BooleanProperty sessionActive = new SimpleBooleanProperty();
private final Property<DataStore> store = new SimpleObjectProperty<>();
private final Property<String> information = new SimpleStringProperty();
private final BooleanProperty perUser = new SimpleBooleanProperty();
public StoreEntryWrapper(DataStoreEntry entry) {
this.entry = entry;
@@ -183,6 +184,7 @@ public class StoreEntryWrapper {
.getCategoryWrapper(DataStorage.get()
.getStoreCategoryIfPresent(entry.getCategoryUuid())
.orElseThrow()));
perUser.setValue(!category.getValue().getRoot().equals(StoreViewState.get().getAllIdentitiesCategory()) && entry.isPerUserStore());
if (!entry.getValidity().isUsable()) {
summary.setValue(null);
@@ -191,6 +191,10 @@ public class StoreSectionComp extends Comp<CompStructure<VBox>> {
}
struc.get().getStyleClass().setAll(newList);
});
section.getWrapper().getPerUser().subscribe(val -> {
struc.get().pseudoClassStateChanged(PseudoClass.getPseudoClass("per-user"), val);
});
})
.createStructure();
}
@@ -29,7 +29,11 @@ public class ShellSession extends Session {
try {
shellControl.start();
} catch (Exception ex) {
stop();
try {
stop();
} catch (Exception stopEx) {
ex.addSuppressed(stopEx);
}
throw ex;
}
}
@@ -42,7 +42,7 @@ public class AppPrefsSidebarComp extends SimpleComp {
})
.collect(Collectors.toCollection(ArrayList::new));
var restartButton = new ButtonComp(AppI18n.observable("restart"), new FontIcon("mdi2r-restart"), () -> {
var restartButton = new ButtonComp(AppI18n.observable("restartApp"), new FontIcon("mdi2r-restart"), () -> {
OperationMode.restart();
});
restartButton.grow(true, false);
@@ -32,6 +32,10 @@
-fx-text-fill: #851908;
}
.store-entry-grid .user-icon .ikonli-font-icon {
-fx-icon-color: #5b2cffff;
}
.store-entry-grid:incomplete .icon {
-fx-opacity: 0.5;
}
@@ -163,6 +167,10 @@
-fx-spacing: 0.2em;
}
.root .store-entry-section-comp.color-box.vertical-comp:per-user {
-fx-border-color: #5b2cffcc;
}
/* Light sub backgrounds */
.root:light .store-entry-section-comp:sub:expanded {
@@ -53,7 +53,6 @@ public interface NetworkTunnelStore extends DataStore {
sessions.isEmpty() ? remotePort : sessions.getLast().getLocalPort();
var t = current.createTunnelSession(
currentLocalPort, currentRemotePort, current == this ? address : "localhost");
t.start();
sessions.add(t);
} while ((current = (NetworkTunnelStore) current.getNetworkParent()) != null);
@@ -33,15 +33,40 @@ public class SessionChain extends NetworkTunnelSession {
@Override
public void start() throws Exception {
for (Session session : sessions) {
session.start();
for (var i = 0; i < sessions.size(); i++) {
try {
sessions.get(i).start();
} catch (Exception e) {
for (var j = 0; j < i; j++) {
var started = sessions.get(j);
try {
started.stop();
} catch (Exception stopEx) {
e.addSuppressed(stopEx);
}
}
throw e;
}
}
}
@Override
public void stop() throws Exception {
for (Session session : sessions) {
session.stop();
Exception ex = null;
for (var i = sessions.size() - 1; i >= 0; i--) {
try {
sessions.get(i).stop();
} catch (Exception e) {
if (ex == null) {
ex = e;
} else {
ex.addSuppressed(e);
}
}
}
if (ex != null) {
throw ex;
}
}
}
+6
View File
@@ -1247,9 +1247,15 @@ activate=Aktiver
validUntil=Gyldig indtil
licenseActivated=Licens aktiveret
restart=Genstart
restartApp=Genstart XPipe
free=Gratis
upgradeInfo=Du kan finde oplysninger om opgradering til en professionel licens nedenfor.
upgradeInfoPreview=Du kan finde oplysninger om opgradering til en professionel licens nedenfor eller prøve forhåndsvisningen.
enterLicenseKey=Indtast licensnøgle for at opgradere
isOnlySupported=understøttes kun med mindst en $TYPE$ -licens
areOnlySupported=understøttes kun med mindst en $TYPE$ -licens
openApiDocs=API-dokumentation
openApiDocsDescription=HTTP API-dokumentationen følger med XPipe, inklusive en OpenAPI .yaml-specifikation. Du kan åbne den i din webbrowser.
openApiDocsButton=Åbn dokumenter
pythonApi=Python API
personalConnection=Denne forbindelse og alle dens børn er kun tilgængelige for din bruger, da de afhænger af en personlig identitet.
+6
View File
@@ -1227,9 +1227,15 @@ activate=Aktivieren
validUntil=Gültig bis
licenseActivated=Lizenz aktiviert
restart=Neustart
restartApp=XPipe neu starten
free=Kostenlos
upgradeInfo=Informationen zum Upgrade auf eine professionelle Lizenz findest du weiter unten.
upgradeInfoPreview=Informationen zum Upgrade auf eine professionelle Lizenz findest du weiter unten oder du kannst die Vorschau ausprobieren.
enterLicenseKey=Lizenzschlüssel für das Upgrade eingeben
isOnlySupported=wird nur mit mindestens einer $TYPE$ Lizenz unterstützt
areOnlySupported=werden nur mit mindestens einer $TYPE$ Lizenz unterstützt
openApiDocs=API-Dokumentation
openApiDocsDescription=Die HTTP-API-Dokumentation ist im Lieferumfang von XPipe enthalten, einschließlich einer OpenAPI .yaml-Spezifikation. Du kannst sie in deinem Webbrowser öffnen.
openApiDocsButton=Docs öffnen
pythonApi=Python-API
personalConnection=Diese Verbindung und alle ihre Kinder sind nur für deinen Nutzer verfügbar, da sie von einer persönlichen Identität abhängen.
+2 -1
View File
@@ -1247,6 +1247,7 @@ activate=Activate
validUntil=Valid until
licenseActivated=License activated
restart=Restart
restartApp=Restart XPipe
#context: No payment required
free=Free
upgradeInfo=You can find information about upgrading to a professional license below.
@@ -1258,4 +1259,4 @@ openApiDocs=API documentation
openApiDocsDescription=The HTTP API documentation is bundled with XPipe, including an OpenAPI .yaml specification. You can open it in your web browser.
openApiDocsButton=Open docs
pythonApi=Python API
personalConnection=This connection and all its children are only available to your user as they depend on a personal identity.
+6
View File
@@ -1198,9 +1198,15 @@ activate=Activa
validUntil=Válido hasta
licenseActivated=Licencia activada
restart=Reinicia
restartApp=Reiniciar XPipe
free=Gratis
upgradeInfo=A continuación encontrarás información sobre cómo obtener una licencia profesional.
upgradeInfoPreview=A continuación puedes encontrar información sobre cómo pasar a una licencia profesional o probar la vista previa.
enterLicenseKey=Introduce la clave de licencia para actualizar
isOnlySupported=sólo es compatible al menos con la licencia $TYPE$
areOnlySupported=sólo se admiten con una licencia de al menos $TYPE$
openApiDocs=Documentación API
openApiDocsDescription=La documentación de la API HTTP se incluye con XPipe, incluida una especificación OpenAPI .yaml. Puedes abrirla en tu navegador web.
openApiDocsButton=Abrir documentos
pythonApi=API de Python
personalConnection=Esta conexión y todos sus hijos sólo están disponibles para tu usuario, ya que dependen de una identidad personal.
+6
View File
@@ -1233,9 +1233,15 @@ activate=Activer
validUntil=Valable jusqu'au
licenseActivated=Licence activée
restart=Redémarrer
restartApp=Redémarrer XPipe
free=Gratuit
upgradeInfo=Tu trouveras ci-dessous des informations sur la mise à niveau vers une licence professionnelle.
upgradeInfoPreview=Tu peux trouver des informations sur la mise à niveau vers une licence professionnelle ci-dessous ou essayer l'aperçu.
enterLicenseKey=Saisis la clé de licence pour la mise à niveau
isOnlySupported=n'est pris en charge qu'avec au moins une licence $TYPE$
areOnlySupported=ne sont pris en charge qu'avec au moins une licence $TYPE$
openApiDocs=Documentation de l'API
openApiDocsDescription=La documentation de l'API HTTP est fournie avec XPipe, y compris une spécification OpenAPI .yaml. Tu peux l'ouvrir dans ton navigateur web.
openApiDocsButton=Open docs
pythonApi=API Python
personalConnection=Cette connexion et tous ses enfants ne sont disponibles que pour ton utilisateur car ils dépendent d'une identité personnelle.
+6
View File
@@ -1198,9 +1198,15 @@ activate=Mengaktifkan
validUntil=Berlaku hingga
licenseActivated=Lisensi diaktifkan
restart=Mulai ulang
restartApp=Mulai ulang XPipe
free=Gratis
upgradeInfo=Anda dapat menemukan informasi tentang meningkatkan ke lisensi profesional di bawah ini.
upgradeInfoPreview=Anda dapat menemukan informasi tentang meningkatkan ke lisensi profesional di bawah ini atau mencoba pratinjau.
enterLicenseKey=Masukkan kunci lisensi untuk meningkatkan
isOnlySupported=hanya didukung dengan setidaknya lisensi $TYPE$
areOnlySupported=hanya didukung dengan setidaknya lisensi $TYPE$
openApiDocs=Dokumentasi API
openApiDocsDescription=Dokumentasi API HTTP dibundel dengan XPipe, termasuk spesifikasi OpenAPI .yaml. Anda dapat membukanya di browser web Anda.
openApiDocsButton=Buka dokumen
pythonApi=API Python
personalConnection=Sambungan ini dan semua anak sambungannya hanya tersedia untuk pengguna Anda karena bergantung pada identitas pribadi.
+6
View File
@@ -1198,9 +1198,15 @@ activate=Attivare
validUntil=Valido fino a
licenseActivated=Licenza attivata
restart=Riavvio
restartApp=Riavviare XPipe
free=Gratuito
upgradeInfo=Qui di seguito puoi trovare informazioni sull'aggiornamento a una licenza professionale.
upgradeInfoPreview=Puoi trovare informazioni sull'aggiornamento a una licenza professionale qui sotto o provare l'anteprima.
enterLicenseKey=Inserisci la chiave di licenza per aggiornare
isOnlySupported=è supportato solo con almeno una licenza $TYPE$
areOnlySupported=sono supportati solo con una licenza di almeno $TYPE$
openApiDocs=Documentazione API
openApiDocsDescription=La documentazione dell'API HTTP viene fornita con XPipe e include una specifica OpenAPI .yaml. Puoi aprirla nel tuo browser web.
openApiDocsButton=Documenti aperti
pythonApi=API Python
personalConnection=Questa connessione e tutti i suoi figli sono disponibili solo per il tuo utente in quanto dipendono da un'identità personale.
+6
View File
@@ -1198,9 +1198,15 @@ activate=アクティブにする
validUntil=有効期限
licenseActivated=ライセンスの有効化
restart=再起動
restartApp=XPipeを再起動する
free=無料
upgradeInfo=プロフェッショナル・ライセンスへのアップグレードに関する情報は以下を参照のこと。
upgradeInfoPreview=プロフェッショナル・ライセンスへのアップグレードについては、下記を参照するか、プレビューをお試しいただきたい。
enterLicenseKey=ライセンスキーを入力してアップグレードする
isOnlySupported=は、少なくとも$TYPE$ ライセンスでのみサポートされる。
areOnlySupported=は、少なくとも$TYPE$ ライセンスでのみサポートされる。
openApiDocs=APIドキュメント
openApiDocsDescription=XPipeには、OpenAPI .yaml仕様を含むHTTP APIドキュメントがバンドルされている。ウェブブラウザで開くことができる。
openApiDocsButton=ドキュメントを開く
pythonApi=Python API
personalConnection=この接続とそのすべての子は、個人のIDに依存するため、あなたのユーザーのみが利用できる。
+6
View File
@@ -1198,9 +1198,15 @@ activate=Activeer
validUntil=Geldig tot
licenseActivated=Licentie geactiveerd
restart=Herstart
restartApp=XPipe opnieuw opstarten
free=Gratis
upgradeInfo=Informatie over upgraden naar een professionele licentie vind je hieronder.
upgradeInfoPreview=Je kunt hieronder informatie vinden over het upgraden naar een professionele licentie of de preview uitproberen.
enterLicenseKey=Licentiesleutel invoeren om te upgraden
isOnlySupported=wordt alleen ondersteund met minimaal een $TYPE$ licentie
areOnlySupported=worden alleen ondersteund met minimaal een $TYPE$ licentie
openApiDocs=API-documentatie
openApiDocsDescription=De HTTP API documentatie is gebundeld met XPipe, inclusief een OpenAPI .yaml specificatie. Je kunt deze openen in je webbrowser.
openApiDocsButton=Open documenten
pythonApi=Python API
personalConnection=Deze verbinding en al haar kinderen zijn alleen beschikbaar voor jouw gebruiker omdat ze afhankelijk zijn van een persoonlijke identiteit.
+6
View File
@@ -1198,9 +1198,15 @@ activate=Aktywuj
validUntil=Ważny do
licenseActivated=Aktywowana licencja
restart=Restart
restartApp=Uruchom ponownie XPipe
free=Darmowy
upgradeInfo=Poniżej znajdziesz informacje na temat uaktualnienia do licencji profesjonalnej.
upgradeInfoPreview=Poniżej znajdziesz informacje na temat uaktualnienia do licencji profesjonalnej lub wypróbowania wersji zapoznawczej.
enterLicenseKey=Wprowadź klucz licencyjny do aktualizacji
isOnlySupported=jest obsługiwany tylko z licencją $TYPE$
areOnlySupported=są obsługiwane tylko z co najmniej licencją $TYPE$
openApiDocs=Dokumentacja API
openApiDocsDescription=Dokumentacja API HTTP jest dołączona do XPipe, w tym specyfikacja OpenAPI .yaml. Możesz ją otworzyć w przeglądarce internetowej.
openApiDocsButton=Otwórz dokumenty
pythonApi=API Python
personalConnection=To połączenie i wszystkie jego elementy podrzędne są dostępne tylko dla Twojego użytkownika, ponieważ zależą od tożsamości osobistej.
+6
View File
@@ -1198,9 +1198,15 @@ activate=Ativar
validUntil=Válido até
licenseActivated=Licença activada
restart=Reinicia
restartApp=Reinicia o XPipe
free=Gratuito
upgradeInfo=Podes encontrar informações sobre a atualização para uma licença profissional abaixo.
upgradeInfoPreview=Podes encontrar informações sobre a atualização para uma licença profissional abaixo ou experimentar a pré-visualização.
enterLicenseKey=Introduzir a chave de licença para atualizar
isOnlySupported=só é suportado com, pelo menos, uma licença $TYPE$
areOnlySupported=só são suportados com, pelo menos, uma licença $TYPE$
openApiDocs=Documentação API
openApiDocsDescription=A documentação da API HTTP é fornecida com o XPipe, incluindo uma especificação OpenAPI .yaml. Podes abri-la no teu navegador web.
openApiDocsButton=Abre documentos
pythonApi=API Python
personalConnection=Esta ligação e todos os seus filhos só estão disponíveis para o teu utilizador, uma vez que dependem de uma identidade pessoal.
+6
View File
@@ -1198,9 +1198,15 @@ activate=Активируй
validUntil=Действует до
licenseActivated=Лицензия активирована
restart=Перезапустите
restartApp=Перезапустить XPipe
free=Бесплатно
upgradeInfo=Информацию о переходе на профессиональную лицензию ты найдешь ниже.
upgradeInfoPreview=Ниже ты можешь найти информацию о переходе на профессиональную лицензию или попробовать предварительный просмотр.
enterLicenseKey=Введите лицензионный ключ для обновления
isOnlySupported=поддерживается только при наличии лицензии $TYPE$
areOnlySupported=поддерживаются только при наличии лицензии $TYPE$
openApiDocs=Документация по API
openApiDocsDescription=В комплекте с XPipe идет документация по HTTP API, включая спецификацию OpenAPI в формате .yaml. Ты можешь открыть ее в своем веб-браузере.
openApiDocsButton=Открытые документы
pythonApi=Python API
personalConnection=Это соединение и все его дочерние элементы доступны только твоему пользователю, так как зависят от персональной идентификации.
+6
View File
@@ -1198,9 +1198,15 @@ activate=Aktivera
validUntil=Giltig till
licenseActivated=Licens aktiverad
restart=Starta om
restartApp=Starta om XPipe
free=Gratis
upgradeInfo=Du hittar information om uppgradering till en professionell licens nedan.
upgradeInfoPreview=Du kan hitta information om uppgradering till en professionell licens nedan eller prova förhandsgranskningen.
enterLicenseKey=Ange licensnyckel för att uppgradera
isOnlySupported=stöds endast med minst en $TYPE$ -licens
areOnlySupported=stöds endast med minst en $TYPE$ -licens
openApiDocs=API-dokumentation
openApiDocsDescription=HTTP API-dokumentationen levereras tillsammans med XPipe, inklusive en OpenAPI .yaml-specifikation. Du kan öppna den i din webbläsare.
openApiDocsButton=Öppna dokument
pythonApi=Python API
personalConnection=Denna anslutning och alla dess barn är endast tillgängliga för din användare eftersom de är beroende av en personlig identitet.
+6
View File
@@ -1198,9 +1198,15 @@ activate=Etkinleştir
validUntil=Şu tarihe kadar geçerlidir
licenseActivated=Lisans etkinleştirildi
restart=Yeniden Başlat
restartApp=XPipe'ı yeniden başlatın
free=Ücretsiz
upgradeInfo=Profesyonel lisansa yükseltme ile ilgili bilgileri aşağıda bulabilirsiniz.
upgradeInfoPreview=Aşağıda profesyonel lisansa yükseltme hakkında bilgi bulabilir veya önizlemeyi deneyebilirsiniz.
enterLicenseKey=Yükseltmek için lisans anahtarını girin
isOnlySupported=yalnızca en az $TYPE$ lisansı ile desteklenir
areOnlySupported=yalnızca en az bir $TYPE$ lisansı ile desteklenir
openApiDocs=API belgeleri
openApiDocsDescription=HTTP API belgeleri, OpenAPI .yaml belirtimi de dahil olmak üzere XPipe ile birlikte gelir. Web tarayıcınızda açabilirsiniz.
openApiDocsButton=Açık dokümanlar
pythonApi=Python API
personalConnection=Bu bağlantı ve tüm çocukları, kişisel bir kimliğe bağlı oldukları için yalnızca kullanıcınız tarafından kullanılabilir.
+6
View File
@@ -1198,9 +1198,15 @@ activate=激活
validUntil=有效期至
licenseActivated=许可证已激活
restart=重新启动
restartApp=重新启动 XPipe
free=免费
upgradeInfo=您可以在下面找到有关升级到专业许可证的信息。
upgradeInfoPreview=您可以在下面找到有关升级到专业许可证的信息,或试用预览版。
enterLicenseKey=输入许可证密钥进行升级
isOnlySupported=至少要有$TYPE$ 许可证才支持
areOnlySupported=至少需要$TYPE$ 许可证才能支持
openApiDocs=API 文档
openApiDocsDescription=XPipe 中捆绑了 HTTP API 文档,包括 OpenAPI .yaml 规范。您可以在网络浏览器中打开它。
openApiDocsButton=打开文档
pythonApi=Python API
personalConnection=此连接及其所有子连接仅对您的用户开放,因为它们取决于个人身份。