diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java index ddbe6808b..87a3f3e59 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java @@ -22,17 +22,24 @@ import com.jfoenix.controls.JFXDialogLayout; import javafx.scene.control.Label; import javafx.scene.control.ProgressIndicator; import javafx.scene.control.ScrollPane; +import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.construct.DialogCloseEvent; import org.jackhuang.hmcl.ui.construct.JFXHyperlink; import org.jackhuang.hmcl.upgrade.RemoteVersion; +import org.jackhuang.hmcl.util.versioning.VersionNumber; +import org.jetbrains.annotations.Nullable; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; import org.jsoup.nodes.Node; +import org.jsoup.nodes.TextNode; import java.io.IOException; import java.net.URL; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import static org.jackhuang.hmcl.Metadata.CHANGELOG_URL; import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed; @@ -40,6 +47,26 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.logging.Logger.LOG; public final class UpgradeDialog extends JFXDialogLayout { + + private static final Pattern CHANGELOG_TITLE_PATTERN = Pattern.compile("HMCL (?\\d(?:\\.\\d+)+)"); + + private static @Nullable VersionNumber extractVersionNumber(Node node) { + String text; + if (node instanceof Element element) { + text = element.text(); + } else if (node instanceof TextNode textNode) { + text = textNode.text(); + } else { + return null; + } + + Matcher matcher = CHANGELOG_TITLE_PATTERN.matcher(text); + if (matcher.find()) + return VersionNumber.asVersion(matcher.group("version")); + else + return null; + } + public UpgradeDialog(RemoteVersion remoteVersion, Runnable updateRunnable) { maxWidthProperty().bind(Controllers.getScene().widthProperty().multiply(0.7)); maxHeightProperty().bind(Controllers.getScene().heightProperty().multiply(0.7)); @@ -49,7 +76,14 @@ public final class UpgradeDialog extends JFXDialogLayout { String url = CHANGELOG_URL + remoteVersion.getChannel().channelName + ".html"; boolean isPreview = remoteVersion.isPreview(); + Task.supplyAsync(Schedulers.io(), () -> { + VersionNumber targetVersion = VersionNumber.asVersion(remoteVersion.getVersion()); + VersionNumber currentVersion = VersionNumber.asVersion(Metadata.VERSION); + if (targetVersion.compareTo(currentVersion) <= 0) { + return null; + } + Document document = Jsoup.parse(new URL(url), 30 * 1000); String id = null; Node node = null; @@ -65,14 +99,26 @@ public final class UpgradeDialog extends JFXDialogLayout { if (node == null || !"h1".equals(node.nodeName())) throw new IOException("Cannot find current changelog in document"); + VersionNumber changelogVersion = extractVersionNumber(node); + if (changelogVersion == null) + throw new IOException("Cannot find current changelog in document. The node: " + node); + + if (!targetVersion.equals(changelogVersion)) { + LOG.warning("The changelog has not been updated yet. Expected: " + targetVersion + ", Actual: " + changelogVersion); + return null; + } + HTMLRenderer renderer = new HTMLRenderer(uri -> { LOG.info("Open link: " + uri); FXUtils.openLink(uri.toString()); }); do { - if ("h1".equals(node.nodeName()) && !id.equals(node.attr("id"))) { - break; + if ("h1".equals(node.nodeName())) { + changelogVersion = extractVersionNumber(node); + if (changelogVersion == null || changelogVersion.compareTo(currentVersion) <= 0) { + break; + } } renderer.appendNode(node); node = node.nextSibling(); @@ -82,10 +128,14 @@ public final class UpgradeDialog extends JFXDialogLayout { return renderer.render(); }).whenComplete(Schedulers.javafx(), (result, exception) -> { if (exception == null) { - ScrollPane scrollPane = new ScrollPane(result); - scrollPane.setFitToWidth(true); - FXUtils.smoothScrolling(scrollPane); - setBody(scrollPane); + if (result != null) { + ScrollPane scrollPane = new ScrollPane(result); + scrollPane.setFitToWidth(true); + FXUtils.smoothScrolling(scrollPane); + setBody(scrollPane); + } else { + setBody(); + } } else { LOG.warning("Failed to load update log, trying to open it in browser"); FXUtils.openLink(url);