From d35693bbbc870265c41dacd02cce803f72ba6d9d Mon Sep 17 00:00:00 2001
From: James Rowe <jroweboy@gmail.com>
Date: Thu, 19 Apr 2018 10:23:39 -0600
Subject: [PATCH] More minor issue fixes

* Move Joining state change sooner in the code to prevent an issue where
failing to connect multiple times in a row doesn't change the state (as
it goes from CouldNotConnect -> CouldNotConnect which doesn't trigger a
state changed callback)
* Prevent double clicking too fast on a room in the lobby from causing
issues
* Lobby no longer closes when joining a room
---
 src/citra_qt/multiplayer/lobby.cpp | 29 +++++------------------------
 src/citra_qt/multiplayer/lobby.h   | 18 +-----------------
 src/citra_qt/multiplayer/state.cpp | 16 +---------------
 src/network/room_member.cpp        |  3 ++-
 src/network/room_member.h          | 26 ++++++++++++++++++++++++++
 5 files changed, 35 insertions(+), 57 deletions(-)

diff --git a/src/citra_qt/multiplayer/lobby.cpp b/src/citra_qt/multiplayer/lobby.cpp
index aca07f59c..0b58091cb 100644
--- a/src/citra_qt/multiplayer/lobby.cpp
+++ b/src/citra_qt/multiplayer/lobby.cpp
@@ -26,7 +26,7 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
 
     // setup the watcher for background connections
     watcher = new QFutureWatcher<void>;
-    connect(watcher, &QFutureWatcher<void>::finished, this, &Lobby::OnConnection);
+    connect(watcher, &QFutureWatcher<void>::finished, [&] { joining = false; });
 
     model = new QStandardItemModel(ui->room_list);
     proxy = new LobbyFilterProxyModel(this, game_list);
@@ -62,8 +62,6 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
 
     // Actions
     connect(this, &Lobby::LobbyRefreshed, this, &Lobby::OnRefreshLobby);
-    // TODO(jroweboy): change this slot to OnConnected?
-    connect(this, &Lobby::Connected, p, &MultiplayerState::OnOpenNetworkRoom);
 
     // manually start a refresh when the window is opening
     // TODO(jroweboy): if this refresh is slow for people with bad internet, then don't do it as
@@ -86,6 +84,10 @@ void Lobby::OnExpandRoom(const QModelIndex& index) {
 }
 
 void Lobby::OnJoinRoom(const QModelIndex& source) {
+    if (joining) {
+        return;
+    }
+    joining = true;
     QModelIndex index = source;
     // If the user double clicks on a child row (aka the player list) then use the parent instead
     if (source.parent() != QModelIndex()) {
@@ -301,24 +303,3 @@ void LobbyFilterProxyModel::SetFilterSearch(const QString& filter) {
     filter_search = filter;
     invalidate();
 }
-
-void Lobby::OnConnection() {
-    if (auto room_member = Network::GetRoomMember().lock()) {
-        switch (room_member->GetState()) {
-        case Network::RoomMember::State::CouldNotConnect:
-            ShowError(NetworkMessage::UNABLE_TO_CONNECT);
-            break;
-        case Network::RoomMember::State::NameCollision:
-            ShowError(NetworkMessage::USERNAME_IN_USE);
-            break;
-        case Network::RoomMember::State::Error:
-            ShowError(NetworkMessage::UNABLE_TO_CONNECT);
-            break;
-        case Network::RoomMember::State::Joining:
-            auto parent = static_cast<MultiplayerState*>(parentWidget());
-            parent->OnOpenNetworkRoom();
-            close();
-            break;
-        }
-    }
-}
diff --git a/src/citra_qt/multiplayer/lobby.h b/src/citra_qt/multiplayer/lobby.h
index d44c7fcbc..783225737 100644
--- a/src/citra_qt/multiplayer/lobby.h
+++ b/src/citra_qt/multiplayer/lobby.h
@@ -60,29 +60,12 @@ private slots:
      */
     void OnJoinRoom(const QModelIndex&);
 
-    /**
-     * Handler for connection status changes. Launches the client room window if successful or
-     * displays an error
-     */
-    void OnConnection();
-
 signals:
     /**
      * Signalled when the latest lobby data is retrieved.
      */
     void LobbyRefreshed();
 
-    /**
-     * Signalled when the status for room connection changes.
-     */
-    void Connected();
-
-    /**
-     * Signalled by this widget when it is closing itself and destroying any state such as
-     * connections that it might have.
-     */
-    void Closed();
-
     void StateChanged(const Network::RoomMember::State&);
 
 private:
@@ -106,6 +89,7 @@ private:
     std::unique_ptr<Ui::Lobby> ui;
     QFutureWatcher<void>* watcher;
     Validation validation;
+    bool joining = false;
 };
 
 /**
diff --git a/src/citra_qt/multiplayer/state.cpp b/src/citra_qt/multiplayer/state.cpp
index f741b299b..dfd5ee66f 100644
--- a/src/citra_qt/multiplayer/state.cpp
+++ b/src/citra_qt/multiplayer/state.cpp
@@ -66,45 +66,31 @@ void MultiplayerState::Close() {
 }
 
 void MultiplayerState::OnNetworkStateChanged(const Network::RoomMember::State& state) {
-    NGLOG_DEBUG(Frontend, "Network state change");
+    NGLOG_DEBUG(Frontend, "Network State: {}", Network::GetStateStr(state));
     bool is_connected = false;
     switch (state) {
-    case Network::RoomMember::State::Idle:
-        NGLOG_DEBUG(Network, "State: Idle");
-        break;
-    case Network::RoomMember::State::Joining:
-        NGLOG_DEBUG(Network, "State: Joining");
-        break;
     case Network::RoomMember::State::LostConnection:
         NetworkMessage::ShowError(NetworkMessage::LOST_CONNECTION);
-        NGLOG_DEBUG(Network, "State: LostConnection");
         break;
     case Network::RoomMember::State::CouldNotConnect:
         NetworkMessage::ShowError(NetworkMessage::UNABLE_TO_CONNECT);
-        NGLOG_DEBUG(Network, "State: CouldNotConnect");
         break;
     case Network::RoomMember::State::NameCollision:
         NetworkMessage::ShowError(NetworkMessage::USERNAME_IN_USE);
-        NGLOG_DEBUG(Network, "State: NameCollision");
         break;
     case Network::RoomMember::State::MacCollision:
         NetworkMessage::ShowError(NetworkMessage::MAC_COLLISION);
-        NGLOG_DEBUG(Network, "State: MacCollision");
         break;
     case Network::RoomMember::State::WrongPassword:
         NetworkMessage::ShowError(NetworkMessage::WRONG_PASSWORD);
-        NGLOG_DEBUG(Network, "State: WrongPassword");
         break;
     case Network::RoomMember::State::WrongVersion:
         NetworkMessage::ShowError(NetworkMessage::WRONG_VERSION);
-        NGLOG_DEBUG(Network, "State: WrongVersion");
         break;
     case Network::RoomMember::State::Error:
         NetworkMessage::ShowError(NetworkMessage::UNABLE_TO_CONNECT);
-        NGLOG_DEBUG(Network, "State: GenericError");
         break;
     case Network::RoomMember::State::Joined:
-        NGLOG_DEBUG(Network, "State: Joined");
         is_connected = true;
         OnOpenNetworkRoom();
         break;
diff --git a/src/network/room_member.cpp b/src/network/room_member.cpp
index 3a143ce5d..e8d9094c5 100644
--- a/src/network/room_member.cpp
+++ b/src/network/room_member.cpp
@@ -406,6 +406,8 @@ void RoomMember::Join(const std::string& nick, const char* server_addr, u16 serv
         ASSERT_MSG(room_member_impl->client != nullptr, "Could not create client");
     }
 
+    room_member_impl->SetState(State::Joining);
+
     ENetAddress address{};
     enet_address_set_host(&address, server_addr);
     address.port = server_port;
@@ -421,7 +423,6 @@ void RoomMember::Join(const std::string& nick, const char* server_addr, u16 serv
     int net = enet_host_service(room_member_impl->client, &event, ConnectionTimeoutMs);
     if (net > 0 && event.type == ENET_EVENT_TYPE_CONNECT) {
         room_member_impl->nickname = nick;
-        room_member_impl->SetState(State::Joining);
         room_member_impl->StartLoop();
         room_member_impl->SendJoinRequest(nick, preferred_mac, password);
         SendGameInfo(room_member_impl->current_game_info);
diff --git a/src/network/room_member.h b/src/network/room_member.h
index 77b73890d..d01eb7dcd 100644
--- a/src/network/room_member.h
+++ b/src/network/room_member.h
@@ -187,4 +187,30 @@ private:
     std::unique_ptr<RoomMemberImpl> room_member_impl;
 };
 
+static const char* GetStateStr(const RoomMember::State& s) {
+    switch (s) {
+    case RoomMember::State::Idle:
+        return "Idle";
+    case RoomMember::State::Error:
+        return "Error";
+    case RoomMember::State::Joining:
+        return "Joining";
+    case RoomMember::State::Joined:
+        return "Joined";
+    case RoomMember::State::LostConnection:
+        return "LostConnection";
+    case RoomMember::State::NameCollision:
+        return "NameCollision";
+    case RoomMember::State::MacCollision:
+        return "MacCollision";
+    case RoomMember::State::WrongVersion:
+        return "WrongVersion";
+    case RoomMember::State::WrongPassword:
+        return "WrongPassword";
+    case RoomMember::State::CouldNotConnect:
+        return "CouldNotConnect";
+    }
+    return "Unknown";
+}
+
 } // namespace Network