Merge pull request #4 from PartowRoshani/Login/Register

Login/Register front done
This commit is contained in:
Mohammad Sajjad Zanganeh
2025-07-04 17:29:33 +03:30
committed by GitHub
16 changed files with 628 additions and 87 deletions
@@ -7,7 +7,7 @@ import java.sql.SQLException;
public class ConnectionDb {
private static final String JDBC_URL = "jdbc:postgresql://localhost:5432/Telegram";
private static final String USERNAME = "postgres";
private static final String PASSWORD = "Partow@1384";
private static final String PASSWORD = "124postpass";
public ConnectionDb() {
}
@@ -0,0 +1,145 @@
package org.to.telegramfinalproject.UI;
import javafx.animation.TranslateTransition;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.util.Duration;
import javafx.scene.shape.Circle;
import javafx.scene.paint.Color;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class IntroController {
@FXML private StackPane imagePane;
@FXML private Label caption;
@FXML private HBox dotContainer;
@FXML private Button startButton;
private List<Image> images = new ArrayList<>();
private List<String> captions = new ArrayList<>();
private int currentIndex = 0;
private final int width = 200;
private final int height = 200;
@FXML
public void initialize() {
loadSlides();
setupDots();
showSlide(currentIndex);
startAutoSlide();
}
private void loadSlides() {
images.add(new Image(getClass().getResource("/org/to/telegramfinalproject/Images/telegram_icon.png").toExternalForm()));
captions.add("🚀 The world's fastest messaging app.\nIt is free and secure.");
images.add(new Image(getClass().getResource("/org/to/telegramfinalproject/Images/fast.png").toExternalForm()));
captions.add("🚀 Telegram delivers messages \nfastest than any other application.");
images.add(new Image(getClass().getResource("/org/to/telegramfinalproject/Images/free.png").toExternalForm()));
captions.add("🎁 Telegram is free forever. No ads.\nNo subscription fees.");
images.add(new Image(getClass().getResource("/org/to/telegramfinalproject/Images/secure.png").toExternalForm()));
captions.add("🔒 Telegram keeps your messages \nsafe from hacker attacks.");
}
private void setupDots() {
dotContainer.getChildren().clear();
for (int i = 0; i < images.size(); i++) {
Circle dot = new Circle(5, Color.LIGHTGRAY);
dotContainer.getChildren().add(dot);
}
}
private void updateDots() {
for (int i = 0; i < dotContainer.getChildren().size(); i++) {
Circle dot = (Circle) dotContainer.getChildren().get(i);
if (i == currentIndex) {
dot.setFill(getSlideColor(i));
} else {
dot.setFill(Color.LIGHTGRAY);
}
}
}
private Color getSlideColor(int index) {
return switch (index) {
case 0 -> Color.DODGERBLUE; // Blue for Telegram logo
case 1 -> Color.FIREBRICK; // Red slide
case 2 -> Color.GOLDENROD; // Yellow slide
case 3 -> Color.SEAGREEN; // Green slide
default -> Color.GRAY;
};
}
private void showSlide(int index) {
imagePane.getChildren().clear();
ImageView imageView = new ImageView(images.get(index));
imageView.setFitWidth(180);
imageView.setFitHeight(180);
imageView.setPreserveRatio(true);
// Clip the image into a circle
Circle clip = new Circle(90, 90, 80); // centerX, centerY, radius
imageView.setClip(clip);
imagePane.getChildren().add(imageView);
caption.setText(captions.get(index));
updateDots();
}
private void startAutoSlide() {
Thread slider = new Thread(() -> {
while (true) {
try {
Thread.sleep(3000);
} catch (InterruptedException ignored) {}
javafx.application.Platform.runLater(() -> {
currentIndex = (currentIndex + 1) % images.size();
showSlide(currentIndex);
});
}
});
slider.setDaemon(true);
slider.start();
}
@FXML
private void handleStartMessaging(ActionEvent event) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/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();
}
}
}
@@ -0,0 +1,134 @@
package org.to.telegramfinalproject.UI;
import javafx.animation.PauseTransition;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.Parent;
import javafx.scene.control.*;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.json.JSONObject;
import org.to.telegramfinalproject.Client.ClientConnection;
import org.to.telegramfinalproject.Database.userDatabase;
import org.to.telegramfinalproject.Models.User;
import org.to.telegramfinalproject.Security.PasswordHashing;
import java.io.IOException;
public class LoginController {
@FXML private TextField usernameField;
@FXML private PasswordField passwordField;
@FXML private TextField visiblePasswordField;
@FXML private Button togglePasswordBtn;
@FXML private Label errorLabel;
private ClientConnection connection;
private boolean passwordVisible = false;
@FXML
public void initialize() {
// Sync hidden and visible password fields
visiblePasswordField.textProperty().bindBidirectional(passwordField.textProperty());
try {
connection = new ClientConnection("localhost", 12345);
} catch (Exception e) {
System.out.println("Could not connect to server: " + e.getMessage());
}
}
@FXML
private void togglePasswordVisibility() {
passwordVisible = !passwordVisible;
visiblePasswordField.setVisible(passwordVisible);
visiblePasswordField.setManaged(passwordVisible);
passwordField.setVisible(!passwordVisible);
passwordField.setManaged(!passwordVisible);
togglePasswordBtn.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.");
}
}
@FXML
private void switchToRegister() throws IOException {
switchScene("register_view.fxml");
}
private void switchScene(String fxmlFile) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/" + fxmlFile));
Parent root = loader.load();
Stage stage = (Stage) usernameField.getScene().getWindow();
stage.setScene(new Scene(root, 500, 700));
stage.show();
} catch (IOException e) {
e.printStackTrace();
showError("Could not load scene: " + fxmlFile);
}
}
private void showError(String message) {
errorLabel.setVisible(false);
errorLabel.setText(""); // Clear the label text
PauseTransition pause = new PauseTransition(Duration.millis(50));
pause.setOnFinished(event -> {
errorLabel.setText(message);
errorLabel.setVisible(true);
});
pause.play();
}
}
@@ -0,0 +1,160 @@
package org.to.telegramfinalproject.UI;
import javafx.animation.PauseTransition;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.json.JSONObject;
import org.to.telegramfinalproject.Client.ClientConnection;
import org.to.telegramfinalproject.Database.userDatabase;
import java.io.IOException;
public class RegisterController {
@FXML private TextField userIdField;
@FXML private TextField usernameField;
@FXML private TextField profileNameField;
@FXML private PasswordField passwordField;
@FXML private TextField visiblePasswordField;
@FXML private PasswordField confirmPasswordField;
@FXML private TextField visibleConfirmPasswordField;
@FXML private Button togglePasswordBtn;
@FXML private Button toggleConfirmBtn;
@FXML private Label errorLabel;
private ClientConnection connection;
private boolean passwordVisible = false;
private boolean confirmVisible = false;
@FXML
public void initialize() {
// Sync password and confirm fields with their visible counterparts
visiblePasswordField.textProperty().bindBidirectional(passwordField.textProperty());
visibleConfirmPasswordField.textProperty().bindBidirectional(confirmPasswordField.textProperty());
try {
connection = new ClientConnection("localhost", 12345);
} catch (Exception e) {
System.out.println("Could not connect to server: " + e.getMessage());
}
}
@FXML
private void togglePasswordVisibility() {
passwordVisible = !passwordVisible;
visiblePasswordField.setVisible(passwordVisible);
visiblePasswordField.setManaged(passwordVisible);
passwordField.setVisible(!passwordVisible);
passwordField.setManaged(!passwordVisible);
togglePasswordBtn.setText(passwordVisible ? "👁" : "👁");
}
@FXML
private void toggleConfirmPasswordVisibility() {
confirmVisible = !confirmVisible;
visibleConfirmPasswordField.setVisible(confirmVisible);
visibleConfirmPasswordField.setManaged(confirmVisible);
confirmPasswordField.setVisible(!confirmVisible);
confirmPasswordField.setManaged(!confirmVisible);
toggleConfirmBtn.setText(confirmVisible ? "👁" : "👁");
}
@FXML
private void handleRegister() {
String userID = userIdField.getText().trim();
String username = usernameField.getText().trim();
String profileName = profileNameField.getText().trim();
String password = passwordField.getText();
String confirmPass = confirmPasswordField.getText();
userDatabase userDb = new userDatabase();
String passwordRegex = "\\b(?=[^\\s]*[A-Z])(?=[^\\s]*[a-z])(?=[^\\s]*\\d)(?=[^\\s]*[!@#$%^&*])[^\\s]{8,}\\b";
// 1. Empty fields
if (username.isEmpty() || profileName.isEmpty() || password.isEmpty() || confirmPass.isEmpty()) {
showError("Please fill in all required fields.");
return;
}
// 2. Username exists
if (userDb.existsByUsername(username)) {
showError("This username is already taken.");
return;
}
// 3. User ID exists (if entered)
if (!userID.isEmpty() && userDb.existsByUserId(userID)) {
showError("This user ID is already taken.");
return;
}
// 4. Password mismatch
if (!password.equals(confirmPass)) {
showError("Passwords do not match.");
return;
}
// 5. Weak password
if (!password.matches(passwordRegex)) {
showError("Password must be at least 8 characters, include a capital letter, a number, and a special character.");
return;
}
// 6. Attempt registration
try {
JSONObject request = new JSONObject();
request.put("action", "register");
request.put("user_id", userID.isEmpty() ? JSONObject.NULL : userID);
request.put("username", username);
request.put("password", password);
request.put("profile_name", profileName);
connection.send(request.toString());
Alert alert = new Alert(Alert.AlertType.INFORMATION, "Registration successful!");
alert.show();
} catch (Exception ex) {
showError("Failed to register. Please try again later.");
}
}
@FXML
private void switchToLogin() throws IOException {
switchScene("login_view.fxml");
}
private void switchScene(String fxmlFile) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/" + fxmlFile));
Parent root = loader.load();
Stage stage = (Stage) usernameField.getScene().getWindow(); // Or any node from your current scene
stage.setScene(new Scene(root, 500, 700));
stage.show();
} catch (IOException e) {
e.printStackTrace();
showError("Could not load scene: " + fxmlFile);
}
}
private void showError(String message) {
errorLabel.setVisible(false);
errorLabel.setText(""); // Clear the label text
PauseTransition pause = new PauseTransition(Duration.millis(50));
pause.setOnFinished(event -> {
errorLabel.setText(message);
errorLabel.setVisible(true);
});
pause.play();
}
}
@@ -81,20 +81,14 @@ public class RegisterForm {
alert.show();
}
else {
Alert alert = new Alert(Alert.AlertType.ERROR, "Password doesn't Strong enough");
Alert alert = new Alert(Alert.AlertType.ERROR, "Password isn't Strong enough");
alert.show();
}
});
backButton.setOnAction(e -> {
switchScene("login_view.fxml");
});
}
private void switchScene(String fxmlFile) {
@@ -12,9 +12,9 @@ import java.io.IOException;
public class TelegramApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("login_view.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 320, 240);
stage.setTitle("Hello!");
FXMLLoader fxmlLoader = new FXMLLoader(TelegramApplication.class.getResource("/org/to/telegramfinalproject/Intro.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 1480, 820);
stage.setTitle("Telegram");
stage.setScene(scene);
stage.show();
}
@@ -22,5 +22,4 @@ public class TelegramApplication extends Application {
launch();
}
}
}
@@ -25,7 +25,7 @@ public class login_view {
});
registerButton.setOnAction(e -> {
switchScene("RegisterForm.fxml");
switchScene("register_view.fxml");
});
}