$ git clone https://socialnetwork.ion.nu/socialnetwork-web.git
commit 8fb4d64c949c48bfb95b3a70982bb2d6d81a6726
Author: Alicia <...>
Date: Sun Jul 23 23:15:06 2017 +0200
Implemented basic post updates.
diff --git a/Makefile b/Makefile
index 9d07c5d..2b9da73 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ SOCIALNETWORKREVISION=f5e92db17a617d4777df4b7a1107d67114d3b6f9
REVISION=$(shell git log | sed -n -e 's/^commit //p;q')
JSLIBS=$(shell PKG_CONFIG_PATH=toolchain/usr/lib/pkgconfig pkg-config --libs gnutls nettle hogweed) -lgmp
JSCFLAGS=$(shell PKG_CONFIG_PATH=toolchain/usr/lib/pkgconfig pkg-config --cflags gnutls)
-JSSYMBOLS='_social_init','_peer_handlesocket','_peer_new_unique','_websockproxy_read','_websockproxy_setwrite','_getcirclecount','_circle_getcount','_circle_getname','_circle_getprivacyptr','_social_addfriend','_circle_getid','_social_finduser','_self_getid','_user_getupdatecount','_user_getupdatetype','_user_getupdatetimestamp','_setcircle','_privacy_getflags','_privacy_getcirclecount','_privacy_getcircle'
+JSSYMBOLS='_social_init','_peer_handlesocket','_peer_new_unique','_websockproxy_read','_websockproxy_setwrite','_getcirclecount','_circle_getcount','_circle_getname','_circle_getprivacyptr','_social_addfriend','_circle_getid','_social_finduser','_self_getid','_user_getupdatecount','_user_getupdateptr','_update_gettype','_update_gettimestamp','_update_post_getmessage','_setcircle','_privacy_getflags','_privacy_getcirclecount','_privacy_getcircle','_createpost'
all: webpeer libsocial.js
diff --git a/jsglue.c b/jsglue.c
index e140e43..0e59ac7 100644
--- a/jsglue.c
+++ b/jsglue.c
@@ -80,9 +80,10 @@ void setcircle(uint32_t circle, const char* name, uint8_t flags, void* circles,
}
struct privacy* circle_getprivacyptr(uint32_t circle){return &social_self->circles[circle].privacy;}
unsigned int user_getupdatecount(struct user* user){return user->updatecount;}
-const char* user_getupdatetype(struct user* user, unsigned int index)
+struct update* user_getupdateptr(struct user* user, unsigned int index){return &user->updates[index];}
+const char* update_gettype(struct update* update)
{
- switch(user->updates[index].type)
+ switch(update->type)
{
case UPDATE_FIELD: return "Field";
case UPDATE_POST: return "Post";
@@ -92,10 +93,8 @@ const char* user_getupdatetype(struct user* user, unsigned int index)
}
return "Unknown";
}
-uint64_t user_getupdatetimestamp(struct user* user, unsigned int index)
-{
- return user->updates[index].timestamp;
-}
+uint64_t update_gettimestamp(struct update* update){return update->timestamp;}
+const char* update_post_getmessage(struct update* update){return update->post.message;}
const char* self_getid(void)
{
unsigned char* bin=social_self->id;
@@ -106,3 +105,12 @@ const char* self_getid(void)
uint8_t privacy_getflags(struct privacy* priv){return priv->flags;}
uint32_t privacy_getcirclecount(struct privacy* priv){return priv->circlecount;}
uint32_t privacy_getcircle(struct privacy* priv, uint32_t i){return priv->circles[i];}
+void createpost(const char* msg, uint8_t flags, void* circles, uint32_t circlecount)
+{
+ struct privacy priv={
+ .flags=flags,
+ .circles=circles,
+ .circlecount=circlecount
+ };
+ social_createpost(msg, &priv);
+}
diff --git a/libsocialjs.js b/libsocialjs.js
index 097d444..c934ef4 100644
--- a/libsocialjs.js
+++ b/libsocialjs.js
@@ -34,12 +34,15 @@ var circle_getprivacyptr;
var social_addfriend;
var social_finduser;
var user_getupdatecount;
-var user_getupdatetype;
-var user_getupdatetimestamp;
+var user_getupdateptr;
+var update_gettype;
+var update_gettimestamp;
+var update_post_getmessage;
var self_getid;
var privacy_getflags;
var privacy_getcirclecount;
var privacy_getcircle;
+var createpost;
var websockproxy_to=false;
var firstpacket=true;
@@ -84,12 +87,15 @@ function init(privkey)
social_addfriend=Module.cwrap('social_addfriend', null, ['array', 'number']);
social_finduser=Module.cwrap('social_finduser', 'number', ['array']);
user_getupdatecount=Module.cwrap('user_getupdatecount', 'number', ['number']);
- user_getupdatetype=Module.cwrap('user_getupdatetype', 'string', ['number','number']);
- user_getupdatetimestamp=Module.cwrap('user_getupdatetimestamp', 'number', ['number','number']);
+ user_getupdateptr=Module.cwrap('user_getupdateptr', 'number', ['number','number']);
+ update_gettype=Module.cwrap('update_gettype', 'string', ['number']);
+ update_gettimestamp=Module.cwrap('update_gettimestamp', 'number', ['number']);
+ update_post_getmessage=Module.cwrap('update_post_getmessage', 'string', ['number']);
self_getid=Module.cwrap('self_getid', 'string', []);
privacy_getflags=Module.cwrap('privacy_getflags', 'number', ['number']);
privacy_getcirclecount=Module.cwrap('privacy_getcirclecount', 'number', ['number']);
privacy_getcircle=Module.cwrap('privacy_getcircle', 'number', ['number', 'number']);
+ createpost=Module.cwrap('createpost', null, ['string', 'number', 'array', 'number']);
_websockproxy_setwrite(Runtime.addFunction(websockwrite));
FS.writeFile('privkey.pem', privkey, {});
@@ -138,18 +144,6 @@ function circle_getprivacy(index)
var ptr=circle_getprivacyptr(index);
return getprivacy(ptr);
}
-function circle_set(index, name, priv)
-{
- var circles=[];
- for(circle of priv.circles) // Can only pass Uint8 arrays, so construct our Uint32 values from Uint8 pieces
- {
- circles.push(circle.index&0xff);
- circles.push((circle.index&0xff00)/0x100);
- circles.push((circle.index&0xff0000)/0x10000);
- circles.push((circle.index&0xff000000)/0x1000000);
- }
- setcircle(configcircle_index, name, priv.flags, new Uint8Array(circles), priv.circles.length);
-}
function hextobin(hex)
{
var bin=new Array();
@@ -173,15 +167,40 @@ function getuser(id)
function user_getupdate(user, index)
{
var update=new Object();
- update.type=user_getupdatetype(user.ptr, index);
- update.timestamp=user_getupdatetimestamp(user.ptr, index);
-// TODO: Get type-specific data
+ var ptr=user_getupdateptr(user.ptr, index);
+ update.type=update_gettype(ptr);
+ update.timestamp=update_gettimestamp(ptr);
+ // Get type-specific data
+ switch(update.type)
+ {
+ case 'Post':
+ update.message=update_post_getmessage(ptr);
+ break;
+ }
return update;
}
function privacy(flags, circles)
{
this.flags=flags;
this.circles=circles;
+ this.toString=function()
+ {
+ if(this.flags&1){return 'Everyone';}
+ if(this.flags&2){return 'Friends';}
+ return 'Select circles only ('+this.circles.length+')';
+ };
+ this.bincircles=function()
+ { // Can only pass Uint8 arrays to C functions, so construct our Uint32 values from Uint8 pieces
+ var circles=[];
+ for(circle of this.circles)
+ {
+ circles.push(circle.index&0xff);
+ circles.push((circle.index&0xff00)/0x100);
+ circles.push((circle.index&0xff0000)/0x10000);
+ circles.push((circle.index&0xff000000)/0x1000000);
+ }
+ return new Uint8Array(circles);
+ };
}
function getprivacy(ptr)
{
diff --git a/websocial.css b/websocial.css
index de10c55..d2b6278 100644
--- a/websocial.css
+++ b/websocial.css
@@ -47,3 +47,18 @@ div.menu>a:nth-child(1)
{
border-left-style:none;
}
+div.update
+{
+ border-style:solid;
+ border-color:#808080;
+ border-width:1px;
+ border-radius:6px;
+ padding:4px;
+ margin:5px;
+ min-width:40%;
+ max-width:96%;
+ overflow-wrap:break-word;
+ display:inline-block;
+ box-shadow:0px 0px 2px #c0c0c0;
+ background-color:#ffffff;
+}
diff --git a/websocial.html b/websocial.html
index b205bca..048a4b7 100644
--- a/websocial.html
+++ b/websocial.html
@@ -53,6 +53,15 @@
<div id="circle_privacy_circles"></div><br />
<button onclick="circle_save();">OK</button> <button onclick="chdisplay('circle_window',false);">Cancel</button>
</div>
+ <div class="modal" id="privacy_window" style="display:none;">
+ <select id="generic_privacy">
+ <option value="0">Select circles only</option>
+ <option value="2">Friends</option>
+ <option value="1">Everyone</option>
+ </select><br />
+ <div id="generic_privacy_circles"></div><br />
+ <button id="privacy_button">OK</button> <button onclick="chdisplay('privacy_window',false);">Cancel</button>
+ </div>
<!-- Main interface -->
<div class="menu">
<a href="#" onclick="return false;">Feed</a><a href="#" onclick="page_friends();return false;">Friends</a><a href="#" onclick="page_user(false);return false;">Self</a>
diff --git a/websocial.js b/websocial.js
index e6e4c0c..795a7ad 100644
--- a/websocial.js
+++ b/websocial.js
@@ -151,14 +151,30 @@ function page_user(id)
var user=getuser(id);
display.appendChild(document.createTextNode(id+':'));
display.appendChild(document.createElement('br'));
+ var button=document.createElement('button');
+ button.name='postbutton';
+ button.onclick=postwidget;
+ button.appendChild(document.createTextNode('Create update'));
+ display.appendChild(button);
+ display.appendChild(document.createElement('br'));
display.appendChild(document.createTextNode(user.updatecount+' updates'));
for(var i=1; i<=user.updatecount && i<=20; ++i)
{
var update=user_getupdate(user, user.updatecount-i);
+ if(update.type=='Circle'){continue;} // Don't display circle changes
var box=document.createElement('div');
- box.appendChild(document.createTextNode('Posted at: '+update.timestamp));
+ box.className='update';
+ var date=new Date(update.timestamp*1000);
+ box.appendChild(document.createTextNode('Posted at: '+date.toLocaleString()));
box.appendChild(document.createElement('br'));
box.appendChild(document.createTextNode('Update type: '+update.type));
+ // Display type-specific data
+ if(update.type=='Post')
+ {
+ box.appendChild(document.createElement('br'));
+ box.appendChild(document.createTextNode('Message: '+update.message));
+ }
+ display.appendChild(document.createElement('br'));
display.appendChild(box);
}
// TODO: Option to load more updates
@@ -180,6 +196,7 @@ function privacy_openconfig(prefix, priv)
checkbox.type='checkbox';
checkbox.name=prefix+'_privacy_circles';
checkbox.value=item.index;
+ checkbox.dataset.name=item.name;
label.appendChild(checkbox);
label.appendChild(document.createTextNode(item.name+' '));
circlebox.appendChild(label);
@@ -207,7 +224,7 @@ function privacy_save(prefix)
var items=document.getElementsByName(prefix+'_privacy_circles');
for(item of items)
{
- if(item.checked){circles.push({'index':item.value});}
+ if(item.checked){circles.push({'index':parseInt(item.value),'name':item.dataset.name});}
}
return new privacy(flags, circles);
}
@@ -236,14 +253,14 @@ function circle_openconfig(index, option)
function circle_save()
{
- var name=document.getElementById('circle_name');
+ var name=document.getElementById('circle_name').value;
var priv=privacy_save('circle');
- circle_set(configcircle_index, name.value, priv);
+ setcircle(configcircle_index, name, priv.flags, priv.bincircles(), priv.circles.length);
if(configcircle_option)
{
var select=configcircle_option.parentNode;
// Update list of circles
- configcircle_option.text=name.value;
+ configcircle_option.text=name;
configcircle_option.value=configcircle_index;
configcircle_option=false;
// Make a new 'new circle' option?
@@ -254,3 +271,56 @@ function circle_save()
}
chdisplay('circle_window',false);
}
+
+var postwidgetbox=false;
+var postprivacy=new privacy(0,[]);
+function postwidget()
+{
+// TODO: Differences in widgets for posts on others walls or in response to other posts?
+ if(postwidgetbox && postwidgetbox.parentNode)
+ {
+ postwidgetbox.parentNode.removeChild(postwidgetbox);
+ }
+ postwidgetbox=document.createElement('div');
+// TODO: Configurable default privacy?
+ var privtext=document.createTextNode('Privacy: '+postprivacy.toString());
+ postwidgetbox.appendChild(privtext);
+ button=document.createElement('button');
+ button.appendChild(document.createTextNode('Change'));
+ button.onclick=function()
+ {
+ privacy_openconfig('generic', postprivacy);
+ document.getElementById('privacy_button').onclick=function()
+ {
+ postprivacy=privacy_save('generic');
+ chdisplay('privacy_window', false);
+ privtext.textContent='Privacy: '+postprivacy.toString();
+ };
+ chdisplay(false, 'privacy_window');
+ };
+ postwidgetbox.appendChild(button);
+ postwidgetbox.appendChild(document.createElement('br'));
+// TODO: Non-text posts, maybe media for starters
+ var text=document.createElement('textarea');
+ postwidgetbox.appendChild(text);
+ postwidgetbox.appendChild(document.createElement('br'));
+ // Submit button
+ button=document.createElement('button');
+ button.appendChild(document.createTextNode('Post'));
+ button.onclick=function()
+ {
+ createpost(text.value, postprivacy.flags, postprivacy.bincircles(), postprivacy.circles.length);
+// TODO: Instead of reloading the user page, insert the update and hide the postwidget (and re-show postbutton)
+ page_user(false);
+ };
+ postwidgetbox.appendChild(button);
+ // Re-show all postbuttons
+ var buttons=document.getElementsByName('postbutton');
+ for(button of buttons)
+ {
+ button.style.display='inline';
+ }
+ // Hide this one and insert postwidget
+ this.style.display='none';
+ this.parentNode.insertBefore(postwidgetbox, this);
+}