From 67009cee8e6db04a3ba3b07a7bbde8c9e8e21b8a Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 20 Mar 2019 04:21:58 +0100 Subject: [PATCH] IRCClient: Add ability to change nickname. --- Applications/IRCClient/IRCAppWindow.cpp | 21 +++++++++++-- Applications/IRCClient/IRCAppWindow.h | 2 ++ Applications/IRCClient/IRCChannel.cpp | 20 +++++++++--- Applications/IRCClient/IRCChannel.h | 2 ++ Applications/IRCClient/IRCClient.cpp | 39 +++++++++++++++++++++++- Applications/IRCClient/IRCClient.h | 4 +++ Base/res/icons/16x16/irc-nick.png | Bin 0 -> 470 bytes Base/res/icons/16x16/irc-nick.rgb | Bin 0 -> 1024 bytes SharedGraphics/Color.cpp | 4 +++ SharedGraphics/Color.h | 4 +++ 10 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 Base/res/icons/16x16/irc-nick.png create mode 100644 Base/res/icons/16x16/irc-nick.rgb diff --git a/Applications/IRCClient/IRCAppWindow.cpp b/Applications/IRCClient/IRCAppWindow.cpp index 95ee161f3be..98edbc4030c 100644 --- a/Applications/IRCClient/IRCAppWindow.cpp +++ b/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("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(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(); diff --git a/Applications/IRCClient/IRCAppWindow.h b/Applications/IRCClient/IRCAppWindow.h index 367c494e398..e34c281f2ef 100644 --- a/Applications/IRCClient/IRCAppWindow.h +++ b/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 m_whois_action; RetainPtr m_open_query_action; RetainPtr m_close_query_action; + RetainPtr m_change_nick_action; }; diff --git a/Applications/IRCClient/IRCChannel.cpp b/Applications/IRCClient/IRCChannel.cpp index 97e644b91df..57e645bdd9e 100644 --- a/Applications/IRCClient/IRCChannel.cpp +++ b/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; + } + } } diff --git a/Applications/IRCClient/IRCChannel.h b/Applications/IRCClient/IRCChannel.h index 12c0ae491f5..8770dd181d3 100644 --- a/Applications/IRCClient/IRCChannel.h +++ b/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&); diff --git a/Applications/IRCClient/IRCClient.cpp b/Applications/IRCClient/IRCClient.cpp index b46773c23f1..1aeb56d69bd 100644 --- a/Applications/IRCClient/IRCClient.cpp +++ b/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); diff --git a/Applications/IRCClient/IRCClient.h b/Applications/IRCClient/IRCClient.h index 8c6029f39d8..2c582da4205 100644 --- a/Applications/IRCClient/IRCClient.h +++ b/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 on_connect; Function on_disconnect; Function on_server_message; + Function on_nickname_changed; Function aid_create_window; Function 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&); diff --git a/Base/res/icons/16x16/irc-nick.png b/Base/res/icons/16x16/irc-nick.png new file mode 100644 index 0000000000000000000000000000000000000000..e52da4d2f4bdbc975bc1a101b979a8fd9eaa641c GIT binary patch literal 470 zcmV;{0V)28P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00BNpL_t(I%Z-vfZo)tmgugW| zkP=Z^v}scL0+CF|B~m#BDYybOX>x`fflJVFh4lqe8A~grM%sBP42U1w;z?VKv@`o@ z-#B_E&vU!f-h0QRljphBb$vcnRoQLeX_7AUcDud1IGIf73Q7AYrqd|^RaNo1SP<0- za81zndX$hNe(6tnxfU&a$_TaEX%$wTlVz3%=U423yG_u2aw+acjbIZcnz6S41-Tc~CQK$&_-U7-MC*kFl4J@Rj9#NA?XdkoW$rw}?UmeB^!M>;A!N zjS$$^o%adp;5W2z2C9=t6DDy`vZE;6gB_= literal 0 HcmV?d00001 diff --git a/SharedGraphics/Color.cpp b/SharedGraphics/Color.cpp index f93b48b4581..bb66a2af1fa 100644 --- a/SharedGraphics/Color.cpp +++ b/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; diff --git a/SharedGraphics/Color.h b/SharedGraphics/Color.h index f077c0da72c..dd075e3c7ca 100644 --- a/SharedGraphics/Color.h +++ b/SharedGraphics/Color.h @@ -26,6 +26,10 @@ public: DarkGreen, DarkBlue, DarkRed, + MidGreen, + MidRed, + MidBlue, + MidMagenta, }; Color() { }