Merge branch 'dev-avatar' into 'dev'

feat(avatar): Gestion des avatars en base64

See merge request iut_rt/but2/sae302-applicom/bouclyma!8
This commit is contained in:
Emi Boucly 2025-01-28 09:48:25 +01:00
commit 8cea05bb7b
4 changed files with 89 additions and 36 deletions

View file

@ -126,11 +126,6 @@ public class ChatController implements Initializable {
sendButton.disableProperty().bind(canSendCondition);
messageTextField.disableProperty().bind(canSendCondition);
/* /!\ Set-up d'environnement de test /!\ */
/* -------------------------------------- */
loginTextField.setText("riri");
connectionButton.setSelected(true);
/* -------------------------------------- */
}
private void initRoomListView() {
@ -161,20 +156,25 @@ public class ChatController implements Initializable {
/**
* Ouvre une fenêtre de dialogue permettant de choisir son avatar
*/
FileChooser fileChooser = new FileChooser();
Stage stage = (Stage) avatarImageView.getScene().getWindow();
fileChooser.setTitle("Select Avatar");
fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter("Image Files", "*.png", "*.jpg")
);
File selectedFile = fileChooser.showOpenDialog(stage);
if (selectedFile != null) {
avatarImageView.setImage(new Image(selectedFile.toURI().toString()));
try {
FileChooser fileChooser = new FileChooser();
Stage stage = (Stage) avatarImageView.getScene().getWindow();
fileChooser.setTitle("Select Avatar");
fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter("Image Files", "*.png", "*.jpg")
);
File selectedFile = fileChooser.showOpenDialog(stage);
if (selectedFile != null) {
avatarImageView.setImage(new Image(selectedFile.toURI().toString()));
contact.setAvatar(ImageIO.read(selectedFile));
}
} catch (IOException e) {
LOGGER.warning("Impossible de lire l'image!");
}
client.sendEvent(new rtgre.modeles.Event("CONT", this.contact.toJsonObject()));
}
private void handleConnection(Observable observable) {
if (connectionButton.isSelected()) {
java.awt.Image img = SwingFXUtils.fromFXImage(this.avatarImageView.getImage(), null);
@ -198,7 +198,7 @@ public class ChatController implements Initializable {
client.sendAuthEvent(contact);
client.sendListRoomEvent();
client.sendEvent(new rtgre.modeles.Event(rtgre.modeles.Event.LIST_CONTACTS, new JSONObject()));
client.sendEvent(new rtgre.modeles.Event(rtgre.modeles.Event.CONT, contact.toJsonObject()));
initContactListView();
initPostListView();
this.statusLabel.setText("Connected to %s@%s:%s".formatted(this.contact.getLogin(), host, port));
@ -260,9 +260,9 @@ public class ChatController implements Initializable {
contactsListView.setCellFactory(contactListView -> new ContactListViewCell());
contactsListView.setItems(contactObservableList);
File avatars = new File(getClass().getResource("avatars.png").toURI());
Contact fifi = new Contact("fifi", true, avatars);
contactObservableList.add(fifi);
contactMap.add(fifi);
//Contact fifi = new Contact("fifi", true, avatars);
//contactObservableList.add(fifi);
//contactMap.add(fifi);
} catch (Exception e) {
LOGGER.severe(e.getMessage());
}
@ -432,18 +432,29 @@ public class ChatController implements Initializable {
}
private void handleContEvent(JSONObject content) {
Contact contact = contactMap.getContact(content.getString("login"));
java.awt.Image avatar = null;
if (!content.getString("avatar").isEmpty()) {
avatar = Contact.base64ToImage(content.getString("avatar"));
}
System.out.println(avatar);
if (contact != null) {
LOGGER.info(contactMap.toString());
contactMap.getContact(content.getString("login")).setConnected(content.getBoolean("connected"));
if (avatar != null) {
contactMap.getContact(content.getString("login")).setAvatar(avatar);
}
contactsListView.refresh();
LOGGER.info(contactMap.toString());
} else {
System.out.println(content);
LOGGER.info(contactMap.toString());
Contact user = Contact.fromJSON(
content,
new File("chat/src/main/resources/rtgre/chat/avatars.png")
);
System.out.println(user.getAvatar());
if (avatar != null) {
user.setAvatar(avatar);
}
contactMap.add(user);
contactObservableList.add(user);
LOGGER.info(contactMap.toString());

View file

@ -4,9 +4,13 @@ package rtgre.modeles;
import org.json.JSONObject;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Base64;
import java.util.Objects;
import static rtgre.chat.ChatApplication.LOGGER;
@ -108,7 +112,8 @@ public class Contact {
public JSONObject toJsonObject() {
return new JSONObject()
.put("login", this.login)
.put("connected", this.connected);
.put("connected", this.connected)
.put("avatar", Contact.imageToBase64((BufferedImage) avatar));
}
public String toJson() {
@ -140,8 +145,35 @@ public class Contact {
}
}
public void setAvatar(java.awt.Image avatar) {
this.avatar = avatar;
}
public void setCurrentRoom(String currentRoom) {
this.currentRoom = currentRoom;
}
public static String imageToBase64(BufferedImage img) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ImageIO.write(img, "png", bos);
System.out.println(Base64.getEncoder().encodeToString(bos.toByteArray()));
return Base64.getEncoder().encodeToString(bos.toByteArray());
} catch (IOException e) {
LOGGER.severe("Impossible de convertir l'image en base64");
}
return "";
}
public static java.awt.Image base64ToImage(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

View file

@ -39,7 +39,7 @@ public class ChatServer {
public static void main(String[] args) throws IOException {
ChatServer server = new ChatServer(2024);
daisyConnect();
//daisyConnect();
server.acceptClients();
}
@ -268,12 +268,23 @@ public class ChatServer {
} else if (event.getType().equals(Event.QUIT)) {
LOGGER.info("Déconnexion");
return false;
} else if (event.getType().equals(Event.CONT)) {
doCont(event.getContent());
LOGGER.info("Update de contact");
return true;
} else {
LOGGER.warning("Unhandled event type: " + event.getType());
return false;
}
}
private void doCont(JSONObject content) {
if (user.isConnected()) {
sendEventToAllContacts(new Event("CONT", content));
contactMap.getContact(content.getString("login")).setAvatar(Contact.base64ToImage(content.getString("avatar")));
}
}
private void doJoin(JSONObject content) {
if (content.getString("room").isEmpty()) {
user.setCurrentRoom(null);
@ -368,11 +379,7 @@ public class ChatServer {
private void doListContact(JSONObject content) throws JSONException, IllegalStateException {
for (Contact contact: contactMap.values()) {
if (contactMap.getContact(user.getLogin()).isConnected()) {
try {
send(new Event(Event.CONT, contact.toJsonObject()).toJson());
} catch (IOException e) {
throw new IllegalStateException();
}
sendEventToContact(user, new Event(Event.CONT, contact.toJsonObject()));
}
}
}