edit profile (#5)

This commit is contained in:
Notify-ctrl 2022-03-27 20:00:29 +08:00 committed by GitHub
parent a67175f8eb
commit 3e4080f2ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 319 additions and 83 deletions

View File

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

View File

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

View File

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

View File

@ -0,0 +1,5 @@
import QtQuick 2.0
Text {
text: "dsdsd"
}

View File

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

View File

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

13
qml/Pages/Logic.js Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<int, Room *> rooms;
QHash<int, ServerPlayer *> players;
lua_State *L;
sqlite3 *db;
lua_State *L;
void handleNameAndPassword(ClientSocket *client, const QString &name, const QString &password);
};

View File

@ -6,6 +6,8 @@ public:
Room *findRoom(int id) const;
ServerPlayer *findPlayer(int id) const;
sqlite3 *getDatabase();
LuaFunction callback;
LuaFunction startRoom;
};