Chat page UI updated.

This commit is contained in:
Asal Lotfi
2025-09-05 17:15:29 +03:30
parent f4be87a6df
commit 7fe4a997fd
4 changed files with 77 additions and 48 deletions
@@ -71,15 +71,17 @@ public class ChatPageController {
@FXML private VBox blockedPane; @FXML private VBox blockedPane;
@FXML @FXML
private Button moreButton; // 3-dots button private Button chatMoreButton; // 3-dots button
@FXML @FXML
private ImageView moreIcon; private ImageView moreIcon;
@FXML @FXML
private ContextMenu moreMenu; private ContextMenu chatMoreMenu;
@FXML @FXML
private MenuItem viewProfileItem; private MenuItem viewProfileItem;
@FXML @FXML
private MenuItem deleteChatItem; private MenuItem deleteChatItem;
@FXML
private MenuItem archiveItem;
// ===== send icon ===== // ===== send icon =====
@FXML @FXML
@@ -262,12 +264,12 @@ public class ChatPageController {
} }
// Hook "More" button → show menu under it // Hook "More" button → show menu under it
if (moreButton != null) { if (chatMoreButton != null) {
moreButton.setOnAction(e -> { chatMoreButton.setOnAction(e -> {
if (!moreMenu.isShowing()) { if (!chatMoreMenu.isShowing()) {
moreMenu.show(moreButton, Side.BOTTOM, 0, 0); chatMoreMenu.show(chatMoreButton, Side.BOTTOM, 0, 0);
} else { } else {
moreMenu.hide(); chatMoreMenu.hide();
} }
}); });
} }
@@ -283,6 +285,19 @@ public class ChatPageController {
// TODO: delete logic // TODO: delete logic
}); });
if (archiveItem != null) {
archiveItem.setOnAction(e -> {
System.out.println("Toggling archive for chat " + chatName);
// TODO: backend call → toggleArchive(chatId, type)
// Also update text: "Archive chat" ↔ "Unarchive chat"
if ("Archive chat".equals(archiveItem.getText())) {
archiveItem.setText("Unarchive chat");
} else {
archiveItem.setText("Archive chat");
}
});
}
// Initial icon sync once the Scene is ready (stylesheet applied) // Initial icon sync once the Scene is ready (stylesheet applied)
Platform.runLater(this::syncIconsWithTheme); Platform.runLater(this::syncIconsWithTheme);
@@ -933,42 +948,34 @@ public class ChatPageController {
} }
private void configureHeaderActions(ChatEntry entry) { private void configureHeaderActions(ChatEntry entry) {
moreMenu.getItems().clear(); chatMoreMenu.getItems().clear();
switch (entry.getType().toLowerCase(Locale.ROOT)) { switch (entry.getType().toLowerCase(Locale.ROOT)) {
case "private" -> { case "private" -> {
MenuItem viewProfile = new MenuItem("View profile"); archiveItem.setOnAction(e -> toggleArchive(entry));
viewProfile.setOnAction(e -> openInfoScene(entry)); viewProfileItem.setOnAction(e -> openInfoScene(entry));
deleteChatItem.setOnAction(e -> deleteChatButton(entry));
MenuItem deleteChat = new MenuItem("Delete chat"); chatMoreMenu.getItems().addAll(archiveItem, viewProfileItem, deleteChatItem);
deleteChat.setStyle("-fx-text-fill: red;");
deleteChat.setOnAction(e -> deleteChatButton(entry));
moreMenu.getItems().addAll(viewProfile, deleteChat);
} }
case "group" -> { case "group" -> {
MenuItem viewGroup = new MenuItem("View group info"); MenuItem viewGroup = new MenuItem("View group info");
viewGroup.setOnAction(e -> openInfoScene(entry)); viewGroup.setOnAction(e -> openInfoScene(entry));
MenuItem leaveGroup = new MenuItem("Leave group"); MenuItem leaveGroup = new MenuItem("Leave group");
leaveGroup.setOnAction(e -> leaveGroupButton(entry)); leaveGroup.setOnAction(e -> leaveGroupButton(entry));
chatMoreMenu.getItems().addAll(viewGroup, leaveGroup);
moreMenu.getItems().addAll(viewGroup, leaveGroup);
} }
case "channel" -> { case "channel" -> {
MenuItem viewChannel = new MenuItem("View channel info"); MenuItem viewChannel = new MenuItem("View channel info");
viewChannel.setOnAction(e -> openInfoScene(entry)); viewChannel.setOnAction(e -> openInfoScene(entry));
MenuItem leaveChannel = new MenuItem("Leave channel"); MenuItem leaveChannel = new MenuItem("Leave channel");
leaveChannel.setOnAction(e -> leaveChannelButton(entry)); leaveChannel.setOnAction(e -> leaveChannelButton(entry));
chatMoreMenu.getItems().addAll(viewChannel, leaveChannel);
moreMenu.getItems().addAll(viewChannel, leaveChannel);
} }
} }
// Clicking header (but not the 3-dot) → open info scene // Header click opens info
chatHeader.setOnMouseClicked(e -> { chatHeader.setOnMouseClicked(e -> {
if (!moreButton.equals(e.getTarget())) { if (!chatMoreButton.equals(e.getTarget())) {
openInfoScene(entry); openInfoScene(entry);
} }
}); });
@@ -1138,6 +1145,19 @@ public class ChatPageController {
} }
} }
private void toggleArchive(ChatEntry entry) {
if (entry == null) return;
// Just toggle the text for now
if ("Archive chat".equals(archiveItem.getText())) {
archiveItem.setText("Unarchive chat");
System.out.println("Pretend: chat " + entry.getName() + " archived.");
} else {
archiveItem.setText("Archive chat");
System.out.println("Pretend: chat " + entry.getName() + " unarchived.");
}
}
private void loadMessages(ChatEntry entry) { private void loadMessages(ChatEntry entry) {
JSONObject req = new JSONObject(); JSONObject req = new JSONObject();
req.put("action", "get_messages_UI"); req.put("action", "get_messages_UI");
@@ -2945,20 +2965,24 @@ public class ChatPageController {
String suffix = dark ? "_light.png" : "_dark.png"; String suffix = dark ? "_light.png" : "_dark.png";
if (attachmentIcon != null) attachmentIcon.setImage(loadIcon("attachment" + suffix)); if (attachmentIcon != null) attachmentIcon.setImage(loadIcon("attachment" + suffix));
if (sendIcon != null) sendIcon.setImage(loadIcon("send_cyan2.png")); if (sendIcon != null) sendIcon.setImage(loadIcon("send_cyan2.png")); // always cyan
if (searchIcon != null) searchIcon.setImage(loadIcon("search" + suffix)); if (searchIcon != null) searchIcon.setImage(loadIcon("search" + suffix));
if (moreIcon != null) moreIcon.setImage(loadIcon("more" + suffix)); if (moreIcon != null) moreIcon.setImage(loadIcon("more" + suffix));
if (chatTitle != null) chatTitle.setStyle(dark ? "-fx-text-fill:#e8f1f8;" : "-fx-text-fill:#0f141a;"); if (chatTitle != null) chatTitle.setStyle(dark ? "-fx-text-fill:#e8f1f8;" : "-fx-text-fill:#0f141a;");
if (chatStatus != null) chatStatus.setStyle(dark ? "-fx-text-fill:#8ea1b2;" : "-fx-text-fill:#7e8a97;"); if (chatStatus != null) chatStatus.setStyle(dark ? "-fx-text-fill:#8ea1b2;" : "-fx-text-fill:#7e8a97;");
// 👇 این خط قبلاً ممکن بود NPE بده // === Context menu icons ===
if (archiveItem != null && archiveItem.getGraphic() instanceof ImageView iv) {
iv.setImage(loadIcon("archived_chats" + suffix));
}
if (viewProfileItem != null && viewProfileItem.getGraphic() instanceof ImageView iv) { if (viewProfileItem != null && viewProfileItem.getGraphic() instanceof ImageView iv) {
iv.setImage(loadIcon("view_profile" + suffix)); iv.setImage(loadIcon("view_profile" + suffix));
} }
if (deleteChatItem != null && deleteChatItem.getGraphic() instanceof ImageView iv) {
iv.setImage(loadIcon("delete_red.png")); // stays red in both themes
}
} }
// ChatPageController // ChatPageController
@@ -2996,7 +3020,4 @@ public class ChatPageController {
} }
} }
} }
@@ -30,8 +30,8 @@ public class UserInfoController {
@FXML private HBox usernameBlock; @FXML private HBox usernameBlock;
@FXML private Label userId; @FXML private Label userId;
@FXML private Button moreButton; @FXML private Button infoMoreButton;
@FXML private ContextMenu moreMenu; @FXML private ContextMenu infoMoreMenu;
@FXML private MenuItem deleteChatItem; @FXML private MenuItem deleteChatItem;
@FXML private MenuItem blockItem; @FXML private MenuItem blockItem;
@FXML private MenuItem unblockItem; @FXML private MenuItem unblockItem;
@@ -51,21 +51,21 @@ public class UserInfoController {
MainController.getInstance().closeOverlay(profileCard.getParent())); MainController.getInstance().closeOverlay(profileCard.getParent()));
// Show menu manually // Show menu manually
moreButton.setOnAction(e -> { infoMoreButton.setOnAction(e -> {
if (moreMenu != null) { if (infoMoreMenu != null) {
moreMenu.show(moreButton, javafx.geometry.Side.BOTTOM, 0, 0); infoMoreMenu.show(infoMoreButton, javafx.geometry.Side.BOTTOM, 0, 0);
} }
}); });
// Hide menu when clicking outside // Hide menu when clicking outside
Platform.runLater(() -> { Platform.runLater(() -> {
if (moreButton.getScene() != null) { if (infoMoreButton.getScene() != null) {
moreButton.getScene().addEventFilter( infoMoreButton.getScene().addEventFilter(
javafx.scene.input.MouseEvent.MOUSE_PRESSED, ev -> { javafx.scene.input.MouseEvent.MOUSE_PRESSED, ev -> {
if (moreMenu.isShowing() if (infoMoreMenu.isShowing()
&& !moreButton.localToScreen(moreButton.getBoundsInLocal()) && !infoMoreButton.localToScreen(infoMoreButton.getBoundsInLocal())
.contains(ev.getScreenX(), ev.getScreenY())) { .contains(ev.getScreenX(), ev.getScreenY())) {
moreMenu.hide(); infoMoreMenu.hide();
} }
} }
); );
@@ -197,7 +197,7 @@ public class UserInfoController {
moreIcon.setImage(loadImage(ICON_PATH + "more" + suffix)); moreIcon.setImage(loadImage(ICON_PATH + "more" + suffix));
bioIcon.setImage(loadImage(ICON_PATH + "bio" + suffix)); bioIcon.setImage(loadImage(ICON_PATH + "bio" + suffix));
usernameIcon.setImage(loadImage(ICON_PATH + "user_id" + suffix)); usernameIcon.setImage(loadImage(ICON_PATH + "username" + suffix));
} }
// --- helpers ------------------------------------------------------------- // --- helpers -------------------------------------------------------------
@@ -41,19 +41,27 @@
</Button> </Button>
<!-- More / overflow --> <!-- More / overflow -->
<Button fx:id="moreButton" styleClass="icon-btn"> <Button fx:id="chatMoreButton" styleClass="icon-btn">
<graphic> <graphic>
<ImageView fx:id="moreIcon" fitWidth="18" fitHeight="18" preserveRatio="true"> <ImageView fx:id="moreIcon" fitWidth="18" fitHeight="18" preserveRatio="true">
<image><Image url="@/org/to/telegramfinalproject/Icons/more_light.png"/></image> <image><Image url="@/org/to/telegramfinalproject/Icons/more_light.png"/></image>
</ImageView> </ImageView>
</graphic> </graphic>
<contextMenu> <contextMenu>
<ContextMenu fx:id="moreMenu"> <ContextMenu fx:id="chatMoreMenu">
<items> <items>
<MenuItem fx:id="archiveItem" text="Archive chat">
<graphic>
<ImageView fitWidth="16" fitHeight="16" preserveRatio="true">
<image><Image url="@/org/to/telegramfinalproject/Icons/archived_chats_dark.png"/>
</image>
</ImageView>
</graphic>
</MenuItem>
<MenuItem fx:id="viewProfileItem" text="View profile"> <MenuItem fx:id="viewProfileItem" text="View profile">
<graphic> <graphic>
<ImageView fitWidth="16" fitHeight="16" preserveRatio="true"> <ImageView fitWidth="16" fitHeight="16" preserveRatio="true">
<image><Image url="@/org/to/telegramfinalproject/Icons/view_profile_light.png"/></image> <image><Image url="@/org/to/telegramfinalproject/Icons/view_profile_dark.png"/></image>
</ImageView> </ImageView>
</graphic> </graphic>
</MenuItem> </MenuItem>
@@ -24,7 +24,7 @@
<Pane HBox.hgrow="ALWAYS"/> <!-- pushes buttons to right --> <Pane HBox.hgrow="ALWAYS"/> <!-- pushes buttons to right -->
<!-- More / overflow --> <!-- More / overflow -->
<Button fx:id="moreButton" styleClass="icon-button"> <Button fx:id="infoMoreButton" styleClass="icon-button">
<graphic> <graphic>
<ImageView fx:id="moreIcon" fitWidth="18" fitHeight="18" preserveRatio="true"> <ImageView fx:id="moreIcon" fitWidth="18" fitHeight="18" preserveRatio="true">
<image> <image>
@@ -33,7 +33,7 @@
</ImageView> </ImageView>
</graphic> </graphic>
<contextMenu> <contextMenu>
<ContextMenu fx:id="moreMenu"> <ContextMenu fx:id="infoMoreMenu">
<items> <items>
<MenuItem fx:id="deleteChatItem" text="Delete chat" style="-fx-text-fill: red;"> <MenuItem fx:id="deleteChatItem" text="Delete chat" style="-fx-text-fill: red;">
<graphic> <graphic>
@@ -113,7 +113,7 @@
<ImageView fx:id="usernameIcon" fitWidth="16" fitHeight="16" preserveRatio="true" <ImageView fx:id="usernameIcon" fitWidth="16" fitHeight="16" preserveRatio="true"
styleClass="info-icon"> styleClass="info-icon">
<image> <image>
<Image url="@/org/to/telegramfinalproject/Icons/user_id_dark.png"/> <Image url="@/org/to/telegramfinalproject/Icons/username_dark.png"/>
</image> </image>
</ImageView> </ImageView>