Skip to content
12 changes: 12 additions & 0 deletions HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import org.jackhuang.hmcl.ui.versions.GameListPage;
import org.jackhuang.hmcl.ui.versions.VersionPage;
import org.jackhuang.hmcl.ui.versions.Versions;
import org.jackhuang.hmcl.upgrade.UpdateChecker;
import org.jackhuang.hmcl.util.*;
import org.jackhuang.hmcl.util.i18n.I18n;
import org.jackhuang.hmcl.util.i18n.SupportedLocale;
Expand Down Expand Up @@ -331,6 +332,12 @@ public static void initialize(Stage stage) {
stage.setOnCloseRequest(e -> Launcher.stopApplication());

decorator = new DecoratorController(stage, getRootPage());
getRootPage().getMainPage().showUpdateProperty().bind(UpdateChecker.checkingUpdateProperty().not().and(UpdateChecker.outdatedProperty()));
getRootPage().getMainPage().showUpdateDialogProperty().bind(
decorator.backableProperty().not()
.and(getRootPage().getMainPage().showUpdateProperty())
.and(config().disableAutoShowUpdateDialogProperty().not())
);

if (config().getCommonDirType() == EnumCommonDirectory.CUSTOM &&
!FileUtils.canCreateDirectory(config().getCommonDirectory())) {
Expand Down Expand Up @@ -563,6 +570,11 @@ public static void confirmWithCountdown(String text, String title, int seconds,
timeline.play();
}

public static void dialogLater(Region content) {
if (decorator != null)
decorator.showDialogLater(content);
}

public static CompletableFuture<String> prompt(String title, FutureCallback<String> onResult) {
return prompt(title, onResult, "");
}
Expand Down
38 changes: 38 additions & 0 deletions HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
import org.jackhuang.hmcl.ui.decorator.Decorator;
import org.jetbrains.annotations.Nullable;

import java.util.LinkedList;
import java.util.Optional;
import java.util.Queue;
import java.util.function.Consumer;

public final class DialogUtils {
Expand All @@ -45,6 +47,8 @@ private DialogUtils() {
public static final String PROPERTY_PARENT_PANE_REF = DialogUtils.class.getName() + ".dialog.parentPaneRef";
public static final String PROPERTY_PARENT_DIALOG_REF = DialogUtils.class.getName() + ".dialog.parentDialogRef";

public static final String PROPERTY_DIALOG_SHOW_LATER = DialogUtils.class.getName() + ".dialog.showLater";

public static void show(Decorator decorator, Node content) {
if (decorator.getDrawerWrapper() == null) {
Platform.runLater(() -> show(decorator, content));
Expand Down Expand Up @@ -121,6 +125,30 @@ public void changed(ObservableValue<? extends Boolean> observable, Boolean oldVa
}
}

public static void showLater(Decorator decorator, Node content) {
if (decorator.getDrawerWrapper() == null) {
Platform.runLater(() -> showLater(decorator, content));
return;
}
showLater(decorator.getDrawerWrapper(), () -> show(decorator, content));
}

@SuppressWarnings("unchecked")
public static void showLater(StackPane container, Runnable showDialogAction) {
FXUtils.checkFxUserThread();

if (container.getProperties().get(PROPERTY_DIALOG_INSTANCE) == null) {
showDialogAction.run();
return;
}
Queue<Runnable> queue = (Queue<Runnable>) container.getProperties().get(PROPERTY_DIALOG_SHOW_LATER);
if (queue == null) {
queue = new LinkedList<>();
container.getProperties().put(PROPERTY_DIALOG_SHOW_LATER, queue);
}
queue.add(showDialogAction);
}
Comment on lines +137 to +150
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

It is recommended to add a null check for showDialogAction before adding it to the queue to prevent potential NullPointerException when the action is eventually executed.

Suggested change
public static void showLater(StackPane container, Runnable showDialogAction) {
FXUtils.checkFxUserThread();
if (container.getProperties().get(PROPERTY_DIALOG_INSTANCE) == null) {
showDialogAction.run();
return;
}
Queue<Runnable> queue = (Queue<Runnable>) container.getProperties().get(PROPERTY_DIALOG_SHOW_LATER);
if (queue == null) {
queue = new LinkedList<>();
container.getProperties().put(PROPERTY_DIALOG_SHOW_LATER, queue);
}
queue.add(showDialogAction);
}
@SuppressWarnings("unchecked")
public static void showLater(StackPane container, Runnable showDialogAction) {
FXUtils.checkFxUserThread();
if (showDialogAction == null) return;
if (container.getProperties().get(PROPERTY_DIALOG_INSTANCE) == null) {
showDialogAction.run();
return;
}
Queue<Runnable> queue = (Queue<Runnable>) container.getProperties().get(PROPERTY_DIALOG_SHOW_LATER);
if (queue == null) {
queue = new LinkedList<>();
container.getProperties().put(PROPERTY_DIALOG_SHOW_LATER, queue);
}
queue.add(showDialogAction);
}


@SuppressWarnings("unchecked")
public static void close(Node content) {
FXUtils.checkFxUserThread();
Expand All @@ -131,6 +159,8 @@ public static void close(Node content) {
JFXDialogPane pane = (JFXDialogPane) content.getProperties().get(PROPERTY_PARENT_PANE_REF);
JFXDialog dialog = (JFXDialog) content.getProperties().get(PROPERTY_PARENT_DIALOG_REF);

Runnable showNextDialogAction = null;

if (dialog != null && pane != null) {
if (pane.size() == 1 && pane.peek().orElse(null) == content) {
dialog.setOnDialogClosed(e -> pane.pop(content));
Expand All @@ -142,6 +172,12 @@ public static void close(Node content) {
container.getProperties().remove(PROPERTY_DIALOG_PANE_INSTANCE);
container.getProperties().remove(PROPERTY_PARENT_DIALOG_REF);
container.getProperties().remove(PROPERTY_PARENT_PANE_REF);

Queue<Runnable> queue = (Queue<Runnable>) container.getProperties().get(PROPERTY_DIALOG_SHOW_LATER);
if (queue != null && !queue.isEmpty()) {
Runnable next = queue.remove();
if (next != null) showNextDialogAction = next;
}
}
} else {
pane.pop(content);
Expand All @@ -151,5 +187,7 @@ public static void close(Node content) {
dialogAware.onDialogClosed();
}
}

if (showNextDialogAction != null) showNextDialogAction.run();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import javafx.animation.Interpolator;
import javafx.beans.InvalidationListener;
import javafx.beans.WeakInvalidationListener;
import javafx.beans.property.BooleanProperty;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.image.Image;
Expand Down Expand Up @@ -343,6 +344,10 @@ public void navigate(Node node, AnimationProducer animationProducer, Duration du
navigator.navigate(node, animationProducer, duration, interpolator);
}

public BooleanProperty backableProperty() {
return navigator.backableProperty();
}

private void close() {
if (navigator.getCurrentPage() instanceof DecoratorPage) {
DecoratorPage page = (DecoratorPage) navigator.getCurrentPage();
Expand Down Expand Up @@ -427,6 +432,10 @@ private void closeDialog(Node node) {
DialogUtils.close(node);
}

public void showDialogLater(Node node) {
DialogUtils.showLater(decorator, node);
}

// ==== Toast ====

public void showToast(String content) {
Expand Down
31 changes: 23 additions & 8 deletions HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public final class MainPage extends StackPane implements DecoratorPage {

private final StringProperty currentGame = new SimpleStringProperty(this, "currentGame");
private final BooleanProperty showUpdate = new SimpleBooleanProperty(this, "showUpdate");
private final BooleanProperty showUpdateDialog = new SimpleBooleanProperty(this, "showUpdateDialog");
private final ObjectProperty<RemoteVersion> latestVersion = new SimpleObjectProperty<>(this, "latestVersion");
private final ObservableList<Version> versions = FXCollections.observableArrayList();
private Profile profile;
Expand All @@ -98,6 +99,8 @@ public final class MainPage extends StackPane implements DecoratorPage {
private final StackPane updatePane;
private final JFXButton menuButton;

private RemoteVersion lastShownVersion;

{
HBox titleNode = new HBox(8);
titleNode.setPadding(new Insets(0, 0, 0, 2));
Expand Down Expand Up @@ -170,7 +173,8 @@ public final class MainPage extends StackPane implements DecoratorPage {
FXUtils.setLimitHeight(updatePane, 55);
StackPane.setAlignment(updatePane, Pos.TOP_RIGHT);
FXUtils.onClicked(updatePane, this::onUpgrade);
FXUtils.onChange(showUpdateProperty(), this::showUpdate);
FXUtils.onChange(showUpdateProperty(), this::doAnimation);
FXUtils.onChange(showUpdateDialogProperty(), this::showUpdateDialog);

{
HBox hBox = new HBox();
Expand Down Expand Up @@ -274,13 +278,12 @@ public void accept(String currentGame) {

}

private void showUpdate(boolean show) {
doAnimation(show);

if (show && !config().isDisableAutoShowUpdateDialog()
&& getLatestVersion() != null
&& !Objects.equals(config().getPromptedVersion(), getLatestVersion().getVersion())) {
Controllers.dialog(new MessageDialogPane.Builder("", i18n("update.bubble.title", getLatestVersion().getVersion()), MessageDialogPane.MessageType.INFO)
private void showUpdateDialog(boolean show) {
if (show && getLatestVersion() != null && !Objects.equals(getLatestVersion(), lastShownVersion)
&& !Objects.equals(config().getPromptedVersion(), getLatestVersion().getVersion())
) {
lastShownVersion = getLatestVersion();
Controllers.dialogLater(new MessageDialogPane.Builder("", i18n("update.bubble.title", getLatestVersion().getVersion()), MessageDialogPane.MessageType.INFO)
.addAction(i18n("button.view"), () -> {
config().setPromptedVersion(getLatestVersion().getVersion());
onUpgrade();
Expand Down Expand Up @@ -403,6 +406,18 @@ public void setShowUpdate(boolean showUpdate) {
this.showUpdate.set(showUpdate);
}

public boolean isShowUpdateDialog() {
return showUpdateDialog.get();
}

public BooleanProperty showUpdateDialogProperty() {
return showUpdateDialog;
}

public void setShowUpdateDialog(boolean showUpdateDialog) {
this.showUpdateDialog.set(showUpdateDialog);
}

public RemoteVersion getLatestVersion() {
return latestVersion.get();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ public MainPage getMainPage() {
});

FXUtils.onChangeAndOperate(Profiles.selectedVersionProperty(), mainPage::setCurrentGame);
mainPage.showUpdateProperty().bind(UpdateChecker.outdatedProperty());
mainPage.latestVersionProperty().bind(UpdateChecker.latestVersionProperty());

Profiles.registerVersionsListener(profile -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,10 @@ public static void requestCheckUpdate(UpdateChannel channel, boolean preview) {

RemoteVersion finalResult = result;
Platform.runLater(() -> {
checkingUpdate.set(false);
if (finalResult != null) {
latestVersion.set(finalResult);
}
checkingUpdate.set(false);
});
}, "Update Checker", true);
});
Expand Down