Skip to content

Commit

Permalink
Add install button to map and mod cards for easier UX for installing
Browse files Browse the repository at this point in the history
Add install button to map and mod cards for easier UX for installing
Fixes #1874, Fixes #702
  • Loading branch information
Sheikah45 committed Sep 13, 2020
1 parent 5f4ac29 commit 3b9440f
Show file tree
Hide file tree
Showing 11 changed files with 379 additions and 38 deletions.
59 changes: 52 additions & 7 deletions src/main/java/com/faforever/client/map/MapCardController.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import com.faforever.client.fx.JavaFxUtil;
import com.faforever.client.i18n.I18n;
import com.faforever.client.map.MapService.PreviewSize;
import com.faforever.client.notification.ImmediateErrorNotification;
import com.faforever.client.notification.NotificationService;
import com.faforever.client.reporting.ReportingService;
import com.faforever.client.util.IdenticonUtil;
import com.faforever.client.vault.review.Review;
import com.faforever.client.vault.review.StarsController;
Expand All @@ -15,6 +18,7 @@
import javafx.collections.ObservableList;
import javafx.collections.WeakListChangeListener;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
Expand All @@ -32,7 +36,9 @@
public class MapCardController implements Controller<Node> {

private final MapService mapService;
private final NotificationService notificationService;
private final I18n i18n;
private final ReportingService reportingService;

public ImageView thumbnailImageView;
public Label nameLabel;
Expand All @@ -43,25 +49,29 @@ public class MapCardController implements Controller<Node> {
public Label numberOfPlaysLabel;
public Label sizeLabel;
public Label maxPlayersLabel;
public Button installButton;
public Button uninstallButton;

private MapBean map;
private Consumer<MapBean> onOpenDetailListener;
private ListChangeListener<MapBean> installedMapsChangeListener;
private ListChangeListener<MapBean> installStatusChangeListener;
private final InvalidationListener reviewsChangedListener = observable -> populateReviews();
private JFXRippler jfxRippler;

public void initialize() {
jfxRippler = new JFXRippler(mapTileRoot);
installedMapsChangeListener = change -> {
installButton.managedProperty().bind(installButton.visibleProperty());
uninstallButton.managedProperty().bind(uninstallButton.visibleProperty());
installStatusChangeListener = change -> {
while (change.next()) {
for (MapBean mapBean : change.getAddedSubList()) {
if (map.getId().equals(mapBean.getId())) {
if (map.getFolderName().equalsIgnoreCase(mapBean.getFolderName())) {
setInstalled(true);
return;
}
}
for (MapBean mapBean : change.getRemoved()) {
if (map.getId().equals(mapBean.getId())) {
if (map.getFolderName().equals(mapBean.getFolderName())) {
setInstalled(false);
return;
}
Expand All @@ -87,8 +97,14 @@ public void setMap(MapBean map) {
sizeLabel.setText(i18n.get("mapPreview.size", size.getWidthInKm(), size.getHeightInKm()));
maxPlayersLabel.setText(i18n.number(map.getPlayers()));

ObservableList<MapBean> installedMaps = mapService.getInstalledMaps();
JavaFxUtil.addListener(installedMaps, new WeakListChangeListener<>(installedMapsChangeListener));
if (mapService.isOfficialMap(map.getFolderName())) {
installButton.setVisible(false);
uninstallButton.setVisible(false);
} else {
ObservableList<MapBean> installedMaps = mapService.getInstalledMaps();
JavaFxUtil.addListener(installedMaps, new WeakListChangeListener<>(installStatusChangeListener));
setInstalled(mapService.isInstalled(map.getFolderName()));
}

ObservableList<Review> reviews = map.getReviews();
JavaFxUtil.addListener(reviews, new WeakInvalidationListener(reviewsChangedListener));
Expand All @@ -103,8 +119,37 @@ private void populateReviews() {
});
}

public void onInstallButtonClicked() {
mapService.downloadAndInstallMap(map, null, null)
.thenRun(() -> setInstalled(true))
.exceptionally(throwable -> {
notificationService.addNotification(new ImmediateErrorNotification(
i18n.get("errorTitle"),
i18n.get("mapVault.installationFailed", map.getDisplayName(), throwable.getLocalizedMessage()),
throwable, i18n, reportingService
));
setInstalled(false);
return null;
});
}

public void onUninstallButtonClicked() {
mapService.uninstallMap(map)
.thenRun(() -> setInstalled(false))
.exceptionally(throwable -> {
notificationService.addNotification(new ImmediateErrorNotification(
i18n.get("errorTitle"),
i18n.get("mapVault.couldNotDeleteMap", map.getDisplayName(), throwable.getLocalizedMessage()),
throwable, i18n, reportingService
));
setInstalled(true);
return null;
});
}

private void setInstalled(boolean installed) {
// FIXME implement
installButton.setVisible(!installed);
uninstallButton.setVisible(installed);
}

public Node getRoot() {
Expand Down
17 changes: 9 additions & 8 deletions src/main/java/com/faforever/client/map/MapDetailController.java
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ public void setMap(MapBean map) {
dateLabel.setText(timeService.asDate(createTime));

boolean mapInstalled = mapService.isInstalled(map.getFolderName());
installButton.setVisible(!mapInstalled);
setInstalled(mapInstalled);

Player player = playerService.getCurrentPlayer().orElseThrow(() -> new IllegalStateException("No user is logged in"));

Expand All @@ -200,17 +200,21 @@ public void setMap(MapBean map) {
installButton.setDisable(true);
}
}));
uninstallButton.setVisible(mapInstalled);

mapDescriptionLabel.setText(Optional.ofNullable(map.getDescription())
.map(Strings::emptyToNull)
.map(FaStrings::removeLocalizationTag)
.orElseGet(() -> i18n.get("map.noDescriptionAvailable")));

ObservableList<MapBean> installedMaps = mapService.getInstalledMaps();
JavaFxUtil.addListener(installedMaps, new WeakListChangeListener<>(installStatusChangeListener));

setInstalled(mapService.isInstalled(map.getFolderName()));
if (mapService.isOfficialMap(map.getFolderName())) {
installButton.setVisible(false);
uninstallButton.setVisible(false);
} else {
ObservableList<MapBean> installedMaps = mapService.getInstalledMaps();
JavaFxUtil.addListener(installedMaps, new WeakListChangeListener<>(installStatusChangeListener));
setInstalled(mapService.isInstalled(map.getFolderName()));
}
}

private void onDeleteReview(Review review) {
Expand Down Expand Up @@ -246,8 +250,6 @@ private void onSendReview(Review review) {
}

public void onInstallButtonClicked() {
installButton.setVisible(false);

mapService.downloadAndInstallMap(map, progressBar.progressProperty(), progressLabel.textProperty())
.thenRun(() -> setInstalled(true))
.exceptionally(throwable -> {
Expand All @@ -264,7 +266,6 @@ public void onInstallButtonClicked() {
public void onUninstallButtonClicked() {
progressBar.progressProperty().unbind();
progressBar.setProgress(-1);
uninstallButton.setVisible(false);

mapService.uninstallMap(map)
.thenRun(() -> setInstalled(false))
Expand Down
41 changes: 40 additions & 1 deletion src/main/java/com/faforever/client/mod/ModCardController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import com.faforever.client.fx.Controller;
import com.faforever.client.fx.JavaFxUtil;
import com.faforever.client.i18n.I18n;
import com.faforever.client.notification.ImmediateErrorNotification;
import com.faforever.client.notification.NotificationService;
import com.faforever.client.reporting.ReportingService;
import com.faforever.client.util.TimeService;
import com.faforever.client.vault.review.Review;
import com.faforever.client.vault.review.StarsController;
Expand All @@ -14,6 +17,7 @@
import javafx.collections.ObservableList;
import javafx.collections.WeakListChangeListener;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import lombok.RequiredArgsConstructor;
Expand All @@ -29,15 +33,19 @@
public class ModCardController implements Controller<Node> {

private final ModService modService;
private final NotificationService notificationService;
private final TimeService timeService;
private final I18n i18n;
private final ReportingService reportingService;
public ImageView thumbnailImageView;
public Label nameLabel;
public Label authorLabel;
public Node modTileRoot;
public Label createdLabel;
public Label numberOfReviewsLabel;
public Label typeLabel;
public Button installButton;
public Button uninstallButton;
private ModVersion modVersion;
private Consumer<ModVersion> onOpenDetailListener;
private ListChangeListener<ModVersion> installStatusChangeListener;
Expand All @@ -55,6 +63,8 @@ private void populateReviews() {

public void initialize() {
jfxRippler = new JFXRippler(modTileRoot);
installButton.managedProperty().bind(installButton.visibleProperty());
uninstallButton.managedProperty().bind(uninstallButton.visibleProperty());
installStatusChangeListener = change -> {
while (change.next()) {
for (ModVersion modVersion : change.getAddedSubList()) {
Expand All @@ -73,8 +83,36 @@ public void initialize() {
};
}

public void onInstallButtonClicked() {
modService.downloadAndInstallMod(modVersion, null, null)
.thenRun(() -> setInstalled(true))
.exceptionally(throwable -> {
notificationService.addNotification(new ImmediateErrorNotification(
i18n.get("errorTitle"),
i18n.get("modVault.installationFailed", modVersion.getDisplayName(), throwable.getLocalizedMessage()),
throwable, i18n, reportingService
));
setInstalled(false);
return null;
});
}

public void onUninstallButtonClicked() {
modService.uninstallMod(modVersion).thenRun(() -> setInstalled(false))
.exceptionally(throwable -> {
notificationService.addNotification(new ImmediateErrorNotification(
i18n.get("errorTitle"),
i18n.get("modVault.couldNotDeleteMod", modVersion.getDisplayName(), throwable.getLocalizedMessage()),
throwable, i18n, reportingService
));
setInstalled(true);
return null;
});
}

private void setInstalled(boolean installed) {
//TODO:IMPLEMENT ISSUE #670
installButton.setVisible(!installed);
uninstallButton.setVisible(installed);
}

public void setModVersion(ModVersion modVersion) {
Expand All @@ -86,6 +124,7 @@ public void setModVersion(ModVersion modVersion) {
}
createdLabel.setText(timeService.asDate(modVersion.getCreateTime()));
typeLabel.setText(modVersion.getModType() != null ? i18n.get(modVersion.getModType().getI18nKey()) : "");
setInstalled(modService.isModInstalled(modVersion.getUid()));

ObservableList<ModVersion> installedModVersions = modService.getInstalledModVersions();
JavaFxUtil.addListener(installedModVersions, new WeakListChangeListener<>(installStatusChangeListener));
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/com/faforever/client/mod/ModDetailController.java
Original file line number Diff line number Diff line change
Expand Up @@ -202,31 +202,31 @@ private long getModSize() {
}

public void onInstallButtonClicked() {
installButton.setVisible(false);

modService.downloadAndInstallMod(modVersion, progressBar.progressProperty(), progressLabel.textProperty())
.thenRun(() -> uninstallButton.setVisible(true))
.thenRun(() -> setInstalled(true))
.exceptionally(throwable -> {
notificationService.addNotification(new ImmediateErrorNotification(
i18n.get("errorTitle"),
i18n.get("modVault.installationFailed", modVersion.getDisplayName(), throwable.getLocalizedMessage()),
throwable, i18n, reportingService
));
setInstalled(false);
return null;
});
}

public void onUninstallButtonClicked() {
progressBar.progressProperty().unbind();
progressBar.setProgress(-1);
uninstallButton.setVisible(false);

modService.uninstallMod(modVersion).exceptionally(throwable -> {
modService.uninstallMod(modVersion).thenRun(() -> setInstalled(false))
.exceptionally(throwable -> {
notificationService.addNotification(new ImmediateErrorNotification(
i18n.get("errorTitle"),
i18n.get("modVault.couldNotDeleteMod", modVersion.getDisplayName(), throwable.getLocalizedMessage()),
throwable, i18n, reportingService
));
setInstalled(true);
return null;
});
}
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ mapVault.mostLikedMaps=Most liked
mapVault.newestMaps=Most recent
mapVault.mostPlayed=Most played
mapVault.installButtonFormat=Install ({0})
mapVault.install=Install
mapVault.uninstall=Uninstall
vault.upload=Upload…
mod.description=Description
Expand Down
9 changes: 9 additions & 0 deletions src/main/resources/theme/icons.css
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@
-fx-padding: 0.833333em 0.583333em;
}

.install-icon {
-fx-shape: "M832 64h-640l-192 192v672c0 17.674 14.326 32 32 32h960c17.672 0 32-14.326 32-32v-672l-192-192zM512 832l-320-256h192v-192h256v192h192l-320 256zM154.51 192l64-64h586.978l64 64h-714.978z";
}

.uninstall-icon {
-fx-shape: "M192 1024h640l64-704h-768zM640 128v-128h-256v128h-320v192l64-64h768l64 64v-192h-320zM576 128h-128v-64h128v64z";
-fx-padding: 0.666667em 0.5em;
}

.random-icon {
-fx-shape: "M 18.68 35.69 c 1.13 -1.86 2.95 -3.07 5.03 -3.07 s 3.88 1.21 5.03 3.07 c -0.9 -3.72 -2.81 -6.31 -5.03 -6.31 s -4.13 2.57 -5.03 6.31 z M 28.86 40.99 c 0 -3.62 -2.3 -6.59 -5.15 -6.59 s -5.15 2.95 -5.15 6.59 s 2.3 6.59 5.15 6.59 c 2.84 0 5.15 -2.95 5.15 -6.59 z M 27.84 47.29 c 1.56 -1.51 2.57 -3.88 2.57 -6.5 c 0 -0.9 -0.12 -1.76 -0.32 -2.57 c 0.04 -0.73 0.25 -2.24 -0.35 -4.45 c -0.61 -2.23 -2.02 -3.8 -2.88 -4.68 c 1.31 -0.32 2.46 -1.38 3.24 -2.72 s 1.69 -3.48 1.99 -7.1 s -0.73 -8.26 -1.21 -9.95 c 1.25 1.44 2.94 4.38 4.03 7.14 s 2.27 7.04 2.71 10.06 s 0.55 4.92 0.19 6.94 c -1.42 -0.84 -2.3 -0.23 -2.69 0.06 s -1.22 1.21 -1.63 2.3 c -0.41 1.09 -0.55 2.71 -0.36 3.9 s 0.65 1.5 1.08 1.5 s 1.13 -0.23 2.63 -1.99 c 1.5 -1.76 2.57 -3.88 2.98 -4.96 s 1.03 -2.75 1.46 -4.73 c 0.41 3.53 -0.26 6.95 -1.13 9.28 s -2.21 4.76 -4.96 7.81 s -5.64 4.92 -8.64 5.59 c 0.42 -0.55 0.84 -1.51 1.06 -2.34 s 0.29 -1.8 0.29 -2.53 z M 19.58 47.29 c -1.51 -1.51 -2.57 -3.91 -2.57 -6.5 c 0 -1 0.16 -1.98 0.42 -2.86 c -0.13 -1.32 -0.04 -2.15 0.13 -3.17 c 0.19 -1.08 0.74 -2.42 1.12 -3.19 c -2.46 -0.79 -3.68 -2.3 -4.36 -3.97 s -0.89 -4.38 -0.79 -6.7 c 0.1 -2.33 0.48 -3.94 1.02 -5.47 c -1.46 1.73 -3.01 4.39 -3.72 6.02 s -1.4 4.22 -1.61 6.14 s -0.25 3.71 0.41 5.8 c 1.44 -0.89 2.33 -0.23 2.71 0.06 s 1.19 1.27 1.66 2.52 c 0.46 1.25 0.5 2.52 0.29 3.68 s -0.71 1.44 -1.06 1.44 c -0.36 0 -1.12 -0.17 -2.59 -1.94 s -2.63 -3.91 -3.04 -4.96 c -0.41 -1.02 -0.96 -2.52 -1.32 -4.49 c -0.44 3.43 -0.04 6.11 1.03 9.05 s 3.23 5.83 4.96 7.81 c 1.73 1.98 4.61 4.54 8.64 5.59 c -0.48 -0.92 -0.71 -1.51 -0.96 -2.44 s -0.31 -1.73 -0.38 -2.44 z";
-fx-padding: 0.833333em 0.583333em;
Expand Down
21 changes: 21 additions & 0 deletions src/main/resources/theme/vault/map/map_card.fxml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.ColumnConstraints?>
Expand All @@ -26,6 +27,26 @@
<children>
<ImageView fx:id="thumbnailImageView" fitHeight="224.0" fitWidth="224.0" pickOnBounds="true" preserveRatio="true"
GridPane.columnSpan="2147483647" GridPane.halignment="CENTER"/>
<VBox alignment="TOP_RIGHT" spacing="10.0" GridPane.columnSpan="2147483647" GridPane.valignment="TOP" GridPane.vgrow="NEVER"
GridPane.hgrow="NEVER">
<children>
<Button fx:id="installButton" defaultButton="true"
mnemonicParsing="false" onAction="#onInstallButtonClicked">
<graphic>
<Region styleClass="icon,install-icon"/>
</graphic>
</Button>
<Button fx:id="uninstallButton" mnemonicParsing="false"
onAction="#onUninstallButtonClicked">
<graphic>
<Region styleClass="icon,uninstall-icon"/>
</graphic>
</Button>
</children>
<GridPane.margin>
<Insets top="10.0" right="10.0"/>
</GridPane.margin>
</VBox>
<VBox alignment="BOTTOM_LEFT" styleClass="image-dimmer" GridPane.columnSpan="2147483647" GridPane.hgrow="NEVER"
GridPane.valignment="BOTTOM" GridPane.vgrow="NEVER">
<children>
Expand Down

0 comments on commit 3b9440f

Please sign in to comment.