Explorar o código

IRCClient: Add Channel application menu and LIST and KICK commands

The new Channel application menu allow offers various commands
related to the currently visible channel, including changing
the topic, kicking a user, and leaving the channel.
Brendan Coles %!s(int64=5) %!d(string=hai) anos
pai
achega
175ec99814

+ 36 - 1
Applications/IRCClient/IRCAppWindow.cpp

@@ -114,6 +114,10 @@ void IRCAppWindow::setup_actions()
             m_client->handle_join_action(input_box->text_value());
             m_client->handle_join_action(input_box->text_value());
     });
     });
 
 
+    m_list_channels_action = GUI::Action::create("List channels", [&](auto&) {
+        m_client->handle_list_channels_action();
+    });
+
     m_part_action = GUI::Action::create("Part from channel", { Mod_Ctrl, Key_P }, Gfx::Bitmap::load_from_file("/res/icons/16x16/irc-part.png"), [this](auto&) {
     m_part_action = GUI::Action::create("Part from channel", { Mod_Ctrl, Key_P }, Gfx::Bitmap::load_from_file("/res/icons/16x16/irc-part.png"), [this](auto&) {
         auto* window = m_client->current_window();
         auto* window = m_client->current_window();
         if (!window || window->type() != IRCWindow::Type::Channel) {
         if (!window || window->type() != IRCWindow::Type::Channel) {
@@ -144,6 +148,30 @@ void IRCAppWindow::setup_actions()
         if (input_box->exec() == GUI::InputBox::ExecOK && !input_box->text_value().is_empty())
         if (input_box->exec() == GUI::InputBox::ExecOK && !input_box->text_value().is_empty())
             m_client->handle_change_nick_action(input_box->text_value());
             m_client->handle_change_nick_action(input_box->text_value());
     });
     });
+
+    m_change_topic_action = GUI::Action::create("Change topic", [this](auto&) {
+        auto* window = m_client->current_window();
+        if (!window || window->type() != IRCWindow::Type::Channel) {
+            // FIXME: Perhaps this action should have been disabled instead of allowing us to activate it.
+            return;
+        }
+        auto input_box = GUI::InputBox::construct("Enter topic:", "Change topic", this);
+        if (input_box->exec() == GUI::InputBox::ExecOK && !input_box->text_value().is_empty())
+            m_client->handle_change_topic_action(window->channel().name(), input_box->text_value());
+    });
+
+    m_kick_user_action = GUI::Action::create("Kick user", [this](auto&) {
+        auto* window = m_client->current_window();
+        if (!window || window->type() != IRCWindow::Type::Channel) {
+            // FIXME: Perhaps this action should have been disabled instead of allowing us to activate it.
+            return;
+        }
+        auto input_box = GUI::InputBox::construct("Enter nick:", "Kick user", this);
+        auto reason_box = GUI::InputBox::construct("Enter reason:", "Reason", this);
+        if (input_box->exec() == GUI::InputBox::ExecOK && !input_box->text_value().is_empty())
+            if (reason_box->exec() == GUI::InputBox::ExecOK)
+                m_client->handle_kick_user_action(window->channel().name(), input_box->text_value(), reason_box->text_value().characters());
+    });
 }
 }
 
 
 void IRCAppWindow::setup_menus()
 void IRCAppWindow::setup_menus()
@@ -161,13 +189,20 @@ void IRCAppWindow::setup_menus()
     server_menu->add_action(*m_change_nick_action);
     server_menu->add_action(*m_change_nick_action);
     server_menu->add_separator();
     server_menu->add_separator();
     server_menu->add_action(*m_join_action);
     server_menu->add_action(*m_join_action);
-    server_menu->add_action(*m_part_action);
+    server_menu->add_action(*m_list_channels_action);
     server_menu->add_separator();
     server_menu->add_separator();
     server_menu->add_action(*m_whois_action);
     server_menu->add_action(*m_whois_action);
     server_menu->add_action(*m_open_query_action);
     server_menu->add_action(*m_open_query_action);
     server_menu->add_action(*m_close_query_action);
     server_menu->add_action(*m_close_query_action);
     menubar->add_menu(move(server_menu));
     menubar->add_menu(move(server_menu));
 
 
+    auto channel_menu = GUI::Menu::construct("Channel");
+    channel_menu->add_action(*m_change_topic_action);
+    channel_menu->add_action(*m_kick_user_action);
+    channel_menu->add_separator();
+    channel_menu->add_action(*m_part_action);
+    menubar->add_menu(move(channel_menu));
+
     auto help_menu = GUI::Menu::construct("Help");
     auto help_menu = GUI::Menu::construct("Help");
     help_menu->add_action(GUI::Action::create("About", [this](const GUI::Action&) {
     help_menu->add_action(GUI::Action::create("About", [this](const GUI::Action&) {
         GUI::AboutDialog::show("IRC Client", Gfx::Bitmap::load_from_file("/res/icons/32x32/app-irc-client.png"), this);
         GUI::AboutDialog::show("IRC Client", Gfx::Bitmap::load_from_file("/res/icons/32x32/app-irc-client.png"), this);

+ 3 - 0
Applications/IRCClient/IRCAppWindow.h

@@ -55,9 +55,12 @@ private:
     RefPtr<GUI::StackWidget> m_container;
     RefPtr<GUI::StackWidget> m_container;
     RefPtr<GUI::TableView> m_window_list;
     RefPtr<GUI::TableView> m_window_list;
     RefPtr<GUI::Action> m_join_action;
     RefPtr<GUI::Action> m_join_action;
+    RefPtr<GUI::Action> m_list_channels_action;
     RefPtr<GUI::Action> m_part_action;
     RefPtr<GUI::Action> m_part_action;
     RefPtr<GUI::Action> m_whois_action;
     RefPtr<GUI::Action> m_whois_action;
     RefPtr<GUI::Action> m_open_query_action;
     RefPtr<GUI::Action> m_open_query_action;
     RefPtr<GUI::Action> m_close_query_action;
     RefPtr<GUI::Action> m_close_query_action;
     RefPtr<GUI::Action> m_change_nick_action;
     RefPtr<GUI::Action> m_change_nick_action;
+    RefPtr<GUI::Action> m_change_topic_action;
+    RefPtr<GUI::Action> m_kick_user_action;
 };
 };

+ 38 - 0
Applications/IRCClient/IRCClient.cpp

@@ -317,6 +317,16 @@ void IRCClient::send_topic(const String& channel_name, const String& text)
     send(String::format("TOPIC %s :%s\r\n", channel_name.characters(), text.characters()));
     send(String::format("TOPIC %s :%s\r\n", channel_name.characters(), text.characters()));
 }
 }
 
 
+void IRCClient::send_kick(const String& channel_name, const String& nick, const String& comment)
+{
+    send(String::format("KICK %s %s :%s\r\n", channel_name.characters(), nick.characters(), comment.characters()));
+}
+
+void IRCClient::send_list()
+{
+    send("LIST\r\n");
+}
+
 void IRCClient::send_privmsg(const String& target, const String& text)
 void IRCClient::send_privmsg(const String& target, const String& text)
 {
 {
     send(String::format("PRIVMSG %s :%s\r\n", target.characters(), text.characters()));
     send(String::format("PRIVMSG %s :%s\r\n", target.characters(), text.characters()));
@@ -696,6 +706,19 @@ void IRCClient::handle_user_command(const String& input)
         send_topic(channel, topic);
         send_topic(channel, topic);
         return;
         return;
     }
     }
+    if (command == "/KICK") {
+        if (parts.size() < 3)
+            return;
+        auto channel = parts[1];
+        auto nick = parts[2];
+        auto reason = input.view().substring_view_starting_after_substring(nick);
+        send_kick(channel, nick, reason);
+        return;
+    }
+    if (command == "/LIST") {
+        send_list();
+        return;
+    }
     if (command == "/QUERY") {
     if (command == "/QUERY") {
         if (parts.size() >= 2) {
         if (parts.size() >= 2) {
             auto& query = ensure_query(parts[1]);
             auto& query = ensure_query(parts[1]);
@@ -724,6 +747,11 @@ void IRCClient::change_nick(const String& nick)
     send(String::format("NICK %s\r\n", nick.characters()));
     send(String::format("NICK %s\r\n", nick.characters()));
 }
 }
 
 
+void IRCClient::handle_list_channels_action()
+{
+    send_list();
+}
+
 void IRCClient::handle_whois_action(const String& nick)
 void IRCClient::handle_whois_action(const String& nick)
 {
 {
     send_whois(nick);
     send_whois(nick);
@@ -739,6 +767,16 @@ void IRCClient::handle_change_nick_action(const String& nick)
     change_nick(nick);
     change_nick(nick);
 }
 }
 
 
+void IRCClient::handle_change_topic_action(const String& channel, const String& topic)
+{
+    send_topic(channel, topic);
+}
+
+void IRCClient::handle_kick_user_action(const String& channel, const String& nick, const String& message)
+{
+    send_kick(channel, nick, message);
+}
+
 void IRCClient::handle_close_query_action(const String& nick)
 void IRCClient::handle_close_query_action(const String& nick)
 {
 {
     m_queries.remove(nick);
     m_queries.remove(nick);

+ 5 - 0
Applications/IRCClient/IRCClient.h

@@ -99,12 +99,15 @@ public:
     void handle_user_input_in_query(const String& query_name, const String&);
     void handle_user_input_in_query(const String& query_name, const String&);
     void handle_user_input_in_server(const String&);
     void handle_user_input_in_server(const String&);
 
 
+    void handle_list_channels_action();
     void handle_whois_action(const String&);
     void handle_whois_action(const String&);
     void handle_open_query_action(const String&);
     void handle_open_query_action(const String&);
     void handle_close_query_action(const String&);
     void handle_close_query_action(const String&);
     void handle_join_action(const String&);
     void handle_join_action(const String&);
     void handle_part_action(const String&);
     void handle_part_action(const String&);
     void handle_change_nick_action(const String&);
     void handle_change_nick_action(const String&);
+    void handle_change_topic_action(const String& channel_name, const String&);
+    void handle_kick_user_action(const String& channel_name, const String& nick, const String&);
 
 
     IRCQuery* query_with_name(const String&);
     IRCQuery* query_with_name(const String&);
     IRCQuery& ensure_query(const String& name);
     IRCQuery& ensure_query(const String& name);
@@ -134,6 +137,8 @@ private:
     void send_privmsg(const String& target, const String&);
     void send_privmsg(const String& target, const String&);
     void send_notice(const String& target, const String&);
     void send_notice(const String& target, const String&);
     void send_topic(const String& channel_name, const String&);
     void send_topic(const String& channel_name, const String&);
+    void send_kick(const String& channel_name, const String& nick, const String&);
+    void send_list();
     void send_whois(const String&);
     void send_whois(const String&);
     void process_line(ByteBuffer&&);
     void process_line(ByteBuffer&&);
     void handle_join(const Message&);
     void handle_join(const Message&);