-
Notifications
You must be signed in to change notification settings - Fork 66
Chatwindow #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Chatwindow #15
Changes from all commits
768fd40
e314f01
16ee028
5ff126e
d08df97
d555609
db7c52e
13ed7b9
483ffb2
711e436
6b0e7fd
72eee3b
57f673e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| target/ | ||
| /.idea/ | ||
| .env |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,28 @@ | ||
| package com.example; | ||
|
|
||
| import javafx.application.Platform; | ||
| import javafx.beans.property.SimpleStringProperty; | ||
| import javafx.beans.property.StringProperty; | ||
| import javafx.collections.FXCollections; | ||
| import javafx.collections.ObservableList; | ||
|
|
||
| import java.util.concurrent.CompletableFuture; | ||
|
|
||
| /** | ||
| * Model layer: encapsulates application data and business logic. | ||
| */ | ||
| public class HelloModel { | ||
|
|
||
| private final NtfyConnection connection; | ||
|
|
||
| private final ObservableList<NtfyMessageDto> messages = FXCollections.observableArrayList(); | ||
| private final StringProperty messageToSend = new SimpleStringProperty(); | ||
|
|
||
| public HelloModel(NtfyConnection connection) { | ||
| this.connection = connection; | ||
| receiveMessage(); | ||
| } | ||
|
Comment on lines
+21
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid starting async operations in the constructor. Line 23 calls
Consider one of these alternatives: Option 1: Require explicit initialization after construction: public HelloModel(NtfyConnection connection) {
this.connection = connection;
- receiveMessage();
+ }
+
+ public void initialize() {
+ receiveMessage();
}Then update callers to call Option 2: Use a factory method: private HelloModel(NtfyConnection connection) {
this.connection = connection;
}
public static HelloModel create(NtfyConnection connection) {
HelloModel model = new HelloModel(connection);
model.receiveMessage();
return model;
}🤖 Prompt for AI Agents |
||
|
|
||
| /** | ||
| * Returns a greeting based on the current Java and JavaFX versions. | ||
| */ | ||
|
|
@@ -12,4 +31,40 @@ public String getGreeting() { | |
| String javafxVersion = System.getProperty("javafx.version"); | ||
| return "Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + "."; | ||
| } | ||
| public ObservableList<NtfyMessageDto> getMessages() { | ||
| return messages; | ||
| } | ||
|
|
||
| public String getMessageToSend() { | ||
| return messageToSend.get(); | ||
| } | ||
|
|
||
| public StringProperty messageToSendProperty() { | ||
| return messageToSend; | ||
| } | ||
|
|
||
| public void setMessageToSend(String message) { | ||
| messageToSend.set(message); | ||
| } | ||
|
|
||
| public CompletableFuture<Void> sendMessage() { | ||
| return connection.send(messageToSend.get()); | ||
| } | ||
|
|
||
| public void receiveMessage() { | ||
| connection.receive(m->runOnFx(()-> messages.add(m))); | ||
| } | ||
|
|
||
| private static void runOnFx(Runnable task) { | ||
| try { | ||
| if (Platform.isFxApplicationThread()) task.run(); | ||
| else Platform.runLater(task); | ||
| } catch (IllegalStateException notInitialized) { | ||
| // JavaFX toolkit not initialized (e.g., unit tests): run inline | ||
| task.run(); | ||
| } | ||
| } | ||
|
|
||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package com.example; | ||
|
|
||
| import java.util.concurrent.CompletableFuture; | ||
| import java.util.function.Consumer; | ||
|
|
||
| public interface NtfyConnection { | ||
|
|
||
| CompletableFuture<Void> send(String message); | ||
|
|
||
| void receive(Consumer<NtfyMessageDto> messageHandler); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package com.example; | ||
|
|
||
| import io.github.cdimascio.dotenv.Dotenv; | ||
| import tools.jackson.databind.ObjectMapper; | ||
|
|
||
| import java.net.URI; | ||
| import java.net.http.HttpClient; | ||
| import java.net.http.HttpRequest; | ||
| import java.net.http.HttpResponse; | ||
| import java.util.Objects; | ||
| import java.util.concurrent.CompletableFuture; | ||
| import java.util.function.Consumer; | ||
|
|
||
| public class NtfyConnectionImpl implements NtfyConnection { | ||
|
|
||
| private final HttpClient http = HttpClient.newHttpClient(); | ||
| private final String hostName; | ||
| private final ObjectMapper mapper = new ObjectMapper(); | ||
|
|
||
| public NtfyConnectionImpl() { | ||
| Dotenv dotenv = Dotenv.load(); | ||
| hostName = Objects.requireNonNull(dotenv.get("HOST_NAME")); | ||
| } | ||
|
|
||
| public NtfyConnectionImpl(String hostName) { | ||
| this.hostName = hostName; | ||
| } | ||
|
|
||
| @Override | ||
| public CompletableFuture<Void> send(String message) { | ||
| HttpRequest httpRequest = HttpRequest.newBuilder() | ||
| .POST(HttpRequest.BodyPublishers.ofString(message)) | ||
| .header("Cache-Control", "no") | ||
| .uri(URI.create(hostName + "/mytopic")) | ||
| .build(); | ||
|
|
||
| return http.sendAsync(httpRequest, HttpResponse.BodyHandlers.discarding()) | ||
| .thenAccept(response -> System.out.println("Message sent!")) | ||
| .exceptionally(e -> { | ||
| System.out.println("Error sending message"); | ||
| return null; | ||
| }); | ||
| } | ||
|
Comment on lines
+29
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix the Cache header and use proper logging. Line 34 uses an incorrect header name Apply this diff: public CompletableFuture<Void> send(String message) {
HttpRequest httpRequest = HttpRequest.newBuilder()
.POST(HttpRequest.BodyPublishers.ofString(message))
- .header("Cache", "no")
+ .header("Cache-Control", "no-cache")
.uri(URI.create(hostName + "/mytopic"))
.build();
return http.sendAsync(httpRequest, HttpResponse.BodyHandlers.discarding())
- .thenAccept(response -> System.out.println("Message sent!"))
+ .thenAccept(response -> logger.info("Message sent successfully"))
.exceptionally(e -> {
- System.out.println("Error sending message");
+ logger.error("Error sending message", e);
return null;
});
}You'll need to add a logger field: private static final Logger logger = LoggerFactory.getLogger(NtfyConnectionImpl.class);🤖 Prompt for AI Agents |
||
|
|
||
| @Override | ||
| public void receive (Consumer < NtfyMessageDto > messageHandler) { | ||
| 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.out.println("Failed to parse message"); | ||
| return null; | ||
| } | ||
| }) | ||
| .filter(message -> message !=null && message.event().equals("message")) | ||
| .peek(System.out::println) | ||
| .forEach(messageHandler)); | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package com.example; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
|
|
||
| @JsonIgnoreProperties(ignoreUnknown = true) | ||
| public record NtfyMessageDto( | ||
| String id, | ||
| long time, | ||
| String event, | ||
| String topic, | ||
| String message | ||
| ){} |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,6 +1,10 @@ | ||||||
| module hellofx { | ||||||
| requires javafx.controls; | ||||||
| requires javafx.fxml; | ||||||
| requires io.github.cdimascio.dotenv.java; | ||||||
| requires java.net.http; | ||||||
| requires tools.jackson.databind; | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incorrect module name for Jackson databind. The module name requires java.net.http;
- requires tools.jackson.databind;
+ requires com.fasterxml.jackson.databind;
requires javafx.graphics;This must be fixed alongside the pom.xml groupId correction. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| requires javafx.graphics; | ||||||
|
|
||||||
| opens com.example to javafx.fxml; | ||||||
| exports com.example; | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,25 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <?import javafx.scene.layout.StackPane?> | ||
| <?import javafx.scene.control.Label?> | ||
|
|
||
| <StackPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.example.HelloController"> | ||
| <children> | ||
| <Label fx:id="messageLabel" text="Hello, JavaFX!" /> | ||
| </children> | ||
| </StackPane> | ||
|
|
||
| <?import javafx.geometry.*?> | ||
| <?import javafx.scene.control.*?> | ||
| <?import javafx.scene.layout.*?> | ||
|
|
||
| <VBox prefHeight="500.0" prefWidth="300.0" stylesheets="@../../css/style.css" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.HelloController"> | ||
|
|
||
| <Label fx:id="messageLabel" alignment="CENTER" contentDisplay="CENTER" maxWidth="Infinity" text="Hello, JavaFX!" VBox.vgrow="NEVER" /> | ||
| <BorderPane VBox.vgrow="ALWAYS"> | ||
| <center> | ||
| <ListView fx:id="messageView"> | ||
| <padding> | ||
| <Insets bottom="1.0" left="1.0" right="1.0" top="1.0" /> | ||
| </padding> | ||
| </ListView> | ||
| </center> | ||
| </BorderPane> | ||
|
|
||
| <HBox VBox.vgrow="NEVER" alignment="CENTER_LEFT"> <padding> <Insets bottom="5.0" left="10.0" right="10.0" top="10.0" /></padding> | ||
| <TextArea fx:id="chatArea" opacity="0.8" prefRowCount="3" wrapText="true" HBox.hgrow="ALWAYS" /> | ||
| <Button fx:id="chatButton" maxWidth="-Infinity" minWidth="-Infinity" onAction="#sendMessage" text="Send Message" /> | ||
| </HBox> | ||
|
|
||
| </VBox> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
|
|
||
| /* | ||
| styles.css | ||
| */ | ||
| .root { | ||
| -fx-background-color: | ||
| linear-gradient(to bottom, | ||
| rgba(0,0,0,0.1) 0%, | ||
| rgba(0,0,0,0) 10%), | ||
| linear-gradient(to bottom, | ||
| #8b0000 30%, | ||
| #ffd700 100%); | ||
| -fx-background-insets: 0, 4; | ||
| -fx-background-radius: 0, 3; | ||
| -fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.4), 10, 0.5, 0, 0) | ||
|
|
||
| } | ||
| .list-view { | ||
| -fx-background-color: transparent; /* Make background transparent */ | ||
| -fx-background-insets: 0; | ||
| -fx-padding: 0; | ||
| -fx-border-color: transparent; | ||
| -fx-background-radius: 5; | ||
| -fx-border-radius: 5; | ||
| } | ||
| .list-cell{ | ||
| -fx-background-color: transparent; | ||
| -fx-border-color: transparent; | ||
| -fx-control-inner-background: transparent; | ||
| -fx-font-size: 14; | ||
| -fx-font-weight: bold; | ||
| -fx-padding: 5 10 5 10; | ||
| } | ||
| .text-area{ | ||
| -fx-control-inner-background: #FFFFFF; | ||
| -fx-padding: 5px 7px; | ||
| -fx-text-fill: black; | ||
| -fx-font-size: 14; | ||
|
|
||
| -fx-border-radius: 10; | ||
| -fx-background-radius: 10; | ||
| -fx-background-color: transparent; | ||
| -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.2), 5, 0, 0, 0); | ||
| } | ||
| .text-area .content, .viewport { | ||
| -fx-background-radius: 8; | ||
| -fx-border-radius: 8; | ||
| } | ||
| .button{ | ||
| -fx-background-color: #610202; | ||
| -fx-text-fill: white; | ||
| -fx-font-size: 12px; | ||
| -fx-padding: 10 15 10 15; | ||
| -fx-background-radius: 5px; | ||
| -fx-border-radius: 8px; | ||
| } | ||
| .button:hover{ | ||
| -fx-background-color: #400101; | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.