Skip to content

Commit

Permalink
Merge pull request #1937 from axpoems/alert-improvements
Browse files Browse the repository at this point in the history
Fix alert banner paddings
  • Loading branch information
djing-chan authored Mar 27, 2024
2 parents 7c7f35c + a8dcc61 commit 5dac806
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import bisq.application.ShutDownHandler;
import bisq.bisq_easy.BisqEasyService;
import bisq.bonded_roles.BondedRolesService;
import bisq.bonded_roles.security_manager.alert.AlertNotificationsService;
import bisq.chat.ChatService;
import bisq.common.application.Service;
import bisq.common.observable.Observable;
Expand Down Expand Up @@ -92,6 +93,7 @@ public class DesktopApplicationService extends ApplicationService {
private final TradeService tradeService;
private final UpdaterService updaterService;
private final BisqEasyService bisqEasyService;
private final AlertNotificationsService alertNotificationsService;

public DesktopApplicationService(String[] args, ShutDownHandler shutDownHandler) {
super("desktop", args);
Expand Down Expand Up @@ -179,6 +181,8 @@ public DesktopApplicationService(String[] args, ShutDownHandler shutDownHandler)
sendNotificationService,
tradeService);

alertNotificationsService = new AlertNotificationsService(settingsService, bondedRolesService.getAlertService());

// TODO (refactor, low prio): Not sure if ServiceProvider is still needed as we added BisqEasyService which exposes most of the services.
serviceProvider = new ServiceProvider(shutDownHandler,
getConfig(),
Expand All @@ -198,7 +202,8 @@ public DesktopApplicationService(String[] args, ShutDownHandler shutDownHandler)
sendNotificationService,
tradeService,
updaterService,
bisqEasyService);
bisqEasyService,
alertNotificationsService);
}

@Override
Expand Down Expand Up @@ -243,6 +248,7 @@ public CompletableFuture<Boolean> initialize() {
.thenCompose(result -> tradeService.initialize())
.thenCompose(result -> updaterService.initialize())
.thenCompose(result -> bisqEasyService.initialize())
.thenCompose(result -> alertNotificationsService.initialize())
.orTimeout(STARTUP_TIMEOUT_SEC, TimeUnit.SECONDS)
.handle((result, throwable) -> {
if (throwable == null) {
Expand Down Expand Up @@ -274,6 +280,7 @@ public CompletableFuture<Boolean> shutdown() {
.thenCompose(result -> sendNotificationService.shutdown())
.thenCompose(result -> chatService.shutdown())
.thenCompose(result -> offerService.shutdown())
.thenCompose(result -> alertNotificationsService.shutdown())
.thenCompose(result -> settingsService.shutdown())
.thenCompose(result -> userService.shutdown())
.thenCompose(result -> contractService.shutdown())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import bisq.application.ShutDownHandler;
import bisq.bisq_easy.BisqEasyService;
import bisq.bonded_roles.BondedRolesService;
import bisq.bonded_roles.security_manager.alert.AlertNotificationsService;
import bisq.chat.ChatService;
import bisq.contract.ContractService;
import bisq.identity.IdentityService;
Expand Down Expand Up @@ -67,6 +68,7 @@ public class ServiceProvider {
private final TradeService tradeService;
private final UpdaterService updaterService;
private final BisqEasyService bisqEasyService;
private final AlertNotificationsService alertNotificationsService;

public ServiceProvider(ShutDownHandler shutDownHandler,
ApplicationService.Config config,
Expand All @@ -86,7 +88,8 @@ public ServiceProvider(ShutDownHandler shutDownHandler,
SendNotificationService sendNotificationService,
TradeService tradeService,
UpdaterService updaterService,
BisqEasyService bisqEasyService) {
BisqEasyService bisqEasyService,
AlertNotificationsService alertNotificationsService) {
this.shutDownHandler = shutDownHandler;
this.config = config;
this.persistenceService = persistenceService;
Expand All @@ -106,5 +109,6 @@ public ServiceProvider(ShutDownHandler shutDownHandler,
this.tradeService = tradeService;
this.updaterService = updaterService;
this.bisqEasyService = bisqEasyService;
this.alertNotificationsService = alertNotificationsService;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import bisq.application.ApplicationService;
import bisq.bisq_easy.NavigationTarget;
import bisq.bonded_roles.security_manager.alert.AlertService;
import bisq.bonded_roles.security_manager.alert.AlertNotificationsService;
import bisq.desktop.ServiceProvider;
import bisq.desktop.common.threading.UIThread;
import bisq.desktop.common.view.Controller;
Expand All @@ -31,7 +31,6 @@
import bisq.desktop.main.left.LeftNavController;
import bisq.desktop.main.notification.NotificationPanelController;
import bisq.desktop.main.top.TopPanelController;
import bisq.settings.SettingsService;
import bisq.updater.UpdaterService;
import bisq.updater.UpdaterUtils;
import lombok.Getter;
Expand All @@ -48,24 +47,20 @@ public class MainController extends NavigationController {
private final MainView view;
private final ServiceProvider serviceProvider;
private final LeftNavController leftNavController;
private final SettingsService settingsService;
private final UpdaterService updaterService;
private final ApplicationService.Config config;
private final AlertBannerController alertBannerController;

public MainController(ServiceProvider serviceProvider) {
super(NavigationTarget.MAIN);

this.serviceProvider = serviceProvider;
settingsService = serviceProvider.getSettingsService();
AlertService alertService = serviceProvider.getBondedRolesService().getAlertService();
updaterService = serviceProvider.getUpdaterService();
config = serviceProvider.getConfig();

leftNavController = new LeftNavController(serviceProvider);
TopPanelController topPanelController = new TopPanelController(serviceProvider);
NotificationPanelController notificationPanelController = new NotificationPanelController(serviceProvider);
alertBannerController = new AlertBannerController(settingsService, alertService);
AlertBannerController alertBannerController = new AlertBannerController(serviceProvider);
view = new MainView(model,
this,
leftNavController.getView().getRoot(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@

package bisq.desktop.main.alert;

import bisq.bonded_roles.security_manager.alert.AlertService;
import bisq.bonded_roles.security_manager.alert.AlertType;
import bisq.bisq_easy.BisqEasyNotificationsService;
import bisq.bonded_roles.security_manager.alert.AlertNotificationsService;
import bisq.bonded_roles.security_manager.alert.AuthorizedAlertData;
import bisq.common.observable.Pin;
import bisq.common.observable.collection.CollectionObserver;
import bisq.desktop.ServiceProvider;
import bisq.desktop.common.threading.UIThread;
import bisq.desktop.common.view.Controller;
import bisq.settings.SettingsService;
import javafx.collections.ListChangeListener;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

Expand All @@ -37,102 +35,58 @@ public class AlertBannerController implements Controller {
private final AlertBannerModel model;
@Getter
private final AlertBannerView view;
private final SettingsService settingsService;
private final AlertService alertService;
private final ListChangeListener<AuthorizedAlertData> listChangeListener;
private Pin authorizedAlertDataSetPin;
private final AlertNotificationsService alertNotificationsService;
private final BisqEasyNotificationsService bisqEasyNotificationsService;
private Pin unconsumedAlertsPin, isBisqEasyNotificationVisiblePin;

public AlertBannerController(SettingsService settingsService, AlertService alertService) {
this.settingsService = settingsService;
this.alertService = alertService;
public AlertBannerController(ServiceProvider serviceProvider) {
alertNotificationsService = serviceProvider.getAlertNotificationsService();
bisqEasyNotificationsService = serviceProvider.getBisqEasyService().getBisqEasyNotificationsService();
model = new AlertBannerModel();
view = new AlertBannerView(model, this);

model.getSortedList().setComparator(Comparator.comparing(AuthorizedAlertData::getAlertType).reversed());

listChangeListener = change -> {
change.next();
if (change.wasAdded()) {
AuthorizedAlertData newItem = model.getSortedList().get(0);
AuthorizedAlertData displayed = model.getDisplayedAuthorizedAlertData();
if (displayed == null || newItem.getAlertType().ordinal() >= displayed.getAlertType().ordinal()) {
add(newItem);
}
} else if (change.wasRemoved()) {
change.getRemoved().stream()
.filter(e -> e.equals(model.getDisplayedAuthorizedAlertData()))
.findFirst()
.ifPresent(e -> handleRemove());
}
};
}

@Override
public void onActivate() {
updatePredicate();

authorizedAlertDataSetPin = alertService.getAuthorizedAlertDataSet().addObserver(new CollectionObserver<>() {
@Override
public void add(AuthorizedAlertData authorizedAlertData) {
if (authorizedAlertData == null) {
return;
}
UIThread.run(() -> model.getObservableList().add(authorizedAlertData));
}

@Override
public void remove(Object element) {
if (element instanceof AuthorizedAlertData) {
UIThread.run(() -> model.getObservableList().remove((AuthorizedAlertData) element));
}
}

@Override
public void clear() {
UIThread.run(() -> model.getObservableList().clear());
}
});

model.getSortedList().addListener(listChangeListener);
model.getSortedList().stream().findFirst().ifPresent(this::add);
unconsumedAlertsPin = alertNotificationsService.getUnconsumedAlerts().addObserver(this::showAlertBanner);
isBisqEasyNotificationVisiblePin = bisqEasyNotificationsService.getIsNotificationPanelVisible().addObserver(
this::updateIsBisqEasyNotificationVisible);
}

@Override
public void onDeactivate() {
authorizedAlertDataSetPin.unbind();
model.getSortedList().removeListener(listChangeListener);
unconsumedAlertsPin.unbind();
isBisqEasyNotificationVisiblePin.unbind();
}

void onClose() {
settingsService.getConsumedAlertIds().add(model.getDisplayedAuthorizedAlertData().getId());
updatePredicate();
handleRemove();
UIThread.run(() -> {
alertNotificationsService.dismissAlert(model.getDisplayedAuthorizedAlertData());
model.reset();
showAlertBanner();
});
}

private void add(AuthorizedAlertData authorizedAlertData) {
model.setDisplayedAuthorizedAlertData(authorizedAlertData);
Optional<String> optionalMessage = authorizedAlertData.getMessage();

if (optionalMessage.isPresent()) {
log.info("Showing alert with message {}", optionalMessage.get());
model.getHeadline().set(authorizedAlertData.getHeadline().orElseThrow());
model.getMessage().set(authorizedAlertData.getMessage().orElseThrow());
model.getAlertType().set(authorizedAlertData.getAlertType());
model.getIsAlertVisible().set(true);
} else {
log.warn("optionalMessage not present");
model.getIsAlertVisible().set(false);
}
private void showAlertBanner() {
UIThread.run(() -> {
Optional<AuthorizedAlertData> mostRelevantAlert = alertNotificationsService.getUnconsumedAlerts().stream()
.max(Comparator.comparing(AuthorizedAlertData::getAlertType).thenComparing(AuthorizedAlertData::getDate));
if (mostRelevantAlert.isPresent() && !mostRelevantAlert.get().equals(model.getDisplayedAuthorizedAlertData())) {
model.reset();
add(mostRelevantAlert.get());
}
});
}

private void handleRemove() {
model.reset();
model.getSortedList().stream().findFirst().ifPresent(this::add);
private void add(AuthorizedAlertData authorizedAlertData) {
model.setDisplayedAuthorizedAlertData(authorizedAlertData);
model.getHeadline().set(authorizedAlertData.getHeadline().orElseThrow());
authorizedAlertData.getMessage().ifPresent(message -> model.getMessage().set(message));
model.getAlertType().set(authorizedAlertData.getAlertType());
model.getIsAlertVisible().set(true);
}

private void updatePredicate() {
model.getFilteredList().setPredicate(authorizedAlertData ->
!settingsService.getConsumedAlertIds().contains(authorizedAlertData.getId()) &&
authorizedAlertData.getAlertType() != AlertType.BAN);
private void updateIsBisqEasyNotificationVisible(boolean isVisible) {
model.getIsBisqEasyNotificationVisible().set(isVisible);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,18 @@
import bisq.bonded_roles.security_manager.alert.AuthorizedAlertData;
import bisq.desktop.common.view.Model;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import lombok.Getter;
import lombok.Setter;

import java.util.HashSet;
import java.util.Set;

@Getter
public class AlertBannerModel implements Model {
private final ObservableList<AuthorizedAlertData> observableList = FXCollections.observableArrayList();
private final FilteredList<AuthorizedAlertData> filteredList = new FilteredList<>(observableList);
private final SortedList<AuthorizedAlertData> sortedList = new SortedList<>(filteredList);
private final Set<AuthorizedAlertData> displayedAlerts = new HashSet<>();

@Setter
private AuthorizedAlertData displayedAuthorizedAlertData;
private final BooleanProperty isAlertVisible = new SimpleBooleanProperty();
private final StringProperty headline = new SimpleStringProperty();
private final StringProperty message = new SimpleStringProperty();
private final ObjectProperty<AlertType> alertType = new SimpleObjectProperty<>();
private final BooleanProperty isBisqEasyNotificationVisible = new SimpleBooleanProperty();

public AlertBannerModel() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,17 @@
@Slf4j
public class AlertBannerView extends View<BorderPane, AlertBannerModel, AlertBannerController> {
public static final int DURATION = Transitions.DEFAULT_DURATION / 2;
private final VBox contentVBox;
public static final Insets DEFAULT_PADDING = new Insets(20, 40, 20, 40);
public static final Insets PADDING_WITH_NOTIFICATION = new Insets(0, 40, 20, 40);

Label headline = new Label();
Label message = new Label();
private final VBox contentVBox;
private final Button closeButton;
private final HBox banner;
private final ChangeListener<Number> heightListener;
Label headline = new Label();
Label message = new Label();
private Timeline slideInRightTimeline, slideOutTopTimeline;
private Subscription isVisiblePin, alertTypePin;
private Subscription isVisiblePin, alertTypePin, isBisqEasyNotificationVisiblePin;

public AlertBannerView(AlertBannerModel model, AlertBannerController controller) {
super(new BorderPane(), model, controller);
Expand All @@ -74,7 +76,7 @@ public AlertBannerView(AlertBannerModel model, AlertBannerController controller)
heightListener = ((observable, oldValue, newValue) -> banner.setMinHeight(contentVBox.getHeight() + 25)); // padding = 25

root.setCenter(banner);
root.setPadding(new Insets(20, 40, 20, 40));
root.setPadding(DEFAULT_PADDING);
}

@Override
Expand Down Expand Up @@ -119,6 +121,9 @@ protected void onViewAttached() {
}
});

isBisqEasyNotificationVisiblePin = EasyBind.subscribe(model.getIsBisqEasyNotificationVisible(), isVisible ->
root.setPadding(isVisible ? PADDING_WITH_NOTIFICATION : DEFAULT_PADDING));

message.heightProperty().addListener(heightListener);

closeButton.setOnAction(e -> controller.onClose());
Expand All @@ -131,6 +136,7 @@ protected void onViewDetached() {

isVisiblePin.unsubscribe();
alertTypePin.unsubscribe();
isBisqEasyNotificationVisiblePin.unsubscribe();

message.heightProperty().removeListener(heightListener);

Expand Down
Loading

0 comments on commit 5dac806

Please sign in to comment.