Write conversation list, put it in main window

Now all active conversations will be listed in the main window, in a
ConversationListView. Clicking one of the items will open its
conversation window as you'd expect, etc.
This commit is contained in:
Jaidyn Ann 2021-05-27 11:15:30 -05:00
parent 0326cee687
commit 13ea8fecdf
12 changed files with 275 additions and 15 deletions

View File

@ -17,6 +17,9 @@ const uint32 CAYA_CLOSE_CHAT_WINDOW = 'CYcw';
//! Chat messages
const uint32 CAYA_CHAT = 'CYch';
//! Create a new chat
const uint32 CAYA_NEW_CHAT = 'CYnc';
//! Send replicant's messenger to Caya
const uint32 CAYA_REPLICANT_MESSENGER = 'RPme';

View File

@ -13,6 +13,7 @@
#include "CayaProtocolMessages.h"
#include "CayaUtils.h"
#include "ChatWindow.h"
#include "ConversationItem.h"
#include "MainWindow.h"
#include "ProtocolLooper.h"
#include "ProtocolManager.h"
@ -31,6 +32,7 @@ Conversation::Conversation(BString id, BMessenger msgn)
fLooper(NULL),
fDateFormatter()
{
fConversationItem = new ConversationItem(fName.String(), this);
}
@ -181,6 +183,13 @@ Conversation::SetProtocolLooper(ProtocolLooper* looper)
}
ConversationItem*
Conversation::GetConversationItem()
{
return fConversationItem;
}
BString
Conversation::GetName() const
{

View File

@ -11,11 +11,12 @@
#include <libsupport/KeyMap.h>
#include "Notifier.h"
#include "Observer.h"
#include "User.h"
class ChatWindow;
class Contact;
class ConversationItem;
class ProtocolLooper;
class Server;
@ -49,6 +50,8 @@ public:
ProtocolLooper* GetProtocolLooper() const;
void SetProtocolLooper(ProtocolLooper* looper);
ConversationItem* GetConversationItem();
BString GetName() const;
UserMap Users();
@ -68,6 +71,7 @@ private:
ProtocolLooper* fLooper;
ChatWindow* fChatWindow;
bool fNewWindow;
ConversationItem* fConversationItem;
BString fID;
BString fName;

View File

@ -26,6 +26,8 @@
#include "CayaMessages.h"
#include "CayaProtocolMessages.h"
#include "CayaPreferences.h"
#include "ConversationItem.h"
#include "ConversationListView.h"
#include "NotifyMessage.h"
#include "MainWindow.h"
#include "PreferencesDialog.h"
@ -36,7 +38,6 @@
const uint32 kLogin = 'LOGI';
const uint32 CAYA_NEW_CHAT = 'CRCH';
MainWindow::MainWindow()
@ -67,8 +68,11 @@ MainWindow::MainWindow()
menuBar->AddItem(programMenu);
menuBar->AddItem(chatMenu);
fListView = new ConversationListView("roomList");
BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f)
.Add(menuBar)
.Add(fListView)
.AddGroup(B_VERTICAL)
.SetInsets(5, 5, 5, 10)
.Add(fStatusView)
@ -220,6 +224,13 @@ MainWindow::ImMessage(BMessage* msg)
}
break;
}
case IM_MESSAGE_RECEIVED:
case IM_MESSAGE_SENT:
case IM_CHAT_CREATED:
{
_EnsureConversationItem(msg);
break;
}
}
}
@ -235,6 +246,16 @@ MainWindow::ObserveInteger(int32 what, int32 val)
}
void
MainWindow::UpdateListItem(ConversationItem* item)
{
if (fListView->HasItem(item) == true)
fListView->InvalidateItem(fListView->IndexOf(item));
else
fListView->AddItem(item);
}
void
MainWindow::WorkspaceActivated(int32 workspace, bool active)
{
@ -245,3 +266,26 @@ MainWindow::WorkspaceActivated(int32 workspace, bool active)
}
ConversationItem*
MainWindow::_EnsureConversationItem(BMessage* msg)
{
ChatMap chats = fServer->Conversations();
BString chat_id = msg->FindString("chat_id");
Conversation* chat = fServer->ConversationById(chat_id);
if (chat != NULL) {
ConversationItem* item = chat->GetConversationItem();
if (fListView->HasItem(item)) {
UpdateListItem(item);
}
else if (item != NULL) {
fListView->AddItem(item);
}
return item;
}
return NULL;
}

View File

@ -13,9 +13,10 @@
class BCardLayout;
class BTextControl;
class ConversationItem;
class ConversationListView;
class Server;
class StatusView;
class RosterListView;
class RosterItem;
@ -37,17 +38,16 @@ public:
Server* GetServer() const { return fServer; }
void UpdateListItem(RosterItem* item);
void UpdateListItem(ConversationItem* item);
int32 CountItems() const;
RosterItem* ItemAt(int index);
void AddItem(RosterItem*);
bool HasItem(RosterItem*);
void RemoveItem(RosterItem*);
private:
ConversationItem* _EnsureConversationItem(BMessage* msg);
ConversationListView* fListView;
StatusView* fStatusView;
RosterListView* fListView;
Server* fServer;
bool fWorkspaceChanged;
};

View File

@ -62,15 +62,17 @@ SRCS = \
application/preferences/PreferencesBehavior.cpp \
application/preferences/PreferencesReplicant.cpp \
application/preferences/PreferencesChatWindow.cpp \
application/views/SearchBarTextControl.cpp \
application/views/NicknameTextControl.cpp \
application/views/RosterItem.cpp \
application/views/RosterListView.cpp \
application/views/StatusMenuItem.cpp \
application/views/StatusView.cpp \
application/views/CayaRenderView.cpp \
application/views/ConversationItem.cpp \
application/views/ConversationListView.cpp \
application/views/NicknameTextControl.cpp \
application/views/ReplicantStatusView.cpp \
application/views/ReplicantMenuItem.cpp \
application/views/RosterItem.cpp \
application/views/RosterListView.cpp \
application/views/SearchBarTextControl.cpp \
application/views/StatusMenuItem.cpp \
application/views/StatusView.cpp \
application/views/UserInfoWindow.cpp \
application/views/UserPopUp.cpp

View File

@ -340,6 +340,7 @@ Server::ImMessage(BMessage* msg)
chat->AddUser(user);
chat->ShowWindow(false, true);
}
break;
}
case IM_SEND_MESSAGE:
@ -354,7 +355,7 @@ Server::ImMessage(BMessage* msg)
{
Conversation* item = _EnsureConversation(msg);
item->ImMessage(msg);
result = B_SKIP_MESSAGE;
break;
}
case IM_CONTACT_STARTED_TYPING:

View File

@ -19,10 +19,12 @@ class CayaProtocol;
class RosterItem;
class ProtocolLooper;
typedef KeyMap<BString, Contact*> RosterMap;
typedef KeyMap<BString, Conversation*> ChatMap;
typedef KeyMap<bigtime_t, ProtocolLooper*> ProtocolLoopers;
class Server: public BMessageFilter {
public:
Server();
@ -65,4 +67,6 @@ private:
Contact* fMySelf;
};
#endif // _SERVER_H

View File

@ -0,0 +1,43 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "ConversationItem.h"
#include "Conversation.h"
ConversationItem::ConversationItem(const char* name, Conversation* chat)
:
BStringItem(name),
fChat(chat)
{
}
Conversation*
ConversationItem::GetConversation()
{
return fChat;
}
void
ConversationItem::ObserveString(int32 what, BString str)
{
}
void
ConversationItem::ObservePointer(int32 what, void* ptr)
{
}
void
ConversationItem::ObserveInteger(int32 what, int32 val)
{
}

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 CONVERSATIONITEM_H
#define CONVERSATIONITEM_H
#include <ListView.h>
#include "Observer.h"
class Conversation;
class ConversationItem : public BStringItem, public Observer {
public:
ConversationItem(const char* name, Conversation* chat);
Conversation* GetConversation();
protected:
void ObserveString(int32 what, BString str);
void ObservePointer(int32 what, void* ptr);
void ObserveInteger(int32 what, int32 val);
private:
Conversation* fChat;
};
#endif // CONVERSATIONITEM_H

View File

@ -0,0 +1,92 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "ConversationListView.h"
#include <PopUpMenu.h>
#include <MenuItem.h>
#include <Window.h>
#include "CayaMessages.h"
#include "Conversation.h"
#include "ConversationItem.h"
const uint32 kOpenSelectedChat = 'CVos';
const uint32 kLeaveSelectedChat = 'CVcs';
ConversationListView::ConversationListView(const char* name)
: BOutlineListView(name)
{
}
void
ConversationListView::MessageReceived(BMessage* msg)
{
switch (msg->what) {
case kOpenSelectedChat:
{
ConversationItem* item;
int32 selIndex = CurrentSelection();
if ((item = (ConversationItem*)ItemAt(selIndex)) != NULL)
item->GetConversation()->ShowWindow(false, true);
break;
}
default:
BOutlineListView::MessageReceived(msg);
}
}
void
ConversationListView::MouseDown(BPoint where)
{
BListView::MouseDown(where);
uint32 buttons = 0;
Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
if (buttons & B_PRIMARY_MOUSE_BUTTON)
MessageReceived(new BMessage(kOpenSelectedChat));
if (!(buttons & B_SECONDARY_MOUSE_BUTTON))
return;
if (CurrentSelection() >= 0)
_ConversationPopUp()->Go(ConvertToScreen(where), true, false);
else
_BlankPopUp()->Go(ConvertToScreen(where), true, false);
}
BPopUpMenu*
ConversationListView::_ConversationPopUp()
{
BPopUpMenu* menu = new BPopUpMenu("chatPopUp");
menu->AddItem(new BMenuItem("Open chat…", new BMessage(kOpenSelectedChat)));
menu->AddItem(new BMenuItem("Leave chat", new BMessage(kLeaveSelectedChat)));
menu->SetTargetForItems(this);
return menu;
}
BPopUpMenu*
ConversationListView::_BlankPopUp()
{
BPopUpMenu* menu = new BPopUpMenu("blankPopUp");
menu->AddItem(new BMenuItem("New chat" B_UTF8_ELLIPSIS,
new BMessage(CAYA_NEW_CHAT)));
menu->SetTargetForItems(Window());
return menu;
}

View File

@ -0,0 +1,27 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#ifndef CONVERSATIONLIST_H
#define CONVERSATIONLIST_H
#include <OutlineListView.h>
class BPopUpMenu;
class ConversationListView : public BOutlineListView {
public:
ConversationListView(const char* name);
void MessageReceived(BMessage* msg);
void MouseDown(BPoint where);
private:
BPopUpMenu* _ConversationPopUp();
BPopUpMenu* _BlankPopUp();
};
#endif // CONVERSATIONLIST_H