diff --git a/.gitignore b/.gitignore
index 6ac465db..244268f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
target/
/.idea/
+.env
diff --git a/pom.xml b/pom.xml
index c40f667e..9ee23793 100644
--- a/pom.xml
+++ b/pom.xml
@@ -45,6 +45,16 @@
javafx-fxml
${javafx.version}
+
+ io.github.cdimascio
+ dotenv-java
+ 3.2.0
+
+
+ tools.jackson.core
+ jackson-databind
+ 3.0.1
+
diff --git a/src/main/java/com/example/HelloController.java b/src/main/java/com/example/HelloController.java
index fdd160a0..e0bd49a9 100644
--- a/src/main/java/com/example/HelloController.java
+++ b/src/main/java/com/example/HelloController.java
@@ -1,7 +1,10 @@
package com.example;
+import javafx.event.ActionEvent;
import javafx.fxml.FXML;
-import javafx.scene.control.Label;
+import javafx.geometry.Pos;
+import javafx.geometry.Side;
+import javafx.scene.control.*;
/**
* Controller layer: mediates between the view (FXML) and the model.
@@ -10,13 +13,78 @@ public class HelloController {
private final HelloModel model = new HelloModel();
+ @FXML
+ public ListView messageView ;
+
@FXML
private Label messageLabel;
+ @FXML
+ private TextField messageField;
+
+ @FXML
+ private Button emojiButton;
+
+ @FXML
+ private void emojis() {
+
+ String[] emojis = {"😀", "😂", "😍", "😎", "😭", "👍", "🎉"};
+
+
+ ContextMenu emojiMenu = new ContextMenu();
+ for (String emoji : emojis) {
+ MenuItem item = new MenuItem(emoji);
+ item.setOnAction(e -> {
+ messageField.appendText(emoji);
+ });
+ emojiMenu.getItems().add(item);
+ }
+
+ emojiMenu.show(emojiButton, Side.BOTTOM, 0, 0);
+ }
+
@FXML
private void initialize() {
- if (messageLabel != null) {
- messageLabel.setText(model.getGreeting());
+ messageLabel.setText(model.getGreeting());
+ messageView.setItems(model.getMessages());
+ messageView.setCellFactory(list -> new ListCell<>() {
+ @Override
+ protected void updateItem(NtfyMessageDto msg, boolean empty) {
+ super.updateItem(msg, empty);
+
+ if (empty || msg == null) {
+ setGraphic(null);
+ return;
+ }
+
+ Label label = new Label(msg.toString());
+ label.setWrapText(true);
+ label.setMaxWidth(180);
+
+
+ boolean fromMe = msg.topic() != null && msg.topic().equals("me");
+
+ if (fromMe) {
+ label.setStyle("-fx-background-color: lightgreen; -fx-padding: 6; -fx-background-radius: 8;");
+ setAlignment(Pos.CENTER_RIGHT);
+ } else {
+ label.setStyle("-fx-background-color: lightgray; -fx-padding: 6; -fx-background-radius: 8;");
+ setAlignment(Pos.CENTER_LEFT);
+ }
+
+ setGraphic(label);
+ }
+ });
+
+ }
+
+
+
+ public void sendMessage(ActionEvent actionEvent) {
+ String text = messageField.getText().trim();
+ if (!text.isEmpty()) {
+ model.sendMessage(text);
+ messageField.clear();
}
}
}
diff --git a/src/main/java/com/example/HelloFX.java b/src/main/java/com/example/HelloFX.java
index 96bdc5ca..263c58ca 100644
--- a/src/main/java/com/example/HelloFX.java
+++ b/src/main/java/com/example/HelloFX.java
@@ -1,5 +1,6 @@
package com.example;
+import io.github.cdimascio.dotenv.Dotenv;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
@@ -10,6 +11,7 @@ public class HelloFX extends Application {
@Override
public void start(Stage stage) throws Exception {
+
FXMLLoader fxmlLoader = new FXMLLoader(HelloFX.class.getResource("hello-view.fxml"));
Parent root = fxmlLoader.load();
Scene scene = new Scene(root, 640, 480);
diff --git a/src/main/java/com/example/HelloModel.java b/src/main/java/com/example/HelloModel.java
index 385cfd10..083f39bf 100644
--- a/src/main/java/com/example/HelloModel.java
+++ b/src/main/java/com/example/HelloModel.java
@@ -1,9 +1,40 @@
package com.example;
+import io.github.cdimascio.dotenv.Dotenv;
+import javafx.application.Platform;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import tools.jackson.databind.ObjectMapper;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.util.Objects;
+
/**
* Model layer: encapsulates application data and business logic.
*/
public class HelloModel {
+
+ private final String hostName;
+ private final HttpClient http = HttpClient.newHttpClient();
+ private final ObjectMapper mapper = new ObjectMapper();
+ private final ObservableList messages = FXCollections.observableArrayList();
+
+ private boolean senderMe=false;
+
+ public HelloModel() {
+ Dotenv dotenv = Dotenv.load();
+ hostName = Objects.requireNonNull(dotenv.get("HOST_NAME"));
+ receiveMessage();
+ }
+
+ public ObservableList getMessages() {
+ return messages;
+ }
+
/**
* Returns a greeting based on the current Java and JavaFX versions.
*/
@@ -12,4 +43,52 @@ public String getGreeting() {
String javafxVersion = System.getProperty("javafx.version");
return "Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + ".";
}
+
+ public void sendMessage(String text) {
+
+ senderMe=true;
+
+ long now = System.currentTimeMillis() / 1000;
+ NtfyMessageDto myMsg = new NtfyMessageDto("local", now, "message", "me", text);
+
+ Platform.runLater(() -> messages.add(myMsg));
+
+ HttpRequest httpRequest= HttpRequest.newBuilder()
+ .POST(HttpRequest.BodyPublishers.ofString(text))
+ .uri(URI.create(hostName + "/mytopic"))
+ .build();
+ http.sendAsync(httpRequest, HttpResponse.BodyHandlers.discarding())
+ .exceptionally(ex -> {
+ System.out.println("Error sending message: " + ex.getMessage());
+ return null;
+ });
+ }
+
+ public void receiveMessage(){
+ HttpRequest httpRequest = HttpRequest.newBuilder()
+ .GET()
+ .uri(URI.create(hostName + "/mytopic/json"))
+ .build();
+
+ http.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofLines())
+ .thenAccept(response -> response.body()
+ .map(s -> {
+ try {
+ return mapper.readValue(s, NtfyMessageDto.class);
+ } catch (Exception e) {
+ System.err.println("Failed to parse message: " + e.getMessage());
+ return null;
+ }
+ })
+ .filter(Objects::nonNull)
+ .filter(msg -> "message".equals(msg.event()))
+ .forEach(msg->{
+ if (senderMe) {
+ senderMe=false;
+ return;
+ }
+ Platform.runLater(() -> messages.add(msg));
+ }));
+ }
+
}
diff --git a/src/main/java/com/example/ManyParameters.java b/src/main/java/com/example/ManyParameters.java
new file mode 100644
index 00000000..76596d06
--- /dev/null
+++ b/src/main/java/com/example/ManyParameters.java
@@ -0,0 +1,20 @@
+package com.example;
+
+public class ManyParameters {
+
+ public ManyParameters(String computerName, int timeout, String method, int size, byte[] data) {
+
+ }
+
+ static void main () {
+
+ ManyParametersBuilder builder= new ManyParametersBuilder();
+ builder
+ .setComputerName("localhost")
+ .setTimeout(10)
+ .setSize(0)
+ .createManyParameters();
+ }
+
+
+}
diff --git a/src/main/java/com/example/ManyParametersBuilder.java b/src/main/java/com/example/ManyParametersBuilder.java
new file mode 100644
index 00000000..fd49920d
--- /dev/null
+++ b/src/main/java/com/example/ManyParametersBuilder.java
@@ -0,0 +1,38 @@
+package com.example;
+
+public class ManyParametersBuilder {
+ private String computerName;
+ private int timeout = 0;
+ private String method;
+ private int size = 0;
+ private byte[] data = null;
+
+ public ManyParametersBuilder setComputerName(String computerName) {
+ this.computerName = computerName;
+ return this;
+ }
+
+ public ManyParametersBuilder setTimeout(int timeout) {
+ this.timeout = timeout;
+ return this;
+ }
+
+ public ManyParametersBuilder setMethod(String method) {
+ this.method = method;
+ return this;
+ }
+
+ public ManyParametersBuilder setSize(int size) {
+ this.size = size;
+ return this;
+ }
+
+ public ManyParametersBuilder setData(byte[] data) {
+ this.data = data;
+ return this;
+ }
+
+ public ManyParameters createManyParameters() {
+ return new ManyParameters(computerName, timeout, method, size, data);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/NtfyMessageDto.java b/src/main/java/com/example/NtfyMessageDto.java
new file mode 100644
index 00000000..0a03f854
--- /dev/null
+++ b/src/main/java/com/example/NtfyMessageDto.java
@@ -0,0 +1,20 @@
+package com.example;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import java.text.SimpleDateFormat;
+import java.time.format.DateTimeFormatter;
+import java.util.Date;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public record NtfyMessageDto(String id, long time, String event, String topic, String message){
+ private static final DateTimeFormatter date =
+ DateTimeFormatter.ofPattern("HH:mm");
+ @Override
+ public String toString(){
+ String timeStr = new SimpleDateFormat("HH:mm").format(new Date(time * 1000));
+ return timeStr+ " " + message ;
+ }
+
+
+}
diff --git a/src/main/java/com/example/Singelton.java b/src/main/java/com/example/Singelton.java
new file mode 100644
index 00000000..2ff0fa10
--- /dev/null
+++ b/src/main/java/com/example/Singelton.java
@@ -0,0 +1,11 @@
+package com.example;
+
+public class Singelton {
+
+ private final static Singelton instance= new Singelton();
+
+ public static Singelton getInstance(){
+ return instance;
+ }
+
+}
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index 71574a27..649be1ab 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -1,6 +1,9 @@
module hellofx {
requires javafx.controls;
requires javafx.fxml;
+ requires io.github.cdimascio.dotenv.java;
+ requires java.net.http;
+ requires tools.jackson.databind;
opens com.example to javafx.fxml;
exports com.example;
diff --git a/src/main/resources/com/example/hello-view.fxml b/src/main/resources/com/example/hello-view.fxml
index 20a7dc82..667c7f1f 100644
--- a/src/main/resources/com/example/hello-view.fxml
+++ b/src/main/resources/com/example/hello-view.fxml
@@ -1,9 +1,22 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+