diff --git a/Linux/Bungloo.py b/Linux/Bungloo.py index 6eaebd5..2f849ab 100755 --- a/Linux/Bungloo.py +++ b/Linux/Bungloo.py @@ -21,7 +21,7 @@ class Bungloo: self.preferences = Windows.Preferences(self) self.preferences.show() - self.oauth_implementation = Windows.Oauth(self) + #self.oauth_implementation = Windows.Oauth(self) if self.controller.stringForKey("user_access_token") != "": self.authentification_succeded() @@ -43,17 +43,17 @@ class Bungloo: def authentification_succeded(self): self.preferences.hide() - if hasattr(self, "oauth_implementation"): - self.oauth_implementation.hide() + #if hasattr(self, "oauth_implementation"): + # self.oauth_implementation.hide() self.preferences.active(False) self.init_web_views() def init_web_views(self): self.timeline = Windows.Timeline(self) - self.mentions = Windows.Timeline(self, "mentions", "Mentions") + #self.mentions = Windows.Timeline(self, "mentions", "Mentions") self.timeline.show() - self.conversation = Windows.Timeline(self, "conversation", "Conversation") - self.profile = Windows.Timeline(self, "profile", "Profile") + #self.conversation = Windows.Timeline(self, "conversation", "Conversation") + #self.profile = Windows.Timeline(self, "profile", "Profile") self.find_entity = Windows.FindEntity(self) def timeline_show(self): @@ -61,7 +61,7 @@ class Bungloo: def mentions_show(self): self.controller.unreadMentions(0) - self.mentions.show() + #self.mentions.show() def find_entity_show(self): self.find_entity.show() @@ -131,7 +131,7 @@ class Controller(QtCore.QObject): self.app.timeline.set_window_title("Bungloo (^" + str(i) + ")") else: self.app.timeline.set_window_title("Bungloo") - self.app.mentions.evaluateJavaScript("bungloo_instance.unread_mentions = 0;") + #self.app.mentions.evaluateJavaScript("bungloo_instance.unread_mentions = 0;") @QtCore.pyqtSlot(str, str, str, str) def notificateUserAboutMentionFromNameWithPostIdAndEntity(self, text, name, post_id, entity): @@ -188,28 +188,29 @@ class Controller(QtCore.QObject): if message.isPrivate: isPrivate = "true" - func = u"bungloo_instance.sendNewMessage(\"{}\", \"{}\", \"{}\", {}, {}, {});".format(text, in_reply_to_status_id, in_reply_to_entity, locationObject, imageFilePath, isPrivate) + func = u"bungloo.timeline.sendNewMessage(\"{}\", \"{}\", \"{}\", {}, {}, {});".format(text, in_reply_to_status_id, in_reply_to_entity, locationObject, imageFilePath, isPrivate) self.app.timeline.evaluateJavaScript(func) @QtCore.pyqtSlot(str, str) def showConversationForPostIdandEntity(self, postId, entity): - func = "bungloo_instance.showStatus('{}', '{}');".format(postId, entity) - self.app.conversation.evaluateJavaScript(func) - self.app.conversation.show() + func = "bungloo.sidebar.onConversation(); bungloo.conversation.showStatus('{}', '{}');".format(postId, entity) + self.app.timeline.evaluateJavaScript(func) + self.app.timeline.show() @QtCore.pyqtSlot(str) def showProfileForEntity(self, entity): - func = "bungloo_instance.showProfileForEntity('{}');".format(entity) - self.app.profile.evaluateJavaScript(func) - self.app.profile.show() + func = "bungloo.sidebar.onEntityProfile(); bungloo.entityProfile.showProfileForEntity('{}');".format(entity) + self.app.timeline.evaluateJavaScript(func) @QtCore.pyqtSlot(str, str) def notificateViewsAboutDeletedPostWithIdbyEntity(self, post_id, entity): - func = "bungloo_instance.postDeleted('{}', '{}')".format(post_id, entity); + f = ".postDeleted('{}', '{}')".format(post_id, entity); + func = "bungloo.timeline" + f + ";" + func += "bungloo.mentions" + f + ";" + func += "bungloo.conversation" + f + ";" + func += "bungloo.entityProfile" + f + ";" + self.app.timeline.evaluateJavaScript(func) - self.app.mentions.evaluateJavaScript(func) - self.app.conversation.evaluateJavaScript(func) - self.app.profile.evaluateJavaScript(func) @QtCore.pyqtSlot(str) def authentificationDidNotSucceed(self, errorMessage): diff --git a/Linux/Helper.py b/Linux/Helper.py index 21b2212..baa31b8 100644 --- a/Linux/Helper.py +++ b/Linux/Helper.py @@ -39,6 +39,30 @@ class WebViewCreator(QtWebKit.QWebView): self.connect(self, SIGNAL("linkClicked (const QUrl&)"), self.app.controller.openQURL) self.setPage(WebPage(self, self.app)) + self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + self.customContextMenuRequested.connect(self.context_menu_requested) + self.actions = [] + QtWebKit.QWebSettings.globalSettings().setAttribute(QtWebKit.QWebSettings.DeveloperExtrasEnabled, True) + + def context_menu_requested(self, point): + context_menu = QtGui.QMenu() + + for action in self.actions: + if action.isEnabled(): + context_menu.addAction(action) + + frame = self.page().currentFrame() + + hit_test = frame.hitTestContent(point) + if unicode(hit_test.linkUrl().toString()): + context_menu.addAction(self.action_copy_link) + + if self.settings().testAttribute(QtWebKit.QWebSettings.DeveloperExtrasEnabled): + context_menu.addSeparator() + context_menu.addAction(self.pageAction(QtWebKit.QWebPage.InspectElement)) + + context_menu.exec_(self.mapToGlobal(point)) + def load_local(self, callback=None): self.page().settings().setAttribute(QtWebKit.QWebSettings.LocalContentCanAccessRemoteUrls, True) self.page().settings().setAttribute(QtWebKit.QWebSettings.LocalStorageEnabled, True) diff --git a/Linux/Windows.py b/Linux/Windows.py index ee1fc0c..9b2769f 100644 --- a/Linux/Windows.py +++ b/Linux/Windows.py @@ -91,6 +91,8 @@ class Timeline: self.initUI() + self.webView.triggerPageAction(QtWebKit.QWebPage.InspectElement) + def moveWindow(self, x=0, y=0): self.show() geo = self.window.geometry() diff --git a/WebKit/css/default.css b/WebKit/css/default.css index dfe42cf..17527bd 100644 --- a/WebKit/css/default.css +++ b/WebKit/css/default.css @@ -16,6 +16,36 @@ a { outline: 0; } +#sidebar { + position: fixed; + top: 0; + left: 0; + width: 62px; + height: 100%; + background: #333; +} + +#sidebar ul { + list-style-type: none; + margin: 0; + padding: 7px 0 0 0; + text-align: center; +} + +#siedebar a { + color: #5b5b5b; +} + +#sidebar .sidebar-user img { + max-width: 50px; + max-height: 50px; + border-radius: 8px; +} + +#content { + margin-left: 62px; +} + ol { list-style-type: none; margin: 0; @@ -39,37 +69,37 @@ ol li, .error, header.profile { color: red; } -body > ol > li { +#content ol > li { } -body > ol > li:first-child { +#content ol > li:first-child { border-top: 0; } -body > ol > li:nth-child(odd), .error, header.profile { +#content ol > li:nth-child(odd), .error, header.profile { background: #fafafa; } -body > ol > li:nth-child(even) { +#content ol > li:nth-child(even) { background: #f2f2f2; } -body > ol > li:hover { +#content ol > li:hover { background: #dedede; } -body > ol > li.highlighteffect { +#content ol > li.highlighteffect { background-color: #FFFBD0; -webkit-transition: background-color 200ms linear; } -body > ol > li.highlighteffect-after { +#content ol > li.highlighteffect-after { -webkit-transition: background-color 1000ms linear; } -body > ol > li:after, header.profile:after { +#content ol > li:after, header.profile:after { content: "."; display: block; clear: both; diff --git a/WebKit/img/background.png b/WebKit/img/background.png index dcce74e..f3bd7ae 100644 Binary files a/WebKit/img/background.png and b/WebKit/img/background.png differ diff --git a/WebKit/img/sidebar/conversation.png b/WebKit/img/sidebar/conversation.png new file mode 100644 index 0000000..1670531 Binary files /dev/null and b/WebKit/img/sidebar/conversation.png differ diff --git a/WebKit/img/sidebar/conversation_active.png b/WebKit/img/sidebar/conversation_active.png new file mode 100644 index 0000000..93d96df Binary files /dev/null and b/WebKit/img/sidebar/conversation_active.png differ diff --git a/WebKit/img/sidebar/mentions.png b/WebKit/img/sidebar/mentions.png new file mode 100644 index 0000000..a04c705 Binary files /dev/null and b/WebKit/img/sidebar/mentions.png differ diff --git a/WebKit/img/sidebar/mentions_active.png b/WebKit/img/sidebar/mentions_active.png new file mode 100644 index 0000000..407c7a3 Binary files /dev/null and b/WebKit/img/sidebar/mentions_active.png differ diff --git a/WebKit/img/sidebar/profile.png b/WebKit/img/sidebar/profile.png new file mode 100644 index 0000000..9cc7e3a Binary files /dev/null and b/WebKit/img/sidebar/profile.png differ diff --git a/WebKit/img/sidebar/profile_active.png b/WebKit/img/sidebar/profile_active.png new file mode 100644 index 0000000..732d9b6 Binary files /dev/null and b/WebKit/img/sidebar/profile_active.png differ diff --git a/WebKit/img/sidebar/search.png b/WebKit/img/sidebar/search.png new file mode 100644 index 0000000..1ea9d65 Binary files /dev/null and b/WebKit/img/sidebar/search.png differ diff --git a/WebKit/img/sidebar/search_active.png b/WebKit/img/sidebar/search_active.png new file mode 100644 index 0000000..4b946f8 Binary files /dev/null and b/WebKit/img/sidebar/search_active.png differ diff --git a/WebKit/img/sidebar/timeline.png b/WebKit/img/sidebar/timeline.png new file mode 100644 index 0000000..e29ae97 Binary files /dev/null and b/WebKit/img/sidebar/timeline.png differ diff --git a/WebKit/img/sidebar/timeline_active.png b/WebKit/img/sidebar/timeline_active.png new file mode 100644 index 0000000..4de24dd Binary files /dev/null and b/WebKit/img/sidebar/timeline_active.png differ diff --git a/WebKit/img/sidebar/user.png b/WebKit/img/sidebar/user.png new file mode 100644 index 0000000..563c606 Binary files /dev/null and b/WebKit/img/sidebar/user.png differ diff --git a/WebKit/img/sidebar/user_active.png b/WebKit/img/sidebar/user_active.png new file mode 100644 index 0000000..856f62c Binary files /dev/null and b/WebKit/img/sidebar/user_active.png differ diff --git a/WebKit/index.html b/WebKit/index.html index 098642f..f6d8422 100644 --- a/WebKit/index.html +++ b/WebKit/index.html @@ -7,5 +7,11 @@ + +
+ +
\ No newline at end of file diff --git a/WebKit/scripts/controller/Conversation.js b/WebKit/scripts/controller/Conversation.js index c09d6f6..a92897e 100644 --- a/WebKit/scripts/controller/Conversation.js +++ b/WebKit/scripts/controller/Conversation.js @@ -14,15 +14,15 @@ function(HostApp, Core, Paths, URI) { this.action = "conversation"; - document.body.innerHTML = ""; - this.body = document.createElement("ol"); this.body.className = this.action; - document.body.appendChild(this.body); + + document.getElementById("content").appendChild(this.body); + this.hide(); } Conversation.prototype = Object.create(Core.prototype); - + Conversation.addStatus = function(status) { diff --git a/WebKit/scripts/controller/Mentions.js b/WebKit/scripts/controller/Mentions.js index 5410e10..1909aa5 100644 --- a/WebKit/scripts/controller/Mentions.js +++ b/WebKit/scripts/controller/Mentions.js @@ -17,11 +17,13 @@ function(HostApp, Timeline, URI, Paths) { this.action = "mentions"; this.body.className = this.action; - + + this.hide(); } Mentions.prototype = Object.create(Timeline.prototype); + Mentions.prototype.newStatus = function(statuses) { Timeline.prototype.newStatus.call(this, statuses); diff --git a/WebKit/scripts/controller/Profile.js b/WebKit/scripts/controller/Profile.js index 972c0e9..f9b39e3 100644 --- a/WebKit/scripts/controller/Profile.js +++ b/WebKit/scripts/controller/Profile.js @@ -14,12 +14,25 @@ function(HostApp, Core, Paths, URI) { this.action = "profile"; - document.body.innerHTML = ""; + this.container = document.createElement("div"); + document.getElementById("content").appendChild(this.container); this.initProfileTemplate(); + this.hide(); + + this.showProfileForEntity(); // Load users profile on start } Profile.prototype = Object.create(Core.prototype); + + + Profile.prototype.show = function() { + $(this.container).show(); + } + + Profile.prototype.hide = function() { + $(this.container).hide(); + }; Profile.prototype.showList = function(list) { $(this.body).hide(); @@ -30,6 +43,10 @@ function(HostApp, Core, Paths, URI) { Profile.prototype.showProfileForEntity = function(entity) { + if (!entity) { + entity = HostApp.stringForKey("entity"); + }; + this.clear(); this.entity = entity; this.following = null; @@ -46,8 +63,9 @@ function(HostApp, Core, Paths, URI) { var _this = this; var header = document.createElement("header"); - header.className = "profile" - document.body.appendChild(header); + header.className = "profile"; + + this.container.appendChild(header); this.profile_template = { avatar: document.createElement("img"), @@ -139,15 +157,15 @@ function(HostApp, Core, Paths, URI) { this.body = document.createElement("ol"); this.body.className = this.action; - document.body.appendChild(this.body); + this.container.appendChild(this.body); this.followingsBody = document.createElement("ol"); this.followingsBody.className = this.action + " followings"; - document.body.appendChild(this.followingsBody); + this.container.appendChild(this.followingsBody); this.followersBody = document.createElement("ol"); this.followersBody.className = this.action + " folloewds"; - document.body.appendChild(this.followersBody); + this.container.appendChild(this.followersBody); } diff --git a/WebKit/scripts/controller/Sidebar.js b/WebKit/scripts/controller/Sidebar.js new file mode 100644 index 0000000..fd43d49 --- /dev/null +++ b/WebKit/scripts/controller/Sidebar.js @@ -0,0 +1,182 @@ +define([ + "helper/HostApp", + "helper/Paths", + "helper/Cache" +], + +function(HostApp, Paths, Cache) { + + + function Sidebar() { + + this.cache = new Cache(); + + this.body = document.createElement("ul"); + this.body.class = "sidebar"; + + var _this = this; + + this.menu = {}; + + this.menu.user = this.createItem("User", function() { _this.onEntity() }, "img/sidebar/user.png", "img/sidebar/user.png"); + this.menu.timeline = this.createItem("Timeline", function() { _this.onTimeline() }, "img/sidebar/timeline.png", "img/sidebar/timeline_active.png", true); + this.menu.mentions = this.createItem("Mentions", function() { _this.onMentions() }, "img/sidebar/mentions.png", "img/sidebar/mentions_active.png"); + + this.menu.conversation = this.createItem("Conversation", function() { _this.onConversation() }, "img/sidebar/conversation.png", "img/sidebar/conversation_active.png"); + this.menu.entityProfile = this.createItem("Profile", function() { _this.onEntityProfile() }, "img/sidebar/profile.png", "img/sidebar/profile_active.png"); + this.menu.search = this.createItem("Search", function() { _this.onSearch() }, "img/sidebar/search.png", "img/sidebar/search_active.png") + + this.body.appendChild(this.menu.user); + this.body.appendChild(this.menu.timeline); + this.body.appendChild(this.menu.mentions); + this.body.appendChild(this.menu.conversation); + this.body.appendChild(this.menu.entityProfile); + this.body.appendChild(this.menu.search); + + document.getElementById("sidebar").appendChild(this.body); + + this.setEntityAvatar(); + } + + Sidebar.prototype.createItem = function(name, callback, src_inactive, src_active, active) { + + var li = document.createElement("li"); + li.className = "sidebar-" + name.toLowerCase(); + li.active = false; + li.title = name; + li.name = name; + + var a = document.createElement("a"); + a.href = "#"; + a.onclick = callback; + + var img = document.createElement("img"); + img.src = active ? src_active : src_inactive; + img.src_inactive = src_inactive; + img.src_active = src_active; + img.alt = name; + + a.appendChild(img); + li.appendChild(a); + + return li; + } + + Sidebar.prototype.setEntityAvatar = function() { + + var entity = HostApp.stringForKey("entity"); + this.menu.user.title = entity; + + var img = this.menu.user.getElementsByTagName("img")[0]; + + var _this = this; + + var profile_callback = function(p) { + + var basic = p["https://tent.io/types/info/basic/v0.1.0"]; + + if (p && basic) { + if(basic.name) { + _this.menu.user.title = basic.name; + } + if(basic.avatar_url) { + + img.onerror = function() { + img.src = "img/sidebar/user.png"; + img.src_inactive = img.src; + img.src_active = img.src; + } + + img.src = basic.avatar_url; + img.src_inactive = basic.avatar_url; + img.src_active = basic.avatar_url; + + } + } + + } + + 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.showContentFor = function(active_part, active_li) { + + // Show active content + var parts = [ + bungloo.timeline, + bungloo.mentions, + bungloo.conversation, + bungloo.entityProfile, + bungloo.search + ]; + + for (var i = 0; i < parts.length; i++) { + if (parts[i] != active_part && parts[i] != null) { + parts[i].hide(); + } + } + + active_part.show(); + + // Show active icon + for(var li in this.menu) { + if (this.menu[li] != active_part) { + var img = this.menu[li].getElementsByTagName("img")[0]; + img.src = img.src_inactive; + } + } + + var img = active_li.getElementsByTagName("img")[0]; + img.src = img.src_active; + } + + Sidebar.prototype.onEntity = function() { + bungloo.entityProfile.showProfileForEntity(); + this.onEntityProfile(); + } + + Sidebar.prototype.onTimeline = function() { + this.showContentFor(bungloo.timeline, this.menu.timeline); + } + + Sidebar.prototype.onMentions = function() { + this.showContentFor(bungloo.mentions, this.menu.mentions); + bungloo.mentions.setAllMentionsRead(); + } + + Sidebar.prototype.onConversation = function() { + this.showContentFor(bungloo.conversation, this.menu.conversation); + } + + Sidebar.prototype.onEntityProfile = function() { + this.showContentFor(bungloo.entityProfile, this.menu.entityProfile); + } + + Sidebar.prototype.onSearch = function() { + debug("Search not implemented yet") + } + + return Sidebar; + +}); \ No newline at end of file diff --git a/WebKit/scripts/controller/Timeline.js b/WebKit/scripts/controller/Timeline.js index 4b997bd..e287635 100644 --- a/WebKit/scripts/controller/Timeline.js +++ b/WebKit/scripts/controller/Timeline.js @@ -14,7 +14,7 @@ function(Core, Paths, HostApp, URI) { this.action = "timeline"; this.reload_blocked = false; - this.max_length = 200; + this.max_length = 20; this.timeout = 10 * 1000; // every 10 seconds this.since_id = null; this.since_id_entity = null; @@ -22,7 +22,7 @@ function(Core, Paths, HostApp, URI) { this.body = document.createElement("ol"); this.body.className = this.action; - document.body.appendChild(this.body); + document.getElementById("content").appendChild(this.body); var _this = this; this.reloadIntervall = setInterval(function() { _this.getNewData() }, this.timeout); @@ -31,7 +31,7 @@ function(Core, Paths, HostApp, URI) { } Timeline.prototype = Object.create(Core.prototype); - + Timeline.prototype.newStatus = function(statuses) { diff --git a/WebKit/scripts/helper/Core.js b/WebKit/scripts/helper/Core.js index 38a49ab..9632ba7 100644 --- a/WebKit/scripts/helper/Core.js +++ b/WebKit/scripts/helper/Core.js @@ -13,6 +13,15 @@ function(jQuery, Paths, URI, HostApp, Cache) { this.cache = new Cache(); } + + Core.prototype.show = function() { + if (this.body) $(this.body).show(); + } + + Core.prototype.hide = function() { + if (this.body) $(this.body).hide(); + } + Core.prototype.getTemplate = function() { if(this.template == "undefined") { diff --git a/WebKit/scripts/main.js b/WebKit/scripts/main.js index 7eda271..3bea0cb 100644 --- a/WebKit/scripts/main.js +++ b/WebKit/scripts/main.js @@ -1,54 +1,57 @@ -var bungloo_instance; -var bungloo_cache = {}; + +var bungloo = { + oauth: null, + sidebar: null, + timeline: null, + mentions: null, + entityProfile: null, + conversation: null, + cache: {} +}; requirejs.config({ baseUrl: 'scripts' }); -function start(view) { +function start() { +/* + require(["controller/Oauth"], function(Oauth) { - if (view == "oauth") { - require(["controller/Oauth"], function(Oauth) { + bungloo.oauth = new Oauth(); - bungloo_instance = new Oauth(); + });*/ - }); + require(["controller/Sidebar"], function(Sidebar) { - } else if (view == "timeline") { + bungloo.sidebar = new Sidebar(); - require(["controller/Timeline"], function(Timeline) { + }); - bungloo_instance = new Timeline(); + require(["controller/Timeline"], function(Timeline) { - }); + bungloo.timeline = new Timeline(); - } else if (view == "mentions") { + }); - require(["controller/Mentions"], function(Mentions) { + require(["controller/Mentions"], function(Mentions) { - bungloo_instance = new Mentions(); + bungloo.mentions = new Mentions(); - }); + }); - } else if (view == "profile") { + + require(["controller/Profile"], function(Profile) { - require(["controller/Profile"], function(Profile) { + bungloo.entityProfile = new Profile(); - bungloo_instance = new Profile(); + }); - }); + require(["controller/Conversation"], function(Conversation) { - } else if (view == "follow") { + bungloo.conversation = new Conversation(); - } else if (view == "conversation") { + }); - require(["controller/Conversation"], function(Conversation) { - - bungloo_instance = new Conversation(); - - }); - - } }