diff --git a/Qt/Bungloo.py b/Qt/Bungloo.py
index 4545b5d..aa0f5d4 100755
--- a/Qt/Bungloo.py
+++ b/Qt/Bungloo.py
@@ -107,15 +107,12 @@ class Controller(QtCore.QObject):
QtCore.QObject.__init__(self)
self.app = app
- oldpath = os.path.expanduser('~/.bungloo/')
- if os.path.isdir(oldpath):
- shutil.copytree(oldpath, os.path.expanduser('~/.config/bungloo/'))
- shutil.rmtree(os.path.expanduser('~/.bungloo/'))
+ name = "bungloo2"
- if not os.path.exists(os.path.expanduser("~/.config/bungloo/")):
- os.makedirs(os.path.expanduser("~/.config/bungloo/"))
+ if not os.path.exists(os.path.expanduser("~/.config/" + name + "/")):
+ os.makedirs(os.path.expanduser("~/.config/" + name + "/"))
- self.config_path = os.path.expanduser('~/.config/bungloo/bungloo.cfg')
+ self.config_path = os.path.expanduser('~/.config/' + name + '/bungloo.cfg')
if os.access(self.config_path, os.R_OK):
with open(self.config_path, 'r') as f:
@@ -173,22 +170,18 @@ class Controller(QtCore.QObject):
except OSError:
pass
- @QtCore.pyqtSlot(str)
- def openNewMessageWidow(self, is_private=False, string=""):
- string = str(string)
- self.openNewMessageWindowInReplyTostatusIdwithStringIsPrivate(None, None, string, is_private)
+ @QtCore.pyqtSlot()
+ def openNewMessageWidow(self):
+ self.openNewMessageWindowInReplyToStatus("")
- @QtCore.pyqtSlot(str, str, str, bool)
- def openNewMessageWindowInReplyTostatusIdwithStringIsPrivate(self, entity, status_id, string, is_private):
- new_message_window = Windows.NewPost(self.app)
- new_message_window.inReplyToStatusIdWithString(entity, status_id, string)
- new_message_window.setIsPrivate(is_private)
+ @QtCore.pyqtSlot(str)
+ def openNewMessageWindowInReplyToStatus(self, status_string):
+ new_message_window = Windows.NewPost(self.app, status_string)
new_message_window.show()
new_message_window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.app.new_message_windows.append(new_message_window)
new_message_window.activateWindow()
new_message_window.setFocus()
- new_message_window.textInput.setFocus()
new_message_window.show()
new_message_window.raise_()
@@ -268,6 +261,16 @@ class Controller(QtCore.QObject):
msgBox.setInformativeText(message)
msgBox.exec_()
+ @QtCore.pyqtSlot(result=str)
+ def getCachedProfiles(self):
+ entities = self.app.timeline.evaluateJavaScript("JSON.stringify(bungloo.cache.profiles);")
+ return entities.toString()
+
+ @QtCore.pyqtSlot()
+ def getNewData(self):
+ func = "bungloo.timeline.getNewData()"
+ self.app.timeline.evaluateJavaScript(func)
+
def logout(self, sender):
print "logout is not implemented yet"
@@ -297,7 +300,7 @@ class Console(QtCore.QObject):
if __name__ == "__main__":
- key = 'BUNGLOO'
+ key = 'BUNGLOO2'
if len(sys.argv) > 1 and sys.argv[1] == "--help":
print """
diff --git a/Qt/Windows.py b/Qt/Windows.py
index b47d8ae..762a02a 100644
--- a/Qt/Windows.py
+++ b/Qt/Windows.py
@@ -9,7 +9,7 @@ class Preferences:
# window
self.window = QtGui.QMainWindow()
- self.window.setWindowTitle("Preferences")
+ self.window.setWindowTitle("Login")
self.window.resize(480, 186)
self.window.setMinimumSize(480, 186)
self.window.setMaximumSize(480, 186)
@@ -242,7 +242,7 @@ class Oauth:
new_manager.sslErrors.connect(lambda reply, errors: self.handleSslErrors(reply, errors))
self.auth_view.page().setNetworkAccessManager(new_manager)
self.auth_view.show()
-
+ print url
self.auth_view.load_url(url)
return False
@@ -329,25 +329,29 @@ class FindEntity(QtGui.QDialog):
class NewPost(Helper.RestorableWindow):
- def __init__(self, app):
+ def __init__(self, app, status_string):
self.app = app
+ self.status_string = status_string
+
Helper.RestorableWindow.__init__(self, "newpost", self.app)
+ self.activateWindow()
+ self.raise_()
self.setWindowIcon(QtGui.QIcon(self.app.resources_path() + "/images/Icon.png"))
- self.textInput = QtGui.QPlainTextEdit(self)
- self.setCentralWidget(self.textInput)
- self.textInput.textChanged.connect(self.onChanged)
+ self.webView = Helper.WebViewCreator(self.app, True, self)
+ self.webView.load_local(self.load_finished)
+ self.setCentralWidget(self.webView)
+
+ self.initUI()
+
+ self.webView.triggerPageAction(QtWebKit.QWebPage.InspectElement)
+ frame = self.webView.page().mainFrame()
+ frame.addToJavaScriptWindowObject("new_post_window", self)
self.setWindowTitle("New Post")
self.resize(300, 150)
self.setMinimumSize(100, 100)
- self.initUI()
-
- self.setIsPrivate(False)
- self.status_id = None
- self.reply_to_entity = None
- self.imageFilePath = None
def initUI(self):
newPostAction = QtGui.QAction("&New Post", self)
@@ -396,89 +400,38 @@ class NewPost(Helper.RestorableWindow):
aboutAction.setStatusTip("Open about page in Webbrowser")
aboutAction.triggered.connect(self.app.open_about)
+ developerExtrasAction = QtGui.QAction("&Developer Extras", self)
+ developerExtrasAction.setStatusTip("Activate webkit inspector")
+ developerExtrasAction.triggered.connect(self.developer_extras)
+
helpMenu = menubar.addMenu("&Help")
helpMenu.addAction(aboutAction)
+ helpMenu.addAction(developerExtrasAction)
-
- self.statusBar().showMessage('256')
-
- self.addButton = QtGui.QToolButton()
- self.addButton.setToolTip("Add photo")
- self.addButton.clicked.connect(self.openFileDialog)
- self.addButton.setAutoRaise(True)
- #addIcon = QtGui.QIcon.fromTheme("insert-image", QtGui.QIcon(self.app.resources_path() + "/images/Actions-insert-image-icon.png"))
- addIcon = QtGui.QIcon(self.app.resources_path() + "/images/glyphicons_138_picture.png")
- self.addButton.setIcon(addIcon)
- self.statusBar().addPermanentWidget(self.addButton)
-
- self.isPrivateButton = QtGui.QToolButton()
- self.isPrivateButton.setToolTip("Make private")
- self.isPrivateButton.clicked.connect(self.toggleIsPrivate)
- self.isPrivateButton.setAutoRaise(True)
- #self.isPrivateIcon = QtGui.QIcon(self.app.resources_path() + "/images/Lock-Lock-icon.png")
- self.isPrivateIcon = QtGui.QIcon(self.app.resources_path() + "/images/glyphicons_203_lock.png")
- #self.isNotPrivateIcon = QtGui.QIcon(self.app.resources_path() + "/images/Lock-Unlock-icon.png")
- self.isNotPrivateIcon = QtGui.QIcon(self.app.resources_path() + "/images/glyphicons_204_unlock.png")
- self.isPrivateButton.setIcon(self.isNotPrivateIcon)
- self.statusBar().addPermanentWidget(self.isPrivateButton)
-
- self.sendButton = QtGui.QToolButton()
- self.sendButton.setToolTip("Send")
- self.sendButton.clicked.connect(self.sendMessage)
- self.sendButton.setAutoRaise(True)
- #sendIcon = QtGui.QIcon.fromTheme("mail-send", QtGui.QIcon(self.app.resources_path() + "/images/send-icon.png"))
- sendIcon = QtGui.QIcon(self.app.resources_path() + "/images/glyphicons_123_message_out.png")
- self.sendButton.setIcon(sendIcon)
- self.statusBar().addPermanentWidget(self.sendButton)
-
- def setIsPrivate(self, is_private):
- self.isPrivate = is_private
- icon = self.isNotPrivateIcon
- if self.isPrivate:
- icon = self.isPrivateIcon
-
- self.isPrivateButton.setIcon(icon)
+ def load_finished(self, widget):
+ callback = "function() { bungloo.newpost.setStatus('%s'); }" % (self.status_string)
+ script = "function HostAppGo() { start('newpost', " + callback + "); }"
+ self.webView.page().mainFrame().evaluateJavaScript(script)
+ self.webView.setFocus()
def toggleIsPrivate(self):
- self.setIsPrivate(not self.isPrivate)
-
- def setString(self, string):
- self.inReplyToStatusIdWithString(None, None, string)
-
- def inReplyToStatusIdWithString(self, reply_to, status_id, string):
- self.reply_to_entity = reply_to
- self.status_id = status_id
- self.textInput.setPlainText(string)
-
- cursor = self.textInput.textCursor()
- cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.MoveAnchor)
- cursor.movePosition(QtGui.QTextCursor.Start, QtGui.QTextCursor.KeepAnchor)
- cursor.movePosition(QtGui.QTextCursor.EndOfLine, QtGui.QTextCursor.KeepAnchor)
- self.textInput.setTextCursor(cursor)
-
- def onChanged(self):
- count = 256 - len(self.textInput.toPlainText())
- self.statusBar().showMessage(str(count))
+ script = "bungloo.newpost.toggleIsPrivate();"
+ self.webView.page().mainFrame().evaluateJavaScript(script)
def sendMessage(self):
- count = len(self.textInput.toPlainText())
- if count > 0 and count <= 256:
- message = Helper.PostModel()
- message.text = unicode(self.textInput.toPlainText().toUtf8(), "utf-8")
- message.inReplyTostatusId = self.status_id
- message.inReplyToEntity = self.reply_to_entity
- message.location = None
- message.imageFilePath = self.imageFilePath
- message.isPrivate = self.isPrivate
- self.app.controller.sendMessage(message)
- self.close()
- else:
- QtGui.qApp.beep()
+ script = "bungloo.newpost.send()"
+ self.webView.page().mainFrame().evaluateJavaScript(script)
+
+ def developer_extras(self, widget):
+ QtWebKit.QWebSettings.globalSettings().setAttribute(QtWebKit.QWebSettings.DeveloperExtrasEnabled, True)
def openFileDialog(self):
- fileNamePath = QtGui.QFileDialog.getOpenFileName(self, "Choose a image", "", "Images (*.png *.gif *.jpg *.jpeg)")
- if len(fileNamePath) > 0:
- self.imageFilePath = str(fileNamePath)
- else:
- self.imageFilePath = None
+ print "openFileDialog Not implemented yet"
+ @QtCore.pyqtSlot()
+ def closeWindow(self):
+ self.close()
+
+ @QtCore.pyqtSlot()
+ def beep(self):
+ QtGui.qApp.beep()
\ No newline at end of file
diff --git a/WebKit/css/default.css b/WebKit/css/default.css
index ff8bbfd..76013fd 100644
--- a/WebKit/css/default.css
+++ b/WebKit/css/default.css
@@ -18,6 +18,15 @@ a {
text-decoration: none;
color: #00317a;
outline: 0;
+ outline : none;
+}
+
+button {
+ background: transparent;
+ border: 0;
+ margin: 0;
+ padding: 4px 5px 0 5px;
+ outline : none;
}
#sidebar {
@@ -446,4 +455,23 @@ form.search input {
p.noresult {
padding : 10px;
text-align : center;
-}
\ No newline at end of file
+}
+
+.new_post #sidebar, .new_post #content { display: none; }
+.new_post { height: 100%; }
+#new_post_container { position: absolute; border-collapse: collapse; height: 100%; width: 100%; }
+#new_post_container td { position: relative; height: 90%; }
+#new_post_container .text td { background: white; }
+#new_post_container textarea { resize: none; box-sizing: border-box; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; background: transparent; outline: none; }
+#new_post_container div { box-sizing: border-box; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; background: white; color: white; padding: 2px; }
+
+#new_post_container div span { background: #D8DFEA; }
+#suggestions { width: 100%; position: absolute; left: 0; bottom: 0; background: #efefef; list-style-type: none; padding: 0; margin: 0; border-top: 1px solid #ccc; }
+#suggestions li { border-top: 1px solid #fefefe; border-bottom: #c9c9c9; padding: 0 0.5em; }
+#suggestions strong { font-weight: normal; color: #555; }
+#suggestions .active { background: #dedede; }
+#suggestions .active strong { color: black; }
+#status_bar { height: 1em; border-top: 1px solid #ccc; }
+#status_bar p { float: right; margin: 0; padding: 0; }
+#status_bar span { display: inline-block; margin: 4px 5px 0 5px; }
+
diff --git a/images/glyphicons_138_picture.png b/WebKit/img/images.png
similarity index 100%
rename from images/glyphicons_138_picture.png
rename to WebKit/img/images.png
diff --git a/images/glyphicons_203_lock.png b/WebKit/img/private.png
similarity index 100%
rename from images/glyphicons_203_lock.png
rename to WebKit/img/private.png
diff --git a/images/glyphicons_204_unlock.png b/WebKit/img/public.png
similarity index 100%
rename from images/glyphicons_204_unlock.png
rename to WebKit/img/public.png
diff --git a/images/glyphicons_123_message_out.png b/WebKit/img/send.png
similarity index 100%
rename from images/glyphicons_123_message_out.png
rename to WebKit/img/send.png
diff --git a/WebKit/scripts/controller/Conversation.js b/WebKit/scripts/controller/Conversation.js
index cb49aeb..817cf01 100644
--- a/WebKit/scripts/controller/Conversation.js
+++ b/WebKit/scripts/controller/Conversation.js
@@ -1,11 +1,11 @@
define([
"helper/HostApp",
"helper/Core",
- "helper/Paths",
+ "helper/APICalls",
"lib/URI"
],
-function(HostApp, Core, Paths, URI) {
+function(HostApp, Core, APICalls, URI) {
function Conversation(standalone) {
@@ -86,15 +86,15 @@ function(HostApp, Core, Paths, URI) {
function getRemoteStatus(profile) {
var server = profile["https://tent.io/types/info/core/v0.1.0"].servers[0];
- Paths.getURL(URI(server + "/posts/" + id).toString(), "GET", callback, null, false);
+ APICalls.http_call(URI(server + "/posts/" + id).toString(), "GET", callback, null, false);
}
var profile = this.cache.profiles.getItem(entity);
if (entity == HostApp.stringForKey("entity")) {
- var url = URI(Paths.mkApiRootPath("/posts/" + id));
- Paths.getURL(url.toString(), "GET", callback, null);
+ var url = URI(APICalls.mkApiRootPath("/posts/" + id));
+ APICalls.http_call(url.toString(), "GET", callback, null);
} else if(profile) {
@@ -102,7 +102,7 @@ function(HostApp, Core, Paths, URI) {
} else {
- Paths.findProfileURL(entity, function(profile_url) {
+ APICalls.findProfileURL(entity, function(profile_url) {
if (profile_url) {
@@ -113,7 +113,7 @@ function(HostApp, Core, Paths, URI) {
} else {
- Paths.getURL(profile_url, "GET", function(resp) {
+ APICalls.http_call(profile_url, "GET", function(resp) {
var profile = JSON.parse(resp.responseText)
this.cache.profiles.setItem(entity, profile);
@@ -128,7 +128,7 @@ function(HostApp, Core, Paths, URI) {
Conversation.prototype.appendMentioned = function(id, entity, node) {
- var url = URI(Paths.mkApiRootPath("/posts"));
+ var url = URI(APICalls.mkApiRootPath("/posts"));
url.addSearch("mentioned_post", id);
url.addSearch("post_types", "https%3A%2F%2Ftent.io%2Ftypes%2Fpost%2Fstatus%2Fv0.1.0");
@@ -147,7 +147,7 @@ function(HostApp, Core, Paths, URI) {
}
}
- Paths.getURL(url.toString(), "GET", callback);
+ APICalls.http_call(url.toString(), "GET", callback);
}
diff --git a/WebKit/scripts/controller/Mentions.js b/WebKit/scripts/controller/Mentions.js
index a0cc51c..80f1ab8 100644
--- a/WebKit/scripts/controller/Mentions.js
+++ b/WebKit/scripts/controller/Mentions.js
@@ -2,11 +2,11 @@ define([
"helper/HostApp",
"controller/Timeline",
"lib/URI",
- "helper/Paths",
+ "helper/APICalls",
"helper/Core"
],
-function(HostApp, Timeline, URI, Paths, Core) {
+function(HostApp, Timeline, URI, APICalls, Core) {
function Mentions() {
@@ -36,7 +36,7 @@ function(HostApp, Timeline, URI, Paths, Core) {
Mentions.prototype.newStatus = function(statuses, append) {
Timeline.prototype.newStatus.call(this, statuses, append);
-
+/*
if(this.is_not_init) {
for (var i = 0; i < statuses.length; i++) {
@@ -51,21 +51,21 @@ function(HostApp, Timeline, URI, Paths, Core) {
if(!append) HostApp.notificateUserAboutMention(status.content.text, name || status.entity, status.id, status.entity);
}
}
-
+*/
this.is_not_init = true;
}
- Mentions.prototype.getNewData = function(add_to_search, append) {
+ Mentions.prototype.getNewData = function(add_to_search, append, query) {
add_to_search = add_to_search || {};
- if (!add_to_search["mentioned_entity"]) {
- add_to_search["mentioned_entity"] = HostApp.stringForKey("entity");
+ if (!add_to_search["mentions"]) {
+ add_to_search["mentions"] = HostApp.stringForKey("entity");
}
- Timeline.prototype.getNewData.call(this, add_to_search, append);
+ Timeline.prototype.getNewData.call(this, add_to_search, append, query);
- this.getLatestMentionRead();
+ //this.getLatestMentionRead();
}
Mentions.prototype.mentionRead = function(id, entity) {
@@ -90,7 +90,7 @@ function(HostApp, Timeline, URI, Paths, Core) {
if (!status.__repost) {
if (status && status.type == "https://tent.io/types/post/status/v0.1.0") {
- var url = URI(Paths.mkApiRootPath("/profile/" + encodeURIComponent("https://tent.io/types/info/cursor/v0.1.0")));
+ var url = URI(APICalls.mkApiRootPath("/profile/" + encodeURIComponent("https://tent.io/types/info/cursor/v0.1.0")));
var body = {
"mentions": {
"https://tent.io/types/post/status/v0.1.0": {
@@ -104,7 +104,7 @@ function(HostApp, Timeline, URI, Paths, Core) {
}
- Paths.getURL(url.toString(), "PUT", callback, JSON.stringify(body));
+ APICalls.http_call(url.toString(), "PUT", callback, JSON.stringify(body));
}
break;
@@ -115,11 +115,11 @@ function(HostApp, Timeline, URI, Paths, Core) {
Mentions.prototype.getLatestMentionRead = function() {
- var cursor_url = URI(Paths.mkApiRootPath("/profile/" + encodeURIComponent("https://tent.io/types/info/cursor/v0.1.0")));
+ var cursor_url = URI(APICalls.mkApiRootPath("/profile/" + encodeURIComponent("https://tent.io/types/info/cursor/v0.1.0")));
- Paths.getURL(cursor_url.toString(), "GET", function(resp) {
+ APICalls.http_call(cursor_url.toString(), "GET", function(resp) {
- var url = URI(Paths.mkApiRootPath("/posts/count"));
+ var url = URI(APICalls.mkApiRootPath("/posts/count"));
var post_types = [
"https://tent.io/types/post/status/v0.1.0",
];
@@ -139,7 +139,7 @@ function(HostApp, Timeline, URI, Paths, Core) {
HostApp.unreadMentions(this.unread_mentions);
}
- Paths.getURL(url.toString(), "GET", callback); // FIXME: error callback
+ APICalls.http_call(url.toString(), "GET", callback); // FIXME: error callback
});
}
diff --git a/WebKit/scripts/controller/NewPost.js b/WebKit/scripts/controller/NewPost.js
new file mode 100644
index 0000000..cd33d35
--- /dev/null
+++ b/WebKit/scripts/controller/NewPost.js
@@ -0,0 +1,395 @@
+define([
+ "helper/APICalls",
+ "helper/HostApp"
+],
+
+function(APICalls, HostApp) {
+
+ function NewPost() {
+
+ this.profiles = JSON.parse(controller.getCachedProfiles());
+ for (var key in this.profiles) {
+ var item = this.profiles[key];
+ if(!item.entity) item.entity = key;
+ if(!item.name) item.name = key;
+ }
+
+ this.mentions = [];
+ document.body.className = "new_post";
+ this.is_private = false;
+
+ // Textarea
+
+ this.container = $("
");
+ this.textarea = this.container.find("textarea");
+ this.highlighter = this.container.find("div");
+
+ $(document.body).append(this.container);
+
+ this.textarea.keyup(this.keyup.bind(this));
+ this.textarea.keydown(this.keydown.bind(this));
+
+ this.suggestions = $("");
+
+ $(document.body).append(this.suggestions);
+
+ // Status bar
+ this.counter = $("256");
+ var buttons = $(
+ "" +
+ //"" +
+ "" +
+ "" +
+ "
");
+
+ this.buttons = {
+ images: buttons.find("#images"),
+ is_private: buttons.find("#private"),
+ send: buttons.find("#send")
+ }
+
+ //this.buttons.images.bind("click", this.addImage.bind(this));
+ this.buttons.is_private.bind("click", this.toggleIsPrivate.bind(this));
+ this.buttons.send.bind("click", this.send.bind(this));
+
+ this.container.find("#status_bar").append(this.counter);
+ this.container.find("#status_bar").append(buttons);
+
+ this.textarea.focus();
+ this.setIsPrivate(false);
+ }
+
+ NewPost.prototype.setStatus = function(status_string) {
+ if (status_string && status_string.length > 0) {
+ this.status = JSON.parse(status_string);
+ this.setIsPrivate(this.status.permissions && !this.status.permissions.public);
+ this.setMentions(this.status);
+ } else {
+ this.status = null;
+ }
+
+ // FIXME set string, private, mentions, etc.
+ };
+
+ NewPost.prototype.setString = function(string) {
+ this.textarea.val(string);
+ }
+
+ NewPost.prototype.setMentions = function(status) {
+
+ var mentions = [this.profiles[status.entity]];
+ var text = this.profiles[status.entity].name + " ";
+ var start = text.length;
+
+ if(status.mentions && status.mentions.length > 0) {
+
+ var mentions_text = ""
+ for (var i = 0; i < status.mentions.length; i++) {
+
+ var entity = status.mentions[i].entity;
+
+ // Sometimes there are mentions without entity, don't know why
+ if(entity) {
+ // fix broken profiles
+ var profile = this.profiles[entity];
+ if(!profile) {
+ profile = {};
+ this.profiles[entity] = profile;
+ }
+ if(!profile.entity) profile.entity = entity;
+ if(!profile.name) profile.name = entity;
+
+ // add profile to mentions and textarea
+ mentions.push(profile);
+ mentions_text += profile.name;
+
+ // add space after mention
+ if(i < status.mentions.length) {
+ mentions_text += " ";
+ }
+ }
+ }
+ if (mentions_text.length > 0) {
+ text += "\n\n/cc " + mentions_text;
+ };
+
+ }
+
+ this.mentions = mentions;
+ this.textarea.val(text);
+ this.parseText(text);
+
+ // Select other mentions so user can start writing and removing them
+ var end = text.length;
+ this.textarea.get(0).setSelectionRange(start, end);
+ }
+
+ NewPost.prototype.setIsPrivate = function(is_private) {
+ this.is_private = is_private;
+ if (this.is_private) {
+ this.buttons.is_private.find("img").attr("src", "img/private.png");
+ } else {
+ this.buttons.is_private.find("img").attr("src", "img/public.png");
+ }
+ }
+
+ NewPost.prototype.toggleIsPrivate = function() {
+ this.setIsPrivate(!this.is_private);
+ }
+
+ NewPost.prototype.keyup = function(e) {
+ if(!e) return;
+
+ var key = e.which;
+ if(key != 38 && key != 40 && key != 13) {
+
+ this.applyText($(this.textarea).val());
+
+ } else {
+
+ var lis = this.suggestions.find("li");
+
+ if (lis.length > 0) {
+ e.preventDefault();
+ var active = this.suggestions.find(".active");
+ if(key == 38) { // up
+ var prev = active.prev();
+ if(active.lentgh == 0) {
+ lis.last().addClass("active");
+ } else if(prev) {
+ active.removeClass("active");
+ prev.addClass("active");
+ }
+ } else if(key == 40) { // down
+ var next = active.next();
+ if(active.length == 0) {
+ lis.first().addClass("active");
+ } else if(next) {
+ active.removeClass("active");
+ next.addClass("active");
+ }
+ } else if(key == 13) { // enter
+ if(active.length > 0) {
+ this.replaceWithName(this.textarea.val(), this.suggestions.find("li.active").get(0).item);
+ }
+ }
+ }
+ }
+ }
+
+ NewPost.prototype.keydown = function(e) {
+ var key = e.which;
+ var lis = this.suggestions.find("li");
+ if(lis.length > 0 && (key == 38 || key == 40 || key == 13)) {
+ e.preventDefault();
+ }
+ }
+
+ NewPost.prototype.replaceAll = function(txt, replace, with_this) {
+ return txt.replace(new RegExp(replace, 'g'),with_this);
+ }
+
+ NewPost.prototype.replaceWithName = function(txt, with_item) {
+ var words = txt.match(/(^|\s)\^([^\s]+)/);
+ var replace = words[2];
+
+ var original = txt.replace("^" + replace, with_item.name + " ");
+ this.textarea.val(original);
+
+ this.mentions.push(with_item);
+
+ this.applyText(original);
+ }
+
+ NewPost.prototype.applyText = function (text) {
+ var words = text.match(/(^|\s)\^([^\s]+)/);
+ this.suggestions.html("");
+
+ if(words) {
+ var name = words[2];
+ for (var key in this.profiles) {
+ var item = this.profiles[key];
+ if((item.name.toLowerCase().indexOf(name.toLowerCase()) != -1) || item.entity.toLowerCase().indexOf(name.toLowerCase()) != -1) {
+ var li = $("" + item.name + "")
+ li.get(0).item = item;
+ this.suggestions.append(li);
+ }
+ }
+ this.suggestions.find("li:first-child").addClass("active");
+ }
+
+ this.parseText(text);
+ }
+
+ NewPost.prototype.parseText = function(text) {
+ // parse the text:
+ // replace all the line braks by
, and all the double spaces by the html version
+ text = this.replaceAll(text,'\n','
');
+ text = this.replaceAll(text,' ',' ');
+
+ // replace the words by a highlighted version of the words
+
+ var remove = [];
+
+ for (var i=0;i' + name + '');
+ } else {
+ remove.push(this.mentions[i]);
+ }
+ }
+
+ for (var i = 0; i < remove.length; i++) {
+ this.mentions.splice(this.mentions.indexOf(remove[i]), 1);
+ }
+
+ // re-inject the processed text into the div
+ this.highlighter.html(text);
+
+ var count = 256 - this.textarea.val().length + (this.mentions.length * 6);
+ this.counter.html(count);
+ }
+
+ NewPost.prototype.send = function() {
+
+ var count = 256 - this.textarea.val().length + (this.mentions.length * 6);
+ if(count >= 0 && count <= 256) {
+ this.sendNewMessage();
+ return true;
+ } else {
+ debug("BEEP");
+ return false;
+ }
+ }
+
+ NewPost.prototype.sendNewMessage = function() {
+
+ var content = this.textarea.val();
+
+ var type = "https://tent.io/types/status/v0#";
+ var data = {
+ type: type,
+ content: {
+ text: content
+ },
+ permissions: {
+ public: !this.is_private
+ }
+ };
+
+ var mentions = [];
+ for (var i = 0; i < this.mentions.length; i++) {
+ var mention = this.mentions[i];
+ if(this.status && this.status.entity == mention.entity) {
+ mentions.push({
+ entity: this.status.entity,
+ post: this.status.id,
+ type: this.status.type
+ });
+ } else {
+ mentions.push({
+ entity: mention.entity
+ });
+ }
+ }
+
+ data.mentions = mentions;
+
+ // Make tent flavored markdown mentions
+ for (var i = 0; i < this.mentions.length; i++) {
+ var mention = this.mentions[i];
+ data.content.text = this.replaceAll(data.content.text, mention.name, "^[" + mention.name + "](" + i + ")")
+ }
+
+ APICalls.post(HostApp.serverUrl("new_post"), JSON.stringify(data), {
+ content_type: data.type,
+ accept: 'application/vnd.tent.post.v0+json; type="https://tent.io/types/status/v0#"',
+ callback: function(resp) {
+ if (resp.status >= 200 < 300) {
+ new_post_window.closeWindow();
+ controller.getNewData();
+ } else {
+ new_post_window.beep();
+ }
+ }
+ });
+ }
+/*
+ NewPost.prototype.sendNewMessageWithImage = function(content, in_reply_to_status_id, in_reply_to_entity, location, image_data_uri, is_private, callback) {
+
+ var url = URI(APICalls.mkApiRootPath("/posts"));
+
+ var data = {
+ "type": "https://tent.io/types/post/photo/v0.1.0",
+ "published_at": parseInt(new Date().getTime() / 1000, 10),
+ "permissions": {
+ "public": !is_private
+ },
+ "content": {
+ "caption": content,
+ },
+ };
+
+ if (location) {
+ data["content"]["location"] = { "type": "Point", "coordinates": location }
+ }
+
+ var mentions = this.parseMentions(content, in_reply_to_status_id, in_reply_to_entity);
+ if (mentions.length > 0) {
+ data["mentions"] = mentions;
+ if (is_private) {
+ var entities = {};
+ for (var i = 0; i < mentions.length; i++) {
+ var entity = mentions[i]["entity"]
+ entities[entity] = true;
+ };
+
+ data["permissions"]["entities"] = entities;
+ }
+ }
+
+ var data_string = JSON.stringify(data);
+
+ var boundary = "TentAttachment----------TentAttachment";
+ var post = "--" + boundary + "\r\n";
+
+ post += 'Content-Disposition: form-data; name="post"; filename="post.json"\r\n';
+ post += 'Content-Length: ' + data_string.length + '\r\n';
+ post += 'Content-Type: application/vnd.tent.v0+json\r\n';
+ post += 'Content-Transfer-Encoding: binary\r\n\r\n';
+ post += data_string;
+
+ post += "\r\n--" + boundary + "\r\n";
+
+ var blob_string = image_data_uri.split(',')[1];
+ var mime_type = image_data_uri.split(',')[0].split(':')[1].split(';')[0];
+ var ext = "png";
+ if (mime_type == "image/jpeg") {
+ ext = "jpeg";
+ } else if (mime_type == "image/gif") {
+ ext = "gif";
+ }
+
+
+ post += 'Content-Disposition: form-data; name="photos[0]"; filename="photo.' + ext + '"\r\n';
+ post += 'Content-Length: ' + blob_string.length + "\r\n";
+ post += 'Content-Type: ' + mime_type + "\r\n";
+ post += 'Content-Transfer-Encoding: base64\r\n\r\n';
+ post += blob_string;
+ post += "\r\n--" + boundary + "--\r\n";
+
+ var newCallback = function(resp) {
+ if (resp.status == 403) {
+ var err = JSON.parse(resp.responseText);
+ HostApp.alertTitleWithMessage(resp.statusText, err.error);
+ }
+ callback(resp);
+ }
+
+ APICalls.postMultipart(url.toString(), newCallback, post, boundary);
+ }
+*/
+
+ return NewPost;
+})
\ No newline at end of file
diff --git a/WebKit/scripts/controller/Oauth.js b/WebKit/scripts/controller/Oauth.js
index 0cebc2e..7967c12 100644
--- a/WebKit/scripts/controller/Oauth.js
+++ b/WebKit/scripts/controller/Oauth.js
@@ -1,38 +1,46 @@
define([
"helper/HostApp",
- "helper/Paths",
+ "helper/APICalls",
"helper/Hmac"
],
-function(HostApp, Paths, Hmac) {
+function(HostApp, APICalls, Hmac) {
function Oauth() {
this.app_info = {
- "id": null,
- "name": "Bungloo on " + HostApp.osType(),
- "description": "A small TentStatus client.",
- "url": "http://jabs.nu/bungloo/",
- "icon": "http://jabs.nu/bungloo/icon.png",
- "redirect_uris": [
- "bungloo://oauthtoken"
- ],
- "scopes": {
- "read_posts": "Uses posts to show them in a list",
- "write_posts": "Posts on users behalf",
- "read_profile": "Displays your own profile",
- "write_profile": "Updating profile and mentions pointer",
- "read_followers": "Display a list of people who follow you",
- "write_followers": "Be able to block people who follow you",
- "read_followings": "Display following list and their older posts in conversations",
- "write_followings": "Follow ne entities"
+ "type": "https://tent.io/types/app/v0#",
+ "content": {
+ "name": "Bungloo on " + HostApp.osType(),
+ "url": "http://jabs.nu/bungloo/",
+ "description": "A desktop Tent client.",
+ "redirect_uri": "bungloo://oauthtoken",
+ "types": {
+ "read": [
+ "https://tent.io/types/meta/v0",
+ "https://tent.io/types/relationship/v0",
+ "https://tent.io/types/subscription/v0",
+ "https://tent.io/types/delete/v0",
+ "https://tent.io/types/status/v0",
+ "https://tent.io/types/repost/v0",
+ "https://tent.io/types/photo/v0",
+ "https://tent.io/types/cursor/v0",
+ "https://tent.io/types/basic-profile/v0"
+ ],
+ "write": [
+ "https://tent.io/types/relationship/v0",
+ "https://tent.io/types/subscription/v0",
+ "https://tent.io/types/delete/v0",
+ "https://tent.io/types/status/v0",
+ "https://tent.io/types/repost/v0",
+ "https://tent.io/types/photo/v0",
+ "https://tent.io/types/cursor/v0"
+ ]
+ },
+ "scopes": ["permissions"]
},
- "tent_profile_info_types": [ "all" ],
- "tent_post_types": [
- "https://tent.io/types/post/status/v0.1.0",
- "https://tent.io/types/post/photo/v0.1.0",
- "https://tent.io/types/post/repost/v0.1.0",
- "https://tent.io/types/post/delete/v0.1.0"
- ]
+ "permissions": {
+ "public": false
+ }
};
this.register_data = null;
this.profile = null;
@@ -61,13 +69,9 @@ function(HostApp, Paths, Hmac) {
}
}
- Oauth.prototype.apiRoot = function() {
- return this.profile["https://tent.io/types/info/core/v0.1.0"]["servers"][0];
- }
-
Oauth.prototype.requestProfileURL = function (entity) {
var those = this;
- Paths.findProfileURL(entity,
+ APICalls.findProfileURL(entity,
function(profile_url) {
if (profile_url && (profile_url.startsWith("http://") || profile_url.startsWith("https://"))) {
those.register(profile_url);
@@ -76,6 +80,7 @@ function(HostApp, Paths, Hmac) {
}
},
function(errorMessage) { // error callback
+ HostApp.authentificationDidNotSucceed(errorMessage);
HostApp.authentificationDidNotSucceed("Could not find profile for: " + entity);
}
);
@@ -84,72 +89,76 @@ function(HostApp, Paths, Hmac) {
Oauth.prototype.register = function (url) {
var those = this;
- Paths.getURL(url, "GET", function(resp) {
+ APICalls.get(url, {
+ no_auth: true,
+ callback: function(resp) {
- those.profile = JSON.parse(resp.responseText);
- those.entity = those.profile["https://tent.io/types/info/core/v0.1.0"].entity;
+ those.profile = JSON.parse(resp.responseText).post;
+ those.entity = those.profile.content.entity;
HostApp.setStringForKey(those.entity, "entity")
- HostApp.setStringForKey(those.apiRoot(), "api_root");
+ HostApp.setServerUrls(those.profile.content.servers[0].urls);
+ APICalls.post(HostApp.serverUrl("new_post"), JSON.stringify(those.app_info), {
+ content_type: "https://tent.io/types/app/v0#",
+ no_auth: true,
+ callback: function(resp) {
+ var app_id = JSON.parse(resp.responseText).post.id;
+ var header_string = resp.getAllResponseHeaders();
+ var regexp = /https:\/\/tent.io\/rels\/credentials/i
+ var url = APICalls.parseHeaderForLink(header_string, regexp);
- var callback = function(resp) {
- var data = JSON.parse(resp.responseText);
- those.authRequest(data);
- }
- Paths.getURL(Paths.mkApiRootPath("/apps"), "POST", callback, JSON.stringify(those.app_info), false);
- }, null, false);
+ APICalls.get(url, {
+ content_type: "https://tent.io/types/app/v0#",
+ no_auth: true,
+ callback: function(resp) {
+ var data = JSON.parse(resp.responseText);
+ those.authRequest(data.post, app_id);
+ }
+ });
+ }});
+
+ }});
}
- Oauth.prototype.authRequest = function(register_data) {
- // id
- // mac_key_id
- // mac_key
- // mac_algorithm
- this.register_data = register_data;
-
- // Needed for later App Registration Modification
- HostApp.setStringForKey(register_data["mac_key"], "app_mac_key");
- HostApp.setStringForKey(register_data["mac_key_id"], "app_mac_key_id");
- HostApp.setStringForKey(register_data["id"], "app_id");
- HostApp.setStringForKey(register_data["mac_algorithm"], "app_mac_algorithm");
-
+ Oauth.prototype.authRequest = function(credentials, app_id) {
+
+ HostApp.setStringForKey(app_id, "app_id");
+ HostApp.setStringForKey(credentials.id, "app_hawk_id");
+ HostApp.setStringForKey(credentials.content.hawk_key, "app_hawk_key");
+ HostApp.setStringForKey(credentials.content.hawk_algorithm, "app_hawk_algorithm");
+
this.state = Hmac.makeid(19);
- var auth = "/oauth/authorize?client_id=" + register_data["id"]
- + "&redirect_uri=" + this.app_info["redirect_uris"][0]
- + "&scope=" + Object.keys(this.app_info["scopes"]).join(",")
- + "&state=" + this.state
- + "&tent_post_types=" + this.app_info["tent_post_types"].join(",")
- + "&tent_profile_info_types=" + this.app_info["tent_profile_info_types"].join(",");
-
- HostApp.openAuthorizationURL(this.apiRoot() + auth);
+ var url = HostApp.serverUrl("oauth_auth") + "?client_id=" + app_id + "&state=" + this.state;
+ HostApp.openAuthorizationURL(url);
}
Oauth.prototype.requestAccessToken = function(responseBody) {
// /oauthtoken?code=51d0115b04d1ed94001dde751c5b360f&state=aQfH1VEohYsQr86qqyv
+ // https://app.example.com/oauth?code=K4m2J2bGI9rcICBqmUCYuQ&state=d173d2bb868a
- var urlVars = Paths.getUrlVars(responseBody);
+ var urlVars = APICalls.getUrlVars(responseBody);
if(this.state && this.state != "" && urlVars["state"] == this.state) {
- var url = Paths.mkApiRootPath("/apps/") + this.register_data["id"] + "/authorizations";
+ var url = HostApp.serverUrl("oauth_token");
var requestBody = JSON.stringify({
'code' : urlVars["code"],
- 'token_type' : "mac"
+ 'token_type': "https://tent.io/oauth/hawk-token"
});
var those = this;
- var http_method = "POST";
- var callback = function(resp) {
- those.requestAccessTokenTicketFinished(resp.responseText);
- };
-
- var auth_header = Hmac.makeAuthHeader(
+ var auth_header = Hmac.makeHawkAuthHeader(
url,
- http_method,
- HostApp.stringForKey("app_mac_key"),
- HostApp.stringForKey("app_mac_key_id")
+ "POST",
+ HostApp.stringForKey("app_hawk_id"),
+ HostApp.stringForKey("app_hawk_key")
);
- Paths.getURL(url, http_method, callback, requestBody, auth_header);
+ APICalls.post(url, requestBody, {
+ content_type: "application/json",
+ auth_header: auth_header,
+ callback: function(resp) {
+ those.requestAccessTokenTicketFinished(resp.responseText);
+ }});
} else {
console.error("State is not the same: {" + this.state + "} vs {" + urlVars["state"] + "}")
@@ -163,16 +172,16 @@ function(HostApp, Paths, Hmac) {
var access = JSON.parse(responseBody);
HostApp.setStringForKey(access["access_token"], "user_access_token");
- HostApp.setSecret(access["mac_key"]);
- HostApp.setStringForKey(access["mac_algorithm"], "user_mac_algorithm");
+ HostApp.setSecret(access["hawk_key"]);
+ HostApp.setStringForKey(access["hawk_algorithm"], "user_hawk_algorithm");
HostApp.setStringForKey(access["token_type"], "user_token_type");
HostApp.loggedIn();
}
- Oauth.prototype.logout = function() {
+ Oauth.prototype.logout = function() { // FIXME
- var url = Paths.mkApiRootPath("/apps/" + HostApp.stringForKey("app_id"));
+ var url = APICalls.mkApiRootPath("/apps/" + HostApp.stringForKey("app_id"));
var http_method = "DELETE";
var auth_header = Hmac.makeAuthHeader(
url,
@@ -181,7 +190,7 @@ function(HostApp, Paths, Hmac) {
HostApp.stringForKey("app_mac_key_id")
);
- Paths.getURL(url, http_method, function(resp) {
+ APICalls.http_call(url, http_method, function(resp) {
HostApp.setStringForKey(null, "app_mac_key");
HostApp.setStringForKey(null, "app_mac_key_id");
HostApp.setStringForKey(null, "app_id");
diff --git a/WebKit/scripts/controller/Profile.js b/WebKit/scripts/controller/Profile.js
index 584a046..840eed9 100644
--- a/WebKit/scripts/controller/Profile.js
+++ b/WebKit/scripts/controller/Profile.js
@@ -1,667 +1,667 @@
define([
- "helper/HostApp",
- "helper/Core",
- "helper/Paths",
- "lib/URI"
+ "helper/HostApp",
+ "helper/Core",
+ "helper/APICalls",
+ "lib/URI",
+ "controller/Timeline"
],
-function(HostApp, Core, Paths, URI) {
+function(HostApp, Core, APICalls, URI, Timeline) {
- function Profile() {
+ function Profile() {
+
+ Timeline.call(this);
- Core.call(this);
+ this.action = "profile";
- this.action = "profile";
+ this.container = document.createElement("div");
+ this.container.className = this.action;
+ document.getElementById("content").appendChild(this.container);
- this.posts_limit = 25;
+ this.initProfileTemplate();
+ this.hide();
+ }
- this.container = document.createElement("div");
- this.container.className = this.action;
- document.getElementById("content").appendChild(this.container);
+ Profile.prototype = Object.create(Timeline.prototype);
+
- this.initProfileTemplate();
- this.hide();
+ Profile.prototype.show = function() {
+ Core.prototype.show.call(this, this.container);
+ }
+
+ Profile.prototype.hide = function() {
+ Core.prototype.hide.call(this, this.container);
+ }
+
+ Profile.prototype.logout = function() {
+ this.container = "";
+ }
+
+ Profile.prototype.showList = function(list) {
+ $(this.body).hide();
+ $(this.followingsBody).hide();
+ $(this.followersBody).hide();
+ $(list).show();
+ }
- var _this = this;
- setTimeout(function() { _this.showProfileForEntity() }, 5000); // Load users profile on start
- }
+ Profile.prototype.showEntity = function(a, i) {
+ var entity = $(a).closest("li").get(0).status.mentions[i].entity;
+ this.showProfileForEntity(entity);
+ bungloo.sidebar.onEntityProfile();
+ };
+
+ Profile.prototype.showProfileForEntity = function(entity) {
+
+ if (!entity) {
+ entity = HostApp.stringForKey("entity");
+ }
+
+ this.clear();
+ this.entity = entity;
+ this.following = null;
+ this.following_id = null;
+ this.profile_template.entity.innerHTML = this.entity;
+ this.profile_template.entity.href = this.entity;
+
+ this.getProfile();
+ this.getFollowing();
+ this.getStatuses();
+ }
+
+ Profile.prototype.initProfileTemplate = function() {
+
+ var _this = this;
+
+ var header = document.createElement("header");
+ header.className = "profile";
- Profile.prototype = Object.create(Core.prototype);
-
+ this.container.appendChild(header);
- Profile.prototype.show = function() {
- Core.prototype.show.call(this, this.container);
- }
+ this.profile_template = {
+ avatar: document.createElement("img"),
+ name: document.createElement("h1"),
+ entity: document.createElement("a"),
+ bio: document.createElement("p"),
+ relationships: document.createElement("td"),
+ posts: document.createElement("a"),
+ following: document.createElement("a"),
+ followed: document.createElement("a"),
+ birthdate: document.createElement("td"),
+ location: document.createElement("td"),
+ gender: document.createElement("td"),
+ url: document.createElement("a"),
+ following_button: document.createElement("button"),
+ mention_button: document.createElement("button")
+ };
- Profile.prototype.hide = function() {
- Core.prototype.hide.call(this, this.container);
- }
+ header.appendChild(this.profile_template.avatar);
+ this.profile_template.avatar.src = "img/default-avatar.png";
+
+ var div = document.createElement("div");
+ header.appendChild(div);
+
+ this.profile_template.following_button.onclick = function(e) {
+ _this.toggleFollow()
+ }
+ div.appendChild(this.profile_template.following_button);
+
+ this.profile_template.mention_button.onclick = function() {
+ HostApp.openNewMessageWidow({entity:_this.entity});
+ }
+ div.appendChild(this.profile_template.mention_button);
+ this.profile_template.mention_button.innerHTML = "Mention";
+
+ div.appendChild(this.profile_template.name);
+
+ var p = document.createElement("p");
+ p.appendChild(this.profile_template.entity);
+ div.appendChild(p);
+
+ div.appendChild(this.profile_template.bio);
+
+ var table = document.createElement("table");
+ div.appendChild(table);
+
+ function mkLi(name, template) {
+ var tr = document.createElement("tr");
+ var th = document.createElement("th");
+ tr.style.display = "none";
+ th.innerText = name + ": ";
+ tr.appendChild(th);
+ tr.appendChild(template);
+ table.appendChild(tr);
+ }
+
+ mkLi("Birth date", this.profile_template.birthdate);
+ mkLi("Location", this.profile_template.location);
+ mkLi("Gender", this.profile_template.gender);
+
+ var td = document.createElement("td");
+ td.appendChild(this.profile_template.url);
+ mkLi("Homepage", td);
+
+ mkLi("Relationships", this.profile_template.relationships);
+
+ td = document.createElement("td");
+ td.appendChild(this.profile_template.posts);
+ this.profile_template.posts.href = "#";
+ this.profile_template.posts.onclick = function() { _this.showPosts(); return false; };
+ mkLi("Posts", td);
+
+ td = document.createElement("td");
+ td.appendChild(this.profile_template.following);
+ this.profile_template.following.href = "#";
+ this.profile_template.following.onclick = function() { _this.showFollowings(); return false; };
+ mkLi("Following", td);
+
+ td = document.createElement("td");
+ td.appendChild(this.profile_template.followed);
+ this.profile_template.followed.href = "#";
+ this.profile_template.followed.onclick = function() { _this.showFollowers(); return false; };
+ mkLi("Followed by", td);
+
+
+ this.body = document.createElement("ol");
+ this.body.className = this.action;
+ this.container.appendChild(this.body);
+
+ this.followingsBody = document.createElement("ol");
+ this.followingsBody.className = this.action + " followings";
+ this.container.appendChild(this.followingsBody);
+
+ this.followersBody = document.createElement("ol");
+ this.followersBody.className = this.action + " folloewds";
+ this.container.appendChild(this.followersBody);
+
+ }
+
+ Profile.prototype.clear = function() {
+
+ this.server = null;
+ this.before = {id: null, entity: null, loading: false};
+
+
+ this.profile_template.avatar.src = "img/default-avatar.png";
+
+ this.relationships = {
+ following_you: false,
+ followed_by_you: false,
+ it_is_you: false
+ }
+
+ this.profile_template.name.innerText = "";
+ this.profile_template.entity.innerText = "";
+ this.profile_template.bio.innerText = "";
+ this.profile_template.relationships.innerText = "";
+ this.profile_template.posts.innerText = "";
+ this.profile_template.following.innerText = "";
+ this.profile_template.followed.innerText = "";
+ this.profile_template.birthdate.innerText = "";
+ this.profile_template.location.innerText = "";
+ this.profile_template.gender.innerText = "";
+ this.profile_template.url.innerText = "";
+ this.profile_template.url.href = "";
+
+ this.profile_template.posts.parentNode.parentNode.style.display = "none";
+ this.profile_template.following.parentNode.parentNode.style.display = "none";
+ this.profile_template.followed.parentNode.parentNode.style.display = "none";
+ this.profile_template.birthdate.parentNode.style.display = "none";
+ this.profile_template.location.parentNode.style.display = "none";
+ this.profile_template.gender.parentNode.style.display = "none";
+ this.profile_template.url.parentNode.parentNode.style.display = "none";
+
+ this.profile_template.following_button.style.display = "";
+ this.setFollowingButton(false);
+
+ this.body.innerHTML = "";
+ this.followingsBody.innerHTML = "";
+ this.followersBody.innerHTML = "";
+
+ this.showList(this.body);
+ };
+
+ Profile.prototype.getProfile = function() {
+
+ var _this = this;
+
+ if (HostApp.stringForKey("entity") == this.entity) {
+ this.relationships.it_is_you = true;
+ this.profile_template.following_button.style.display = "none";
+ }
+
+ var url = HostApp.serverUrl("posts_feed") + "?types=" + encodeURIComponent("https://tent.io/types/meta/v0") + "&entities=" + encodeURIComponent(this.entity);
+ APICalls.get(url, {
+ callback: function(resp) {
+ var profile = JSON.parse(resp.responseText);
+ _this.showProfile(profile);
+ _this.profile = profile;
+ }});
+ }
+
+ Profile.prototype.getFollowing = function() {
+ if(this.entity != HostApp.stringForKey("entity")) {
+
+ var url = HostApp.serverUrl("posts_feed") + "?mentions=" + encodeURIComponent(this.entity) + "&types=" + encodeURIComponent("https://tent.io/types/subscription/v0#https://tent.io/types/status/v0");
+ var _this = this;
+
+ APICalls.get(url, {callback: function(resp) {
+
+ var json = JSON.parse(resp.responseText);
+ var count = json.posts.length;
+
+ if (count > 0) {
+ _this.setFollowingButton(true);
+ _this.following_id = json.posts[0].id;
+ } else {
+ _this.setFollowingButton(false);
+ delete _this.following_id;
+ }
+
+ }});
+
+ } else {
+
+ this.setFollowingButton(false);
+ this.following_id = null;
+ }
+ }
+
+ Profile.prototype.showProfile = function(profiles) {
+
+ if(profiles.posts.length < 1) return;
+ var profile = profiles.posts[0];
+ bungloo.cache.profiles[profile.entity] = profile.content.profile;
+
+ var basic = profile.content.profile;
+
+ if (profile && basic) {
+
+ // Find and apply avatar
+ if(profile.attachments) {
+
+ var digest = null;
+ for (var i = 0; i < profile.attachments.length; i++) {
+ var attachment = profile.attachments[i];
+ if(attachment.category == "avatar") {
+ digest = attachment.digest;
+ break;
+ }
+ }
+
+ if(digest) {
+ var _this = this;
+ this.profile_template.avatar.onerror = function() { _this.profile_template.avatar.src = 'img/default-avatar.png' };
+ var avatar_url = profile.content.servers[0].urls.attachment.replace(/\{entity\}/, encodeURIComponent(profile.entity));
+ this.profile_template.avatar.src = avatar_url.replace(/\{digest\}/, digest);
+ }
+ }
+
+ this.populate(this.profile_template.name, basic.name);
+ this.populate(this.profile_template.birthdate, basic.birthdate);
+ this.populate(this.profile_template.location, basic.location);
+ this.populate(this.profile_template.gender, basic.gender);
+ this.populate(this.profile_template.bio, basic.bio);
+
+ if(basic.website) {
+
+ var url = basic.website;
+ this.profile_template.url.innerText = url;
+ this.profile_template.url.parentNode.parentNode.style.display = "";
+
+ if (!url.startsWith("http")) {
+ url = "http://" + url;
+ }
+
+ this.profile_template.url.href = url;
+ }
+ }
+
+ if (profile) {
+ this.profile = profile;
+
+ // FIXME
+ this.getMeta(this.profile);
+ this.getStatuses();
+ }
+ }
+
+ Profile.prototype.populate = function(t, v) {
+ if (v) {
+ t.innerText = v;
+ t.parentNode.style.display = "";
+ t.parentNode.parentNode.style.display = "";
+ }
+ }
+
+ Profile.prototype.getMeta = function(profile) {
+
+ // FIXME!
+
+ var _this = this;
+/*
+ var url = HostApp.serverUrl("posts_feed") + "?entities=" + encodeURIComponent(this.entity) + "&types=" + encodeURIComponent("https://tent.io/types/subscription/v0#");
+ APICalls.head(url, {
+ callback: function(resp) {
+ _this.populate(_this.profile_template.followed, APICalls.getCount(resp) + " ");
+ }
+ });
+
+ var url = HostApp.serverUrl("posts_feed") + "?entities=" + encodeURIComponent(this.entity) + "&types=" + encodeURIComponent("https://tent.io/types/relationship/v0#following");
+ APICalls.head(url, {
+ callback: function(resp) {
+ _this.populate(_this.profile_template.following, APICalls.getCount(resp) + " ");
+ }
+ });
+
+ var url = HostApp.serverUrl("posts_feed") + "?entities=" + encodeURIComponent(this.entity) + "&types=" + encodeURIComponent("https://tent.io/types/status/v0#");
+ APICalls.head(url, {
+ callback: function(resp) {
+ _this.populate(_this.profile_template.posts, APICalls.getCount(resp) + " ");
+ }
+ });
+*/
+
+ // is following you
+ // FIXME: should use HEAD
+ var url = HostApp.serverUrl("posts_feed") + "?entities=" + encodeURIComponent(this.entity) + "&types=" + encodeURIComponent("https://tent.io/types/subscription/v0#https://tent.io/types/status/v0") + "&mentions=" + encodeURIComponent(HostApp.stringForKey("entity"));
+ APICalls.get(url, {
+ callback: function(resp) {
+ var json = JSON.parse(resp.responseText);
+ if (json.posts.length > 0) {
+ _this.relationships.following_you = true;
+ } else {
+ _this.relationships.following_you = false;
+ }
+ _this.setRelationships();
+ }
+ });
+
+ // is followed by you
+ // FIXME: should use HEAD
+ var url = HostApp.serverUrl("posts_feed") + "?mentions=" + encodeURIComponent(this.entity) + "&types=" + encodeURIComponent("https://tent.io/types/subscription/v0#https://tent.io/types/status/v0");
+ APICalls.get(url, {
+ callback: function(resp) {
+ var json = JSON.parse(resp.responseText);
+ if (json.posts.length > 0) {
+ _this.relationships.followed_by_you = true;
+ } else {
+ _this.relationships.followed_by_you = false;
+ }
+ _this.setRelationships();
+ }
+ });
+
+ return;
+/*
+
+
+ if (this.entity != HostApp.stringForKey("entity")) {
+ APICalls.http_call(URI(root_url + "/followers/" + encodeURIComponent(HostApp.stringForKey("entity"))).toString(), "GET", function(resp) {
+ if (resp.status == 200) {
+ _this.relationships.following_you = true;
+ }
+ _this.setRelationships();
+
+ }, null, false);
+
+ APICalls.http_call(URI(APICalls.mkApiRootPath("/followings/" + encodeURIComponent(this.entity))), "GET", function(resp) {
+ if (resp.status == 200) {
+ _this.relationships.followed_by_you = true;
+ }
+ _this.setRelationships();
+ });
+
+ } else {
+ this.setRelationships();
+ }
+
+
+ var url = URI(root_url + "/posts/count");
+ var post_types = [
+ "https://tent.io/types/post/repost/v0.1.0",
+ "https://tent.io/types/post/status/v0.1.0",
+ "https://tent.io/types/post/photo/v0.1.0"
+ ];
+ url.addSearch("post_types", post_types.join(","));
+
+ APICalls.http_call(url.toString(), "GET", function(resp) {
+
+ _this.populate(_this.profile_template.posts, resp.responseText);
+ }, null, false);*/
+ }
+
+ Profile.prototype.setRelationships = function() {
+ var relation = "none";
+ if (HostApp.stringForKey("entity") == this.entity) {
+ relation = "it's you";
+ } else {
+ if (this.relationships.following_you && !this.relationships.followed_by_you) {
+ relation = "is following you";
+ } else if (this.relationships.following_you && this.relationships.followed_by_you) {
+ relation = "you both follow each other";
+ } else if (!this.relationships.following_you && this.relationships.followed_by_you) {
+ relation = "being followed by you";
+ }
+ }
+ this.populate(this.profile_template.relationships, relation);
+ }
+
+
+ Profile.prototype.getStatuses = function() {
+
+ Timeline.prototype.getNewData.call(this, {entities: this.entity});
+ }
+
+ Profile.prototype.setFollowingButton = function(following) {
+
+ this.following = following;
+
+ if (following) {
+ this.profile_template.following_button.className = "following";
+ this.profile_template.following_button.innerText = "Unfollow";
+ } else {
+ this.profile_template.following_button.className = "";
+ this.profile_template.following_button.innerText = "Follow";
+ }
+ }
+
+ Profile.prototype.toggleFollow = function() {
+
+ var _this = this;
+
+ if (this.following_id) {
+
+ this.setFollowingButton(false);
+
+ var url = HostApp.serverUrl("post").replace(/\{entity\}/, encodeURIComponent(HostApp.stringForKey("entity"))).replace(/\{post\}/, this.following_id);
+ APICalls.delete(url, { callback: function(resp) {
+ if (resp.status >= 200 && resp.status < 300) {
+ _this.setFollowingButton(false);
+ delete _this.following_id;
+ } else {
+ _this.setFollowingButton(true);
+ }
+ _this.getMeta();
+ }});
+
+ } else {
+
+ this.setFollowingButton(true);
+
+ var url = HostApp.serverUrl("new_post");
+
+ var data = {
+ content: {
+ type: "https://tent.io/types/status/v0"
+ },
+ mentions: [{
+ entity: this.entity
+ }],
+ type: "https://tent.io/types/subscription/v0#https://tent.io/types/status/v0"
+ };
+
+ debug(data)
+ debug(url)
+
+ APICalls.post(url, JSON.stringify(data), {
+ content_type: data.type,
+ callback: function(resp) {
+ if (resp.status >= 200 && resp.status < 300) {
+ _this.setFollowingButton(true);
+ var json = JSON.parse(resp.responseText);
+ _this.following_id = json.post.id;
+ } else {
+ _this.setFollowingButton(false);
+ }
+ _this.getMeta();
+ }
+ });
+ }
+ }
+
+ Profile.prototype.showPosts = function() {
+ this.showList(this.body);
+ }
+
+ Profile.prototype.showFollowings = function() {
+
+ this.showList(this.followingsBody);
+ this.followingsBody.innerHTML = "";
+
+ var _this = this;
+ var callback = function(resp) {
+ var followings = JSON.parse(resp.responseText);
+ for (var i = 0; i < followings.length; i++) {
+ var li = _this.getDOMSmallProfile(followings[i]);
+ _this.followingsBody.appendChild(li);
+ }
+ }
+
+ var url = URI(this.server + "/followings");
+ url.addSearch("limit", 200);
+ APICalls.http_call(url.toString(), "GET", callback, null, false);
+ }
+
+ Profile.prototype.showFollowers = function() {
+
+ this.showList(this.followersBody);
+ this.followersBody.innerHTML = "";
+
+ var _this = this;
+ var callback = function(resp) {
+ var followers = JSON.parse(resp.responseText);
+ for (var i = 0; i < followers.length; i++) {
+ var li = _this.getDOMSmallProfile(followers[i]);
+ _this.followersBody.appendChild(li);
+ }
+ }
+
+ var url = URI(this.server + "/followers");
+ url.addSearch("limit", 200);
+ APICalls.http_call(url.toString(), "GET", callback, null, false);
+ }
+
+ Profile.prototype.getDOMSmallProfile = function(profile) {
+
+ var li = document.createElement("li");
+
+ var image = document.createElement("img");
+ image.title = profile.entity;
+ image.className = "image";
+ image.src = 'img/default-avatar.png';
+ li.appendChild(image);
+ image.onclick = function(e) {
+ HostApp.showProfileForEntity(e.target.title);
+ return false;
+ }
+
+ var div = document.createElement("div");
+ div.className = "data"
+
+ var h1 = document.createElement("h1");
+ var username = document.createElement("a");
+ username.title = profile.entity;
+ username.className = "name";
+ username.href = profile.entity;
+ username.onclick = function(e) {
+ HostApp.showProfileForEntity(profile.entity);
+ return false;
+ }
+
+ h1.appendChild(username)
+ div.appendChild(h1);
+ li.appendChild(div);
+
+ var p = document.createElement("p");
+ p.className = "message";
+
+ var entity_tag = document.createElement("a");
+ entity_tag.innerText = profile.entity;
+ entity_tag.href = profile.entity;
+ entity_tag.title = profile.entity;
+
+ var new_line = document.createElement("br");
+ var follows_since = document.createTextNode("follows since ");
+ var follows_since_time = document.createElement("span");
+ follows_since_time.innerText = this.ISODateString(new Date(profile.created_at * 1000));
+ follows_since_time.title = follows_since_time.innerText;
+ follows_since_time.className = "timeago";
+ jQuery(follows_since_time).timeago();
+
+ p.appendChild(entity_tag);
+ p.appendChild(new_line);
+ p.appendChild(follows_since);
+ p.appendChild(follows_since_time);
+ div.appendChild(p);
+
+ var profile_callback = function(p) {
+
+ var basic = p["https://tent.io/types/info/basic/v0.1.0"];
+
+ if (p && basic) {
+ if(basic.name) {
+ username.title = username.innerText;
+ username.innerText = basic.name;
+ }
+ if(basic.avatar_url) {
+ image.onerror = function() { image.src = 'img/default-avatar.png'; };
+ image.src = basic.avatar_url;
+ }
+ }
+
+ }
+
+ var p = this.cache.profiles.getItem(profile.entity);
+
+ if (p && p != "null") {
+
+ profile_callback(p);
- Profile.prototype.logout = function() {
- this.container = "";
- }
+ } else {
+
+ var _this = this;
+ APICalls.findProfileURL(profile.entity, function(profile_url) {
- Profile.prototype.showList = function(list) {
- $(this.body).hide();
- $(this.followingsBody).hide();
- $(this.followersBody).hide();
- $(list).show();
- };
-
- Profile.prototype.showProfileForEntity = function(entity) {
+ if (profile_url) {
+ APICalls.http_call(profile_url, "GET", function(resp) {
+ var p = JSON.parse(resp.responseText);
+ if (p && p != "null") {
+ _this.cache.profiles.setItem(profile.entity, p);
+ profile_callback(p);
+ }
+
+ }, null, false); // do not send auth-headers
+ }
+ });
+ }
- if (!entity) {
- entity = HostApp.stringForKey("entity");
- };
-
- this.clear();
- this.entity = entity;
- this.following = null;
- this.following_id = null;
- this.profile_template.entity.innerHTML = this.entity;
- this.profile_template.entity.href = this.entity;
-
- this.getProfile();
- this.getFollowing();
- }
-
- Profile.prototype.initProfileTemplate = function() {
+ return li;
+ }
- var _this = this;
-
- var header = document.createElement("header");
- header.className = "profile";
-
- this.container.appendChild(header);
- this.profile_template = {
- avatar: document.createElement("img"),
- name: document.createElement("h1"),
- entity: document.createElement("a"),
- bio: document.createElement("p"),
- relationships: document.createElement("td"),
- posts: document.createElement("a"),
- following: document.createElement("a"),
- followed: document.createElement("a"),
- birthdate: document.createElement("td"),
- location: document.createElement("td"),
- gender: document.createElement("td"),
- url: document.createElement("a"),
- following_button: document.createElement("button"),
- mention_button: document.createElement("button")
- };
- header.appendChild(this.profile_template.avatar);
- this.profile_template.avatar.src = "img/default-avatar.png";
- var div = document.createElement("div");
- header.appendChild(div);
-
- this.profile_template.following_button.onclick = function(e) {
- _this.toggleFollow()
- }
- div.appendChild(this.profile_template.following_button);
-
- this.profile_template.mention_button.onclick = function() {
- var e = _this.entity;
- if (e.startsWith("https://")) {
- e = e.substr(8, e.length);
- }
- HostApp.openNewMessageWidow(null, null, "^" + e + " ", false);
- }
- div.appendChild(this.profile_template.mention_button);
- this.profile_template.mention_button.innerHTML = "Mention";
-
- div.appendChild(this.profile_template.name);
-
- var p = document.createElement("p");
- p.appendChild(this.profile_template.entity);
- div.appendChild(p);
-
- div.appendChild(this.profile_template.bio);
-
- var table = document.createElement("table");
- div.appendChild(table);
-
- function mkLi(name, template) {
- var tr = document.createElement("tr");
- var th = document.createElement("th");
- tr.style.display = "none";
- th.innerText = name + ": ";
- tr.appendChild(th);
- tr.appendChild(template);
- table.appendChild(tr);
- }
-
- mkLi("Birth date", this.profile_template.birthdate);
- mkLi("Location", this.profile_template.location);
- mkLi("Gender", this.profile_template.gender);
-
- var td = document.createElement("td");
- td.appendChild(this.profile_template.url);
- mkLi("Homepage", td);
-
- mkLi("Relationships", this.profile_template.relationships);
-
- td = document.createElement("td");
- td.appendChild(this.profile_template.posts);
- this.profile_template.posts.href = "#";
- this.profile_template.posts.onclick = function() { _this.showPosts(); return false; };
- mkLi("Posts", td);
-
- td = document.createElement("td");
- td.appendChild(this.profile_template.following);
- this.profile_template.following.href = "#";
- this.profile_template.following.onclick = function() { _this.showFollowings(); return false; };
- mkLi("Following", td);
-
- td = document.createElement("td");
- td.appendChild(this.profile_template.followed);
- this.profile_template.followed.href = "#";
- this.profile_template.followed.onclick = function() { _this.showFollowers(); return false; };
- mkLi("Followed by", td);
-
-
- this.body = document.createElement("ol");
- this.body.className = this.action;
- this.container.appendChild(this.body);
-
- this.followingsBody = document.createElement("ol");
- this.followingsBody.className = this.action + " followings";
- this.container.appendChild(this.followingsBody);
-
- this.followersBody = document.createElement("ol");
- this.followersBody.className = this.action + " folloewds";
- this.container.appendChild(this.followersBody);
-
- }
-
- Profile.prototype.clear = function() {
-
- this.server = null;
- this.before = {id: null, entity: null, loading: false};
-
-
- this.profile_template.avatar.src = "img/default-avatar.png";
-
- this.relationships = {
- following_you: false,
- followed_by_you: false,
- it_is_you: false
- }
-
- this.profile_template.name.innerText = "";
- this.profile_template.entity.innerText = "";
- this.profile_template.bio.innerText = "";
- this.profile_template.relationships.innerText = "";
- this.profile_template.posts.innerText = "";
- this.profile_template.following.innerText = "";
- this.profile_template.followed.innerText = "";
- this.profile_template.birthdate.innerText = "";
- this.profile_template.location.innerText = "";
- this.profile_template.gender.innerText = "";
- this.profile_template.url.innerText = "";
- this.profile_template.url.href = "";
-
- this.profile_template.posts.parentNode.parentNode.style.display = "none";
- this.profile_template.following.parentNode.parentNode.style.display = "none";
- this.profile_template.followed.parentNode.parentNode.style.display = "none";
- this.profile_template.birthdate.parentNode.style.display = "none";
- this.profile_template.location.parentNode.style.display = "none";
- this.profile_template.gender.parentNode.style.display = "none";
- this.profile_template.url.parentNode.parentNode.style.display = "none";
-
- this.profile_template.following_button.style.display = "";
- this.setFollowingButton(false);
-
- this.body.innerHTML = "";
- this.followingsBody.innerHTML = "";
- this.followersBody.innerHTML = "";
-
- this.showList(this.body);
- };
-
- Profile.prototype.getProfile = function() {
-
- var _this = this;
-
- if (HostApp.stringForKey("entity") == this.entity) {
- this.relationships.it_is_you = true;
- this.profile_template.following_button.style.display = "none";
- }
-
- var profile = this.cache.profiles.getItem(this.entity);
-
- if (profile && profile != "null") {
-
- this.showProfile(profile);
- this.profile = profile;
-
- } else {
- Paths.findProfileURL(this.entity, function(profile_url) {
-
- if (profile_url) {
-
- Paths.getURL(profile_url, "GET", function(resp) {
-
- profile = JSON.parse(resp.responseText);
- _this.showProfile(profile);
- _this.profile = profile;
-
- }, null, false); // do not send auth-headers
- }
- });
-
- }
- }
-
- Profile.prototype.getFollowing = function() {
- if(this.entity != HostApp.stringForKey("entity")) {
- var url = Paths.mkApiRootPath("/followings") + "/" + encodeURIComponent(this.entity);
- var _this = this;
- Paths.getURL(url, "GET", function(resp) {
- if (resp.status >= 200 && resp.status < 400) {
- var following = JSON.parse(resp.responseText);
- _this.following_id = following.id
- _this.setFollowingButton(true);
- } else {
- _this.setFollowingButton(false);
- _this.following_id = null;
- }
- })
- } else {
- this.setFollowingButton(false);
- this.following_id = null;
- }
- }
-
- Profile.prototype.showProfile = function(profile) {
-
- var basic = profile["https://tent.io/types/info/basic/v0.1.0"];
-
- if (profile && basic) {
-
- if(basic.avatar_url) {
- this.profile_template.avatar.onerror = function() { this.profile_template.avatar.src = 'img/default-avatar.png' };
- this.profile_template.avatar.src = basic.avatar_url;
- }
-
- this.populate(this.profile_template.name, basic.name);
- this.populate(this.profile_template.birthdate, basic.birthdate);
- this.populate(this.profile_template.location, basic.location);
- this.populate(this.profile_template.gender, basic.gender);
- this.populate(this.profile_template.bio, basic.bio);
-
- if(basic.website_url) {
-
- var url = basic.website_url;
- this.profile_template.url.innerText = url;
- this.profile_template.url.parentNode.parentNode.style.display = "";
-
- if (!url.startsWith("http")) {
- url = "http://" + url;
- }
-
- this.profile_template.url.href = url;
- }
- }
-
- if (profile) {
- this.server = profile["https://tent.io/types/info/core/v0.1.0"]["servers"][0];
- this.getMeta(this.server);
- this.getStatuses(this.server);
- }
- }
-
- Profile.prototype.populate = function(t, v) {
- if (v) {
- t.innerText = v;
- t.parentNode.style.display = "";
- t.parentNode.parentNode.style.display = "";
- }
- }
-
- Profile.prototype.getMeta = function(root_url) {
-
- var _this = this;
- Paths.getURL(URI(root_url + "/followings/count").toString(), "GET", function(resp) {
-
- _this.populate(_this.profile_template.following, resp.responseText);
- }, null, false);
-
- Paths.getURL(URI(root_url + "/followers/count").toString(), "GET", function(resp) {
-
- _this.populate(_this.profile_template.followed, resp.responseText);
- }, null, false);
-
- if (this.entity != HostApp.stringForKey("entity")) {
- Paths.getURL(URI(root_url + "/followers/" + encodeURIComponent(HostApp.stringForKey("entity"))).toString(), "GET", function(resp) {
- if (resp.status == 200) {
- _this.relationships.following_you = true;
- }
- _this.setRelationships();
-
- }, null, false);
-
- Paths.getURL(URI(Paths.mkApiRootPath("/followings/" + encodeURIComponent(this.entity))), "GET", function(resp) {
- if (resp.status == 200) {
- _this.relationships.followed_by_you = true;
- }
- _this.setRelationships();
- });
-
- } else {
- this.setRelationships();
- }
-
- var url = URI(root_url + "/posts/count");
- var post_types = [
- "https://tent.io/types/post/repost/v0.1.0",
- "https://tent.io/types/post/status/v0.1.0",
- "https://tent.io/types/post/photo/v0.1.0"
- ];
- url.addSearch("post_types", post_types.join(","));
-
- Paths.getURL(url.toString(), "GET", function(resp) {
-
- _this.populate(_this.profile_template.posts, resp.responseText);
- }, null, false);
- }
-
- Profile.prototype.setRelationships = function() {
- var relation = "none";
- if (this.relationships.it_is_you) {
- relation = "it's you";
- } else {
- if (this.relationships.following_you && !this.relationships.followed_by_you) {
- relation = "is following you";
- } else if (this.relationships.following_you && this.relationships.followed_by_you) {
- relation = "you both follow each other";
- } else if (!this.relationships.following_you && this.relationships.followed_by_you) {
- relation = "being followed by you";
- }
- }
- this.populate(this.profile_template.relationships, relation);
- }
-
-
- Profile.prototype.getStatuses = function(root_url, add_search, append) {
- var _this = this;
-
- add_search = add_search || {};
-
- var url = URI(root_url + "/posts");
- url.addSearch("limit", this.posts_limit);
-
- var post_types = [
- "https://tent.io/types/post/repost/v0.1.0",
- "https://tent.io/types/post/status/v0.1.0",
- "https://tent.io/types/post/photo/v0.1.0"
- ];
- url.addSearch("post_types", post_types.join(","));
-
- for(var key in add_search) {
- url.addSearch(key, add_search[key]);
- }
-
- Paths.getURL(url.toString(), "GET", function(resp) {
-
- var statuses = JSON.parse(resp.responseText);
-
- _this.newStatus(statuses, append);
-
- }, null, false);
- }
-
-
- Profile.prototype.newStatus = function(statuses, append) {
-
- if(statuses != null && statuses.length > 0) {
-
- this.before.loading = false;
-
- if (append) statuses = statuses.reverse();
-
- for(var i = statuses.length-1, c=0; i>=c; --i) {
-
- var status = statuses[i];
-
- if (status.type == "https://tent.io/types/post/status/v0.1.0" || status.type == "https://tent.io/types/post/photo/v0.1.0") {
-
- var new_node = this.getStatusDOMElement(status);
-
- if(!append && this.body.childNodes.length > 0) {
-
- if(this.body.childNodes.length > this.max_length) {
-
- this.body.removeChild(this.body.lastChild);
- }
-
- this.body.insertBefore(new_node, this.body.firstChild);
-
- } else {
-
- this.body.appendChild(new_node);
- }
-
- } else if (status.type == "https://tent.io/types/post/delete/v0.1.0") {
-
- var li = document.getElementById("post-" + status.content.id + "-" + this.action);
- if (li) {
- this.body.removeChild(li);
- }
- } else if (status.type == "https://tent.io/types/post/repost/v0.1.0") {
-
- this.getRepost(status, this.body.firstChild);
- }
-
- }
- }
- }
-
- Profile.prototype.getMoreStatusPosts = function() {
- if (!this.before.loading) {
- this.before.loading = true;
- var add_search = {
- "before_id": this.body.lastChild.status.id,
- "before_id_entity": this.body.lastChild.status.entity
- }
- this.getStatuses(this.server, add_search, true);
- }
- }
-
- Profile.prototype.mention = function() {
-
- }
-
- Profile.prototype.setFollowingButton = function(following) {
-
- this.following = following;
-
- if (following) {
- this.profile_template.following_button.className = "following";
- this.profile_template.following_button.innerText = "Unfollow";
- } else {
- this.profile_template.following_button.className = "";
- this.profile_template.following_button.innerText = "Follow";
- }
- }
-
- Profile.prototype.toggleFollow = function() {
-
- var _this = this;
-
- if (this.following_id) {
-
- this.setFollowingButton(false);
- var url = Paths.mkApiRootPath("/followings/") + this.following_id;
- Paths.getURL(url, "DELETE", function(resp) {
- if (resp.status >= 200 && resp.status < 300) {
- _this.setFollowingButton(false);
- _this.following_id = null;
- } else {
- _this.setFollowingButton(true);
- }
- });
-
- } else {
-
- this.setFollowingButton(true);
- var url = URI(Paths.mkApiRootPath("/followings"));
- var data = JSON.stringify({"entity": this.entity });
-
- Paths.getURL(url.toString(), "POST", function(resp) {
- if (resp.status >= 200 && resp.status < 300) {
- _this.following_id = JSON.parse(resp.responseText).id
- _this.setFollowingButton(true);
- } else {
- _this.setFollowingButton(false);
- }
- }, data);
- }
- }
-
- Profile.prototype.showPosts = function() {
- this.showList(this.body);
- }
-
- Profile.prototype.showFollowings = function() {
-
- this.showList(this.followingsBody);
- this.followingsBody.innerHTML = "";
-
- var _this = this;
- var callback = function(resp) {
- var followings = JSON.parse(resp.responseText);
- for (var i = 0; i < followings.length; i++) {
- var li = _this.getDOMSmallProfile(followings[i]);
- _this.followingsBody.appendChild(li);
- }
- }
-
- var url = URI(this.server + "/followings");
- url.addSearch("limit", 200);
- Paths.getURL(url.toString(), "GET", callback, null, false);
- }
-
- Profile.prototype.showFollowers = function() {
-
- this.showList(this.followersBody);
- this.followersBody.innerHTML = "";
-
- var _this = this;
- var callback = function(resp) {
- var followers = JSON.parse(resp.responseText);
- for (var i = 0; i < followers.length; i++) {
- var li = _this.getDOMSmallProfile(followers[i]);
- _this.followersBody.appendChild(li);
- }
- }
-
- var url = URI(this.server + "/followers");
- url.addSearch("limit", 200);
- Paths.getURL(url.toString(), "GET", callback, null, false);
- }
-
- Profile.prototype.getDOMSmallProfile = function(profile) {
-
- var li = document.createElement("li");
-
- var image = document.createElement("img");
- image.title = profile.entity;
- image.className = "image";
- image.src = 'img/default-avatar.png';
- li.appendChild(image);
- image.onclick = function(e) {
- HostApp.showProfileForEntity(e.target.title);
- return false;
- }
-
- var div = document.createElement("div");
- div.className = "data"
-
- var h1 = document.createElement("h1");
- var username = document.createElement("a");
- username.title = profile.entity;
- username.className = "name";
- username.href = profile.entity;
- username.onclick = function(e) {
- HostApp.showProfileForEntity(profile.entity);
- return false;
- }
-
- h1.appendChild(username)
- div.appendChild(h1);
- li.appendChild(div);
-
- var p = document.createElement("p");
- p.className = "message";
-
- var entity_tag = document.createElement("a");
- entity_tag.innerText = profile.entity;
- entity_tag.href = profile.entity;
- entity_tag.title = profile.entity;
-
- var new_line = document.createElement("br");
- var follows_since = document.createTextNode("follows since ");
- var follows_since_time = document.createElement("span");
- follows_since_time.innerText = this.ISODateString(new Date(profile.created_at * 1000));
- follows_since_time.title = follows_since_time.innerText;
- follows_since_time.className = "timeago";
- jQuery(follows_since_time).timeago();
-
- p.appendChild(entity_tag);
- p.appendChild(new_line);
- p.appendChild(follows_since);
- p.appendChild(follows_since_time);
- div.appendChild(p);
-
- var profile_callback = function(p) {
-
- var basic = p["https://tent.io/types/info/basic/v0.1.0"];
-
- if (p && basic) {
- if(basic.name) {
- username.title = username.innerText;
- username.innerText = basic.name;
- }
- if(basic.avatar_url) {
- image.onerror = function() { image.src = 'img/default-avatar.png'; };
- image.src = basic.avatar_url;
- }
- }
-
- }
-
- var p = this.cache.profiles.getItem(profile.entity);
-
- if (p && p != "null") {
-
- profile_callback(p);
-
- } else {
-
- var _this = this;
- Paths.findProfileURL(profile.entity, function(profile_url) {
-
- if (profile_url) {
- Paths.getURL(profile_url, "GET", function(resp) {
- var p = JSON.parse(resp.responseText);
- if (p && p != "null") {
- _this.cache.profiles.setItem(profile.entity, p);
- profile_callback(p);
- }
-
- }, null, false); // do not send auth-headers
- }
- });
- }
-
- return li;
- }
-
-
- return Profile;
+ return Profile;
});
diff --git a/WebKit/scripts/controller/Search.js b/WebKit/scripts/controller/Search.js
index 51ce153..b083362 100644
--- a/WebKit/scripts/controller/Search.js
+++ b/WebKit/scripts/controller/Search.js
@@ -1,11 +1,11 @@
define([
"helper/HostApp",
"helper/Core",
- "helper/Paths",
+ "helper/APICalls",
"lib/URI"
],
-function(HostApp, Core, Paths, URI) {
+function(HostApp, Core, APICalls, URI) {
function Search() {
@@ -79,7 +79,7 @@ function(HostApp, Core, Paths, URI) {
var _this = this;
- Paths.getURL(url.toString(), "GET", function(resp) {
+ APICalls.http_call(url.toString(), "GET", function(resp) {
var results = JSON.parse(resp.responseText).results;
if (results && results.length > 0) {
diff --git a/WebKit/scripts/controller/Sidebar.js b/WebKit/scripts/controller/Sidebar.js
index 5b453b8..845946c 100644
--- a/WebKit/scripts/controller/Sidebar.js
+++ b/WebKit/scripts/controller/Sidebar.js
@@ -1,16 +1,13 @@
define([
"helper/HostApp",
- "helper/Paths",
- "helper/Cache"
+ "helper/APICalls",
],
-function(HostApp, Paths, Cache) {
+function(HostApp, APICalls) {
function Sidebar() {
- this.cache = new Cache();
-
this.body = document.createElement("ul");
this.body.class = "sidebar";
@@ -84,57 +81,39 @@ function(HostApp, Paths, Cache) {
var entity = HostApp.stringForKey("entity");
this.menu.user.title = entity;
- var img = this.menu.user.getElementsByTagName("img")[0];
-
+ var avatar = this.menu.user.getElementsByTagName("img")[0];
var _this = this;
- var profile_callback = function(p) {
+ var url = HostApp.serverUrl("posts_feed") + "?types=" + encodeURIComponent("https://tent.io/types/meta/v0") + "&entities=" + encodeURIComponent(entity);
+ APICalls.get(url, { callback: function(resp) {
+ var profiles = JSON.parse(resp.responseText);
- var basic = p["https://tent.io/types/info/basic/v0.1.0"];
+ if(profiles.posts.length < 1) return;
+ var profile = profiles.posts[0];
+ bungloo.cache.profiles[entity] = profile;
- if (p && basic) {
- if(basic.name) {
- _this.menu.user.title = basic.name;
- }
- if(basic.avatar_url) {
+ // Find and apply avatar
+ if(profile.attachments) {
- img.onerror = function() {
- img.src = "img/sidebar/user.png";
- img.src_inactive = img.src;
- img.src_active = img.src;
+ var digest = null;
+ for (var i = 0; i < profile.attachments.length; i++) {
+ var attachment = profile.attachments[i];
+ if(attachment.category == "avatar") {
+ digest = attachment.digest;
+ break;
}
+ }
- img.src = basic.avatar_url;
- img.src_inactive = basic.avatar_url;
- img.src_active = basic.avatar_url;
-
+ if(digest) {
+ var _this = this;
+ avatar.onerror = function() { avatar.src = 'img/default-avatar.png' };
+ var avatar_url = profile.content.servers[0].urls.attachment.replace(/\{entity\}/, encodeURIComponent(profile.entity));
+ avatar.src = avatar_url.replace(/\{digest\}/, digest);
+ avatar.src_inactive = avatar.src;
+ avatar.src_active = avatar.src;
}
}
-
- }
-
- var p = this.cache.profiles.getItem(entity);
-
- if (p && p != "null") {
-
- profile_callback(p);
-
- } else {
-
- Paths.findProfileURL(entity, function(profile_url) {
-
- if (profile_url) {
- Paths.getURL(profile_url, "GET", function(resp) {
- var p = JSON.parse(resp.responseText);
- if (p && p != "null") {
- _this.cache.profiles.setItem(entity, p);
- profile_callback(p);
- }
-
- }, null, false); // do not send auth-headers
- }
- });
- }
+ }});
}
Sidebar.prototype.removeEntityAvatar = function() {
diff --git a/WebKit/scripts/controller/Timeline.js b/WebKit/scripts/controller/Timeline.js
index fbd1383..c7d9331 100644
--- a/WebKit/scripts/controller/Timeline.js
+++ b/WebKit/scripts/controller/Timeline.js
@@ -1,11 +1,11 @@
define([
"helper/Core",
- "helper/Paths",
+ "helper/APICalls",
"helper/HostApp",
"lib/URI"
],
-function(Core, Paths, HostApp, URI) {
+function(Core, APICalls, HostApp, URI) {
function Timeline() {
@@ -21,6 +21,8 @@ function(Core, Paths, HostApp, URI) {
this.since_id_entity = null;
this.since_time = 0;
+ this.pages = {};
+
this.before = {id: null, entity: null, loading: false};
this.container = document.createElement("div");
@@ -46,8 +48,19 @@ function(Core, Paths, HostApp, URI) {
}
- Timeline.prototype.newStatus = function(statuses, append) {
+ Timeline.prototype.newStatus = function(_statuses, append) {
+ for (var entity in _statuses.profiles) {
+ if (_statuses.profiles[entity] != null) {
+ bungloo.cache.profiles[entity] = _statuses.profiles[entity];
+ } else {
+ bungloo.cache.profiles[entity] = {};
+ }
+ }
+
+ this.pages = _statuses.pages;
+
+ statuses = _statuses.posts;
if(statuses != null && statuses.length > 0) {
this.before.loading = false;
@@ -62,7 +75,7 @@ function(Core, Paths, HostApp, URI) {
this.since_id_entity = status.entity;
}
- if (status.type == "https://tent.io/types/post/status/v0.1.0" || status.type == "https://tent.io/types/post/photo/v0.1.0") {
+ if (status.type == "https://tent.io/types/status/v0#") {
var new_node = this.getStatusDOMElement(status);
@@ -95,68 +108,69 @@ function(Core, Paths, HostApp, URI) {
}
}
- Timeline.prototype.getNewData = function(add_to_search, append) {
+ Timeline.prototype.getNewData = function(add_to_search, append, query) {
add_to_search = add_to_search || {};
var those = this;
- var url = URI(Paths.mkApiRootPath("/posts"));
+ var url = HostApp.serverUrl("posts_feed");
- var post_types = [
- "https://tent.io/types/post/repost/v0.1.0",
- "https://tent.io/types/post/status/v0.1.0",
- "https://tent.io/types/post/delete/v0.1.0",
- "https://tent.io/types/post/photo/v0.1.0"
- ];
- url.addSearch("post_types", post_types.join(","));
- //url.addSearch("sort_by", "published_at");
- url.addSearch("limit", this.posts_limit);
+ if(!query) {
- if(this.since_id && !append) {
- url.addSearch("since_id", this.since_id);
- url.addSearch("since_id_entity", this.since_id_entity);
- }
+ var uri = URI(url);
- for (key in add_to_search) {
- url.addSearch(key, add_to_search[key]);
- }
+ var post_types = [
+ "https://tent.io/types/status/v0#",
+ "https://tent.io/types/status/v0#reply",
+ "https://tent.io/types/repost/v0#",
+ "https://tent.io/types/delete/v0#",
+ //"https://tent.io/types/post/photo/v0.1.0"
+ ];
+ uri.addSearch("types", post_types.join(","));
+ //uri.addSearch("sort_by", "published_at");
+ uri.addSearch("limit", this.posts_limit);
+ uri.addSearch("max_refs", 20);
+ uri.addSearch("profiles", "entity");
- var http_method = "GET";
- var callback = function(resp) {
-
- those.reload_blocked = false;
-
- try {
-
- var json = JSON.parse(resp.responseText);
- those.newStatus(json, append);
-
- } catch (e) {
- console.error(url + " JSON parse error");
- throw e;
+ for (key in add_to_search) {
+ uri.addSearch(key, add_to_search[key]);
}
- }
- var data = null;
+ url = uri.toString();
+
+ } else {
+ url += query;
+ }
if (HostApp.stringForKey("user_access_token")) {
if (!this.reload_blocked) {
this.reload_blocked = true;
- Paths.getURL(url.toString(), http_method, callback, data); // FIXME: error callback
+
+ APICalls.get(url, { callback: function(resp) {
+ // FIXME this is getting data when it shouldn't debug(resp.responseText)
+
+ those.reload_blocked = false;
+
+ try {
+ var json = JSON.parse(resp.responseText);
+ those.newStatus(json, append);
+
+ } catch (e) {
+ console.error(url + " JSON parse error");
+ throw e;
+ }
+ } });
}
}
}
Timeline.prototype.getMoreStatusPosts = function() {
if (!this.before.loading) {
- this.before.loading = true;
- var add_search = {
- "before_id": this.body.lastChild.status.id,
- "before_id_entity": this.body.lastChild.status.entity
+ if (this.pages.next) {
+ this.before.loading = true;
+ this.getNewData({}, true, this.pages.next);
}
-
- this.getNewData(add_search, true);
}
}
diff --git a/WebKit/scripts/helper/APICalls.js b/WebKit/scripts/helper/APICalls.js
new file mode 100644
index 0000000..7d97790
--- /dev/null
+++ b/WebKit/scripts/helper/APICalls.js
@@ -0,0 +1,319 @@
+define([
+ "jquery",
+ "helper/HostApp",
+ "helper/Hmac",
+ "helper/Cache"
+],
+
+function(jQuery, HostApp, Hmac, Cache) {
+ var APICalls = {};
+
+ APICalls.cache = new Cache();
+
+ APICalls.getUrlVars = function(url) {
+ var vars = [], hash;
+ if(url.indexOf("#") > -1) url = url.slice(0, url.indexOf("#"));
+ var hashes = url.slice(url.indexOf('?') + 1).split('&');
+ for(var i = 0; i < hashes.length; i++)
+ {
+ hash = hashes[i].split('=');
+ vars.push(hash[0]);
+ vars[hash[0]] = hash[1];
+ }
+ return vars;
+ }
+
+ APICalls.http_call = function(options) {
+
+ if (typeof options === "string") {
+ console.error(options + " not implemented yet")
+ return;
+ }
+
+ var content_type = null;
+
+ if((options.http_method == "POST" || options.http_method == "PUT") && !options.content_type) {
+ console.error("No content type for " + options.url);
+ return;
+ } else if(options.content_type != "AAA") {
+ if(options.content_type == "application/json") {
+ content_type = "application/json";
+ } else if(options.content_type) {
+ content_type = "application/vnd.tent.post.v0+json; charset=UTF-8; type=\"" + options.content_type + "\"";
+ }
+ } else {
+ content_type = 'application/vnd.tent.post.v0+json; charset=UTF-8; type="https://tent.io/types/status/v0#"';
+ }
+
+ var settings = {
+ beforeSend: function(xhr) {
+ if (options.data) xhr.setRequestHeader("Content-Length", options.data.length);
+
+ if (options.accept) xhr.setRequestHeader("Accept", options.accept);
+ else xhr.setRequestHeader("Accept", "application/vnd.tent.post.v0+json");
+
+ var user_access_token = HostApp.stringForKey("user_access_token");
+ if (!options.auth_header && !options.no_auth && user_access_token) {
+ var auth_header = Hmac.makeHawkAuthHeader(
+ options.url,
+ options.http_method,
+ user_access_token,
+ HostApp.secret()//,
+ //HostApp.stringForKey("app_id")
+ );
+ xhr.setRequestHeader("Authorization", auth_header);
+ } else if(options.auth_header) {
+ xhr.setRequestHeader("Authorization", options.auth_header);
+ } else if(!options.no_auth) {
+ console.error("No user_access_token yet - " + options.url);
+ }
+ xhr.setRequestHeader("Cache-Control", "no-proxy");
+ },
+ url: options.url,
+ contentType: content_type,
+ type: options.http_method,
+ complete: options.callback,
+ data: options.data,
+ processData: false,
+ error: function(xhr, ajaxOptions, thrownError) {
+ console.error("HTTP CALL (" + xhr.status + ") " + xhr.statusText + " " + options.http_method + " URL(" + options.url + "): '" + xhr.responseText + "'");
+ }
+ };
+
+ jQuery.ajax(settings);
+ }
+
+ APICalls.head = function(url, options) {
+ var settings = {
+ url: url,
+ http_method: "HEAD",
+ };
+
+ for (var key in options) {
+ settings[key] = options[key];
+ }
+
+ APICalls.http_call(settings);
+ }
+
+ APICalls.get = function(url, options) {
+ var settings = {
+ url: url,
+ http_method: "GET",
+ };
+
+ for (var key in options) {
+ settings[key] = options[key];
+ }
+
+ APICalls.http_call(settings);
+ }
+
+ APICalls.post = function(url, data, options) {
+ var settings = {
+ url: url,
+ http_method: "POST",
+ data: data
+ };
+
+ for (var key in options) {
+ settings[key] = options[key];
+ }
+
+ APICalls.http_call(settings);
+ }
+
+ APICalls.delete = function(url, options) {
+ var settings = {
+ url: url,
+ http_method: "DELETE"
+ };
+
+ for (var key in options) {
+ settings[key] = options[key];
+ }
+
+ APICalls.http_call(settings);
+ }
+
+ APICalls.put = function(url, data, options) {
+ var settings = {
+ url: url,
+ http_method: "PUT",
+ data: data
+ };
+
+ for (var key in options) {
+ settings[key] = options[key];
+ }
+
+ APICalls.http_call(settings);
+ }
+
+
+ APICalls.postMultipart = function(url, callback, data, boundary, accepts) {
+
+ accepts = accepts || "application/vnd.tent.v0+json";
+
+ jQuery.ajax({
+
+ beforeSend: function(xhr) {
+ xhr.setRequestHeader("Accept", accepts);
+
+ if (data) xhr.setRequestHeader("Content-Length", data.length);
+
+ var user_access_token = HostApp.stringForKey("user_access_token");
+
+ if (user_access_token) {
+
+ auth_header = Hmac.makeAuthHeader(
+ url,
+ "POST",
+ HostApp.secret(),
+ user_access_token
+ );
+
+ xhr.setRequestHeader("Authorization", auth_header);
+ }
+ },
+ url: url,
+ contentType: "multipart/form-data;boundary=" + boundary,
+ type: "POST",
+ complete: callback,
+ data: data,
+ processData: false,
+ error: function(xhr, ajaxOptions, thrownError) {
+ console.error("postMultipart (" + xhr.status + ")" + xhr.statusText + " (" + url + "): '" + xhr.responseText + "'");
+ }
+ });
+ }
+
+ APICalls.findProfileURL = function(entity, callback, errorCallback) {
+ var profile_url = APICalls.cache.profile_urls.getItem(entity);
+
+ if (profile_url && profile_url != "null") {
+
+ callback(profile_url);
+
+ } else {
+
+ jQuery.ajax({
+ url: entity,
+ type: "HEAD",
+ complete: function(resp) {
+ if(resp) {
+ var headers = resp.getAllResponseHeaders();
+
+ var profile_urls = APICalls.parseHeaderForProfiles(headers);
+ var profile_url = null;
+ if(profile_urls.length > 0) {
+ var profile_url = profile_urls[0];
+ if (!profile_url.startsWith("http")) {
+ profile_url = entity + profile_url;
+ }
+ }
+
+ if (profile_url) {
+ APICalls.cache.profile_urls.setItem(entity, profile_url);
+ callback(profile_url);
+ } else {
+ APICalls.http_call(entity, "GET", function(resp) {
+
+ if (resp.status >= 200 && resp.status < 300) {
+ var doc = document.implementation.createHTMLDocument("");
+ doc.documentElement.innerHTML = resp.responseText;
+ var links = $(doc).find("link[rel='https://tent.io/rels/meta-post']");
+
+ if (links.length > 0) {
+ var href = links.get(0).href;
+ APICalls.cache.profile_urls.setItem(entity, href);
+ if (!href.startsWith("http")) {
+ href = entity + href;
+ }
+ callback(href);
+
+ } else {
+ if(errorCallback) errorCallback(entity + " has no profile URL");
+ }
+ } else {
+ if(errorCallback) errorCallback(entity + " has no profile URL");
+ }
+
+ }, null, false, false);
+
+ //if(errorCallback) errorCallback(entity + " has no profile URL");
+ }
+ }
+ },
+ error: function(xhr, ajaxOptions, thrownError) {
+ console.error("findProfileURL " + xhr.statusText + " (" + entity + "): " + xhr.responseText);
+ if (errorCallback) errorCallback(xhr.statusText + " - " + xhr.responseText)
+ }
+ });
+ }
+ }
+
+ APICalls.mkApiRootPath = function(path) {
+
+ var api_root = HostApp.stringForKey("api_root");
+
+ if((api_root.substring(api_root.length - 1, api_root.length) != "/") && (path.substring(0, 1) != "/")) {
+ api_root += "/";
+ } else if((api_root.substring(api_root.length - 1, api_root.length) == "/") && (path.substring(0, 1) == "/")) {
+ api_root = api_root.substring(0, api_root.length -1);
+ }
+ return api_root + path;
+ }
+
+ APICalls.parseHeaderForProfiles = function(header_string) {
+ var regexp = /https:\/\/tent.io\/rels\/meta-post/i;
+ return APICalls.parseHeaderForLink(header_string, regexp);
+ }
+
+ APICalls.parseHeader = function(header_string) {
+ var header_strings = header_string.split(/\n/);
+ var headers = {};
+ for (var i = 0; i < header_strings.length; i++) {
+ var hs = header_strings[i].split(/:(.+)?/);
+ headers[hs[0]] = hs[1];
+ }
+ return headers;
+ }
+
+ APICalls.getCount = function(resp) {
+ var count = 0;
+ var headers = APICalls.parseHeader(resp.getAllResponseHeaders());
+ if(headers["Count"]) count = parseInt(headers["Count"], 10);
+ return count;
+ }
+
+ APICalls.parseHeaderForLink = function(header_string, match) {
+ var headers = header_string.split(/\n/);
+ var links = [];
+ for (var i = 0; i < headers.length; i++) {
+ var header = headers[i];
+ if (header.match(/^Link:(.*)/i)) {
+ links.push(header.replace(/\r/, "").substr(5).trim());
+ }
+ }
+
+ var items = [];
+ for (var i = 0; i < links.length; i++) {
+ items = items.concat(links[i].split(","));
+ }
+ var things = [];
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ if (item.match(match)) {
+ var n = item.match(/<([^>]*)>/);
+ if (n) {
+ things.push(n[1]);
+ }
+ }
+ }
+
+ return things;
+ }
+
+ return APICalls;
+});
\ No newline at end of file
diff --git a/WebKit/scripts/helper/Cache.js b/WebKit/scripts/helper/Cache.js
index eb79fe7..2b35364 100644
--- a/WebKit/scripts/helper/Cache.js
+++ b/WebKit/scripts/helper/Cache.js
@@ -40,12 +40,12 @@ function(URI, CacheStorage, require) {
}
}
- var url = URI(require("helper/Paths").mkApiRootPath("/followings"));
+ var url = URI(require("helper/APICalls").mkApiRootPath("/followings"));
if (this.followings_before_id) {
url.addSearch("before_id", this.followings_before_id);
}
- require("helper/Paths").getURL(url, "GET", callback);
+ require("helper/APICalls").getURL(url, "GET", callback);
}
Cache.prototype.periodicallyGetFollowings = function() {
diff --git a/WebKit/scripts/helper/Core.js b/WebKit/scripts/helper/Core.js
index 7f3b350..4b8983e 100644
--- a/WebKit/scripts/helper/Core.js
+++ b/WebKit/scripts/helper/Core.js
@@ -1,17 +1,15 @@
define([
"jquery",
- "helper/Paths",
+ "helper/APICalls",
"lib/URI",
"helper/HostApp",
- "helper/Cache",
"lib/Timeago",
"lib/SingleDoubleClick"
],
-function(jQuery, Paths, URI, HostApp, Cache) {
+function(jQuery, APICalls, URI, HostApp) {
function Core() {
- this.cache = new Cache();
this.saveScrollTop = 0;
}
@@ -69,6 +67,7 @@ function(jQuery, Paths, URI, HostApp, Cache) {
image.className = "image";
image.src = "img/default-avatar.png";
image.onmousedown = function(e) { e.preventDefault(); };
+ image.onerror = function() { this.src = 'img/default-avatar.png' };
item.appendChild(image);
var image_username = a.cloneNode();
@@ -162,7 +161,28 @@ function(jQuery, Paths, URI, HostApp, Cache) {
}
Core.prototype.getStatusDOMElement = function(status) {
-
+ /*
+{
+ "app": {
+ "id": "P8FJjaiRv0AKXfjUMd_4YQ",
+ "name": "Bungloo on Linux",
+ "url": "http:\/\/jabs.nu\/bungloo\/"
+ },
+ "content": {
+ "text": "jeena test"
+ },
+ "entity": "http:\/\/155969d81672.alpha.attic.is",
+ "id": "HlSXe8MREzU4h2fGLGSnCA",
+ "published_at": 1369566009,
+ "received_at": 1369566008799,
+ "type": "https:\/\/tent.io\/types\/status\/v0#",
+ "version": {
+ "id": "a2f702b4615c7d7dd0f98c73d7b55749880bf6e437a77349454ff10745d134c6",
+ "published_at": 1369566009,
+ "received_at": 1369566008799
+ }
+}
+ */
var _this = this;
var template = this.getTemplate();
@@ -191,7 +211,8 @@ function(jQuery, Paths, URI, HostApp, Cache) {
template.reply_to.onclick = function() {
var mentions = [];
- var status_mentions = status.mentions.slice(0);
+ var status_mentions = [];
+ if(status.mentions) status_mentions = status.mentions.slice(0);
if (typeof status.__repost != "undefined") {
status_mentions.push({entity:status.__repost.entity});
@@ -202,7 +223,7 @@ function(jQuery, Paths, URI, HostApp, Cache) {
mentions.push(mention);
}
- _this.replyTo(status.entity, status.id, mentions, (status && status.permissions && !status.permissions.public));
+ _this.replyTo(status);
return false;
}
@@ -212,7 +233,8 @@ function(jQuery, Paths, URI, HostApp, Cache) {
return false;
}
- template.username.innerText = status.entity;
+ if(bungloo.cache.profiles[status.entity].name) template.username.innerText = bungloo.cache.profiles[status.entity].name;
+ else template.username.innerText = status.entity;
template.username.href = status.entity;
template.username.title = status.entity;
template.username.onclick = function() {
@@ -220,47 +242,12 @@ function(jQuery, Paths, URI, HostApp, Cache) {
return false;
}
+ if(bungloo.cache.profiles[status.entity].avatar_digest) {
+ template.image.src = HostApp.serverUrl("attachment").replace(/\{entity\}/, encodeURIComponent(status.entity)).replace(/\{digest\}/, bungloo.cache.profiles[status.entity].avatar_digest);
+ }
+
template.image.onclick = template.username.onclick;
- var profile_callback = function(p) {
-
- var basic = p["https://tent.io/types/info/basic/v0.1.0"];
-
- if (p && basic) {
- if(basic.name) {
- template.username.title = template.username.innerText;
- template.username.innerText = basic.name;
- }
- if(basic.avatar_url) {
- template.image.onerror = function() { template.image.src = 'img/default-avatar.png' };
- template.image.src = basic.avatar_url;
- }
- }
-
- }
-
- var p = this.cache.profiles.getItem(status.entity);
-
- if (p && p != "null") {
-
- profile_callback(p);
-
- } else {
-
- Paths.findProfileURL(status.entity, function(profile_url) {
-
- if (profile_url) {
- Paths.getURL(profile_url, "GET", function(resp) {
- var p = JSON.parse(resp.responseText);
- if (p && p != "null") {
- _this.cache.profiles.setItem(status.entity, p);
- profile_callback(p);
- }
-
- }, null, false); // do not send auth-headers
- }
- });
- }
if (status && status.permissions && !status.permissions.public) {
template.is_private.style.display = '';
@@ -290,6 +277,7 @@ function(jQuery, Paths, URI, HostApp, Cache) {
template.message.innerHTML = this.replaceURLWithHTMLLinks(text, entities, template.message);
this.afterChangingTextinMessageHTML(template.message)
+ /*
if (status.type == "https://tent.io/types/post/photo/v0.1.0") {
for (var i = 0; i < status.attachments.length; i++) {
@@ -308,18 +296,19 @@ function(jQuery, Paths, URI, HostApp, Cache) {
}
if (status.entity == HostApp.stringForKey("entity")) {
- var url = Paths.mkApiRootPath("/posts/" + status.id + "/attachments/" + attachment.name);
- Paths.getURL(url, "GET", callback, null, null, attachment.type);
+ var url = APICalls.mkApiRootPath("/posts/" + status.id + "/attachments/" + attachment.name);
+ APICalls.http_call(url, "GET", callback, null, null, attachment.type);
} else {
- var url = Paths.mkApiRootPath("/posts/" + encodeURIComponent(status.entity) + "/" + status.id + "/attachments/" + attachment.name);
- Paths.getURL(url, "GET", callback, null, null, attachment.type);
+ var url = APICalls.mkApiRootPath("/posts/" + encodeURIComponent(status.entity) + "/" + status.id + "/attachments/" + attachment.name);
+ APICalls.http_call(url, "GET", callback, null, null, attachment.type);
}
})();
}
}
-
+ */
this.findMentions(template.message, status.mentions);
+/*
for (var i = 0; i < status.mentions.length; i++) {
var mention = status.mentions[i];
if (mention.entity == HostApp.stringForKey("entity")) {
@@ -327,10 +316,10 @@ function(jQuery, Paths, URI, HostApp, Cache) {
break;
}
}
-
- var published_at = typeof status.__repost == "undefined" ? status.published_at : status.__repost.published_at;
+*/
+ var published_at = typeof status.__repost == "undefined" ? status.version.published_at : status.__repost.published_at;
var time = document.createElement("abbr");
- time.innerText = this.ISODateString(new Date(published_at * 1000));
+ time.innerText = this.ISODateString(new Date(published_at));
time.title = time.innerText;
time.className = "timeago";
jQuery(time).timeago();
@@ -366,9 +355,11 @@ function(jQuery, Paths, URI, HostApp, Cache) {
template.source.innerHTML = status.__repost.app.name;
template.source.title = status.__repost.app.url;
} else {
- template.source.href = status.app.url;
- template.source.innerHTML = status.app.name;
- template.source.title = status.app.url;
+ if(status.app) {
+ template.source.href = status.app.url;
+ template.source.innerHTML = status.app.name;
+ template.source.title = status.app.url;
+ }
}
return template.item;
@@ -431,9 +422,9 @@ function(jQuery, Paths, URI, HostApp, Cache) {
});
var _this = this;
- Paths.findProfileURL(repost.entity, function(profile_url) {
+ APICalls.findProfileURL(repost.entity, function(profile_url) {
if (profile_url) {
- Paths.getURL(profile_url, "GET", function(resp) {
+ APICalls.http_call(profile_url, "GET", function(resp) {
if (resp.status >= 200 && resp.status < 400) {
var _p = JSON.parse(resp.responseText);
_this.cache.profiles.setItem(repost.entity, _p);
@@ -460,14 +451,14 @@ function(jQuery, Paths, URI, HostApp, Cache) {
}
}
- Paths.findProfileURL(repost.content.entity, function(profile_url) {
+ APICalls.findProfileURL(repost.content.entity, function(profile_url) {
if (profile_url) {
- Paths.getURL(profile_url, "GET", function(resp) {
+ APICalls.http_call(profile_url, "GET", function(resp) {
var profile = JSON.parse(resp.responseText);
var server = profile["https://tent.io/types/info/core/v0.1.0"].servers[0];
- Paths.getURL(URI(server + "/posts/" + repost.content.id).toString(), "GET", callback, null, false);
+ APICalls.http_call(URI(server + "/posts/" + repost.content.id).toString(), "GET", callback, null, false);
}, null, false); // do not send auth-headers
}
@@ -475,55 +466,8 @@ function(jQuery, Paths, URI, HostApp, Cache) {
}
}
- Core.prototype.sendNewMessage = function(content, in_reply_to_status_id, in_reply_to_entity, location, image_data_uri, is_private, callback) {
-
- if (image_data_uri) {
-
- this.sendNewMessageWithImage(content, in_reply_to_status_id, in_reply_to_entity, location, image_data_uri, is_private, callback);
-
- } else {
-
- var url = URI(Paths.mkApiRootPath("/posts"));
-
- var http_method = "POST";
-
- var data = {
- "type": "https://tent.io/types/post/status/v0.1.0",
- "published_at": parseInt(new Date().getTime() / 1000, 10),
- "permissions": {
- "public": !is_private
- },
- "content": {
- "text": content,
- },
- };
-
- if (location) {
- data["content"]["location"] = { "type": "Point", "coordinates": location }
- }
-
- var mentions = this.parseMentions(content, in_reply_to_status_id, in_reply_to_entity);
-
- if (mentions.length > 0) {
- data["mentions"] = mentions;
- if (is_private) {
- var entities = {};
- for (var i = 0; i < mentions.length; i++) {
- var entity = mentions[i]["entity"]
- entities[entity] = true;
- };
-
- data["permissions"]["entities"] = entities;
- }
- }
-
- Paths.getURL(url.toString(), http_method, callback, JSON.stringify(data));
- }
- }
-
-
Core.prototype.repost = function(id, entity, callback) {
- var url = URI(Paths.mkApiRootPath("/posts"));
+ var url = URI(APICalls.mkApiRootPath("/posts"));
var data = {
"type": "https://tent.io/types/post/repost/v0.1.0",
@@ -549,88 +493,14 @@ function(jQuery, Paths, URI, HostApp, Cache) {
_this.highlight(id);
}
- Paths.getURL(url.toString(), "POST", new_callback, JSON.stringify(data));
- }
-
- Core.prototype.sendNewMessageWithImage = function(content, in_reply_to_status_id, in_reply_to_entity, location, image_data_uri, is_private, callback) {
-
- var url = URI(Paths.mkApiRootPath("/posts"));
-
- var data = {
- "type": "https://tent.io/types/post/photo/v0.1.0",
- "published_at": parseInt(new Date().getTime() / 1000, 10),
- "permissions": {
- "public": !is_private
- },
- "content": {
- "caption": content,
- },
- };
-
- if (location) {
- data["content"]["location"] = { "type": "Point", "coordinates": location }
- }
-
- var mentions = this.parseMentions(content, in_reply_to_status_id, in_reply_to_entity);
- if (mentions.length > 0) {
- data["mentions"] = mentions;
- if (is_private) {
- var entities = {};
- for (var i = 0; i < mentions.length; i++) {
- var entity = mentions[i]["entity"]
- entities[entity] = true;
- };
-
- data["permissions"]["entities"] = entities;
- }
- }
-
- var data_string = JSON.stringify(data);
-
- var boundary = "TentAttachment----------TentAttachment";
- var post = "--" + boundary + "\r\n";
-
- post += 'Content-Disposition: form-data; name="post"; filename="post.json"\r\n';
- post += 'Content-Length: ' + data_string.length + '\r\n';
- post += 'Content-Type: application/vnd.tent.v0+json\r\n';
- post += 'Content-Transfer-Encoding: binary\r\n\r\n';
- post += data_string;
-
- post += "\r\n--" + boundary + "\r\n";
-
- var blob_string = image_data_uri.split(',')[1];
- var mime_type = image_data_uri.split(',')[0].split(':')[1].split(';')[0];
- var ext = "png";
- if (mime_type == "image/jpeg") {
- ext = "jpeg";
- } else if (mime_type == "image/gif") {
- ext = "gif";
- }
-
-
- post += 'Content-Disposition: form-data; name="photos[0]"; filename="photo.' + ext + '"\r\n';
- post += 'Content-Length: ' + blob_string.length + "\r\n";
- post += 'Content-Type: ' + mime_type + "\r\n";
- post += 'Content-Transfer-Encoding: base64\r\n\r\n';
- post += blob_string;
- post += "\r\n--" + boundary + "--\r\n";
-
- var newCallback = function(resp) {
- if (resp.status == 403) {
- var err = JSON.parse(resp.responseText);
- HostApp.alertTitleWithMessage(resp.statusText, err.error);
- }
- callback(resp);
- }
-
- Paths.postMultipart(url.toString(), newCallback, post, boundary);
+ APICalls.http_call(url.toString(), "POST", new_callback, JSON.stringify(data));
}
Core.prototype.remove = function(id, callback, type) {
type = type || "post";
if (confirm("Really delete this " + type + "?")) {
- var url = URI(Paths.mkApiRootPath("/posts/" + id));
- Paths.getURL(url.toString(), "DELETE", callback);
+ var url = URI(APICalls.mkApiRootPath("/posts/" + id));
+ APICalls.http_call(url.toString(), "DELETE", callback);
}
}
@@ -738,9 +608,9 @@ function(jQuery, Paths, URI, HostApp, Cache) {
} else {
- Paths.findProfileURL(mention.entity, function(profile_url) {
+ APICalls.findProfileURL(mention.entity, function(profile_url) {
if (profile_url) {
- Paths.getURL(profile_url, "GET", function(resp) {
+ APICalls.http_call(profile_url, "GET", function(resp) {
if (resp.status >= 200 && resp.status < 400) {
var p = JSON.parse(resp.responseText);
_this.cache.profiles.setItem(mention.entity, p);
@@ -796,27 +666,14 @@ function(jQuery, Paths, URI, HostApp, Cache) {
}
Core.prototype.replaceURLWithHTMLLinks = function(text, entities, message_node) {
-
- var callback = function(url) {
-
- var result;
-
- if (entities && entities.some(function(x) { return x == url })) {
- result = url;
- } else {
-
- result = url;
- if (url.startsWith("http://") || url.startsWith("https://")) {
- result = '' + url + '';
- }
- }
-
- return result;
- }
-
- var hash = /(^|\s)(#)(\w+)/ig;
-
- return URI.withinString(text, callback).replace(hash, "$1$2$3");
+ // FIXME: this has to be done better so one can nest that stuff and escape with \
+ return text.replace(/_([^_]+)_/g, "$1")
+ .replace(/\*([^\*]+)\*/g, "$1")
+ .replace(/`([^`]+)`/g, "$1
")
+ .replace(/~([^~]+)~/g, "$1")
+ .replace(/\#([^\s]+)/g, "#$1")
+ .replace(/(^|[^\^])\[([^\]]+)\]\(([^\)]+)\)/g, "$2")
+ .replace(/\^\[([^\]]+)\]\((\d+)\)/g, "$1");
}
Core.prototype.parseForMedia = function(text, images) {
@@ -838,7 +695,7 @@ function(jQuery, Paths, URI, HostApp, Cache) {
} else if(word.startsWith("http://youtube.com/") || word.startsWith("http://www.youtube.com/") || word.startsWith("https://youtube.com/") || word.startsWith("https://www.youtube.com/")) {
- var v = Paths.getUrlVars(word)["v"];
+ var v = APICalls.getUrlVars(word)["v"];
this.addYouTube(v, images);
} else if (word.startsWith("http://youtu.be/") || word.startsWith("https://youtu.be/")) {
@@ -890,19 +747,8 @@ function(jQuery, Paths, URI, HostApp, Cache) {
}
}
- Core.prototype.replyTo = function(entity, status_id, mentions, is_private) {
-
- var string = "^" + entity.replace("https://", "") + " ";
-
- var ms = "";
- for (var i = 0; i < mentions.length; i++) {
- var e = mentions[i].entity.replace("https://", "");
- if(string.indexOf(e) == -1) ms += " ^" + e;
- }
-
- if(ms.length > 0) string += "\n\n/cc" + ms;
-
- HostApp.openNewMessageWidow(entity, status_id, string, is_private);
+ Core.prototype.replyTo = function(status) {
+ HostApp.openNewMessageWidow(status);
}
Core.prototype.postDeleted = function(post_id, entity) {
@@ -1001,21 +847,22 @@ function(jQuery, Paths, URI, HostApp, Cache) {
Core.prototype.afterChangingTextinMessageHTML = function(message_node) {
// adding show search on click hash
+ /*
$(message_node).find("a.hash").click(function(e) {
if(bungloo.search) bungloo.search.searchFor(e.target.innerHTML);
return false;
});
-
+ */
// adding show profile on click
+ /*
$(message_node).find("a.name").click(function(e) {
HostApp.showProfileForEntity(e.target.title);
return false;
- });
+ });*/
}
-
return Core;
});
\ No newline at end of file
diff --git a/WebKit/scripts/helper/Hmac.js b/WebKit/scripts/helper/Hmac.js
index b22a2f3..be4db38 100644
--- a/WebKit/scripts/helper/Hmac.js
+++ b/WebKit/scripts/helper/Hmac.js
@@ -7,7 +7,7 @@ function(URI, CryptoJS) {
var Hmac = {};
- Hmac.makeAuthHeader = function(url, http_method, mac_key, mac_key_id) {
+ Hmac.makeHawkAuthHeader = function(url, http_method, hawk_id, key, app_id) {
url = URI(url);
var nonce = Hmac.makeid(8);
@@ -18,26 +18,47 @@ function(URI, CryptoJS) {
port = url.protocol() == "https" ? "443" : "80";
}
- var normalizedRequestString = ""
- + time_stamp + '\n'
- + nonce + '\n'
- + http_method + '\n'
- + url.path() + url.search() + url.hash() + '\n'
- + url.hostname() + '\n'
- + port + '\n'
- + '\n' ;
+ var normalizedRequestString = "hawk.1.header\n" // header
+ + time_stamp + '\n' // ts
+ + nonce + '\n' // nonce
+ + http_method.toUpperCase() + '\n' // method
+ + url.path() + url.search() + url.hash() + '\n' // request uri
+ + url.hostname().toLowerCase() + '\n' // host
+ + port + '\n' // port
+ + '\n' // Hmac.calculatePayloadHash(payload) + '\n' // hash // FIXME implement payload validation
+ + '\n' // ext (we don't use it)
- var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, mac_key);
+ var app = "";
+
+ if(app_id) {
+ app = ', app="' + app_id + "'";
+ normalizedRequestString += app_id + "\n" + // app
+ '\n'; // dlg should be empty
+ }
+
+ var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
hmac.update(normalizedRequestString);
var hash = hmac.finalize();
var mac = hash.toString(CryptoJS.enc.Base64);
- return 'MAC id="' + mac_key_id +
+ return 'Hawk id="' + hawk_id +
+ '", mac="' + mac +
'", ts="' + time_stamp +
- '", nonce="' + nonce +
- '", mac="' + mac + '"';
+ '", nonce="' + nonce + '"' +
+ app
}
+ Hmac.calculatePayloadHash = function (payload) {
+ if (!payload) return "";
+
+ var hash = CryptoJS.algo.SHA256.create();
+ hash.update('hawk.1.payload\n');
+ hash.update('application/vnd.tent.post.v0+json\n');
+ hash.update(payload || '');
+ hash.update('\n');
+ return hash.finalize().toString(CryptoJS.enc.Base64);
+ },
+
Hmac.makeid = function(len) {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
diff --git a/WebKit/scripts/helper/HostApp.js b/WebKit/scripts/helper/HostApp.js
index 60cf9e5..9811fda 100644
--- a/WebKit/scripts/helper/HostApp.js
+++ b/WebKit/scripts/helper/HostApp.js
@@ -37,6 +37,14 @@ define(function() {
}
}
+ HostApp.setServerUrls = function(server_urls) {
+ HostApp.setStringForKey(JSON.stringify(server_urls), "server_urls");
+ }
+
+ HostApp.serverUrl = function(key) {
+ return JSON.parse(HostApp.stringForKey("server_urls"))[key];
+ }
+
HostApp.openURL = function(url) {
if (OS_TYPE == "mac") {
@@ -77,13 +85,12 @@ define(function() {
}
}
- HostApp.openNewMessageWidow = function(entity, status_id, string, is_private) {
+ HostApp.openNewMessageWidow = function(status) {
if (OS_TYPE == "mac") {
- controller.openNewMessageWindowInReplyTo_statusId_withString_isPrivate_(entity, status_id, string, is_private);
+ controller.openNewMessageWindowInReplyToStatus_(JSON.stringify(status));
} else {
- is_private = is_private == true
- controller.openNewMessageWindowInReplyTostatusIdwithStringIsPrivate(entity, status_id, string, is_private);
+ controller.openNewMessageWindowInReplyToStatus(JSON.stringify(status).escapeSpecialChars());
}
}
diff --git a/WebKit/scripts/helper/Paths.js b/WebKit/scripts/helper/Paths.js
index 5f477a7..af1fb75 100644
--- a/WebKit/scripts/helper/Paths.js
+++ b/WebKit/scripts/helper/Paths.js
@@ -25,7 +25,7 @@ function(jQuery, HostApp, Hmac, Cache) {
Paths.getURL = function(url, http_method, callback, data, auth_header, accepts) {
- if(accepts !== false) accepts = accepts || "application/vnd.tent.v0+json; charset=utf-8";
+ if(accepts !== false) accepts = accepts || "application/vnd.tent.post.v0+json";
var options = {
@@ -56,7 +56,7 @@ function(jQuery, HostApp, Hmac, Cache) {
}
},
url: url,
- contentType: "application/vnd.tent.v0+json",
+ contentType: 'application/vnd.tent.post.v0+json; type="https://tent.io/types/app/v0#"',
type: http_method,
complete: callback,
data: data,
@@ -65,7 +65,7 @@ function(jQuery, HostApp, Hmac, Cache) {
console.error("getURL (" + xhr.status + ")" + xhr.statusText + " " + http_method + " (" + url + "): '" + xhr.responseText + "'");
}
}
-
+
jQuery.ajax(options);
}
@@ -127,7 +127,7 @@ function(jQuery, HostApp, Hmac, Cache) {
if(profile_urls.length > 0) {
var profile_url = profile_urls[0];
if (!profile_url.startsWith("http")) {
- profile_url = entity + "/profile";
+ profile_url = entity + profile_url;
}
}
@@ -140,13 +140,13 @@ function(jQuery, HostApp, Hmac, Cache) {
if (resp.status >= 200 && resp.status < 300) {
var doc = document.implementation.createHTMLDocument("");
doc.documentElement.innerHTML = resp.responseText;
- var links = $(doc).find("link[rel='https://tent.io/rels/profile']");
+ var links = $(doc).find("link[rel='https://tent.io/rels/meta-post']");
if (links.length > 0) {
var href = links.get(0).href;
Paths.cache.profile_urls.setItem(entity, href);
if (!href.startsWith("http")) {
- href = entity + "/profile";
+ href = entity + href;
}
callback(href);
@@ -184,6 +184,11 @@ function(jQuery, HostApp, Hmac, Cache) {
}
Paths.parseHeaderForProfiles = function(header_string) {
+ var regexp = /https:\/\/tent.io\/rels\/meta-post/i;
+ return Paths.parseHeaderForLink(header_string, regexp);
+ }
+
+ Paths.parseHeaderForLink = function(header_string, match) {
var headers = header_string.split(/\n/);
var links = [];
for (var i = 0; i < headers.length; i++) {
@@ -197,18 +202,18 @@ function(jQuery, HostApp, Hmac, Cache) {
for (var i = 0; i < links.length; i++) {
items = items.concat(links[i].split(","));
}
- var profiles = [];
+ var things = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
- if (item.match(/https:\/\/tent.io\/rels\/profile/i)) {
+ if (item.match(match)) {
var n = item.match(/<([^>]*)>/);
if (n) {
- profiles.push(n[1]);
+ things.push(n[1]);
}
}
}
- return profiles;
+ return things;
}
return Paths;
diff --git a/WebKit/scripts/main.js b/WebKit/scripts/main.js
index 7e30518..3b48c90 100644
--- a/WebKit/scripts/main.js
+++ b/WebKit/scripts/main.js
@@ -7,7 +7,8 @@ var bungloo = {
entityProfile: null,
conversation: null,
search: null,
- cache: {}
+ cache: { profiles: {}},
+ newpost: null
};
requirejs.config({
@@ -33,6 +34,15 @@ function start(view, callback) {
});
+ } else if (view == "newpost") {
+
+ require(["controller/NewPost"], function(NewPost) {
+
+ bungloo.newpost = new NewPost();
+ if(callback) callback();
+
+ });
+
} else {
@@ -54,33 +64,12 @@ function start(view, callback) {
bungloo.search = new Search();
bungloo.sidebar.showContentForTimeline();
-
});
}
}
-String.prototype.startsWith = function(prefix) {
- return this.indexOf(prefix) === 0;
-}
-
-String.prototype.endsWith = function(suffix) {
- return this.match(suffix+"$") == suffix;
-};
-
-var __entityMap = {
- "&": "&",
- "<": "<",
- ">": ">"
-};
-
-String.prototype.escapeHTML = function() {
- return String(this).replace(/[&<>]/g, function (s) {
- return __entityMap[s];
- });
-}
-
var console = {
log: function(s) {
if (OS_TYPE == "mac") {
@@ -172,4 +161,42 @@ function go() { // wait untill everything is loaded
}, 500);
}
-go();
\ No newline at end of file
+go();
+
+
+// String stuff
+String.prototype.startsWith = function(prefix) {
+ return this.indexOf(prefix) === 0;
+}
+
+String.prototype.endsWith = function(suffix) {
+ return this.match(suffix+"$") == suffix;
+};
+
+var __entityMap = {
+ "&": "&",
+ "<": "<",
+ ">": ">"
+};
+
+String.prototype.escapeHTML = function() {
+ return String(this).replace(/[&<>]/g, function (s) {
+ return __entityMap[s];
+ });
+}
+
+String.prototype.hasArabicCharacter = function() {
+ var arregex = /[\u0600-\u06FF]/;
+ return arregex.test(this);
+}
+
+String.prototype.escapeSpecialChars = function() {
+ return this.replace(/[\\]/g, '\\\\')
+ .replace(/[\"]/g, '\\\"')
+ .replace(/[\/]/g, '\\/')
+ .replace(/[\b]/g, '\\b')
+ .replace(/[\f]/g, '\\f')
+ .replace(/[\n]/g, '\\n')
+ .replace(/[\r]/g, '\\r')
+ .replace(/[\t]/g, '\\t');
+}
\ No newline at end of file
diff --git a/images/Actions-insert-image-icon.png b/images/Actions-insert-image-icon.png
deleted file mode 100644
index 05adf9a..0000000
Binary files a/images/Actions-insert-image-icon.png and /dev/null differ
diff --git a/images/Lock-Lock-icon.png b/images/Lock-Lock-icon.png
deleted file mode 100644
index 45079c9..0000000
Binary files a/images/Lock-Lock-icon.png and /dev/null differ
diff --git a/images/Lock-Unlock-icon.png b/images/Lock-Unlock-icon.png
deleted file mode 100644
index 627d59f..0000000
Binary files a/images/Lock-Unlock-icon.png and /dev/null differ