Connect backend to UI

This commit is contained in:
2025-08-27 23:22:07 +03:30
parent 221f093324
commit ff6f771e5c
15 changed files with 1044 additions and 318 deletions
@@ -0,0 +1,37 @@
// org.to.telegramfinalproject.UI.AppRouter
package org.to.telegramfinalproject.UI;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public final class AppRouter {
private static Stage stage;
private static Scene scene;
private AppRouter() {}
public static void init(Stage st, Scene sc) {
stage = st;
scene = sc;
}
public static void showIntro() { setRoot("/org/to/telegramfinalproject/Fxml/intro.fxml"); }
public static void showLogin() { setRoot("/org/to/telegramfinalproject/Fxml/login_view.fxml"); }
public static void showRegister(){ setRoot("/org/to/telegramfinalproject/Fxml/register_view.fxml"); }
public static void showMain() { setRoot("/org/to/telegramfinalproject/Fxml/main.fxml"); }
private static void setRoot(String fxmlPath) {
try {
System.out.println("Router: setRoot -> " + fxmlPath);
FXMLLoader fx = new FXMLLoader(AppRouter.class.getResource(fxmlPath));
Parent root = fx.load();
if (scene != null) scene.setRoot(root);
else if (stage != null) stage.setScene(new Scene(root, 1480, 820));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -23,4 +23,11 @@ public class ChatItemController {
unreadCount.setVisible(unread > 0);
unreadCount.setText(String.valueOf(unread));
}
public void setUnread(int unread) {
boolean show = unread > 0;
unreadCount.setVisible(show);
unreadCount.setManaged(show);
if (show) unreadCount.setText(String.valueOf(unread));
}
}
@@ -10,38 +10,62 @@ import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Circle;
import javafx.stage.FileChooser;
import org.json.JSONArray;
import org.json.JSONObject;
import org.to.telegramfinalproject.Client.ActionHandler;
import org.to.telegramfinalproject.Models.ChatEntry;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.File;
import java.util.UUID;
public class ChatPageController {
// ===== messages area =====
@FXML private VBox messageContainer;
@FXML private ScrollPane messageScrollPane;
@FXML
private VBox messageContainer;
@FXML
private ScrollPane messageScrollPane;
// ===== input area =====
@FXML private TextArea messageInput;
@FXML private Button sendButton;
@FXML
private TextArea messageInput;
@FXML
private Button sendButton;
@FXML private Button attachmentButton;
@FXML private ImageView attachmentIcon; // <ImageView> inside the attachment button
@FXML
private Button attachmentButton;
@FXML
private ImageView attachmentIcon; // <ImageView> inside the attachment button
// ===== header =====
@FXML private ImageView userAvatar; // 36x36 in the FXML
@FXML private Label chatTitle; // contact/group title
@FXML private Label chatStatus; // last seen / online
@FXML
private ImageView userAvatar; // 36x36 in the FXML
@FXML
private Label chatTitle; // contact/group title
@FXML
private Label chatStatus; // last seen / online
@FXML private Button searchInChatButton; // magnifier button
@FXML private ImageView searchIcon;
@FXML
private Button searchInChatButton; // magnifier button
@FXML
private ImageView searchIcon;
@FXML private Button moreButton; // 3-dots button
@FXML private ImageView moreIcon;
@FXML private ContextMenu moreMenu;
@FXML private MenuItem viewProfileItem;
@FXML private MenuItem deleteChatItem;
@FXML
private Button moreButton; // 3-dots button
@FXML
private ImageView moreIcon;
@FXML
private ContextMenu moreMenu;
@FXML
private MenuItem viewProfileItem;
@FXML
private MenuItem deleteChatItem;
// ===== send icon =====
@FXML private ImageView sendIcon;
@FXML
private ImageView sendIcon;
// ===== state =====
private String chatName;
@@ -49,9 +73,26 @@ public class ChatPageController {
// Where your icons live
private static final String ICON_BASE = "/org/to/telegramfinalproject/Icons/";
private ChatEntry currentChat;
private UUID me;
private void initCurrentUserId() {
try {
// از سشنی که سمت کلاینت داری:
String meStr = org.to.telegramfinalproject.Client.Session
.currentUser.getString("internal_uuid");
me = UUID.fromString(meStr);
} catch (Exception ignore) {
me = null; // اگر به هر دلیلی نبود، خروجی‌ها رو ورودی فرض نکن
}
}
@FXML
public void initialize() {
initCurrentUserId();
// Send button
if (sendButton != null) {
sendButton.setOnAction(e -> sendMessage());
@@ -162,7 +203,9 @@ public class ChatPageController {
MainController.getInstance().showSearchPanel();
}
/** Called by main controller when opening a chat. */
/**
* Called by main controller when opening a chat.
*/
public void setChat(String chatName, String avatarPath) {
this.chatName = chatName;
@@ -210,14 +253,16 @@ public class ChatPageController {
// ----- UI helpers -----
/** Add a normal message bubble (very simple for now). */
/**
* Add a normal message bubble (very simple for now).
*/
public void addMessage(String sender, String content) {
Label msg = new Label(sender + ": " + content);
msg.setWrapText(true);
boolean dark = themeManager.isDarkMode();
String bubbleColor = dark ? "#20405a" : "#4fa8f0";
String textColor = dark ? "#e8f1f8" : "#0f141a";
String textColor = dark ? "#e8f1f8" : "#0f141a";
msg.setStyle(
"-fx-background-color: " + bubbleColor + ";" +
"-fx-text-fill: " + textColor + ";" +
@@ -235,7 +280,9 @@ public class ChatPageController {
messageScrollPane.setVvalue(1.0);
}
/** Update all header/footer icons according to current theme. */
/**
* Update all header/footer icons according to current theme.
*/
private void syncIconsWithTheme() {
boolean dark = themeManager.isDarkMode();
// We use “_light” icons on dark backgrounds, and “_dark” on light backgrounds.
@@ -274,4 +321,153 @@ public class ChatPageController {
}
return new Image(url.toExternalForm());
}
public void showChat(ChatEntry entry) {
this.currentChat = entry;
// Header
chatTitle.setText(entry.getName());
chatStatus.setText(""); // اگر last seen داری اینجا بگذار
if (entry.getImageUrl() != null && !entry.getImageUrl().isEmpty()) {
try {
userAvatar.setImage(new Image(entry.getImageUrl())); // یا لود از ریسورس خودت
userAvatar.setClip(new Circle(18, 18, 18));
} catch (Exception ignored) {
}
}
messageContainer.getChildren().clear();
loadMessages(entry);
// مارک به‌عنوان خوانده
markAsRead(entry);
// فوکوس روی ورودی
Platform.runLater(() -> messageInput.requestFocus());
}
private void loadMessages(ChatEntry entry) {
JSONObject req = new JSONObject();
req.put("action", "get_messages");
req.put("receiver_id", String.valueOf(entry.getId()));
req.put("receiver_type", entry.getType());
req.put("limit", 50);
new Thread(() -> {
JSONObject resp;
try {
resp = org.to.telegramfinalproject.Client.ActionHandler.sendWithResponse(req);
} catch (Exception ex) {
ex.printStackTrace();
return;
}
if (resp == null) return;
// بدون opt* :
String status = "";
try {
status = resp.getString("status");
} catch (Exception ignore) {
}
if (!"success".equals(status)) return;
JSONObject data = null;
try {
data = resp.getJSONObject("data");
} catch (Exception ignore) {
}
if (data == null) return;
JSONArray arr = null;
try {
arr = data.getJSONArray("messages");
} catch (Exception ignore) {
}
if (arr == null) return;
JSONArray finalArr = arr;
Platform.runLater(() -> renderMessages(finalArr));
}).start();
}
private void renderMessages(JSONArray arr) {
messageContainer.getChildren().clear();
for (int i = 0; i < arr.length(); i++) {
JSONObject m = arr.getJSONObject(i);
String senderId = m.optString("sender_id", "");
String type = m.optString("message_type", "TEXT");
String content = m.optString("content", "");
boolean outgoing = false;
if (me != null && senderId != null && !senderId.isEmpty()) {
try {
outgoing = me.equals(UUID.fromString(senderId));
} catch (Exception ignore) {
}
}
String text;
switch (type.toUpperCase()) {
case "TEXT":
text = content;
break;
case "IMAGE":
text = "[Image]";
break;
case "AUDIO":
text = "[Audio]";
break;
case "VIDEO":
text = "[Video]";
break;
case "FILE":
text = "[File]";
break;
default:
text = "[Message]";
}
addBubble(outgoing, text);
}
messageScrollPane.layout();
messageScrollPane.setVvalue(1.0);
}
private void markAsRead(ChatEntry entry) {
JSONObject readReq = new JSONObject();
readReq.put("action", "mark_as_read");
readReq.put("receiver_id", entry.getId().toString()); // ⛳️ internal_id
readReq.put("receiver_type", entry.getType());
ActionHandler.sendWithResponse(readReq);
}
private void addBubble(boolean outgoing, String content) {
Label msg = new Label(content);
msg.setWrapText(true);
boolean dark = themeManager.isDarkMode();
String mine = dark ? "#2b7cff" : "#d8ecff";
String theirs = dark ? "#2c333a" : "#ffffff";
String bg = outgoing ? mine : theirs;
msg.setStyle(
"-fx-background-color:" + bg + ";" +
"-fx-padding:8 12;" +
"-fx-background-radius:12;" +
"-fx-max-width: 520;"
);
msg.setMinHeight(Region.USE_PREF_SIZE);
javafx.scene.layout.HBox row = new javafx.scene.layout.HBox(msg);
row.setFillHeight(true);
row.setSpacing(6);
row.setAlignment(outgoing
? javafx.geometry.Pos.CENTER_RIGHT
: javafx.geometry.Pos.CENTER_LEFT);
messageContainer.getChildren().add(row);
}
}
@@ -118,25 +118,34 @@ public class IntroController {
slider.setDaemon(true);
slider.start();
}
//
// @FXML
// private void handleStartMessaging(ActionEvent event) {
// try {
// FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/login_view.fxml"));
// Scene loginScene = new Scene(loader.load());
//
// // Get the current stage and its dimensions
// Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
// double currentWidth = stage.getWidth();
// double currentHeight = stage.getHeight();
//
// // Set the new scene and apply the previous size
// stage.setScene(loginScene);
// stage.setWidth(currentWidth);
// stage.setHeight(currentHeight);
// stage.show();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
@FXML
private void handleStartMessaging(ActionEvent event) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/login_view.fxml"));
Scene loginScene = new Scene(loader.load());
// Get the current stage and its dimensions
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
double currentWidth = stage.getWidth();
double currentHeight = stage.getHeight();
// Set the new scene and apply the previous size
stage.setScene(loginScene);
stage.setWidth(currentWidth);
stage.setHeight(currentHeight);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
AppRouter.showLogin(); // همون Scene می‌مونه، فقط Root عوض میشه
}
@FXML private void goRegister() { AppRouter.showRegister(); }
}
@@ -9,7 +9,10 @@ import javafx.scene.control.*;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.json.JSONObject;
import org.to.telegramfinalproject.Client.ActionHandler;
import org.to.telegramfinalproject.Client.ClientConnection;
import org.to.telegramfinalproject.Client.Session;
import org.to.telegramfinalproject.Client.TelegramClient;
import org.to.telegramfinalproject.Database.userDatabase;
import org.to.telegramfinalproject.Models.User;
import org.to.telegramfinalproject.Security.PasswordHashing;
@@ -23,7 +26,7 @@ public class LoginController {
@FXML private PasswordField passwordField;
@FXML private TextField visiblePasswordField;
@FXML private Button togglePasswordBtn;
@FXML private Button toggleVisibilityBtn;
@FXML private Label errorLabel;
private ClientConnection connection;
@@ -48,60 +51,119 @@ public class LoginController {
visiblePasswordField.setManaged(passwordVisible);
passwordField.setVisible(!passwordVisible);
passwordField.setManaged(!passwordVisible);
togglePasswordBtn.setText(passwordVisible ? "👁" : "👁");
toggleVisibilityBtn.setText(passwordVisible ? "👁" : "👁");
}
// @FXML
// private void handleLogin() {
// String username = usernameField.getText();
// String password = passwordField.getText();
//
// // 1. Check for empty fields
// if (username.isEmpty() || password.isEmpty()) {
// showError("Please fill in all required fields.");
// return;
// }
//
// // 2. Check if username exists
// userDatabase userDb = new userDatabase();
// if (!userDb.existsByUsername(username)) {
// showError("This username doesnt exist.");
// return;
// }
//
// // 3. Check if password is correct
// User user = userDb.findByUsername(username);
// if (!PasswordHashing.verify(password, user.getPassword())) {
// showError("Incorrect password.");
// return;
// }
//
// // 4. Attempt to send to server
// try {
// JSONObject request = new JSONObject();
// request.put("action", "login");
// request.put("user_id", JSONObject.NULL);
// request.put("username", username);
// request.put("password", password);
// request.put("profile_name", JSONObject.NULL);
//
// if (connection != null) {
// connection.send(request.toString());
// String responseStr = connection.receive();
// JSONObject response = new JSONObject(responseStr);
// System.out.println("Status: " + response.getString("status"));
// System.out.println("Message: " + response.getString("message"));
//
// // Simulate successful login (since main.fxml isnt ready)
// Alert alert = new Alert(Alert.AlertType.INFORMATION, "Login successful!");
// alert.show();
// }
//
// } catch (Exception ex) {
// showError("Unable to connect to server. Please try again later.");
// }
// }
// LoginController.java (متد اصلی)
@FXML
private void handleLogin() {
String username = usernameField.getText();
String password = passwordField.getText();
String u = usernameField.getText().trim();
String p = passwordField.getText();
if (u.isEmpty() || p.isEmpty()) { showError("Please fill in all required fields."); return; }
// 1. Check for empty fields
if (username.isEmpty() || password.isEmpty()) {
showError("Please fill in all required fields.");
return;
}
setUiBusy(true);
// 2. Check if username exists
userDatabase userDb = new userDatabase();
if (!userDb.existsByUsername(username)) {
showError("This username doesnt exist.");
return;
}
new Thread(() -> {
try {
var cli = org.to.telegramfinalproject.Client.TelegramClient.getOrInitForUI();
var handler = cli.getHandler();
// 3. Check if password is correct
User user = userDb.findByUsername(username);
if (!PasswordHashing.verify(password, user.getPassword())) {
showError("Incorrect password.");
return;
}
// بساز و بفرست — همون send خودت که Session رو پر می‌کند
// org.json.JSONObject req = new org.json.JSONObject()
// .put("action","login")
// .put("username", u)
// .put("password", p);
//
// handler.send(req); // ⬅️ بلاکینگ؛ پس درستش کردیم که تو Thread هست
// 4. Attempt to send to server
try {
JSONObject request = new JSONObject();
request.put("action", "login");
request.put("user_id", JSONObject.NULL);
request.put("username", username);
request.put("password", password);
request.put("profile_name", JSONObject.NULL);
if (connection != null) {
connection.send(request.toString());
String responseStr = connection.receive();
JSONObject response = new JSONObject(responseStr);
System.out.println("Status: " + response.getString("status"));
System.out.println("Message: " + response.getString("message"));
handler.login(u,p);
// Simulate successful login (since main.fxml isnt ready)
Alert alert = new Alert(Alert.AlertType.INFORMATION, "Login successful!");
alert.show();
javafx.application.Platform.runLater(() -> {
setUiBusy(false);
if (!handler.wasSuccess() || Session.currentUser == null) {
showError(handler.getLastMessage().isEmpty() ? "Login failed." : handler.getLastMessage());
return;
}
// موفق: Session از داخل send پر شده
goMain(); // بدون Alert → مستقیم به main.fxml
});
} catch (Exception ex) {
javafx.application.Platform.runLater(() -> {
setUiBusy(false);
showError("Connection error.");
});
}
} catch (Exception ex) {
showError("Unable to connect to server. Please try again later.");
}
}, "login-thread").start();
}
private void goMain() {
AppRouter.showMain();
}
private void setUiBusy(boolean b) {
usernameField.setDisable(b);
passwordField.setDisable(b);
}
@FXML
private void switchToRegister() throws IOException {
switchScene("register_view.fxml");
@@ -13,8 +13,15 @@ import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.util.Duration;
import org.to.telegramfinalproject.Models.ChatEntry;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class MainController {
@@ -57,10 +64,14 @@ public class MainController {
public static MainController getInstance() {
return instance;
}
private final Map<UUID, ChatItemController> itemControllers = new HashMap<>();
@FXML
public void initialize() {
addSampleChats();
// addSampleChats();
populateChatListFromSession();
// Register the scene for automatic CSS updates
Platform.runLater(() -> {
@@ -138,58 +149,155 @@ public class MainController {
scrollPane.setManaged(true);
}
private void addSampleChats() {
addChat("Archived Chats", "Your archived chats", "10:45", 0);
addChat("Saved Messages", "Keep messages for later", "Yesterday", 0);
addChat("Alice", "Hey, how are you?", "14:12", 3);
addChat("Bob", "Let's meet tomorrow", "12:08", 1);
addChat("Alice", "Hey, how are you?", "14:12", 3);
addChat("Bob", "Let's meet tomorrow", "12:08", 1);
addChat("Alice", "Hey, how are you?", "14:12", 3);
addChat("Bob", "Let's meet tomorrow", "12:08", 1);
addChat("Alice", "Hey, how are you?", "14:12", 3);
addChat("Bob", "Let's meet tomorrow", "12:08", 1);
addChat("Alice", "Hey, how are you?", "14:12", 3);
addChat("Bob", "Let's meet tomorrow", "12:08", 1);
addChat("Alice", "Hey, how are you?", "14:12", 3);
addChat("Bob", "Let's meet tomorrow", "12:08", 1);
addChat("Alice", "Hey, how are you?", "14:12", 3);
addChat("Bob", "Let's meet tomorrow", "12:08", 1);
addChat("Alice", "Hey, how are you?", "14:12", 3);
addChat("Bob", "Let's meet tomorrow", "12:08", 1);
// private void addSampleChats() {
// addChat("Archived Chats", "Your archived chats", "10:45", 0);
// addChat("Saved Messages", "Keep messages for later", "Yesterday", 0);
// addChat("Alice", "Hey, how are you?", "14:12", 3);
// addChat("Bob", "Let's meet tomorrow", "12:08", 1);
// addChat("Alice", "Hey, how are you?", "14:12", 3);
// addChat("Bob", "Let's meet tomorrow", "12:08", 1);
// addChat("Alice", "Hey, how are you?", "14:12", 3);
// addChat("Bob", "Let's meet tomorrow", "12:08", 1);
// addChat("Alice", "Hey, how are you?", "14:12", 3);
// addChat("Bob", "Let's meet tomorrow", "12:08", 1);
// addChat("Alice", "Hey, how are you?", "14:12", 3);
// addChat("Bob", "Let's meet tomorrow", "12:08", 1);
// addChat("Alice", "Hey, how are you?", "14:12", 3);
// addChat("Bob", "Let's meet tomorrow", "12:08", 1);
// addChat("Alice", "Hey, how are you?", "14:12", 3);
// addChat("Bob", "Let's meet tomorrow", "12:08", 1);
// addChat("Alice", "Hey, how are you?", "14:12", 3);
// addChat("Bob", "Let's meet tomorrow", "12:08", 1);
//
//
// }
private final DateTimeFormatter timeFmt = DateTimeFormatter.ofPattern("HH:mm");
private final DateTimeFormatter dayFmt = DateTimeFormatter.ofPattern("dd/MM"); // همون سال
private final DateTimeFormatter fullDateFmt= DateTimeFormatter.ofPattern("yyyy/MM/dd"); // سال متفاوت
private String formatListTimestamp(LocalDateTime ts) {
if (ts == null) return "";
LocalDate today = LocalDate.now();
LocalDate d = ts.toLocalDate();
if (d.isEqual(today)) {
// امروز → فقط ساعت
return timeFmt.format(ts);
}
// اگر همان سال است → تاریخ کوتاه + ساعت
if (d.getYear() == today.getYear()) {
return dayFmt.format(ts) + " " + timeFmt.format(ts); // مثال: 15/08 13:28
}
// سال متفاوت → تاریخ کامل + ساعت
return fullDateFmt.format(ts) + " " + timeFmt.format(ts); // مثال: 2024/12/31 21:10
}
private void addChat(String name, String lastMsg, String time, int unread) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_item.fxml"));
Node chatItem = loader.load();
ChatItemController controller = loader.getController();
controller.setChatData(name, lastMsg, time, unread);
chatItem.setOnMouseClicked(e -> openChat(name));
chatListContainer.getChildren().add(chatItem);
} catch (IOException e) {
e.printStackTrace();
private void populateChatListFromSession() {
chatListContainer.getChildren().clear();
var list = (org.to.telegramfinalproject.Client.Session.activeChats != null
&& !org.to.telegramfinalproject.Client.Session.activeChats.isEmpty())
? org.to.telegramfinalproject.Client.Session.activeChats
: org.to.telegramfinalproject.Client.Session.chatList;
if (list == null || list.isEmpty()) return;
for (ChatEntry c : list) {
addChatNode(c);
}
}
private void openChat(String chatName) {
// private void addChatNode(ChatEntry chat ) {
// try {
// FXMLLoader fx = new FXMLLoader(getClass().getResource(
// "/org/to/telegramfinalproject/Fxml/chat_item.fxml"));
// Node item = fx.load();
// ChatItemController cc = fx.getController();
//
// String lastPreview = "";
// String time = (chat.getLastMessageTime() != null)
// ? timeFmt.format(chat.getLastMessageTime()) : "";
//
// cc.setChatData(chat.getName(), lastPreview, time, 0);
//
// item.setOnMouseClicked(e -> openChat(String.valueOf(chat)));
// chatListContainer.getChildren().add(item);
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
private void addChatNode(ChatEntry chat) {
try {
FXMLLoader fx = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_item.fxml"));
Node item = fx.load();
ChatItemController cc = fx.getController();
String preview = chat.getLastMessagePreview() == null ? "" : chat.getLastMessagePreview();
String time = formatListTimestamp(chat.getLastMessageTime());
cc.setChatData(chat.getName(), preview, time, chat.getUnreadCount());
item.setOnMouseClicked(e -> openChat(chat));
chatListContainer.getChildren().add(item);
itemControllers.put(chat.getId(), cc);
} catch (Exception ex) {
ex.printStackTrace();
}
}
private String mapTypeToLabel(String t) {
switch (t.toUpperCase()) {
case "IMAGE": return "[Image]";
case "AUDIO": return "[Audio]";
case "VIDEO": return "[Video]";
case "FILE": return "[File]";
default: return "[Message]";
}
}
// private void addChat(String name, String lastMsg, String time, int unread) {
// try {
// FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_item.fxml"));
// Node chatItem = loader.load();
// ChatItemController controller = loader.getController();
// controller.setChatData(name, lastMsg, time, unread);
//
// chatItem.setOnMouseClicked(e -> openChat(name));
// chatListContainer.getChildren().add(chatItem);
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
private void openChat(ChatEntry chat) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_page.fxml"));
Node chatPage = loader.load();
ChatPageController controller = loader.getController();
controller.setChat("Alice", "/org/to/telegramfinalproject/Avatars/profile_test.png");
controller.showChat(chat); // ✅ متد جدید در ChatPageController
chatDisplayArea.getChildren().setAll(chatPage);
chatDisplayArea.getChildren().clear();
chatDisplayArea.getChildren().add(chatPage);
// اختیاری: صفر کردن badge و مارک‌کردن به‌عنوان خوانده در UI
ChatItemController item = itemControllers.get(chat.getId());
if (item != null) item.setUnread(0);
} catch (IOException e) {
e.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
@FXML
private void toggleSidebar() {
if (isSidebarOpen) {
@@ -3,6 +3,7 @@ package org.to.telegramfinalproject.UI;
import javafx.animation.TranslateTransition;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
@@ -12,12 +13,16 @@ import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.util.Duration;
import java.net.URL;
public class SidebarMenuController {
private static final String ICON_PATH = "/org/to/telegramfinalproject/Icons/";
@FXML private VBox sidebarRoot;
@FXML private ImageView profileImage;
@FXML private Label usernameLabel;
@@ -176,4 +181,8 @@ public class SidebarMenuController {
private void openSettings() { System.out.println("Opening Settings..."); }
private void openTelegramFeatures() { System.out.println("Opening Telegram Features..."); }
private void openTelegramQnA() { System.out.println("Opening Telegram Q&A..."); }
}
@@ -1,4 +1,36 @@
package org.to.telegramfinalproject.UI;
package org.to.telegramfinalproject.UI;//package org.to.telegramfinalproject.UI;
//
//
//import javafx.application.Application;
//import javafx.fxml.FXMLLoader;
//import javafx.scene.Scene;
//import javafx.scene.image.Image;
//import javafx.stage.Stage;
//
//import java.io.IOException;
//
//public class TelegramApplication extends Application {
// @Override
// public void start(Stage stage) throws IOException {
// FXMLLoader fxmlLoader = new FXMLLoader(TelegramApplication.class.getResource("/org/to/telegramfinalproject/Fxml/main.fxml"));
// Scene scene = new Scene(fxmlLoader.load(), 1480, 820);
//
// scene.getStylesheets().add(getClass().getResource("/org/to/telegramfinalproject/CSS/light_theme.css").toExternalForm());
//
// stage.setTitle("Telegram");
// stage.setScene(scene);
//
// // Add icon to the stage
// Image icon = new Image(TelegramApplication.class.getResourceAsStream("/org/to/telegramfinalproject/Images/telegram_icon.png"));
// stage.getIcons().add(icon);
//
// stage.show();
// }
// public static void main(String[] args) {
// launch();
// }
//
//}
import javafx.application.Application;
@@ -6,28 +38,31 @@ import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import org.to.telegramfinalproject.UI.AppRouter;
import java.io.IOException;
public class TelegramApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(TelegramApplication.class.getResource("/org/to/telegramfinalproject/Fxml/main.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 1480, 820);
// اول intro.fxml
FXMLLoader fx = new FXMLLoader(
TelegramApplication.class.getResource("/org/to/telegramfinalproject/Fxml/intro.fxml"));
Scene scene = new Scene(fx.load(), 1480, 820);
scene.getStylesheets().add(getClass().getResource("/org/to/telegramfinalproject/CSS/light_theme.css").toExternalForm());
scene.getStylesheets().add(
getClass().getResource("/org/to/telegramfinalproject/CSS/light_theme.css").toExternalForm()
);
stage.setTitle("Telegram");
stage.getIcons().add(new Image(
TelegramApplication.class.getResourceAsStream("/org/to/telegramfinalproject/Images/telegram_icon.png")
));
stage.setScene(scene);
// Add icon to the stage
Image icon = new Image(TelegramApplication.class.getResourceAsStream("/org/to/telegramfinalproject/Images/telegram_icon.png"));
stage.getIcons().add(icon);
stage.show();
}
public static void main(String[] args) {
launch();
AppRouter.init(stage, scene);
}
}
public static void main(String[] args) { launch(); }
}