IRCClient: Add ability to change nickname.

This commit is contained in:
Andreas Kling 2019-03-20 04:21:58 +01:00
parent 4ea625e08b
commit 67009cee8e
Notes: sideshowbarker 2024-07-19 14:59:42 +09:00
10 changed files with 89 additions and 7 deletions

View File

@ -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();

View File

@ -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;
};

View File

@ -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;
}
}
}

View File

@ -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&);

View File

@ -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);

View File

@ -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&);

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

View File

@ -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;

View File

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