diff --git a/app/src/main/java/io/xpipe/app/browser/FileBrowserComp.java b/app/src/main/java/io/xpipe/app/browser/FileBrowserComp.java index 526f4e2b..f0710ee4 100644 --- a/app/src/main/java/io/xpipe/app/browser/FileBrowserComp.java +++ b/app/src/main/java/io/xpipe/app/browser/FileBrowserComp.java @@ -38,6 +38,7 @@ public class FileBrowserComp extends SimpleComp { @Override protected Region createSimple() { var bookmarksList = new BookmarkList(model).createRegion(); + VBox.setVgrow(bookmarksList, Priority.ALWAYS); var localDownloadStage = new LocalFileTransferComp(model.getLocalTransfersStage()).hide(Bindings.createBooleanBinding(() -> { if (model.getOpenFileSystems().size() == 0) { return true; diff --git a/app/src/main/java/io/xpipe/app/comp/about/UpdateCheckComp.java b/app/src/main/java/io/xpipe/app/comp/about/UpdateCheckComp.java index bcad935e..db195c7a 100644 --- a/app/src/main/java/io/xpipe/app/comp/about/UpdateCheckComp.java +++ b/app/src/main/java/io/xpipe/app/comp/about/UpdateCheckComp.java @@ -40,20 +40,16 @@ public class UpdateCheckComp extends SimpleComp { } private void restart() { - // Check if we're still on latest - if (!AppUpdater.get().isDownloadedUpdateStillLatest()) { - return; - } - + AppUpdater.get().refreshUpdateCheckSilent(); AppUpdater.get().executeUpdateAndClose(); } - private void update() { + private void download() { AppUpdater.get().downloadUpdateAsync(); } private void refresh() { - AppUpdater.get().checkForUpdateAsync(true); + AppUpdater.get().checkForUpdateAsync(); } private ObservableValue descriptionText() { @@ -131,8 +127,6 @@ public class UpdateCheckComp extends SimpleComp { updateReady)); button.getStyleClass().add("button-comp"); button.setOnAction(e -> { - AppUpdater.get().refreshUpdateState(); - if (updateReady.getValue()) { restart(); return; @@ -142,7 +136,7 @@ public class UpdateCheckComp extends SimpleComp { Hyperlinks.open( AppUpdater.get().getLastUpdateCheckResult().getValue().getReleaseUrl()); } else if (updateAvailable.getValue()) { - update(); + download(); } else { refresh(); } diff --git a/app/src/main/java/io/xpipe/app/issue/TerminalErrorHandler.java b/app/src/main/java/io/xpipe/app/issue/TerminalErrorHandler.java index 133139b2..3d7394c4 100644 --- a/app/src/main/java/io/xpipe/app/issue/TerminalErrorHandler.java +++ b/app/src/main/java/io/xpipe/app/issue/TerminalErrorHandler.java @@ -88,7 +88,7 @@ public class TerminalErrorHandler implements ErrorHandler { private static void handleProbableUpdate() { try { AppUpdater.init(); - var rel = AppUpdater.get().checkForUpdate(true); + var rel = AppUpdater.get().refreshUpdateCheck(); if (rel != null && rel.isUpdate()) { var update = AppWindowHelper.showBlockingAlert(alert -> { alert.setAlertType(Alert.AlertType.INFORMATION); diff --git a/app/src/main/java/io/xpipe/app/update/AppDownloads.java b/app/src/main/java/io/xpipe/app/update/AppDownloads.java index 596f9b1d..86272add 100644 --- a/app/src/main/java/io/xpipe/app/update/AppDownloads.java +++ b/app/src/main/java/io/xpipe/app/update/AppDownloads.java @@ -1,5 +1,6 @@ package io.xpipe.app.update; +import io.xpipe.app.core.AppProperties; import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.issue.TrackEvent; import io.xpipe.app.prefs.AppPrefs; @@ -96,26 +97,41 @@ public class AppDownloads { } } - public static String getLatestVersion(boolean omitErrors) { - return getLatestSuitableRelease(omitErrors) + public static String getLatestVersion() throws IOException { + return getLatestSuitableRelease() .map(ghRelease -> ghRelease.getTagName()) .orElse("?"); } - public static Optional getLatestSuitableRelease(boolean omitErrors) { - try { - var repo = getRepository(); - // Always choose most up-to-date release as we assume that there are only full releases and prereleases - if (AppPrefs.get() != null && AppPrefs.get().updateToPrereleases().get()) { - return Optional.ofNullable(repo.listReleases().iterator().next()); - } + public static Optional getLatestIncludingPreRelease() throws IOException { + var repo = getRepository(); + return Optional.ofNullable(repo.listReleases().iterator().next()); + } - return Optional.ofNullable(repo.getLatestRelease()); - } catch (IOException e) { - ErrorEvent.fromThrowable("Unable to fetch latest release information", e).omitted(omitErrors).handle(); - return Optional.empty(); + public static Optional getLatestRelease() throws IOException { + var repo = getRepository(); + return Optional.ofNullable(repo.getLatestRelease()); + } + + public static Optional getLatestSuitableRelease() throws IOException { + var preIncluding = getLatestIncludingPreRelease(); + + if (AppPrefs.get() != null && AppPrefs.get().updateToPrereleases().get()) { + return preIncluding; } + + // If we are currently running a prerelease, always return this as the suitable release! + if (preIncluding.isPresent() && AppProperties.get().getVersion().equals(preIncluding.get().getTagName())) { + return preIncluding; + } + + // If this release is not a prerelease, just return it to prevent querying another release + if (preIncluding.isPresent() && !preIncluding.get().isPrerelease()) { + return preIncluding; + } + + return getLatestRelease(); } public static Optional getRelease(String version, boolean omitErrors) { diff --git a/app/src/main/java/io/xpipe/app/update/AppUpdater.java b/app/src/main/java/io/xpipe/app/update/AppUpdater.java index f67831c1..0b54de56 100644 --- a/app/src/main/java/io/xpipe/app/update/AppUpdater.java +++ b/app/src/main/java/io/xpipe/app/update/AppUpdater.java @@ -20,6 +20,7 @@ import lombok.With; import lombok.extern.jackson.Jacksonized; import org.kohsuke.github.GHRelease; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; @@ -50,6 +51,8 @@ public class AppUpdater { } downloadedUpdate.setValue(AppCache.get("downloadedUpdate", DownloadedUpdate.class, () -> null)); + + // Check if the original version this was downloaded from is still the same if (downloadedUpdate.getValue() != null && !downloadedUpdate .getValue() @@ -57,6 +60,16 @@ public class AppUpdater { .equals(AppProperties.get().getVersion())) { downloadedUpdate.setValue(null); } + + // Check if somehow the downloaded version is equal to the current one + if (downloadedUpdate.getValue() != null + && downloadedUpdate + .getValue() + .getVersion() + .equals(AppProperties.get().getVersion())) { + downloadedUpdate.setValue(null); + } + if (!XPipeDistributionType.get().supportsUpdate()) { downloadedUpdate.setValue(null); } @@ -64,20 +77,10 @@ public class AppUpdater { downloadedUpdate.addListener((c, o, n) -> { AppCache.update("downloadedUpdate", n); }); - - lastUpdateCheckResult.setValue(AppCache.get("lastUpdateCheckResult", AvailableRelease.class, () -> null)); - if (lastUpdateCheckResult.getValue() != null - && lastUpdateCheckResult.getValue().getSourceVersion() != null - && !lastUpdateCheckResult - .getValue() - .getSourceVersion() - .equals(AppProperties.get().getVersion())) { - lastUpdateCheckResult.setValue(null); - } - event("Last update check result was " + lastUpdateCheckResult.getValue()); lastUpdateCheckResult.addListener((c, o, n) -> { - AppCache.update("lastUpdateCheckResult", n); + downloadedUpdate.setValue(null); }); + refreshUpdateCheckSilent(); } private static void event(String msg) { @@ -94,14 +97,17 @@ public class AppUpdater { } INSTANCE = new AppUpdater(); + startBackgroundUpdater(); + } + private static void startBackgroundUpdater() { if (XPipeDistributionType.get().supportsUpdate() && XPipeDistributionType.get() != XPipeDistributionType.DEVELOPMENT) { ThreadHelper.create("updater", true, () -> { ThreadHelper.sleep(Duration.ofMinutes(10).toMillis()); event("Starting background updater thread"); while (true) { - var rel = INSTANCE.checkForUpdate(false); + var rel = INSTANCE.refreshUpdateCheckSilent(); if (rel != null && AppPrefs.get().automaticallyUpdate().get() && rel.isUpdate()) { event("Performing background update"); @@ -115,7 +121,7 @@ public class AppUpdater { } } - private static boolean isUpdate(String currentVersion) { + private static boolean isUpdate(String releaseVersion) { if (AppPrefs.get() != null && AppPrefs.get().developerMode().getValue() && AppPrefs.get().developerDisableUpdateVersionCheck().get()) { @@ -123,10 +129,7 @@ public class AppUpdater { return true; } - if ( - // true - // || - !AppProperties.get().getVersion().equals(currentVersion)) { + if (!AppProperties.get().getVersion().equals(releaseVersion)) { event("Release has a different version"); return true; } @@ -134,13 +137,6 @@ public class AppUpdater { return false; } - public void refreshUpdateState() { - if (lastUpdateCheckResult.getValue() != null - && !isUpdate(lastUpdateCheckResult.getValue().getVersion())) { - lastUpdateCheckResult.setValue(lastUpdateCheckResult.getValue().withUpdate(false)); - } - } - public void downloadUpdateAsync() { ThreadHelper.runAsync(() -> downloadUpdate()); } @@ -158,6 +154,10 @@ public class AppUpdater { return; } + if (!lastUpdateCheckResult.getValue().isUpdate()) { + return; + } + try (var ignored = new BusyProperty(busy)) { event("Performing update download ..."); try { @@ -184,20 +184,12 @@ public class AppUpdater { } } - private boolean shouldPerformUpdate() { + public void executeUpdateAndClose() { if (busy.getValue()) { - return false; + return; } if (downloadedUpdate.getValue() == null) { - return false; - } - - return true; - } - - public void executeUpdateAndClose() { - if (!shouldPerformUpdate()) { return; } @@ -222,69 +214,57 @@ public class AppUpdater { }); } - public void checkForUpdateAsync(boolean forceCheck) { - ThreadHelper.runAsync(() -> checkForUpdate(forceCheck)); + public void checkForUpdateAsync() { + ThreadHelper.runAsync(() -> refreshUpdateCheckSilent()); } - public synchronized boolean isDownloadedUpdateStillLatest() { - if (downloadedUpdate.getValue() == null) { - return false; + public synchronized AvailableRelease refreshUpdateCheckSilent() { + try { + return refreshUpdateCheck(); + } catch (Exception ex) { + ErrorEvent.fromThrowable(ex).omit().handle(); + return null; } - - var available = checkForUpdate(true); - if (available == null) { - return true; - } - - return downloadedUpdate.getValue() != null - && available.getVersion().equals(downloadedUpdate.getValue().getVersion()); } - public synchronized AvailableRelease checkForUpdate(boolean forceCheck) { + public synchronized AvailableRelease refreshUpdateCheck() throws IOException { if (busy.getValue()) { return lastUpdateCheckResult.getValue(); } - if (!forceCheck - && lastUpdateCheckResult.getValue() != null - && Duration.between(lastUpdateCheckResult.getValue().getCheckTime(), Instant.now()) - .compareTo(Duration.ofHours(1)) - <= 0) { - return lastUpdateCheckResult.getValue(); - } - try (var ignored = new BusyProperty(busy)) { - var rel = AppDownloads.getLatestSuitableRelease(!forceCheck); + var rel = AppDownloads.getLatestSuitableRelease(); event("Determined latest suitable release " + rel.map(GHRelease::getName).orElse(null)); - lastUpdateCheckResult.setValue(null); + if (rel.isEmpty()) { + lastUpdateCheckResult.setValue(null); return null; } - var isUpdate = isUpdate(rel.get().getTagName()); - try { - var assetType = AppInstaller.getSuitablePlatformAsset(); - var ghAsset = rel.orElseThrow().listAssets().toList().stream() - .filter(g -> assetType.isCorrectAsset(g.getName())) - .findAny(); - if (ghAsset.isEmpty()) { - return null; - } - - event("Selected asset " + ghAsset.get().getName()); - lastUpdateCheckResult.setValue(new AvailableRelease( - AppProperties.get().getVersion(), - rel.get().getTagName(), - rel.get().getHtmlUrl().toString(), - ghAsset.get().getBrowserDownloadUrl(), - assetType, - Instant.now(), - isUpdate)); - - } catch (Exception ex) { - ErrorEvent.fromThrowable(ex).omit().handle(); + // Don't update value if result is the same + if (lastUpdateCheckResult.getValue() != null && lastUpdateCheckResult.getValue().getVersion().equals(rel.get().getTagName())) { + return lastUpdateCheckResult.getValue(); } + + var isUpdate = isUpdate(rel.get().getTagName()); + var assetType = AppInstaller.getSuitablePlatformAsset(); + var ghAsset = rel.orElseThrow().listAssets().toList().stream() + .filter(g -> assetType.isCorrectAsset(g.getName())) + .findAny(); + if (ghAsset.isEmpty()) { + return null; + } + + event("Selected asset " + ghAsset.get().getName()); + lastUpdateCheckResult.setValue(new AvailableRelease( + AppProperties.get().getVersion(), + rel.get().getTagName(), + rel.get().getHtmlUrl().toString(), + ghAsset.get().getBrowserDownloadUrl(), + assetType, + Instant.now(), + isUpdate)); } return lastUpdateCheckResult.getValue(); diff --git a/app/src/main/java/io/xpipe/app/update/UpdateAvailableAlert.java b/app/src/main/java/io/xpipe/app/update/UpdateAvailableAlert.java index 34d139f9..aa7289f3 100644 --- a/app/src/main/java/io/xpipe/app/update/UpdateAvailableAlert.java +++ b/app/src/main/java/io/xpipe/app/update/UpdateAvailableAlert.java @@ -18,11 +18,6 @@ public class UpdateAvailableAlert { return; } - if (AppUpdater.get().getDownloadedUpdate().getValue() != null && !AppUpdater.get().isDownloadedUpdateStillLatest()) { - AppUpdater.get().getDownloadedUpdate().setValue(null); - return; - } - var update = AppWindowHelper.showBlockingAlert(alert -> { alert.setTitle(AppI18n.get("updateReadyAlertTitle")); alert.setHeaderText(AppI18n.get("updateReadyAlertHeader", AppUpdater.get().getDownloadedUpdate().getValue().getVersion())); diff --git a/app/src/main/java/io/xpipe/app/util/ProxyManagerProviderImpl.java b/app/src/main/java/io/xpipe/app/util/ProxyManagerProviderImpl.java index 4e73acab..573d8344 100644 --- a/app/src/main/java/io/xpipe/app/util/ProxyManagerProviderImpl.java +++ b/app/src/main/java/io/xpipe/app/util/ProxyManagerProviderImpl.java @@ -32,7 +32,7 @@ public class ProxyManagerProviderImpl extends ProxyManagerProvider { @Override public Optional checkCompatibility(ShellControl s) throws Exception { - var version = ModuleHelper.isImage() ? AppProperties.get().getVersion() : AppDownloads.getLatestVersion(true); + var version = ModuleHelper.isImage() ? AppProperties.get().getVersion() : AppDownloads.getLatestVersion(); if (AppPrefs.get().developerDisableConnectorInstallationVersionCheck().get()) { return Optional.of(AppI18n.get("versionCheckOverride")); @@ -59,7 +59,7 @@ public class ProxyManagerProviderImpl extends ProxyManagerProvider { if (message.isPresent()) { if (showAlert()) { var version = - ModuleHelper.isImage() ? AppProperties.get().getVersion() : AppDownloads.getLatestVersion(true); + ModuleHelper.isImage() ? AppProperties.get().getVersion() : AppDownloads.getLatestVersion(); AppInstaller.installOnRemoteMachine(s, version); return true; } diff --git a/dist/changelogs/0.5.29.md b/dist/changelogs/0.5.29.md new file mode 100644 index 00000000..826e9f12 --- /dev/null +++ b/dist/changelogs/0.5.29.md @@ -0,0 +1,5 @@ +- Introduce new download functionality in the file browser +- Allow for the creation of desktop shortcuts on portable distributions as well +- Fix file sizes sometimes being incorrectly displayed +- Fix background updater downloading the same version +- Fix various small bugs \ No newline at end of file diff --git a/version b/version index dc2c2a78..aa0ea79c 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.5.28 \ No newline at end of file +0.5.29 \ No newline at end of file