POST requests for APIRequest, allow saving user details from within the game, Asynchronous HTTP POST
This commit is contained in:
parent
b4564f212a
commit
81a34222d1
@ -3,6 +3,7 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <iomanip>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
@ -1181,6 +1182,40 @@ std::vector<unsigned char> Client::GetSaveData(int saveID, int saveDate)
|
||||
return saveData;
|
||||
}
|
||||
|
||||
RequestBroker::Request * Client::SaveUserInfoAsync(UserInfo info)
|
||||
{
|
||||
class StatusParser: public APIResultParser
|
||||
{
|
||||
virtual void * ProcessResponse(unsigned char * data, int dataLength)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::istringstream dataStream((char*)data);
|
||||
json::Object objDocument;
|
||||
json::Reader::Read(objDocument, dataStream);
|
||||
json::Number tempStatus = objDocument["Status"];
|
||||
|
||||
bool returnValue = tempStatus.Value() == 1;
|
||||
|
||||
return (void*)(returnValue ? 1 : 0);
|
||||
}
|
||||
catch (json::Exception &e)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
virtual void Cleanup(void * objectPtr)
|
||||
{
|
||||
//delete (UserInfo*)objectPtr;
|
||||
}
|
||||
virtual ~StatusParser() { }
|
||||
};
|
||||
std::map<std::string, std::string> postData;
|
||||
postData.insert(std::pair<std::string, std::string>("Location", info.Location));
|
||||
postData.insert(std::pair<std::string, std::string>("Biography", info.Biography));
|
||||
return new APIRequest("http://" SERVER "/Profile.json", postData, new StatusParser());
|
||||
}
|
||||
|
||||
RequestBroker::Request * Client::GetUserInfoAsync(std::string username)
|
||||
{
|
||||
class UserInfoParser: public APIResultParser
|
||||
@ -1197,13 +1232,15 @@ RequestBroker::Request * Client::GetUserInfoAsync(std::string username)
|
||||
json::Number userIDTemp = tempUser["ID"];
|
||||
json::String usernameTemp = tempUser["Username"];
|
||||
json::String bioTemp = tempUser["Biography"];
|
||||
//json::Number ageTemp = tempUser["Age"];
|
||||
json::String locationTemp = tempUser["Location"];
|
||||
json::Number ageTemp = tempUser["Age"];
|
||||
|
||||
return new UserInfo(
|
||||
userIDTemp.Value(),
|
||||
0,//ageTemp.Value(),
|
||||
ageTemp.Value(),
|
||||
usernameTemp.Value(),
|
||||
bioTemp.Value());
|
||||
bioTemp.Value(),
|
||||
locationTemp.Value());
|
||||
}
|
||||
catch (json::Exception &e)
|
||||
{
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "Singleton.h"
|
||||
|
||||
#include "User.h"
|
||||
#include "UserInfo.h"
|
||||
|
||||
#include "cajun/elements.h"
|
||||
|
||||
@ -93,6 +94,9 @@ public:
|
||||
std::vector<std::string> DirectorySearch(std::string directory, std::string search, std::vector<std::string> extensions);
|
||||
std::vector<std::string> DirectorySearch(std::string directory, std::string search, std::string extension);
|
||||
|
||||
std::string FileOpenDialogue();
|
||||
//std::string FileSaveDialogue();
|
||||
|
||||
bool DoInstallation();
|
||||
|
||||
std::vector<unsigned char> ReadFile(std::string filename);
|
||||
@ -130,6 +134,7 @@ public:
|
||||
|
||||
//Retrieves a "UserInfo" object
|
||||
RequestBroker::Request * GetUserInfoAsync(std::string username);
|
||||
RequestBroker::Request * SaveUserInfoAsync(UserInfo info);
|
||||
|
||||
unsigned char * GetSaveData(int saveID, int saveDate, int & dataLength);
|
||||
std::vector<unsigned char> GetSaveData(int saveID, int saveDate);
|
||||
|
@ -1102,3 +1102,194 @@ fail:
|
||||
*len = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void *http_multipart_post_async(char *uri, char **names, char **parts, int *plens, char *user, char *pass, char *session_id)
|
||||
{
|
||||
void *ctx;
|
||||
char *data = NULL, *tmp, *p;
|
||||
int dlen = 0, i, j;
|
||||
unsigned char hash[16];
|
||||
unsigned char boundary[32], ch;
|
||||
int blen = 0;
|
||||
unsigned int map[62], m;
|
||||
struct md5_context md5;
|
||||
//struct md5_context md52;
|
||||
int own_plen = 0;
|
||||
|
||||
if (names)
|
||||
{
|
||||
if (!plens)
|
||||
{
|
||||
own_plen = 1;
|
||||
for (i=0; names[i]; i++) ;
|
||||
plens = (int *)calloc(i, sizeof(int));
|
||||
for (i=0; names[i]; i++)
|
||||
plens[i] = strlen(parts[i]);
|
||||
}
|
||||
|
||||
retry:
|
||||
if (blen >= 31)
|
||||
goto fail;
|
||||
memset(map, 0, 62*sizeof(int));
|
||||
for (i=0; names[i]; i++)
|
||||
{
|
||||
for (j=0; j<plens[i]-blen; j++)
|
||||
if (!blen || !memcmp(parts[i]+j, boundary, blen))
|
||||
{
|
||||
ch = parts[i][j+blen];
|
||||
if (ch>='0' && ch<='9')
|
||||
map[ch-'0']++;
|
||||
else if (ch>='A' && ch<='Z')
|
||||
map[ch-'A'+10]++;
|
||||
else if (ch>='a' && ch<='z')
|
||||
map[ch-'a'+36]++;
|
||||
}
|
||||
}
|
||||
m = ~0;
|
||||
j = 61;
|
||||
for (i=0; i<62; i++)
|
||||
if (map[i]<m)
|
||||
{
|
||||
m = map[i];
|
||||
j = i;
|
||||
}
|
||||
if (j<10)
|
||||
boundary[blen] = '0'+j;
|
||||
else if (j<36)
|
||||
boundary[blen] = 'A'+(j-10);
|
||||
else
|
||||
boundary[blen] = 'a'+(j-36);
|
||||
blen++;
|
||||
if (map[j])
|
||||
goto retry;
|
||||
boundary[blen] = 0;
|
||||
|
||||
for (i=0; names[i]; i++)
|
||||
dlen += blen+strlen(names[i])+plens[i]+128;
|
||||
dlen += blen+8;
|
||||
data = (char *)malloc(dlen);
|
||||
dlen = 0;
|
||||
for (i=0; names[i]; i++)
|
||||
{
|
||||
dlen += sprintf(data+dlen, "--%s\r\n", boundary);
|
||||
dlen += sprintf(data+dlen, "Content-transfer-encoding: binary\r\n");
|
||||
if (strchr(names[i], ':'))
|
||||
{
|
||||
tmp = mystrdup(names[i]);
|
||||
p = strchr(tmp, ':');
|
||||
*p = 0;
|
||||
dlen += sprintf(data+dlen, "content-disposition: form-data; name=\"%s\"; ", tmp);
|
||||
free(tmp);
|
||||
p = strchr(names[i], ':');
|
||||
dlen += sprintf(data+dlen, "filename=\"%s\"\r\n\r\n", p+1);
|
||||
}
|
||||
else
|
||||
dlen += sprintf(data+dlen, "content-disposition: form-data; name=\"%s\"\r\n\r\n", names[i]);
|
||||
memcpy(data+dlen, parts[i], plens[i]);
|
||||
dlen += plens[i];
|
||||
dlen += sprintf(data+dlen, "\r\n");
|
||||
}
|
||||
dlen += sprintf(data+dlen, "--%s--\r\n", boundary);
|
||||
}
|
||||
|
||||
ctx = http_async_req_start(NULL, uri, data, dlen, 0);
|
||||
if (!ctx)
|
||||
goto fail;
|
||||
|
||||
if (user)
|
||||
{
|
||||
//http_async_add_header(ctx, "X-Auth-User", user);
|
||||
if (pass)
|
||||
{
|
||||
md5_init(&md5);
|
||||
md5_update(&md5, (unsigned char *)user, strlen(user));
|
||||
md5_update(&md5, (unsigned char *)"-", 1);
|
||||
m = 0;
|
||||
if (names)
|
||||
{
|
||||
for (i=0; names[i]; i++)
|
||||
{
|
||||
//md5_update(&md5, (unsigned char *)parts[i], plens[i]); //WHY?
|
||||
//md5_update(&md5, (unsigned char *)"-", 1);
|
||||
p = strchr(names[i], ':');
|
||||
if (p)
|
||||
m += (p - names[i]) + 1;
|
||||
else
|
||||
m += strlen(names[i])+1;
|
||||
}
|
||||
|
||||
tmp = (char *)malloc(m);
|
||||
m = 0;
|
||||
for (i=0; names[i]; i++)
|
||||
{
|
||||
p = strchr(names[i], ':');
|
||||
if (m)
|
||||
{
|
||||
tmp[m] = ' ';
|
||||
m ++;
|
||||
}
|
||||
if (p)
|
||||
{
|
||||
memcpy(tmp+m, names[i], p-names[i]);
|
||||
m += p - names[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(tmp+m, names[i]);
|
||||
m += strlen(names[i]);
|
||||
}
|
||||
}
|
||||
tmp[m] = 0;
|
||||
http_async_add_header(ctx, "X-Auth-Objects", tmp);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
md5_update(&md5, (unsigned char *)pass, strlen(pass));
|
||||
md5_final(hash, &md5);
|
||||
tmp = (char *)malloc(33);
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
tmp[i*2] = hexChars[hash[i]>>4];
|
||||
tmp[i*2+1] = hexChars[hash[i]&15];
|
||||
}
|
||||
tmp[32] = 0;
|
||||
http_async_add_header(ctx, "X-Auth-Hash", tmp);
|
||||
free(tmp);
|
||||
}
|
||||
if (session_id)
|
||||
{
|
||||
http_async_add_header(ctx, "X-Auth-User-Id", user);
|
||||
http_async_add_header(ctx, "X-Auth-Session-Key", session_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
http_async_add_header(ctx, "X-Auth-User", user);
|
||||
}
|
||||
}
|
||||
|
||||
if (data)
|
||||
{
|
||||
tmp = (char *)malloc(32+strlen((char *)boundary));
|
||||
sprintf(tmp, "multipart/form-data, boundary=%s", boundary);
|
||||
http_async_add_header(ctx, "Content-type", tmp);
|
||||
free(tmp);
|
||||
free(data);
|
||||
}
|
||||
|
||||
if (own_plen)
|
||||
free(plens);
|
||||
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
if (data)
|
||||
free(data);
|
||||
if (own_plen)
|
||||
free(plens);
|
||||
//if (ret)
|
||||
// *ret = 600;
|
||||
//if (len)
|
||||
// *len = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ char *http_async_req_stop(void *ctx, int *ret, int *len);
|
||||
void http_async_req_close(void *ctx);
|
||||
|
||||
char *http_multipart_post(char *uri, char **names, char **parts, int *plens, char *user, char *pass, char * session_id, int *ret, int *len);
|
||||
void *http_multipart_post_async(char *uri, char **names, char **parts, int *plens, char *user, char *pass, char * session_id);
|
||||
|
||||
char *http_ret_text(int ret);
|
||||
|
||||
|
@ -10,12 +10,15 @@ public:
|
||||
int Age;
|
||||
std::string Username;
|
||||
std::string Biography;
|
||||
UserInfo(int id, int age, std::string username, std::string biography):
|
||||
std::string Location;
|
||||
UserInfo(int id, int age, std::string username, std::string biography, std::string location):
|
||||
ID(id),
|
||||
Age(age),
|
||||
Username(username),
|
||||
Biography(biography)
|
||||
Biography(biography),
|
||||
Location(location)
|
||||
{ }
|
||||
UserInfo() {}
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include "Config.h"
|
||||
#include "Format.h"
|
||||
#include "client/Client.h"
|
||||
#include "APIRequest.h"
|
||||
#include "client/HTTP.h"
|
||||
#include "APIResultParser.h"
|
||||
@ -8,6 +12,17 @@
|
||||
APIRequest::APIRequest(std::string url, APIResultParser * parser, ListenerHandle listener):
|
||||
RequestBroker::Request(API, listener)
|
||||
{
|
||||
Post = false;
|
||||
HTTPContext = NULL;
|
||||
Parser = parser;
|
||||
URL = url;
|
||||
}
|
||||
|
||||
APIRequest::APIRequest(std::string url, std::map<std::string, std::string> postData, APIResultParser * parser, ListenerHandle listener):
|
||||
RequestBroker::Request(API, listener)
|
||||
{
|
||||
Post = true;
|
||||
PostData = postData;
|
||||
HTTPContext = NULL;
|
||||
Parser = parser;
|
||||
URL = url;
|
||||
@ -26,17 +41,18 @@ RequestBroker::ProcessResponse APIRequest::Process(RequestBroker & rb)
|
||||
if (status == 200 && data)
|
||||
{
|
||||
void * resultObject = Parser->ProcessResponse((unsigned char *)data, data_size);
|
||||
free(data);
|
||||
|
||||
if(resultObject)
|
||||
{
|
||||
this->ResultObject = resultObject;
|
||||
rb.requestComplete(this);
|
||||
free(data);
|
||||
return RequestBroker::Finished;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << typeid(*this).name() << " Request for " << URL << " could not be parsed" << status << std::endl;
|
||||
std::cout << typeid(*this).name() << " Request for " << URL << " could not be parsed: " << data << std::endl;
|
||||
free(data);
|
||||
return RequestBroker::Failed;
|
||||
}
|
||||
}
|
||||
@ -55,7 +71,50 @@ RequestBroker::ProcessResponse APIRequest::Process(RequestBroker & rb)
|
||||
else
|
||||
{
|
||||
std::cout << typeid(*this).name() << " New Request for " << URL << std::endl;
|
||||
HTTPContext = http_async_req_start(NULL, (char *)URL.c_str(), NULL, 0, 0);
|
||||
if(Post)
|
||||
{
|
||||
char ** postNames = new char*[PostData.size() + 1];
|
||||
char ** postData = new char*[PostData.size()];
|
||||
int * postLength = new int[PostData.size()];
|
||||
|
||||
int i = 0;
|
||||
std::map<std::string, std::string>::iterator iter = PostData.begin();
|
||||
while(iter != PostData.end())
|
||||
{
|
||||
std::string name = iter->first;
|
||||
std::string data = iter->second;
|
||||
char * cName = new char[name.length() + 1];
|
||||
char * cData = new char[data.length() + 1];
|
||||
std::strcpy(cName, name.c_str());
|
||||
std::strcpy(cData, data.c_str());
|
||||
postNames[i] = cName;
|
||||
postData[i] = cData;
|
||||
postLength[i] = data.length();
|
||||
i++;
|
||||
iter++;
|
||||
}
|
||||
postNames[i] = NULL;
|
||||
|
||||
if(Client::Ref().GetAuthUser().ID)
|
||||
{
|
||||
std::cout << typeid(*this).name() << " Authenticated " << std::endl;
|
||||
User user = Client::Ref().GetAuthUser();
|
||||
char userName[12];
|
||||
char userSession[user.SessionID.length() + 1];
|
||||
std::strcpy(userName, format::NumberToString<int>(user.ID).c_str());
|
||||
std::strcpy(userSession, user.SessionID.c_str());
|
||||
HTTPContext = http_multipart_post_async((char*)URL.c_str(), postNames, postData, postLength, userName, NULL, userSession);
|
||||
}
|
||||
else
|
||||
{
|
||||
HTTPContext = http_multipart_post_async((char*)URL.c_str(), postNames, postData, postLength, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
HTTPContext = http_async_req_start(NULL, (char *)URL.c_str(), NULL, 0, 0);
|
||||
}
|
||||
//RequestTime = time(NULL);
|
||||
}
|
||||
return RequestBroker::OK;
|
||||
|
@ -1,13 +1,17 @@
|
||||
#include <map>
|
||||
#include "RequestBroker.h"
|
||||
|
||||
class APIResultParser;
|
||||
class APIRequest: public RequestBroker::Request
|
||||
{
|
||||
public:
|
||||
bool Post;
|
||||
APIResultParser * Parser;
|
||||
std::string URL;
|
||||
std::map<std::string, std::string> PostData;
|
||||
void * HTTPContext;
|
||||
APIRequest(std::string url, APIResultParser * parser, ListenerHandle listener = ListenerHandle(0, 0));
|
||||
APIRequest(std::string url, std::map<std::string, std::string>, APIResultParser * parser, ListenerHandle listener = ListenerHandle(0, 0));
|
||||
virtual RequestBroker::ProcessResponse Process(RequestBroker & rb);
|
||||
virtual ~APIRequest();
|
||||
virtual void Cleanup();
|
||||
|
@ -3,15 +3,20 @@
|
||||
#include "interface/Button.h"
|
||||
#include "interface/Textbox.h"
|
||||
#include "interface/Label.h"
|
||||
#include "interface/AvatarButton.h"
|
||||
#include "interface/ScrollPanel.h"
|
||||
#include "interface/Keys.h"
|
||||
#include "Style.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/UserInfo.h"
|
||||
#include "client/requestbroker/RequestListener.h"
|
||||
|
||||
ProfileActivity::ProfileActivity(std::string username) :
|
||||
WindowActivity(ui::Point(-1, -1), ui::Point(236, 302))
|
||||
WindowActivity(ui::Point(-1, -1), ui::Point(236, 200)),
|
||||
loading(false),
|
||||
saving(false)
|
||||
{
|
||||
bool editable = Client::Ref().GetAuthUser().ID && Client::Ref().GetAuthUser().Username == username;
|
||||
editable = Client::Ref().GetAuthUser().ID && Client::Ref().GetAuthUser().Username == username;
|
||||
|
||||
|
||||
class CloseAction: public ui::ButtonAction
|
||||
@ -32,6 +37,15 @@ ProfileActivity::ProfileActivity(std::string username) :
|
||||
SaveAction(ProfileActivity * a) : a(a) { }
|
||||
void ActionCallback(ui::Button * sender_)
|
||||
{
|
||||
if(!a->loading && !a->saving && a->editable)
|
||||
{
|
||||
sender_->Enabled = false;
|
||||
sender_->SetText("Saving...");
|
||||
a->saving = true;
|
||||
a->info.Location = ((ui::Textbox*)a->location)->GetText();
|
||||
a->info.Biography = ((ui::Textbox*)a->bio)->GetText();
|
||||
RequestBroker::Ref().Start(Client::Ref().SaveUserInfoAsync(a->info), a);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -47,12 +61,104 @@ ProfileActivity::ProfileActivity(std::string username) :
|
||||
|
||||
AddComponent(closeButton);
|
||||
|
||||
loading = true;
|
||||
RequestBroker::Ref().Start(Client::Ref().GetUserInfoAsync(username), this);
|
||||
}
|
||||
|
||||
void ProfileActivity::setUserInfo(UserInfo newInfo)
|
||||
{
|
||||
info = newInfo;
|
||||
|
||||
if(!info.Biography.length() && !editable)
|
||||
info.Biography = "\bg(no bio)";
|
||||
|
||||
if(!info.Location.length() && !editable)
|
||||
info.Location = "\bg(no location)";
|
||||
|
||||
ui::AvatarButton * avatar = new ui::AvatarButton(ui::Point((Size.X-40)-8, 8), ui::Point(40, 40), info.Username);
|
||||
AddComponent(avatar);
|
||||
|
||||
int currentY = 5;
|
||||
ui::Label * title = new ui::Label(ui::Point(4, currentY), ui::Point(Size.X-8-(40+8), 15), info.Username);
|
||||
title->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||
AddComponent(title);
|
||||
currentY += 20;
|
||||
|
||||
ui::Label * locationTitle = new ui::Label(ui::Point(4, currentY), ui::Point(Size.X-8-(40+8), 15), "Location");
|
||||
locationTitle->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||
AddComponent(locationTitle);
|
||||
currentY += 17;
|
||||
|
||||
if(editable)
|
||||
{
|
||||
ui::Textbox * location = new ui::Textbox(ui::Point(8, currentY), ui::Point(Size.X-16-(40+8), 17), info.Location);
|
||||
location->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||
AddComponent(location);
|
||||
this->location = location;
|
||||
currentY += 10+location->Size.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui::Label * location = new ui::Label(ui::Point(4, currentY), ui::Point(Size.X-8-(40+8), 12), info.Location);
|
||||
location->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||
location->SetTextColour(ui::Colour(180, 180, 180));
|
||||
AddComponent(location);
|
||||
this->location = location;
|
||||
currentY += 10+location->Size.Y;
|
||||
}
|
||||
|
||||
ui::Label * bioTitle = new ui::Label(ui::Point(4, currentY), ui::Point(Size.X-8, 15), "Biography");
|
||||
bioTitle->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||
AddComponent(bioTitle);
|
||||
currentY += 17;
|
||||
|
||||
if(editable)
|
||||
{
|
||||
ui::Textbox * bio = new ui::Textbox(ui::Point(8, currentY), ui::Point(Size.X-16, Size.Y-30-currentY), info.Biography);
|
||||
bio->SetMultiline(true);
|
||||
bio->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||
bio->Appearance.VerticalAlign = ui::Appearance::AlignTop;
|
||||
AddComponent(bio);
|
||||
currentY += 10+bio->Size.Y;
|
||||
this->bio = bio;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui::Label * bio = new ui::Label(ui::Point(4, currentY), ui::Point(Size.X-8, -1), info.Biography);
|
||||
bio->SetMultiline(true);
|
||||
bio->SetTextColour(ui::Colour(180, 180, 180));
|
||||
bio->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||
currentY += 10+bio->Size.Y;
|
||||
if(currentY > Size.Y - 20)
|
||||
{
|
||||
ui::ScrollPanel * scrollPanel = new ui::ScrollPanel(bio->Position, ui::Point(Size.X, Size.Y-30-bio->Position.Y));
|
||||
AddComponent(scrollPanel);
|
||||
bio->Position = ui::Point(4, 4);
|
||||
scrollPanel->AddChild(bio);
|
||||
scrollPanel->InnerSize = ui::Point(Size.X, bio->Size.Y+8);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddComponent(bio);
|
||||
}
|
||||
this->bio = bio;
|
||||
}
|
||||
|
||||
//exit(0);
|
||||
}
|
||||
|
||||
void ProfileActivity::OnResponseReady(void * userDataPtr)
|
||||
{
|
||||
exit(0);
|
||||
if(loading)
|
||||
{
|
||||
loading = false;
|
||||
setUserInfo(*(UserInfo*)userDataPtr);
|
||||
delete (UserInfo*)userDataPtr;
|
||||
}
|
||||
else if(saving)
|
||||
{
|
||||
Exit();
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileActivity::OnDraw()
|
||||
|
@ -4,9 +4,17 @@
|
||||
#include <string>
|
||||
#include "Activity.h"
|
||||
#include "client/requestbroker/RequestListener.h"
|
||||
#include "client/UserInfo.h"
|
||||
#include "interface/Window.h"
|
||||
|
||||
class ProfileActivity: public WindowActivity, public RequestListener {
|
||||
ui::Component * location;
|
||||
ui::Component * bio;
|
||||
UserInfo info;
|
||||
bool editable;
|
||||
bool loading;
|
||||
bool saving;
|
||||
void setUserInfo(UserInfo newInfo);
|
||||
public:
|
||||
ProfileActivity(std::string username);
|
||||
virtual ~ProfileActivity();
|
||||
|
Reference in New Issue
Block a user