\
\
@@ -185,8 +325,8 @@ class Post {
\
\
\
\
\
@@ -199,8 +339,8 @@ class Post {
\
\
\
-
like\
- \
+
$liked\
+ \
\
\
\
@@ -209,22 +349,37 @@ class Post {
\
';
+ var template = '';
+
+ if(type !== undefined && type !== null && type == 'reply')
+ template = replyTemplate;
+ else
+ template = postTemplate;
+
var device = (jQuery(document).width() < 768 ? 'mobile' : 'desktop');
- postTemplate = postTemplate.replaceAll('$user-name-url', Sanitize.html(Sanitize.url(this.getUser().getName())));
- postTemplate = postTemplate.replaceAll('$user-name', Sanitize.html(this.getUser().getName()));
- postTemplate = postTemplate.replaceAll('$user-id-url', Sanitize.html(Sanitize.url(this.getUser().getID())));
+ template = template.replaceAll('$user-name-url', Sanitize.html(Sanitize.url(this.getUser().getName())));
+ template = template.replaceAll('$user-name', Sanitize.html(this.getUser().getName()));
+ template = template.replaceAll('$user-id-url', Sanitize.html(Sanitize.url(this.getUser().getID())));
- postTemplate = postTemplate.replaceAll('$user-id-truncated', Sanitize.html(this.getUser().getID().substring(0, 12) + '...'));
- // postTemplate = postTemplate.replaceAll('$user-id-truncated', Sanitize.html(this.getUser().getID().split('-').slice(0, 4).join('-')));
+ template = template.replaceAll('$user-id-truncated', Sanitize.html(this.getUser().getID().substring(0, 12) + '...'));
+ // template = template.replaceAll('$user-id-truncated', Sanitize.html(this.getUser().getID().split('-').slice(0, 4).join('-')));
- postTemplate = postTemplate.replaceAll('$user-id', Sanitize.html(this.getUser().getID()));
- postTemplate = postTemplate.replaceAll('$user-image', Sanitize.html(this.getUser().getIcon()));
- postTemplate = postTemplate.replaceAll('$content', Sanitize.html(this.getContent()));
- postTemplate = postTemplate.replaceAll('$date-relative', timeSince(this.getPostDate(), device) + (device === 'desktop' ? ' ago' : ''));
- postTemplate = postTemplate.replaceAll('$date', this.getPostDate().toLocaleString());
+ template = template.replaceAll('$user-id', Sanitize.html(this.getUser().getID()));
+ template = template.replaceAll('$user-image', "data:image/jpeg;base64," + Sanitize.html(this.getUser().getIcon()));
+ template = template.replaceAll('$content', Sanitize.html(this.getContent()).replaceAll('\n', '
', 16)); // Maximum of 16 lines
+ template = template.replaceAll('$post-hash', this.getHash());
+ template = template.replaceAll('$date-relative-truncated', timeSince(this.getPostDate(), 'mobile'));
+ template = template.replaceAll('$date-relative', timeSince(this.getPostDate(), device) + (device === 'desktop' ? ' ago' : ''));
+ template = template.replaceAll('$date', this.getPostDate().toLocaleString());
- return postTemplate;
+ if(this.getHash() in getPostMap() && getPostMap()[this.getHash()]['liked']) {
+ template = template.replaceAll('$liked', 'unlike');
+ } else {
+ template = template.replaceAll('$liked', 'like');
+ }
+
+ return template;
}
setUser(user) {
@@ -243,6 +398,14 @@ class Post {
return this.content;
}
+ setParent(parent) {
+ this.parent = parent;
+ }
+
+ getParent() {
+ return this.parent;
+ }
+
setPostDate(date) { // unix timestamp input
if(date instanceof Date)
this.date = date;
@@ -253,6 +416,51 @@ class Post {
getPostDate() {
return this.date;
}
+
+ setHash(hash) {
+ this.hash = hash;
+ }
+
+ getHash() {
+ return this.hash;
+ }
+
+ save(callback) {
+ var args = {'type' : 'onionr-post', 'sign' : true, 'content' : JSON.stringify({'content' : this.getContent()})};
+
+ if(this.getParent() !== undefined && this.getParent() !== null)
+ args['parent'] = (this.getParent() instanceof Post ? this.getParent().getHash() : (this.getParent() instanceof Block ? this.getParent().getHash() : this.getParent()));
+
+ var url = '/client/?action=insertBlock&data=' + Sanitize.url(JSON.stringify(args)) + '&token=' + Sanitize.url(getWebPassword()) + '&timingToken=' + Sanitize.url(getTimingToken());
+
+ console.log(url);
+
+ var http = new XMLHttpRequest();
+
+ if(callback !== undefined) {
+ // async
+
+ var thisObject = this;
+
+ http.addEventListener('load', function() {
+ thisObject.setHash(Block.parseBlockArray(JSON.parse(http.responseText)['hash']));
+ callback(thisObject.getHash());
+ }, false);
+
+ http.open('GET', url, true);
+ http.timeout = 5000;
+ http.send(null);
+ } else {
+ // sync
+
+ http.open('GET', url, false);
+ http.send(null);
+
+ this.setHash(Block.parseBlockArray(JSON.parse(http.responseText)['hash']));
+
+ return this.getHash();
+ }
+ }
}
/* block class */
@@ -301,8 +509,12 @@ class Block {
// returns the parent block's hash (not Block object, for performance)
getParent() {
- if(!(this.parent instanceof Block) && this.parent !== undefined && this.parent !== null)
- this.parent = Block.openBlock(this.parent); // convert hash to Block object
+ // console.log(this.parent);
+
+ // TODO: Create a function to fetch the block contents and parse it from the server; right now it is only possible to search for types of blocks (see Block.getBlocks), so it is impossible to return a Block object here
+
+ // if(!(this.parent instanceof Block) && this.parent !== undefined && this.parent !== null)
+ // this.parent = Block.openBlock(this.parent); // convert hash to Block object
return this.parent;
}
@@ -355,11 +567,57 @@ class Block {
return !(this.hash === null || this.hash === undefined);
}
+ // saves the block, returns the hash
+ save(sign, callback) {
+ var type = this.getType();
+ var content = this.getContent();
+ var parent = this.getParent();
+
+ if(content !== undefined && content !== null && type !== '') {
+ var args = {'content' : content};
+
+ if(type !== undefined && type !== null && type !== '')
+ args['type'] = type;
+ if(parent !== undefined && parent !== null && parent.getHash() !== undefined && parent.getHash() !== null && parent.getHash() !== '')
+ args['parent'] = parent.getHash();
+ if(sign !== undefined && sign !== null)
+ args['sign'] = String(sign) !== 'false'
+
+
+ var url = '/client/?action=insertBlock&data=' + Sanitize.url(JSON.stringify(args)) + '&token=' + Sanitize.url(getWebPassword()) + '&timingToken=' + Sanitize.url(getTimingToken());
+
+ console.log(url);
+
+ var http = new XMLHttpRequest();
+
+ if(callback !== undefined) {
+ // async
+
+ http.addEventListener('load', function() {
+ callback(Block.parseBlockArray(JSON.parse(http.responseText)['hash']));
+ }, false);
+
+ http.open('GET', url, true);
+ http.timeout = 5000;
+ http.send(null);
+ } else {
+ // sync
+
+ http.open('GET', url, false);
+ http.send(null);
+
+ return Block.parseBlockArray(JSON.parse(http.responseText)['hash']);
+ }
+ }
+
+ return false;
+ }
+
/* static functions */
// recreates a block by hash
static openBlock(hash) {
- return parseBlock(response);
+ return Block.parseBlock(hash);
}
// converts an associative array to a Block
@@ -438,14 +696,58 @@ class Block {
/* temporary code */
+var tt = getParameter("timingToken");
+if(tt !== null && tt !== undefined) {
+ setTimingToken(tt);
+}
+
if(getWebPassword() === null) {
var password = "";
while(password.length != 64) {
password = prompt("Please enter the web password (run `./RUN-LINUX.sh --get-password`)");
}
- setTimingToken(prompt("Please enter the timing token (optional)"));
-
setWebPassword(password);
- window.location.reload(true);
}
+
+if(getCurrentUser() === null) {
+ jQuery('#modal').modal('show');
+
+ var url = '/client/?action=info&token=' + Sanitize.url(getWebPassword()) + '&timingToken=' + Sanitize.url(getTimingToken());
+
+ console.log(url);
+
+ var http = new XMLHttpRequest();
+
+ // sync
+
+ http.addEventListener('load', function() {
+ var id = JSON.parse(http.responseText)['pubkey'];
+
+ User.getUser(id, function(data) {
+ if(data === null || data === undefined) {
+ var user = new User();
+
+ user.setName('New User');
+ user.setID(id);
+ user.setIcon('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\
+');
+ user.setDescription('A new OnionrUI user');
+
+ user.remember();
+ user.save();
+
+ setCurrentUser(user);
+ } else {
+ setCurrentUser(data);
+ }
+
+ window.location.reload();
+ });
+ }, false);
+
+ http.open('GET', url, true);
+ http.send(null);
+}
+
+currentUser = getCurrentUser();
diff --git a/onionr/static-data/www/ui/dist/js/timeline.js b/onionr/static-data/www/ui/dist/js/timeline.js
index 0dbd634a..e9ca8a13 100644
--- a/onionr/static-data/www/ui/dist/js/timeline.js
+++ b/onionr/static-data/www/ui/dist/js/timeline.js
@@ -4,24 +4,488 @@ Block.getBlocks({'type' : 'onionr-post', 'signed' : true, 'reverse' : true}, fun
try {
var block = data[i];
- var post = new Post();
- var user = new User();
+ var finished = false;
+ User.getUser(new String(block.getHeader('signer', 'unknown')), function(user) {
+ var post = new Post();
- var blockContent = JSON.parse(block.getContent());
+ var blockContent = JSON.parse(block.getContent());
- user.setName('unknown');
- user.setID(new String(block.getHeader('signer', 'unknown')));
- post.setContent(blockContent['content']);
- post.setPostDate(block.getDate());
- post.setUser(user);
+ // just ignore anything shorter than 280 characters
+ if(String(blockContent['content']).length <= 280 && block.getParent() === null) {
+ post.setContent(blockContent['content']);
+ post.setPostDate(block.getDate());
+ post.setUser(user);
- document.getElementById('onionr-timeline-posts').innerHTML += post.getHTML();
+ post.setHash(block.getHash());
+
+ document.getElementById('onionr-timeline-posts').innerHTML += post.getHTML();
+ }
+
+ finished = true;
+ });
+
+ while(!finished);
} catch(e) {
+ console.log('Troublemaker block: ' + data[i].getHash());
console.log(e);
}
}
});
-function viewProfile(id, name) {
- document.getElementById("onionr-profile-username").innerHTML = Sanitize.html(decodeURIComponent(name));
+function toggleLike(hash) {
+ var post = getPostMap(hash);
+ if(post === null || !getPostMap()[hash]['liked']) {
+ console.log('Liking ' + hash + '...');
+
+ if(post === null)
+ getPostMap()[hash] = {};
+
+ getPostMap()[hash]['liked'] = true;
+
+ set('postmap', JSON.stringify(getPostMap()));
+
+ var block = new Block();
+
+ block.setType('onionr-post-like');
+ block.setContent(JSON.stringify({'hash' : hash}));
+ block.save(true, function(hash) {});
+ } else {
+ console.log('Unliking ' + hash + '...');
+ }
}
+
+function postCreatorChange() {
+ var content = document.getElementById('onionr-post-creator-content').value;
+ var message = '';
+
+ var maxlength = 280;
+
+ var disable = true;
+ var warn = false;
+
+ if(content.length !== 0) {
+ if(content.length - content.replaceAll('\n', '').length > 16) {
+ // 16 max newlines
+ message = 'Please use less than 16 newlines';
+ } else if(content.length <= maxlength) {
+ // 280 max characters
+ message = '%s characters remaining'.replaceAll('%s', (280 - content.length));
+ disable = false;
+
+ if(maxlength - content.length < maxlength / 4) {
+ warn = true;
+ }
+ } else {
+ message = '%s characters over maximum'.replaceAll('%s', (content.length - maxlength));
+ }
+ }
+
+ var element = document.getElementById('onionr-post-creator-content-message');
+ var button = document.getElementById("onionr-post-creator-create");
+
+ if(message === '')
+ element.style.visibility = 'hidden';
+ else {
+ element.style.visibility = 'visible';
+
+ element.innerHTML = message;
+
+ if(disable)
+ element.style.color = 'red';
+ else if(warn)
+ element.style.color = '#FF8C00';
+ else
+ element.style.color = 'gray';
+ }
+
+ if(disable)
+ button.disabled = true;
+ else
+ button.disabled = false;
+}
+
+function replyCreatorChange() {
+ var content = document.getElementById('onionr-reply-creator-content').value;
+ var message = '';
+
+ var maxlength = 280;
+
+ var disable = true;
+ var warn = false;
+
+ if(content.length !== 0) {
+ if(content.length - content.replaceAll('\n', '').length > 16) {
+ // 16 max newlines
+ message = 'Please use less than 16 newlines';
+ } else if(content.length <= maxlength) {
+ // 280 max characters
+ message = '%s characters remaining'.replaceAll('%s', (280 - content.length));
+ disable = false;
+
+ if(maxlength - content.length < maxlength / 4) {
+ warn = true;
+ }
+ } else {
+ message = '%s characters over maximum'.replaceAll('%s', (content.length - maxlength));
+ }
+ }
+
+ var element = document.getElementById('onionr-reply-creator-content-message');
+ var button = document.getElementById("onionr-reply-creator-create");
+
+ if(message === '')
+ element.style.visibility = 'hidden';
+ else {
+ element.style.visibility = 'visible';
+
+ element.innerHTML = message;
+
+ if(disable)
+ element.style.color = 'red';
+ else if(warn)
+ element.style.color = '#FF8C00';
+ else
+ element.style.color = 'gray';
+ }
+
+ if(disable)
+ button.disabled = true;
+ else
+ button.disabled = false;
+}
+
+function focusReplyCreatorChange() {
+ var content = document.getElementById('onionr-post-focus-reply-creator-content').value;
+ var message = '';
+
+ var maxlength = 280;
+
+ var disable = true;
+ var warn = false;
+
+ if(content.length !== 0) {
+ if(content.length - content.replaceAll('\n', '').length > 16) {
+ // 16 max newlines
+ message = 'Please use less than 16 newlines';
+ } else if(content.length <= maxlength) {
+ // 280 max characters
+ message = '%s characters remaining'.replaceAll('%s', (280 - content.length));
+ disable = false;
+
+ if(maxlength - content.length < maxlength / 4) {
+ warn = true;
+ }
+ } else {
+ message = '%s characters over maximum'.replaceAll('%s', (content.length - maxlength));
+ }
+ }
+
+ var element = document.getElementById('onionr-post-focus-reply-creator-content-message');
+ var button = document.getElementById("onionr-post-focus-reply-creator-create");
+
+ if(message === '')
+ element.style.visibility = 'hidden';
+ else {
+ element.style.visibility = 'visible';
+
+ element.innerHTML = message;
+
+ if(disable)
+ element.style.color = 'red';
+ else if(warn)
+ element.style.color = '#FF8C00';
+ else
+ element.style.color = 'gray';
+ }
+
+ if(disable)
+ button.disabled = true;
+ else
+ button.disabled = false;
+}
+
+function viewProfile(id, name) {
+ id = decodeURIComponent(id);
+ document.getElementById("onionr-profile-username").innerHTML = Sanitize.html(decodeURIComponent(name));
+
+ User.getUser(id, function(data) {
+ if(data !== null) {
+ document.getElementById("onionr-profile-user-icon").src = "data:image/jpeg;base64," + Sanitize.html(data.getIcon());
+ document.getElementById("onionr-profile-user-icon").b64 = Sanitize.html(data.getIcon());
+ document.getElementById("onionr-profile-username").innerHTML = Sanitize.html(Sanitize.username(data.getName()));
+ document.getElementById("onionr-profile-username").title = Sanitize.html(data.getID());
+ document.getElementById("onionr-profile-description").innerHTML = Sanitize.html(Sanitize.description(data.getDescription()));
+ }
+ });
+}
+
+function updateUser() {
+ toggleSaveButton(false);
+
+ // jQuery('#modal').modal('show');
+
+ var name = jQuery('#onionr-profile-username').text();
+ var id = document.getElementById("onionr-profile-username").title;
+ var icon = document.getElementById("onionr-profile-user-icon").b64;
+ var description = jQuery("#onionr-profile-description").text();
+
+ var user = new User();
+
+ user.setName(name);
+ user.setID(id);
+ user.setIcon(icon);
+ user.setDescription(Sanitize.description(description));
+
+ user.remember();
+ user.save(function() {
+ setCurrentUser(user);
+
+ window.location.reload();
+ });
+}
+
+function cancelUpdate() {
+ toggleSaveButton(false);
+
+ var name = jQuery('#onionr-profile-username').text();
+ var id = document.getElementById("onionr-profile-username").title;
+
+ viewProfile(id, name);
+}
+
+function toggleSaveButton(show) {
+ document.getElementById("onionr-profile-edit").style.display = (show ? 'block' : 'none');
+}
+
+function makePost() {
+ var content = document.getElementById("onionr-post-creator-content").value;
+
+ if(content.trim() !== '') {
+ var post = new Post();
+
+ post.setUser(getCurrentUser());
+ post.setContent(content);
+ post.setPostDate(new Date());
+
+ post.save(function(data) {}); // async, but no function
+
+ document.getElementById('onionr-timeline-posts').innerHTML = post.getHTML() + document.getElementById('onionr-timeline-posts').innerHTML;
+
+ document.getElementById("onionr-post-creator-content").value = "";
+ document.getElementById("onionr-post-creator-content").focus();
+ postCreatorChange();
+ } else {
+ console.log('Not making empty post.');
+ }
+}
+
+function getReplies(id, callback) {
+ Block.getBlocks({'type' : 'onionr-post', 'parent' : id, 'signed' : true, 'reverse' : true}, callback);
+}
+
+function focusPost(id) {
+ viewReplies(id);
+}
+
+function viewRepliesMobile(id) {
+ var post = document.getElementById('onionr-post-' + id);
+
+ var user_name = '';
+ var user_id = '';
+ var user_id_trunc = '';
+ var user_icon = '';
+ var post_content = '';
+
+ if(post !== null && post !== undefined) {
+ // if the post is in the timeline, get the data from it
+ user_name = post.getElementsByClassName('onionr-post-user-name')[0].innerHTML;
+ user_id = post.getElementsByClassName('onionr-post-user-id')[0].title;
+ user_id_trunc = post.getElementsByClassName('onionr-post-user-id')[0].innerHTML;
+ user_icon = post.getElementsByClassName('onionr-post-user-icon')[0].src;
+ post_content = post.getElementsByClassName('onionr-post-content')[0].innerHTML;
+ } else {
+ // otherwise, fetch the data
+ }
+
+ document.getElementById('onionr-post-focus-user-icon').src = user_icon;
+ document.getElementById('onionr-post-focus-user-name').innerHTML = user_name;
+ document.getElementById('onionr-post-focus-user-id').innerHTML = user_id_trunc;
+ document.getElementById('onionr-post-focus-user-id').title = user_id;
+ document.getElementById('onionr-post-focus-content').innerHTML = post_content;
+
+ document.getElementById('onionr-post-focus-reply-creator-user-name').innerHTML = Sanitize.html(Sanitize.username(getCurrentUser().getName()));
+ document.getElementById('onionr-post-focus-reply-creator-user-icon').src = "data:image/jpeg;base64," + Sanitize.html(getCurrentUser().getIcon());
+ document.getElementById('onionr-post-focus-reply-creator-content').value = '';
+ document.getElementById('onionr-post-focus-reply-creator-content-message').value = '';
+
+ jQuery('#onionr-post-focus').modal('show');
+}
+
+function viewReplies(id) {
+ document.getElementById('onionr-replies-title').innerHTML = 'Replies';
+ document.getElementById('onionr-reply-creator-panel').originalPost = id;
+ document.getElementById('onionr-reply-creator-panel').innerHTML = '\
+
\
+
\
+
\
+
\
+
\
+
\
+
\
+
\
+
\
+\
+
\
+\
+
\
+\
+
\
+
\
+
\
+
\
+
\
+
\
+\
+
\
+\
+';
+
+ document.getElementById('onionr-reply-creator-content').innerHTML = '';
+ document.getElementById("onionr-reply-creator-content").placeholder = "Enter a message here...";
+ document.getElementById('onionr-reply-creator-user-name').innerHTML = Sanitize.html(Sanitize.username(getCurrentUser().getName()));
+ document.getElementById('onionr-reply-creator-user-icon').src = "data:image/jpeg;base64," + Sanitize.html(getCurrentUser().getIcon());
+
+ document.getElementById('onionr-replies').innerHTML = '';
+ getReplies(id, function(data) {
+ var replies = document.getElementById('onionr-replies');
+
+ replies.innerHTML = '';
+
+ for(var i = 0; i < data.length; i++) {
+ try {
+ var block = data[i];
+
+ var finished = false;
+ User.getUser(new String(block.getHeader('signer', 'unknown')), function(user) {
+ var post = new Post();
+
+ var blockContent = JSON.parse(block.getContent());
+
+ // just ignore anything shorter than 280 characters
+ if(String(blockContent['content']).length <= 280) {
+ post.setContent(blockContent['content']);
+ post.setPostDate(block.getDate());
+ post.setUser(user);
+
+ post.setHash(block.getHash());
+
+ replies.innerHTML += post.getHTML('reply');
+ }
+
+ finished = true;
+ });
+
+ while(!finished);
+ } catch(e) {
+ console.log('Troublemaker block: ' + data[i].getHash());
+ console.log(e);
+ }
+ }
+ });
+}
+
+function makeReply() {
+ var content = document.getElementById("onionr-reply-creator-content").value;
+
+ if(content.trim() !== '') {
+ var post = new Post();
+
+ var originalPost = document.getElementById('onionr-reply-creator-panel').originalPost;
+
+ console.log('Original post hash: ' + originalPost);
+
+ post.setUser(getCurrentUser());
+ post.setParent(originalPost);
+ post.setContent(content);
+ post.setPostDate(new Date());
+
+ post.save(function(data) {}); // async, but no function
+
+ document.getElementById('onionr-replies').innerHTML = post.getHTML('reply') + document.getElementById('onionr-replies').innerHTML;
+
+ document.getElementById("onionr-reply-creator-content").value = "";
+ document.getElementById("onionr-reply-creator-content").focus();
+ replyCreatorChange();
+ } else {
+ console.log('Not making empty reply.');
+ }
+}
+
+jQuery('body').on('click', '[data-editable]', function() {
+ var el = jQuery(this);
+ var txt = el.text();
+ var maxlength = el.attr("maxlength");
+
+ var input = jQuery('
').val(txt);
+ input.attr('maxlength', maxlength);
+ el.replaceWith(input);
+
+ var save = function() {
+ var newTxt = input.val();
+
+ if(el.attr('id') === 'onionr-profile-username')
+ newTxt = Sanitize.username(newTxt);
+ if(el.attr('id') === 'onionr-profile-description')
+ newTxt = Sanitize.description(newTxt);
+
+ var p = el.text(newTxt);
+
+ input.replaceWith(p);
+
+ if(newTxt !== txt)
+ toggleSaveButton(true);
+ };
+
+ var saveEnter = function(event) {
+ console.log(event);
+ console.log(event.keyCode);
+ if (event.keyCode === 13)
+ save();
+ };
+
+ input.one('blur', save).bind('keyup', saveEnter).focus();
+});
+//viewProfile('$user-id-url', '$user-name-url')
+// jQuery('#onionr-post-user-id').on('click', function(e) { alert(3);});
+//jQuery('#onionr-post *').on('click', function(e) { e.stopPropagation(); });
+// jQuery('#onionr-post').click(function(e) { alert(1); });
+
+currentUser = getCurrentUser();
+if(currentUser !== undefined && currentUser !== null) {
+ document.getElementById("onionr-post-creator-user-name").innerHTML = Sanitize.html(currentUser.getName());
+ document.getElementById("onionr-post-creator-user-id").innerHTML = "you";
+ document.getElementById("onionr-post-creator-user-icon").src = "data:image/jpeg;base64," + Sanitize.html(currentUser.getIcon());
+ document.getElementById("onionr-post-creator-user-id").title = currentUser.getID();
+
+ document.getElementById("onionr-post-creator-content").placeholder = "Enter a message here...";
+ document.getElementById("onionr-post-focus-reply-creator-content").placeholder = "Enter a message here...";
+
+ document.getElementById("onionr-post-focus-reply-creator-user-id").innerHTML = "you";
+}
+
+viewCurrentProfile = function() {
+ viewProfile(encodeURIComponent(currentUser.getID()), encodeURIComponent(currentUser.getName()));
+}
+
+document.getElementById("onionr-post-creator-user-id").onclick = viewCurrentProfile;
+document.getElementById("onionr-post-creator-user-name").onclick = viewCurrentProfile;
+
+// on some browsers it saves the user input on reload. So, it should also recheck the input.
+postCreatorChange();
diff --git a/onionr/static-data/www/ui/lang.json b/onionr/static-data/www/ui/lang.json
index 28606a56..eb8a1403 100644
--- a/onionr/static-data/www/ui/lang.json
+++ b/onionr/static-data/www/ui/lang.json
@@ -6,10 +6,35 @@
"NOTIFICATIONS" : "Notifications",
"MESSAGES" : "Messages",
+ "LATEST" : "Latest...",
"TRENDING" : "Trending",
+ "REPLIES" : "Replies",
+
+ "MODAL_TITLE" : "Loading...",
+ "MODAL_MESSAGE" : "Onionr has begun performing a CPU-intensive operation. If this operation does not complete in the next 10 seconds, try reloading the page.",
"POST_LIKE" : "like",
- "POST_REPLY" : "reply"
+ "POST_UNLIKE" : "unlike",
+ "POST_REPLY" : "reply",
+
+ "POST_CREATOR_YOU" : "you",
+ "POST_CREATOR_PLACEHOLDER" : "Enter a message here...",
+ "POST_CREATOR_CREATE" : "Create post",
+
+ "REPLY_CREATOR_YOU" : "you",
+ "REPLY_CREATOR_PLACEHOLDER" : "Enter reply here...",
+ "REPLY_CREATOR_CREATE" : "Reply",
+
+ "POST_CREATOR_MESSAGE_MAXIMUM_NEWLINES" : "Please use less than 16 newlines",
+ "POST_CREATOR_MESSAGE_REMAINING" : "%s characters remaining",
+ "POST_CREATOR_MESSAGE_OVER" : "%s characters over maximum",
+
+ "REPLY_CREATOR_MESSAGE_MAXIMUM_NEWLINES" : "Please use less than 16 newlines",
+ "REPLY_CREATOR_MESSAGE_REMAINING" : "%s characters remaining",
+ "REPLY_CREATOR_MESSAGE_OVER" : "%s characters over maximum",
+
+ "PROFILE_EDIT_SAVE" : "Save",
+ "PROFILE_EDIT_CANCEL" : "Cancel"
},
"spa" : {
diff --git a/onionr/static-data/www/ui/src/css/main.css b/onionr/static-data/www/ui/src/css/main.css
index dab080ef..8854fc44 100644
--- a/onionr/static-data/www/ui/src/css/main.css
+++ b/onionr/static-data/www/ui/src/css/main.css
@@ -37,10 +37,20 @@ body {
/* timeline */
+.onionr-post-focus-separator {
+ width: 100%;
+
+ padding: 1rem;
+ padding-left: 0;
+ padding-right: 0;
+}
+
.onionr-post {
padding: 1rem;
margin-bottom: 1rem;
+ cursor: pointer;
+
width: 100%;
}
@@ -60,6 +70,35 @@ body {
width: 100%;
}
+.onionr-post-creator {
+ padding: 1rem;
+ margin-bottom: 1rem;
+
+ width: 100%;
+}
+
+.onionr-post-creator-user-name {
+ display: inline;
+}
+
+.onionr-post-creator-user-id:before { content: "("; }
+.onionr-post-creator-user-id:after { content: ")"; }
+
+.onionr-post-creator-content {
+ word-wrap: break-word;
+ width: 100%;
+}
+
+.onionr-post-creator-user-icon {
+ border-radius: 100%;
+ width: 100%;
+}
+
+.onionr-post-creator-create {
+ width: 100%;
+ text-align: center;
+}
+
.h-divider {
margin: 5px 15px;
height: 1px;
@@ -77,3 +116,7 @@ body {
.onionr-profile-username {
text-align: center;
}
+
+.onionr-profile-save {
+ width: 100%;
+}
diff --git a/onionr/static-data/www/ui/src/css/themes/dark.css b/onionr/static-data/www/ui/src/css/themes/dark.css
index b0473390..a81e25cf 100644
--- a/onionr/static-data/www/ui/src/css/themes/dark.css
+++ b/onionr/static-data/www/ui/src/css/themes/dark.css
@@ -5,6 +5,17 @@ body {
/* timeline */
+.onionr-post-focus-separator {
+ border-color: black;
+}
+
+.modal-content {
+ border: 1px solid black;
+ border-radius: 1rem;
+
+ background-color: lightgray;
+}
+
.onionr-post {
border: 1px solid black;
border-radius: 1rem;
@@ -31,6 +42,35 @@ body {
font-size: 15pt;
}
+.onionr-post-creator {
+ border: 1px solid black;
+ border-radius: 1rem;
+
+ background-color: lightgray;
+}
+
+.onionr-post-creator-user-name {
+ color: green;
+ font-weight: bold;
+}
+
+.onionr-post-creator-user-id {
+ color: gray;
+}
+
+.onionr-post-creator-date {
+ color: gray;
+}
+
+.onionr-post-creator-content {
+ font-family: sans-serif, serif;
+ border-top: 1px solid black;
+ font-size: 15pt;
+ background-color: lightgray;
+ color: black;
+ border-width: 0px;
+}
+
.h-divider {
border-top:1px solid gray;
}
diff --git a/onionr/static-data/www/ui/src/index.html b/onionr/static-data/www/ui/src/index.html
index e5791cb9..3fd62f87 100644
--- a/onionr/static-data/www/ui/src/index.html
+++ b/onionr/static-data/www/ui/src/index.html
@@ -10,10 +10,24 @@
-
+
-
arinerron
+
+
+
+
+
@@ -22,6 +36,40 @@
+
+
+
+
<$= LANG.TIMELINE $>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -30,15 +78,58 @@
-
-
<$= LANG.TRENDING $>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <$= htmlTemplate('onionr-timeline-reply-creator') $>
+
+
+
+
+
+