Rev949, Newsfeed allows items 2min from future, Switch sidebar content.json list to input for faster opening, Promise based sidebar rendering to make it more reliable on slow connections, RateLimit sidebar globe updating, Some PEP8 formatting

This commit is contained in:
HelloZeroNet 2016-03-06 19:28:22 +01:00
parent bfdccb809c
commit 2901f1e1ba
7 changed files with 77 additions and 27 deletions

View file

@ -35,7 +35,7 @@ class UiWebsocketPlugin(object):
continue continue
for row in res: for row in res:
row = dict(row) row = dict(row)
if row["date_added"] > time.time() + 60: if row["date_added"] > time.time() + 120:
continue # Feed item is in the future, skip it continue # Feed item is in the future, skip it
row["site"] = address row["site"] = address
row["feed_name"] = name row["feed_name"] = name

View file

@ -148,8 +148,11 @@ class UiWebsocketPlugin(object):
percent = 0 percent = 0
else: else:
percent = 100 * (float(size) / size_total) percent = 100 * (float(size) / size_total)
percent = math.floor(percent*100)/100 # Floor to 2 digits percent = math.floor(percent * 100) / 100 # Floor to 2 digits
body.append(u"""<li style='width: %.2f%%' class='%s back-%s' title="%s"></li>""" % (percent, extension, color, extension)) body.append(
u"""<li style='width: %.2f%%' class='%s back-%s' title="%s"></li>""" %
(percent, extension, color, extension)
)
# Legend # Legend
body.append("</ul><ul class='graph-legend'>") body.append("</ul><ul class='graph-legend'>")
@ -334,15 +337,7 @@ class UiWebsocketPlugin(object):
body.append(""" body.append("""
<li> <li>
<label>Content publishing</label> <label>Content publishing</label>
<select id='select-contents'> <input type='text' class='text' value="content.json" id='input-contents' style='width: 201px'/>
""")
for inner_path in sorted(site.content_manager.contents.keys()):
body.append(u"<option>%s</option>" % cgi.escape(inner_path, True))
body.append("""
</select>
<span class='select-down'>&rsaquo;</span>
<a href='#Sign' class='button' id='button-sign'>Sign</a> <a href='#Sign' class='button' id='button-sign'>Sign</a>
<a href='#Publish' class='button' id='button-publish'>Publish</a> <a href='#Publish' class='button' id='button-publish'>Publish</a>
</li> </li>

View file

@ -0,0 +1,14 @@
limits = {}
call_after_interval = {}
window.RateLimit = (interval, fn) ->
if not limits[fn]
call_after_interval[fn] = false
fn() # First call is not delayed
limits[fn] = setTimeout (->
if call_after_interval[fn]
fn()
delete limits[fn]
delete call_after_interval[fn]
), interval
else # Called within iterval, delay the call
call_after_interval[fn] = true

View file

@ -114,6 +114,7 @@ class Sidebar extends Class
# Create the sidebar html tag # Create the sidebar html tag
createHtmltag: -> createHtmltag: ->
@when_loaded = $.Deferred()
if not @container if not @container
@container = $(""" @container = $("""
<div class="sidebar-container"><div class="sidebar scrollable"><div class="content-wrapper"><div class="content"> <div class="sidebar-container"><div class="sidebar scrollable"><div class="content-wrapper"><div class="content">
@ -141,6 +142,7 @@ class Sidebar extends Class
else else
return true return true
} }
@when_loaded.resolve()
animDrag: (e) => animDrag: (e) =>
@ -195,7 +197,8 @@ class Sidebar extends Class
# Opened # Opened
targetx = @width targetx = @width
if not @opened if not @opened
@onOpened() @when_loaded.done =>
@onOpened()
@opened = true @opened = true
# Revent sidebar transitions # Revent sidebar transitions
@ -265,7 +268,7 @@ class Sidebar extends Class
# Sign content.json # Sign content.json
@tag.find("#button-sign").off("click").on "click", => @tag.find("#button-sign").off("click").on "click", =>
inner_path = @tag.find("#select-contents").val() inner_path = @tag.find("#input-contents").val()
if wrapper.site_info.privatekey if wrapper.site_info.privatekey
# Privatekey stored in users.json # Privatekey stored in users.json
@ -304,12 +307,14 @@ class Sidebar extends Class
loadGlobe: => loadGlobe: =>
console.log "loadGlobe", @tag.find(".globe").hasClass("loading")
if @tag.find(".globe").hasClass("loading") if @tag.find(".globe").hasClass("loading")
setTimeout (=> setTimeout (=>
if typeof(DAT) == "undefined" # Globe script not loaded, do it first if typeof(DAT) == "undefined" # Globe script not loaded, do it first
$.getScript("/uimedia/globe/all.js", @displayGlobe) $.getScript("/uimedia/globe/all.js", @displayGlobe)
else else
@displayGlobe() RateLimit 5000, =>
@displayGlobe()
), 600 ), 600

View file

@ -57,6 +57,36 @@
}).call(this); }).call(this);
/* ---- plugins/Sidebar/media/RateLimit.coffee ---- */
(function() {
var call_after_interval, limits;
limits = {};
call_after_interval = {};
window.RateLimit = function(interval, fn) {
if (!limits[fn]) {
call_after_interval[fn] = false;
fn();
return limits[fn] = setTimeout((function() {
if (call_after_interval[fn]) {
fn();
}
delete limits[fn];
return delete call_after_interval[fn];
}), interval);
} else {
return call_after_interval[fn] = true;
}
};
}).call(this);
/* ---- plugins/Sidebar/media/Scrollable.js ---- */ /* ---- plugins/Sidebar/media/Scrollable.js ---- */
@ -291,6 +321,7 @@ window.initScrollable = function () {
}; };
Sidebar.prototype.createHtmltag = function() { Sidebar.prototype.createHtmltag = function() {
this.when_loaded = $.Deferred();
if (!this.container) { if (!this.container) {
this.container = $("<div class=\"sidebar-container\"><div class=\"sidebar scrollable\"><div class=\"content-wrapper\"><div class=\"content\">\n</div></div></div></div>"); this.container = $("<div class=\"sidebar-container\"><div class=\"sidebar scrollable\"><div class=\"content-wrapper\"><div class=\"content\">\n</div></div></div></div>");
this.container.appendTo(document.body); this.container.appendTo(document.body);
@ -305,10 +336,10 @@ window.initScrollable = function () {
return function(res) { return function(res) {
if (_this.tag.find(".content").children().length === 0) { if (_this.tag.find(".content").children().length === 0) {
_this.log("Creating content"); _this.log("Creating content");
return morphdom(_this.tag.find(".content")[0], '<div class="content">' + res + '</div>'); morphdom(_this.tag.find(".content")[0], '<div class="content">' + res + '</div>');
} else { } else {
_this.log("Patching content"); _this.log("Patching content");
return morphdom(_this.tag.find(".content")[0], '<div class="content">' + res + '</div>', { morphdom(_this.tag.find(".content")[0], '<div class="content">' + res + '</div>', {
onBeforeMorphEl: function(from_el, to_el) { onBeforeMorphEl: function(from_el, to_el) {
if (from_el.className === "globe") { if (from_el.className === "globe") {
return false; return false;
@ -318,6 +349,7 @@ window.initScrollable = function () {
} }
}); });
} }
return _this.when_loaded.resolve();
}; };
})(this)); })(this));
}; };
@ -371,7 +403,11 @@ window.initScrollable = function () {
} else { } else {
targetx = this.width; targetx = this.width;
if (!this.opened) { if (!this.opened) {
this.onOpened(); this.when_loaded.done((function(_this) {
return function() {
return _this.onOpened();
};
})(this));
} }
this.opened = true; this.opened = true;
} }
@ -457,7 +493,7 @@ window.initScrollable = function () {
this.tag.find("#button-sign").off("click").on("click", (function(_this) { this.tag.find("#button-sign").off("click").on("click", (function(_this) {
return function() { return function() {
var inner_path; var inner_path;
inner_path = _this.tag.find("#select-contents").val(); inner_path = _this.tag.find("#input-contents").val();
if (wrapper.site_info.privatekey) { if (wrapper.site_info.privatekey) {
wrapper.ws.cmd("siteSign", ["stored", inner_path], function(res) { wrapper.ws.cmd("siteSign", ["stored", inner_path], function(res) {
return wrapper.notifications.add("sign", "done", inner_path + " Signed!", 5000); return wrapper.notifications.add("sign", "done", inner_path + " Signed!", 5000);
@ -505,13 +541,16 @@ window.initScrollable = function () {
}; };
Sidebar.prototype.loadGlobe = function() { Sidebar.prototype.loadGlobe = function() {
console.log("loadGlobe", this.tag.find(".globe").hasClass("loading"));
if (this.tag.find(".globe").hasClass("loading")) { if (this.tag.find(".globe").hasClass("loading")) {
return setTimeout(((function(_this) { return setTimeout(((function(_this) {
return function() { return function() {
if (typeof DAT === "undefined") { if (typeof DAT === "undefined") {
return $.getScript("/uimedia/globe/all.js", _this.displayGlobe); return $.getScript("/uimedia/globe/all.js", _this.displayGlobe);
} else { } else {
return _this.displayGlobe(); return RateLimit(5000, function() {
return _this.displayGlobe();
});
} }
}; };
})(this)), 600); })(this)), 600);

View file

@ -8,7 +8,7 @@ class Config(object):
def __init__(self, argv): def __init__(self, argv):
self.version = "0.3.6" self.version = "0.3.6"
self.rev = 948 self.rev = 949
self.argv = argv self.argv = argv
self.action = None self.action = None
self.config_file = "zeronet.conf" self.config_file = "zeronet.conf"

View file

@ -190,8 +190,6 @@ class UiRequest(object):
return self.actionSiteMedia("/media" + path) # Only serve html files with frame return self.actionSiteMedia("/media" + path) # Only serve html files with frame
if self.isAjaxRequest(): if self.isAjaxRequest():
return self.error403("Ajax request not allowed to load wrapper") # No ajax allowed on wrapper return self.error403("Ajax request not allowed to load wrapper") # No ajax allowed on wrapper
# if self.env.get("HTTP_ORIGIN") and self.env.get("HTTP_ORIGIN").strip("/") != self.env.get("HTTP_HOST", "").strip("/"):
# return self.error403("Origin does not match")
site = SiteManager.site_manager.get(address) site = SiteManager.site_manager.get(address)
@ -261,7 +259,6 @@ class UiRequest(object):
if content.get("postmessage_nonce_security"): if content.get("postmessage_nonce_security"):
postmessage_nonce_security = "true" postmessage_nonce_security = "true"
if site.settings.get("own"): if site.settings.get("own"):
sandbox_permissions = "allow-modals" # For coffeescript compile errors sandbox_permissions = "allow-modals" # For coffeescript compile errors
else: else:
@ -328,9 +325,9 @@ class UiRequest(object):
allowed_dir = os.path.abspath("%s/%s" % (config.data_dir, address)) # Only files within data/sitehash allowed allowed_dir = os.path.abspath("%s/%s" % (config.data_dir, address)) # Only files within data/sitehash allowed
data_dir = os.path.abspath("data") # No files from data/ allowed data_dir = os.path.abspath("data") # No files from data/ allowed
if ( if (
".." in file_path ".." in file_path or
or not os.path.dirname(os.path.abspath(file_path)).startswith(allowed_dir) not os.path.dirname(os.path.abspath(file_path)).startswith(allowed_dir) or
or allowed_dir == data_dir allowed_dir == data_dir
): # File not in allowed path ): # File not in allowed path
return self.error403() return self.error403()
else: else: