Manage Group UI + backend implemented.
This commit is contained in:
@@ -12,10 +12,12 @@ import javafx.scene.layout.*;
|
||||
import org.json.JSONObject;
|
||||
import org.to.telegramfinalproject.Client.ActionHandler;
|
||||
import org.to.telegramfinalproject.Client.AvatarLocalResolver;
|
||||
import org.to.telegramfinalproject.Client.Session;
|
||||
import org.to.telegramfinalproject.Models.ChatEntry;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GroupInfoController {
|
||||
|
||||
@@ -55,6 +57,10 @@ public class GroupInfoController {
|
||||
if (infoMoreMenu != null) infoMoreMenu.show(infoMoreButton, javafx.geometry.Side.BOTTOM, 0, 0);
|
||||
});
|
||||
|
||||
if (manageGroupItem != null) {
|
||||
manageGroupItem.setOnAction(e -> openManageGroupScene());
|
||||
}
|
||||
|
||||
deleteGroupItem.setOnAction(e -> handleDeleteGroup());
|
||||
|
||||
Platform.runLater(() -> {
|
||||
@@ -100,15 +106,26 @@ public class GroupInfoController {
|
||||
groupName.setText(data.optString("group_name", entry.getName()));
|
||||
memberCount.setText(data.optInt("member_count", 0) + " members");
|
||||
|
||||
// show/hide Delete button if user is owner
|
||||
String myRole = data.optString("my_role", "member");
|
||||
if ("owner".equalsIgnoreCase(myRole)) {
|
||||
deleteGroupItem.setVisible(true);
|
||||
} else {
|
||||
deleteGroupItem.setVisible(false);
|
||||
// --- Role-based UI ---
|
||||
String myRole = data.optString("my_role", "member").toLowerCase();
|
||||
|
||||
// Delete group → only owner
|
||||
deleteGroupItem.setVisible("owner".equals(myRole));
|
||||
|
||||
// Add member (button + menu item) → owner or admin
|
||||
boolean canAdd = "owner".equals(myRole) || "admin".equals(myRole);
|
||||
addMemberButton.setVisible(canAdd);
|
||||
addMemberButton.setManaged(canAdd);
|
||||
if (addMemberItem != null) {
|
||||
addMemberItem.setVisible(canAdd);
|
||||
}
|
||||
|
||||
// Group picture
|
||||
// More menu (3-dot) → hide entirely for plain members
|
||||
boolean showMore = "owner".equals(myRole) || "admin".equals(myRole);
|
||||
infoMoreButton.setVisible(showMore);
|
||||
infoMoreButton.setManaged(showMore);
|
||||
|
||||
// --- Group picture ---
|
||||
String imgUrl = data.optString("image_url", "");
|
||||
if (!imgUrl.isBlank()) {
|
||||
try {
|
||||
@@ -122,7 +139,7 @@ public class GroupInfoController {
|
||||
);
|
||||
}
|
||||
|
||||
// Members
|
||||
// --- Members list ---
|
||||
membersList.getChildren().clear();
|
||||
var arr = data.optJSONArray("members");
|
||||
if (arr != null) {
|
||||
@@ -191,6 +208,66 @@ public class GroupInfoController {
|
||||
membersList.getChildren().add(row);
|
||||
}
|
||||
|
||||
private void openManageGroupScene() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
JSONObject req = new JSONObject()
|
||||
.put("action", "view_group")
|
||||
.put("group_id", groupId)
|
||||
.put("viewer_id", Session.getUserUUID());
|
||||
|
||||
JSONObject resp = ActionHandler.sendWithResponse(req);
|
||||
|
||||
if (resp == null || !"success".equalsIgnoreCase(resp.optString("status"))) {
|
||||
Platform.runLater(() -> MainController.getInstance().showAlert(
|
||||
"Error",
|
||||
resp != null ? resp.optString("message") : "Server not responding.",
|
||||
Alert.AlertType.ERROR
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
JSONObject data = resp.optJSONObject("data");
|
||||
if (data == null) {
|
||||
Platform.runLater(() -> MainController.getInstance().showAlert(
|
||||
"Error",
|
||||
"Malformed server response.",
|
||||
Alert.AlertType.ERROR
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
Platform.runLater(() -> {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource(
|
||||
"/org/to/telegramfinalproject/Fxml/manage_group.fxml"));
|
||||
Node overlay = loader.load();
|
||||
|
||||
ManageGroupController controller = loader.getController();
|
||||
controller.setGroupData(data); // pass the full JSON
|
||||
|
||||
MainController.getInstance().showOverlay(overlay);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
MainController.getInstance().showAlert(
|
||||
"Error",
|
||||
"Could not load Manage Group scene.",
|
||||
Alert.AlertType.ERROR
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Platform.runLater(() -> MainController.getInstance().showAlert(
|
||||
"Error",
|
||||
"Error while fetching group info: " + e.getMessage(),
|
||||
Alert.AlertType.ERROR
|
||||
));
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void openAddMemberScene() {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource(
|
||||
@@ -198,8 +275,7 @@ public class GroupInfoController {
|
||||
Node overlay = loader.load();
|
||||
|
||||
AddMembersController controller = loader.getController();
|
||||
// 👇 Pass group id so AddMember scene knows which group to add to
|
||||
controller.setGroupForAdd(groupId, groupName);
|
||||
controller.setGroupForAdd(UUID.fromString(groupId), String.valueOf(groupName));
|
||||
|
||||
MainController.getInstance().showOverlay(overlay);
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
package org.to.telegramfinalproject.UI;
|
||||
|
||||
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.*;
|
||||
import javafx.stage.FileChooser;
|
||||
import org.json.JSONObject;
|
||||
import org.to.telegramfinalproject.Client.ActionHandler;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ManageGroupController {
|
||||
|
||||
@FXML private VBox manageGroupCard;
|
||||
@FXML private Pane overlayBackground;
|
||||
@FXML private Button closeButton, changePicButton, cancelButton, saveButton;
|
||||
@FXML private ImageView groupImage;
|
||||
@FXML private TextField groupNameField;
|
||||
@FXML private Label adminCount, memberCount;
|
||||
@FXML private TextField groupIdField;
|
||||
@FXML private Button manageAdminsButton;
|
||||
@FXML private Button manageMembersButton;
|
||||
|
||||
private String groupId; // Internal UUID of the current group
|
||||
private String originalName;
|
||||
private String originalGroupId;
|
||||
private String originalImageUrl;
|
||||
private File selectedImageFile;
|
||||
|
||||
private JSONObject data;
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
closeButton.setOnAction(e -> MainController.getInstance().closeOverlay(manageGroupCard.getParent()));
|
||||
cancelButton.setOnAction(e -> MainController.getInstance().closeOverlay(manageGroupCard.getParent()));
|
||||
overlayBackground.setOnMouseClicked(e -> MainController.getInstance().closeOverlay(manageGroupCard.getParent()));
|
||||
|
||||
changePicButton.setOnAction(e -> choosePicture());
|
||||
saveButton.setOnAction(e -> saveChanges());
|
||||
|
||||
manageAdminsButton.setOnAction(e -> openManageAdminsScene());
|
||||
manageMembersButton.setOnAction(e -> openManageMembersScene(data));
|
||||
}
|
||||
|
||||
private void openManageAdminsScene() {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource(
|
||||
"/org/to/telegramfinalproject/Fxml/manage_admins.fxml"));
|
||||
Node overlay = loader.load();
|
||||
|
||||
// ManageAdminsController controller = loader.getController();
|
||||
// controller.setGroupId(UUID.fromString(groupId));
|
||||
|
||||
MainController.getInstance().showOverlay(overlay);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
MainController.getInstance().showAlert(
|
||||
"Error", "Could not load Manage Admins scene.", Alert.AlertType.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private void openManageMembersScene(JSONObject data) {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource(
|
||||
"/org/to/telegramfinalproject/Fxml/manage_members.fxml"));
|
||||
Node overlay = loader.load();
|
||||
|
||||
ManageMembersController controller = loader.getController();
|
||||
// Pass groupId and members list from the JSON data
|
||||
controller.setGroupData(
|
||||
data.optString("internal_uuid"),
|
||||
data.optJSONArray("members")
|
||||
);
|
||||
|
||||
MainController.getInstance().showOverlay(overlay);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
MainController.getInstance().showAlert(
|
||||
"Error", "Could not load Manage Members scene.", Alert.AlertType.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public void setGroupData(JSONObject data) {
|
||||
this.data = data;
|
||||
this.groupId = data.optString("internal_uuid");
|
||||
|
||||
originalName = data.optString("group_name", "");
|
||||
originalGroupId = data.optString("group_id", "");
|
||||
originalImageUrl = data.optString("image_url", "");
|
||||
|
||||
groupNameField.setText(originalName);
|
||||
groupIdField.setText(originalGroupId);
|
||||
|
||||
if (!originalImageUrl.isBlank()) {
|
||||
groupImage.setImage(new Image(originalImageUrl, true));
|
||||
}
|
||||
|
||||
adminCount.setText(String.valueOf(countRole(data, "admin")));
|
||||
memberCount.setText(String.valueOf(countRole(data, "member")));
|
||||
}
|
||||
|
||||
private int countRole(JSONObject groupData, String role) {
|
||||
var arr = groupData.optJSONArray("members");
|
||||
if (arr == null) return 0;
|
||||
int count = 0;
|
||||
for (int i = 0; i < arr.length(); i++) {
|
||||
if (role.equalsIgnoreCase(arr.getJSONObject(i).optString("role"))) count++;
|
||||
}
|
||||
return count + 1;
|
||||
}
|
||||
|
||||
private void choosePicture() {
|
||||
FileChooser fc = new FileChooser();
|
||||
fc.setTitle("Select group picture");
|
||||
selectedImageFile = fc.showOpenDialog(manageGroupCard.getScene().getWindow());
|
||||
if (selectedImageFile != null) {
|
||||
groupImage.setImage(new Image(selectedImageFile.toURI().toString()));
|
||||
}
|
||||
}
|
||||
|
||||
private void saveChanges() {
|
||||
String newName = groupNameField.getText().trim();
|
||||
String newGroupId = groupIdField.getText().trim(); // make sure you added this field
|
||||
String newImageUrl = (selectedImageFile != null)
|
||||
? selectedImageFile.toURI().toString()
|
||||
: originalImageUrl;
|
||||
|
||||
// Check if anything actually changed
|
||||
boolean changed =
|
||||
!Objects.equals(originalName, newName) ||
|
||||
!Objects.equals(originalGroupId, newGroupId) ||
|
||||
!Objects.equals(originalImageUrl, newImageUrl);
|
||||
|
||||
if (!changed) {
|
||||
// Nothing changed → just close overlay
|
||||
MainController.getInstance().closeOverlay(manageGroupCard.getParent());
|
||||
return;
|
||||
}
|
||||
|
||||
// Build request with all fields (server expects them)
|
||||
JSONObject req = new JSONObject()
|
||||
.put("action", "edit_group_info")
|
||||
.put("group_id", groupId) // internal_uuid
|
||||
.put("new_group_id", newGroupId) // display id
|
||||
.put("name", newName);
|
||||
|
||||
if (newImageUrl != null && !newImageUrl.isBlank()) {
|
||||
req.put("image_url", newImageUrl);
|
||||
} else {
|
||||
req.put("image_url", JSONObject.NULL);
|
||||
}
|
||||
|
||||
JSONObject resp = ActionHandler.sendWithResponse(req);
|
||||
if (resp != null && "success".equalsIgnoreCase(resp.optString("status"))) {
|
||||
MainController.getInstance().closeOverlay(manageGroupCard.getParent());
|
||||
} else {
|
||||
String msg = (resp != null)
|
||||
? resp.optString("message", "Failed to update group")
|
||||
: "No response from server";
|
||||
Alert a = new Alert(Alert.AlertType.ERROR, msg, ButtonType.OK);
|
||||
a.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,8 @@ public class NewChannelController {
|
||||
if (resp == null || !"success".equalsIgnoreCase(resp.optString("status"))) {
|
||||
Platform.runLater(() -> {
|
||||
createButton.setDisable(false);
|
||||
showToast("Create failed: " + (resp == null ? "no response" : resp.optString("message","")));
|
||||
channelIdField.getStyleClass().add("error");
|
||||
channelIdLabel.getStyleClass().add("error");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -110,8 +110,10 @@ public class NewGroupController {
|
||||
new Thread(() -> {
|
||||
JSONObject resp = ActionHandler.sendWithResponse(req);
|
||||
if (resp == null || !"success".equalsIgnoreCase(resp.optString("status"))) {
|
||||
Platform.runLater(() -> showToast("Create failed: " +
|
||||
(resp == null ? "no response" : resp.optString("message",""))));
|
||||
Platform.runLater(() -> {
|
||||
groupIdField.getStyleClass().add("error");
|
||||
groupIdLabel.getStyleClass().add("error");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -182,7 +184,4 @@ public class NewGroupController {
|
||||
a.initOwner(overlayRoot.getScene().getWindow());
|
||||
a.show();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user