diff --git a/application/Account.cpp b/application/Account.cpp index 2caf297..1f6ab45 100644 --- a/application/Account.cpp +++ b/application/Account.cpp @@ -34,6 +34,8 @@ Account::Account(bigtime_t instanceId, CayaProtocol* cayap, if (path.InitCheck() == B_OK) { path.Append(name); + fProtocol->SetName(name); + // Load settings file BFile file(path.Path(), B_READ_ONLY); if (fSettings->Unflatten(&file) == B_OK) diff --git a/application/CayaMessages.h b/application/CayaMessages.h index d88eed7..3848467 100644 --- a/application/CayaMessages.h +++ b/application/CayaMessages.h @@ -20,6 +20,9 @@ const uint32 CAYA_CHAT = 'CYch'; //! Create a new chat const uint32 CAYA_NEW_CHAT = 'CYnc'; +//! Join a chat +const uint32 CAYA_JOIN_CHAT = 'CYjc'; + //! Invite user to current chat const uint32 CAYA_SEND_INVITE = 'CYin'; diff --git a/application/CayaProtocol.h b/application/CayaProtocol.h index 4b3c2a5..bb059f6 100644 --- a/application/CayaProtocol.h +++ b/application/CayaProtocol.h @@ -51,8 +51,12 @@ public: virtual bool SaveLogs() const = 0; //! Add-on's path - virtual void SetPath(BPath path) = 0; - virtual BPath Path() = 0; + virtual void SetAddOnPath(BPath path) = 0; + virtual BPath AddOnPath() = 0; + + //! Name of account file (leaf) + virtual const char* GetName() = 0; + virtual void SetName(const char* name) = 0; //! Preferred encoding of messages virtual uint32 GetEncoding() = 0; diff --git a/application/CayaProtocolAddOn.cpp b/application/CayaProtocolAddOn.cpp index c8eb3a2..56d2e0e 100644 --- a/application/CayaProtocolAddOn.cpp +++ b/application/CayaProtocolAddOn.cpp @@ -52,7 +52,7 @@ CayaProtocol* CayaProtocolAddOn::ProtocolAt(int32 i) const { CayaProtocol* proto = fGetProtocol(i); - proto->SetPath(BPath(fPath.String())); + proto->SetAddOnPath(BPath(fPath.String())); return proto; } diff --git a/application/CayaProtocolMessages.h b/application/CayaProtocolMessages.h index 3ddf865..6c39c35 100644 --- a/application/CayaProtocolMessages.h +++ b/application/CayaProtocolMessages.h @@ -40,17 +40,18 @@ enum im_what_code { //! Contact(s) removed from the server-side list IM_CONTACT_LIST_REMOVED_CONTACT = 4, + /* * Messages related to text chat. */ - //! Send a chat message to a contact + //! Send a chat message IM_SEND_MESSAGE = 20, - //! Chat message has been sent to contact + //! Chat message has been sent IM_MESSAGE_SENT = 21, - //! Chat message received from contact + //! Chat message received IM_MESSAGE_RECEIVED = 22, //! Contact started typing @@ -71,11 +72,23 @@ enum im_what_code { //! Logs received IM_LOGS_RECEIVED = 28, + + /* + * Messages related to rooms + */ + //! Create an individual chat - IM_CREATE_CHAT = 29, + IM_CREATE_CHAT = 30, //! Chat has been created - IM_CHAT_CREATED = 30, + IM_CHAT_CREATED = 31, + + //! Join a room + IM_JOIN_ROOM = 32, + + //! Confirm the room's been joined + IM_ROOM_JOINED = 33, + /* * Messages related to contact changes. @@ -87,6 +100,7 @@ enum im_what_code { //! Contact's status has changed IM_NICKNAME_SET = 41, + /* * Messages related to contact's information received from protocols. */ @@ -109,6 +123,7 @@ enum im_what_code { //! Received extended contact information IM_EXTENDED_CONTACT_INFO = 65, + /* * Messages that involve changing own information. */ @@ -134,6 +149,7 @@ enum im_what_code { //! Own avatar icon was changed IM_OWN_AVATAR_SET = 86, + /* * Contacts registration. */ @@ -144,6 +160,7 @@ enum im_what_code { //! Stop listening to status changes from these contacts IM_UNREGISTER_CONTACTS = 101, + /* * Authorization. */ @@ -163,6 +180,7 @@ enum im_what_code { //! Contact has been authorized IM_CONTACT_AUTHORIZED = 124, + /* * Miscellaneous. */ diff --git a/application/JoinWindow.cpp b/application/JoinWindow.cpp new file mode 100644 index 0000000..dab3178 --- /dev/null +++ b/application/JoinWindow.cpp @@ -0,0 +1,116 @@ +/* + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#include "JoinWindow.h" + +#include +#include +#include +#include +#include + +#include "CayaProtocolMessages.h" + + +const uint32 kJoinRoom = 'JWjr'; +const uint32 kAccSelected = 'JWas'; + + +JoinWindow::JoinWindow(BMessenger* messenger, AccountInstances accounts) + : + BWindow(BRect(0, 0, 300, 100), "Join a room", B_FLOATING_WINDOW, 0), + fTarget(messenger), + fAccounts(accounts), + fSelectedAcc(0) +{ + _InitInterface(); + + CenterOnScreen(); +} + + +void +JoinWindow::MessageReceived(BMessage* msg) +{ + switch (msg->what) + { + case kAccSelected: + { + int32 index; + if (msg->FindInt32("index", &index) == B_OK) + fSelectedAcc = index; + break; + } + + case kJoinRoom: + { + BString roomId = fTextBox->Text(); + BString selected = fMenuField->Menu()->ItemAt(fSelectedAcc)->Label(); + int64 instanceId = fAccounts.ValueFor(selected); + + if (roomId.IsEmpty() == true) { + BAlert* alert = new BAlert("No room ID", "You can't join a room " + "with no name― you need to specify a room ID.", "OK", "", "", + B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_IDEA_ALERT); + alert->Go(); + return; + } + + BMessage* joinMsg = new BMessage(IM_MESSAGE); + joinMsg->AddInt32("im_what", IM_JOIN_ROOM); + joinMsg->AddInt64("instance", instanceId); + joinMsg->AddString("chat_id", roomId); + fTarget->SendMessage(joinMsg); + + Quit(); + break; + } + + default: + BWindow::MessageReceived(msg); + } +} + + +void +JoinWindow::_InitInterface() +{ + fMenuField = new BMenuField("accountMenuField", NULL, _CreateAccountMenu()); + BButton* join = new BButton("Join", new BMessage(kJoinRoom)); + fTextBox = new BTextControl("Room ID:", "", NULL); + + BLayoutBuilder::Group<>(this, B_VERTICAL) + .SetInsets(B_USE_DEFAULT_SPACING) + .Add(fTextBox) + .AddGroup(B_HORIZONTAL) + .Add(fMenuField) + .AddGlue() + .Add(new BButton("Cancel", new BMessage(B_QUIT_REQUESTED))) + .Add(join) + .End() + .End(); + + fTextBox->MakeFocus(true); + join->MakeDefault(true); +} + + +BMenu* +JoinWindow::_CreateAccountMenu() +{ + BMenu* menu = new BMenu("accountMenu"); + + for (int i = 0; i < fAccounts.CountItems(); i++) + menu->AddItem(new BMenuItem(fAccounts.KeyAt(i).String(), + new BMessage(kAccSelected))); + + menu->SetRadioMode(true); + menu->SetLabelFromMarked(true); + menu->ItemAt(fSelectedAcc)->SetMarked(true); + + return menu; +} + + diff --git a/application/JoinWindow.h b/application/JoinWindow.h new file mode 100644 index 0000000..c1724cc --- /dev/null +++ b/application/JoinWindow.h @@ -0,0 +1,40 @@ +/* + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef JOINWINDOW_H +#define JOINWINDOW_H + +#include + +#include "Server.h" + +class BMenu; +class BMenuField; +class BMessenger; +class BTextControl; + + +/* A window used to specify a room to join. */ +class JoinWindow : public BWindow { +public: + JoinWindow(BMessenger* messenger, AccountInstances accounts); + + void MessageReceived(BMessage* message); + +private: + void _InitInterface(); + BMenu* _CreateAccountMenu(); + + BMessenger* fTarget; + AccountInstances fAccounts; + + BMenuField* fMenuField; + BTextControl* fTextBox; + + int32 fSelectedAcc; +}; + + +#endif // JOINWINDOW_H + diff --git a/application/MainWindow.cpp b/application/MainWindow.cpp index 6cbf6bf..b7e095f 100644 --- a/application/MainWindow.cpp +++ b/application/MainWindow.cpp @@ -23,6 +23,7 @@ #include "ConversationListView.h" #include "ConversationView.h" #include "EditingFilter.h" +#include "JoinWindow.h" #include "MainWindow.h" #include "NotifyMessage.h" #include "PreferencesDialog.h" @@ -111,6 +112,14 @@ MainWindow::MessageReceived(BMessage* message) break; } + case CAYA_JOIN_CHAT: + { + JoinWindow* win = new JoinWindow(new BMessenger(this), + fServer->GetAccounts()); + win->Show(); + break; + } + case CAYA_MOVE_UP: { if (fConversation == NULL) @@ -350,9 +359,16 @@ MainWindow::_CreateMenuBar() BMenuItem* invite = new BMenuItem("Invite user" B_UTF8_ELLIPSIS, new BMessage(CAYA_SEND_INVITE), 'I', B_COMMAND_KEY); invite->SetEnabled(false); + BMenuItem* newRoom = new BMenuItem("New room" B_UTF8_ELLIPSIS, + new BMessage(), 'N', B_COMMAND_KEY); + newRoom->SetEnabled(false); + chatMenu->AddItem(new BMenuItem("Join room" B_UTF8_ELLIPSIS, + new BMessage(CAYA_JOIN_CHAT), 'J', B_COMMAND_KEY)); + chatMenu->AddSeparatorItem(); chatMenu->AddItem(new BMenuItem("New chat" B_UTF8_ELLIPSIS, new BMessage(CAYA_NEW_CHAT), 'M', B_COMMAND_KEY)); + chatMenu->AddItem(newRoom); chatMenu->AddSeparatorItem(); chatMenu->AddItem(invite); chatMenu->SetTargetForItems(this); diff --git a/application/Makefile b/application/Makefile index 370f98e..d540ec9 100644 --- a/application/Makefile +++ b/application/Makefile @@ -41,6 +41,7 @@ SRCS = \ application/Conversation.cpp \ application/EditingFilter.cpp \ application/ImageCache.cpp \ + application/JoinWindow.cpp \ application/Main.cpp \ application/MainWindow.cpp \ application/Notifier.cpp \ diff --git a/application/Server.cpp b/application/Server.cpp index f0ce680..1c74434 100644 --- a/application/Server.cpp +++ b/application/Server.cpp @@ -245,6 +245,15 @@ Server::ImMessage(BMessage* msg) break; } + case IM_JOIN_ROOM: + { + SendProtocolMessage(msg); + break; + } + case IM_ROOM_JOINED: + { + break; + } case IM_SEND_MESSAGE: { // Route this message through the appropriate ProtocolLooper @@ -348,6 +357,7 @@ Server::AddProtocolLooper(bigtime_t instanceId, CayaProtocol* cayap) { ProtocolLooper* looper = new ProtocolLooper(cayap); fLoopers.AddItem(instanceId, looper); + fAccounts.AddItem(cayap->GetName(), instanceId); } @@ -357,6 +367,21 @@ Server::RemoveProtocolLooper(bigtime_t instanceId) } +ProtocolLooper* +Server::GetProtocolLooper(bigtime_t instanceId) +{ + bool found = false; + return fLoopers.ValueFor(instanceId, &found); +} + + +AccountInstances +Server::GetAccounts() +{ + return fAccounts; +} + + void Server::SendProtocolMessage(BMessage* msg) { diff --git a/application/Server.h b/application/Server.h index 26c2eae..65a87a7 100644 --- a/application/Server.h +++ b/application/Server.h @@ -25,6 +25,7 @@ typedef KeyMap RosterMap; typedef KeyMap UserMap; typedef KeyMap ChatMap; typedef KeyMap ProtocolLoopers; +typedef KeyMap AccountInstances; class Server: public BMessageFilter { @@ -39,6 +40,10 @@ public: void AddProtocolLooper(bigtime_t instanceId, CayaProtocol* cayap); void RemoveProtocolLooper(bigtime_t instanceId); + ProtocolLooper* GetProtocolLooper(bigtime_t instanceId); + + AccountInstances + GetAccounts(); void SendProtocolMessage(BMessage* msg); void SendAllProtocolMessage(BMessage* msg); @@ -71,6 +76,8 @@ private: UserMap fUserMap; ChatMap fChatMap; ProtocolLoopers fLoopers; + AccountInstances + fAccounts; BString fMySelf; };