diff --git a/application/CayaMessages.h b/application/CayaMessages.h index c1da0ad..ef6a2e8 100644 --- a/application/CayaMessages.h +++ b/application/CayaMessages.h @@ -50,4 +50,7 @@ const uint32 CAYA_DISABLE_ACCOUNT = 'CYda'; //! Request a "help" message const uint32 CAYA_REQUEST_HELP = 'CYhm'; +//! Display a "user info" window +const uint32 CAYA_USER_INFO = 'CYuw'; + #endif // _CAYA_MESSAGES_H diff --git a/application/DefaultItems.cpp b/application/DefaultItems.cpp new file mode 100644 index 0000000..f199c4f --- /dev/null +++ b/application/DefaultItems.cpp @@ -0,0 +1,149 @@ +/* + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#include "DefaultItems.h" + +#include + +#include "CayaMessages.h" +#include "CayaProtocolMessages.h" +#include "Role.h" + + +CommandMap +DefaultCommands() +{ + List roomUser; + roomUser.AddItem(CMD_ROOM_PARTICIPANT); + List kickBody; + kickBody.AddItem(CMD_ROOM_PARTICIPANT); + kickBody.AddItem(CMD_BODY_STRING); + List knownUser; + knownUser.AddItem(CMD_KNOWN_USER); + List anyUser; + anyUser.AddItem(CMD_ANY_USER); + + CommandMap commands; + + BMessage kickMsg(IM_MESSAGE); + kickMsg.AddInt32("im_what", IM_ROOM_KICK_PARTICIPANT); + ChatCommand* kick = new ChatCommand("kick", kickMsg, true, kickBody); + kick->SetDesc("Force a user to temporarily leave the room, assuming your " + "power level's high enough."); + commands.AddItem("kick", kick); + + BMessage banMsg(IM_MESSAGE); + banMsg.AddInt32("im_what", IM_ROOM_BAN_PARTICIPANT); + ChatCommand* ban = new ChatCommand("ban", banMsg, true, kickBody); + ban->SetDesc("Kick a user out of the room and slam the door behind them― " + "locking it while you're at it."); + commands.AddItem("ban", ban); + + BMessage unbanMsg(IM_MESSAGE); + unbanMsg.AddInt32("im_what", IM_ROOM_UNBAN_PARTICIPANT); + ChatCommand* unban = new ChatCommand("unban", unbanMsg, true, anyUser); + unban->SetDesc("Undo a previous ban, allowing the user to rejoin (if they " + "still want to)."); + commands.AddItem("unban", unban); + + BMessage muteMsg(IM_MESSAGE); + muteMsg.AddInt32("im_what", IM_ROOM_MUTE_PARTICIPANT); + ChatCommand* mute = new ChatCommand("mute", muteMsg, true, roomUser); + mute->SetDesc("Disallow a user from sending visible messages."); + commands.AddItem("mute", mute); + + BMessage unmuteMsg(IM_MESSAGE); + unmuteMsg.AddInt32("im_what", IM_ROOM_UNMUTE_PARTICIPANT); + ChatCommand* unmute = new ChatCommand("unmute", unmuteMsg, true, roomUser); + unmute->SetDesc("Restore a user's ability to send messages."); + commands.AddItem("unmute", unmute); + + BMessage deafenMsg(IM_MESSAGE); + deafenMsg.AddInt32("im_what", IM_ROOM_DEAFEN_PARTICIPANT); + ChatCommand* deafen = new ChatCommand("deafen", deafenMsg, true, roomUser); + deafen->SetDesc("Disallow a user from reading messages sent in the room."); + commands.AddItem("deafen", deafen); + + BMessage undeafenMsg(IM_MESSAGE); + undeafenMsg.AddInt32("im_what", IM_ROOM_UNDEAFEN_PARTICIPANT); + ChatCommand* undeafen = new ChatCommand("undeafen", undeafenMsg, true, roomUser); + undeafen->SetDesc("Restore a user's ability to receive messages."); + commands.AddItem("undeafen", undeafen); + + BMessage inviteMsg(IM_MESSAGE); + inviteMsg.AddInt32("im_what", IM_ROOM_SEND_INVITE); + ChatCommand* invite = new ChatCommand("invite", inviteMsg, true, knownUser); + invite->SetDesc("Invite a user to the current room."); + commands.AddItem("invite", invite); + + BMessage helpMsg(CAYA_REQUEST_HELP); + ChatCommand* help = new ChatCommand("help", helpMsg, false, List()); + help->SetDesc("List all current commands, or get help for certain command."); + commands.AddItem("help", help); + + return commands; +} + + +BObjectList +DefaultUserPopUpItems() +{ + BObjectList items; + + BMessage* infoMsg = new BMessage(CAYA_USER_INFO); + items.AddItem(_UserMenuItem("User info" B_UTF8_ELLIPSIS, infoMsg, 0, 0, 0, + false, false)); + + BMessage* kickMsg = new BMessage(IM_MESSAGE); + kickMsg->AddInt32("im_what", IM_ROOM_KICK_PARTICIPANT); + items.AddItem(_UserMenuItem("Kick user", kickMsg, PERM_KICK, 0, 0, false, + true)); + + BMessage* banMsg = new BMessage(IM_MESSAGE); + banMsg->AddInt32("im_what", IM_ROOM_BAN_PARTICIPANT); + items.AddItem(_UserMenuItem("Ban user", banMsg, PERM_BAN, 0, 0, false, true)); + + BMessage* muteMsg = new BMessage(IM_MESSAGE); + muteMsg->AddInt32("im_what", IM_ROOM_MUTE_PARTICIPANT); + items.AddItem(_UserMenuItem("Mute user", muteMsg, PERM_MUTE, PERM_WRITE, 0, + false, true)); + + BMessage* unmuteMsg = new BMessage(IM_MESSAGE); + unmuteMsg->AddInt32("im_what", IM_ROOM_UNMUTE_PARTICIPANT); + items.AddItem(_UserMenuItem("Unmute user", unmuteMsg, PERM_MUTE, 0, + PERM_WRITE, false, true)); + + BMessage* deafenMsg = new BMessage(IM_MESSAGE); + deafenMsg->AddInt32("im_what", IM_ROOM_DEAFEN_PARTICIPANT); + items.AddItem(_UserMenuItem("Deafen user", deafenMsg, PERM_DEAFEN, PERM_READ, + 0, false, true)); + + BMessage* undeafenMsg = new BMessage(IM_MESSAGE); + undeafenMsg->AddInt32("im_what", IM_ROOM_UNDEAFEN_PARTICIPANT); + items.AddItem(_UserMenuItem("Undeafen user", undeafenMsg, PERM_DEAFEN, 0, + PERM_READ, false, true)); + return items; +} + + +BMessage* +_UserMenuItem(const char* label, BMessage* msg, int32 user_perms, + int32 target_perms, int32 target_lacks, bool ignorePriority, + bool toProtocol) +{ + BMessage* item = new BMessage(); + item->AddString("class", "BMenuItem"); + item->AddString("_label", label); + item->AddMessage("_msg", msg); + + item->AddInt32("x_perms", user_perms); + item->AddInt32("x_target_perms", target_perms); + item->AddInt32("x_target_antiperms", target_lacks); + item->AddBool("x_priority", ignorePriority); + item->AddBool("x_to_protocol", toProtocol); + return item; +} + + diff --git a/application/DefaultItems.h b/application/DefaultItems.h new file mode 100644 index 0000000..3309821 --- /dev/null +++ b/application/DefaultItems.h @@ -0,0 +1,21 @@ +/* + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef DEFAULTITEMS_H +#define DEFAULTITEMS_H + +#include "ChatCommand.h" + +#include + + +CommandMap DefaultCommands(); +BObjectList DefaultUserPopUpItems(); +BMessage* _UserMenuItem(const char* label, BMessage* msg, + int32 user_perms, int32 target_perms, + int32 target_lacks, bool ignorePriority, + bool toProtocol); + + +#endif // DEFAULTITEMS_H diff --git a/application/Makefile b/application/Makefile index f4bafa3..2024ee9 100644 --- a/application/Makefile +++ b/application/Makefile @@ -39,6 +39,7 @@ SRCS = \ application/ChatCommand.cpp \ application/Contact.cpp \ application/Conversation.cpp \ + application/DefaultItems.cpp \ application/EditingFilter.cpp \ application/ImageCache.cpp \ application/Main.cpp \ diff --git a/application/Server.cpp b/application/Server.cpp index 5420d42..ad6c5e9 100644 --- a/application/Server.cpp +++ b/application/Server.cpp @@ -1,16 +1,20 @@ /* * Copyright 2009-2011, Andrea Anzani. All rights reserved. * Copyright 2009-2011, Pier Luigi Fiorini. All rights reserved. + * Copyright 2021, Jaidyn Levesque. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Andrea Anzani, andrea.anzani@gmail.com * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com + * Jaidyn Levesque, jadedctrl@teknik.io * * Contributors: * Dario Casalinuovo */ +#include "Server.h" + #include #include #include @@ -26,20 +30,22 @@ #include "CayaPreferences.h" #include "CayaProtocolMessages.h" #include "CayaUtils.h" +#include "DefaultItems.h" #include "ImageCache.h" #include "InviteDialogue.h" #include "ProtocolLooper.h" #include "ProtocolManager.h" #include "RoomFlags.h" #include "RosterItem.h" -#include "Server.h" +#include "UserInfoWindow.h" Server::Server() : - BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE) + BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE), + fUserItems(DefaultUserPopUpItems()), + fCommands(DefaultCommands()) { - _InitDefaultCommands(); } @@ -113,6 +119,16 @@ Server::Filter(BMessage* message, BHandler **target) break; } + case CAYA_USER_INFO: + { + User* user = _EnsureUser(message); + if (user != NULL) { + UserInfoWindow* win = new UserInfoWindow(user); + win->Show(); + } + break; + } + case CAYA_REQUEST_HELP: { BString body; @@ -749,19 +765,6 @@ Server::AddConversation(Conversation* chat, int64 instance) } -CommandMap -Server::Commands() -{ - CommandMap commands = fCommands; - for (int i = 0; i < fAccounts.CountItems(); i++) { - ProtocolLooper* fruitLoop = fLoopers.ValueFor(fAccounts.ValueAt(i)); - if (fruitLoop == NULL) continue; - commands.AddList(fruitLoop->Commands()); - } - return fCommands; -} - - ChatCommand* Server::CommandById(BString id, int64 instance) { @@ -775,6 +778,20 @@ Server::CommandById(BString id, int64 instance) } +BObjectList +Server::ConversationPopUpItems() +{ + return fChatItems; +} + + +BObjectList +Server::UserPopUpItems() +{ + return fUserItems; +} + + ProtocolLooper* Server::_LooperFromMessage(BMessage* message) { @@ -890,74 +907,4 @@ Server::_GetRole(BMessage* msg) return new Role(title, perms, priority); } -void -Server::_InitDefaultCommands() -{ - List roomUser; - roomUser.AddItem(CMD_ROOM_PARTICIPANT); - List kickBody; - kickBody.AddItem(CMD_ROOM_PARTICIPANT); - kickBody.AddItem(CMD_BODY_STRING); - List knownUser; - knownUser.AddItem(CMD_KNOWN_USER); - List anyUser; - anyUser.AddItem(CMD_ANY_USER); - - BMessage kickMsg(IM_MESSAGE); - kickMsg.AddInt32("im_what", IM_ROOM_KICK_PARTICIPANT); - ChatCommand* kick = new ChatCommand("kick", kickMsg, true, kickBody); - kick->SetDesc("Force a user to temporarily leave the room, assuming your " - "power level's high enough."); - fCommands.AddItem("kick", kick); - - BMessage banMsg(IM_MESSAGE); - banMsg.AddInt32("im_what", IM_ROOM_BAN_PARTICIPANT); - ChatCommand* ban = new ChatCommand("ban", banMsg, true, kickBody); - ban->SetDesc("Kick a user out of the room and slam the door behind them― " - "locking it while you're at it."); - fCommands.AddItem("ban", ban); - - BMessage unbanMsg(IM_MESSAGE); - unbanMsg.AddInt32("im_what", IM_ROOM_UNBAN_PARTICIPANT); - ChatCommand* unban = new ChatCommand("unban", unbanMsg, true, anyUser); - unban->SetDesc("Undo a previous ban, allowing the user to rejoin (if they " - "still want to)."); - fCommands.AddItem("unban", unban); - - BMessage muteMsg(IM_MESSAGE); - muteMsg.AddInt32("im_what", IM_ROOM_MUTE_PARTICIPANT); - ChatCommand* mute = new ChatCommand("mute", muteMsg, true, roomUser); - mute->SetDesc("Disallow a user from sending visible messages."); - fCommands.AddItem("mute", mute); - - BMessage unmuteMsg(IM_MESSAGE); - unmuteMsg.AddInt32("im_what", IM_ROOM_UNMUTE_PARTICIPANT); - ChatCommand* unmute = new ChatCommand("unmute", unmuteMsg, true, roomUser); - unmute->SetDesc("Restore a user's ability to send messages."); - fCommands.AddItem("unmute", unmute); - - BMessage deafenMsg(IM_MESSAGE); - deafenMsg.AddInt32("im_what", IM_ROOM_DEAFEN_PARTICIPANT); - ChatCommand* deafen = new ChatCommand("deafen", deafenMsg, true, roomUser); - deafen->SetDesc("Disallow a user from reading messages sent in the room."); - fCommands.AddItem("deafen", deafen); - - BMessage undeafenMsg(IM_MESSAGE); - undeafenMsg.AddInt32("im_what", IM_ROOM_UNDEAFEN_PARTICIPANT); - ChatCommand* undeafen = new ChatCommand("undeafen", undeafenMsg, true, roomUser); - undeafen->SetDesc("Restore a user's ability to receive messages."); - fCommands.AddItem("undeafen", undeafen); - - BMessage inviteMsg(IM_MESSAGE); - inviteMsg.AddInt32("im_what", IM_ROOM_SEND_INVITE); - ChatCommand* invite = new ChatCommand("invite", inviteMsg, true, knownUser); - invite->SetDesc("Invite a user to the current room."); - fCommands.AddItem("invite", invite); - - BMessage helpMsg(CAYA_REQUEST_HELP); - ChatCommand* help = new ChatCommand("help", helpMsg, false, List()); - help->SetDesc("List all current commands, or get help for certain command."); - fCommands.AddItem("help", help); -} - diff --git a/application/Server.h b/application/Server.h index 3e76c51..4c47b20 100644 --- a/application/Server.h +++ b/application/Server.h @@ -59,9 +59,11 @@ public: Conversation* ConversationById(BString id, int64 instance); void AddConversation(Conversation* chat, int64 instance); - CommandMap Commands(); ChatCommand* CommandById(BString id, int64 instance); + BObjectList ConversationPopUpItems(); + BObjectList UserPopUpItems(); + private: ProtocolLooper* _LooperFromMessage(BMessage* message); @@ -72,14 +74,18 @@ private: Role* _GetRole(BMessage* msg); - void _InitDefaultCommands(); void _ReplicantStatusNotify(CayaStatus status); ProtocolLoopers fLoopers; AccountInstances fAccounts; - CommandMap fCommands; BString fMySelf; + + CommandMap fCommands; + BObjectList + fChatItems; + BObjectList + fUserItems; }; diff --git a/application/views/UserListView.cpp b/application/views/UserListView.cpp index 3da7e69..0312fea 100644 --- a/application/views/UserListView.cpp +++ b/application/views/UserListView.cpp @@ -12,8 +12,11 @@ #include "CayaMessages.h" #include "CayaProtocolMessages.h" #include "Conversation.h" +#include "MainWindow.h" #include "ProtocolLooper.h" #include "Role.h" +#include "Server.h" +#include "TheApp.h" #include "User.h" #include "UserInfoWindow.h" #include "UserItem.h" @@ -27,44 +30,6 @@ UserListView::UserListView(const char* name) } -void -UserListView::MessageReceived(BMessage* msg) -{ - switch (msg->what) { - case kUserInfo: - { - UserItem* item = (UserItem*)ItemAt(CurrentSelection()); - if (item == NULL) - return; - - UserInfoWindow* win = new UserInfoWindow(item->GetUser()); - win->Show(); - break; - } - case kKickUser: - _ModerationAction(IM_ROOM_KICK_PARTICIPANT); - break; - case kBanUser: - _ModerationAction(IM_ROOM_BAN_PARTICIPANT); - break; - case kMuteUser: - _ModerationAction(IM_ROOM_MUTE_PARTICIPANT); - break; - case kUnmuteUser: - _ModerationAction(IM_ROOM_UNMUTE_PARTICIPANT); - break; - case kDeafenUser: - _ModerationAction(IM_ROOM_DEAFEN_PARTICIPANT); - break; - case kUndeafenUser: - _ModerationAction(IM_ROOM_UNDEAFEN_PARTICIPANT); - break; - default: - BListView::MessageReceived(msg); - } -} - - void UserListView::MouseDown(BPoint where) { @@ -87,47 +52,24 @@ BPopUpMenu* UserListView::_UserPopUp() { BPopUpMenu* menu = new BPopUpMenu("userPopUp"); - menu->AddItem(new BMenuItem("User info" B_UTF8_ELLIPSIS, - new BMessage(kUserInfo))); - menu->SetTargetForItems(this); - - // Now for the moderation items - Role* role = fChat->GetRole(fChat->GetOwnId()); - if (role == NULL) return menu; - int32 perms = role->fPerms; UserItem* item = (UserItem*)ItemAt(CurrentSelection()); User* selected_user; - if (item == NULL || (selected_user = item->GetUser()) == NULL) - return menu; + return _BlankPopUp(); + + Role* own_role = fChat->GetRole(fChat->GetOwnId()); + if (own_role == NULL) return _BlankPopUp(); Role* selected_role = fChat->GetRole(selected_user->GetId()); - if (selected_role == NULL) return menu; - int32 selected_priority = selected_role->fPriority; - int32 selected_perms = selected_role->fPerms; - if (selected_priority > role->fPriority) - return menu; + if (selected_role == NULL) return _BlankPopUp(); - if ((perms & PERM_DEAFEN) || (perms & PERM_MUTE) || (perms & PERM_KICK) - || (perms & PERM_BAN)) - menu->AddSeparatorItem(); + Server* server = ((TheApp*)be_app)->GetMainWindow()->GetServer(); + BObjectList items = server->UserPopUpItems(); - if ((perms & PERM_DEAFEN) && (selected_perms & PERM_READ)) - menu->AddItem(new BMenuItem("Deafen user", new BMessage(kDeafenUser))); - if ((perms & PERM_DEAFEN) && !(selected_perms & PERM_READ)) - menu->AddItem(new BMenuItem("Undeafen user", new BMessage(kUndeafenUser))); - - if ((perms & PERM_MUTE) && (selected_perms & PERM_WRITE)) - menu->AddItem(new BMenuItem("Mute user", new BMessage(kMuteUser))); - if ((perms & PERM_MUTE) && !(selected_perms & PERM_WRITE)) - menu->AddItem(new BMenuItem("Unmute user", new BMessage(kUnmuteUser))); - - if (perms & PERM_KICK) - menu->AddItem(new BMenuItem("Kick user", new BMessage(kKickUser))); - if (perms & PERM_BAN) - menu->AddItem(new BMenuItem("Ban user", new BMessage(kBanUser))); - - menu->SetTargetForItems(this); + for (int i = 0; i < items.CountItems(); i++) { + BMessage* itemMsg = items.ItemAt(i); + _ProcessItem(itemMsg, menu, own_role, selected_role, selected_user->GetId()); + } return menu; } @@ -150,19 +92,35 @@ UserListView::_BlankPopUp() void -UserListView::_ModerationAction(int32 im_what) +UserListView::_ProcessItem(BMessage* itemMsg, BPopUpMenu* menu, Role* user, + Role* target, BString target_id) { - Role* role = fChat->GetRole(fChat->GetOwnId()); - int32 perms = role->fPerms; - UserItem* item = (UserItem*)ItemAt(CurrentSelection()); - if (item == NULL) - return; + BMessage* msg = new BMessage(*itemMsg); + bool priority = msg->GetBool("x_priority", false); + int32 perms = msg->GetInt32("x_perms", 0); + int32 target_perms = msg->GetInt32("x_target_perms", 0); + int32 target_antiperms = msg->GetInt32("x_target_antiperms", 0); - BMessage modMsg(IM_MESSAGE); - modMsg.AddInt32("im_what", im_what); - modMsg.AddString("user_id", item->GetUser()->GetId()); - modMsg.AddString("chat_id", fChat->GetId()); - fChat->GetProtocolLooper()->PostMessage(&modMsg); + BMessage toSend; + msg->FindMessage("_msg", &toSend); + toSend.AddString("user_id", target_id); + toSend.AddString("chat_id", fChat->GetId()); + toSend.AddInt64("instance", fChat->GetProtocolLooper()->GetInstance()); + msg->ReplaceMessage("_msg", &toSend); + + if ((perms == 0 || (user->fPerms & perms)) + && (target_perms == 0 || (target->fPerms & target_perms)) + && (target_antiperms == 0 || (!(target->fPerms & target_antiperms))) + && ((priority == false) || (user->fPriority > target->fPriority))) + { + BMenuItem* item = new BMenuItem(msg); + if (msg->GetBool("x_to_protocol", true) == true) + item->SetTarget(fChat->GetProtocolLooper()); + else + item->SetTarget(Window()); + + menu->AddItem(item); + } } diff --git a/application/views/UserListView.h b/application/views/UserListView.h index 813e136..e27e4c5 100644 --- a/application/views/UserListView.h +++ b/application/views/UserListView.h @@ -7,6 +7,8 @@ #include +#include "Role.h" + class BPopUpMenu; class Conversation; @@ -27,8 +29,6 @@ class UserListView : public BListView { public: UserListView(const char* name); - void MessageReceived(BMessage* msg); - void MouseDown(BPoint where); void SetConversation(Conversation* chat) { fChat = chat; } @@ -38,6 +38,8 @@ private: BPopUpMenu* _BlankPopUp(); void _ModerationAction(int32 im_what); + void _ProcessItem(BMessage* itemMsg, BPopUpMenu* menu, Role* user, + Role* target, BString target_id); Conversation* fChat; };