diff --git a/pom.xml b/pom.xml index b9bf2f8..74cb421 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.github.franckyi cmpdl - 2.2.0 + 2.3.0 1.8 1.8 @@ -15,17 +15,43 @@ org.json json - 20180130 + 20180813 - com.squareup.okhttp3 - okhttp - 3.10.0 + com.squareup.retrofit2 + retrofit + 2.6.0 org.jsoup jsoup - 1.11.2 + 1.12.1 + + + + maven-assembly-plugin + + + + com.github.franckyi.cmpdl.CMPDL + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + diff --git a/src/main/java/com/github/franckyi/cmpdl/CMPDL.java b/src/main/java/com/github/franckyi/cmpdl/CMPDL.java index 68d0184..0581a3a 100644 --- a/src/main/java/com/github/franckyi/cmpdl/CMPDL.java +++ b/src/main/java/com/github/franckyi/cmpdl/CMPDL.java @@ -1,5 +1,7 @@ package com.github.franckyi.cmpdl; +import com.github.franckyi.cmpdl.api.CMPDLConverterFactory; +import com.github.franckyi.cmpdl.api.TwitchAppAPI; import com.github.franckyi.cmpdl.controller.*; import com.github.franckyi.cmpdl.core.ContentControllerView; import com.github.franckyi.cmpdl.core.ControllerView; @@ -9,6 +11,7 @@ import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.stage.Stage; +import retrofit2.Retrofit; import java.awt.*; import java.io.IOException; @@ -20,16 +23,14 @@ public class CMPDL extends Application { public static final String NAME = "CMPDL"; - public static final String VERSION = "2.2.0"; + public static final String VERSION = "2.3.0"; public static final String AUTHOR = "Franckyi"; public static final String TITLE = String.format("%s v%s by %s", NAME, VERSION, AUTHOR); - // As per the "Required reading" section on https://staging_cursemeta.dries007.net/docs - public static final String USER_AGENT = String.format("%s/%s (%s)", NAME, AUTHOR, VERSION); - public static final ExecutorService EXECUTOR_SERVICE = Executors.newCachedThreadPool(); public static Stage stage; + public static TwitchAppAPI api; public static ControllerView mainWindow; public static ContentControllerView modpackPane; @@ -39,6 +40,15 @@ public class CMPDL extends Application { public static ContentControllerView currentContent; + public static void main(String[] args) { + api = new Retrofit.Builder() + .baseUrl("https://addons-ecs.forgesvc.net/api/v2/") + .addConverterFactory(CMPDLConverterFactory.create()) + .build() + .create(TwitchAppAPI.class); + launch(args); + } + @Override public void start(Stage primaryStage) throws Exception { stage = primaryStage; @@ -53,15 +63,15 @@ public void start(Stage primaryStage) throws Exception { stage.show(); } - public static void main(String[] args) { - launch(args); - } - @Override public void stop() { EXECUTOR_SERVICE.shutdown(); } + public static TwitchAppAPI getAPI() { + return api; + } + public static void openBrowser(String url) { if (Desktop.isDesktopSupported()) { EXECUTOR_SERVICE.execute(() -> { diff --git a/src/main/java/com/github/franckyi/cmpdl/CurseMetaAPI.java b/src/main/java/com/github/franckyi/cmpdl/CurseMetaAPI.java deleted file mode 100644 index dc5413c..0000000 --- a/src/main/java/com/github/franckyi/cmpdl/CurseMetaAPI.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.github.franckyi.cmpdl; - -import com.github.franckyi.cmpdl.model.Project; -import com.github.franckyi.cmpdl.model.ProjectFile; -import com.github.franckyi.cmpdl.model.ProjectFilesList; -import javafx.application.Platform; -import javafx.scene.control.Alert; -import javafx.scene.control.ButtonType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.IOException; - -public class CurseMetaAPI { - - private static final OkHttpClient CLIENT = new OkHttpClient(); - // Docs: https://staging_cursemeta.dries007.net/docs - private static final String URL = "https://staging_cursemeta.dries007.net/api/v3/direct"; - - public static Project getProject(int projectId) { - try { - return new Project(new JSONObject(get("/addon", projectId))); - } catch (JSONException e) { - e.printStackTrace(); - Platform.runLater(() -> new Alert(Alert.AlertType.ERROR, String.format("Unknown project (%d)", projectId), ButtonType.OK).show()); - return null; - } - } - - public static ProjectFilesList getProjectFiles(int projectId) { - try { - return new ProjectFilesList(new JSONArray(get("/addon", projectId, "/files"))); - } catch (JSONException e) { - e.printStackTrace(); - Platform.runLater(() -> new Alert(Alert.AlertType.ERROR, String.format("Unknown project (%d)", projectId), ButtonType.OK).show()); - return null; - } - } - - public static ProjectFile getProjectFile(int projectId, int fileId) { - try { - return new ProjectFile(new JSONObject(get("/addon", projectId, "/file", fileId))); - } catch (JSONException e) { - e.printStackTrace(); - Platform.runLater(() -> new Alert(Alert.AlertType.ERROR, String.format("Unknown project file (%d:%d)", projectId, fileId), ButtonType.OK).show()); - return null; - } - } - - private static String get(String path, Object... args) { - StringBuilder sb = new StringBuilder(URL + path); - for (Object o : args) { - sb.append("/").append(o); - } - Request request = new Request.Builder().header("User-Agent", CMPDL.USER_AGENT).url(sb.toString()).get().build(); - try (Response response = CLIENT.newCall(request).execute()) { - if (response.body() != null) { - return response.body().string(); - } else { - return ""; - } - } catch (IOException e) { - e.printStackTrace(); - return ""; - } - } - -} diff --git a/src/main/java/com/github/franckyi/cmpdl/api/CMPDLConverterFactory.java b/src/main/java/com/github/franckyi/cmpdl/api/CMPDLConverterFactory.java new file mode 100644 index 0000000..84b8632 --- /dev/null +++ b/src/main/java/com/github/franckyi/cmpdl/api/CMPDLConverterFactory.java @@ -0,0 +1,127 @@ +package com.github.franckyi.cmpdl.api; + +import okhttp3.MediaType; +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import okio.BufferedSink; +import org.json.JSONArray; +import org.json.JSONObject; +import retrofit2.Converter; +import retrofit2.Retrofit; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +public class CMPDLConverterFactory extends Converter.Factory { + + private CMPDLConverterFactory() { + } + + public static CMPDLConverterFactory create() { + return new CMPDLConverterFactory(); + } + + @Override + public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { + return value -> { + try { + if (type instanceof Class) { + Class clazz = (Class) type; + if (clazz == Instant.class) { + return Instant.parse(value.string()); + } else if (IBean.class.isAssignableFrom(clazz)) { + return ((IBean) clazz.newInstance()).fromJson(new JSONObject(value.string())); + } + } else if (type instanceof ParameterizedType) { + ParameterizedType type0 = (ParameterizedType) type; + if (List.class.isAssignableFrom((Class) type0.getRawType())) { + return toList(type0, new JSONArray(value.string())); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + }; + } + + @Override + public Converter requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { + return value -> { + try { + if (value instanceof List) { + return new JSONBody(fromList(((ParameterizedType) type), (List) value)); + } else if (value instanceof IBean) { + return new JSONBody(((IBean) value).toJson()); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + }; + } + + public static List toList(ParameterizedType type, JSONArray array) throws Exception { + Class type0 = (Class) getParameterUpperBound(0, type); + List list = new ArrayList<>(); + if (IBean.class.isAssignableFrom(type0)) { + for (int i = 0; i < array.length(); i++) { + list.add(((IBean) type0.newInstance()).fromJson(array.getJSONObject(i))); + } + } else { + list.addAll(array.toList()); + } + return list; + } + + public static JSONArray fromList(List list) throws Exception { + Type[] types = CMPDLConverterFactory.class.getDeclaredMethod("fromList", List.class).getGenericParameterTypes(); + ParameterizedType type = (ParameterizedType) types[0]; + return fromList(type, list); + } + + public static JSONArray fromList(ParameterizedType type, List list) { + Class clazz = (Class) type.getActualTypeArguments()[0]; + return fromList(clazz, list); + } + + public static JSONArray fromList(Class clazz, List list) { + JSONArray array = new JSONArray(); + if (IBean.class.isAssignableFrom(clazz)) { + list.stream() + .map(IBean.class::cast) + .map(IBean::toJson) + .forEach(array::put); + } else { + array.put(list); + } + return array; + } + + private class JSONBody extends RequestBody { + private final Object json; + + public JSONBody(JSONArray json) { + this.json = json; + } + + public JSONBody(JSONObject json) { + this.json = json; + } + + @Override + public MediaType contentType() { + return MediaType.get("application/json"); + } + + @Override + public void writeTo(BufferedSink sink) throws IOException { + sink.writeUtf8(json.toString()); + } + } +} diff --git a/src/main/java/com/github/franckyi/cmpdl/api/IBean.java b/src/main/java/com/github/franckyi/cmpdl/api/IBean.java new file mode 100644 index 0000000..23e915a --- /dev/null +++ b/src/main/java/com/github/franckyi/cmpdl/api/IBean.java @@ -0,0 +1,78 @@ +package com.github.franckyi.cmpdl.api; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.time.Instant; +import java.util.List; + +public interface IBean { + + default IBean fromJson(JSONObject json) throws Exception { + for (Field field : this.getClass().getDeclaredFields()) { + if (json.has(field.getName())) { + field.setAccessible(true); + Object val = json.get(field.getName()); + if (val == JSONObject.NULL) { + if (field.getType().isPrimitive()) { + if (field.getType().equals(boolean.class)) { + val = false; + } else if (field.getType().equals(byte.class)) { + val = (byte) 0; + } else if (field.getType().equals(short.class)) { + val = (short) 0; + } else if (field.getType().equals(int.class)) { + val = 0; + } else if (field.getType().equals(long.class)) { + val = 0L; + } else if (field.getType().equals(float.class)) { + val = 0f; + } else if (field.getType().equals(double.class)) { + val = 0.0; + } + field.set(this, val); + } else { + field.set(this, null); + } + } else if (val instanceof JSONObject && IBean.class.isAssignableFrom(field.getType())) { + field.set(this, ((IBean) field.getType().newInstance()).fromJson(((JSONObject) val))); + } else if (val instanceof JSONArray && List.class.isAssignableFrom(field.getType())) { + ParameterizedType type = (ParameterizedType) field.getGenericType(); + JSONArray array = (JSONArray) val; + field.set(this, CMPDLConverterFactory.toList(type, array)); + } else if (val instanceof Integer && Enum.class.isAssignableFrom(field.getType())) { + field.set(this, IEnum.fromJson(field.getType(), (int) val)); + } else if (val instanceof String && Instant.class.isAssignableFrom(field.getType())) { + field.set(this, Instant.parse((String) val)); + } else { + field.set(this, val); + } + } + } + return this; + } + + default JSONObject toJson() { + JSONObject json = new JSONObject(); + for (Field field : this.getClass().getDeclaredFields()) { + try { + Object val = field.get(this); + if (val instanceof IBean) { + json.put(field.getName(), ((IBean) val).toJson()); + } else if (val instanceof List) { + List list = (List) val; + json.put(field.getName(), CMPDLConverterFactory.fromList(list)); + } else if (val instanceof IEnum) { + json.put(field.getName(), ((IEnum) val).toJson()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + return json; + } + + +} diff --git a/src/main/java/com/github/franckyi/cmpdl/api/IEnum.java b/src/main/java/com/github/franckyi/cmpdl/api/IEnum.java new file mode 100644 index 0000000..c05f432 --- /dev/null +++ b/src/main/java/com/github/franckyi/cmpdl/api/IEnum.java @@ -0,0 +1,20 @@ +package com.github.franckyi.cmpdl.api; + +import java.lang.reflect.InvocationTargetException; + +public interface IEnum { + + int toJson(); + + @SuppressWarnings("unchecked") + static & IEnum> T fromJson(Class clazz, int i) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + T[] values = (T[]) clazz.getDeclaredMethod("values").invoke(null); + for (T value : values) { + if (value.toJson() == i) { + return value; + } + } + return null; + } + +} diff --git a/src/main/java/com/github/franckyi/cmpdl/api/TwitchAppAPI.java b/src/main/java/com/github/franckyi/cmpdl/api/TwitchAppAPI.java new file mode 100644 index 0000000..a599cab --- /dev/null +++ b/src/main/java/com/github/franckyi/cmpdl/api/TwitchAppAPI.java @@ -0,0 +1,22 @@ +package com.github.franckyi.cmpdl.api; + +import com.github.franckyi.cmpdl.api.response.Addon; +import com.github.franckyi.cmpdl.api.response.AddonFile; +import retrofit2.Call; +import retrofit2.http.GET; +import retrofit2.http.Path; + +import java.util.List; + +public interface TwitchAppAPI { + + @GET("addon/{addonId}") + Call getAddon(@Path("addonId") int addonId); + + @GET("addon/{addonId}/file/{fileId}") + Call getFile(@Path("addonId") int addonId, @Path("fileId") int fileId); + + @GET("addon/{addonId}/files") + Call> getAddonFiles(@Path("addonId") int addonId); + +} diff --git a/src/main/java/com/github/franckyi/cmpdl/api/response/Addon.java b/src/main/java/com/github/franckyi/cmpdl/api/response/Addon.java new file mode 100644 index 0000000..17dc0fe --- /dev/null +++ b/src/main/java/com/github/franckyi/cmpdl/api/response/Addon.java @@ -0,0 +1,60 @@ +package com.github.franckyi.cmpdl.api.response; + +import com.github.franckyi.cmpdl.api.IBean; + +import java.util.List; + +public class Addon implements IBean { + + private int id; + private String name; + private List authors; + private List attachments; + private String websiteUrl; + private String summary; + private List latestFiles; + private List categories; + private int primaryCategoryId; + private CategorySection categorySection; + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public List getAuthors() { + return authors; + } + + public List getAttachments() { + return attachments; + } + + public String getWebsiteUrl() { + return websiteUrl; + } + + public String getSummary() { + return summary; + } + + public List getLatestFiles() { + return latestFiles; + } + + public List getCategories() { + return categories; + } + + public int getPrimaryCategoryId() { + return primaryCategoryId; + } + + public CategorySection getCategorySection() { + return categorySection; + } + +} diff --git a/src/main/java/com/github/franckyi/cmpdl/api/response/AddonFile.java b/src/main/java/com/github/franckyi/cmpdl/api/response/AddonFile.java new file mode 100644 index 0000000..def4bb6 --- /dev/null +++ b/src/main/java/com/github/franckyi/cmpdl/api/response/AddonFile.java @@ -0,0 +1,46 @@ +package com.github.franckyi.cmpdl.api.response; + +import com.github.franckyi.cmpdl.api.IBean; + +import java.time.Instant; +import java.util.List; + +public class AddonFile implements IBean { + + private int id; + private String displayName; + private String fileName; + private Instant fileDate; + private ReleaseType releaseType; + private String downloadUrl; + private List gameVersion; + + public int getId() { + return id; + } + + public String getDisplayName() { + return displayName; + } + + public String getFileName() { + return fileName; + } + + public Instant getFileDate() { + return fileDate; + } + + public ReleaseType getReleaseType() { + return releaseType; + } + + public String getDownloadUrl() { + return downloadUrl; + } + + public List getGameVersion() { + return gameVersion; + } + +} diff --git a/src/main/java/com/github/franckyi/cmpdl/api/response/Attachment.java b/src/main/java/com/github/franckyi/cmpdl/api/response/Attachment.java new file mode 100644 index 0000000..985ef4c --- /dev/null +++ b/src/main/java/com/github/franckyi/cmpdl/api/response/Attachment.java @@ -0,0 +1,18 @@ +package com.github.franckyi.cmpdl.api.response; + +import com.github.franckyi.cmpdl.api.IBean; + +public class Attachment implements IBean { + + private boolean isDefault; + private String thumbnailUrl; + + public boolean isDefault() { + return isDefault; + } + + public String getThumbnailUrl() { + return thumbnailUrl; + } + +} diff --git a/src/main/java/com/github/franckyi/cmpdl/api/response/Author.java b/src/main/java/com/github/franckyi/cmpdl/api/response/Author.java new file mode 100644 index 0000000..871a8b8 --- /dev/null +++ b/src/main/java/com/github/franckyi/cmpdl/api/response/Author.java @@ -0,0 +1,13 @@ +package com.github.franckyi.cmpdl.api.response; + +import com.github.franckyi.cmpdl.api.IBean; + +public class Author implements IBean { + + private String name; + + public String getName() { + return name; + } + +} diff --git a/src/main/java/com/github/franckyi/cmpdl/api/response/Category.java b/src/main/java/com/github/franckyi/cmpdl/api/response/Category.java new file mode 100644 index 0000000..c669e4c --- /dev/null +++ b/src/main/java/com/github/franckyi/cmpdl/api/response/Category.java @@ -0,0 +1,23 @@ +package com.github.franckyi.cmpdl.api.response; + +import com.github.franckyi.cmpdl.api.IBean; + +public class Category implements IBean { + + private int categoryId; + private String name; + private String avatarUrl; + + public int getCategoryId() { + return categoryId; + } + + public String getName() { + return name; + } + + public String getAvatarUrl() { + return avatarUrl; + } + +} diff --git a/src/main/java/com/github/franckyi/cmpdl/api/response/CategorySection.java b/src/main/java/com/github/franckyi/cmpdl/api/response/CategorySection.java new file mode 100644 index 0000000..0560fd5 --- /dev/null +++ b/src/main/java/com/github/franckyi/cmpdl/api/response/CategorySection.java @@ -0,0 +1,13 @@ +package com.github.franckyi.cmpdl.api.response; + +import com.github.franckyi.cmpdl.api.IBean; + +public class CategorySection implements IBean { + + private String name; + + public String getName() { + return name; + } + +} diff --git a/src/main/java/com/github/franckyi/cmpdl/api/response/ReleaseType.java b/src/main/java/com/github/franckyi/cmpdl/api/response/ReleaseType.java new file mode 100644 index 0000000..bf66ade --- /dev/null +++ b/src/main/java/com/github/franckyi/cmpdl/api/response/ReleaseType.java @@ -0,0 +1,27 @@ +package com.github.franckyi.cmpdl.api.response; + +import com.github.franckyi.cmpdl.api.IEnum; +import javafx.scene.paint.Color; + +public enum ReleaseType implements IEnum { + RELEASE(1, 20, 184, 102), + BETA(2, 14, 115, 216), + ALPHA(3, 126, 121, 139); + + private final int id; + private final Color color; + + ReleaseType(int id, int r, int g, int b) { + this.id = id; + this.color = Color.rgb(r, g, b); + } + + @Override + public int toJson() { + return id; + } + + public Color getColor() { + return color; + } +} diff --git a/src/main/java/com/github/franckyi/cmpdl/controller/DestinationPaneController.java b/src/main/java/com/github/franckyi/cmpdl/controller/DestinationPaneController.java index 91c290f..38353a9 100644 --- a/src/main/java/com/github/franckyi/cmpdl/controller/DestinationPaneController.java +++ b/src/main/java/com/github/franckyi/cmpdl/controller/DestinationPaneController.java @@ -1,17 +1,23 @@ package com.github.franckyi.cmpdl.controller; import com.github.franckyi.cmpdl.CMPDL; -import com.github.franckyi.cmpdl.model.Project; -import com.github.franckyi.cmpdl.model.ProjectFile; +import com.github.franckyi.cmpdl.api.response.Addon; +import com.github.franckyi.cmpdl.api.response.AddonFile; +import com.github.franckyi.cmpdl.api.response.Attachment; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; +import javafx.geometry.Insets; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.image.Image; import javafx.scene.image.ImageView; +import javafx.scene.layout.Background; +import javafx.scene.layout.BackgroundFill; +import javafx.scene.layout.CornerRadii; +import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.text.FontWeight; import javafx.stage.DirectoryChooser; @@ -22,8 +28,8 @@ public class DestinationPaneController implements Initializable, IContentController { - private Project project; - private ProjectFile file; + private Addon addon; + private AddonFile addonFile; @FXML private ImageView logoImageView; @@ -71,7 +77,7 @@ void actionChooseDestination(ActionEvent event) { @FXML void actionViewInBrowser(ActionEvent event) { - CMPDL.openBrowser(project.getUrl()); + CMPDL.openBrowser(addon.getWebsiteUrl()); } @Override @@ -102,7 +108,7 @@ public void handleStart() { if (!dst.canWrite()) { new Alert(Alert.AlertType.ERROR, "Permission denied. Please choose another destination folder.", ButtonType.OK).show(); } else { - CMPDL.progressPane.getController().setData(file, dst); + CMPDL.progressPane.getController().setData(addonFile, dst); CMPDL.mainWindow.getController().setContent(CMPDL.progressPane); CMPDL.mainWindow.getController().getStartButton().setDisable(true); CMPDL.mainWindow.getController().getPreviousButton().setDisable(true); @@ -113,18 +119,28 @@ public void handleStart() { } } - public void setProjectAndFile(Project project, ProjectFile file) { - this.project = project; - this.file = file; - logoImageView.setImage(new Image(project.getLogoUrl())); - titleLabel.setText(project.getName()); - authorLabel.setText("by " + project.getAuthor()); - summaryLabel.setText(project.getSummary()); - categoryImageView.setImage(new Image(project.getCategoryLogoUrl())); - categoryLabel.setText(project.getCategoryName()); - fileNameLabel.setText(file.getFileName()); - mcVersionLabel.setText(file.getGameVersion()); - releaseTypeLabel.setText(file.getFileType().toString()); - releaseTypeLabel.setTextFill(file.getColor()); + public void setAddonAndFile(Addon addon, AddonFile file) { + this.addon = addon; + this.addonFile = file; + addon.getAttachments().stream() + .filter(Attachment::isDefault) + .findFirst() + .ifPresent(a -> logoImageView.setImage(new Image(a.getThumbnailUrl()))); + titleLabel.setText(addon.getName()); + authorLabel.setText("by " + addon.getAuthors().get(0).getName()); + summaryLabel.setText(addon.getSummary()); + addon.getCategories().stream() + .filter(category -> category.getCategoryId() == addon.getPrimaryCategoryId()) + .findFirst() + .ifPresent(c -> { + categoryImageView.setImage(new Image(c.getAvatarUrl())); + categoryLabel.setText(c.getName()); + }); + fileNameLabel.setText(file.getDisplayName()); + mcVersionLabel.setText(String.join(", ", file.getGameVersion())); + releaseTypeLabel.setText(file.getReleaseType().toString()); + releaseTypeLabel.setBackground(new Background(new BackgroundFill(file.getReleaseType().getColor(), new CornerRadii(5), new Insets(-2, -5, -2, -5)))); + releaseTypeLabel.setTextFill(Color.WHITE); + } } diff --git a/src/main/java/com/github/franckyi/cmpdl/controller/FilePaneController.java b/src/main/java/com/github/franckyi/cmpdl/controller/FilePaneController.java index 862f31c..221c11e 100644 --- a/src/main/java/com/github/franckyi/cmpdl/controller/FilePaneController.java +++ b/src/main/java/com/github/franckyi/cmpdl/controller/FilePaneController.java @@ -1,12 +1,11 @@ package com.github.franckyi.cmpdl.controller; import com.github.franckyi.cmpdl.CMPDL; -import com.github.franckyi.cmpdl.model.IProjectFile; -import com.github.franckyi.cmpdl.model.Project; -import com.github.franckyi.cmpdl.model.ProjectFilesList; -import com.github.franckyi.cmpdl.task.cursemeta.GetProjectFileTask; -import com.github.franckyi.cmpdl.task.cursemeta.GetProjectFilesTask; -import com.github.franckyi.cmpdl.view.ProjectFileMinimalView; +import com.github.franckyi.cmpdl.api.response.Addon; +import com.github.franckyi.cmpdl.api.response.AddonFile; +import com.github.franckyi.cmpdl.api.response.Attachment; +import com.github.franckyi.cmpdl.task.api.CallTask; +import com.github.franckyi.cmpdl.view.AddonFileMinimalView; import javafx.application.Platform; import javafx.collections.ListChangeListener; import javafx.event.ActionEvent; @@ -18,12 +17,14 @@ import javafx.scene.layout.VBox; import java.net.URL; +import java.util.Comparator; +import java.util.List; import java.util.ResourceBundle; public class FilePaneController implements Initializable, IContentController { - private Project project; - private ProjectFilesList files = null; + private Addon addon; + private List files = null; @FXML private ImageView logoImageView; @@ -53,7 +54,7 @@ public class FilePaneController implements Initializable, IContentController { private VBox directPane; @FXML - private ListView filesListView; + private ListView filesListView; @FXML private Button changeViewButton; @@ -68,8 +69,8 @@ public class FilePaneController implements Initializable, IContentController { public void initialize(URL location, ResourceBundle resources) { directPane.disableProperty().bind(directButton.selectedProperty().not()); idField.disableProperty().bind(idButton.selectedProperty().not()); - filesListView.setCellFactory(param -> new ProjectFileMinimalView()); - filesListView.getSelectionModel().getSelectedItems().addListener((ListChangeListener) c -> { + filesListView.setCellFactory(param -> new AddonFileMinimalView()); + filesListView.getSelectionModel().getSelectedItems().addListener((ListChangeListener) c -> { if (CMPDL.currentContent == CMPDL.filePane && directButton.isSelected()) { CMPDL.mainWindow.getController().getNextButton().setDisable(c.getList().size() != 1); } @@ -87,28 +88,40 @@ private void viewAllFiles() { } public void viewLatestFiles() { - filesListView.getItems().setAll(project.getFiles()); + filesListView.getItems().setAll(addon.getLatestFiles()); changeViewButton.setText("View all files..."); changeViewButton.setOnAction(e -> viewAllFiles()); } @FXML void actionViewInBrowser(ActionEvent event) { - CMPDL.openBrowser(project.getUrl()); + CMPDL.openBrowser(addon.getWebsiteUrl()); } - public void setProject(Project project) { - this.project = project; - logoImageView.setImage(new Image(project.getLogoUrl())); - titleLabel.setText(project.getName()); - authorLabel.setText("by " + project.getAuthor()); - summaryLabel.setText(project.getSummary()); - categoryImageView.setImage(new Image(project.getCategoryLogoUrl())); - categoryLabel.setText(project.getCategoryName()); + public void setAddon(Addon addon) { + this.addon = addon; + addon.getLatestFiles().sort(Comparator.comparing(AddonFile::getFileDate).reversed()); + addon.getAttachments().stream() + .filter(Attachment::isDefault) + .findFirst() + .ifPresent(a -> logoImageView.setImage(new Image(a.getThumbnailUrl()))); + titleLabel.setText(addon.getName()); + authorLabel.setText("by " + addon.getAuthors().get(0).getName()); + summaryLabel.setText(addon.getSummary()); + addon.getCategories().stream() + .filter(category -> category.getCategoryId() == addon.getPrimaryCategoryId()) + .findFirst() + .ifPresent(c -> { + categoryImageView.setImage(new Image(c.getAvatarUrl())); + categoryLabel.setText(c.getName()); + }); CMPDL.mainWindow.getController().getNextButton().setDisable(true); CMPDL.mainWindow.getController().getPreviousButton().setDisable(false); - GetProjectFilesTask task = new GetProjectFilesTask(project.getProjectId()); + CallTask> task = new CallTask<>(String.format("Getting addon files for addon %d", addon.getId()), CMPDL.getAPI().getAddonFiles(addon.getId())); task.setOnSucceeded(e -> files = task.getValue().orElse(null)); + if (files != null) { + files.sort(Comparator.comparing(AddonFile::getFileDate).reversed()); + } CMPDL.EXECUTOR_SERVICE.execute(task); } @@ -116,10 +129,10 @@ public void setProject(Project project) { public void handleNext() { Alert alert = new Alert(Alert.AlertType.INFORMATION, "Loading file data...", ButtonType.CLOSE); alert.show(); - int fileId = file.getSelectedToggle() == directButton ? filesListView.getSelectionModel().getSelectedItem().getFileId() : Integer.parseInt(idField.getText()); - GetProjectFileTask task = new GetProjectFileTask(project.getProjectId(), fileId); + int fileId = file.getSelectedToggle() == directButton ? filesListView.getSelectionModel().getSelectedItem().getId() : Integer.parseInt(idField.getText()); + CallTask task = new CallTask<>(String.format("Getting project file %d:%d", addon.getId(), fileId), CMPDL.getAPI().getFile(addon.getId(), fileId)); task.setOnSucceeded(e -> Platform.runLater(() -> task.getValue().ifPresent(file -> { - CMPDL.destinationPane.getController().setProjectAndFile(project, file); + CMPDL.destinationPane.getController().setAddonAndFile(addon, file); CMPDL.mainWindow.getController().setContent(CMPDL.destinationPane); CMPDL.mainWindow.getController().getNextButton().setDisable(true); alert.hide(); @@ -132,6 +145,7 @@ public void handlePrevious() { CMPDL.mainWindow.getController().getStartButton().disableProperty().bind(CMPDL.modpackPane.getController().getZipButton().selectedProperty().not()); CMPDL.mainWindow.getController().getNextButton().disableProperty().bind(CMPDL.modpackPane.getController().getZipButton().selectedProperty()); CMPDL.mainWindow.getController().setContent(CMPDL.modpackPane); + CMPDL.mainWindow.getController().getNextButton().disableProperty().unbind(); CMPDL.mainWindow.getController().getNextButton().setDisable(false); CMPDL.mainWindow.getController().getPreviousButton().setDisable(true); } diff --git a/src/main/java/com/github/franckyi/cmpdl/controller/ModpackPaneController.java b/src/main/java/com/github/franckyi/cmpdl/controller/ModpackPaneController.java index 2132dea..9a3dd88 100644 --- a/src/main/java/com/github/franckyi/cmpdl/controller/ModpackPaneController.java +++ b/src/main/java/com/github/franckyi/cmpdl/controller/ModpackPaneController.java @@ -1,8 +1,9 @@ package com.github.franckyi.cmpdl.controller; import com.github.franckyi.cmpdl.CMPDL; -import com.github.franckyi.cmpdl.task.cursemeta.GetProjectIdTask; -import com.github.franckyi.cmpdl.task.cursemeta.GetProjectTask; +import com.github.franckyi.cmpdl.api.response.Addon; +import com.github.franckyi.cmpdl.task.api.CallTask; +import com.github.franckyi.cmpdl.task.api.GetProjectIdTask; import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.fxml.FXML; @@ -106,21 +107,21 @@ public void handleStart() { } } - public void handleNext(int projectId) { + public void handleNext(int addonId) { Alert alert = new Alert(Alert.AlertType.INFORMATION, "Loading project data...", ButtonType.CLOSE); alert.show(); - GetProjectTask task = new GetProjectTask(projectId); - task.setOnSucceeded(event -> Platform.runLater(() -> task.getValue().ifPresent(project -> { - if (project.isModpack()) { + CallTask task = new CallTask<>(String.format("Getting project data for project %d", addonId), CMPDL.getAPI().getAddon(addonId)); + task.setOnSucceeded(event -> Platform.runLater(() -> task.getValue().ifPresent(addon -> { + if (addon.getCategorySection().getName().equals("Modpacks")) { CMPDL.mainWindow.getController().getStartButton().disableProperty().unbind(); CMPDL.mainWindow.getController().getNextButton().disableProperty().unbind(); - CMPDL.filePane.getController().setProject(project); + CMPDL.filePane.getController().setAddon(addon); CMPDL.filePane.getController().viewLatestFiles(); CMPDL.mainWindow.getController().setContent(CMPDL.filePane); alert.hide(); } else { alert.hide(); - new Alert(Alert.AlertType.ERROR, "The project isn't a modpack !", ButtonType.OK).show(); + new Alert(Alert.AlertType.ERROR, "The addon isn't a modpack !", ButtonType.OK).show(); } }))); CMPDL.EXECUTOR_SERVICE.execute(task); diff --git a/src/main/java/com/github/franckyi/cmpdl/controller/ProgressPaneController.java b/src/main/java/com/github/franckyi/cmpdl/controller/ProgressPaneController.java index 2520b11..b8cd553 100644 --- a/src/main/java/com/github/franckyi/cmpdl/controller/ProgressPaneController.java +++ b/src/main/java/com/github/franckyi/cmpdl/controller/ProgressPaneController.java @@ -1,8 +1,8 @@ package com.github.franckyi.cmpdl.controller; import com.github.franckyi.cmpdl.CMPDL; +import com.github.franckyi.cmpdl.api.response.AddonFile; import com.github.franckyi.cmpdl.model.ModpackManifest; -import com.github.franckyi.cmpdl.model.ProjectFile; import com.github.franckyi.cmpdl.task.mpimport.*; import javafx.application.Platform; import javafx.concurrent.Task; @@ -20,7 +20,7 @@ public class ProgressPaneController implements Initializable, IContentController private Task task1, task2; private boolean done = false; - private ProjectFile projectFile; + private AddonFile addonFile; private File destination, zipFile, unzipFolder, minecraft, modsFolder, temp, progressFile; private ModpackManifest manifest; @@ -85,8 +85,8 @@ public void handleClose() { } } - public void setData(ProjectFile projectFile, File destination) { - this.projectFile = projectFile; + public void setData(AddonFile addonFile, File destination) { + this.addonFile = addonFile; this.destination = destination; minecraft = new File(destination, "minecraft"); minecraft.mkdirs(); @@ -95,8 +95,8 @@ public void setData(ProjectFile projectFile, File destination) { temp = new File(destination, ".cmpdl_temp"); temp.mkdirs(); progressFile = new File(temp, ".progress"); - zipFile = new File(temp, projectFile.getFileNameOnDisk()); - unzipFolder = new File(temp, projectFile.getFileNameOnDisk().replace(".zip", "")); + zipFile = new File(temp, addonFile.getFileName()); + unzipFolder = new File(temp, addonFile.getFileName().replace(".zip", "")); unzipFolder.mkdirs(); } @@ -155,7 +155,7 @@ public void start() { private void downloadModpack() { log("Downloading modpack"); - DownloadFileTask task = new DownloadFileTask(projectFile.getDownloadUrl(), new File(temp, projectFile.getFileNameOnDisk())); + DownloadFileTask task = new DownloadFileTask(addonFile.getDownloadUrl(), new File(temp, addonFile.getFileName())); task.setOnSucceeded(e -> { log("Modpack downloaded successfully"); unzipModpack(); diff --git a/src/main/java/com/github/franckyi/cmpdl/model/FileReleaseType.java b/src/main/java/com/github/franckyi/cmpdl/model/FileReleaseType.java deleted file mode 100644 index 358980a..0000000 --- a/src/main/java/com/github/franckyi/cmpdl/model/FileReleaseType.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.github.franckyi.cmpdl.model; - -public enum FileReleaseType { - ALPHA, - BETA, - RELEASE, -} diff --git a/src/main/java/com/github/franckyi/cmpdl/model/IProjectFile.java b/src/main/java/com/github/franckyi/cmpdl/model/IProjectFile.java deleted file mode 100644 index 6380c6c..0000000 --- a/src/main/java/com/github/franckyi/cmpdl/model/IProjectFile.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.github.franckyi.cmpdl.model; - -import javafx.scene.paint.Color; -import javafx.scene.paint.Paint; - -import java.util.Comparator; - -public interface IProjectFile extends Comparable { - - int getFileId(); - - /** - * Parses the integer type provided by api to FileReleaseType - * - * @param releaseType the integer received from API - * @return FileReleaseType - * @throws Exception Thrown when the release type could not be determined - */ - default FileReleaseType parseFileType(int releaseType) throws Exception { - switch (releaseType) { - case 1: - return FileReleaseType.RELEASE; - case 2: - return FileReleaseType.BETA; - case 3: - return FileReleaseType.ALPHA; - default: - throw new Exception("Failed to find release type for id " + releaseType); - } - } - - String getFileName(); - - String getGameVersion(); - - FileReleaseType getFileType(); - - @Override - default int compareTo(IProjectFile o) { - return Comparator.comparingInt(IProjectFile::getFileId).reversed().compare(this, o); - } - - default Paint getColor() { - switch (getFileType()) { - case ALPHA: - return Color.web("#E49788"); - case BETA: - return Color.web("#7FA5C4"); - case RELEASE: - return Color.web("#8CAF62"); - default: - return Color.BLACK; - } - } -} diff --git a/src/main/java/com/github/franckyi/cmpdl/model/Project.java b/src/main/java/com/github/franckyi/cmpdl/model/Project.java deleted file mode 100644 index c6f998b..0000000 --- a/src/main/java/com/github/franckyi/cmpdl/model/Project.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.github.franckyi.cmpdl.model; - -import org.json.JSONArray; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class Project { - - private static final int PACKAGE_TYPE_MODPACK = 5; - - private final int projectId; - private final String name; - private final String author; - private final String summary; - private final String logoUrl; - private final String url; - private final String categoryName; - private final String categoryLogoUrl; - private final boolean modpack; - private final List files; - - public Project(JSONObject json) { - projectId = json.getInt("id"); - name = json.getString("name"); - author = json.getString("primaryAuthorName"); - summary = json.getString("summary"); - logoUrl = json.getJSONArray("attachments").getJSONObject(0).getString("url"); - url = json.getString("websiteUrl"); - categoryName = json.getString("primaryCategoryName"); - categoryLogoUrl = json.getString("primaryCategoryAvatarUrl"); - modpack = json.getInt("packageType") == PACKAGE_TYPE_MODPACK; - JSONArray array = json.getJSONArray("gameVersionLatestFiles"); - files = new ArrayList<>(array.length()); - for (int i = 0; i < array.length(); i++) { - files.add(new ProjectFileMinimal(array.getJSONObject(i))); - } - Collections.sort(files); - } - - public int getProjectId() { - return projectId; - } - - public String getName() { - return name; - } - - public String getAuthor() { - return author; - } - - public String getSummary() { - return summary; - } - - public String getLogoUrl() { - return logoUrl; - } - - public String getUrl() { - return url; - } - - public String getCategoryName() { - return categoryName; - } - - public String getCategoryLogoUrl() { - return categoryLogoUrl; - } - - public boolean isModpack() { - return modpack; - } - - public List getFiles() { - return files; - } -} diff --git a/src/main/java/com/github/franckyi/cmpdl/model/ProjectFile.java b/src/main/java/com/github/franckyi/cmpdl/model/ProjectFile.java deleted file mode 100644 index 4d33676..0000000 --- a/src/main/java/com/github/franckyi/cmpdl/model/ProjectFile.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.github.franckyi.cmpdl.model; - -import org.json.JSONObject; - -public class ProjectFile implements IProjectFile { - - private final String fileName; - private final String fileNameOnDisk; - private final String gameVersion; - private FileReleaseType fileType; - private final int fileId; - private final String downloadUrl; - - public ProjectFile(JSONObject json) { - fileName = json.getString("fileName"); - fileNameOnDisk = json.getString("fileNameOnDisk"); - gameVersion = json.getJSONArray("gameVersion").getString(0); - try { - fileType = parseFileType(json.getInt("releaseType")); - } catch (Exception e) { - fileType = FileReleaseType.ALPHA; - e.printStackTrace(); - } - fileId = json.getInt("id"); - downloadUrl = json.getString("downloadUrl"); - } - - @Override - public int getFileId() { - return fileId; - } - - @Override - public String getFileName() { - return fileName; - } - - public String getFileNameOnDisk() { - return fileNameOnDisk; - } - - @Override - public String getGameVersion() { - return gameVersion; - } - - @Override - public FileReleaseType getFileType() { - return fileType; - } - - public String getDownloadUrl() { - return downloadUrl; - } -} diff --git a/src/main/java/com/github/franckyi/cmpdl/model/ProjectFileMinimal.java b/src/main/java/com/github/franckyi/cmpdl/model/ProjectFileMinimal.java deleted file mode 100644 index b13f769..0000000 --- a/src/main/java/com/github/franckyi/cmpdl/model/ProjectFileMinimal.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.github.franckyi.cmpdl.model; - -import org.json.JSONObject; - -public class ProjectFileMinimal implements IProjectFile { - - private final String fileName; - private final String gameVersion; - private FileReleaseType fileType; - private final int fileId; - - ProjectFileMinimal(JSONObject json) { - fileName = json.getString("projectFileName"); - gameVersion = json.getString("gameVersion"); - try { - fileType = parseFileType(json.getInt("fileType")); - } catch (Exception e) { - fileType = FileReleaseType.ALPHA; - e.printStackTrace(); - } - fileId = json.getInt("projectFileId"); - } - - public String getFileName() { - return fileName; - } - - public String getGameVersion() { - return gameVersion; - } - - @Override - public FileReleaseType getFileType() { - return fileType; - } - - public int getFileId() { - return fileId; - } -} diff --git a/src/main/java/com/github/franckyi/cmpdl/model/ProjectFilesList.java b/src/main/java/com/github/franckyi/cmpdl/model/ProjectFilesList.java deleted file mode 100644 index 3577728..0000000 --- a/src/main/java/com/github/franckyi/cmpdl/model/ProjectFilesList.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.github.franckyi.cmpdl.model; - -import org.json.JSONArray; - -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class ProjectFilesList extends AbstractList { - - private final List list; - - public ProjectFilesList(JSONArray json) { - list = new ArrayList<>(json.length()); - for (int i = 0; i < json.length(); i++) { - list.add(new ProjectFile(json.getJSONObject(i))); - } - Collections.sort(list); - } - - @Override - public ProjectFile get(int index) { - return list.get(index); - } - - @Override - public int size() { - return list.size(); - } -} diff --git a/src/main/java/com/github/franckyi/cmpdl/task/api/CallTask.java b/src/main/java/com/github/franckyi/cmpdl/task/api/CallTask.java new file mode 100644 index 0000000..2d06372 --- /dev/null +++ b/src/main/java/com/github/franckyi/cmpdl/task/api/CallTask.java @@ -0,0 +1,23 @@ +package com.github.franckyi.cmpdl.task.api; + +import com.github.franckyi.cmpdl.task.TaskBase; +import retrofit2.Call; + +import java.io.IOException; + +public class CallTask extends TaskBase { + + private final String title; + private final Call call; + + public CallTask(String title, Call call) { + this.title = title; + this.call = call; + } + + @Override + protected T call0() throws IOException { + updateTitle(title); + return call.execute().body(); + } +} diff --git a/src/main/java/com/github/franckyi/cmpdl/task/cursemeta/GetProjectIdTask.java b/src/main/java/com/github/franckyi/cmpdl/task/api/GetProjectIdTask.java similarity index 79% rename from src/main/java/com/github/franckyi/cmpdl/task/cursemeta/GetProjectIdTask.java rename to src/main/java/com/github/franckyi/cmpdl/task/api/GetProjectIdTask.java index 4fde0fc..84251b6 100644 --- a/src/main/java/com/github/franckyi/cmpdl/task/cursemeta/GetProjectIdTask.java +++ b/src/main/java/com/github/franckyi/cmpdl/task/api/GetProjectIdTask.java @@ -1,10 +1,9 @@ -package com.github.franckyi.cmpdl.task.cursemeta; +package com.github.franckyi.cmpdl.task.api; import com.github.franckyi.cmpdl.task.TaskBase; import javafx.application.Platform; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; -import org.json.JSONObject; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; @@ -27,9 +26,9 @@ protected Integer call0() { URL url = new URL(projectUrl); Document doc = Jsoup.parse(url, 10000); if (url.getHost().equals("www.curseforge.com")) { - return new JSONObject(doc.select("a.button--twitch").get(0).attr("data-action-value")).getInt("ProjectID"); + return Integer.parseInt(doc.select("div.mb-3:nth-child(2) > div:nth-child(1) > span:nth-child(2)").html()); } else { - return Integer.parseInt(doc.select("ul.cf-details.project-details").get(0).child(0).child(1).html()); + return Integer.parseInt(doc.select(".fa-icon-twitch").attr("data-id")); } } catch (MalformedURLException e) { e.printStackTrace(); diff --git a/src/main/java/com/github/franckyi/cmpdl/task/cursemeta/GetProjectFileTask.java b/src/main/java/com/github/franckyi/cmpdl/task/cursemeta/GetProjectFileTask.java deleted file mode 100644 index 3b67eca..0000000 --- a/src/main/java/com/github/franckyi/cmpdl/task/cursemeta/GetProjectFileTask.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.github.franckyi.cmpdl.task.cursemeta; - -import com.github.franckyi.cmpdl.CurseMetaAPI; -import com.github.franckyi.cmpdl.model.ProjectFile; -import com.github.franckyi.cmpdl.task.TaskBase; - -public class GetProjectFileTask extends TaskBase { - - private final int projectId, fileId; - - public GetProjectFileTask(int projectId, int fileId) { - this.projectId = projectId; - this.fileId = fileId; - } - - @Override - protected ProjectFile call0() { - updateTitle(String.format("Getting project file %d:%d", projectId, fileId)); - return CurseMetaAPI.getProjectFile(projectId, fileId); - } -} diff --git a/src/main/java/com/github/franckyi/cmpdl/task/cursemeta/GetProjectFilesTask.java b/src/main/java/com/github/franckyi/cmpdl/task/cursemeta/GetProjectFilesTask.java deleted file mode 100644 index a74b31a..0000000 --- a/src/main/java/com/github/franckyi/cmpdl/task/cursemeta/GetProjectFilesTask.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.github.franckyi.cmpdl.task.cursemeta; - -import com.github.franckyi.cmpdl.CurseMetaAPI; -import com.github.franckyi.cmpdl.model.ProjectFilesList; -import com.github.franckyi.cmpdl.task.TaskBase; - -public class GetProjectFilesTask extends TaskBase { - - private final int projectId; - - public GetProjectFilesTask(int projectId) { - this.projectId = projectId; - } - - @Override - protected ProjectFilesList call0() { - updateTitle(String.format("Getting project files for project %d", projectId)); - return CurseMetaAPI.getProjectFiles(projectId); - } -} diff --git a/src/main/java/com/github/franckyi/cmpdl/task/cursemeta/GetProjectTask.java b/src/main/java/com/github/franckyi/cmpdl/task/cursemeta/GetProjectTask.java deleted file mode 100644 index 5140019..0000000 --- a/src/main/java/com/github/franckyi/cmpdl/task/cursemeta/GetProjectTask.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.github.franckyi.cmpdl.task.cursemeta; - -import com.github.franckyi.cmpdl.CurseMetaAPI; -import com.github.franckyi.cmpdl.model.Project; -import com.github.franckyi.cmpdl.task.TaskBase; - -public class GetProjectTask extends TaskBase { - - private final int projectId; - - public GetProjectTask(int projectId) { - this.projectId = projectId; - } - - @Override - protected Project call0() { - updateTitle(String.format("Getting project data for project %d", projectId)); - return CurseMetaAPI.getProject(projectId); - } -} diff --git a/src/main/java/com/github/franckyi/cmpdl/task/mpimport/DownloadModsTask.java b/src/main/java/com/github/franckyi/cmpdl/task/mpimport/DownloadModsTask.java index cf1dcd5..83b9db2 100644 --- a/src/main/java/com/github/franckyi/cmpdl/task/mpimport/DownloadModsTask.java +++ b/src/main/java/com/github/franckyi/cmpdl/task/mpimport/DownloadModsTask.java @@ -1,9 +1,8 @@ package com.github.franckyi.cmpdl.task.mpimport; import com.github.franckyi.cmpdl.CMPDL; -import com.github.franckyi.cmpdl.CurseMetaAPI; +import com.github.franckyi.cmpdl.api.response.AddonFile; import com.github.franckyi.cmpdl.model.ModpackManifest; -import com.github.franckyi.cmpdl.model.ProjectFile; import com.github.franckyi.cmpdl.task.TaskBase; import javafx.application.Platform; import javafx.beans.property.ObjectProperty; @@ -54,9 +53,9 @@ protected Void call0() throws IOException { updateTitle(String.format("Downloading mods (%d/%d)", i + 1, max)); ModpackManifest.ModpackManifestMod mod = mods.get(i - start); CMPDL.progressPane.getController().log("Resolving file %d:%d", mod.getProjectId(), mod.getFileId()); - ProjectFile file = CurseMetaAPI.getProjectFile(mod.getProjectId(), mod.getFileId()); + AddonFile file = CMPDL.getAPI().getFile(mod.getProjectId(), mod.getFileId()).execute().body(); if (file != null) { - DownloadFileTask task = new DownloadFileTask(file.getDownloadUrl(), new File(modsFolder, file.getFileNameOnDisk())); + DownloadFileTask task = new DownloadFileTask(file.getDownloadUrl(), new File(modsFolder, file.getFileName())); setTask(task); CMPDL.progressPane.getController().log("Downloading file %s", file.getFileName().replaceAll("%", "")); task.setOnSucceeded(e -> { diff --git a/src/main/java/com/github/franckyi/cmpdl/view/AddonFileMinimalView.java b/src/main/java/com/github/franckyi/cmpdl/view/AddonFileMinimalView.java new file mode 100644 index 0000000..95e3055 --- /dev/null +++ b/src/main/java/com/github/franckyi/cmpdl/view/AddonFileMinimalView.java @@ -0,0 +1,44 @@ +package com.github.franckyi.cmpdl.view; + +import com.github.franckyi.cmpdl.api.response.AddonFile; +import javafx.geometry.Insets; +import javafx.scene.control.Label; +import javafx.scene.control.ListCell; +import javafx.scene.layout.Background; +import javafx.scene.layout.BackgroundFill; +import javafx.scene.layout.CornerRadii; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import javafx.scene.text.Font; +import javafx.scene.text.FontWeight; + +public class AddonFileMinimalView extends ListCell { + + private final VBox root = new VBox(5); + private final Label fileName = new Label(); + private final Label gameVersion = new Label(); + private final Label fileType = new Label(); + + public AddonFileMinimalView() { + fileName.setFont(Font.font(Font.getDefault().getFamily(), FontWeight.BOLD, 16)); + fileType.setFont(Font.font(Font.getDefault().getFamily(), FontWeight.BOLD, Font.getDefault().getSize())); + root.getChildren().addAll(fileName, gameVersion, fileType); + VBox.setMargin(fileType, new Insets(0, 0, 0, 2)); + } + + @Override + protected void updateItem(AddonFile item, boolean empty) { + super.updateItem(item, empty); + if (empty) { + setGraphic(null); + } else { + fileName.setText(item.getDisplayName()); + gameVersion.setText("for MC " + String.join(", ", item.getGameVersion())); + fileType.setText(item.getReleaseType().toString()); + fileType.setBackground(new Background(new BackgroundFill(item.getReleaseType().getColor(), new CornerRadii(5), new Insets(-2, -5, -2, -5)))); + fileType.setTextFill(Color.WHITE); + setGraphic(root); + } + } + +} diff --git a/src/main/java/com/github/franckyi/cmpdl/view/ProjectFileMinimalView.java b/src/main/java/com/github/franckyi/cmpdl/view/ProjectFileMinimalView.java deleted file mode 100644 index d164aa8..0000000 --- a/src/main/java/com/github/franckyi/cmpdl/view/ProjectFileMinimalView.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.github.franckyi.cmpdl.view; - -import com.github.franckyi.cmpdl.model.IProjectFile; -import javafx.scene.control.Label; -import javafx.scene.control.ListCell; -import javafx.scene.layout.VBox; -import javafx.scene.text.Font; -import javafx.scene.text.FontWeight; - -public class ProjectFileMinimalView extends ListCell { - - private final VBox root = new VBox(5); - private final Label fileName = new Label(); - private final Label gameVersion = new Label(); - private final Label fileType = new Label(); - - public ProjectFileMinimalView() { - fileName.setFont(Font.font(Font.getDefault().getFamily(), FontWeight.BOLD, 16)); - fileType.setFont(Font.font(Font.getDefault().getFamily(), FontWeight.BOLD, Font.getDefault().getSize())); - root.getChildren().addAll(fileName, gameVersion, fileType); - } - - @Override - protected void updateItem(IProjectFile item, boolean empty) { - super.updateItem(item, empty); - if (empty) { - setGraphic(null); - } else { - fileName.setText(item.getFileName()); - gameVersion.setText("for MC " + item.getGameVersion()); - fileType.setText(item.getFileType().toString()); - fileType.setTextFill(item.getColor()); - setGraphic(root); - } - } - -} diff --git a/src/main/resources/fxml/DestinationPane.fxml b/src/main/resources/fxml/DestinationPane.fxml index 619df7b..d65bb16 100644 --- a/src/main/resources/fxml/DestinationPane.fxml +++ b/src/main/resources/fxml/DestinationPane.fxml @@ -6,7 +6,7 @@ - + @@ -59,7 +58,11 @@