diff --git a/src/main/java/com/faforever/client/preferences/Preferences.java b/src/main/java/com/faforever/client/preferences/Preferences.java index e469e7e8ad..a2c3f4eb89 100644 --- a/src/main/java/com/faforever/client/preferences/Preferences.java +++ b/src/main/java/com/faforever/client/preferences/Preferences.java @@ -71,6 +71,11 @@ public class Preferences { @Getter private final FiltersPrefs filters = new FiltersPrefs(); + /* Temporary solution to see POC, probably will be moved somewhere else and renamed*/ + @JsonMerge + @Getter + ReplayHistoryPrefs replayHistory = new ReplayHistoryPrefs(); + private final StringProperty themeName = new SimpleStringProperty(DEFAULT_THEME_NAME); private final BooleanProperty preReleaseCheckEnabled = new SimpleBooleanProperty(false); private final BooleanProperty mapAndModAutoUpdate = new SimpleBooleanProperty(true); diff --git a/src/main/java/com/faforever/client/preferences/ReplayHistoryPrefs.java b/src/main/java/com/faforever/client/preferences/ReplayHistoryPrefs.java new file mode 100644 index 0000000000..7cd5cd1c21 --- /dev/null +++ b/src/main/java/com/faforever/client/preferences/ReplayHistoryPrefs.java @@ -0,0 +1,23 @@ +package com.faforever.client.preferences; + +import javafx.beans.property.MapProperty; +import javafx.beans.property.SimpleMapProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableMap; + +import java.time.OffsetDateTime; + +public class ReplayHistoryPrefs { + + private final MapProperty watchedReplayMap = new SimpleMapProperty<>( + FXCollections.observableHashMap()); + + public ObservableMap getWatchedReplayMap() {return watchedReplayMap.getValue();} + + public void setWatchedReplayMap(ObservableMap watchedReplayMap) { + this.watchedReplayMap.setValue(watchedReplayMap); + } + + public MapProperty watchedReplayMapProperty() {return watchedReplayMap;} + +} diff --git a/src/main/java/com/faforever/client/replay/ReplayCardController.java b/src/main/java/com/faforever/client/replay/ReplayCardController.java index 1c81d02996..af9aa19331 100644 --- a/src/main/java/com/faforever/client/replay/ReplayCardController.java +++ b/src/main/java/com/faforever/client/replay/ReplayCardController.java @@ -55,6 +55,7 @@ public class ReplayCardController extends VaultEntityCardController { private final UiService uiService; private final ReplayService replayService; + private final ReplayWatchedService replayWatchedService; private final TimeService timeService; private final MapService mapService; private final RatingService ratingService; @@ -81,6 +82,7 @@ public class ReplayCardController extends VaultEntityCardController { public Button deleteButton; public TextField replayIdField; public StarsController starsController; + public Label replayWatchedLabel; private Consumer onOpenDetailListener; private Runnable onDeleteListener; @@ -89,7 +91,7 @@ public class ReplayCardController extends VaultEntityCardController { @Override protected void onInitialize() { - JavaFxUtil.bindManagedToVisible(deleteButton, tickDurationLabel, realTimeDurationLabel); + JavaFxUtil.bindManagedToVisible(deleteButton, tickDurationLabel, realTimeDurationLabel, replayWatchedLabel); ObservableValue mapVersionObservable = entity.map(Replay::mapVersion); onMapLabel.textProperty() @@ -136,13 +138,26 @@ protected void onInitialize() { .map(reviewsSummary -> reviewsSummary.score() / reviewsSummary.numReviews()) .when(showing)); + + replayWatchedLabel.visibleProperty().bind(replayWatchedLabel.textProperty().isNotEmpty()); + replayWatchedLabel.textProperty().bind( entity.map(Replay::id).when(showing).map( + replayWatchedService::getReplayWatchedDateTime).map(timeService::asDate).map(date -> { + if( date != null ) { + replayTileRoot.setStyle("-fx-border-color: -card-watched-color;"); + replayTileRoot.setStyle("-fx-border-width: 7;"); + } + return date; + + }).when(showing)); + + teams.bind(entity.map(Replay::teamPlayerStats).when(showing)); teams.orElse(java.util.Map.of()).addListener(teamsListener); } private void populatePlayers(java.util.Map> newValue) { teamsContainer.getChildren().clear(); - CompletableFuture.supplyAsync(() -> createTeams(newValue)).thenAcceptAsync(teamCards -> + CompletableFuture.supplyAsync(() -> createTeams(newValue)).thenAcceptAsync(teamCards -> teamsContainer.getChildren().setAll(teamCards), fxApplicationThreadExecutor); } @@ -170,7 +185,7 @@ private List createTeams(java.util.Map> team return teamCard; }).toList(); } - VBox helperLabel = new VBox(); + VBox helperLabel = new VBox(); helperLabel.getChildren().add(new Label("Click for teams")); ArrayList helpers = new ArrayList(); helpers.add(helperLabel); diff --git a/src/main/java/com/faforever/client/replay/ReplayService.java b/src/main/java/com/faforever/client/replay/ReplayService.java index 8386608d54..66edaf0fa8 100644 --- a/src/main/java/com/faforever/client/replay/ReplayService.java +++ b/src/main/java/com/faforever/client/replay/ReplayService.java @@ -102,6 +102,7 @@ public class ReplayService { private final ReplayMapper replayMapper; private final DataPrefs dataPrefs; private final ObjectFactory replayDownloadTaskFactory; + private final ReplayWatchedService replayWatchedService; @VisibleForTesting static Integer parseSupComVersion(ReplayDataParser parser) { @@ -259,6 +260,7 @@ public void runReplay(Replay item) { if (item.replayFile() != null) { try { runReplayFile(item.replayFile()); + this.replayWatchedService.updateReplayWatchHistory(item.id()); } catch (Exception e) { log.error("Could not read replay file `{}`", item.replayFile(), e); notificationService.addImmediateErrorNotification(e, "replay.couldNotParse"); @@ -333,6 +335,7 @@ private void runOnlineReplay(int replayId) { downloadReplay(replayId).thenAccept((path) -> { try { runReplayFile(path); + this.replayWatchedService.updateReplayWatchHistory(replayId); } catch (IOException | CompressorException e) { throw new RuntimeException(e); } diff --git a/src/main/java/com/faforever/client/replay/ReplayWatchedService.java b/src/main/java/com/faforever/client/replay/ReplayWatchedService.java new file mode 100644 index 0000000000..fa740877db --- /dev/null +++ b/src/main/java/com/faforever/client/replay/ReplayWatchedService.java @@ -0,0 +1,36 @@ +package com.faforever.client.replay; + +import com.faforever.client.preferences.Preferences; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import java.time.OffsetDateTime; + +@Lazy +@Service +@Slf4j +@RequiredArgsConstructor +public class ReplayWatchedService { + + private final Preferences preferences; + + boolean wasReplayWatched(Integer replayId) { + return preferences.getReplayHistory().getWatchedReplayMap().containsKey(replayId); + } + + OffsetDateTime getReplayWatchedDateTime(Integer replayId) { + if (wasReplayWatched(replayId)) { + return preferences.getReplayHistory().getWatchedReplayMap().get(replayId); + } else { + return null; + } + } + + void updateReplayWatchHistory(Integer replayId) { + preferences.getReplayHistory().getWatchedReplayMap().put(replayId, OffsetDateTime.now()); + } + + +} diff --git a/src/main/resources/theme/colors.css b/src/main/resources/theme/colors.css index 9e640fb8ee..4cb67a0c51 100644 --- a/src/main/resources/theme/colors.css +++ b/src/main/resources/theme/colors.css @@ -36,6 +36,7 @@ -divider-color: #424242; -card-color: #424242CC; + -card-watched-color: #A8A8A882; -dimmer-color: #21212199; -fx-text-color: #fff; -darkened-color: dimgrey; diff --git a/src/main/resources/theme/icons.css b/src/main/resources/theme/icons.css index fd73862ae5..fc24c2fdf2 100644 --- a/src/main/resources/theme/icons.css +++ b/src/main/resources/theme/icons.css @@ -363,6 +363,10 @@ -fx-shape: "m144.8143 121.6803c-71.8005 0-130 58.1994-130 130 0 71.8005 58.1995 130 130 130 71.8006 0 130-58.1995 130-130 0-71.8006-58.1994-130-130-130zm225.1602 0c-8.9746 0-16.25 7.2754-16.25 16.25v16.25h32.5v16.5566c-54.5385 4.1483-97.5 49.7165-97.5 105.3184 0 58.3349 47.2901 105.625 105.625 105.625 58.3349 0 105.625-47.2901 105.625-105.625 0-55.6013-42.9615-101.1695-97.5-105.3184v-16.5566h32.5v-16.25c0-8.9746-7.2749-16.25-16.25-16.25zm-225.1524 16.25c17.875 0 34.7842 4.1277 49.8399 11.4727-1.0563.8856-2.0797 1.8196-3.0547 2.8027-9.2056 9.2056-14.2754 21.4503-14.2754 34.4746 0 13.0244 5.0698 25.2609 14.2754 34.4746 9.2544 9.2544 21.6364 14.2832 34.4414 14.2832.8043 0 1.6077-.016 2.4121-.0566 3.51 13.1544 9.8395 47.394-2.1367 94.5352-.1137.4469-.1784.8855-.2109 1.3242-20.6456 21.0925-49.4313 34.1895-81.2813 34.1895h-.0176c-15.9819 0-31.1998-3.3064-44.9961-9.2539l59.1992-66.6016c1.3244-1.4869 2.0547-3.4039 2.0547-5.3945v-24.375c0-4.485-3.64-8.125-8.125-8.125-28.6893 0-58.9533-29.8266-59.2539-30.1191-1.5275-1.5275-3.593-2.3809-5.7461-2.3809h-32.5c-4.485 0-8.125 3.64-8.125 8.125v48.75c0 3.0794 1.7398 5.8906 4.4941 7.2637l28.0059 14.0078v47.7012c-29.4693-20.5562-48.75-54.6971-48.75-93.3477 0-17.4444 3.9331-33.9706 10.9531-48.75h29.6719c2.1531 0 4.2267-.8534 5.7461-2.3809l32.5-32.5c1.5275-1.5275 2.3789-3.591 2.3789-5.7441v-19.6543c10.3025-3.0631 21.2063-4.7207 32.5-4.7207zm246.9492 56.9199-5.5039 79.7324c-.4723 6.6752 3.1633 9.5976 8.082 9.5976 4.9187 0 8.5568-2.9225 8.084-9.5976l-5.5039-79.7324c20.7355.6429 40.1363 9.0157 54.873 23.752 15.3461 15.3461 23.7969 35.7508 23.7969 57.4531 0 21.7024-8.4508 42.1071-23.7969 57.4531-15.3466 15.3461-35.7502 23.7969-57.4531 23.7969-21.7029 0-42.1051-8.4508-57.4512-23.7969-15.3461-15.3461-23.7988-35.7507-23.7988-57.4531 0-21.7023 8.4527-42.1071 23.7988-57.4531 14.7367-14.7362 34.1376-23.1096 54.873-23.752z"; } +.watched-icon { + -fx-shape: "M16 6c-6.979 0-13.028 4.064-16 10 2.972 5.936 9.021 10 16 10s13.027-4.064 16-10c-2.972-5.936-9.021-10-16-10zM23.889 11.303c1.88 1.199 3.473 2.805 4.67 4.697-1.197 1.891-2.79 3.498-4.67 4.697-2.362 1.507-5.090 2.303-7.889 2.303s-5.527-0.796-7.889-2.303c-1.88-1.199-3.473-2.805-4.67-4.697 1.197-1.891 2.79-3.498 4.67-4.697 0.122-0.078 0.246-0.154 0.371-0.228-0.311 0.854-0.482 1.776-0.482 2.737 0 4.418 3.582 8 8 8s8-3.582 8-8c0-0.962-0.17-1.883-0.482-2.737 0.124 0.074 0.248 0.15 0.371 0.228v0zM16 13c0 1.657-1.343 3-3 3s-3-1.343-3-3 1.343-3 3-3 3 1.343 3 3z" +} + .game-duration-icon { -fx-shape: "m383.0234 122.6191c-8.7244 0-15.7969 7.0725-15.7969 15.7969v15.7969h31.5938v16.0977c-53.0183 4.0327-94.7832 48.3288-94.7832 102.3809 0 56.7089 45.9728 102.6816 102.6816 102.6816 56.7089 0 102.6816-45.9728 102.6816-102.6816 0-54.0515-41.7649-98.3477-94.7832-102.3809v-16.0977h31.5938v-15.7969c0-8.7244-7.072-15.7969-15.7969-15.7969zm-380.4043 1.3945v178.5469h285.6758v-178.5469zm17.8535 17.8535h249.9668v142.8379h-249.9668zm383.7383 51.8828-5.3496 77.5098c-.4591 6.4891 3.0759 9.3301 7.8574 9.3301 4.7816 0 8.317-2.841 7.8574-9.3301l-5.3496-77.5098c20.1575.625 39.0178 8.7644 53.3438 23.0898 14.9183 14.9183 23.1348 34.7541 23.1348 55.8516 0 21.0974-8.2164 40.9332-23.1348 55.8516-14.9188 14.9183-34.7536 23.1348-55.8516 23.1348-21.0979 0-40.9332-8.2164-55.8516-23.1348-14.9183-14.9183-23.1328-34.7541-23.1328-55.8516 0-21.0974 8.2145-40.9332 23.1328-55.8516 14.3259-14.3254 33.1862-22.4654 53.3438-23.0898zm-303.3906 126.6641-8.9277 35.7109-17.8555 17.8535h142.8379l-17.8535-17.8535-8.9277-35.7109z"; } diff --git a/src/main/resources/theme/vault/replay/replay_card.fxml b/src/main/resources/theme/vault/replay/replay_card.fxml index 76adc3ff58..cbb9c33e5e 100644 --- a/src/main/resources/theme/vault/replay/replay_card.fxml +++ b/src/main/resources/theme/vault/replay/replay_card.fxml @@ -90,6 +90,12 @@ + +