Ver código fonte

IRCClient: Add ability to change nickname.

Andreas Kling 6 anos atrás
pai
commit
67009cee8e

+ 19 - 2
Applications/IRCClient/IRCAppWindow.cpp

@@ -15,7 +15,7 @@
 IRCAppWindow::IRCAppWindow()
     : m_client("127.0.0.1", 6667)
 {
-    set_title(String::format("IRC Client: %s@%s:%d", m_client.nickname().characters(), m_client.hostname().characters(), m_client.port()));
+    update_title();
     set_rect(200, 200, 600, 400);
     setup_actions();
     setup_menus();
@@ -28,6 +28,11 @@ IRCAppWindow::~IRCAppWindow()
 {
 }
 
+void IRCAppWindow::update_title()
+{
+    set_title(String::format("IRC Client: %s@%s:%d", m_client.nickname().characters(), m_client.hostname().characters(), m_client.port()));
+}
+
 void IRCAppWindow::setup_client()
 {
     m_client.aid_create_window = [this] (void* owner, IRCWindow::Type type, const String& name) {
@@ -39,7 +44,9 @@ void IRCAppWindow::setup_client()
     m_client.aid_update_window_list = [this] {
         m_window_list->model()->update();
     };
-
+    m_client.on_nickname_changed = [this] (const String&) {
+        update_title();
+    };
     m_client.on_connect = [this] {
         m_client.join_channel("#test");
     };
@@ -74,6 +81,12 @@ void IRCAppWindow::setup_actions()
     m_close_query_action = GAction::create("Close query", GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/16x16/irc-close-query.rgb", { 16, 16 }), [] (auto&) {
         printf("FIXME: Implement close-query action\n");
     });
+
+    m_change_nick_action = GAction::create("Change nickname", GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/16x16/irc-nick.rgb", { 16, 16 }), [this] (auto&) {
+        GInputBox input_box("Enter nickname:", "Change nickname", this);
+        if (input_box.exec() == GInputBox::ExecOK && !input_box.text_value().is_empty())
+            m_client.handle_change_nick_action(input_box.text_value());
+    });
 }
 
 void IRCAppWindow::setup_menus()
@@ -88,6 +101,8 @@ void IRCAppWindow::setup_menus()
     menubar->add_menu(move(app_menu));
 
     auto server_menu = make<GMenu>("Server");
+    server_menu->add_action(*m_change_nick_action);
+    server_menu->add_separator();
     server_menu->add_action(*m_join_action);
     server_menu->add_action(*m_part_action);
     server_menu->add_separator();
@@ -112,6 +127,8 @@ void IRCAppWindow::setup_widgets()
     widget->set_layout(make<GBoxLayout>(Orientation::Vertical));
 
     auto* toolbar = new GToolBar(widget);
+    toolbar->add_action(*m_change_nick_action);
+    toolbar->add_separator();
     toolbar->add_action(*m_join_action);
     toolbar->add_action(*m_part_action.copy_ref());
     toolbar->add_separator();

+ 2 - 0
Applications/IRCClient/IRCAppWindow.h

@@ -18,6 +18,7 @@ private:
     void setup_actions();
     void setup_menus();
     void setup_widgets();
+    void update_title();
 
     IRCWindow& create_window(void* owner, IRCWindow::Type, const String& name);
     IRCClient m_client;
@@ -28,4 +29,5 @@ private:
     RetainPtr<GAction> m_whois_action;
     RetainPtr<GAction> m_open_query_action;
     RetainPtr<GAction> m_close_query_action;
+    RetainPtr<GAction> m_change_nick_action;
 };

+ 16 - 4
Applications/IRCClient/IRCChannel.cpp

@@ -70,7 +70,7 @@ void IRCChannel::handle_join(const String& nick, const String& hostmask)
 {
     if (nick == m_client.nickname())
         m_open = true;
-    add_message(String::format("*** %s [%s] has joined %s", nick.characters(), hostmask.characters(), m_name.characters()), Color::DarkGreen);
+    add_message(String::format("*** %s [%s] has joined %s", nick.characters(), hostmask.characters(), m_name.characters()), Color::MidGreen);
 }
 
 void IRCChannel::handle_part(const String& nick, const String& hostmask)
@@ -82,13 +82,25 @@ void IRCChannel::handle_part(const String& nick, const String& hostmask)
         remove_member(nick);
     }
     m_member_model->update();
-    add_message(String::format("*** %s [%s] has parted from %s", nick.characters(), hostmask.characters(), m_name.characters()), Color::DarkGreen);
+    add_message(String::format("*** %s [%s] has parted from %s", nick.characters(), hostmask.characters(), m_name.characters()), Color::MidGreen);
 }
 
 void IRCChannel::handle_topic(const String& nick, const String& topic)
 {
     if (nick.is_null())
-        add_message(String::format("*** Topic is \"%s\"", topic.characters()), Color::DarkBlue);
+        add_message(String::format("*** Topic is \"%s\"", topic.characters()), Color::MidBlue);
     else
-        add_message(String::format("*** %s set topic to \"%s\"", nick.characters(), topic.characters()), Color::DarkBlue);
+        add_message(String::format("*** %s set topic to \"%s\"", nick.characters(), topic.characters()), Color::MidBlue);
+}
+
+void IRCChannel::notify_nick_changed(const String& old_nick, const String& new_nick)
+{
+    for (auto& member : m_members) {
+        if (member.name == old_nick) {
+            member.name = new_nick;
+            add_message(String::format("~ %s changed nickname to %s", old_nick.characters(), new_nick.characters()), Color::MidMagenta);
+            m_member_model->update();
+            return;
+        }
+    }
 }

+ 2 - 0
Applications/IRCClient/IRCChannel.h

@@ -49,6 +49,8 @@ public:
 
     String topic() const { return m_topic; }
 
+    void notify_nick_changed(const String& old_nick, const String& new_nick);
+
 private:
     IRCChannel(IRCClient&, const String&);
 

+ 38 - 1
Applications/IRCClient/IRCClient.cpp

@@ -237,6 +237,9 @@ void IRCClient::handle(const Message& msg, const String&)
     if (msg.command == "PRIVMSG")
         return handle_privmsg(msg);
 
+    if (msg.command == "NICK")
+        return handle_nick(msg);
+
     if (msg.arguments.size() >= 2)
         add_server_message(String::format("[%s] %s", msg.command.characters(), msg.arguments[1].characters()));
 }
@@ -379,6 +382,25 @@ void IRCClient::handle_part(const Message& msg)
     ensure_channel(channel_name).handle_part(nick, msg.prefix);
 }
 
+void IRCClient::handle_nick(const Message& msg)
+{
+    auto prefix_parts = msg.prefix.split('!');
+    if (prefix_parts.size() < 1)
+        return;
+    auto old_nick = prefix_parts[0];
+    if (msg.arguments.size() != 1)
+        return;
+    auto& new_nick = msg.arguments[0];
+    if (old_nick == m_nickname)
+        m_nickname = new_nick;
+    add_server_message(String::format("~ %s changed nickname to %s", old_nick.characters(), new_nick.characters()));
+    if (on_nickname_changed)
+        on_nickname_changed(new_nick);
+    for (auto& it : m_channels) {
+        it.value->notify_nick_changed(old_nick, new_nick);
+    }
+}
+
 void IRCClient::handle_topic(const Message& msg)
 {
     if (msg.arguments.size() != 2)
@@ -500,7 +522,7 @@ void IRCClient::handle_rpl_topicwhotime(const Message& msg)
             tm->tm_sec
         );
     }
-    ensure_channel(channel_name).add_message(String::format("*** (set by %s at %s)", nick.characters(), setat.characters()), Color::DarkBlue);
+    ensure_channel(channel_name).add_message(String::format("*** (set by %s at %s)", nick.characters(), setat.characters()), Color::Blue);
 }
 
 void IRCClient::register_subwindow(IRCWindow& subwindow)
@@ -533,6 +555,11 @@ void IRCClient::handle_user_command(const String& input)
     if (parts.is_empty())
         return;
     auto command = parts[0].to_uppercase();
+    if (command == "/NICK") {
+        if (parts.size() >= 2)
+            change_nick(parts[1]);
+        return;
+    }
     if (command == "/JOIN") {
         if (parts.size() >= 2)
             join_channel(parts[1]);
@@ -555,6 +582,11 @@ void IRCClient::handle_user_command(const String& input)
     }
 }
 
+void IRCClient::change_nick(const String& nick)
+{
+    send(String::format("NICK %s\r\n", nick.characters()));
+}
+
 void IRCClient::handle_whois_action(const String& nick)
 {
     send_whois(nick);
@@ -565,6 +597,11 @@ void IRCClient::handle_open_query_action(const String& nick)
     ensure_query(nick);
 }
 
+void IRCClient::handle_change_nick_action(const String& nick)
+{
+    change_nick(nick);
+}
+
 void IRCClient::handle_close_query_action(const String& nick)
 {
     m_queries.remove(nick);

+ 4 - 0
Applications/IRCClient/IRCClient.h

@@ -29,6 +29,7 @@ public:
 
     void join_channel(const String&);
     void part_channel(const String&);
+    void change_nick(const String&);
 
     bool is_nick_prefix(char) const;
 
@@ -38,6 +39,7 @@ public:
     Function<void()> on_connect;
     Function<void()> on_disconnect;
     Function<void()> on_server_message;
+    Function<void(const String&)> on_nickname_changed;
 
     Function<IRCWindow*(void*, IRCWindow::Type, const String&)> aid_create_window;
     Function<IRCWindow*()> aid_get_active_window;
@@ -62,6 +64,7 @@ public:
     void handle_close_query_action(const String&);
     void handle_join_action(const String&);
     void handle_part_action(const String&);
+    void handle_change_nick_action(const String&);
 
     IRCQuery& ensure_query(const String& name);
     IRCChannel& ensure_channel(const String& name);
@@ -100,6 +103,7 @@ private:
     void handle_rpl_endofnames(const Message&);
     void handle_rpl_namreply(const Message&);
     void handle_privmsg(const Message&);
+    void handle_nick(const Message&);
     void handle(const Message&, const String& verbatim);
     void handle_user_command(const String&);
 

BIN
Base/res/icons/16x16/irc-nick.png


BIN
Base/res/icons/16x16/irc-nick.rgb


+ 4 - 0
SharedGraphics/Color.cpp

@@ -20,6 +20,10 @@ Color::Color(NamedColor named)
     case DarkGray: rgb = { 64, 64, 64 }; break;
     case MidGray: rgb = { 127, 127, 127 }; break;
     case LightGray: rgb = { 192, 192, 192 }; break;
+    case MidGreen: rgb = { 0, 192, 0 }; break;
+    case MidBlue: rgb = { 0, 0, 192 }; break;
+    case MidRed: rgb = { 192, 0, 0 }; break;
+    case MidMagenta: rgb = { 192, 0, 192 }; break;
     case DarkGreen: rgb = { 0, 128, 0 }; break;
     case DarkBlue: rgb = { 0, 0, 128 }; break;
     case DarkRed: rgb = { 128, 0, 0 }; break;

+ 4 - 0
SharedGraphics/Color.h

@@ -26,6 +26,10 @@ public:
         DarkGreen,
         DarkBlue,
         DarkRed,
+        MidGreen,
+        MidRed,
+        MidBlue,
+        MidMagenta,
     };
 
     Color() { }