Skip to content

Commit 2f2961d

Browse files
committed
Merge remote-tracking branch 'upstream/main' into switch-stable
2 parents 30a8eef + afbf567 commit 2f2961d

54 files changed

Lines changed: 1374 additions & 746 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

HMCL/image/8mi-tech.png

10 KB
Loading

HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,7 @@
4242
import org.jackhuang.hmcl.theme.Themes;
4343
import org.jackhuang.hmcl.upgrade.UpdateChecker;
4444
import org.jackhuang.hmcl.upgrade.UpdateHandler;
45-
import org.jackhuang.hmcl.util.CrashReporter;
46-
import org.jackhuang.hmcl.util.FileSaver;
47-
import org.jackhuang.hmcl.util.Lang;
48-
import org.jackhuang.hmcl.util.StringUtils;
45+
import org.jackhuang.hmcl.util.*;
4946
import org.jackhuang.hmcl.util.io.JarUtils;
5047
import org.jackhuang.hmcl.util.platform.*;
5148

@@ -347,6 +344,8 @@ public static void main(String[] args) {
347344
LOG.info("XDG Current Desktop: " + System.getenv("XDG_CURRENT_DESKTOP"));
348345
}
349346

347+
LOG.info("Zlib Compatible: " + ZlibUtils.IS_ZLIB_COMPATIBLE);
348+
350349
Lang.thread(SystemInfo::initialize, "Detection System Information", true);
351350

352351
launch(Launcher.class, args);

HMCL/src/main/java/org/jackhuang/hmcl/Metadata.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ private Metadata() {
4545
public static final int RECOMMENDED_JAVA_VERSION = 21;
4646

4747
public static final String PUBLISH_URL = "https://hmcl.huangyuhui.net";
48-
public static final String ABOUT_URL = PUBLISH_URL + "/about";
4948
public static final String DOWNLOAD_URL = PUBLISH_URL + "/download";
5049
public static final String HMCL_UPDATE_URL = System.getProperty("hmcl.update_source.override", PUBLISH_URL + "/api/update_link");
5150
public static final String MANUAL_UPDATE_URL = "https://github.com/HMCL-dev/HMCL/releases";

HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,9 @@ public static String localizeErrorMessage(Exception exception) {
468468
}
469469
} else if (exception instanceof MicrosoftService.XBox400Exception) {
470470
return i18n("account.methods.microsoft.error.wrong_verify_method");
471-
} else if (exception instanceof MicrosoftService.NoMinecraftJavaEditionProfileException) {
471+
} else if (exception instanceof MicrosoftService.MinecraftJavaEditionLicenseNotFoundException) {
472+
return i18n("account.methods.microsoft.error.no_license");
473+
} else if (exception instanceof MicrosoftService.MinecraftJavaEditionProfileNotFoundException) {
472474
return i18n("account.methods.microsoft.error.no_character");
473475
} else if (exception instanceof MicrosoftService.NoXuiException) {
474476
return i18n("account.methods.microsoft.error.add_family");

HMCL/src/main/java/org/jackhuang/hmcl/terracotta/TerracottaBundle.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,15 @@ protected Context getContext(HttpResponse<?> response, boolean checkETag, String
7171
return new Context() {
7272
@Override
7373
public void withResult(boolean success) {
74+
super.withResult(success);
7475
delegate.withResult(success);
7576
}
7677

78+
@Override
79+
public void reset() throws IOException {
80+
delegate.reset();
81+
}
82+
7783
@Override
7884
public void write(byte[] buffer, int offset, int len) throws IOException {
7985
context.checkCancellation();
@@ -113,7 +119,7 @@ public Task<?> install(Path pkg) {
113119
throw new ArtifactMalformedException(String.format("Expecting %s file in terracotta bundle.", file));
114120
}
115121

116-
MessageDigest digest = DigestUtils.getDigest(check.getAlgorithm());
122+
MessageDigest digest = DigestUtils.getDigest(check.algorithm());
117123
try (
118124
InputStream is = tree.getInputStream(archive);
119125
OutputStream os = new DigestOutputStream(Files.newOutputStream(path), digest)
@@ -122,8 +128,8 @@ public Task<?> install(Path pkg) {
122128
}
123129

124130
String hash = HexFormat.of().formatHex(digest.digest());
125-
if (!check.getChecksum().equalsIgnoreCase(hash)) {
126-
throw new ChecksumMismatchException(check.getAlgorithm(), check.getChecksum(), hash);
131+
if (!check.checksum().equalsIgnoreCase(hash)) {
132+
throw new ChecksumMismatchException(check.algorithm(), check.checksum(), hash);
127133
}
128134

129135
switch (OperatingSystem.CURRENT_OS) {
@@ -172,7 +178,7 @@ private boolean isLocalBundleValid() throws IOException { // FIXME: Make control
172178
return false;
173179
}
174180

175-
MessageDigest digest = DigestUtils.getDigest(check.getAlgorithm());
181+
MessageDigest digest = DigestUtils.getDigest(check.algorithm());
176182
try (InputStream is = new DigestInputStream(Files.newInputStream(path), digest)) {
177183
int n;
178184
while ((n = is.read(buffer)) >= 0) {
@@ -182,7 +188,7 @@ private boolean isLocalBundleValid() throws IOException { // FIXME: Make control
182188
}
183189
}
184190
}
185-
if (!HexFormat.of().formatHex(digest.digest()).equalsIgnoreCase(check.getChecksum())) {
191+
if (!HexFormat.of().formatHex(digest.digest()).equalsIgnoreCase(check.checksum())) {
186192
return false;
187193
}
188194
}

HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import org.jackhuang.hmcl.util.io.FileUtils;
7171
import org.jackhuang.hmcl.util.platform.Architecture;
7272
import org.jackhuang.hmcl.util.platform.OperatingSystem;
73+
import org.jetbrains.annotations.NotNull;
7374
import org.jetbrains.annotations.Nullable;
7475

7576
import java.io.IOException;
@@ -594,15 +595,15 @@ public static CompletableFuture<List<PromptDialogPane.Builder.Question<?>>> prom
594595
return pane.getCompletableFuture();
595596
}
596597

597-
public static TaskExecutorDialogPane taskDialog(TaskExecutor executor, String title, TaskCancellationAction onCancel) {
598+
public static TaskExecutorDialogPane taskDialog(TaskExecutor executor, String title, @NotNull TaskCancellationAction onCancel) {
598599
TaskExecutorDialogPane pane = new TaskExecutorDialogPane(onCancel);
599600
pane.setTitle(title);
600601
pane.setExecutor(executor);
601602
dialog(pane);
602603
return pane;
603604
}
604605

605-
public static TaskExecutorDialogPane taskDialog(Task<?> task, String title, TaskCancellationAction onCancel) {
606+
public static TaskExecutorDialogPane taskDialog(Task<?> task, String title, @NotNull TaskCancellationAction onCancel) {
606607
TaskExecutor executor = task.executor();
607608
TaskExecutorDialogPane pane = taskDialog(executor, title, onCancel);
608609
executor.start();

HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public enum SVG {
6262
EXTENSION_FILL("M8.8 21H5q-.825 0-1.4125-.5875T3 19V15.2q1.2 0 2.1-.7625T6 12.5q0-1.175-.9-1.9375T3 9.8V6q0-.825.5875-1.4125T5 4H9q0-1.05.725-1.775T11.5 1.5q1.05 0 1.775.725T14 4h4q.825 0 1.4125.5875T20 6v4q1.05 0 1.775.725T22.5 12.5q0 1.05-.725 1.775T20 15v4q0 .825-.5875 1.4125T18 21H14.2q0-1.25-.7875-2.125T11.5 18q-1.125 0-1.9125.875T8.8 21Z"),
6363
FEEDBACK("M12 15Q12.425 15 12.7125 14.7125T13 14Q13 13.575 12.7125 13.2875T12 13Q11.575 13 11.2875 13.2875T11 14Q11 14.425 11.2875 14.7125T12 15ZM11 11H13V5H11V11ZM2 22V4Q2 3.175 2.5875 2.5875T4 2H20Q20.825 2 21.4125 2.5875T22 4V16Q22 16.825 21.4125 17.4125T20 18H6L2 22ZM5.15 16H20V4H4V17.125L5.15 16ZM4 16V4 16Z"),
6464
FEEDBACK_FILL("M2 22V4q0-.825.5875-1.4125T4 2H20q.825 0 1.4125.5875T22 4V16q0 .825-.5875 1.4125T20 18H6L2 22Zm10-7q.425 0 .7125-.2875T13 14t-.2875-.7125T12 13t-.7125.2875T11 14t.2875.7125T12 15Zm-1-4h2V5H11v6Z"),
65+
FILE_OPEN("M6 22q-0.825 0-1.4125-0.5875T4 20v-16q0-0.825 0.5875-1.4125T6 2h8l6 6v6h-2v-5H13v-5H6v16h9v2H6Zm15.95 0.375L19 19.425v2.225h-2v-5.65h5.65v2h-2.25l2.95 2.95-1.4 1.425Zm-15.95-2.375v-16 16Z"),
6566
FOLDER("M4 20Q3.175 20 2.5875 19.4125T2 18V6Q2 5.175 2.5875 4.5875T4 4H10L12 6H20Q20.825 6 21.4125 6.5875T22 8V18Q22 18.825 21.4125 19.4125T20 20H4ZM4 18H20V8H11.175L9.175 6H4V18ZM4 18V6 18Z"),
6667
FOLDER_COPY("M3 21Q2.175 21 1.5875 20.4125T1 19V6H3V19H20V21H3ZM7 17Q6.175 17 5.5875 16.4125T5 15V4Q5 3.175 5.5875 2.5875T7 2H12L14 4H21Q21.825 4 22.4125 4.5875T23 6V15Q23 15.825 22.4125 16.4125T21 17H7ZM7 15H21V6H13.175L11.175 4H7V15ZM7 15V4 15Z"),
6768
FOLDER_OPEN("M4 20Q3.175 20 2.5875 19.4125T2 18V6Q2 5.175 2.5875 4.5875T4 4H10L12 6H20Q20.825 6 21.4125 6.5875T22 8H11.175L9.175 6H4V18L6.4 10H23.5L20.925 18.575Q20.725 19.225 20.1875 19.6125T19 20H4ZM6.1 18H19L20.8 12H7.9L6.1 18ZM6.1 18 7.9 12 6.1 18ZM4 8V6 8Z"),

HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ public UpgradeDialog(RemoteVersion remoteVersion, Runnable updateRunnable) {
5050
setHeading(new Label(i18n("update.changelog")));
5151
setBody(new JFXSpinner());
5252

53-
String url = CHANGELOG_URL + remoteVersion.getChannel().channelName + ".html";
53+
String url = CHANGELOG_URL + remoteVersion.channel().channelName + ".html";
5454

5555
Task.supplyAsync(Schedulers.io(), () -> {
56-
VersionNumber targetVersion = VersionNumber.asVersion(remoteVersion.getVersion());
56+
VersionNumber targetVersion = VersionNumber.asVersion(remoteVersion.version());
5757
VersionNumber currentVersion = VersionNumber.asVersion(Metadata.VERSION);
5858
if (targetVersion.compareTo(currentVersion) <= 0)
5959
// Downgrade update, no need to display changelog

HMCL/src/main/java/org/jackhuang/hmcl/ui/account/OfflineAccountSkinPane.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.jfoenix.controls.JFXComboBox;
2222
import com.jfoenix.controls.JFXDialogLayout;
2323
import com.jfoenix.controls.JFXTextField;
24+
import javafx.animation.PauseTransition;
2425
import javafx.application.Platform;
2526
import javafx.beans.InvalidationListener;
2627
import javafx.geometry.Insets;
@@ -29,6 +30,7 @@
2930
import javafx.scene.input.DragEvent;
3031
import javafx.scene.input.TransferMode;
3132
import javafx.scene.layout.*;
33+
import javafx.util.Duration;
3234
import org.jackhuang.hmcl.auth.offline.OfflineAccount;
3335
import org.jackhuang.hmcl.auth.offline.Skin;
3436
import org.jackhuang.hmcl.auth.yggdrasil.TextureModel;
@@ -135,7 +137,9 @@ public OfflineAccountSkinPane(OfflineAccount account) {
135137
capeSelector.setValue(account.getSkin().getLocalCapePath());
136138
}
137139

138-
skinBinding = FXUtils.observeWeak(() -> {
140+
PauseTransition pauseTransition = new PauseTransition(Duration.seconds(1));
141+
142+
Runnable loadSkin = () -> {
139143
getSkin().load(account.getUsername())
140144
.whenComplete(Schedulers.javafx(), (result, exception) -> {
141145
if (exception != null) {
@@ -157,6 +161,23 @@ public OfflineAccountSkinPane(OfflineAccount account) {
157161
result.getCape() != null ? result.getCape().getImage() : null);
158162
}
159163
}).start();
164+
};
165+
166+
pauseTransition.setOnFinished(e -> loadSkin.run());
167+
168+
skinBinding = FXUtils.observeWeak(() -> {
169+
Skin.Type selectedType = skinItem.getSelectedData();
170+
171+
if (selectedType == Skin.Type.CUSTOM_SKIN_LOADER_API) {
172+
if (!cslApiField.validate()) {
173+
pauseTransition.stop();
174+
return;
175+
}
176+
pauseTransition.playFromStart();
177+
} else {
178+
pauseTransition.stop();
179+
loadSkin.run();
180+
}
160181
}, skinItem.selectedDataProperty(), cslApiField.textProperty(), modelCombobox.valueProperty(), skinSelector.valueProperty(), capeSelector.valueProperty());
161182

162183
FXUtils.onChangeAndOperate(skinItem.selectedDataProperty(), selectedData -> {

HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileSelector.java

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.jackhuang.hmcl.ui.construct;
1919

2020
import com.jfoenix.controls.JFXButton;
21+
import com.jfoenix.controls.JFXPopup;
2122
import com.jfoenix.controls.JFXTextField;
2223
import javafx.beans.property.SimpleStringProperty;
2324
import javafx.beans.property.StringProperty;
@@ -30,6 +31,7 @@
3031
import org.jackhuang.hmcl.ui.Controllers;
3132
import org.jackhuang.hmcl.ui.FXUtils;
3233
import org.jackhuang.hmcl.ui.SVG;
34+
import org.jackhuang.hmcl.util.StringUtils;
3335
import org.jackhuang.hmcl.util.io.FileUtils;
3436

3537
import java.nio.file.Path;
@@ -38,10 +40,18 @@
3840

3941
public class FileSelector extends HBox {
4042
private final StringProperty value = new SimpleStringProperty();
41-
private String chooserTitle = i18n("selector.choose_file");
42-
private boolean directory = false;
43+
private String chooserTitle = "";
44+
private SelectionMode selectionMode = SelectionMode.FILE;
4345
private final ObservableList<FileChooser.ExtensionFilter> extensionFilters = FXCollections.observableArrayList();
4446

47+
JFXButton selectButton = FXUtils.newToggleButton4(SVG.FOLDER_OPEN, 15);
48+
49+
public enum SelectionMode {
50+
FILE,
51+
DIRECTORY,
52+
FILE_OR_DIRECTORY
53+
}
54+
4555
public String getValue() {
4656
return value.get();
4757
}
@@ -63,12 +73,12 @@ public FileSelector setChooserTitle(String chooserTitle) {
6373
return this;
6474
}
6575

66-
public boolean isDirectory() {
67-
return directory;
76+
public SelectionMode getSelectionMode() {
77+
return selectionMode;
6878
}
6979

70-
public FileSelector setDirectory(boolean directory) {
71-
this.directory = directory;
80+
public FileSelector setSelectionMode(SelectionMode selectionMode) {
81+
this.selectionMode = selectionMode;
7282
return this;
7383
}
7484

@@ -80,26 +90,20 @@ public FileSelector() {
8090
JFXTextField customField = new JFXTextField();
8191
FXUtils.bindString(customField, valueProperty());
8292

83-
JFXButton selectButton = FXUtils.newToggleButton4(SVG.FOLDER_OPEN, 15);
8493
selectButton.setOnAction(e -> {
85-
if (directory) {
86-
DirectoryChooser chooser = new DirectoryChooser();
87-
chooser.setTitle(chooserTitle);
88-
Path dir = FileUtils.toPath(chooser.showDialog(Controllers.getStage()));
89-
if (dir != null) {
90-
String path = FileUtils.getAbsolutePath(dir);
91-
customField.setText(path);
92-
value.setValue(path);
93-
}
94-
} else {
95-
FileChooser chooser = new FileChooser();
96-
chooser.getExtensionFilters().addAll(getExtensionFilters());
97-
chooser.setTitle(chooserTitle);
98-
Path file = FileUtils.toPath(chooser.showOpenDialog(Controllers.getStage()));
99-
if (file != null) {
100-
String path = FileUtils.getAbsolutePath(file);
101-
customField.setText(path);
102-
value.setValue(path);
94+
switch (selectionMode) {
95+
case FILE -> openFileChooser(customField);
96+
case DIRECTORY -> openDirectoryChooser(customField);
97+
case FILE_OR_DIRECTORY -> {
98+
PopupMenu selectPopupMenu = new PopupMenu();
99+
JFXPopup selectModePopup = new JFXPopup(selectPopupMenu);
100+
101+
selectPopupMenu.getContent().addAll(
102+
new IconedMenuItem(SVG.FILE_OPEN, i18n("selector.choose_file"), () -> openFileChooser(customField), selectModePopup),
103+
new IconedMenuItem(SVG.FOLDER_OPEN, i18n("selector.choose_directory"), () -> openDirectoryChooser(customField), selectModePopup)
104+
);
105+
106+
selectModePopup.show(selectButton, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.RIGHT, -selectButton.getWidth(), 0);
103107
}
104108
}
105109
});
@@ -108,4 +112,27 @@ public FileSelector() {
108112
setSpacing(3);
109113
getChildren().addAll(customField, selectButton);
110114
}
115+
116+
private void openFileChooser(JFXTextField customField) {
117+
FileChooser chooser = new FileChooser();
118+
chooser.getExtensionFilters().addAll(getExtensionFilters());
119+
chooser.setTitle(StringUtils.isBlank(chooserTitle) ? i18n("selector.choose_file") : chooserTitle);
120+
Path file = FileUtils.toPath(chooser.showOpenDialog(Controllers.getStage()));
121+
if (file != null) {
122+
String path = FileUtils.getAbsolutePath(file);
123+
customField.setText(path);
124+
value.setValue(path);
125+
}
126+
}
127+
128+
private void openDirectoryChooser(JFXTextField customField) {
129+
DirectoryChooser chooser = new DirectoryChooser();
130+
chooser.setTitle(StringUtils.isBlank(chooserTitle) ? i18n("selector.choose_directory") : chooserTitle);
131+
Path dir = FileUtils.toPath(chooser.showDialog(Controllers.getStage()));
132+
if (dir != null) {
133+
String path = FileUtils.getAbsolutePath(dir);
134+
customField.setText(path);
135+
value.setValue(path);
136+
}
137+
}
111138
}

0 commit comments

Comments
 (0)