Privacy & Security UI implemented.
@@ -0,0 +1,115 @@
|
|||||||
|
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 java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public class PrivacySecurityController {
|
||||||
|
|
||||||
|
@FXML private VBox privacyCard;
|
||||||
|
@FXML private Pane overlayBackground;
|
||||||
|
@FXML private Button closeButton;
|
||||||
|
@FXML private Button backButton;
|
||||||
|
@FXML private Button blockedUsersButton;
|
||||||
|
@FXML private Button changeCredentialsButton;
|
||||||
|
@FXML private ImageView blockIcon;
|
||||||
|
@FXML private ImageView usernameIcon;
|
||||||
|
|
||||||
|
private static final String ICON_PATH = "/org/to/telegramfinalproject/Icons/";
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void initialize() {
|
||||||
|
// Set back button icon
|
||||||
|
ImageView backIcon = new ImageView(
|
||||||
|
new Image(getClass().getResourceAsStream("/org/to/telegramfinalproject/Icons/back_button_dark.png"))
|
||||||
|
);
|
||||||
|
backIcon.setFitWidth(18);
|
||||||
|
backIcon.setFitHeight(18);
|
||||||
|
backButton.setGraphic(backIcon);
|
||||||
|
|
||||||
|
changeCredentialsButton.setOnAction(e -> openPasswordCheckOverlay());
|
||||||
|
|
||||||
|
// Blocked users management
|
||||||
|
blockedUsersButton.setOnAction(e -> {
|
||||||
|
// TODO: open Blocked Users scene
|
||||||
|
System.out.println("Open blocked users management");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close
|
||||||
|
closeButton.setOnAction(e -> MainController.getInstance().closeOverlay(privacyCard.getParent()));
|
||||||
|
|
||||||
|
// Back
|
||||||
|
backButton.setOnAction(e -> MainController.getInstance().goBack(privacyCard));
|
||||||
|
overlayBackground.setOnMouseClicked(e -> MainController.getInstance().closeOverlay(privacyCard.getParent()));
|
||||||
|
|
||||||
|
// Register scene for ThemeManager → stylesheet swap will handle colors/icons
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
if (privacyCard.getScene() != null) {
|
||||||
|
ThemeManager.getInstance().registerScene(privacyCard.getScene());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Listener for theme change
|
||||||
|
ThemeManager.getInstance().darkModeProperty().addListener((obs, oldVal, newVal) -> {
|
||||||
|
updateIcons(newVal);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set initial state
|
||||||
|
updateIcons(ThemeManager.getInstance().isDarkMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openPasswordCheckOverlay() {
|
||||||
|
try {
|
||||||
|
FXMLLoader loader = new FXMLLoader(getClass().getResource(
|
||||||
|
"/org/to/telegramfinalproject/Fxml/check_password.fxml"));
|
||||||
|
Node overlay = loader.load();
|
||||||
|
|
||||||
|
// Show new overlay
|
||||||
|
MainController.getInstance().showOverlay(overlay);
|
||||||
|
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateIcons(boolean darkMode) {
|
||||||
|
String suffix = darkMode ? "_light.png" : "_dark.png";
|
||||||
|
|
||||||
|
backButton.setGraphic(makeIcon(ICON_PATH + "back_button" + suffix));
|
||||||
|
blockIcon.setImage(loadImage(ICON_PATH + "hand" + suffix));
|
||||||
|
usernameIcon.setImage(loadImage(ICON_PATH + "username" + 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,7 +52,19 @@ public class SettingsController {
|
|||||||
// Buttons
|
// Buttons
|
||||||
myAccountButton.setOnAction(e -> openEditProfile());
|
myAccountButton.setOnAction(e -> openEditProfile());
|
||||||
|
|
||||||
privacyButton.setOnAction(e -> System.out.println("Privacy and Security"));
|
privacyButton.setOnAction(e ->
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
FXMLLoader loader = new FXMLLoader(getClass().getResource(
|
||||||
|
"/org/to/telegramfinalproject/Fxml/privacy_security.fxml"));
|
||||||
|
Node privacyOverlay = loader.load();
|
||||||
|
|
||||||
|
MainController.getInstance().showOverlay(privacyOverlay);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
faqButton.setOnAction(e -> System.out.println("Telegram Q&A"));
|
faqButton.setOnAction(e -> System.out.println("Telegram Q&A"));
|
||||||
featuresButton.setOnAction(e -> System.out.println("Telegram Features"));
|
featuresButton.setOnAction(e -> System.out.println("Telegram Features"));
|
||||||
|
|
||||||
|
|||||||
@@ -898,3 +898,94 @@
|
|||||||
.settings-option:pressed {
|
.settings-option:pressed {
|
||||||
-fx-background-color: #1f2a36;
|
-fx-background-color: #1f2a36;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Card */
|
||||||
|
.privacy-card {
|
||||||
|
-fx-background-color: #1f2a36;
|
||||||
|
-fx-background-radius: 10;
|
||||||
|
-fx-padding: 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
.privacy-header {
|
||||||
|
-fx-padding: 8 12 8 12;
|
||||||
|
}
|
||||||
|
.privacy-title {
|
||||||
|
-fx-font-size: 16px;
|
||||||
|
-fx-font-weight: bold;
|
||||||
|
-fx-text-fill: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Section Titles */
|
||||||
|
.section-title {
|
||||||
|
-fx-font-size: 13px;
|
||||||
|
-fx-font-weight: bold;
|
||||||
|
-fx-text-fill: #bbbbbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Items */
|
||||||
|
.privacy-item {
|
||||||
|
-fx-padding: 4 0 4 0;
|
||||||
|
}
|
||||||
|
.item-label {
|
||||||
|
-fx-font-size: 12px;
|
||||||
|
-fx-text-fill: #aaa;
|
||||||
|
}
|
||||||
|
.privacy-input {
|
||||||
|
-fx-background-color: #2a3b47;
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-background-radius: 6;
|
||||||
|
-fx-padding: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buttons */
|
||||||
|
.action-button {
|
||||||
|
-fx-background-color: #3a86ff;
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-background-radius: 6;
|
||||||
|
-fx-padding: 6 12;
|
||||||
|
}
|
||||||
|
.manage-button {
|
||||||
|
-fx-background-color: #1f2a36;
|
||||||
|
-fx-text-fill: #3a86ff;
|
||||||
|
-fx-font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.privacy-section {
|
||||||
|
-fx-spacing: 8;
|
||||||
|
-fx-padding: 10 0 10 0;
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-border-color: #2f2f2f;
|
||||||
|
-fx-border-width: 0 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.privacy-form {
|
||||||
|
-fx-spacing: 8;
|
||||||
|
-fx-alignment: CENTER_LEFT;
|
||||||
|
-fx-padding: 8 0 8 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.privacy-form .label {
|
||||||
|
-fx-font-size: 12px;
|
||||||
|
-fx-text-fill: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error state (same for both themes) */
|
||||||
|
.password-label.error {
|
||||||
|
-fx-text-fill: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-field.error {
|
||||||
|
-fx-text-fill: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-field.error {
|
||||||
|
-fx-text-fill: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-visibility-btn {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-cursor: hand;
|
||||||
|
-fx-padding: 0 6 0 6;
|
||||||
|
-fx-font-size: 14px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -901,3 +901,91 @@
|
|||||||
-fx-background-color: #e0e0e0;
|
-fx-background-color: #e0e0e0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Card */
|
||||||
|
.privacy-card {
|
||||||
|
-fx-background-color: white;
|
||||||
|
-fx-background-radius: 10;
|
||||||
|
-fx-padding: 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
.privacy-header {
|
||||||
|
-fx-padding: 8 12 8 12;
|
||||||
|
}
|
||||||
|
.privacy-title {
|
||||||
|
-fx-font-size: 16px;
|
||||||
|
-fx-font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Section Titles */
|
||||||
|
.section-title {
|
||||||
|
-fx-font-size: 13px;
|
||||||
|
-fx-font-weight: bold;
|
||||||
|
-fx-text-fill: #2a2a2a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Items */
|
||||||
|
.privacy-item {
|
||||||
|
-fx-padding: 4 0 4 0;
|
||||||
|
}
|
||||||
|
.item-label {
|
||||||
|
-fx-font-size: 12px;
|
||||||
|
-fx-text-fill: #444;
|
||||||
|
}
|
||||||
|
.privacy-input {
|
||||||
|
-fx-background-color: #f5f5f5;
|
||||||
|
-fx-background-radius: 6;
|
||||||
|
-fx-padding: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buttons */
|
||||||
|
.action-button {
|
||||||
|
-fx-background-color: #2196f3;
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-background-radius: 6;
|
||||||
|
-fx-padding: 6 12;
|
||||||
|
}
|
||||||
|
.manage-button {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-text-fill: #2196f3;
|
||||||
|
-fx-font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.privacy-section {
|
||||||
|
-fx-spacing: 8;
|
||||||
|
-fx-padding: 10 0 10 0;
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-border-color: #e0e0e0;
|
||||||
|
-fx-border-width: 0 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.privacy-form {
|
||||||
|
-fx-spacing: 8;
|
||||||
|
-fx-alignment: CENTER_LEFT;
|
||||||
|
-fx-padding: 8 0 8 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.privacy-form .label {
|
||||||
|
-fx-font-size: 12px;
|
||||||
|
-fx-text-fill: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error state (same for both themes) */
|
||||||
|
.password-label.error {
|
||||||
|
-fx-text-fill: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-field.error {
|
||||||
|
-fx-text-fill: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-field.error {
|
||||||
|
-fx-text-fill: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-visibility-btn {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-cursor: hand;
|
||||||
|
-fx-padding: 0 6 0 6;
|
||||||
|
-fx-font-size: 14px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
<?import javafx.scene.control.*?>
|
||||||
|
<?import javafx.scene.image.ImageView?>
|
||||||
|
<?import javafx.scene.image.Image?>
|
||||||
|
|
||||||
|
<StackPane fx:id="overlayRoot"
|
||||||
|
xmlns:fx="http://javafx.com/fxml"
|
||||||
|
fx:controller="org.to.telegramfinalproject.UI.PrivacySecurityController"
|
||||||
|
styleClass="overlay-root">
|
||||||
|
|
||||||
|
<!-- Dimmed Background -->
|
||||||
|
<Pane fx:id="overlayBackground" styleClass="overlay-background"/>
|
||||||
|
|
||||||
|
<!-- Main Card -->
|
||||||
|
<VBox fx:id="privacyCard"
|
||||||
|
styleClass="privacy-card"
|
||||||
|
spacing="16"
|
||||||
|
prefWidth="360" maxWidth="360"
|
||||||
|
prefHeight="480" maxHeight="480">
|
||||||
|
|
||||||
|
<!-- ===== Header: Back + Title + Close ===== -->
|
||||||
|
<HBox alignment="CENTER_LEFT" spacing="10" styleClass="privacy-header">
|
||||||
|
<!-- Back button -->
|
||||||
|
<Button fx:id="backButton" styleClass="edit-icon-button"/>
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<Label fx:id="privacyTitle" text="Privacy and Security" styleClass="privacy-title" HBox.hgrow="ALWAYS"/>
|
||||||
|
|
||||||
|
<Pane HBox.hgrow="ALWAYS"/>
|
||||||
|
|
||||||
|
<!-- Close button -->
|
||||||
|
<Button fx:id="closeButton" styleClass="edit-icon-button" text="✕"/>
|
||||||
|
</HBox>
|
||||||
|
|
||||||
|
|
||||||
|
<Separator/>
|
||||||
|
|
||||||
|
<!-- ===== Security Section ===== -->
|
||||||
|
<VBox spacing="8" styleClass="privacy-section">
|
||||||
|
<Label text="Security" styleClass="section-title"/>
|
||||||
|
|
||||||
|
<!-- Username & Password -->
|
||||||
|
<HBox alignment="CENTER_LEFT" spacing="8" styleClass="privacy-item">
|
||||||
|
|
||||||
|
<!-- Icon -->
|
||||||
|
<ImageView fx:id="usernameIcon" fitWidth="18" fitHeight="18" preserveRatio="true">
|
||||||
|
<image>
|
||||||
|
<Image url="@/org/to/telegramfinalproject/Icons/username_dark.png"/>
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
|
||||||
|
<Label text="Username & Password" styleClass="item-label"/>
|
||||||
|
<Pane HBox.hgrow="ALWAYS"/>
|
||||||
|
<Button fx:id="changeCredentialsButton" text="Change" styleClass="manage-button"/>
|
||||||
|
</HBox>
|
||||||
|
</VBox>
|
||||||
|
|
||||||
|
<Separator/>
|
||||||
|
|
||||||
|
<!-- ===== Privacy Section ===== -->
|
||||||
|
<VBox spacing="8" styleClass="privacy-section">
|
||||||
|
<Label text="Privacy" styleClass="section-title"/>
|
||||||
|
|
||||||
|
<!-- Blocked Users -->
|
||||||
|
<HBox alignment="CENTER_LEFT" spacing="8" styleClass="privacy-item">
|
||||||
|
|
||||||
|
<!-- Icon -->
|
||||||
|
<ImageView fx:id="blockIcon" fitWidth="18" fitHeight="18" preserveRatio="true">
|
||||||
|
<image>
|
||||||
|
<Image url="@/org/to/telegramfinalproject/Icons/hand_dark.png"/>
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
|
||||||
|
<Label text="Blocked Users" styleClass="item-label"/>
|
||||||
|
<Pane HBox.hgrow="ALWAYS"/>
|
||||||
|
<Button fx:id="blockedUsersButton" text="Manage" styleClass="manage-button"/>
|
||||||
|
</HBox>
|
||||||
|
</VBox>
|
||||||
|
</VBox>
|
||||||
|
</StackPane>
|
||||||
|
After Width: | Height: | Size: 781 B |
|
After Width: | Height: | Size: 804 B |
|
After Width: | Height: | Size: 310 B |
|
After Width: | Height: | Size: 264 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 618 B |
|
Before Width: | Height: | Size: 985 B After Width: | Height: | Size: 511 B |