mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-13 13:56:55 -04:00
feat: (modpack download): category & sort.
This commit is contained in:
parent
af7cf393dc
commit
37fb9a0d65
@ -42,7 +42,6 @@ import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
|||||||
import org.jackhuang.hmcl.ui.construct.PromptDialogPane;
|
import org.jackhuang.hmcl.ui.construct.PromptDialogPane;
|
||||||
import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane;
|
import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane;
|
||||||
import org.jackhuang.hmcl.ui.decorator.DecoratorController;
|
import org.jackhuang.hmcl.ui.decorator.DecoratorController;
|
||||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
|
||||||
import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider;
|
import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider;
|
||||||
import org.jackhuang.hmcl.ui.main.RootPage;
|
import org.jackhuang.hmcl.ui.main.RootPage;
|
||||||
import org.jackhuang.hmcl.ui.versions.GameListPage;
|
import org.jackhuang.hmcl.ui.versions.GameListPage;
|
||||||
@ -84,11 +83,12 @@ public final class Controllers {
|
|||||||
private static AuthlibInjectorServersPage serversPage = null;
|
private static AuthlibInjectorServersPage serversPage = null;
|
||||||
private static Lazy<RootPage> rootPage = new Lazy<>(RootPage::new);
|
private static Lazy<RootPage> rootPage = new Lazy<>(RootPage::new);
|
||||||
private static DecoratorController decorator;
|
private static DecoratorController decorator;
|
||||||
private static Lazy<ModDownloadListPage> modDownloadListPage = new Lazy<>(() ->
|
private static Lazy<ModDownloadListPage> modDownloadListPage = new Lazy<>(() -> {
|
||||||
new ModDownloadListPage(CurseModManager.SECTION_MODPACK, Versions::downloadModpackImpl) {
|
return new ModDownloadListPage(CurseModManager.SECTION_MODPACK, Versions::downloadModpackImpl) {
|
||||||
{
|
{
|
||||||
state.set(State.fromTitle(i18n("modpack.download")));
|
state.set(State.fromTitle(i18n("modpack.download")));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
private Controllers() {
|
private Controllers() {
|
||||||
|
@ -17,9 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.ui.versions;
|
package org.jackhuang.hmcl.ui.versions;
|
||||||
|
|
||||||
import com.jfoenix.controls.JFXButton;
|
import com.jfoenix.controls.*;
|
||||||
import com.jfoenix.controls.JFXListView;
|
|
||||||
import com.jfoenix.controls.JFXTextField;
|
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.*;
|
import javafx.beans.property.*;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
@ -44,6 +42,7 @@ import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
|||||||
import org.jackhuang.hmcl.util.StringUtils;
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
@ -174,13 +173,37 @@ public class ModDownloadListPage extends Control implements DecoratorPage {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
JFXTextField categoryField = new JFXTextField();
|
StackPane categoryStackPane = new StackPane();
|
||||||
categoryField.setPromptText(i18n("mods.category"));
|
JFXComboBox<CategoryIndented> categoryComboBox = new JFXComboBox<>();
|
||||||
searchPane.add(categoryField, 0, 1);
|
categoryStackPane.getChildren().setAll(categoryComboBox);
|
||||||
|
categoryComboBox.prefWidthProperty().bind(categoryStackPane.widthProperty());
|
||||||
|
categoryComboBox.getStyleClass().add("fit-width");
|
||||||
|
categoryComboBox.setPromptText(i18n("mods.category"));
|
||||||
|
Task.supplyAsync(() -> CurseModManager.getCategories(getSkinnable().section))
|
||||||
|
.thenAcceptAsync(Schedulers.javafx(), categories -> {
|
||||||
|
List<CategoryIndented> result = new ArrayList<>();
|
||||||
|
for (CurseModManager.Category category : categories) {
|
||||||
|
resolveCategory(category, 0, result);
|
||||||
|
}
|
||||||
|
categoryComboBox.getItems().setAll(result);
|
||||||
|
}).start();
|
||||||
|
searchPane.add(categoryStackPane, 0, 1);
|
||||||
|
|
||||||
JFXTextField sortField = new JFXTextField();
|
StackPane sortStackPane = new StackPane();
|
||||||
sortField.setPromptText(i18n("search.sort"));
|
JFXComboBox<String> sortComboBox = new JFXComboBox<>();
|
||||||
searchPane.add(sortField, 1, 1);
|
sortStackPane.getChildren().setAll(sortComboBox);
|
||||||
|
sortComboBox.prefWidthProperty().bind(sortStackPane.widthProperty());
|
||||||
|
sortComboBox.getStyleClass().add("fit-width");
|
||||||
|
sortComboBox.setPromptText(i18n("search.sort"));
|
||||||
|
sortComboBox.getItems().setAll(
|
||||||
|
i18n("curse.sort.date_created"),
|
||||||
|
i18n("curse.sort.popularity"),
|
||||||
|
i18n("curse.sort.last_updated"),
|
||||||
|
i18n("curse.sort.name"),
|
||||||
|
i18n("curse.sort.author"),
|
||||||
|
i18n("curse.sort.total_downloads"));
|
||||||
|
sortComboBox.getSelectionModel().select(0);
|
||||||
|
searchPane.add(sortStackPane, 1, 1);
|
||||||
|
|
||||||
VBox vbox = new VBox();
|
VBox vbox = new VBox();
|
||||||
vbox.setAlignment(Pos.CENTER_RIGHT);
|
vbox.setAlignment(Pos.CENTER_RIGHT);
|
||||||
@ -189,7 +212,14 @@ public class ModDownloadListPage extends Control implements DecoratorPage {
|
|||||||
JFXButton searchButton = new JFXButton();
|
JFXButton searchButton = new JFXButton();
|
||||||
searchButton.setText(i18n("search"));
|
searchButton.setText(i18n("search"));
|
||||||
searchButton.setOnAction(e -> {
|
searchButton.setOnAction(e -> {
|
||||||
getSkinnable().search(gameVersionField.getText(), 0, 0, nameField.getText(), 0);
|
getSkinnable().search(gameVersionField.getText(),
|
||||||
|
Optional.ofNullable(categoryComboBox.getSelectionModel().getSelectedItem())
|
||||||
|
.map(CategoryIndented::getCategory)
|
||||||
|
.map(CurseModManager.Category::getId)
|
||||||
|
.orElse(0),
|
||||||
|
0,
|
||||||
|
nameField.getText(),
|
||||||
|
sortComboBox.getSelectionModel().getSelectedIndex());
|
||||||
});
|
});
|
||||||
searchPane.add(searchButton, 0, 2);
|
searchPane.add(searchButton, 0, 2);
|
||||||
vbox.getChildren().setAll(searchButton);
|
vbox.getChildren().setAll(searchButton);
|
||||||
@ -256,5 +286,35 @@ public class ModDownloadListPage extends Control implements DecoratorPage {
|
|||||||
|
|
||||||
getChildren().setAll(pane);
|
getChildren().setAll(pane);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class CategoryIndented {
|
||||||
|
private final int indent;
|
||||||
|
private final CurseModManager.Category category;
|
||||||
|
|
||||||
|
public CategoryIndented(int indent, CurseModManager.Category category) {
|
||||||
|
this.indent = indent;
|
||||||
|
this.category = category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndent() {
|
||||||
|
return indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CurseModManager.Category getCategory() {
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return StringUtils.repeats(' ', indent) + i18n("curse.category." + category.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void resolveCategory(CurseModManager.Category category, int indent, List<CategoryIndented> result) {
|
||||||
|
result.add(new CategoryIndented(indent, category));
|
||||||
|
for (CurseModManager.Category subcategory : category.getSubcategories()) {
|
||||||
|
resolveCategory(subcategory, indent + 1, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,6 @@ import java.nio.file.Path;
|
|||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.ui.download.LocalModpackPage.MODPACK_FILE;
|
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
public final class Versions {
|
public final class Versions {
|
||||||
|
@ -156,6 +156,13 @@ curse.category.4558=Redstone
|
|||||||
curse.category.4843=Automation
|
curse.category.4843=Automation
|
||||||
curse.category.4906=MCreator
|
curse.category.4906=MCreator
|
||||||
|
|
||||||
|
curse.sort.author=Author
|
||||||
|
curse.sort.date_created=Date Created
|
||||||
|
curse.sort.last_updated=Last Updated
|
||||||
|
curse.sort.name=Name
|
||||||
|
curse.sort.popularity=Popularity
|
||||||
|
curse.sort.total_downloads=Total Downloads
|
||||||
|
|
||||||
download=Download
|
download=Download
|
||||||
download.code.404=File not found on the remote server: %s
|
download.code.404=File not found on the remote server: %s
|
||||||
download.failed=Failed to download %1$s, response code: %2$d
|
download.failed=Failed to download %1$s, response code: %2$d
|
||||||
|
@ -157,6 +157,13 @@ curse.category.4558=红石
|
|||||||
curse.category.4843=自动化
|
curse.category.4843=自动化
|
||||||
curse.category.4906=MCreator
|
curse.category.4906=MCreator
|
||||||
|
|
||||||
|
curse.sort.author=作者
|
||||||
|
curse.sort.date_created=创建日期
|
||||||
|
curse.sort.last_updated=最近更新
|
||||||
|
curse.sort.name=名称
|
||||||
|
curse.sort.popularity=热度
|
||||||
|
curse.sort.total_downloads=下载量
|
||||||
|
|
||||||
download=下载
|
download=下载
|
||||||
download.code.404=远程服务器不包含需要下载的文件: %s
|
download.code.404=远程服务器不包含需要下载的文件: %s
|
||||||
download.failed=下载失败: %1$s,错误码:%2$d
|
download.failed=下载失败: %1$s,错误码:%2$d
|
||||||
|
@ -11,7 +11,9 @@ import java.util.*;
|
|||||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||||
|
|
||||||
public class CurseModManager {
|
public final class CurseModManager {
|
||||||
|
private CurseModManager() {
|
||||||
|
}
|
||||||
|
|
||||||
public static List<CurseAddon> searchPaginated(String gameVersion, int category, int section, int pageOffset, String searchFilter, int sort) throws IOException {
|
public static List<CurseAddon> searchPaginated(String gameVersion, int category, int section, int pageOffset, String searchFilter, int sort) throws IOException {
|
||||||
String response = NetworkUtils.doGet(new URL(NetworkUtils.withQuery("https://addons-ecs.forgesvc.net/api/v2/addon/search", mapOf(
|
String response = NetworkUtils.doGet(new URL(NetworkUtils.withQuery("https://addons-ecs.forgesvc.net/api/v2/addon/search", mapOf(
|
||||||
|
@ -235,4 +235,12 @@ public final class StringUtils {
|
|||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String repeats(char ch, int repeat) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for (int i = 0; i < repeat; i++) {
|
||||||
|
result.append(ch);
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user