1313import javafx .scene .control .TextField ;
1414import javafx .scene .image .Image ;
1515import javafx .scene .image .ImageView ;
16- import javafx .scene .layout .VBox ;
1716import javafx .scene .text .Text ;
1817import javafx .scene .text .TextFlow ;
1918import javafx .stage .FileChooser ;
2019
2120import java .io .File ;
2221import java .net .URL ;
23- import java .nio .file .Files ;
2422import java .time .format .DateTimeFormatter ;
25- import java .util .Base64 ;
2623import java .util .ResourceBundle ;
2724import java .util .function .Predicate ;
2825
@@ -46,99 +43,48 @@ private String getCurrentUsername() {
4643
4744 @ Override
4845 public void initialize (URL url , ResourceBundle rb ) {
49-
5046 filteredList = new FilteredList <>(masterList , msg -> true );
5147 chatList .setItems (filteredList );
5248
5349 chatList .setCellFactory (list -> new ListCell <>() {
5450 @ Override
5551 protected void updateItem (ChatMessage msg , boolean empty ) {
5652 super .updateItem (msg , empty );
57- if (empty || msg == null ) {
58- setGraphic (null );
59- return ;
60- }
53+ if (empty || msg == null ) { setGraphic (null ); return ; }
6154
6255 Text user = new Text (msg .getUsername ());
6356 user .setStyle ("-fx-font-weight: bold;" );
64-
6557 Text time = new Text (" (" + msg .getTimestamp () + ")\n " );
6658 time .setStyle ("-fx-fill: gray; -fx-font-size: 12px;" );
6759
68- if (msg .getFileName () != null ) {
69-
70- if (msg .getFileUrl () != null && msg .getMimeType () != null ) {
71-
72- // Images → inline display
73- if (msg .getMimeType ().startsWith ("image/" )) {
74- ImageView img = new ImageView (new Image (msg .getFileUrl (), true ));
75- img .setPreserveRatio (true );
76- img .setFitWidth (250 );
77-
78- VBox box = new VBox (
79- new TextFlow (user , time ),
80- img
81- );
82- setGraphic (box );
83- return ;
84- }
85-
60+ if (msg .getFileName () != null && msg .getFileUrl () != null ) {
61+ if (msg .getMimeType () != null && msg .getMimeType ().startsWith ("image/" )) {
62+ try {
63+ ImageView imageView = new ImageView (new Image (msg .getFileUrl (), true ));
64+ imageView .setFitWidth (200 );
65+ imageView .setPreserveRatio (true );
66+ Text messageText = new Text (msg .getMessage () + "\n " );
67+ messageText .setStyle ("-fx-font-size: 14px;" );
68+ setGraphic (new TextFlow (user , time , messageText , imageView ));
69+ } catch (Exception e ) { e .printStackTrace (); }
70+ } else {
8671 Hyperlink link = new Hyperlink (msg .getFileName ());
87- link .setOnAction (e -> {
88- try {
89- HelloFX .hostServices ().showDocument (msg .getFileUrl ());
90- } catch (Exception ex ) {
91- ex .printStackTrace ();
92- }
93- });
94-
95- VBox box = new VBox (
96- new TextFlow (user , time ),
97- link
98- );
99- setGraphic (box );
100- return ;
101- }
102-
103-
104- if (msg .getFileData () != null ) {
105- Text messageText = new Text ((msg .getMessage () == null ? "" : msg .getMessage ()) + "\n " );
72+ final String fileUrl = msg .getFileUrl ();
73+ link .setOnAction (ev -> HelloFX .hostServices ().showDocument (fileUrl ));
74+ Text messageText = new Text (msg .getMessage () + "\n " );
10675 messageText .setStyle ("-fx-font-size: 14px;" );
107-
108- Hyperlink fileLink = new Hyperlink (msg .getFileName ());
109- final String fileName = msg .getFileName ();
110- final String fileData = msg .getFileData ();
111-
112- fileLink .setOnAction (event -> {
113- try {
114- byte [] data = Base64 .getDecoder ().decode (fileData );
115- FileChooser chooser = new FileChooser ();
116- chooser .setInitialFileName (fileName );
117- File saveFile = chooser .showSaveDialog (chatList .getScene ().getWindow ());
118- if (saveFile != null ) {
119- Files .write (saveFile .toPath (), data );
120- }
121- } catch (Exception e ) {
122- e .printStackTrace ();
123- }
124- });
125-
126- TextFlow flow = new TextFlow (user , time , messageText , fileLink );
127- setGraphic (flow );
128- return ;
76+ setGraphic (new TextFlow (user , time , messageText , link ));
12977 }
78+ } else {
79+ Text text = new Text (msg .getMessage ());
80+ text .setStyle ("-fx-font-size: 14px;" );
81+ setGraphic (new TextFlow (user , time , text ));
13082 }
131-
132- String body = msg .getMessage () == null ? "" : msg .getMessage ();
133- Text text = new Text (body );
134- text .setStyle ("-fx-font-size: 14px;" );
135- TextFlow flow = new TextFlow (user , time , text );
136- setGraphic (flow );
13783 }
13884 });
13985
140- usernameField .textProperty ().addListener ((obs , oldVal , newVal ) -> updateFilterPredicate ());
14186 hideMyMessagesCheck .selectedProperty ().addListener ((obs , oldVal , newVal ) -> updateFilterPredicate ());
87+ usernameField .textProperty ().addListener ((obs , oldVal , newVal ) -> updateFilterPredicate ());
14288
14389 model .loadHistory (msg -> Platform .runLater (() -> masterList .add (msg )));
14490 model .listenForMessages (msg -> Platform .runLater (() -> masterList .add (msg )));
@@ -147,14 +93,7 @@ protected void updateItem(ChatMessage msg, boolean empty) {
14793 private void updateFilterPredicate () {
14894 final String current = getCurrentUsername ();
14995 final boolean hideMine = hideMyMessagesCheck .isSelected ();
150-
151- Predicate <ChatMessage > pred = chatMessage -> {
152- if (!hideMine ) return true ;
153- String msgUser = chatMessage .getUsername ();
154- if (msgUser == null ) msgUser = "Anonymous" ;
155- return !msgUser .equals (current );
156- };
157-
96+ Predicate <ChatMessage > pred = msg -> !hideMine || !current .equals (msg .getUsername ());
15897 filteredList .setPredicate (pred );
15998 }
16099
@@ -163,22 +102,11 @@ private void onSend() {
163102 String user = getCurrentUsername ();
164103 String msg = inputField .getText ().trim ();
165104 if (msg .isEmpty ()) return ;
166-
167- final String safeUser = user ;
168- final String safeMsg = msg ;
169105 inputField .clear ();
170106
171107 new Thread (() -> {
172- try {
173- model .sendMessage (safeUser , safeMsg );
174- } catch (Exception e ) {
175- e .printStackTrace ();
176- Platform .runLater (() -> masterList .add (new ChatMessage (
177- "system" ,
178- "[send failed] " + e .getMessage (),
179- java .time .ZonedDateTime .now ().format (DateTimeFormatter .ofPattern ("yyyy-MM-dd HH:mm" ))
180- )));
181- }
108+ try { model .sendMessage (user , msg ); }
109+ catch (Exception e ) { e .printStackTrace (); }
182110 }).start ();
183111 }
184112
@@ -187,8 +115,6 @@ private void onAttachFile() {
187115 FileChooser fileChooser = new FileChooser ();
188116 fileChooser .setTitle ("Select a file to send" );
189117 File file = fileChooser .showOpenDialog (chatList .getScene ().getWindow ());
190- if (file != null ) {
191- new Thread (() -> model .sendFile (file , getCurrentUsername ())).start ();
192- }
118+ if (file != null ) new Thread (() -> model .sendFile (getCurrentUsername (), file )).start ();
193119 }
194120}
0 commit comments