Skip to content

Commit

Permalink
Allow to get information on identities from chat and forums
Browse files Browse the repository at this point in the history
  • Loading branch information
zapek committed Oct 15, 2024
1 parent aade068 commit a105f79
Show file tree
Hide file tree
Showing 17 changed files with 127 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,12 @@ public void deleteOwnIdentityImage(long id)
saveIdentity(identity, true);
}

@Override
public void shutdown()
{
contactNotificationService.shutdown();
}

static Sha1Sum makeProfileHash(GxsId gxsId, ProfileFingerprint fingerprint)
{
var gxsIdAsciiUpper = Id.toAsciiBytes(gxsId);
Expand Down
13 changes: 13 additions & 0 deletions ui/src/main/java/io/xeres/ui/client/IdentityClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import io.xeres.common.dto.identity.IdentityDTO;
import io.xeres.common.events.StartupEvent;
import io.xeres.common.id.GxsId;
import io.xeres.common.util.RemoteUtils;
import io.xeres.ui.model.identity.Identity;
import io.xeres.ui.model.identity.IdentityMapper;
Expand Down Expand Up @@ -75,6 +76,18 @@ public Mono<Identity> findById(long id)
.map(IdentityMapper::fromDTO);
}

public Flux<Identity> findByGxsId(GxsId gxsId)
{
return webClient.get()
.uri(uriBuilder -> uriBuilder
.path("")
.queryParam("gxsId", gxsId.toString())
.build())
.retrieve()
.bodyToFlux(IdentityDTO.class)
.map(IdentityMapper::fromDTO);
}

public Mono<Void> uploadIdentityImage(long id, File file)
{
return webClient.post()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@
import io.xeres.ui.custom.led.LedControl;
import io.xeres.ui.custom.led.LedStatus;
import io.xeres.ui.support.tray.TrayService;
import io.xeres.ui.support.uri.ChatRoomUri;
import io.xeres.ui.support.uri.ForumUri;
import io.xeres.ui.support.uri.SearchUri;
import io.xeres.ui.support.uri.UriService;
import io.xeres.ui.support.uri.*;
import io.xeres.ui.support.util.TooltipUtils;
import io.xeres.ui.support.util.UiUtils;
import io.xeres.ui.support.window.WindowManager;
Expand Down Expand Up @@ -550,6 +547,7 @@ public void handleOpenUriEvents(OpenUriEvent event)
case ChatRoomUri ignored -> tabPane.getSelectionModel().select(chatTab);
case ForumUri ignored -> tabPane.getSelectionModel().select(forumTab);
case SearchUri ignored -> tabPane.getSelectionModel().select(fileTab);
case IdentityUri ignored -> tabPane.getSelectionModel().select(contactTab);
default ->
{
// Nothing to do
Expand Down
26 changes: 26 additions & 0 deletions ui/src/main/java/io/xeres/ui/controller/chat/ChatListView.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,16 @@
import io.xeres.ui.support.chat.NicknameCompleter;
import io.xeres.ui.support.contentline.Content;
import io.xeres.ui.support.contentline.ContentImage;
import io.xeres.ui.support.contextmenu.XContextMenu;
import io.xeres.ui.support.markdown.MarkdownService;
import io.xeres.ui.support.markdown.MarkdownService.ParsingMode;
import io.xeres.ui.support.markdown.UriAction;
import io.xeres.ui.support.uri.IdentityUri;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.control.ListView;
import javafx.scene.control.MenuItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
Expand All @@ -45,6 +48,8 @@
import org.fxmisc.flowless.VirtualFlow;
import org.fxmisc.flowless.VirtualizedScrollPane;
import org.jsoup.Jsoup;
import org.kordamp.ikonli.fontawesome5.FontAwesomeSolid;
import org.kordamp.ikonli.javafx.FontIcon;

import java.io.ByteArrayInputStream;
import java.time.Instant;
Expand All @@ -63,6 +68,8 @@ public class ChatListView implements NicknameCompleter.UsernameFinder
private static final int SCROLL_BACK_MAX_LINES = 2000;
private static final int SCROLL_BACK_CLEANUP_THRESHOLD = 100;

private static final String INFO_MENU_ID = "info";

private final ObservableList<ChatLine> messages = FXCollections.observableArrayList();
private final Map<GxsId, ChatRoomUser> userMap = new HashMap<>();
private final ObservableList<ChatRoomUser> users = FXCollections.observableArrayList();
Expand Down Expand Up @@ -109,6 +116,8 @@ private ListView<ChatRoomUser> createUserListView()

view.setCellFactory(param -> new ChatUserCell());
view.setItems(users);

createUsersListViewContextMenu(view);
return view;
}

Expand Down Expand Up @@ -336,4 +345,21 @@ private void trimScrollBackIfNeeded()
messages.remove(0, SCROLL_BACK_CLEANUP_THRESHOLD);
}
}

private void createUsersListViewContextMenu(Node view)
{
var infoItem = new MenuItem("Information");
infoItem.setId(INFO_MENU_ID);
infoItem.setGraphic(new FontIcon(FontAwesomeSolid.INFO_CIRCLE));
infoItem.setOnAction(event -> {
var user = (ChatRoomUser) event.getSource();
if (user.gxsId() != null)
{
uriAction.openUri(new IdentityUri(user.nickname(), user.gxsId(), null));
}
});

var xContextMenu = new XContextMenu<ChatRoomUser>(infoItem);
xContextMenu.addToNode(view);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,9 @@ private void createRoomTreeContextMenu()
Clipboard.getSystemClipboard().setContent(clipboardContent);
});

var roomHolderXContextMenu = new XContextMenu<RoomHolder>(roomTree, subscribeItem, unsubscribeItem, new SeparatorMenuItem(), copyLinkItem);
roomHolderXContextMenu.setOnShowing((contextMenu, roomHolder) -> {
var xContextMenu = new XContextMenu<RoomHolder>(subscribeItem, unsubscribeItem, new SeparatorMenuItem(), copyLinkItem);
xContextMenu.addToNode(roomTree);
xContextMenu.setOnShowing((contextMenu, roomHolder) -> {
var chatRoomInfo = roomHolder.getRoomInfo();

contextMenu.getItems().stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
import io.xeres.common.rest.contact.Contact;
import io.xeres.common.rest.notification.contact.AddContacts;
import io.xeres.common.rest.notification.contact.RemoveContacts;
import io.xeres.ui.OpenUriEvent;
import io.xeres.ui.client.*;
import io.xeres.ui.controller.Controller;
import io.xeres.ui.custom.AsyncImageView;
import io.xeres.ui.model.location.Location;
import io.xeres.ui.support.uri.IdentityUri;
import io.xeres.ui.support.util.DateUtils;
import io.xeres.ui.support.util.UiUtils;
import javafx.application.Platform;
Expand Down Expand Up @@ -61,6 +63,7 @@

import static io.xeres.common.rest.PathConfig.IDENTITIES_PATH;
import static io.xeres.ui.support.util.DateUtils.DATE_TIME_DISPLAY;
import static javafx.scene.control.Alert.AlertType.WARNING;

@Component
@FxmlView(value = "/view/contact/contactview.fxml")
Expand Down Expand Up @@ -452,4 +455,26 @@ public void onApplicationEvent(ContextClosedEvent ignored)
notificationDisposable.dispose();
}
}

@EventListener
public void handleOpenUriEvent(OpenUriEvent event)
{
if (event.uri() instanceof IdentityUri identityUri)
{
identityClient.findByGxsId(identityUri.id()).collectList()
.doOnSuccess(identities -> {
if (!identities.isEmpty())
{
Platform.runLater(() -> contactTableView.getItems().stream()
.filter(contact -> contact.identityId() == identities.getFirst().getId())
.findFirst()
.ifPresentOrElse(contact -> {
contactTableView.getSelectionModel().select(contact);
contactTableView.scrollTo(contact);
}, () -> UiUtils.alert(WARNING, "Contact not found")));
}
})
.subscribe();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ private void createPropertiesTableViewContextMenu()
Clipboard.getSystemClipboard().setContent(clipboardContent);
}
});
new XContextMenu<Map.Entry<String, String>>(propertiesTableView, copyItem);
var xContextMenu = new XContextMenu<Map.Entry<String, String>>(copyItem);
xContextMenu.addToNode(propertiesTableView);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,9 @@ private void createContextMenu()
}
});

var fileXContextMenu = new XContextMenu<FileProgressDisplay>(downloadTableView, openItem, showInExplorerItem, new SeparatorMenuItem(), removeItem);
fileXContextMenu.setOnShowing((contextMenu, file) -> {
var xContextMenu = new XContextMenu<FileProgressDisplay>(openItem, showInExplorerItem, new SeparatorMenuItem(), removeItem);
xContextMenu.addToNode(downloadTableView);
xContextMenu.setOnShowing((contextMenu, file) -> {
if (file == null)
{
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,9 @@ private void createFilesTableViewContextMenu()
}
});

var fileXContextMenu = new XContextMenu<FileResult>(filesTableView, downloadItem, new SeparatorMenuItem(), copyLinkItem);
fileXContextMenu.setOnShowing((contextMenu, file) -> file != null);
var xContextMenu = new XContextMenu<FileResult>(downloadItem, new SeparatorMenuItem(), copyLinkItem);
xContextMenu.addToNode(filesTableView);
xContextMenu.setOnShowing((contextMenu, file) -> file != null);
}

private void showProgress()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ private void createContextMenu()
Clipboard.getSystemClipboard().setContent(clipboardContent);
});

var xContextMenu = new XContextMenu<Tab>(resultTabPane, copyLinkItem);
var xContextMenu = new XContextMenu<Tab>(copyLinkItem);
xContextMenu.addToNode(resultTabPane);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import io.xeres.common.i18n.I18nUtils;
import io.xeres.common.id.GxsId;
import io.xeres.common.id.Id;
import io.xeres.common.id.MessageId;
import io.xeres.common.message.forum.ForumGroup;
Expand All @@ -40,6 +41,7 @@
import io.xeres.ui.support.markdown.MarkdownService.ParsingMode;
import io.xeres.ui.support.uri.ForumUri;
import io.xeres.ui.support.uri.ForumUriFactory;
import io.xeres.ui.support.uri.IdentityUri;
import io.xeres.ui.support.uri.UriService;
import io.xeres.ui.support.util.UiUtils;
import io.xeres.ui.support.window.WindowManager;
Expand Down Expand Up @@ -291,8 +293,9 @@ private void createForumTreeContextMenu()
Clipboard.getSystemClipboard().setContent(clipboardContent);
});

var forumGroupXContextMenu = new XContextMenu<ForumGroup>(forumTree, subscribeItem, unsubscribeItem, new SeparatorMenuItem(), copyLinkItem);
forumGroupXContextMenu.setOnShowing((contextMenu, forumGroup) -> {
var xContextMenu = new XContextMenu<ForumGroup>(subscribeItem, unsubscribeItem, new SeparatorMenuItem(), copyLinkItem);
xContextMenu.addToNode(forumTree);
xContextMenu.setOnShowing((contextMenu, forumGroup) -> {
contextMenu.getItems().stream()
.filter(menuItem -> SUBSCRIBE_MENU_ID.equals(menuItem.getId()))
.findFirst().ifPresent(menuItem -> menuItem.setDisable(forumGroup.isSubscribed()));
Expand Down Expand Up @@ -321,7 +324,8 @@ private void createForumMessageTableViewContextMenu()
Clipboard.getSystemClipboard().setContent(clipboardContent);
});

new XContextMenu<ForumMessage>(forumMessagesTreeTableView, replyItem, new SeparatorMenuItem(), copyLinkItem);
var xContextMenu = new XContextMenu<ForumMessage>(replyItem, new SeparatorMenuItem(), copyLinkItem);
xContextMenu.addToNode(forumMessagesTreeTableView);
}

private void newForumPost(boolean replyTo)
Expand Down Expand Up @@ -538,6 +542,7 @@ private void changeSelectedForumMessage(ForumMessage forumMessage)
messageContent.getChildren().addAll(contents.stream()
.map(Content::getNode).toList());
messageAuthor.setText(forumMessage.getAuthorName());
createAuthorContextMenu(forumMessage.getAuthorName(), forumMessage.getAuthorId());
messageDate.setText(DATE_TIME_PRECISE_DISPLAY.format(forumMessage.getPublished()));
messageSubject.setText(forumMessage.getName());
messageHeader.setVisible(true);
Expand All @@ -560,6 +565,7 @@ private void clearMessage()
{
messageHeader.setVisible(false);
messageAuthor.setText(null);
messageAuthor.setContextMenu(null);
messageDate.setText(null);
messageSubject.setText(null);
messageContent.getChildren().clear();
Expand Down Expand Up @@ -589,4 +595,12 @@ public void onApplicationEvent(ContextClosedEvent ignored)
notificationDisposable.dispose();
}
}

private void createAuthorContextMenu(String name, GxsId gxsId)
{
var infoItem = new MenuItem("Information");
infoItem.setGraphic(new FontIcon(FontAwesomeSolid.INFO_CIRCLE));
infoItem.setOnAction(event -> uriService.openUri(new IdentityUri(name, gxsId, null)));
messageAuthor.setContextMenu(new ContextMenu(infoItem));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ private void createPeersTreeContextMenu()
directMessage.setGraphic(new FontIcon(FontAwesomeSolid.COMMENT_DOTS));
directMessage.setOnAction(event -> directMessage(((PeerHolder) event.getSource())));

new XContextMenu<PeerHolder>(peersTree, directMessage);
var xContextMenu = new XContextMenu<PeerHolder>(directMessage);
xContextMenu.addToNode(peersTree);
}

private void directMessage(PeerHolder peerHolder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ private void createProfilesTableViewContextMenu()
}
});

var profileXContextMenu = new XContextMenu<Profile>(profilesTableView, deleteItem);
profileXContextMenu.setOnShowing((contextMenu, profile) -> profile != null && profile.getId() != OWN_PROFILE_ID);
var xContextMenu = new XContextMenu<Profile>(deleteItem);
xContextMenu.setOnShowing((contextMenu, profile) -> profile != null && profile.getId() != OWN_PROFILE_ID);
xContextMenu.addToNode(profilesTableView);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,9 @@ private void createShareTableViewContextMenu()
}
});

var tableShareXContextMenu = new XContextMenu<Share>(shareTableView, showInExplorerItem, new SeparatorMenuItem(), removeItem);
tableShareXContextMenu.setOnShowing((contextMenu, share) -> {
var xContextMenu = new XContextMenu<Share>(showInExplorerItem, new SeparatorMenuItem(), removeItem);
xContextMenu.addToNode(shareTableView);
xContextMenu.setOnShowing((contextMenu, share) -> {
contextMenu.getItems().stream()
.filter(menuItem -> REMOVE_MENU_ID.equals(menuItem.getId()))
.findFirst().ifPresent(menuItem -> menuItem.setDisable(share.getId() == INCOMING_SHARE));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public class XContextMenu<T>
private final ContextMenu contextMenu;
private boolean showContextMenu = true;

public XContextMenu(Control node, MenuItem... menuItems)
public XContextMenu(MenuItem... menuItems)
{
EventHandler<ActionEvent> action = event -> {
var selectedMenuItem = (MenuItem) event.getTarget();
Expand All @@ -67,6 +67,16 @@ public XContextMenu(Control node, MenuItem... menuItems)
}

contextMenu = new ContextMenu(menuItems);
}

/**
* Attaches the context menu to a node. Must be called otherwise there's not
* much point in creating a context menu.
*
* @param node the node to attach the context menu to
*/
public void addToNode(Node node)
{
node.setOnContextMenuRequested(event -> {
// Using event.getSource() instead of the context menu itself (the default with setContextMenu())
// allows to find out on which node the context menu was activated.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ public Content create(UriComponents uriComponents, String text, UriAction uriAct
var name = uriComponents.getQueryParams().getFirst(PARAMETER_NAME);
var groupData = uriComponents.getQueryParams().getFirst(PARAMETER_GROUPDATA);

if (Stream.of(gxsId, name, groupData).anyMatch(StringUtils::isBlank))
if (Stream.of(gxsId, name).anyMatch(StringUtils::isBlank))
{
return ContentText.EMPTY;
}

var identityUri = new IdentityUri(name, GxsId.fromString(gxsId), groupData); // XXX: groupData is probably something else...
var identityUri = new IdentityUri(name, GxsId.fromString(gxsId), groupData); // groupData contains the gxs group's data so that the peer can do something with it even if it doesn't have the group yet

return new ContentUri(groupData, "Identity (name=" + name + ", ID=" + gxsId + ")", uri -> uriAction.openUri(identityUri));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ public void handleOpenUriEvents(OpenUriEvent event)
{
// Nothing to do. This is handled in SearchViewController
}
case IdentityUri ignored ->
{
// Nothing to do. This is handled in ContactViewController
}
default -> UiUtils.alert(WARNING, "The link for '" + event.uri().getClass().getSimpleName().replace("Uri", "") + "' is not supported yet.");
}
}
Expand Down

0 comments on commit a105f79

Please sign in to comment.