Search system fixed.
This commit is contained in:
@@ -21,10 +21,6 @@ public class ChatItemController {
|
|||||||
@FXML private ImageView profileImageSystem;
|
@FXML private ImageView profileImageSystem;
|
||||||
@FXML private Circle systemCircle;
|
@FXML private Circle systemCircle;
|
||||||
|
|
||||||
// Default avatar resource path
|
|
||||||
private static final String DEFAULT_AVATAR =
|
|
||||||
"/org/to/telegramfinalproject/Avatars/default_avatar.png";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set chat item data, including a profile image (or default).
|
* Set chat item data, including a profile image (or default).
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -431,7 +431,7 @@ public class ChatPageController {
|
|||||||
chatStatus.setText("");
|
chatStatus.setText("");
|
||||||
if (entry.getImageUrl() != null && !entry.getImageUrl().isEmpty()) {
|
if (entry.getImageUrl() != null && !entry.getImageUrl().isEmpty()) {
|
||||||
try {
|
try {
|
||||||
userAvatar.setImage(new Image(entry.getImageUrl()));
|
userAvatar.setImage(new Image(entry.getImageUrl() != null ? entry.getImageUrl() : "/org/to/telegramfinalproject/Avatars/default_user_profile.png"));
|
||||||
userAvatar.setClip(new Circle(18, 18, 18));
|
userAvatar.setClip(new Circle(18, 18, 18));
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import javafx.scene.layout.HBox;
|
|||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.scene.shape.Circle;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import org.to.telegramfinalproject.Models.ChatEntry;
|
import org.to.telegramfinalproject.Models.ChatEntry;
|
||||||
import org.to.telegramfinalproject.Client.ActionHandler;
|
import org.to.telegramfinalproject.Client.ActionHandler;
|
||||||
@@ -28,9 +29,10 @@ public class MainController {
|
|||||||
// === Global Search ===
|
// === Global Search ===
|
||||||
@FXML private TextField searchBar;
|
@FXML private TextField searchBar;
|
||||||
@FXML private VBox globalSearchPane;
|
@FXML private VBox globalSearchPane;
|
||||||
@FXML private ListView<SearchResult> globalSearchResults;
|
|
||||||
@FXML private VBox noResultsBox;
|
@FXML private VBox noResultsBox;
|
||||||
@FXML private ImageView noResultIcon;
|
@FXML private ImageView noResultIcon;
|
||||||
|
@FXML private ScrollPane globalSearchScroll;
|
||||||
|
@FXML private VBox globalSearchResultsContainer;
|
||||||
private enum SearchMode {
|
private enum SearchMode {
|
||||||
GLOBAL,
|
GLOBAL,
|
||||||
CHAT
|
CHAT
|
||||||
@@ -83,10 +85,9 @@ public class MainController {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
// addSampleChats();
|
// Populate chat list
|
||||||
populateChatListFromSession();
|
populateChatListFromSession();
|
||||||
|
|
||||||
|
|
||||||
// Register the scene for automatic CSS updates
|
// Register the scene for automatic CSS updates
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
ThemeManager.getInstance().registerScene(mainRoot.getScene());
|
ThemeManager.getInstance().registerScene(mainRoot.getScene());
|
||||||
@@ -95,17 +96,15 @@ public class MainController {
|
|||||||
// Listen for theme changes to update icons & labels manually
|
// Listen for theme changes to update icons & labels manually
|
||||||
ThemeManager.getInstance().darkModeProperty().addListener((obs, oldVal, newVal) -> {
|
ThemeManager.getInstance().darkModeProperty().addListener((obs, oldVal, newVal) -> {
|
||||||
if (newVal) {
|
if (newVal) {
|
||||||
// Dark mode ON
|
|
||||||
updateIconsForDarkMode();
|
updateIconsForDarkMode();
|
||||||
updateLabelsForDarkMode();
|
updateLabelsForDarkMode();
|
||||||
} else {
|
} else {
|
||||||
// Light mode ON
|
|
||||||
updateIconsForLightMode();
|
updateIconsForLightMode();
|
||||||
updateLabelsForLightMode();
|
updateLabelsForLightMode();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Smooth scroll feel
|
// Smooth scroll feel for chat list
|
||||||
scrollPane.getStylesheets().add(getClass().getResource("/org/to/telegramfinalproject/CSS/scrollpane.css").toExternalForm());
|
scrollPane.getStylesheets().add(getClass().getResource("/org/to/telegramfinalproject/CSS/scrollpane.css").toExternalForm());
|
||||||
scrollPane.setPannable(true);
|
scrollPane.setPannable(true);
|
||||||
scrollPane.setFitToWidth(true);
|
scrollPane.setFitToWidth(true);
|
||||||
@@ -124,25 +123,7 @@ public class MainController {
|
|||||||
mainSplitPane.getDividers().get(0).positionProperty().addListener((o, ov, nv) -> clampDivider());
|
mainSplitPane.getDividers().get(0).positionProperty().addListener((o, ov, nv) -> clampDivider());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search bar enter action
|
||||||
// Search in chat field listener
|
|
||||||
// searchBar.textProperty().addListener((obs, oldV, newV) -> {
|
|
||||||
// if (!chatSearchPane.isVisible()) return; // only react if in search mode
|
|
||||||
//
|
|
||||||
// if (newV.trim().isEmpty()) {
|
|
||||||
// chatSearchResults.setVisible(false);
|
|
||||||
// chatSearchResults.setManaged(false);
|
|
||||||
// } else {
|
|
||||||
// chatSearchResults.setVisible(true);
|
|
||||||
// chatSearchResults.setManaged(true);
|
|
||||||
// chatSearchResults.getItems().setAll(
|
|
||||||
// "Result 1: " + newV,
|
|
||||||
// "Result 2: " + newV,
|
|
||||||
// "Result 3: " + newV
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
searchBar.setOnAction(e -> {
|
searchBar.setOnAction(e -> {
|
||||||
String keyword = searchBar.getText().trim();
|
String keyword = searchBar.getText().trim();
|
||||||
if (keyword.isEmpty()) return;
|
if (keyword.isEmpty()) return;
|
||||||
@@ -154,100 +135,28 @@ public class MainController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
searchBar.setOnAction(e -> performGlobalSearch(searchBar.getText().trim()));
|
// Typing in search bar shows global search panel
|
||||||
|
searchBar.textProperty().addListener((obs, o, n) -> {
|
||||||
searchBar.textProperty().addListener((obs,o,n)->{
|
if (n != null && !n.isBlank()) {
|
||||||
if (n!=null && !n.isBlank()) showGlobalSearchPanel();
|
if (currentSearchMode == SearchMode.GLOBAL) {
|
||||||
});
|
showGlobalSearchPanel();
|
||||||
|
} else if (currentSearchMode == SearchMode.CHAT) {
|
||||||
globalSearchResults.setOnMouseClicked(e -> {
|
showSearchPanel();
|
||||||
int idx = globalSearchResults.getSelectionModel().getSelectedIndex();
|
|
||||||
if (idx >= 0 && idx < searchBacking.size()) {
|
|
||||||
openSearchResult(searchBacking.get(idx));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
globalSearchResults.setCellFactory(list -> new ListCell<>() {
|
|
||||||
private final HBox container = new HBox(10);
|
|
||||||
private final ImageView avatar = new ImageView();
|
|
||||||
private final VBox texts = new VBox(2);
|
|
||||||
private final Label title = new Label();
|
|
||||||
private final Label subtitle = new Label();
|
|
||||||
|
|
||||||
{
|
|
||||||
avatar.setFitWidth(36);
|
|
||||||
avatar.setFitHeight(36);
|
|
||||||
avatar.getStyleClass().add("global-search-avatar");
|
|
||||||
title.getStyleClass().add("global-search-title");
|
|
||||||
subtitle.getStyleClass().add("global-search-subtitle");
|
|
||||||
texts.getChildren().addAll(title, subtitle);
|
|
||||||
container.getChildren().addAll(avatar, texts);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void updateItem(SearchResult r, boolean empty) {
|
|
||||||
super.updateItem(r, empty);
|
|
||||||
if (empty || r == null) {
|
|
||||||
setGraphic(null);
|
|
||||||
} else {
|
|
||||||
title.setText(r.title);
|
|
||||||
if (r.type == SRType.MESSAGE) {
|
|
||||||
subtitle.setText(r.subtitle != null ? r.subtitle : "");
|
|
||||||
} else {
|
|
||||||
subtitle.setText("Press to see messages");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default profile images depending on type
|
|
||||||
switch (r.type) {
|
|
||||||
case USER:
|
|
||||||
avatar.setImage(new Image(
|
|
||||||
Objects.requireNonNull(getClass().getResourceAsStream(
|
|
||||||
"/org/to/telegramfinalproject/Avatars/default_user_profile.png"
|
|
||||||
))
|
|
||||||
));
|
|
||||||
break;
|
|
||||||
case GROUP:
|
|
||||||
avatar.setImage(new Image(
|
|
||||||
Objects.requireNonNull(getClass().getResourceAsStream(
|
|
||||||
"/org/to/telegramfinalproject/Avatars/default_group_profile.png"
|
|
||||||
))
|
|
||||||
));
|
|
||||||
break;
|
|
||||||
case CHANNEL:
|
|
||||||
avatar.setImage(new Image(
|
|
||||||
Objects.requireNonNull(getClass().getResourceAsStream(
|
|
||||||
"/org/to/telegramfinalproject/Avatars/default_channel_profile.png"
|
|
||||||
))
|
|
||||||
));
|
|
||||||
break;
|
|
||||||
case MESSAGE:
|
|
||||||
// For messages, use sender default (user style)
|
|
||||||
avatar.setImage(new Image(
|
|
||||||
Objects.requireNonNull(getClass().getResourceAsStream(
|
|
||||||
"/org/to/telegramfinalproject/Avatars/default_user_profile.png"
|
|
||||||
))
|
|
||||||
));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
avatar.setFitWidth(50);
|
|
||||||
avatar.setFitHeight(50);
|
|
||||||
avatar.setPreserveRatio(true);
|
|
||||||
avatar.setSmooth(true);
|
|
||||||
|
|
||||||
setGraphic(container);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// CLick on the search result
|
// Smooth scroll feel for global search results
|
||||||
chatSearchResults.setOnMouseClicked(e -> {
|
globalSearchScroll.getStylesheets().add(
|
||||||
int idx = chatSearchResults.getSelectionModel().getSelectedIndex();
|
getClass().getResource("/org/to/telegramfinalproject/CSS/scrollpane.css").toExternalForm()
|
||||||
if (idx >= 0 && idx < searchBacking.size()) {
|
);
|
||||||
openSearchResult(searchBacking.get(idx));
|
globalSearchScroll.setPannable(true);
|
||||||
}
|
globalSearchScroll.setFitToWidth(true);
|
||||||
|
globalSearchScroll.setFitToHeight(false);
|
||||||
|
globalSearchScroll.getContent().setOnScroll(event -> {
|
||||||
|
double deltaY = event.getDeltaY() * 0.003; // match chat list smoothness
|
||||||
|
globalSearchScroll.setVvalue(globalSearchScroll.getVvalue() - deltaY);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from ChatPageController when user clicks search button
|
// Called from ChatPageController when user clicks search button
|
||||||
@@ -255,12 +164,28 @@ public class MainController {
|
|||||||
scrollPane.setVisible(false);
|
scrollPane.setVisible(false);
|
||||||
scrollPane.setManaged(false);
|
scrollPane.setManaged(false);
|
||||||
|
|
||||||
|
currentSearchMode = SearchMode.CHAT;
|
||||||
|
|
||||||
chatSearchPane.setVisible(true);
|
chatSearchPane.setVisible(true);
|
||||||
chatSearchPane.setManaged(true);
|
chatSearchPane.setManaged(true);
|
||||||
|
|
||||||
searchBar.requestFocus();
|
searchBar.requestFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void closeSearchPanel() {
|
||||||
|
chatSearchPane.setVisible(false);
|
||||||
|
chatSearchPane.setManaged(false);
|
||||||
|
|
||||||
|
currentSearchMode = SearchMode.GLOBAL;
|
||||||
|
currentChatId = null;
|
||||||
|
|
||||||
|
scrollPane.setVisible(true);
|
||||||
|
scrollPane.setManaged(true);
|
||||||
|
|
||||||
|
searchBar.clear();
|
||||||
|
}
|
||||||
|
|
||||||
public void showGlobalSearchPanel() {
|
public void showGlobalSearchPanel() {
|
||||||
scrollPane.setVisible(false);
|
scrollPane.setVisible(false);
|
||||||
scrollPane.setManaged(false);
|
scrollPane.setManaged(false);
|
||||||
@@ -273,15 +198,14 @@ public class MainController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void closeSearchPanel() {
|
public void closeGlobalSearch() {
|
||||||
chatSearchPane.setVisible(false);
|
globalSearchPane.setVisible(false);
|
||||||
chatSearchPane.setManaged(false);
|
globalSearchPane.setManaged(false);
|
||||||
|
|
||||||
currentSearchMode = SearchMode.GLOBAL;
|
|
||||||
currentChatId = null;
|
|
||||||
|
|
||||||
scrollPane.setVisible(true);
|
scrollPane.setVisible(true);
|
||||||
scrollPane.setManaged(true);
|
scrollPane.setManaged(true);
|
||||||
|
|
||||||
|
searchBar.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void addSampleChats() {
|
// private void addSampleChats() {
|
||||||
@@ -387,11 +311,14 @@ public class MainController {
|
|||||||
|
|
||||||
String preview = chat.getLastMessagePreview() == null ? "" : chat.getLastMessagePreview();
|
String preview = chat.getLastMessagePreview() == null ? "" : chat.getLastMessagePreview();
|
||||||
String timeText = formatChatTime(chat.getLastMessageTime());
|
String timeText = formatChatTime(chat.getLastMessageTime());
|
||||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_item.fxml"));
|
|
||||||
Node chatItem = loader.load();
|
|
||||||
ChatItemController controller = loader.getController();
|
|
||||||
|
|
||||||
cc.setChatData(chat.getName(), preview, timeText, chat.getUnreadCount(), "/org/to/telegramfinalproject/Avatars/default_user_profile.png", chat.getType());
|
// If chat has a profile picture, pass it; otherwise null
|
||||||
|
String imageUrl = (chat.getImageUrl() != null && !chat.getImageUrl().isEmpty())
|
||||||
|
? chat.getImageUrl()
|
||||||
|
: null;
|
||||||
|
|
||||||
|
cc.setChatData(chat.getName(), preview, timeText, chat.getUnreadCount(), imageUrl, chat.getType());
|
||||||
|
|
||||||
item.setOnMouseClicked(e -> openChat(chat));
|
item.setOnMouseClicked(e -> openChat(chat));
|
||||||
chatListContainer.getChildren().add(item);
|
chatListContainer.getChildren().add(item);
|
||||||
|
|
||||||
@@ -434,7 +361,6 @@ public class MainController {
|
|||||||
ChatPageController controller = loader.getController();
|
ChatPageController controller = loader.getController();
|
||||||
controller.showChat(chat);
|
controller.showChat(chat);
|
||||||
|
|
||||||
currentSearchMode = SearchMode.CHAT;
|
|
||||||
currentChatId = UUID.fromString(chat.getId().toString());
|
currentChatId = UUID.fromString(chat.getId().toString());
|
||||||
|
|
||||||
chatDisplayArea.getChildren().setAll(chatPage);
|
chatDisplayArea.getChildren().setAll(chatPage);
|
||||||
@@ -669,7 +595,7 @@ public class MainController {
|
|||||||
|
|
||||||
showGlobalSearchPanel();
|
showGlobalSearchPanel();
|
||||||
|
|
||||||
// درخواست به سرور (مثل کنسول)
|
// Request to server
|
||||||
org.json.JSONObject req = new org.json.JSONObject();
|
org.json.JSONObject req = new org.json.JSONObject();
|
||||||
req.put("action", "search");
|
req.put("action", "search");
|
||||||
req.put("keyword", keyword);
|
req.put("keyword", keyword);
|
||||||
@@ -766,33 +692,61 @@ public class MainController {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
private void renderSearchResults(List<SearchResult> results) {
|
private void renderSearchResults(List<SearchResult> results) {
|
||||||
globalSearchResults.getItems().clear();
|
globalSearchResultsContainer.getChildren().clear();
|
||||||
|
|
||||||
if (results.isEmpty()) {
|
if (results.isEmpty()) {
|
||||||
noResultsBox.setVisible(true);
|
noResultsBox.setVisible(true);
|
||||||
noResultsBox.setManaged(true);
|
noResultsBox.setManaged(true);
|
||||||
globalSearchResults.setVisible(false);
|
globalSearchScroll.setVisible(false);
|
||||||
globalSearchResults.setManaged(false);
|
globalSearchScroll.setManaged(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
noResultsBox.setVisible(false);
|
noResultsBox.setVisible(false);
|
||||||
noResultsBox.setManaged(false);
|
noResultsBox.setManaged(false);
|
||||||
globalSearchResults.setVisible(true);
|
globalSearchScroll.setVisible(true);
|
||||||
globalSearchResults.setManaged(true);
|
globalSearchScroll.setManaged(true);
|
||||||
|
|
||||||
globalSearchResults.getItems().addAll(results);
|
for (SearchResult r : results) {
|
||||||
|
HBox container = new HBox(10);
|
||||||
|
ImageView avatar = new ImageView();
|
||||||
|
avatar.setFitWidth(40);
|
||||||
|
avatar.setFitHeight(40);
|
||||||
|
avatar.setSmooth(true);
|
||||||
|
avatar.setPreserveRatio(true);
|
||||||
|
|
||||||
|
// 🔑 Clip it into a circle
|
||||||
|
Circle clip = new Circle(20, 20, 20); // x,y = center, radius = 20
|
||||||
|
avatar.setClip(clip);
|
||||||
|
|
||||||
|
Label title = new Label(r.title);
|
||||||
|
title.getStyleClass().add("global-search-title");
|
||||||
|
|
||||||
|
Label subtitle = new Label(
|
||||||
|
r.type == SRType.MESSAGE
|
||||||
|
? (r.subtitle != null ? r.subtitle : "")
|
||||||
|
: "Press to see messages"
|
||||||
|
);
|
||||||
|
subtitle.getStyleClass().add("global-search-subtitle");
|
||||||
|
|
||||||
|
VBox texts = new VBox(2, title, subtitle);
|
||||||
|
container.getChildren().addAll(avatar, texts);
|
||||||
|
|
||||||
|
// Default profile per type
|
||||||
|
switch (r.type) {
|
||||||
|
case USER -> avatar.setImage(new Image(Objects.requireNonNull(getClass().getResourceAsStream(
|
||||||
|
"/org/to/telegramfinalproject/Avatars/default_user_profile.png"))));
|
||||||
|
case GROUP -> avatar.setImage(new Image(Objects.requireNonNull(getClass().getResourceAsStream(
|
||||||
|
"/org/to/telegramfinalproject/Avatars/default_group_profile.png"))));
|
||||||
|
case CHANNEL -> avatar.setImage(new Image(Objects.requireNonNull(getClass().getResourceAsStream(
|
||||||
|
"/org/to/telegramfinalproject/Avatars/default_channel_profile.png"))));
|
||||||
|
case MESSAGE -> avatar.setImage(new Image(Objects.requireNonNull(getClass().getResourceAsStream(
|
||||||
|
"/org/to/telegramfinalproject/Avatars/default_user_profile.png"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
container.setOnMouseClicked(e -> openSearchResult(r));
|
||||||
public void closeGlobalSearch() {
|
globalSearchResultsContainer.getChildren().add(container);
|
||||||
globalSearchPane.setVisible(false);
|
}
|
||||||
globalSearchPane.setManaged(false);
|
|
||||||
|
|
||||||
scrollPane.setVisible(true);
|
|
||||||
scrollPane.setManaged(true);
|
|
||||||
|
|
||||||
searchBar.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openSearchResult(SearchResult r) {
|
private void openSearchResult(SearchResult r) {
|
||||||
|
|||||||
@@ -44,10 +44,14 @@
|
|||||||
</graphic>
|
</graphic>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
<HBox spacing="5" alignment="CENTER" HBox.hgrow="ALWAYS">
|
||||||
<TextField fx:id="searchBar"
|
<TextField fx:id="searchBar"
|
||||||
prefHeight="36" prefWidth="430.0"
|
|
||||||
promptText="Search"
|
promptText="Search"
|
||||||
|
HBox.hgrow="ALWAYS"
|
||||||
|
maxWidth="Infinity"
|
||||||
styleClass="global-search"/>
|
styleClass="global-search"/>
|
||||||
|
</HBox>
|
||||||
|
|
||||||
</children>
|
</children>
|
||||||
</HBox>
|
</HBox>
|
||||||
|
|
||||||
@@ -104,8 +108,36 @@
|
|||||||
<Button text="✕" onAction="#closeGlobalSearch" styleClass="search-close-btn"/>
|
<Button text="✕" onAction="#closeGlobalSearch" styleClass="search-close-btn"/>
|
||||||
</HBox>
|
</HBox>
|
||||||
|
|
||||||
<!-- Results -->
|
<!-- Search results -->
|
||||||
<ListView fx:id="globalSearchResults" styleClass="global-search-list"/>
|
<ScrollPane fx:id="globalSearchScroll"
|
||||||
|
fitToWidth="true"
|
||||||
|
hbarPolicy="NEVER"
|
||||||
|
vbarPolicy="AS_NEEDED"
|
||||||
|
styleClass="chat-scroll">
|
||||||
|
<content>
|
||||||
|
<VBox fx:id="globalSearchResultsContainer" spacing="5"
|
||||||
|
styleClass="global-search-list">
|
||||||
|
<!-- One search result item -->
|
||||||
|
<HBox spacing="10" alignment="CENTER_LEFT" styleClass="search-result-item">
|
||||||
|
<!-- Avatar -->
|
||||||
|
<StackPane>
|
||||||
|
<ImageView fx:id="searchResultAvatar"
|
||||||
|
fitWidth="40" fitHeight="40"
|
||||||
|
preserveRatio="true"
|
||||||
|
smooth="true"
|
||||||
|
cache="true"
|
||||||
|
styleClass="avatar"/>
|
||||||
|
</StackPane>
|
||||||
|
|
||||||
|
<!-- Texts -->
|
||||||
|
<VBox spacing="2">
|
||||||
|
<Label fx:id="searchResultTitle" styleClass="global-search-title"/>
|
||||||
|
<Label fx:id="searchResultSubtitle" styleClass="global-search-subtitle"/>
|
||||||
|
</VBox>
|
||||||
|
</HBox>
|
||||||
|
</VBox>
|
||||||
|
</content>
|
||||||
|
</ScrollPane>
|
||||||
|
|
||||||
<!-- No Results Placeholder -->
|
<!-- No Results Placeholder -->
|
||||||
<VBox fx:id="noResultsBox" alignment="CENTER" spacing="10" visible="false" managed="false">
|
<VBox fx:id="noResultsBox" alignment="CENTER" spacing="10" visible="false" managed="false">
|
||||||
|
|||||||
Reference in New Issue
Block a user