Skip to content

Commit

Permalink
UI
Browse files Browse the repository at this point in the history
  • Loading branch information
kozorukov committed Mar 13, 2024
1 parent 6f81435 commit 68f4886
Show file tree
Hide file tree
Showing 10 changed files with 290 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cryptomessenger.desktop.infrastructure.client.feign.dialog;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.UUID;

@FeignClient(name = "dialog-client", url = "${app.server-base-url}")
public interface DialogClient {

@GetMapping("/dialogs/{myId}/{otherUserId}")
Page<DialogMessageDto> getDialog(@PathVariable UUID myId, @PathVariable UUID otherUserId, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cryptomessenger.desktop.infrastructure.client.feign.dialog;

import cryptomessenger.desktop.infrastructure.client.feign.message.MessageDto;
import lombok.Data;

@Data
public class DialogMessageDto {
private final MessageDto message;
private final boolean isMine;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package cryptomessenger.desktop.infrastructure.ui.controller;

import cryptomessenger.desktop.infrastructure.ui.Refreshable;
import cryptomessenger.desktop.service.dialog.DialogMessage;
import cryptomessenger.desktop.service.dialog.DialogService;
import cryptomessenger.desktop.service.message.MessageService;
import cryptomessenger.desktop.utility.ThreadFactories;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.scene.control.Pagination;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.cell.PropertyValueFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;

import java.net.URL;
import java.util.ResourceBundle;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Component
@RequiredArgsConstructor
public class DialogSceneController implements Refreshable {

private final MessageService messageService;
private final DialogService dialogService;

private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1, ThreadFactories.daemon());

public TextArea messageField;

public String username;
public TableView<DialogMessage> messagesTable;
public Pagination messagesTablePagination;

@Override
public void initialize(URL location, ResourceBundle resources) {
username = resources.getString("otherUsername");
refresh();
configureAutoRefresh();
}

private void configureAutoRefresh() {
executor.scheduleWithFixedDelay(() -> Platform.runLater(this::refreshMessagesTable), 1, 1, TimeUnit.SECONDS);
}

@Override
public void refresh() {
refreshMessagesTable();
}

private void refreshMessagesTable() {
configureTable();
}

public void onSend(ActionEvent actionEvent) {
messageService.send(username, messageField.getText());
refreshMessagesTable();
}

private void configureTable() {
configureColumns();
var messages = dialogService.getMessages(username, Pageable.ofSize(25).withPage(messagesTablePagination.getCurrentPageIndex()));
messagesTablePagination.setPageCount(messages.getTotalPages());
messagesTablePagination.setVisible(messages.getTotalPages() > 0);

messagesTable.setItems(FXCollections.observableArrayList(messages.getContent()));
}

private void configureColumns() {
var columns = messagesTable.getColumns();
columns.get(0).setCellValueFactory(new PropertyValueFactory<>("sentAt"));
columns.get(1).setCellValueFactory(new PropertyValueFactory<>("inbox"));
columns.get(2).setCellValueFactory(new PropertyValueFactory<>("outbox"));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cryptomessenger.desktop.infrastructure.ui.controller;

import cryptomessenger.desktop.infrastructure.localstorage.LocalStorage;
import cryptomessenger.desktop.infrastructure.ui.dialog.DialogWithOtherUserDialog;
import cryptomessenger.desktop.service.LocalStorageKeys;
import cryptomessenger.desktop.service.message.MessageService;
import javafx.event.ActionEvent;
Expand All @@ -21,6 +22,7 @@ public class SendMessageSceneController implements Initializable {

private final MessageService messageService;
private final LocalStorage localStorage;
private final DialogWithOtherUserDialog dialogWithOtherUserDialog;

public ComboBox<String> receiverSelector;
public TextArea messageField;
Expand Down Expand Up @@ -49,4 +51,10 @@ public void onSend(ActionEvent actionEvent) {
public void onCancel(ActionEvent actionEvent) {
onCancel.run();
}

public void onOpenDialog(ActionEvent actionEvent) {
var otherUser = receiverSelector.getValue();
dialogWithOtherUserDialog.show(otherUser);
onCancel.run();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package cryptomessenger.desktop.infrastructure.ui.dialog;

import cryptomessenger.desktop.infrastructure.ui.SceneLoader;
import cryptomessenger.desktop.infrastructure.ui.SceneProperties;
import javafx.scene.image.Image;
import javafx.stage.Modality;
import javafx.stage.Stage;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import static java.util.Map.entry;

@Component
@RequiredArgsConstructor
public class DialogWithOtherUserDialog {

private final SceneLoader sceneLoader;

public void show(String username) {
var stage = new Stage();
stage.setTitle("Dialog with " + username);
stage.getIcons().add(new Image(getClass().getResourceAsStream("/graphics/lock.png")));
stage.initModality(Modality.APPLICATION_MODAL);
var sceneProperties = SceneProperties.of(
entry("otherUsername", username == null ? "" : username)
);
stage.setScene(sceneLoader.load("DialogScene", sceneProperties));
stage.show();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cryptomessenger.desktop.service.dialog;

import lombok.Builder;
import lombok.Data;

import java.time.LocalDateTime;
import java.time.format.FormatStyle;

import static java.time.format.DateTimeFormatter.ofLocalizedDateTime;

@Data
@Builder
public class DialogMessage {

private final LocalDateTime sentAt;
private String inbox;
private String outbox;

public String getSentAt() {
return sentAt.format(ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cryptomessenger.desktop.service.dialog;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.UUID;

public interface DialogService {
Page<DialogMessage> getMessages(String username, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package cryptomessenger.desktop.service.dialog;

import cryptomessenger.coder.Coder;
import cryptomessenger.desktop.infrastructure.client.feign.dialog.DialogClient;
import cryptomessenger.desktop.infrastructure.client.feign.dialog.DialogMessageDto;
import cryptomessenger.desktop.infrastructure.client.feign.message.MessageDto;
import cryptomessenger.desktop.infrastructure.client.feign.user.UserClient;
import cryptomessenger.desktop.infrastructure.client.feign.user.UserDto;
import cryptomessenger.desktop.infrastructure.localstorage.LocalStorage;
import cryptomessenger.desktop.service.LocalStorageKeys;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.time.ZoneId;

import static java.time.ZoneOffset.UTC;

@Service
@RequiredArgsConstructor
public class DialogServiceImpl implements DialogService {

private final LocalStorage localStorage;
private final UserClient userClient;
private final DialogClient dialogClient;
private final Coder coder;

@Override
public Page<DialogMessage> getMessages(String username, Pageable pageable) {
var currentUser = getCurrentUser();
var receiver = userClient.getByUsername(username);
try {
return dialogClient.getDialog(currentUser.getId(), receiver.getId(), pageable)
.map(this::convertDialogMessage);
} catch (Exception e) {
return Page.empty();
}
}

private UserDto getCurrentUser() {
var currentUsername = localStorage.getString(LocalStorageKeys.CURRENT_USERNAME);
return userClient.getByUsername(currentUsername);
}

private DialogMessage convertDialogMessage(DialogMessageDto dto) {
var sentAt = dto.getMessage()
.getSentAt()
.atZone(UTC)
.withZoneSameInstant(ZoneId.systemDefault())
.toLocalDateTime();
var isMine = dto.isMine();
return DialogMessage.builder()
.sentAt(sentAt)
.outbox(isMine ? decodeText(dto.getMessage()) : "")
.inbox(!isMine ? decodeText(dto.getMessage()) : "")
.build();
}

private String decodeText(MessageDto dto) {
var currentUser = getCurrentUser();
var isCurrentUserSender = currentUser.getId().equals(dto.getSenderId());
var privateKey = localStorage.getBytes(LocalStorageKeys.PRIVATE_KEY);
try {
return coder.decode(
() -> isCurrentUserSender ? dto.getContentForSender() : dto.getContentForReceiver(),
() -> privateKey
).getText();
} catch (Exception e) {
return "[Unable to decode]";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<VBox xmlns:fx="http://javafx.com/fxml/1" prefHeight="1000.0" prefWidth="1500.0" spacing="10.0"
xmlns="http://javafx.com/javafx/17.0.2-ea"
fx:controller="cryptomessenger.desktop.infrastructure.ui.controller.DialogSceneController">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</padding>
<TableView fx:id="messagesTable" fixedCellSize="30.0" prefHeight="780.0">
<columns>
<TableColumn editable="false" prefWidth="200.0" resizable="false"
sortable="false" text="Date"/>
<TableColumn editable="false" prefWidth="500.0" resizable="false"
sortable="false" text="Inbox"/>
<TableColumn editable="false" prefWidth="500.0" resizable="false"
sortable="false" text="Outbox"/>
</columns>
</TableView>
<Pagination fx:id="messagesTablePagination" maxPageIndicatorCount="5"/>
<TextArea fx:id="messageField" prefHeight="250.0" wrapText="true">
<font>
<Font size="18.0"/>
</font>
</TextArea>
<HBox alignment="CENTER" spacing="10.0">
<Button defaultButton="true" mnemonicParsing="false" onAction="#onSend" prefWidth="100.0" text="Send">
<font>
<Font size="18.0"/>
</font>
</Button>
</HBox>
</VBox>
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<Font size="18.0"/>
</font>
</Button>
<Button onAction="#onOpenDialog" text="Open Dialog">
<font>
<Font size="18.0"/>
</font>
</Button>
</children>
</HBox>
</children>
Expand Down

0 comments on commit 68f4886

Please sign in to comment.