From 3e4080f2adcb1b3c583bb1b09176d38abaca5d46 Mon Sep 17 00:00:00 2001 From: Notify-ctrl <70358032+Notify-ctrl@users.noreply.github.com> Date: Sun, 27 Mar 2022 20:00:29 +0800 Subject: [PATCH] edit profile (#5) --- lua/server/server.lua | 30 ++++++++++ qml/GlobalPopups/CreateRoom.qml | 64 ++++++++++++++++++++ qml/GlobalPopups/EditProfile.qml | 100 +++++++++++++++++++++++++++++++ qml/GlobalPopups/Test.qml | 5 ++ qml/Pages/CreateRoom.qml | 63 ------------------- qml/Pages/Lobby.qml | 7 ++- qml/Pages/Logic.js | 13 ++++ qml/main.qml | 72 ++++++++++++++++++++-- src/client/clientplayer.h | 14 ++++- src/main.cpp | 20 ++++--- src/server/server.cpp | 8 ++- src/server/server.h | 4 +- src/swig/server.i | 2 + 13 files changed, 319 insertions(+), 83 deletions(-) create mode 100644 qml/GlobalPopups/CreateRoom.qml create mode 100644 qml/GlobalPopups/EditProfile.qml create mode 100644 qml/GlobalPopups/Test.qml delete mode 100644 qml/Pages/CreateRoom.qml create mode 100644 qml/Pages/Logic.js diff --git a/lua/server/server.lua b/lua/server/server.lua index 6f9e2411..7fe643ab 100644 --- a/lua/server/server.lua +++ b/lua/server/server.lua @@ -7,6 +7,7 @@ freekill.server_callback = {} function Server:initialize() self.server = freekill.ServerInstance + self.db = freekill.ServerInstance:getDatabase() self.server.callback = function(_self, command, jsonData) local cb = freekill.server_callback[command] if (type(cb) == "function") then @@ -33,6 +34,35 @@ function Server:initialize() self.players = {} end +freekill.server_callback["UpdateAvatar"] = function(jsonData) + -- jsonData: [ int uid, string newavatar ] + local data = json.decode(jsonData) + local id, avatar = data[1], data[2] + local sql = "UPDATE userinfo SET avatar='%s' WHERE id=%d;" + Sql.exec(ServerInstance.db, string.format(sql, avatar, id)) + local player = freekill.ServerInstance:findPlayer(id) + player:doNotify("UpdateAvatar", "[]") +end + +freekill.server_callback["UpdatePassword"] = function(jsonData) + -- jsonData: [ int uid, string oldpassword, int newpassword ] + local data = json.decode(jsonData) + local id, old, new = data[1], data[2], data[3] + local sql_find = "SELECT password FROM userinfo WHERE id=%d;" + local sql_update = "UPDATE userinfo SET password='%s' WHERE id=%d;" + + local db = ServerInstance.db + local passed = false + local result = Sql.exec_select(db, string.format(sql_find, id)) + passed = (result["password"][1] == sha256(old)) + if passed then + Sql.exec(db, string.format(sql_update, sha256(new), id)) + end + + local player = freekill.ServerInstance:findPlayer(tonumber(id)) + player:doNotify("UpdatePassword", passed and "1" or "0") +end + freekill.server_callback["CreateRoom"] = function(jsonData) -- jsonData: [ int uid, string name, int capacity ] local data = json.decode(jsonData) diff --git a/qml/GlobalPopups/CreateRoom.qml b/qml/GlobalPopups/CreateRoom.qml new file mode 100644 index 00000000..8a6383bd --- /dev/null +++ b/qml/GlobalPopups/CreateRoom.qml @@ -0,0 +1,64 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.15 + +Item { + id: root + + width: childrenRect.width + height: childrenRect.height + + signal finished() + + ColumnLayout { + spacing: 20 + + RowLayout { + anchors.rightMargin: 8 + spacing: 16 + Text { + text: "Room Name" + } + TextField { + id: roomName + font.pixelSize: 18 + text: Self.screenName + "'s Room" + } + } + + RowLayout { + anchors.rightMargin: 8 + spacing: 16 + Text { + text: "Player num" + } + SpinBox { + id: playerNum + from: 2 + to: 8 + } + } + + RowLayout { + anchors.rightMargin: 8 + spacing: 16 + Button { + text: "OK" + onClicked: { + root.finished(); + mainWindow.busy = true; + ClientInstance.notifyServer( + "CreateRoom", + JSON.stringify([roomName.text, playerNum.value]) + ); + } + } + Button { + text: "Cancel" + onClicked: { + root.finished(); + } + } + } + } +} diff --git a/qml/GlobalPopups/EditProfile.qml b/qml/GlobalPopups/EditProfile.qml new file mode 100644 index 00000000..c1ceb0d6 --- /dev/null +++ b/qml/GlobalPopups/EditProfile.qml @@ -0,0 +1,100 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.15 + +Item { + id: root + + width: childrenRect.width + height: childrenRect.height + + signal finished() + + ColumnLayout { + spacing: 20 + + RowLayout { + anchors.rightMargin: 8 + spacing: 16 + Text { + text: "Username" + } + Text { + text: Self.screenName + font.pixelSize: 18 + } + } + + RowLayout { + anchors.rightMargin: 8 + spacing: 16 + Text { + text: "Avatar" + } + TextField { + id: avatarName + font.pixelSize: 18 + text: Self.avatar + } + } + + RowLayout { + anchors.rightMargin: 8 + spacing: 16 + Text { + text: "Old Password" + } + TextField { + id: oldPassword + echoMode: TextInput.Password + passwordCharacter: "*" + } + } + + RowLayout { + anchors.rightMargin: 8 + spacing: 16 + Text { + text: "New Password" + } + TextField { + id: newPassword + echoMode: TextInput.Password + passwordCharacter: "*" + } + } + + RowLayout { + anchors.rightMargin: 8 + spacing: 16 + Button { + text: "Update Avatar" + enabled: avatarName.text !== "" + onClicked: { + mainWindow.busy = true; + ClientInstance.notifyServer( + "UpdateAvatar", + JSON.stringify([avatarName.text]) + ); + } + } + Button { + text: "Update Password" + enabled: oldPassword.text !== "" && newPassword.text !== "" + onClicked: { + mainWindow.busy = true; + ClientInstance.notifyServer( + "UpdatePassword", + JSON.stringify([oldPassword.text, newPassword.text]) + ); + } + } + Button { + text: "Exit" + onClicked: { + root.finished(); + } + } + } + } +} diff --git a/qml/GlobalPopups/Test.qml b/qml/GlobalPopups/Test.qml new file mode 100644 index 00000000..001f9e78 --- /dev/null +++ b/qml/GlobalPopups/Test.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Text { + text: "dsdsd" +} \ No newline at end of file diff --git a/qml/Pages/CreateRoom.qml b/qml/Pages/CreateRoom.qml deleted file mode 100644 index cd7ec04d..00000000 --- a/qml/Pages/CreateRoom.qml +++ /dev/null @@ -1,63 +0,0 @@ -import QtQuick 2.15 -import QtQuick.Controls 2.0 -import QtQuick.Layouts 1.15 - -Item { - id: root - Frame { - anchors.centerIn: parent - Column { - x: 32 - y: 20 - spacing: 20 - - RowLayout { - anchors.rightMargin: 8 - spacing: 16 - Text { - text: "Room Name" - } - TextField { - id: roomName - font.pixelSize: 18 - text: "tmp's Room" - } - } - - RowLayout { - anchors.rightMargin: 8 - spacing: 16 - Text { - text: "Player num" - } - SpinBox { - id: playerNum - from: 2 - to: 8 - } - } - - RowLayout { - anchors.rightMargin: 8 - spacing: 16 - Button { - text: "OK" - onClicked: { - mainWindow.busy = true; - mainStack.pop(); - ClientInstance.notifyServer( - "CreateRoom", - JSON.stringify([roomName.text, playerNum.value]) - ); - } - } - Button { - text: "Cancel" - onClicked: { - mainStack.pop(); - } - } - } - } - } -} diff --git a/qml/Pages/Lobby.qml b/qml/Pages/Lobby.qml index 547bfe33..0be44fe3 100644 --- a/qml/Pages/Lobby.qml +++ b/qml/Pages/Lobby.qml @@ -2,6 +2,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.0 import QtQuick.Window 2.0 import QtQuick.Layouts 1.15 +import "Logic.js" as Logic Item { id: root @@ -89,13 +90,15 @@ Item { Button { text: "Edit Profile" onClicked: { - + globalPopup.source = "EditProfile.qml"; + globalPopup.open(); } } Button { text: "Create Room" onClicked: { - mainStack.push(createRoom); + globalPopup.source = "CreateRoom.qml"; + globalPopup.open(); } } Button { diff --git a/qml/Pages/Logic.js b/qml/Pages/Logic.js new file mode 100644 index 00000000..91f97342 --- /dev/null +++ b/qml/Pages/Logic.js @@ -0,0 +1,13 @@ +callbacks["UpdateAvatar"] = function(jsonData) { + mainWindow.busy = false; + self.avatar = avatarName.text; + toast.show("Update avatar done."); +} + +callbacks["UpdatePassword"] = function(jsonData) { + mainWindow.busy = false; + if (jsonData === "1") + toast.show("Update password done."); + else + toast.show("Old password wrong!", 5000); +} diff --git a/qml/main.qml b/qml/main.qml index 1e5f74c2..bbcb1439 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -33,11 +33,6 @@ Window { Room {} } - Component { - id: createRoom - CreateRoom {} - } - property bool busy: false BusyIndicator { running: true @@ -49,6 +44,73 @@ Window { id: config } + // global popup. it is modal and just lower than toast + Rectangle { + id: globalPopupDim + anchors.fill: parent + color: "black" + opacity: 0 + visible: !mainWindow.busy + + property bool stateVisible: false + states: [ + State { + when: globalPopupDim.stateVisible + PropertyChanges { target: globalPopupDim; opacity: 0.5 } + }, + State { + when: !globalPopupDim.stateVisible + PropertyChanges { target: globalPopupDim; opacity: 0.0 } + } + ] + + transitions: Transition { + NumberAnimation { properties: "opacity"; easing.type: Easing.InOutQuad } + } + } + + Popup { + id: globalPopup + property string source: "" + modal: true + dim: false // cannot animate the dim + focus: true + opacity: mainWindow.busy ? 0 : 1 + closePolicy: Popup.CloseOnEscape + anchors.centerIn: parent + + onAboutToShow: { + globalPopupDim.stateVisible = true + } + + enter: Transition { + NumberAnimation { properties: "opacity"; from: 0; to: 1 } + NumberAnimation { properties: "scale"; from: 0.4; to: 1 } + } + + onAboutToHide: { + globalPopupDim.stateVisible = false + } + + exit: Transition { + NumberAnimation { properties: "opacity"; from: 1; to: 0 } + NumberAnimation { properties: "scale"; from: 1; to: 0.4 } + } + + Loader { + visible: !mainWindow.busy + source: globalPopup.source === "" ? "" : "GlobalPopups/" + globalPopup.source + onSourceChanged: { + if (item === null) + return; + item.finished.connect(() => { + globalPopup.close(); + globalPopup.source = ""; + }); + } + } + } + ToastManager { id: toast } diff --git a/src/client/clientplayer.h b/src/client/clientplayer.h index 54df4901..c0f8a663 100644 --- a/src/client/clientplayer.h +++ b/src/client/clientplayer.h @@ -6,9 +6,17 @@ class ClientPlayer : public Player { Q_OBJECT - Q_PROPERTY(int id READ getId) - Q_PROPERTY(QString screenName READ getScreenName WRITE setScreenName) - Q_PROPERTY(QString avatar READ getAvatar WRITE setAvatar) + Q_PROPERTY(int id READ getId CONSTANT) + Q_PROPERTY(QString screenName + READ getScreenName + WRITE setScreenName + NOTIFY screenNameChanged + ) + Q_PROPERTY(QString avatar + READ getAvatar + WRITE setAvatar + NOTIFY avatarChanged + ) public: ClientPlayer(int id, QObject *parent = nullptr); diff --git a/src/main.cpp b/src/main.cpp index faf9f3c9..818b5e5c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,20 +29,26 @@ int main(int argc, char *argv[]) return app.exec(); } - QQmlApplicationEngine engine; + QQmlApplicationEngine *engine = new QQmlApplicationEngine; QmlBackend backend; - backend.setEngine(&engine); + backend.setEngine(engine); - engine.rootContext()->setContextProperty("Backend", &backend); - engine.rootContext()->setContextProperty("AppPath", QUrl::fromLocalFile(QDir::currentPath())); + engine->rootContext()->setContextProperty("Backend", &backend); + engine->rootContext()->setContextProperty("AppPath", QUrl::fromLocalFile(QDir::currentPath())); #ifdef QT_DEBUG bool debugging = true; #else bool debugging = false; #endif - engine.rootContext()->setContextProperty("Debugging", debugging); - engine.load("qml/main.qml"); + engine->rootContext()->setContextProperty("Debugging", debugging); + engine->load("qml/main.qml"); - return app.exec(); + int ret = app.exec(); + + // delete the engine first + // to avoid "TypeError: Cannot read property 'xxx' of null" + delete engine; + + return ret; } diff --git a/src/server/server.cpp b/src/server/server.cpp index 5cf9d48f..270ea3c4 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -22,11 +22,11 @@ Server::Server(QObject* parent) connect(lobby(), &Room::playerAdded, this, &Server::updateRoomList); connect(lobby(), &Room::playerRemoved, this, &Server::updateRoomList); + db = OpenDatabase(); + L = CreateLuaState(); DoLuaScript(L, "lua/freekill.lua"); DoLuaScript(L, "lua/server/server.lua"); - - db = OpenDatabase(); } Server::~Server() @@ -95,6 +95,10 @@ void Server::updateRoomList() ); } +sqlite3 *Server::getDatabase() { + return db; +} + void Server::processNewConnection(ClientSocket* client) { qDebug() << client->peerAddress() << "connected"; diff --git a/src/server/server.h b/src/server/server.h index 39756289..108eedd8 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -24,6 +24,8 @@ public: void updateRoomList(); + sqlite3 *getDatabase(); + void callLua(const QString &command, const QString &jsonData); LuaFunction callback; @@ -49,8 +51,8 @@ private: QMap rooms; QHash players; - lua_State *L; sqlite3 *db; + lua_State *L; void handleNameAndPassword(ClientSocket *client, const QString &name, const QString &password); }; diff --git a/src/swig/server.i b/src/swig/server.i index 576ed725..a028442b 100644 --- a/src/swig/server.i +++ b/src/swig/server.i @@ -6,6 +6,8 @@ public: Room *findRoom(int id) const; ServerPlayer *findPlayer(int id) const; + sqlite3 *getDatabase(); + LuaFunction callback; LuaFunction startRoom; };