Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the repository URL #3192

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions .idea/runConfigurations/Main.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ dependencies {
implementation("io.projectreactor.addons:reactor-extra")
implementation("io.projectreactor:reactor-tools")

def commonsVersion = "1013d75fc9"
def commonsVersion = "9c1978d235"

implementation("com.github.FAForever.faf-java-commons:faf-commons-data:${commonsVersion}") {
exclude module: 'guava'
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/com/faforever/client/domain/api/Mod.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

import com.faforever.client.domain.server.PlayerInfo;

import java.net.URL;

public record Mod(
Integer id,
String displayName,
boolean recommended, String author, PlayerInfo uploader, ReviewsSummary reviewsSummary
URL repositoryURL,
boolean recommended,
String author,
PlayerInfo uploader,
ReviewsSummary reviewsSummary
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ public record ModVersion(
ComparableVersion version,
URL thumbnailUrl,
URL downloadUrl,
ModType modType, boolean ranked, boolean hidden, Mod mod,
ModType modType,
boolean ranked,
boolean hidden,
Mod mod,
OffsetDateTime createTime,
OffsetDateTime updateTime
) {}
2 changes: 2 additions & 0 deletions src/main/java/com/faforever/client/mapstruct/ModMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public interface ModMapper {
@Mapping(target = "modType", source = "modInfo.uiOnly")
@Mapping(target = "mod", expression = "java(new ModBean())")
@Mapping(target = "mod.displayName", source = "modInfo.name")
@Mapping(target = "mod.repositoryURL", source = "modInfo.url")
ModVersion map(com.faforever.commons.mod.Mod modInfo, Path basePath);

default ModType mapModType(boolean isUIOnly) {
Expand All @@ -33,6 +34,7 @@ default Path mapImagePath(com.faforever.commons.mod.Mod modInfo, Path basePath)
}

@Mapping(target = "reviewsSummary", source = "modReviewsSummary")
@Mapping(target = "repositoryURL", source = "repositoryUrl")
Mod map(com.faforever.commons.api.dto.Mod dto);

@InheritInverseConfiguration
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/com/faforever/client/mod/ModDetailController.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.faforever.client.fx.ImageViewHelper;
import com.faforever.client.fx.JavaFxUtil;
import com.faforever.client.fx.NodeController;
import com.faforever.client.fx.PlatformService;
import com.faforever.client.fx.SimpleChangeListener;
import com.faforever.client.fx.contextmenu.ContextMenuBuilder;
import com.faforever.client.i18n.I18n;
Expand All @@ -29,6 +30,7 @@
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.ScrollPane;
Expand All @@ -43,12 +45,16 @@
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.net.URL;
import java.util.Objects;

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Slf4j
@RequiredArgsConstructor
public class ModDetailController extends NodeController<Node> {

private final PlatformService platformService;
private final ModService modService;
private final NotificationService notificationService;
private final I18n i18n;
Expand Down Expand Up @@ -81,6 +87,7 @@ public class ModDetailController extends NodeController<Node> {
public Node modDetailRoot;
public ReviewsController<ModVersionReview> reviewsController;
public Label authorLabel;
public Hyperlink urlHyperlink;

@Override
protected void onInitialize() {
Expand All @@ -98,6 +105,20 @@ protected void onInitialize() {
bindProperties();
modVersion.addListener((SimpleChangeListener<ModVersion>) this::onModVersionChanged);

urlHyperlink.setOnAction(event -> {
ModVersion modVersionCurrent = modVersion.get();
if (modVersionCurrent == null) {
return;
}

URL repositoryURL = modVersionCurrent.mod().repositoryURL();
if (repositoryURL == null) {
return;
}

platformService.showDocument(repositoryURL.toString());
});

// TODO hidden until dependencies are available
dependenciesTitle.setManaged(false);
dependenciesContainer.setManaged(false);
Expand All @@ -109,7 +130,11 @@ private void bindProperties() {
.bind(modVersion.map(modService::loadThumbnail)
.flatMap(imageViewHelper::createPlaceholderImageOnErrorObservable)
.when(showing));

nameLabel.textProperty().bind(modObservable.map(Mod::displayName).when(showing));

urlHyperlink.visibleProperty().bind(modObservable.map(Mod::repositoryURL).map(Objects::nonNull).when(showing));

authorLabel.textProperty().bind(modObservable.map(Mod::author)
.map(author -> i18n.get("modVault.details.author", author))
.when(showing));
Expand Down
22 changes: 19 additions & 3 deletions src/main/java/com/faforever/client/mod/ModUploadTask.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
package com.faforever.client.mod;

import com.faforever.client.api.FafApiAccessor;
import com.faforever.client.domain.api.ModVersion;
import com.faforever.client.i18n.I18n;
import com.faforever.client.preferences.DataPrefs;
import com.faforever.client.task.CompletableTask;
import com.faforever.client.task.ResourceLocks;
import com.faforever.client.util.Validator;
import com.faforever.commons.io.ByteCountListener;
import com.faforever.commons.io.Zipper;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

Expand All @@ -29,15 +33,17 @@
@Slf4j
public class ModUploadTask extends CompletableTask<Void> {

private final ModService modService;
private final FafApiAccessor fafApiAccessor;
private final I18n i18n;
private final DataPrefs dataPrefs;

private Path modPath;

@Autowired
public ModUploadTask(FafApiAccessor fafApiAccessor, I18n i18n, DataPrefs dataPrefs) {
public ModUploadTask(ModService modService, FafApiAccessor fafApiAccessor, I18n i18n, DataPrefs dataPrefs) {
super(Priority.HIGH);
this.modService = modService;
this.dataPrefs = dataPrefs;
this.fafApiAccessor = fafApiAccessor;
this.i18n = i18n;
Expand All @@ -53,6 +59,16 @@ protected Void call() throws Exception {
Path tmpFile = createTempFile(cacheDirectory, "mod", ".zip");

try {

log.debug("Retrieve information from mod_info.lua at: {}", modPath);
ModVersion modVersionInfo = modService.extractModInfo(modPath);
URL repositoryURL = modVersionInfo.mod().repositoryURL();

HashMap<String, String> parameters = new HashMap<>();
if (repositoryURL != null) {
parameters.put("repositoryUrl", repositoryURL.toString());
}

log.debug("Zipping mod `{}` to `{}`", modPath, tmpFile);
updateTitle(i18n.get("modVault.upload.compressing"));

Expand All @@ -72,7 +88,7 @@ protected Void call() throws Exception {
log.debug("Uploading mod `{}` as `{}`", modPath, tmpFile);
updateTitle(i18n.get("modVault.upload.uploading"));

return fafApiAccessor.uploadFile("/mods/upload", tmpFile, byteListener, Map.of()).block();
return fafApiAccessor.uploadFile("/mods/upload", tmpFile, byteListener, Map.of("metadata", parameters)).block();
} finally {
Files.delete(tmpFile);
ResourceLocks.freeUploadLock();
Expand All @@ -82,4 +98,4 @@ protected Void call() throws Exception {
public void setModPath(Path modPath) {
this.modPath = modPath;
}
}
}
1 change: 1 addition & 0 deletions src/main/resources/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ map.versionId = Map version ID
vault.replays.ownReplays = Your replays
modVault.details.uploader = Uploaded by\: {0}
modVault.details.author = Authored by\: {0}
modVault.details.source = Source
gameSelect.select.invalidPath = Invalid path
gamePath.select.noneChosen = You did not select a game location\!
gamePath.select.noValidExe = The specified location does not contain a valid Supreme Commander.exe and is therefore is no valid Forged Alliance installation.
Expand Down
78 changes: 29 additions & 49 deletions src/main/resources/theme/vault/mod/mod_detail.fxml
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import java.lang.String?>
<AnchorPane fx:id="modDetailRoot" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" onMouseClicked="#onDimmerClicked" styleClass="dimmer" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.faforever.client.mod.ModDetailController">
<?import java.lang.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>

<AnchorPane fx:id="modDetailRoot" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" onMouseClicked="#onDimmerClicked" styleClass="dimmer" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.faforever.client.mod.ModDetailController">
<children>
<AnchorPane onMouseClicked="#onContentPaneClicked" styleClass="modal-popup" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="50.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="50.0">
<children>
Expand All @@ -30,54 +22,42 @@
<ColumnConstraints />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="NEVER"/>
<RowConstraints minHeight="10.0" vgrow="NEVER"/>
<RowConstraints fillHeight="false" minHeight="10.0" vgrow="ALWAYS"/>
<RowConstraints fillHeight="false" minHeight="10.0" vgrow="ALWAYS"/>
<RowConstraints fillHeight="false" minHeight="10.0" vgrow="ALWAYS"/>
<RowConstraints minHeight="10.0" vgrow="NEVER" />
<RowConstraints minHeight="10.0" vgrow="NEVER" />
<RowConstraints fillHeight="false" minHeight="10.0" vgrow="ALWAYS" />
<RowConstraints fillHeight="false" minHeight="10.0" vgrow="ALWAYS" />
<RowConstraints fillHeight="false" minHeight="10.0" vgrow="ALWAYS" />
</rowConstraints>
<children>
<Label fx:id="nameLabel" maxWidth="1.7976931348623157E308" styleClass="h1"
text="&lt;Name&gt;" GridPane.columnIndex="1" GridPane.columnSpan="2"/>
<ImageView fx:id="thumbnailImageView" fitHeight="128.0" fitWidth="128.0"
pickOnBounds="true" preserveRatio="true" GridPane.rowSpan="2"/>
<VBox fx:id="progressPane" alignment="CENTER_LEFT" maxWidth="300.0"
GridPane.columnIndex="2" GridPane.halignment="RIGHT"
GridPane.rowIndex="1">
<Label fx:id="nameLabel" maxWidth="1.7976931348623157E308" styleClass="h1" text="&lt;Name&gt;" GridPane.columnIndex="1" GridPane.columnSpan="2" />
<ImageView fx:id="thumbnailImageView" fitHeight="128.0" fitWidth="128.0" pickOnBounds="true" preserveRatio="true" GridPane.rowSpan="2" />
<VBox fx:id="progressPane" alignment="CENTER_LEFT" maxWidth="300.0" GridPane.columnIndex="2" GridPane.halignment="RIGHT" GridPane.rowIndex="1">
<children>
<Label fx:id="progressLabel" text=""/>
<ProgressBar fx:id="progressBar" maxWidth="1.7976931348623157E308"
progress="0.0"/>
<Label fx:id="progressLabel" text="" />
<ProgressBar fx:id="progressBar" maxWidth="1.7976931348623157E308" progress="0.0" />
</children>
</VBox>
<Button fx:id="uninstallButton" mnemonicParsing="false" styleClass="uninstall-button"
onAction="#onUninstallButtonClicked" text="%modVault.uninstall"
GridPane.columnIndex="3" GridPane.halignment="RIGHT"
GridPane.rowIndex="1"/>
<Button fx:id="installButton" defaultButton="true" mnemonicParsing="false"
onAction="#onInstallButtonClicked" styleClass="highlighted-button"
text="%modVault.installButtonFormat" GridPane.columnIndex="3"
GridPane.halignment="RIGHT" GridPane.rowIndex="1"/>
<Button fx:id="uninstallButton" mnemonicParsing="false" onAction="#onUninstallButtonClicked" styleClass="uninstall-button" text="%modVault.uninstall" GridPane.columnIndex="3" GridPane.halignment="RIGHT" GridPane.rowIndex="1" />
<Button fx:id="installButton" defaultButton="true" mnemonicParsing="false" onAction="#onInstallButtonClicked" styleClass="highlighted-button" text="%modVault.installButtonFormat" GridPane.columnIndex="3" GridPane.halignment="RIGHT" GridPane.rowIndex="1" />
<VBox GridPane.columnIndex="1" GridPane.rowIndex="1">
<children>
<Label fx:id="authorLabel" text="&lt;Author&gt;"/>
<Label fx:id="idLabel" text="&lt;ID&gt;"/>
<Label fx:id="uploaderLabel" text="&lt;Uploader&gt;" wrapText="true"/>
<Label fx:id="authorLabel" text="&lt;Author&gt;" />
<Label fx:id="idLabel" text="&lt;ID&gt;" />
<Label fx:id="uploaderLabel" text="&lt;Uploader&gt;" wrapText="true" />
<Hyperlink fx:id="urlHyperlink" text="%modVault.details.source" />
</children>
</VBox>
</children>
</GridPane>
<Label fx:id="modDescriptionLabel" maxHeight="1.7976931348623157E308"
maxWidth="1.7976931348623157E308" text="&lt;Description&gt;" wrapText="true"
GridPane.vgrow="ALWAYS"/>
<Separator layoutX="10.0" layoutY="251.0" maxWidth="1.7976931348623157E308"/>
<Label fx:id="modDescriptionLabel" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" text="&lt;Description&gt;" wrapText="true" GridPane.vgrow="ALWAYS" />
<Separator layoutX="10.0" layoutY="251.0" maxWidth="1.7976931348623157E308" />
<VBox alignment="TOP_CENTER" maxWidth="640.0">
<children>
<fx:include fx:id="reviews" source="../review/reviews.fxml"/>
<fx:include fx:id="reviews" source="../review/reviews.fxml" />
</children>
</VBox>
<Separator prefWidth="200.0"/>
<Label layoutX="10.0" layoutY="204.0" styleClass="h2" text="%mod.detail.moreInfo"/>
<Separator prefWidth="200.0" />
<Label layoutX="10.0" layoutY="204.0" styleClass="h2" text="%mod.detail.moreInfo" />
<GridPane hgap="20.0" maxWidth="640.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
Expand Down Expand Up @@ -108,7 +88,7 @@
</ScrollPane>
<Button cancelButton="true" focusTraversable="false" onAction="#onCloseButtonClicked" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<graphic>
<Region styleClass="icon,close-icon"/>
<Region styleClass="icon,close-icon" />
</graphic>
<styleClass>
<String fx:value="window-button" />
Expand Down
Loading
Loading