diff --git a/src/main/java/org/to/telegramfinalproject/UI/ChatItemController.java b/src/main/java/org/to/telegramfinalproject/UI/ChatItemController.java
new file mode 100644
index 0000000..e1e4d84
--- /dev/null
+++ b/src/main/java/org/to/telegramfinalproject/UI/ChatItemController.java
@@ -0,0 +1,26 @@
+package org.to.telegramfinalproject.UI;
+
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+import javafx.scene.image.ImageView;
+
+import java.io.IOException;
+
+public class ChatItemController {
+
+ @FXML private ImageView profileImage;
+ @FXML private Label chatName;
+ @FXML private Label lastMessage;
+ @FXML private Label chatTime;
+ @FXML private Label unreadCount;
+
+ public void setChatData(String name, String lastMsg, String time, int unread) {
+ chatName.setText(name);
+ lastMessage.setText(lastMsg);
+ chatTime.setText(time);
+ unreadCount.setVisible(unread > 0);
+ unreadCount.setText(String.valueOf(unread));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/to/telegramfinalproject/UI/MainController.java b/src/main/java/org/to/telegramfinalproject/UI/MainController.java
new file mode 100644
index 0000000..d886977
--- /dev/null
+++ b/src/main/java/org/to/telegramfinalproject/UI/MainController.java
@@ -0,0 +1,211 @@
+package org.to.telegramfinalproject.UI;
+
+import javafx.animation.TranslateTransition;
+import javafx.application.Platform;
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.control.Button;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.control.SplitPane;
+import javafx.scene.control.TextField;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.Pane;
+import javafx.scene.layout.StackPane;
+import javafx.scene.layout.VBox;
+import javafx.util.Duration;
+
+import java.io.IOException;
+
+public class MainController {
+
+ @FXML private StackPane mainRoot;
+ @FXML private VBox chatListContainer;
+ @FXML private StackPane chatDisplayArea;
+ @FXML private Pane overlay;
+ @FXML private ImageView menuIcon;
+ @FXML private ScrollPane scrollPane;
+ @FXML private SplitPane mainSplitPane;
+ @FXML private VBox leftPane;
+ @FXML private Button menuButton;
+ @FXML private TextField searchBar;
+
+ private Node sidebarRoot;
+ private boolean isSidebarOpen = false;
+
+ // Add ThemeManager handle
+ private final ThemeManager themeManager = ThemeManager.getInstance();
+
+ @FXML
+ public void initialize() {
+ addSampleChats();
+
+ // Register the scene for automatic CSS updates
+ Platform.runLater(() -> {
+ ThemeManager.getInstance().registerScene(mainRoot.getScene());
+ });
+
+ // Listen for theme changes to update icons & labels manually
+ ThemeManager.getInstance().darkModeProperty().addListener((obs, oldVal, newVal) -> {
+ if (newVal) {
+ // Dark mode ON
+ updateIconsForDarkMode();
+ updateLabelsForDarkMode();
+ } else {
+ // Light mode ON
+ updateIconsForLightMode();
+ updateLabelsForLightMode();
+ }
+ });
+
+ // Smooth scroll feel
+ scrollPane.getStylesheets().add(getClass().getResource("/org/to/telegramfinalproject/CSS/scrollpane.css").toExternalForm());
+ scrollPane.setPannable(true);
+ scrollPane.setFitToWidth(true);
+ scrollPane.setFitToHeight(false);
+ scrollPane.getContent().setOnScroll(event -> {
+ double deltaY = event.getDeltaY() * 0.003; // smaller = smoother
+ scrollPane.setVvalue(scrollPane.getVvalue() - deltaY);
+ });
+
+ // ---------- SplitPane limits so panes can't fully collapse ----------
+ leftPane.setMinWidth(72); // avatars-only collapse
+ chatDisplayArea.setMinWidth(360); // chat area never fully collapses
+
+ mainSplitPane.widthProperty().addListener((o, ov, nv) -> clampDivider());
+ if (!mainSplitPane.getDividers().isEmpty()) {
+ mainSplitPane.getDividers().get(0).positionProperty().addListener((o, ov, nv) -> clampDivider());
+ }
+ }
+
+ 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 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(String chatName) {
+ chatDisplayArea.getChildren().clear();
+ chatDisplayArea.getChildren().add(new javafx.scene.control.Label("Chat with " + chatName));
+ }
+
+ @FXML
+ private void toggleSidebar() {
+ if (isSidebarOpen) {
+ closeSidebar();
+ } else {
+ openSidebar();
+ }
+ }
+
+ @FXML
+ private void openSidebar() {
+ try {
+ if (sidebarRoot == null) {
+ sidebarRoot = FXMLLoader.load(getClass().getResource("/org/to/telegramfinalproject/Fxml/Sidebar_menu.fxml"));
+ StackPane.setAlignment(sidebarRoot, Pos.CENTER_LEFT);
+ sidebarRoot.setTranslateX(-getSidebarWidth());
+ mainRoot.getChildren().add(sidebarRoot);
+ }
+
+ TranslateTransition slideIn = new TranslateTransition(Duration.millis(250), sidebarRoot);
+ slideIn.setToX(0);
+ slideIn.play();
+
+ overlay.setVisible(true);
+ overlay.setMouseTransparent(false);
+
+ isSidebarOpen = true;
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ private void closeSidebar() {
+ if (sidebarRoot != null && isSidebarOpen) {
+ TranslateTransition slideOut = new TranslateTransition(Duration.millis(250), sidebarRoot);
+ slideOut.setToX(-getSidebarWidth());
+ slideOut.setOnFinished(e -> {
+ overlay.setVisible(false);
+ overlay.setMouseTransparent(true);
+ isSidebarOpen = false;
+ });
+ slideOut.play();
+ }
+ }
+
+ private double getSidebarWidth() {
+ return 250; // Sidebar width in px
+ }
+
+ private void clampDivider() {
+ if (mainSplitPane.getDividers().isEmpty()) return;
+
+ double totalW = mainSplitPane.getWidth();
+ if (totalW <= 0) return;
+
+ double leftMinRatio = leftPane.getMinWidth() / totalW;
+ double rightMinRatio = chatDisplayArea.getMinWidth() / totalW;
+ double maxLeftRatio = 1.0 - rightMinRatio;
+
+ SplitPane.Divider d = mainSplitPane.getDividers().get(0);
+ double p = d.getPosition();
+ if (p < leftMinRatio) {
+ d.setPosition(leftMinRatio);
+ } else if (p > maxLeftRatio) {
+ d.setPosition(maxLeftRatio);
+ }
+ }
+
+ private void updateIconsForDarkMode() {
+ // Example: switch images to white versions
+ menuIcon.setImage(new Image(getClass().getResourceAsStream("/org/to/telegramfinalproject/Icons/menu_light.png")));
+ }
+
+ private void updateIconsForLightMode() {
+ // Example: switch images to black versions
+ menuIcon.setImage(new Image(getClass().getResourceAsStream("/org/to/telegramfinalproject/Icons/menu_dark.png")));
+ }
+
+ private void updateLabelsForDarkMode() {
+ //myLabel.setStyle("-fx-text-fill: white;");
+ }
+
+ private void updateLabelsForLightMode() {
+ //myLabel.setStyle("-fx-text-fill: black;");
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/to/telegramfinalproject/UI/SidebarMenuController.java b/src/main/java/org/to/telegramfinalproject/UI/SidebarMenuController.java
index e5c709b..2f8167f 100644
--- a/src/main/java/org/to/telegramfinalproject/UI/SidebarMenuController.java
+++ b/src/main/java/org/to/telegramfinalproject/UI/SidebarMenuController.java
@@ -42,7 +42,7 @@ public class SidebarMenuController {
@FXML
public void initialize() {
- // Load default profile image (if present)
+ // Load default profile image
Image profile = loadImage("/org/to/telegramfinalproject/Images/profile.png");
if (profile != null) profileImage.setImage(profile);
@@ -55,8 +55,7 @@ public class SidebarMenuController {
// 1) Register with ThemeManager so this scene auto-updates on theme changes
themeManager.registerScene(newScene);
- // 2) Make sure we start in LIGHT mode (if that's what you want)
- // (If you already set the initial mode elsewhere, remove the next line)
+ // 2) Make sure we start in LIGHT mode
themeManager.setDarkMode(false);
// 3) Sync icons & toggle with current mode
@@ -93,6 +92,7 @@ public class SidebarMenuController {
// Update the global theme via ThemeManager
themeManager.setDarkMode(newDark);
+ themeManager.applyThemeToAll();
// Animate the thumb to its new position (listener will handle icons & final position sync)
syncToggleVisual(newDark, /*animate=*/true);
diff --git a/src/main/java/org/to/telegramfinalproject/UI/TelegramApplication.java b/src/main/java/org/to/telegramfinalproject/UI/TelegramApplication.java
index 204683a..1dfc7dc 100644
--- a/src/main/java/org/to/telegramfinalproject/UI/TelegramApplication.java
+++ b/src/main/java/org/to/telegramfinalproject/UI/TelegramApplication.java
@@ -11,7 +11,7 @@ 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/sidebar_menu.fxml"));
+ 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());
diff --git a/src/main/java/org/to/telegramfinalproject/UI/ThemeManager.java b/src/main/java/org/to/telegramfinalproject/UI/ThemeManager.java
index c58066c..43b6425 100644
--- a/src/main/java/org/to/telegramfinalproject/UI/ThemeManager.java
+++ b/src/main/java/org/to/telegramfinalproject/UI/ThemeManager.java
@@ -41,7 +41,7 @@ public class ThemeManager {
}
}
- private void applyThemeToAll() {
+ public void applyThemeToAll() {
for (Scene scene : registeredScenes) {
applyTheme(scene);
}
diff --git a/src/main/resources/org/to/telegramfinalproject/CSS/dark_theme.css b/src/main/resources/org/to/telegramfinalproject/CSS/dark_theme.css
index 0b92773..11742c5 100644
--- a/src/main/resources/org/to/telegramfinalproject/CSS/dark_theme.css
+++ b/src/main/resources/org/to/telegramfinalproject/CSS/dark_theme.css
@@ -50,3 +50,11 @@
.button, .label {
-fx-text-fill: white;
}
+
+/* Thin Telegram-like SplitPane divider (dark) */
+.split-pane:horizontal > .split-pane-divider {
+ -fx-background-color: transparent; /* no big solid block */
+ -fx-border-color: #cccccc; /* the visible thin line */
+ -fx-border-width: 0 1px 0 1px; /* 1px vertical line */
+ -fx-padding: 0 0 0 0.5px; /* big invisible hitbox for the mouse */
+}
diff --git a/src/main/resources/org/to/telegramfinalproject/CSS/light_theme.css b/src/main/resources/org/to/telegramfinalproject/CSS/light_theme.css
index 7ef5c23..3f6ffd0 100644
--- a/src/main/resources/org/to/telegramfinalproject/CSS/light_theme.css
+++ b/src/main/resources/org/to/telegramfinalproject/CSS/light_theme.css
@@ -50,3 +50,11 @@
.button, .label {
-fx-text-fill: black;
}
+
+/* Thin Telegram-like SplitPane divider (light) */
+.split-pane:horizontal > .split-pane-divider {
+ -fx-background-color: transparent; /* no big solid block */
+ -fx-border-color: #cccccc; /* the visible thin line */
+ -fx-border-width: 0 1px 0 1px; /* 1px vertical line */
+ -fx-padding: 0 0 0 0.5px; /* big invisible hitbox for the mouse */
+}
diff --git a/src/main/resources/org/to/telegramfinalproject/CSS/scrollpane.css b/src/main/resources/org/to/telegramfinalproject/CSS/scrollpane.css
new file mode 100644
index 0000000..b6f1ffe
--- /dev/null
+++ b/src/main/resources/org/to/telegramfinalproject/CSS/scrollpane.css
@@ -0,0 +1,22 @@
+.scroll-pane > .viewport {
+ -fx-background-color: transparent; /* No background behind content */
+}
+
+.scroll-pane .scroll-bar {
+ -fx-background-color: transparent; /* Remove background bar */
+ -fx-opacity: 0; /* Initially hidden */
+ -fx-padding: 0;
+ -fx-pref-width: 6px; /* Thinner scrollbar */
+ -fx-background-insets: 0;
+ -fx-background-radius: 3px;
+ -fx-transition: opacity 0.3s ease;
+}
+
+.scroll-pane:hover .scroll-bar {
+ -fx-opacity: 0.6; /* Show on hover */
+}
+
+.scroll-pane .thumb {
+ -fx-background-color: rgba(100, 100, 100, 0.5); /* Semi-transparent thumb */
+ -fx-background-radius: 3px;
+}
diff --git a/src/main/resources/org/to/telegramfinalproject/Fxml/chat_item.fxml b/src/main/resources/org/to/telegramfinalproject/Fxml/chat_item.fxml
new file mode 100644
index 0000000..2d94145
--- /dev/null
+++ b/src/main/resources/org/to/telegramfinalproject/Fxml/chat_item.fxml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/org/to/telegramfinalproject/Fxml/main.fxml b/src/main/resources/org/to/telegramfinalproject/Fxml/main.fxml
new file mode 100644
index 0000000..06c0b0c
--- /dev/null
+++ b/src/main/resources/org/to/telegramfinalproject/Fxml/main.fxml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/org/to/telegramfinalproject/Fxml/sidebar_menu.fxml b/src/main/resources/org/to/telegramfinalproject/Fxml/sidebar_menu.fxml
index 41153a8..de39bf4 100644
--- a/src/main/resources/org/to/telegramfinalproject/Fxml/sidebar_menu.fxml
+++ b/src/main/resources/org/to/telegramfinalproject/Fxml/sidebar_menu.fxml
@@ -6,56 +6,71 @@
-
+
+
-
-
-
+
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
-
+
diff --git a/src/main/resources/org/to/telegramfinalproject/Icons/archived_chats_dark.png b/src/main/resources/org/to/telegramfinalproject/Icons/archived_chats_dark.png
new file mode 100644
index 0000000..5e3d1db
Binary files /dev/null and b/src/main/resources/org/to/telegramfinalproject/Icons/archived_chats_dark.png differ
diff --git a/src/main/resources/org/to/telegramfinalproject/Icons/archived_chats_light.png b/src/main/resources/org/to/telegramfinalproject/Icons/archived_chats_light.png
new file mode 100644
index 0000000..6a03fc9
Binary files /dev/null and b/src/main/resources/org/to/telegramfinalproject/Icons/archived_chats_light.png differ
diff --git a/src/main/resources/org/to/telegramfinalproject/Icons/menu_dark.png b/src/main/resources/org/to/telegramfinalproject/Icons/menu_dark.png
new file mode 100644
index 0000000..2a3e6d7
Binary files /dev/null and b/src/main/resources/org/to/telegramfinalproject/Icons/menu_dark.png differ
diff --git a/src/main/resources/org/to/telegramfinalproject/Icons/menu_light.png b/src/main/resources/org/to/telegramfinalproject/Icons/menu_light.png
new file mode 100644
index 0000000..c40e78b
Binary files /dev/null and b/src/main/resources/org/to/telegramfinalproject/Icons/menu_light.png differ