From f19bcba62a706933bb679d315edd82bf39a17e6c Mon Sep 17 00:00:00 2001 From: Jaidyn Ann Date: Fri, 27 Aug 2021 10:57:20 -0500 Subject: [PATCH] Add Room Directory window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This window (Chat→Room directory) is to be used for either a list of publicly available rooms (in most protocols), or for a list of joined-but-hidden rooms (as it'll used with libpurple, to list its ChatBuddies). Each room is sent individually from protocols using IM_ROOM_DIRECTORY messages sent in response to a IM_GET_ROOM_DIRECTORY message. --- application/AppMessages.h | 3 + application/Makefile | 8 +- application/preferences/AppPreferences.cpp | 2 + application/preferences/AppPreferences.h | 1 + application/views/RoomListRow.cpp | 28 +++++ application/views/RoomListRow.h | 31 +++++ application/windows/MainWindow.cpp | 13 ++ application/windows/MainWindow.h | 2 - application/windows/RoomListWindow.cpp | 134 +++++++++++++++++++++ application/windows/RoomListWindow.h | 35 ++++++ protocols/irc/IrcConstants.h | 2 + protocols/irc/IrcProtocol.cpp | 3 + 12 files changed, 258 insertions(+), 4 deletions(-) create mode 100644 application/views/RoomListRow.cpp create mode 100644 application/views/RoomListRow.h create mode 100644 application/windows/RoomListWindow.cpp create mode 100644 application/windows/RoomListWindow.h diff --git a/application/AppMessages.h b/application/AppMessages.h index fc7a210..7d2751d 100644 --- a/application/AppMessages.h +++ b/application/AppMessages.h @@ -23,6 +23,9 @@ const uint32 APP_NEW_ROOM = 'CYnr'; //! Join a chat const uint32 APP_JOIN_ROOM = 'CYjr'; +//! Room directory +const uint32 APP_ROOM_DIRECTORY = 'CYrd'; + //! Invite user to current chat const uint32 APP_SEND_INVITE = 'CYin'; diff --git a/application/Makefile b/application/Makefile index aed7818..360b47e 100644 --- a/application/Makefile +++ b/application/Makefile @@ -64,6 +64,7 @@ SRCS = \ application/views/InviteDialogue.cpp \ application/views/ReplicantStatusView.cpp \ application/views/ReplicantMenuItem.cpp \ + application/views/RoomListRow.cpp \ application/views/RosterItem.cpp \ application/views/RosterListView.cpp \ application/views/RosterView.cpp \ @@ -79,6 +80,7 @@ SRCS = \ application/windows/ConversationInfoWindow.cpp \ application/windows/MainWindow.cpp \ application/windows/PreferencesWindow.cpp \ + application/windows/RoomListWindow.cpp \ application/windows/RosterEditWindow.cpp \ application/windows/RosterWindow.cpp \ application/windows/TemplateWindow.cpp \ @@ -130,7 +132,7 @@ RSRCS = # - if your library does not follow the standard library naming scheme, # you need to specify the path to the library and it's name. # (e.g. for mylib.a, specify "mylib.a" or "path/mylib.a") -LIBS = be expat interface localestub runview shared translation $(STDCPPLIBS) +LIBS = be columnlistview expat interface localestub runview shared translation $(STDCPPLIBS) # Specify additional paths to directories following the standard libXXX.so @@ -143,7 +145,9 @@ LIBPATHS = # Additional paths to look for system headers. These use the form # "#include
". Directories that contain the files in SRCS are # NOT auto-included here. -SYSTEM_INCLUDE_PATHS = libs/ +SYSTEM_INCLUDE_PATHS = libs/ \ + $(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/interface) + # Additional paths paths to look for local headers. These use the form # #include "header". Directories that contain the files in SRCS are diff --git a/application/preferences/AppPreferences.cpp b/application/preferences/AppPreferences.cpp index 8bcbca4..ecb8fe1 100644 --- a/application/preferences/AppPreferences.cpp +++ b/application/preferences/AppPreferences.cpp @@ -56,6 +56,7 @@ AppPreferences::Load() ChatViewVertSendWeight = settings.GetFloat("ChatViewVertSendWeight", 1); MainWindowRect = settings.GetRect("MainWindowRect", BRect(0, 0, 600, 400)); + RoomDirectoryRect = settings.GetRect("RoomDirectoryRect", BRect(0, 0, 630, 330)); } @@ -89,6 +90,7 @@ AppPreferences::Save() settings.AddFloat("ChatViewVertSendWeight", ChatViewVertSendWeight); settings.AddRect("MainWindowRect", MainWindowRect); + settings.AddRect("RoomDirectoryRect", RoomDirectoryRect); if (file.InitCheck() == B_OK) settings.Flatten(&file); diff --git a/application/preferences/AppPreferences.h b/application/preferences/AppPreferences.h index f868764..f0b0078 100644 --- a/application/preferences/AppPreferences.h +++ b/application/preferences/AppPreferences.h @@ -45,6 +45,7 @@ public: float ChatViewVertSendWeight; BRect MainWindowRect; + BRect RoomDirectoryRect; private: const char* _PreferencesPath(); diff --git a/application/views/RoomListRow.cpp b/application/views/RoomListRow.cpp new file mode 100644 index 0000000..617da7a --- /dev/null +++ b/application/views/RoomListRow.cpp @@ -0,0 +1,28 @@ +/* + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#include "RoomListRow.h" + +#include + + +RoomListRow::RoomListRow(BMessage* msg) + : + BRow(), + fMessage(new BMessage(*msg)), + fInstance(-1) +{ + int64 proto = msg->FindInt64("instance"); + BString id = msg->FindString("chat_id"); + BString name = msg->GetString("chat_name", id); + BString desc = msg->FindString("subject"); + int32 user_n = msg->GetInt32("user_count", -1); + + SetField(new BStringField(name), kNameColumn); + SetField(new BStringField(desc), kDescColumn); + SetField(new BStringField(id), kIdColumn); + if (user_n > -1) + SetField(new BIntegerField(user_n), kUserColumn); +} diff --git a/application/views/RoomListRow.h b/application/views/RoomListRow.h new file mode 100644 index 0000000..aedb378 --- /dev/null +++ b/application/views/RoomListRow.h @@ -0,0 +1,31 @@ +/* + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef _ROOM_LIST_ROW_H +#define _ROOM_LIST_ROW_H + +#include + + +enum { + kNameColumn, + kDescColumn, + kIdColumn, + kUserColumn +}; + + +class RoomListRow : public BRow { +public: + RoomListRow(BMessage* msg); + + BMessage* Message() { return fMessage; } + int64 Instance() { return fInstance; } + +private: + int64 fInstance; + BMessage* fMessage; +}; + +#endif // _ROOM_LIST_ROW_H diff --git a/application/windows/MainWindow.cpp b/application/windows/MainWindow.cpp index b5dfb5e..321861c 100644 --- a/application/windows/MainWindow.cpp +++ b/application/windows/MainWindow.cpp @@ -35,6 +35,7 @@ #include "ProtocolManager.h" #include "ProtocolSettings.h" #include "ReplicantStatusView.h" +#include "RoomListWindow.h" #include "RosterEditWindow.h" #include "RosterWindow.h" #include "StatusManager.h" @@ -205,6 +206,11 @@ MainWindow::MessageReceived(BMessage* message) fRosterWindow->Show(); break; } + case APP_ROOM_DIRECTORY: + { + RoomListWindow::Get(fServer)->Show(); + break; + } case APP_EDIT_ROSTER: { RosterEditWindow::Get(fServer)->Show(); @@ -325,6 +331,10 @@ MainWindow::ImMessage(BMessage* msg) fListView->AddAccount(msg->GetInt64("instance", -1)); break; } + case IM_ROOM_DIRECTORY: + if (RoomListWindow::Check() == true) + RoomListWindow::Get(fServer)->PostMessage(msg); + break; case IM_PROTOCOL_DISABLE: fStatusView->MessageReceived(msg); break; @@ -513,6 +523,9 @@ MainWindow::_CreateMenuBar() new BMessage(APP_NEW_ROOM), 'N', B_COMMAND_KEY)); chatMenu->AddItem(new BMenuItem(B_TRANSLATE("New chat" B_UTF8_ELLIPSIS), new BMessage(APP_NEW_CHAT), 'M', B_COMMAND_KEY)); + chatMenu->AddSeparatorItem(); + chatMenu->AddItem(new BMenuItem(B_TRANSLATE("Room directory" B_UTF8_ELLIPSIS), + new BMessage(APP_ROOM_DIRECTORY))); chatMenu->SetTargetForItems(this); // Roster diff --git a/application/windows/MainWindow.h b/application/windows/MainWindow.h index e472320..f0e5e71 100644 --- a/application/windows/MainWindow.h +++ b/application/windows/MainWindow.h @@ -21,7 +21,6 @@ class ConversationListView; class ConversationView; class ProtocolSettings; class RosterItem; -class RosterEditWindow; class RosterWindow; class Server; class StatusView; @@ -65,7 +64,6 @@ private: Server* fServer; RosterWindow* fRosterWindow; - RosterEditWindow* fRosterEditWindow; bool fWorkspaceChanged; BMenuBar* fMenuBar; diff --git a/application/windows/RoomListWindow.cpp b/application/windows/RoomListWindow.cpp new file mode 100644 index 0000000..1789200 --- /dev/null +++ b/application/windows/RoomListWindow.cpp @@ -0,0 +1,134 @@ +/* + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#include "RoomListWindow.h" + +#include +#include +#include +#include +#include +#include + +#include "AppPreferences.h" +#include "ChatProtocolMessages.h" +#include "RoomListRow.h" +#include "Server.h" + + +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "Room directory" + + +const uint32 kJoinRoom = 'join'; +RoomListWindow* RoomListWindow::fInstance = NULL; + + +RoomListWindow::RoomListWindow(Server* server) + : + BWindow(AppPreferences::Get()->RoomDirectoryRect, + B_TRANSLATE("Room directory"), B_FLOATING_WINDOW, + B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS), + fServer(server) +{ + _InitInterface(); + CenterOnScreen(); + + BMessage* request = new BMessage(IM_MESSAGE); + request->AddInt32("im_what", IM_GET_ROOM_DIRECTORY); + server->SendAllProtocolMessage(request); +} + + +RoomListWindow::~RoomListWindow() +{ + fInstance = NULL; + AppPreferences::Get()->RoomDirectoryRect = Bounds(); +} + + +RoomListWindow* +RoomListWindow::Get(Server* server) +{ + if (fInstance == NULL) { + fInstance = new RoomListWindow(server); + } + return fInstance; +} + + +bool +RoomListWindow::Check() +{ + return (fInstance != NULL); +} + + +void +RoomListWindow::MessageReceived(BMessage* msg) +{ + switch (msg->what) { + case IM_MESSAGE: + { + if (msg->GetInt32("im_what", -1) != IM_ROOM_DIRECTORY) + break; + + int64 instance; + BString id; + if (msg->FindInt64("instance", &instance) == B_OK + && msg->FindString("chat_id", &id) == B_OK) + fListView->AddRow(new RoomListRow(msg)); + break; + } + case kJoinRoom: + { + RoomListRow* row = + (RoomListRow*)fListView->CurrentSelection(); + + if (row != NULL) { + BMessage* joinMsg = row->Message(); + joinMsg->ReplaceInt32("im_what", IM_JOIN_ROOM); + fServer->SendProtocolMessage(joinMsg); + Quit(); + } + break; + } + default: + BWindow::MessageReceived(msg); + } +} + + +void +RoomListWindow::_InitInterface() +{ + float size = BFont().Size(); + BStringColumn* name = new BStringColumn(B_TRANSLATE("Name"), 130, 50, 300, + B_TRUNCATE_END); + BStringColumn* desc = new BStringColumn(B_TRANSLATE("Description"), 270, + 50, 5000, B_TRUNCATE_END); + BStringColumn* id = new BStringColumn("ID", 90, 50, 300, B_TRUNCATE_END); + BIntegerColumn* users = new BIntegerColumn("Users", 70, 10, 300); + + fListView = new BColumnListView("roomList", B_NAVIGABLE, B_PLAIN_BORDER); + fListView->SetInvocationMessage(new BMessage(kJoinRoom)); + fListView->SetSelectionMode(B_SINGLE_SELECTION_LIST); + fListView->AddColumn(name, kNameColumn); + fListView->AddColumn(desc, kDescColumn); + fListView->AddColumn(id, kIdColumn); + fListView->AddColumn(users, kUserColumn); + + fJoinButton = new BButton("joinRoom", B_TRANSLATE("Join"), + new BMessage(kJoinRoom)); + + BLayoutBuilder::Group<>(this, B_VERTICAL) + .SetInsets(B_USE_DEFAULT_SPACING) + .Add(fListView) + .AddGroup(B_HORIZONTAL) + .AddGlue() + .Add(fJoinButton) + .End() + .End(); +} diff --git a/application/windows/RoomListWindow.h b/application/windows/RoomListWindow.h new file mode 100644 index 0000000..eb440fb --- /dev/null +++ b/application/windows/RoomListWindow.h @@ -0,0 +1,35 @@ +/* + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef _ROOM_LIST_WINDOW_H +#define _ROOM_LIST_WINDOW_H + +#include + +class BButton; +class BColumnListView; +class Server; + + +class RoomListWindow : public BWindow { +public: + RoomListWindow(Server* server); + ~RoomListWindow(); + + static RoomListWindow* Get(Server* server); + static bool Check(); + + virtual void MessageReceived(BMessage* msg); + +private: + void _InitInterface(); + + BButton* fJoinButton; + BColumnListView* fListView; + + Server* fServer; + static RoomListWindow* fInstance; +}; + +#endif // _ROOM_LIST_WINDOW_H diff --git a/protocols/irc/IrcConstants.h b/protocols/irc/IrcConstants.h index 142af01..c84a06a 100644 --- a/protocols/irc/IrcConstants.h +++ b/protocols/irc/IrcConstants.h @@ -41,6 +41,8 @@ enum UserRole { #define RPL_WHOISUSER 311 #define RPL_ENDOFWHO 315 #define RPL_ENDOFWHOIS 318 +#define RPL_LIST 322 +#define RPL_LISTEND 323 #define RPL_TOPIC 332 #define RPL_WHOREPLY 352 #define RPL_NAMREPLY 353 diff --git a/protocols/irc/IrcProtocol.cpp b/protocols/irc/IrcProtocol.cpp index 10b01bb..32cb70f 100644 --- a/protocols/irc/IrcProtocol.cpp +++ b/protocols/irc/IrcProtocol.cpp @@ -660,6 +660,9 @@ IrcProtocol::_ProcessNumeric(int32 numeric, BString sender, BStringList params, _SendMsg(&send); break; } + case RPL_LIST: + if (fListRequested == false) + break; case RPL_WHOREPLY: if (fWhoRequested == false) break;