Updater rework

This commit is contained in:
crschnick 2024-11-02 23:50:28 +00:00
parent ec6f79a56a
commit 77935c8761
26 changed files with 101 additions and 84 deletions

View file

@ -4,6 +4,8 @@ import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.JsonConfigHelper;
import io.xpipe.core.util.JacksonMapper;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.io.FileUtils;
import java.io.IOException;
@ -13,9 +15,9 @@ import java.util.function.Supplier;
public class AppCache {
private static Path getBasePath() {
return AppProperties.get().getDataDir().resolve("cache");
}
@Getter
@Setter
private static Path basePath;
private static Path getPath(String key) {
var name = key + ".cache";

View file

@ -44,6 +44,8 @@ public class AppProperties {
boolean locatorVersionCheck;
boolean isTest;
boolean autoAcceptEula;
UUID uuid;
boolean initialLaunch;
public AppProperties() {
var appDir = Path.of(System.getProperty("user.dir")).resolve("app");
@ -113,6 +115,15 @@ public class AppProperties {
autoAcceptEula = Optional.ofNullable(System.getProperty("io.xpipe.app.acceptEula"))
.map(Boolean::parseBoolean)
.orElse(false);
AppCache.setBasePath(dataDir.resolve("cache"));
UUID id = AppCache.getNonNull("uuid", UUID.class, null);
if (id == null) {
uuid = UUID.randomUUID();
AppCache.update("uuid", uuid);
} else {
uuid = id;
}
initialLaunch = AppCache.getNonNull("lastBuild", String.class, () -> null) == null;
}
private static boolean isJUnitTest() {

View file

@ -1,48 +0,0 @@
package io.xpipe.app.core;
import lombok.Setter;
import lombok.Value;
import lombok.experimental.NonFinal;
import java.util.UUID;
@Value
public class AppState {
private static AppState INSTANCE;
UUID userId;
boolean initialLaunch;
@NonFinal
@Setter
String userName;
@NonFinal
@Setter
String userEmail;
public AppState() {
UUID id = AppCache.getNonNull("userId", UUID.class, null);
if (id == null) {
initialLaunch = AppCache.getNonNull("lastBuild", String.class, () -> null) == null;
userId = UUID.randomUUID();
AppCache.update("userId", userId);
} else {
userId = id;
initialLaunch = false;
}
}
public static void init() {
if (INSTANCE != null) {
return;
}
INSTANCE = new AppState();
}
public static AppState get() {
return INSTANCE;
}
}

View file

@ -3,7 +3,6 @@ package io.xpipe.app.core.check;
import io.xpipe.app.comp.base.MarkdownComp;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppProperties;
import io.xpipe.app.core.AppState;
import io.xpipe.app.core.AppStyle;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.core.window.AppWindowHelper;
@ -35,7 +34,7 @@ public class AppAvCheck {
public static void check() throws Throwable {
// Only show this on first launch on windows
if (OsType.getLocal() != OsType.WINDOWS || !AppState.get().isInitialLaunch()) {
if (OsType.getLocal() != OsType.WINDOWS || !AppProperties.get().isInitialLaunch()) {
return;
}

View file

@ -105,12 +105,17 @@ public abstract class OperationMode {
return;
}
// Handle any startup uncaught errors
if (OperationMode.isInStartup() && thread.threadId() == 1) {
ex.printStackTrace();
OperationMode.halt(1);
}
ErrorEvent.fromThrowable(ex).unhandled(true).build().handle();
});
TrackEvent.info("Initial setup");
AppProperties.init();
AppState.init();
XPipeSession.init(AppProperties.get().getBuildUuid());
AppUserDirectoryCheck.check();
AppTempCheck.check();

View file

@ -56,7 +56,7 @@ public abstract class PlatformMode extends OperationMode {
// If we downloaded an update, and decided to no longer automatically update, don't remind us!
// You can still update manually in the about tab
if (AppPrefs.get().automaticallyUpdate().get()) {
if (AppPrefs.get().automaticallyUpdate().get() || AppPrefs.get().checkForSecurityUpdates().get()) {
UpdateAvailableAlert.showIfNeeded();
}

View file

@ -11,7 +11,6 @@ public class GuiErrorHandlerBase {
try {
PlatformState.initPlatformOrThrow();
AppProperties.init();
AppState.init();
AppExtensionManager.init(false);
AppI18n.init();
AppStyle.init();

View file

@ -2,7 +2,6 @@ package io.xpipe.app.issue;
import io.xpipe.app.core.AppLogs;
import io.xpipe.app.core.AppProperties;
import io.xpipe.app.core.AppState;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.update.XPipeDistributionType;
@ -145,6 +144,11 @@ public class SentryErrorHandler implements ErrorHandler {
AppPrefs.get() != null
? AppPrefs.get().automaticallyUpdate().getValue().toString()
: "unknown");
s.setTag(
"securityUpdatesEnabled",
AppPrefs.get() != null
? AppPrefs.get().checkForSecurityUpdates().getValue().toString()
: "unknown");
s.setTag("initError", String.valueOf(OperationMode.isInStartup()));
s.setTag(
"developerMode",
@ -177,11 +181,7 @@ public class SentryErrorHandler implements ErrorHandler {
}
var user = new User();
user.setId(AppState.get().getUserId().toString());
if (ee.isShouldSendDiagnostics()) {
user.setEmail(AppState.get().getUserEmail());
user.setUsername(AppState.get().getUserName());
}
user.setId(AppProperties.get().getUuid().toString());
s.setUser(user);
}
@ -189,7 +189,6 @@ public class SentryErrorHandler implements ErrorHandler {
// Assume that this object is wrapped by a synchronous error handler
if (!init) {
AppProperties.init();
AppState.init();
if (AppProperties.get().getSentryUrl() != null) {
Sentry.init(options -> {
options.setDsn(AppProperties.get().getSentryUrl());

View file

@ -40,7 +40,6 @@ public class TerminalErrorHandler extends GuiErrorHandlerBase implements ErrorHa
private void handleGui(ErrorEvent event) {
try {
AppProperties.init();
AppState.init();
AppExtensionManager.init(false);
AppI18n.init();
AppStyle.init();

View file

@ -107,6 +107,8 @@ public class AppPrefs {
.property(new SimpleBooleanProperty(false)).key("enableTerminalLogging").valueClass(Boolean.class).licenseFeatureId("logging").build());
final BooleanProperty enforceWindowModality =
mapLocal(new SimpleBooleanProperty(false), "enforceWindowModality", Boolean.class, false);
final BooleanProperty checkForSecurityUpdates =
mapLocal(new SimpleBooleanProperty(true), "checkForSecurityUpdates", Boolean.class, false);
final BooleanProperty condenseConnectionDisplay =
mapLocal(new SimpleBooleanProperty(false), "condenseConnectionDisplay", Boolean.class, false);
final BooleanProperty showChildCategoriesInParentCategory =
@ -153,6 +155,10 @@ public class AppPrefs {
final BooleanProperty disableApiAuthentication =
mapLocal(new SimpleBooleanProperty(false), "disableApiAuthentication", Boolean.class, false);
public ObservableBooleanValue checkForSecurityUpdates() {
return checkForSecurityUpdates;
}
public ObservableBooleanValue enableTerminalLogging() {
return enableTerminalLogging;
}
@ -510,7 +516,7 @@ public class AppPrefs {
if (rdpClientType.get() == null) {
rdpClientType.setValue(ExternalRdpClientType.determineDefault());
}
if (AppState.get().isInitialLaunch()) {
if (AppProperties.get().isInitialLaunch()) {
performanceMode.setValue(XPipeDistributionType.get() == XPipeDistributionType.WEBTOP);
}
}

View file

@ -15,6 +15,8 @@ public class SecurityCategory extends AppPrefsCategory {
var builder = new OptionsBuilder();
builder.addTitle("securityPolicy")
.sub(new OptionsBuilder()
.pref(prefs.checkForSecurityUpdates)
.addToggle(prefs.checkForSecurityUpdates)
.nameAndDescription("alwaysConfirmElevation")
.addToggle(prefs.alwaysConfirmElevation)
.nameAndDescription("dontCachePasswords")

View file

@ -1,9 +1,12 @@
package io.xpipe.app.update;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import io.xpipe.app.core.AppProperties;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.HttpHelper;
import io.xpipe.core.process.OsType;
import io.xpipe.core.util.JacksonMapper;
import org.apache.commons.io.FileUtils;
@ -15,6 +18,9 @@ import org.kohsuke.github.authorization.AuthorizationProvider;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@ -112,30 +118,42 @@ public class AppDownloads {
}
}
public static Optional<GHRelease> getTopReleaseIncludingPreRelease() throws IOException {
var repo = getRepository();
return Optional.ofNullable(repo.listReleases().iterator().next());
private static String queryLatestVersion() throws Exception {
var req = JsonNodeFactory.instance.objectNode();
req.put("securityOnly", !AppPrefs.get().automaticallyUpdate().get());
req.put("ptb", AppProperties.get().isStaging());
req.put("os", OsType.getLocal().getId());
req.put("arch", AppProperties.get().getArch());
req.put("uuid", AppProperties.get().getUuid().toString());
req.put("version", AppProperties.get().getVersion());
var url = URI.create("https://api.xpipe.io/version");
var builder = HttpRequest.newBuilder();
var httpRequest = builder.uri(url)
.POST(HttpRequest.BodyPublishers.ofString(req.toPrettyString()))
.build();
var client = HttpClient.newHttpClient();
var response = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new IOException(response.body());
}
var json = JacksonMapper.getDefault().readTree(response.body());
var ver = json.required("version").asText();
return ver;
}
public static Optional<GHRelease> getMarkedLatestRelease() throws IOException {
public static Optional<GHRelease> getLatestRelease() throws Exception {
var ver = queryLatestVersion();
var repo = getRepository();
return Optional.ofNullable(repo.getLatestRelease());
var rel = repo.getReleaseByTagName(ver);
return Optional.ofNullable(rel);
}
public static Optional<GHRelease> getLatestSuitableRelease() throws IOException {
public static Optional<GHRelease> getLatestSuitableRelease() throws Exception {
try {
var preIncluding = getTopReleaseIncludingPreRelease();
// If we are currently running a prerelease, always return this as the suitable release!
if (preIncluding.isPresent()
&& preIncluding.get().isPrerelease()
&& AppProperties.get()
.getVersion()
.equals(preIncluding.get().getTagName())) {
return preIncluding;
}
return getMarkedLatestRelease();
} catch (IOException e) {
return getLatestRelease();
} catch (Exception e) {
throw ErrorEvent.expected(e);
}
}

View file

@ -102,7 +102,7 @@ public abstract class UpdateHandler {
ThreadHelper.sleep(Duration.ofMinutes(5).toMillis());
event("Starting background updater thread");
while (true) {
if (AppPrefs.get().automaticallyUpdate().get()) {
if (AppPrefs.get().automaticallyUpdate().get() || AppPrefs.get().checkForSecurityUpdates().get()) {
event("Performing background update");
refreshUpdateCheckSilent();
prepareUpdate();

View file

@ -94,6 +94,7 @@ open module io.xpipe.app {
// For debugging
requires jdk.jdwp.agent;
requires java.net.http;
uses TerminalLauncher;
uses io.xpipe.app.ext.ActionProvider;

View file

@ -545,3 +545,5 @@ scriptsIntroText=Du kan køre scripts ved shell-init, i filbrowseren og efter be
scriptsIntroBottomTitle=Brug af scripts
scriptsIntroBottomText=Der er en række eksempler på scripts til at starte med. Du kan klikke på redigeringsknappen for de enkelte scripts for at se, hvordan de er implementeret. Scripts skal aktiveres for at køre og dukke op i menuer, der er et skifte på hvert script til det.
scriptsIntroStart=Kom godt i gang
checkForSecurityUpdates=Tjek for sikkerhedsopdateringer
checkForSecurityUpdatesDescription=XPipe kan tjekke for potentielle sikkerhedsopdateringer separat fra normale funktionsopdateringer. Når dette er aktiveret, vil i det mindste vigtige sikkerhedsopdateringer blive anbefalet til installation, selv om den normale opdateringskontrol er deaktiveret.\n\nHvis du deaktiverer denne indstilling, vil der ikke blive udført nogen ekstern versionsanmodning, og hun vil ikke få besked om nogen sikkerhedsopdateringer.

View file

@ -539,3 +539,5 @@ scriptsIntroText=Du kannst Skripte bei Shell-Init, im Dateibrowser und bei Bedar
scriptsIntroBottomTitle=Skripte verwenden
scriptsIntroBottomText=Für den Anfang gibt es eine Reihe von Beispielskripten. Du kannst auf die Bearbeitungsschaltfläche der einzelnen Skripte klicken, um zu sehen, wie sie implementiert sind. Skripte müssen aktiviert werden, damit sie ausgeführt und in Menüs angezeigt werden.
scriptsIntroStart=Anfangen
checkForSecurityUpdates=Nach Sicherheitsupdates suchen
checkForSecurityUpdatesDescription=XPipe kann getrennt von den normalen Funktionsupdates auf mögliche Sicherheitsupdates prüfen. Wenn dies aktiviert ist, werden zumindest wichtige Sicherheitsupdates zur Installation empfohlen, auch wenn die normale Updateprüfung deaktiviert ist.\n\nWenn du diese Einstellung deaktivierst, wird keine externe Versionsabfrage durchgeführt und du wirst nicht über Sicherheitsaktualisierungen benachrichtigt.

View file

@ -545,3 +545,5 @@ scriptsIntroText=You can run scripts on shell init, in the file browser, and on
scriptsIntroBottomTitle=Using scripts
scriptsIntroBottomText=There are a variety of sample scripts to start out. You can click on the edit button of the individual scripts to see how they are implemented. Scripts have to be enabled to run and show up in menus, there is a toggle on every script for that.
scriptsIntroStart=Get started
checkForSecurityUpdates=Check for security updates
checkForSecurityUpdatesDescription=XPipe can check for potential security updates separately from normal feature updates. When this is enabled, at least important security updates will be recommended for installation even is the normal update check is disabled.\n\nDisabling this setting will result in no external version request being performed, and she won't be notified about any security updates.

View file

@ -526,3 +526,5 @@ scriptsIntroText=Puedes ejecutar scripts en shell init, en el explorador de arch
scriptsIntroBottomTitle=Utilizar guiones
scriptsIntroBottomText=Hay una variedad de scripts de ejemplo para empezar. Puedes hacer clic en el botón de edición de los scripts individuales para ver cómo se implementan. Los scripts tienen que estar habilitados para ejecutarse y aparecer en los menús, hay un conmutador en cada script para ello.
scriptsIntroStart=Empezar
checkForSecurityUpdates=Buscar actualizaciones de seguridad
checkForSecurityUpdatesDescription=XPipe puede buscar posibles actualizaciones de seguridad separadamente de las actualizaciones normales de funciones. Cuando esta opción está activada, se recomendará la instalación de al menos las actualizaciones de seguridad importantes, aunque la comprobación de actualizaciones normales esté desactivada.\n\nSi desactivas esta opción, no se realizará ninguna solicitud de versión externa y no se le notificará ninguna actualización de seguridad.

View file

@ -526,3 +526,5 @@ scriptsIntroText=Tu peux exécuter des scripts sur le shell init, dans le naviga
scriptsIntroBottomTitle=Utilisation de scripts
scriptsIntroBottomText=Il existe une variété d'exemples de scripts pour commencer. Tu peux cliquer sur le bouton d'édition des scripts individuels pour voir comment ils sont mis en œuvre. Les scripts doivent être activés pour être exécutés et apparaître dans les menus.
scriptsIntroStart=Commence
checkForSecurityUpdates=Vérifier les mises à jour de sécurité
checkForSecurityUpdatesDescription=XPipe peut vérifier les mises à jour de sécurité potentielles séparément des mises à jour normales des fonctionnalités. Lorsque cette fonction est activée, il est recommandé d'installer au moins les mises à jour de sécurité importantes, même si la vérification normale des mises à jour est désactivée.\n\nEn désactivant ce paramètre, aucune demande de version externe ne sera effectuée, et elle ne sera pas informée des mises à jour de sécurité.

View file

@ -526,3 +526,5 @@ scriptsIntroText=Puoi eseguire gli script all'avvio della shell, nel browser dei
scriptsIntroBottomTitle=Utilizzo di script
scriptsIntroBottomText=Ci sono diversi esempi di script per iniziare. Puoi cliccare sul pulsante di modifica dei singoli script per vedere come sono stati implementati. Gli script devono essere abilitati per essere eseguiti e visualizzati nei menu; in ogni script è presente una levetta per questo scopo.
scriptsIntroStart=Iniziare
checkForSecurityUpdates=Controlla gli aggiornamenti di sicurezza
checkForSecurityUpdatesDescription=XPipe può verificare la presenza di potenziali aggiornamenti di sicurezza separatamente dai normali aggiornamenti delle funzioni. Se questa opzione è attivata, l'installazione degli aggiornamenti di sicurezza più importanti viene consigliata anche se il normale controllo degli aggiornamenti è disattivato.\n\nDisattivando questa impostazione, non verrà effettuata alcuna richiesta di versione esterna e non verranno notificati gli aggiornamenti di sicurezza.

View file

@ -526,3 +526,5 @@ scriptsIntroText=シェルinit、ファイルブラウザ、オンデマンド
scriptsIntroBottomTitle=スクリプトを使用する
scriptsIntroBottomText=スクリプトには様々なサンプルが用意されている。個々のスクリプトの編集ボタンをクリックして、どのように実装されているかを見ることができる。スクリプトを実行してメニューに表示するには、スクリプトを有効にする必要がある。
scriptsIntroStart=始める
checkForSecurityUpdates=セキュリティアップデートを確認する
checkForSecurityUpdatesDescription=XPipeは、通常の機能アップデートとは別に、潜在的なセキュリティアップデートをチェックすることができる。これを有効にすると、通常のアップデートチェックが無効になっている場合でも、少なくとも重要なセキュリティアップデートのインストールが推奨される。\n\nこの設定を無効にすると、外部バージョン要求が実行されなくなり、セキュリティアップデートが通知されなくなる。

View file

@ -526,3 +526,5 @@ scriptsIntroText=Je kunt scripts uitvoeren op shell init, in de bestandsbrowser
scriptsIntroBottomTitle=Scripts gebruiken
scriptsIntroBottomText=Er zijn verschillende voorbeeldscripts om mee te beginnen. Je kunt op de bewerkknop van de individuele scripts klikken om te zien hoe ze zijn geïmplementeerd. Scripts moeten worden ingeschakeld om te worden uitgevoerd en om te worden weergegeven in menu's. Elk script heeft daarvoor een schakelaartje.
scriptsIntroStart=Aan de slag
checkForSecurityUpdates=Controleren op beveiligingsupdates
checkForSecurityUpdatesDescription=XPipe kan apart van normale functie-updates controleren op mogelijke beveiligingsupdates. Als dit is ingeschakeld, worden ten minste belangrijke beveiligingsupdates aanbevolen voor installatie, zelfs als de normale updatecontrole is uitgeschakeld.\n\nAls je deze instelling uitschakelt, wordt er geen externe versie opgevraagd en krijg je geen melding van beveiligingsupdates.

View file

@ -526,3 +526,5 @@ scriptsIntroText=Podes executar scripts no shell init, no navegador de ficheiros
scriptsIntroBottomTitle=Utilizar scripts
scriptsIntroBottomText=Há uma variedade de exemplos de scripts para começares. Podes clicar no botão de edição dos scripts individuais para veres como são implementados. Os scripts têm de ser activados para serem executados e aparecerem nos menus; para isso, há uma opção em cada script.
scriptsIntroStart=Começa a trabalhar
checkForSecurityUpdates=Verifica se existem actualizações de segurança
checkForSecurityUpdatesDescription=O XPipe pode verificar potenciais actualizações de segurança separadamente das actualizações de funcionalidades normais. Quando esta opção está activada, pelo menos as actualizações de segurança importantes serão recomendadas para instalação, mesmo que a verificação de atualização normal esteja desactivada.\n\nSe desativar esta definição, não será efectuado qualquer pedido de versão externa e não será notificado sobre quaisquer actualizações de segurança.

View file

@ -526,3 +526,5 @@ scriptsIntroText=Ты можешь запускать скрипты в shell in
scriptsIntroBottomTitle=Использование скриптов
scriptsIntroBottomText=Для начала есть множество примеров скриптов. Ты можешь нажать на кнопку редактирования отдельных скриптов, чтобы посмотреть, как они реализованы. Скрипты должны быть включены, чтобы запускаться и отображаться в меню, для этого в каждом скрипте есть тумблер.
scriptsIntroStart=Приступай к работе
checkForSecurityUpdates=Проверьте наличие обновлений безопасности
checkForSecurityUpdatesDescription=XPipe может проверять потенциальные обновления безопасности отдельно от обычных обновлений функций. Когда эта функция включена, по крайней мере важные обновления безопасности будут рекомендованы к установке, даже если обычная проверка обновлений отключена.\n\nОтключение этой настройки приведет к тому, что внешний запрос версии не будет выполняться, и она не будет получать уведомления о каких-либо обновлениях безопасности.

View file

@ -527,3 +527,5 @@ scriptsIntroText=Komut dosyalarını kabuk başlangıcında, dosya tarayıcısı
scriptsIntroBottomTitle=Komut dosyalarını kullanma
scriptsIntroBottomText=Başlangıç için çeşitli örnek komut dosyaları vardır. Nasıl uygulandıklarını görmek için tek tek komut dosyalarının düzenleme düğmesine tıklayabilirsiniz. Komut dosyalarının çalışması ve menülerde görünmesi için etkinleştirilmesi gerekir, bunun için her komut dosyasında bir geçiş vardır.
scriptsIntroStart=Başlayın
checkForSecurityUpdates=Güvenlik güncellemelerini kontrol edin
checkForSecurityUpdatesDescription=XPipe olası güvenlik güncellemelerini normal özellik güncellemelerinden ayrı olarak kontrol edebilir. Bu etkinleştirildiğinde, normal güncelleme denetimi devre dışı bırakılsa bile en azından önemli güvenlik güncellemeleri yükleme için önerilecektir.\n\nBu ayarın devre dışı bırakılması, harici sürüm talebinin gerçekleştirilmemesine ve herhangi bir güvenlik güncellemesi hakkında bilgilendirilmemesine neden olacaktır.

View file

@ -526,3 +526,5 @@ scriptsIntroText=您可以在 shell init、文件浏览器和按需运行脚本
scriptsIntroBottomTitle=使用脚本
scriptsIntroBottomText=这里有各种示例脚本供您开始使用。你可以点击各个脚本的编辑按钮,查看它们是如何实现的。脚本必须启用才能运行并显示在菜单中,每个脚本上都有一个切换按钮。
scriptsIntroStart=开始使用
checkForSecurityUpdates=检查安全更新
checkForSecurityUpdatesDescription=XPipe 可与正常功能更新分开检查潜在的安全更新。启用此功能后,即使正常的更新检查被禁用,至少也会推荐安装重要的安全更新。\n\n禁用此设置将导致不执行外部版本请求也不会通知她任何安全更新。