Add Room Directory window

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.
This commit is contained in:
Jaidyn Ann 2021-08-27 10:57:20 -05:00
parent 5dbbb3a8ad
commit f19bcba62a
12 changed files with 258 additions and 4 deletions

View File

@ -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';

View File

@ -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 <header>". 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

View File

@ -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);

View File

@ -45,6 +45,7 @@ public:
float ChatViewVertSendWeight;
BRect MainWindowRect;
BRect RoomDirectoryRect;
private:
const char* _PreferencesPath();

View File

@ -0,0 +1,28 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "RoomListRow.h"
#include <ColumnTypes.h>
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);
}

View File

@ -0,0 +1,31 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#ifndef _ROOM_LIST_ROW_H
#define _ROOM_LIST_ROW_H
#include <ColumnListView.h>
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

View File

@ -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

View File

@ -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;

View File

@ -0,0 +1,134 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "RoomListWindow.h"
#include <Button.h>
#include <Catalog.h>
#include <ColumnListView.h>
#include <ColumnTypes.h>
#include <LayoutBuilder.h>
#include <StringList.h>
#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();
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#ifndef _ROOM_LIST_WINDOW_H
#define _ROOM_LIST_WINDOW_H
#include <Window.h>
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

View File

@ -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

View File

@ -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;