Merge remote-tracking branch 'origin/Main-UI' into Main-UI
This commit is contained in:
@@ -29,6 +29,7 @@ public class AddMembersController {
|
||||
private final Set<Contact> selectedContacts = new HashSet<>();
|
||||
|
||||
private String groupName;
|
||||
private String groupId;
|
||||
private File groupImageFile;
|
||||
|
||||
// Sample data for testing
|
||||
@@ -239,8 +240,9 @@ public class AddMembersController {
|
||||
searchIcon.setGraphic(icon);
|
||||
}
|
||||
|
||||
public void setGroupInfo(String groupName, File groupImageFile) {
|
||||
public void setGroupInfo(String groupName, String groupId, File groupImageFile) {
|
||||
this.groupName = groupName;
|
||||
this.groupId = groupId;
|
||||
this.groupImageFile = groupImageFile;
|
||||
|
||||
// You can use these later when creating the group
|
||||
|
||||
@@ -29,6 +29,7 @@ public class AddSubscriberController {
|
||||
private final Set<Contact> selectedContacts = new HashSet<>();
|
||||
|
||||
private String channelName;
|
||||
private String channelId;
|
||||
private File channelImageFile;
|
||||
private String description;
|
||||
|
||||
@@ -201,8 +202,9 @@ public class AddSubscriberController {
|
||||
searchIcon.setGraphic(icon);
|
||||
}
|
||||
|
||||
public void setChannelInfo(String name, String description, File image) {
|
||||
public void setChannelInfo(String name, String id, String description, File image) {
|
||||
this.channelName = name;
|
||||
this.channelId = id;
|
||||
this.channelImageFile = image;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,10 @@ public class EditProfileController {
|
||||
overlayBackground.setOnMouseClicked(e -> closeEdit());
|
||||
|
||||
closeButton.setOnAction(e -> closeEdit());
|
||||
backButton.setOnAction(e -> goBackToProfile());
|
||||
|
||||
backButton.setOnAction(e -> {
|
||||
MainController.getInstance().goBack(overlayBackground);
|
||||
});
|
||||
|
||||
// Load your camera icon image (white camera icon for visibility)
|
||||
cameraIcon.setImage(new Image(
|
||||
@@ -101,38 +104,6 @@ public class EditProfileController {
|
||||
MainController.getInstance().closeOverlay(editCard.getParent());
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void goBackToProfile() {
|
||||
// Close edit overlay
|
||||
MainController.getInstance().closeOverlay(editCard.getParent());
|
||||
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource(
|
||||
"/org/to/telegramfinalproject/Fxml/my_profile.fxml"));
|
||||
Node profileOverlay = loader.load();
|
||||
|
||||
// Get the controller for the loaded MyProfile scene
|
||||
MyProfileController controller = loader.getController();
|
||||
|
||||
// Pass updated data from edit fields
|
||||
controller.setProfileData(
|
||||
nameField.getText(),
|
||||
"online",
|
||||
bioField.getText(),
|
||||
usernameField.getText(),
|
||||
profileImageView.getImage() != null ?
|
||||
profileImageView.getImage().getUrl() :
|
||||
"/org/to/telegramfinalproject/Avatars/default_profile.png"
|
||||
);
|
||||
|
||||
// Show updated MyProfile overlay
|
||||
MainController.getInstance().showOverlay(profileOverlay);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void setProfileData(String name, String status, String bio, String userId, Image profileImage) {
|
||||
profileStatus.setText(status);
|
||||
profileName.setText(name);
|
||||
|
||||
@@ -62,6 +62,9 @@ public class MainController {
|
||||
@FXML private ImageView menuIcon;
|
||||
private SidebarMenuController sidebarController; //save sidebar controller
|
||||
|
||||
// === Overlay ===
|
||||
@FXML private StackPane overlayLayer;
|
||||
|
||||
// === Time formatter for messages ===
|
||||
private static final java.time.format.DateTimeFormatter FMT_HHMM =
|
||||
java.time.format.DateTimeFormatter.ofPattern("HH:mm");
|
||||
@@ -84,6 +87,9 @@ public class MainController {
|
||||
public static MainController getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Keep track of the scene user comes from
|
||||
private final Deque<Node> navigationStack = new ArrayDeque<>();
|
||||
private final Map<UUID, ChatItemController> itemControllers = new HashMap<>();
|
||||
|
||||
|
||||
@@ -590,13 +596,30 @@ public class MainController {
|
||||
|
||||
// === Overlay Handling ===
|
||||
public void showOverlay(Node overlayNode) {
|
||||
mainRoot.getChildren().add(overlayNode);
|
||||
if (!overlayLayer.getChildren().isEmpty()) {
|
||||
Node current = overlayLayer.getChildren().get(overlayLayer.getChildren().size() - 1);
|
||||
navigationStack.push(current);
|
||||
overlayLayer.getChildren().remove(current);
|
||||
}
|
||||
overlayLayer.getChildren().add(overlayNode);
|
||||
}
|
||||
|
||||
public void closeOverlay(Node overlayNode) {
|
||||
mainRoot.getChildren().remove(overlayNode);
|
||||
overlayLayer.getChildren().remove(overlayNode);
|
||||
}
|
||||
|
||||
public void goBack(Pane currentOverlay) {
|
||||
// Remove the current overlay
|
||||
closeOverlay(currentOverlay);
|
||||
|
||||
if (!navigationStack.isEmpty()) {
|
||||
Node previous = navigationStack.pop();
|
||||
|
||||
// Clear existing overlays before showing previous
|
||||
overlayLayer.getChildren().clear();
|
||||
overlayLayer.getChildren().add(previous);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Search UI state =====
|
||||
private final java.util.List<SearchResult> searchBacking = new java.util.ArrayList<>();
|
||||
|
||||
@@ -30,6 +30,8 @@ public class NewChannelController {
|
||||
@FXML private Button createButton;
|
||||
@FXML private StackPane overlayRoot; // the root
|
||||
@FXML private Label descCounter;
|
||||
@FXML private Label channelIdLabel;
|
||||
@FXML private TextField channelIdField;
|
||||
|
||||
private File channelImageFile;
|
||||
|
||||
@@ -67,6 +69,7 @@ public class NewChannelController {
|
||||
// Create button → validate name + submit
|
||||
createButton.setOnAction(e -> {
|
||||
String channelName = channelNameField.getText().trim();
|
||||
String channelId = channelIdField.getText().trim();
|
||||
String description = channelDescField.getText().trim();
|
||||
|
||||
if (channelName.isEmpty()) {
|
||||
@@ -76,6 +79,13 @@ public class NewChannelController {
|
||||
return;
|
||||
}
|
||||
|
||||
if (channelId.isEmpty()) {
|
||||
// Apply error style
|
||||
channelIdField.getStyleClass().add("error");
|
||||
channelIdLabel.getStyleClass().add("error");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Load Add Members overlay
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource(
|
||||
@@ -84,7 +94,7 @@ public class NewChannelController {
|
||||
|
||||
// Pass channel info to AddMembersController
|
||||
AddSubscriberController controller = loader.getController();
|
||||
controller.setChannelInfo(channelName, description, channelImageFile);
|
||||
controller.setChannelInfo(channelName, channelId, description, channelImageFile);
|
||||
|
||||
// Close the current "New Channel" overlay
|
||||
MainController.getInstance().closeOverlay(overlayRoot);
|
||||
@@ -133,6 +143,14 @@ public class NewChannelController {
|
||||
}
|
||||
});
|
||||
|
||||
// Reset error state when typing
|
||||
channelIdField.textProperty().addListener((obs, oldVal, newVal) -> {
|
||||
if (!newVal.trim().isEmpty()) {
|
||||
channelIdField.getStyleClass().remove("error");
|
||||
channelIdLabel.getStyleClass().remove("error");
|
||||
}
|
||||
});
|
||||
|
||||
// Auto-focus channel name on open
|
||||
Platform.runLater(() -> channelNameField.requestFocus());
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ public class NewGroupController {
|
||||
@FXML private Button cancelButton;
|
||||
@FXML private Button nextButton;
|
||||
@FXML private StackPane overlayRoot; // the root
|
||||
@FXML private TextField groupIdField;
|
||||
@FXML private Label groupIdLabel;
|
||||
|
||||
private File groupImageFile;
|
||||
|
||||
@@ -58,6 +60,7 @@ public class NewGroupController {
|
||||
|
||||
nextButton.setOnAction(e -> {
|
||||
String groupName = groupNameField.getText().trim();
|
||||
String groupId = groupIdField.getText().trim();
|
||||
|
||||
if (groupName.isEmpty()) {
|
||||
// Apply error style
|
||||
@@ -67,6 +70,14 @@ public class NewGroupController {
|
||||
return;
|
||||
}
|
||||
|
||||
if (groupId.isEmpty()) {
|
||||
// Apply error style
|
||||
groupIdField.getStyleClass().add("error");
|
||||
groupIdLabel.getStyleClass().add("error");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource(
|
||||
"/org/to/telegramfinalproject/Fxml/add_member.fxml"));
|
||||
@@ -74,7 +85,7 @@ public class NewGroupController {
|
||||
|
||||
// Optional: pass groupName and image to AddMembersController
|
||||
AddMembersController controller = loader.getController();
|
||||
controller.setGroupInfo(groupName, groupImageFile);
|
||||
controller.setGroupInfo(groupName, groupId, groupImageFile);
|
||||
|
||||
// Close the current "New Group" overlay
|
||||
MainController.getInstance().closeOverlay(overlayRoot);
|
||||
@@ -87,6 +98,7 @@ public class NewGroupController {
|
||||
}
|
||||
});
|
||||
|
||||
// Reset error state when typing
|
||||
groupNameField.textProperty().addListener((obs, oldVal, newVal) -> {
|
||||
if (!newVal.trim().isEmpty()) {
|
||||
groupNameField.getStyleClass().remove("error");
|
||||
@@ -94,6 +106,14 @@ public class NewGroupController {
|
||||
}
|
||||
});
|
||||
|
||||
// Reset error state when typing
|
||||
groupIdField.textProperty().addListener((obs, oldVal, newVal) -> {
|
||||
if (!newVal.trim().isEmpty()) {
|
||||
groupIdField.getStyleClass().remove("error");
|
||||
groupIdLabel.getStyleClass().remove("error");
|
||||
}
|
||||
});
|
||||
|
||||
// Auto_focus search bar when overlay opens
|
||||
Platform.runLater(() -> groupNameField.requestFocus());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
package org.to.telegramfinalproject.UI;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.shape.Circle;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
public class SettingsController {
|
||||
|
||||
@FXML private VBox settingsCard;
|
||||
@FXML private ImageView profileImage;
|
||||
@FXML private Label profileName;
|
||||
@FXML private Label profileId;
|
||||
@FXML private MenuButton menuButton;
|
||||
@FXML private MenuItem editProfileItem;
|
||||
@FXML private MenuItem logoutItem;
|
||||
@FXML private Button myAccountButton;
|
||||
@FXML private Button privacyButton;
|
||||
@FXML private Button faqButton;
|
||||
@FXML private Button featuresButton;
|
||||
@FXML private Pane overlayBackground;
|
||||
@FXML private Button closeButton;
|
||||
|
||||
private static final String ICON_PATH = "/org/to/telegramfinalproject/Icons/";
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
editProfileItem.setOnAction(e -> openEditProfile());
|
||||
logoutItem.setOnAction(e -> System.out.println("Log Out clicked"));
|
||||
|
||||
// Example data – load from DB or user session later
|
||||
profileName.setText("Asal");
|
||||
profileId.setText("@Whales_suicide");
|
||||
profileImage.setImage(new Image(
|
||||
getClass().getResourceAsStream("/org/to/telegramfinalproject/Avatars/default_user_profile.png")
|
||||
));
|
||||
|
||||
// Make it circular
|
||||
Circle clip = new Circle(48, 28, 38); // centerX, centerY, radius
|
||||
profileImage.setClip(clip);
|
||||
|
||||
// Buttons
|
||||
myAccountButton.setOnAction(e -> openEditProfile());
|
||||
|
||||
privacyButton.setOnAction(e -> System.out.println("Privacy and Security"));
|
||||
faqButton.setOnAction(e -> System.out.println("Telegram Q&A"));
|
||||
featuresButton.setOnAction(e -> System.out.println("Telegram Features"));
|
||||
|
||||
// Close overlay on background click
|
||||
overlayBackground.setOnMouseClicked(e ->
|
||||
MainController.getInstance().closeOverlay(settingsCard.getParent()));
|
||||
|
||||
closeButton.setOnAction(e ->
|
||||
MainController.getInstance().closeOverlay(settingsCard.getParent())
|
||||
);
|
||||
|
||||
// Register scene for ThemeManager → stylesheet swap will handle colors/icons
|
||||
Platform.runLater(() -> {
|
||||
if (settingsCard.getScene() != null) {
|
||||
ThemeManager.getInstance().registerScene(settingsCard.getScene());
|
||||
}
|
||||
});
|
||||
|
||||
// Listener for theme change
|
||||
ThemeManager.getInstance().darkModeProperty().addListener((obs, oldVal, newVal) -> {
|
||||
updateEditIcon(newVal);
|
||||
updateMoreIcon(newVal);
|
||||
updateButtonsIcons(newVal);
|
||||
});
|
||||
|
||||
// Set initial state
|
||||
updateEditIcon(ThemeManager.getInstance().isDarkMode());
|
||||
updateMoreIcon(ThemeManager.getInstance().isDarkMode());
|
||||
updateButtonsIcons(ThemeManager.getInstance().isDarkMode());
|
||||
}
|
||||
|
||||
private void openEditProfile() {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource(
|
||||
"/org/to/telegramfinalproject/Fxml/edit_profile.fxml"));
|
||||
Node editOverlay = loader.load();
|
||||
|
||||
EditProfileController controller = loader.getController();
|
||||
controller.setProfileData(
|
||||
profileName.getText(),
|
||||
"online",
|
||||
"Pass me that lovely little gun♡.",
|
||||
"@Whales_suicide",
|
||||
profileImage.getImage()
|
||||
);
|
||||
|
||||
MainController.getInstance().showOverlay(editOverlay);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateEditIcon(boolean darkMode) {
|
||||
String editPath = darkMode
|
||||
? "/org/to/telegramfinalproject/Icons/edit_light.png"
|
||||
: "/org/to/telegramfinalproject/Icons/edit_dark.png";
|
||||
|
||||
ImageView icon = new ImageView(new Image(getClass().getResourceAsStream(editPath)));
|
||||
icon.setFitWidth(16);
|
||||
icon.setFitHeight(16);
|
||||
editProfileItem.setGraphic(icon);
|
||||
}
|
||||
|
||||
private void updateMoreIcon(boolean darkMode) {
|
||||
String morePath = darkMode
|
||||
? "/org/to/telegramfinalproject/Icons/more_light.png"
|
||||
: "/org/to/telegramfinalproject/Icons/more_dark.png";
|
||||
|
||||
ImageView icon = new ImageView(new Image(getClass().getResourceAsStream(morePath)));
|
||||
icon.setFitWidth(16);
|
||||
icon.setFitHeight(16);
|
||||
menuButton.setGraphic(icon);
|
||||
}
|
||||
|
||||
private void updateButtonsIcons(boolean darkMode) {
|
||||
String suffix = darkMode ? "_light.png" : "_dark.png";
|
||||
myAccountButton.setGraphic(makeIcon(ICON_PATH + "my_profile" + suffix));
|
||||
privacyButton.setGraphic(makeIcon(ICON_PATH + "lock" + suffix));
|
||||
faqButton.setGraphic(makeIcon(ICON_PATH + "telegram_features" + suffix));
|
||||
featuresButton.setGraphic(makeIcon(ICON_PATH + "telegram_qna" + suffix));
|
||||
}
|
||||
|
||||
// --- helpers -------------------------------------------------------------
|
||||
|
||||
private ImageView makeIcon(String path) {
|
||||
ImageView iv = new ImageView();
|
||||
Image img = loadImage(path);
|
||||
if (img != null) {
|
||||
iv.setImage(img);
|
||||
iv.setFitWidth(22);
|
||||
iv.setFitHeight(22);
|
||||
iv.setPreserveRatio(true);
|
||||
}
|
||||
return iv;
|
||||
}
|
||||
|
||||
private Image loadImage(String path) {
|
||||
URL res = getClass().getResource(path);
|
||||
if (res == null) {
|
||||
System.err.println("Resource not found: " + path);
|
||||
return null;
|
||||
}
|
||||
return new Image(res.toExternalForm());
|
||||
}
|
||||
}
|
||||
@@ -239,7 +239,21 @@ public class SidebarMenuController {
|
||||
}
|
||||
|
||||
private void openSavedMessages() { System.out.println("Opening Saved Messages..."); }
|
||||
private void openSettings() { System.out.println("Opening Settings..."); }
|
||||
|
||||
private void openSettings() {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource(
|
||||
"/org/to/telegramfinalproject/Fxml/settings.fxml"));
|
||||
Node settingsOverlay = loader.load();
|
||||
|
||||
// Show overlay on top of everything
|
||||
MainController.getInstance().showOverlay(settingsOverlay);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void openTelegramFeatures() { System.out.println("Opening Telegram Features..."); }
|
||||
private void openTelegramQnA() { System.out.println("Opening Telegram Q&A..."); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user