Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
target/
/.idea/
.env
24 changes: 22 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,26 @@
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>io.github.cdimascio</groupId>
<artifactId>dotenv-java</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-swing</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock</artifactId>
<version>4.0.0-beta.15</version>
</dependency>
</dependencies>
<build>
<plugins>
Expand All @@ -55,7 +75,7 @@
<configuration>
<mainClass>com.example.HelloFX</mainClass>
<options>
<option>--enable-native-access=javafx.graphics</option>
<option>--enable-native-access=javafx.graphics</option>
</options>
<launcher>javafx</launcher>
<stripDebug>true</stripDebug>
Expand All @@ -65,4 +85,4 @@
</plugin>
</plugins>
</build>
</project>
</project>
7 changes: 7 additions & 0 deletions src/main/java/com/example/AttachmentDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example;

public record AttachmentDto(
String name,
String url,
String type,
long size) {}
104 changes: 103 additions & 1 deletion src/main/java/com/example/HelloController.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,124 @@
package com.example;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.stage.FileChooser;

import javafx.scene.layout.VBox;
import javafx.geometry.Insets;
import javafx.scene.control.Label;

import java.awt.*;
import java.net.URI;
import java.time.Instant;
import java.time.ZoneId;


import java.io.File;
import java.nio.file.Path;

import static com.example.HelloModel.runOnFx;

/**
* Controller layer: mediates between the view (FXML) and the model.
*/
public class HelloController {

private final HelloModel model = new HelloModel();
private final HelloModel model = new HelloModel(new NtfyConnectionImpl());
@FXML
public ListView<NtfyMessageDto> messageView;

@FXML
private Label messageLabel;

@FXML
private void initialize() {
System.out.println("Controller init: kopplar ListView");

if (messageLabel != null) {
messageLabel.setText(model.getGreeting());
}

messageView.setItems(model.getMessages());

messageView.setCellFactory(listView -> new ListCell<>() {
@Override
protected void updateItem(NtfyMessageDto item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
} else {
VBox container = new VBox();
container.setSpacing(4);

Label topicLabel = new Label(item.topic());
topicLabel.setStyle("-fx-font-weight: bold; -fx-text-fill: #2a9df4;");

Label messageLabel = new Label(item.message());
messageLabel.setWrapText(true);
messageLabel.setStyle("-fx-text-fill: #333333;");

Label timeLabel = new Label("⏰ " + Instant.ofEpochMilli(item.time()).atZone(ZoneId.systemDefault()).toLocalDateTime());
timeLabel.setStyle("-fx-font-size: 10px; -fx-text-fill: #888888;");

container.getChildren().addAll(topicLabel, messageLabel, timeLabel);

// Lägg till nedladdningslänk om fil finns
if (item.attachmentUrl() != null && !item.attachmentUrl().isEmpty()) {
Hyperlink downloadLink = new Hyperlink("📎 Ladda ner fil");
downloadLink.setOnAction(e -> {
try {
Desktop.getDesktop().browse(new URI(item.attachmentUrl()));
} catch (Exception ex) {
ex.printStackTrace();
}
});
container.getChildren().add(downloadLink);
}

container.setPadding(new Insets(8));
container.setStyle("-fx-background-color: #f4f4f4; -fx-background-radius: 6;");

setGraphic(container);
}
}
});
}

@FXML
private javafx.scene.control.TextField messageInput;


public void sendMessage(ActionEvent actionEvent) {
String content = messageInput.getText();
model.setMessageToSend(content);
model.sendMessage();
}

@FXML
private void sendFile(ActionEvent event) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Välj en fil att skicka");
File selectedFile = fileChooser.showOpenDialog(messageInput.getScene().getWindow());

if (selectedFile != null) {
Path filePath = selectedFile.toPath();
model.sendFile(filePath).thenAccept(success -> {
runOnFx(() -> {
if (success) {
System.out.println("Fil skickad: " + filePath.getFileName());
} else {
System.out.println("Misslyckades att skicka filen.");
}
});
});
} else {
System.out.println("Ingen fil vald.");
}
}

}

1 change: 1 addition & 0 deletions src/main/java/com/example/HelloFX.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ 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);
scene.getStylesheets().add(getClass().getResource("/com/example/style.css").toExternalForm());
stage.setTitle("Hello MVC");
stage.setScene(scene);
stage.show();
Expand Down
68 changes: 66 additions & 2 deletions src/main/java/com/example/HelloModel.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,79 @@
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.nio.file.Path;
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();
}

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);
}

/**
* Returns a greeting based on the current Java and JavaFX versions.
*/
public String getGreeting() {
String javaVersion = System.getProperty("java.version");
String javafxVersion = System.getProperty("javafx.version");
return "Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + ".";
return "Hello, 404 java not found!";
}

public CompletableFuture<Boolean> sendMessage() {
System.out.println("Meddelande att skicka: " + messageToSend.get());
return connection.send(messageToSend.get());
}
}

public CompletableFuture<Boolean> sendFile(Path filePath) {
return connection.sendFile(filePath);
}

public void receiveMessage() {
connection.receive(m -> runOnFx(() -> messages.add(m)));
}

public void testAddMessage() {
NtfyMessageDto test = new NtfyMessageDto("id123", System.currentTimeMillis(), "message", "mytopic", "Testmeddelande", null);
runOnFx(() -> messages.add(test));
}

static void runOnFx(Runnable task) {
try {
if (Platform.isFxApplicationThread()) task.run();
else Platform.runLater(task);
} catch (IllegalStateException notInitialized) {
task.run();
}
}

}
18 changes: 18 additions & 0 deletions src/main/java/com/example/ManyParameters.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
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") //Fluent API
.setTimeout(10)
.setSize(0)
.createManyParameters();
}
}
38 changes: 38 additions & 0 deletions src/main/java/com/example/ManyParametersBuilder.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
15 changes: 15 additions & 0 deletions src/main/java/com/example/NtfyConnection.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.example;

import java.nio.file.Path;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

public interface NtfyConnection {

public CompletableFuture<Boolean> send(String message);

public void receive(Consumer<NtfyMessageDto> messageHandler);

public CompletableFuture<Boolean> sendFile(Path path);

}
Loading
Loading