feat(config): ajout de persistance de données (taille et position fenêtre, dernier login, avatar, liste des hôtes et dernier hôte)

This commit is contained in:
Emi Boucly 2025-02-05 09:37:28 +01:00
parent d0bea3f7e8
commit 3bc5db868c
4 changed files with 116 additions and 10 deletions

View file

@ -6,10 +6,12 @@ import javafx.scene.Scene;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Locale; import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import java.util.Properties;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.LogManager; import java.util.logging.LogManager;
@ -17,7 +19,8 @@ import java.util.logging.Logger;
public class ChatApplication extends Application { public class ChatApplication extends Application {
public static final Logger LOGGER = Logger.getLogger(ChatApplication.class.getCanonicalName()); public static final Logger LOGGER = Logger.getLogger(ChatApplication.class.getCanonicalName());
private ChatController controller;
private Stage stage;
static { static {
try { try {
InputStream is = ChatApplication.class InputStream is = ChatApplication.class
@ -41,6 +44,45 @@ public class ChatApplication extends Application {
stage.setMinHeight(400); stage.setMinHeight(400);
stage.setScene(scene); stage.setScene(scene);
stage.show(); stage.show();
this.controller = fxmlLoader.getController();
this.stage = stage;
try {
Properties properties = new Properties();
properties.load(getClass().getResourceAsStream("config.properties"));
if (!properties.getProperty("width").isEmpty() && !properties.getProperty("height").isEmpty()) {
stage.setWidth(Double.parseDouble(properties.getProperty("width")));
stage.setHeight(Double.parseDouble(properties.getProperty("height")));
}
if (properties.getProperty("posx").isEmpty() || properties.getProperty("height").isEmpty()) {
stage.centerOnScreen();
} else {
stage.setX(Double.parseDouble(properties.getProperty("posx")));
stage.setY(Double.parseDouble(properties.getProperty("posy")));
}
} catch (IOException e) {
LOGGER.warning("Cannot load stage config!");
}
}
@Override
public void stop() {
try {
Properties properties = new Properties();
properties.load(getClass().getResourceAsStream("config.properties"));
properties.setProperty("width", String.valueOf(stage.getWidth()));
properties.setProperty("height", String.valueOf(stage.getHeight()));
properties.setProperty("posx", String.valueOf(stage.getX()));
properties.setProperty("posy", String.valueOf(stage.getY()));
LOGGER.finest(properties.toString());
properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
} catch (IOException e) {
LOGGER.warning("Cannot store stage info in config!");
}
} }
public static void main(String[] args) { public static void main(String[] args) {

View file

@ -36,12 +36,12 @@ import rtgre.modeles.*;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.util.Date; import java.util.*;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -78,7 +78,8 @@ public class ChatController implements Initializable {
private RoomMap roomMap = new RoomMap(); private RoomMap roomMap = new RoomMap();
private ObservableList<Room> roomObservableList = FXCollections.observableArrayList(); private ObservableList<Room> roomObservableList = FXCollections.observableArrayList();
private ResourceBundle i18nBundle; private ResourceBundle i18nBundle;
private Properties properties = new Properties();
private Vector<String> hostlist;
@Override @Override
public void initialize(URL url, ResourceBundle resourceBundle) { public void initialize(URL url, ResourceBundle resourceBundle) {
@ -87,14 +88,33 @@ public class ChatController implements Initializable {
this.avatarImageView.setImage(image); this.avatarImageView.setImage(image);
this.i18nBundle = resourceBundle; this.i18nBundle = resourceBundle;
try {
InputStream in = ChatController.class.getResourceAsStream("config.properties");
properties.load(in);
if (contact != null) {
this.contact.setAvatar(Contact.base64ToImage(properties.getProperty("avatar")));
}
this.avatarImageView.setImage(SwingFXUtils.toFXImage(Contact.base64ToBufferedImage(properties.getProperty("avatar")), null));
for (String host : (String[]) properties.getProperty("hosts").split(",")) {
host = host.replace("[", "").replace("]", "").replace(" ", "");
hostComboBox.getItems().addAll(host);
}
hostComboBox.setValue(!properties.getProperty("lasthost").isEmpty() ? properties.getProperty("lasthost") : hostComboBox.getItems().get(0));
loginTextField.setText(!properties.getProperty("login").isEmpty() ? properties.getProperty("login") : "");
} catch (IOException e) {
LOGGER.warning("Impossible de charger le fichier de configuration! Configuration par défaut chargée");
System.out.println(e.getMessage());
e.printStackTrace();
} catch (NullPointerException e) {
LOGGER.warning("Impossible de charger le fichier de configuration! Configuration par défaut chargée");
System.out.println(e.getMessage());
e.printStackTrace();
}
Thread dateTimeLoop = new Thread(this::dateTimeLoop); Thread dateTimeLoop = new Thread(this::dateTimeLoop);
dateTimeLoop.setDaemon(true); dateTimeLoop.setDaemon(true);
dateTimeLoop.start(); dateTimeLoop.start();
hostComboBox.getItems().addAll("localhost:2024");
hostComboBox.getItems().addAll("localhost:2025");
hostComboBox.setValue("localhost:2024");
hostComboBox.setOnAction(this::statusNameUpdate); hostComboBox.setOnAction(this::statusNameUpdate);
statusLabel.setText(i18nBundle.getString("disconnected")); statusLabel.setText(i18nBundle.getString("disconnected"));
@ -141,6 +161,8 @@ public class ChatController implements Initializable {
if (controller.isOk()) { if (controller.isOk()) {
hostComboBox.getItems().add(controller.hostTextField.getText()); hostComboBox.getItems().add(controller.hostTextField.getText());
hostComboBox.setValue(controller.hostTextField.getText()); hostComboBox.setValue(controller.hostTextField.getText());
properties.setProperty("hosts", hostComboBox.getItems().toString());
properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
} }
} catch (IOException e) { } catch (IOException e) {
LOGGER.warning("Impossible d'ouvrir la fenêtre de dialogue: fxml introuvable \n" + e.getMessage()); LOGGER.warning("Impossible d'ouvrir la fenêtre de dialogue: fxml introuvable \n" + e.getMessage());
@ -206,12 +228,20 @@ public class ChatController implements Initializable {
File selectedFile = fileChooser.showOpenDialog(stage); File selectedFile = fileChooser.showOpenDialog(stage);
if (selectedFile != null) { if (selectedFile != null) {
avatarImageView.setImage(new Image(selectedFile.toURI().toString())); avatarImageView.setImage(new Image(selectedFile.toURI().toString()));
contact.setAvatar(ImageIO.read(selectedFile)); if (contact != null) {
contact.setAvatar(ImageIO.read(selectedFile));
}
properties.setProperty("avatar", Contact.imageToBase64(ImageIO.read(selectedFile)));
properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
} }
} catch (IOException e) { } catch (IOException e) {
LOGGER.warning("Impossible de lire l'image!"); LOGGER.warning("Impossible de lire l'image!");
} }
client.sendEvent(new rtgre.modeles.Event("CONT", this.contact.toJsonObject())); try {
client.sendEvent(new rtgre.modeles.Event("CONT", this.contact.toJsonObject()));
} catch (Exception e) {
LOGGER.warning("Impossible d'envoyer l'évenement CONT! L'utilisateur est-il connecté?");
}
} }
@ -243,6 +273,14 @@ public class ChatController implements Initializable {
initPostListView(); initPostListView();
this.statusLabel.setText("%s%s@%s:%s".formatted(i18nBundle.getString("connected"), this.contact.getLogin(), host, port)); this.statusLabel.setText("%s%s@%s:%s".formatted(i18nBundle.getString("connected"), this.contact.getLogin(), host, port));
this.connectionButton.setText(i18nBundle.getString("disconnect")); this.connectionButton.setText(i18nBundle.getString("disconnect"));
try {
properties.setProperty("login", loginTextField.getText());
properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
} catch (Exception e) {
LOGGER.warning("Unable to store login in config!");
}
} catch (Exception e) { } catch (Exception e) {
new Alert(Alert.AlertType.ERROR, i18nBundle.getString("connectionError")).showAndWait(); new Alert(Alert.AlertType.ERROR, i18nBundle.getString("connectionError")).showAndWait();
connectionButton.setSelected(false); connectionButton.setSelected(false);
@ -281,6 +319,13 @@ public class ChatController implements Initializable {
private void statusNameUpdate(Event event) { private void statusNameUpdate(Event event) {
statusLabel.setText("not connected to " + hostComboBox.getValue()); statusLabel.setText("not connected to " + hostComboBox.getValue());
properties.setProperty("lasthost", hostComboBox.getValue());
try {
properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
} catch (IOException e) {
LOGGER.warning("Unable to write last host to config!");
}
} }

View file

@ -176,4 +176,16 @@ public class Contact {
return null; return null;
} }
public static BufferedImage base64ToBufferedImage(String avatar64) {
byte[] bytes64 = Base64.getDecoder().decode(avatar64);
try {
BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes64));
return image;
} catch (IOException e) {
LOGGER.severe("Impossible de convertir le base64 en image");
}
return null;
}
} }

File diff suppressed because one or more lines are too long