mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-21 23:20:23 +00:00
Rework updater to fix some bugs [release]
This commit is contained in:
parent
5444bc785f
commit
b1f2272fc2
9 changed files with 104 additions and 113 deletions
|
@ -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;
|
||||
|
|
|
@ -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<String> 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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<GHRelease> 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<GHRelease> 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<GHRelease> getLatestRelease() throws IOException {
|
||||
var repo = getRepository();
|
||||
return Optional.ofNullable(repo.getLatestRelease());
|
||||
}
|
||||
|
||||
public static Optional<GHRelease> 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<GHRelease> getRelease(String version, boolean omitErrors) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -32,7 +32,7 @@ public class ProxyManagerProviderImpl extends ProxyManagerProvider {
|
|||
|
||||
@Override
|
||||
public Optional<String> 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;
|
||||
}
|
||||
|
|
5
dist/changelogs/0.5.29.md
vendored
Normal file
5
dist/changelogs/0.5.29.md
vendored
Normal file
|
@ -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
|
2
version
2
version
|
@ -1 +1 @@
|
|||
0.5.28
|
||||
0.5.29
|
Loading…
Reference in a new issue