From bba8c067326f177166300959da76ac13ee92e103 Mon Sep 17 00:00:00 2001 From: Ihor Dvoretskyi Date: Mon, 16 Nov 2015 14:11:19 +0200 Subject: Ubuntu 15.10 Wily added to the list of supported Ubuntu systems README updated with a note that installation from the PPA is also available for Ubuntu 15.10 and derivations. Workability is confirmed on Kubuntu 15.10. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 01ebae6..b0fc84e 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ sudo apt-get update && sudo apt-get upgrade If not, ScudCloud will crash with some old components or will not be installed. -Then, to install it under **Ubuntu/Kubuntu** (14.04, 14.10, 15.04), **Mint** and **Debian**, open a Terminal (Ctrl+Alt+T) and run: +Then, to install it under **Ubuntu/Kubuntu** (14.04, 14.10, 15.04, 15.10), **Mint** and **Debian**, open a Terminal (Ctrl+Alt+T) and run: ```term sudo apt-add-repository -y ppa:rael-gc/scudcloud -- cgit v1.1 From 8fcb826d428443522afaaf4a5ba6791e5f5ea930 Mon Sep 17 00:00:00 2001 From: Rael Date: Wed, 18 Nov 2015 11:21:55 -0200 Subject: Implement a proper JS client (#292) --- scudcloud-1.0/lib/scudcloud.py | 11 +--- scudcloud-1.0/lib/wrapper.py | 29 ++------- scudcloud-1.0/resources/scudcloud.js | 2 +- scudcloud-1.0/scudcloud-src.js | 122 +++++++++++++++++++++++++---------- 4 files changed, 94 insertions(+), 70 deletions(-) diff --git a/scudcloud-1.0/lib/scudcloud.py b/scudcloud-1.0/lib/scudcloud.py index 3fb3b2c..abcc8ca 100755 --- a/scudcloud-1.0/lib/scudcloud.py +++ b/scudcloud-1.0/lib/scudcloud.py @@ -61,8 +61,6 @@ class ScudCloud(QtGui.QMainWindow): self.systray(ScudCloud.minimized) self.installEventFilter(self) self.statusBar().showMessage('Loading Slack...') - # Starting unread msgs counter - self.setupTimer() def addWrapper(self, url): webView = Wrapper(self) @@ -73,12 +71,6 @@ class ScudCloud(QtGui.QMainWindow): self.stackedWidget.addWidget(webView) self.stackedWidget.setCurrentWidget(webView) - def setupTimer(self): - self.timer = QTimer(self) - self.timer.timeout.connect(self.count) - self.timer.setInterval(2000) - self.timer.start() - def webSettings(self): self.cookiesjar = PersistentCookieJar(self) self.zoom = self.readZoom() @@ -281,7 +273,6 @@ class ScudCloud(QtGui.QMainWindow): break if not exists: self.addWrapper(url) - self.enableMenus(self.current().isConnected()) self.updateEditMenu() def eventFilter(self, obj, event): @@ -367,7 +358,7 @@ class ScudCloud(QtGui.QMainWindow): total = 0 for i in range(0, self.stackedWidget.count()): widget = self.stackedWidget.widget(i) - messages = widget.count() + messages = widget.highlights if messages == 0: self.leftPane.stopAlert(widget.team()) else: diff --git a/scudcloud-1.0/lib/wrapper.py b/scudcloud-1.0/lib/wrapper.py index 084c631..115cbe9 100644 --- a/scudcloud-1.0/lib/wrapper.py +++ b/scudcloud-1.0/lib/wrapper.py @@ -10,6 +10,7 @@ from PyQt4.QtNetwork import QNetworkProxy class Wrapper(QWebView): + highlights = 0 icon = None def __init__(self, window): @@ -26,18 +27,6 @@ class Wrapper(QWebView): self.linkClicked.connect(self._linkClicked) self.page().featurePermissionRequested.connect(self.permissionRequested) self.addActions() - self.setupTimer() - - # Starting a timer that will check by server side reloads (which drops ScudCloud notification) - def setupTimer(self): - timer = QTimer(self) - timer.timeout.connect(self.overrideNotifications) - # Hope each 10 minutes will not be produce high CPU usage - timer.setInterval(600000) - timer.start() - - def overrideNotifications(self): - self.call("overrideNotifications") def permissionRequested(self, frame, feature): self.page().setFeaturePermission(frame, feature, QWebPage.PermissionGrantedByUser) @@ -104,7 +93,6 @@ class Wrapper(QWebView): def _loadFinished(self, ok=True): self.page().currentFrame().addToJavaScriptWindowObject("desktop", self) self.page().currentFrame().evaluateJavaScript(self.js) - self.window.enableMenus(self.isConnected()) self.window.statusBar().hide() def systemOpen(self, url): @@ -127,9 +115,6 @@ class Wrapper(QWebView): self.window.show() self.call("preferences") - def isConnected(self): - return self.call("isConnected") - def createSnippet(self): self.call("createSnippet") @@ -148,9 +133,6 @@ class Wrapper(QWebView): def about(self): subprocess.call(('xdg-open', "https://github.com/raelgc/scudcloud")) - def isConnected(self): - return self.call("isConnected") - def listChannels(self): return self.call("listChannels") @@ -158,11 +140,10 @@ class Wrapper(QWebView): self.call("join", menuitem.property_get("id")) self.window.show() - def count(self): - try: - return self.call("count") - except: - return 0 + @QtCore.pyqtSlot(int, int) + def setBadgeCount(self, highlight, unread): + self.highlights = highlight + self.window.count() @QtCore.pyqtSlot(str) def populate(self, serialized): diff --git a/scudcloud-1.0/resources/scudcloud.js b/scudcloud-1.0/resources/scudcloud.js index 5e121c6..bf1f5d6 100644 --- a/scudcloud-1.0/resources/scudcloud.js +++ b/scudcloud-1.0/resources/scudcloud.js @@ -1 +1 @@ -var ScudCloud={overrideNotifications:function(){TS.ui.growls.no_notifications=!1,TS.ui.growls.checkPermission=function(){return!0},TS.ui.growls.getPermissionLevel=function(){return"granted"},TS.ui.growls.show=function(n,e){desktop.sendMessage(n,e)},TS.ui.banner.close()},overrideConnect:function(){TS.ms.connected_sig.add(function(){ScudCloud.connect(!0)}),TS.ms.disconnected_sig.add(function(){ScudCloud.connect(!1)})},overrideBanner:function(){ScudCloud.showBanner=TS.ui.banner.show,TS.ui.banner.show=function(){ScudCloud.showBanner(),ScudCloud.overrideNotifications()}},connect:function(n){desktop.enableMenus(n),n&&(ScudCloud.overrideNotifications(),desktop.populate(JSON.stringify({channels:ScudCloud.listChannels(),teams:ScudCloud.listTeams(),icon:TS.model.team.icon.image_44})))},count:function(){var n=0;return $("span.unread_highlight").not(".hidden").each(function(){n+=new Number($(this).text().replace("+",""))}),n},createSnippet:function(){return TS.ui.snippet_dialog.start()},listChannels:function(){return TS.channels.getUnarchivedChannelsForUser()},listTeams:function(){var n=TS.getAllTeams();return n[0].team_icon={image_44:TS.model.team.icon.image_44},n},quicklist:function(){desktop.quicklist(ScudCloud.listChannels())},join:function(n){return TS.channels.join(n)},setClipboard:function(n){TS.client.ui.file_pasted_sig.dispatch(n,TS.model.shift_key_pressed)},preferences:function(){return TS.ui.prefs_dialog.start()},addTeam:function(){document.location=TS.boot_data.signin_url},getCurrentTeam:function(){var n=TS.getAllTeams();if(null!=n)for(var e=0;n.length;e++)if(n[e].team_url==TS.boot_data.team_url)return n[e].id;return""},logout:function(){document.location=TS.boot_data.logout_url},help:function(){return TS.help_dialog.start()},isConnected:function(){return"undefined"!=typeof TS&&"undefined"!=typeof TS.model&&TS.model.ms_connected}};"undefined"!=typeof TS&&(document.onpaste=function(){desktop.pasted(!1)},ScudCloud.overrideNotifications(),ScudCloud.overrideConnect(),ScudCloud.overrideBanner()); +ScudCloud={hasPreference:function(e){return ScudCloud.na("hasPreference")},getPreference:function(e){return ScudCloud.na("getPreference")},setPreference:function(e,n){return ScudCloud.na("setPreference")},canShowHtmlNotifications:function(){return ScudCloud.na("canShowHtmlNotifications")},call:function(e,n){switch(ScudCloud.log(e),e){case"reload":return ScudCloud.reload();case"didStartLoading":return ScudCloud.didStartLoading();case"didFinishLoading":return ScudCloud.didFinishLoading();case"setConnectionStatus":return ScudCloud.setConnectionStatus(n);case"notify":return ScudCloud.notify(n);case"setBadgeCount":return ScudCloud.setBadgeCount(n);case"displayTeam":return ScudCloud.displayTeam(n);case"getModifierKeys":case"updateTitleBarColor":case"disableSecureInput":case"setImage":case"listWindows":case"focusWindow":case"openWindow":case"closeWindow":case"getGeometryForWindow":case"startDownload":case"supportsOpenFileAtPath":case"cancelDownloadWithToken":case"openFileAtPath":case"retryDownloadWithToken":case"pruneTokensFromHistory":case"metadataForDownloads":case"readFindString":}return!1},reload:function(){window.location.reload()},didStartLoading:function(){},didFinishLoading:function(){ScudCloud.populate()},setConnectionStatus:function(e){switch(e){case"online":desktop.enableMenus(!0);break;default:desktop.enableMenus(!1)}},notify:function(e){desktop.sendMessage(e.title,e.content)},setBadgeCount:function(e){desktop.setBadgeCount(e.all_unread_highlights_cnt,e.all_unread_cnt)},displayTeam:function(e){},na:function(e){return ScudCloud.log(e),!1},log:function(e){console.log("ScudCloud."+e)},populate:function(){desktop.populate(JSON.stringify({channels:ScudCloud.listChannels(),teams:ScudCloud.listTeams(),icon:TS.model.team.icon.image_44}))},createSnippet:function(){return TS.ui.snippet_dialog.start()},listChannels:function(){return TS.channels.getUnarchivedChannelsForUser()},listTeams:function(){var e=TS.getAllTeams();return e[0].team_icon={image_44:TS.model.team.icon.image_44},e},quicklist:function(){desktop.quicklist(ScudCloud.listChannels())},join:function(e){return TS.channels.join(e)},setClipboard:function(e){TS.client.ui.file_pasted_sig.dispatch(e,TS.model.shift_key_pressed)},preferences:function(){return TS.ui.prefs_dialog.start()},addTeam:function(){document.location=TS.boot_data.signin_url},getCurrentTeam:function(){var e=TS.getAllTeams();if(null!=e)for(var n=0;e.length;n++)if(e[n].team_url==TS.boot_data.team_url)return e[n].id;return""},logout:function(){document.location=TS.boot_data.logout_url},help:function(){return TS.help_dialog.start()}},"undefined"!=typeof TS&&(document.onpaste=function(e){desktop.pasted(!1)},window.winssb=TSSSB=ScudCloud); diff --git a/scudcloud-1.0/scudcloud-src.js b/scudcloud-1.0/scudcloud-src.js index c16a0b9..4cf759b 100644 --- a/scudcloud-1.0/scudcloud-src.js +++ b/scudcloud-1.0/scudcloud-src.js @@ -1,33 +1,90 @@ -var ScudCloud = { - overrideNotifications: function(){ - TS.ui.growls.no_notifications = false; - TS.ui.growls.checkPermission = function() { return true; }; - TS.ui.growls.getPermissionLevel = function() { return 'granted'; }; - TS.ui.growls.show = function(j,f,o,p){ desktop.sendMessage(j,f); }; - TS.ui.banner.close(); - }, - overrideConnect: function(){ - TS.ms.connected_sig.add(function(){ScudCloud.connect(true);}); - TS.ms.disconnected_sig.add(function(){ScudCloud.connect(false);}); - }, - overrideBanner: function(){ - ScudCloud.showBanner = TS.ui.banner.show; - TS.ui.banner.show = function(){ ScudCloud.showBanner(); ScudCloud.overrideNotifications(); }; - }, - connect: function(b){ - desktop.enableMenus(b); - if(b){ - ScudCloud.overrideNotifications(); - desktop.populate(JSON.stringify({'channels': ScudCloud.listChannels(), 'teams': ScudCloud.listTeams(), 'icon': TS.model.team.icon.image_44})); +ScudCloud = { + // App functions + hasPreference: function(name){ + return ScudCloud.na("hasPreference"); + }, + getPreference: function(name){ + return ScudCloud.na("getPreference"); + }, + setPreference: function(name, value){ + return ScudCloud.na("setPreference"); + }, + canShowHtmlNotifications: function(){ + return ScudCloud.na("canShowHtmlNotifications"); + }, + // TSSSB.call + call: function(name, args){ + ScudCloud.log(name); + switch(name){ + case "reload": + return ScudCloud.reload(); + case "didStartLoading": + return ScudCloud.didStartLoading(); + case "didFinishLoading": + return ScudCloud.didFinishLoading(); + case "setConnectionStatus": + return ScudCloud.setConnectionStatus(args); + case "notify": + return ScudCloud.notify(args); + case "setBadgeCount": + return ScudCloud.setBadgeCount(args); + case "displayTeam": + return ScudCloud.displayTeam(args); + case "getModifierKeys": + case "updateTitleBarColor": + case "disableSecureInput": + case "setImage": + case "listWindows": + case "focusWindow": + case "openWindow": + case "closeWindow": + case "getGeometryForWindow": + case "startDownload": + case "supportsOpenFileAtPath": + case "cancelDownloadWithToken": + case "openFileAtPath": + case "retryDownloadWithToken": + case "pruneTokensFromHistory": + case "metadataForDownloads": + case "readFindString": + } + return false; + }, + // TSSSB.call implementations + reload: function(){ + window.location.reload(); + }, + didStartLoading: function(){ + }, + didFinishLoading: function(){ + ScudCloud.populate(); + }, + setConnectionStatus: function(status){ + // "online", "connecting", "offline" + switch(status){ + case "online": desktop.enableMenus(true); break; + default: desktop.enableMenus(false); } }, - count: function(){ - var total=0; - $('span.unread_highlight').not('.hidden').each(function(i){ - total+= new Number($(this).text().replace('+','')); } - ); - return total; - }, + notify: function(args){ + desktop.sendMessage(args.title, args.content); + }, + setBadgeCount: function(args){ + desktop.setBadgeCount(args.all_unread_highlights_cnt, args.all_unread_cnt); + }, + displayTeam: function(id){ + }, + // ScudCloud internal functions + na: function(name){ + ScudCloud.log(name); + return false; + }, + log: function(name){ + console.log("ScudCloud."+name); + }, + populate: function(){ + desktop.populate(JSON.stringify({'channels': ScudCloud.listChannels(), 'teams': ScudCloud.listTeams(), 'icon': TS.model.team.icon.image_44})); + }, createSnippet: function(){ return TS.ui.snippet_dialog.start(); }, @@ -69,14 +126,9 @@ var ScudCloud = { }, help: function(){ return TS.help_dialog.start(); - }, - isConnected: function(){ - return "undefined" != typeof TS && "undefined" != typeof TS.model && TS.model.ms_connected; - } + } }; if("undefined" != typeof TS){ document.onpaste = function(e){desktop.pasted(false);}; - ScudCloud.overrideNotifications(); - ScudCloud.overrideConnect(); - ScudCloud.overrideBanner(); + window.winssb = TSSSB = ScudCloud; } -- cgit v1.1 From 702883e521e9db324f71f77983aafa5c690ae4d8 Mon Sep 17 00:00:00 2001 From: Rael Date: Wed, 18 Nov 2015 12:41:17 -0200 Subject: Small changes to make JS faster (#292) --- scudcloud-1.0/resources/scudcloud.js | 2 +- scudcloud-1.0/scudcloud-src.js | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/scudcloud-1.0/resources/scudcloud.js b/scudcloud-1.0/resources/scudcloud.js index bf1f5d6..b7a2710 100644 --- a/scudcloud-1.0/resources/scudcloud.js +++ b/scudcloud-1.0/resources/scudcloud.js @@ -1 +1 @@ -ScudCloud={hasPreference:function(e){return ScudCloud.na("hasPreference")},getPreference:function(e){return ScudCloud.na("getPreference")},setPreference:function(e,n){return ScudCloud.na("setPreference")},canShowHtmlNotifications:function(){return ScudCloud.na("canShowHtmlNotifications")},call:function(e,n){switch(ScudCloud.log(e),e){case"reload":return ScudCloud.reload();case"didStartLoading":return ScudCloud.didStartLoading();case"didFinishLoading":return ScudCloud.didFinishLoading();case"setConnectionStatus":return ScudCloud.setConnectionStatus(n);case"notify":return ScudCloud.notify(n);case"setBadgeCount":return ScudCloud.setBadgeCount(n);case"displayTeam":return ScudCloud.displayTeam(n);case"getModifierKeys":case"updateTitleBarColor":case"disableSecureInput":case"setImage":case"listWindows":case"focusWindow":case"openWindow":case"closeWindow":case"getGeometryForWindow":case"startDownload":case"supportsOpenFileAtPath":case"cancelDownloadWithToken":case"openFileAtPath":case"retryDownloadWithToken":case"pruneTokensFromHistory":case"metadataForDownloads":case"readFindString":}return!1},reload:function(){window.location.reload()},didStartLoading:function(){},didFinishLoading:function(){ScudCloud.populate()},setConnectionStatus:function(e){switch(e){case"online":desktop.enableMenus(!0);break;default:desktop.enableMenus(!1)}},notify:function(e){desktop.sendMessage(e.title,e.content)},setBadgeCount:function(e){desktop.setBadgeCount(e.all_unread_highlights_cnt,e.all_unread_cnt)},displayTeam:function(e){},na:function(e){return ScudCloud.log(e),!1},log:function(e){console.log("ScudCloud."+e)},populate:function(){desktop.populate(JSON.stringify({channels:ScudCloud.listChannels(),teams:ScudCloud.listTeams(),icon:TS.model.team.icon.image_44}))},createSnippet:function(){return TS.ui.snippet_dialog.start()},listChannels:function(){return TS.channels.getUnarchivedChannelsForUser()},listTeams:function(){var e=TS.getAllTeams();return e[0].team_icon={image_44:TS.model.team.icon.image_44},e},quicklist:function(){desktop.quicklist(ScudCloud.listChannels())},join:function(e){return TS.channels.join(e)},setClipboard:function(e){TS.client.ui.file_pasted_sig.dispatch(e,TS.model.shift_key_pressed)},preferences:function(){return TS.ui.prefs_dialog.start()},addTeam:function(){document.location=TS.boot_data.signin_url},getCurrentTeam:function(){var e=TS.getAllTeams();if(null!=e)for(var n=0;e.length;n++)if(e[n].team_url==TS.boot_data.team_url)return e[n].id;return""},logout:function(){document.location=TS.boot_data.logout_url},help:function(){return TS.help_dialog.start()}},"undefined"!=typeof TS&&(document.onpaste=function(e){desktop.pasted(!1)},window.winssb=TSSSB=ScudCloud); +ScudCloud={hasPreference:function(e){return ScudCloud.na("hasPreference")},getPreference:function(e){return ScudCloud.na("getPreference")},setPreference:function(e,n){return ScudCloud.na("setPreference")},canShowHtmlNotifications:function(){return ScudCloud.na("canShowHtmlNotifications")},call:function(e,n){switch(ScudCloud.log(e),e){case"reload":return ScudCloud.reload();case"didStartLoading":return ScudCloud.didStartLoading();case"didFinishLoading":return ScudCloud.didFinishLoading();case"setConnectionStatus":return ScudCloud.setConnectionStatus(n);case"notify":return ScudCloud.notify(n);case"setBadgeCount":return ScudCloud.setBadgeCount(n);case"displayTeam":return ScudCloud.displayTeam(n);case"getModifierKeys":case"updateTitleBarColor":case"disableSecureInput":case"setImage":case"listWindows":case"focusWindow":case"openWindow":case"closeWindow":case"getGeometryForWindow":case"startDownload":case"supportsOpenFileAtPath":case"cancelDownloadWithToken":case"openFileAtPath":case"retryDownloadWithToken":case"pruneTokensFromHistory":case"metadataForDownloads":case"readFindString":}return!1},reload:function(){window.location.reload()},didStartLoading:function(){},didFinishLoading:function(){ScudCloud.populate()},setConnectionStatus:function(e){switch(e){case"online":desktop.enableMenus(!0);break;default:desktop.enableMenus(!1)}},notify:function(e){desktop.sendMessage(e.title,e.content)},setBadgeCount:function(e){desktop.setBadgeCount(e.all_unread_highlights_cnt,e.all_unread_cnt)},displayTeam:function(e){},na:function(e){return ScudCloud.log(e),!1},log:function(e){console.log("ScudCloud."+e)},populate:function(){desktop.populate(JSON.stringify({channels:ScudCloud.listChannels(),teams:ScudCloud.listTeams(),icon:TS.model.team.icon.image_44}))},createSnippet:function(){return TS.ui.snippet_dialog.start()},listChannels:function(){return TS.channels.getUnarchivedChannelsForUser()},listTeams:function(){var e=TS.getAllTeams();return e[0].team_icon={image_44:TS.model.team.icon.image_44},e},quicklist:function(){desktop.quicklist(ScudCloud.listChannels())},join:function(e){return TS.channels.join(e)},setClipboard:function(e){TS.client.ui.file_pasted_sig.dispatch(e,TS.model.shift_key_pressed)},preferences:function(){return TS.ui.prefs_dialog.start()},addTeam:function(){document.location=TS.boot_data.signin_url},getCurrentTeam:function(){var e=TS.getAllTeams();if(null!=e)for(var n=0;e.length;n++)if(e[n].team_url==TS.boot_data.team_url)return e[n].id;return""},logout:function(){document.location=TS.boot_data.logout_url},help:function(){return TS.help_dialog.start()}},document.onpaste=function(e){desktop.pasted(!1)},window.winssb=TSSSB=ScudCloud; diff --git a/scudcloud-1.0/scudcloud-src.js b/scudcloud-1.0/scudcloud-src.js index 4cf759b..2f253d1 100644 --- a/scudcloud-1.0/scudcloud-src.js +++ b/scudcloud-1.0/scudcloud-src.js @@ -128,7 +128,5 @@ ScudCloud = { return TS.help_dialog.start(); } }; -if("undefined" != typeof TS){ - document.onpaste = function(e){desktop.pasted(false);}; - window.winssb = TSSSB = ScudCloud; -} +document.onpaste = function(e){desktop.pasted(false);}; +window.winssb = TSSSB = ScudCloud; -- cgit v1.1 From 47885a6a2c4f1239232dff6983456ed405f06fa5 Mon Sep 17 00:00:00 2001 From: Rael Date: Wed, 18 Nov 2015 13:29:20 -0200 Subject: Short message title (#292) --- scudcloud-1.0/lib/wrapper.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scudcloud-1.0/lib/wrapper.py b/scudcloud-1.0/lib/wrapper.py index 115cbe9..f018163 100644 --- a/scudcloud-1.0/lib/wrapper.py +++ b/scudcloud-1.0/lib/wrapper.py @@ -12,6 +12,7 @@ class Wrapper(QWebView): highlights = 0 icon = None + name = '' def __init__(self, window): self.configure_proxy() @@ -151,8 +152,8 @@ class Wrapper(QWebView): self.window.teams(data['teams']) if self.window.current() == self: self.window.quicklist(data['channels']) - iconFile = data['teams'][0]['team_name']+'.png' - filename, headers = request.urlretrieve(data['icon'], tempfile.gettempdir()+'/'+iconFile) + self.name = data['teams'][0]['team_name'] + filename, headers = request.urlretrieve(data['icon'], tempfile.gettempdir()+'/'+self.name+'.png') self.icon = filename @QtCore.pyqtSlot(bool) @@ -172,6 +173,6 @@ class Wrapper(QWebView): @QtCore.pyqtSlot(str, str) def sendMessage(self, title, message): - self.window.notify(str(title).replace("New message from ", "").replace("New message in ", ""), str(message), self.icon) + self.window.notify(str(title).replace('New message from ', '', 1).replace('New message in ', '', 1).replace('['+self.name.lower()+'] in ', '', 1), str(message), self.icon) -- cgit v1.1 From 6b503543ae75fcd1172e9c557b6ed2752aa4d943 Mon Sep 17 00:00:00 2001 From: Rael Date: Wed, 18 Nov 2015 14:03:46 -0200 Subject: Better code for sendMessage replacement (#292) --- scudcloud-1.0/lib/wrapper.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scudcloud-1.0/lib/wrapper.py b/scudcloud-1.0/lib/wrapper.py index f018163..13be430 100644 --- a/scudcloud-1.0/lib/wrapper.py +++ b/scudcloud-1.0/lib/wrapper.py @@ -173,6 +173,9 @@ class Wrapper(QWebView): @QtCore.pyqtSlot(str, str) def sendMessage(self, title, message): - self.window.notify(str(title).replace('New message from ', '', 1).replace('New message in ', '', 1).replace('['+self.name.lower()+'] in ', '', 1), str(message), self.icon) + erase = ['New message from ', 'New message in ', '['+self.name.lower()+'] in '] + for s in erase: + title = str(title).replace(s, '', 1) + self.window.notify(title, str(message), self.icon) -- cgit v1.1 From 5c75d1a37803dd6a6b805c040ca9bed1e23ddc8b Mon Sep 17 00:00:00 2001 From: Rael Date: Wed, 18 Nov 2015 14:10:06 -0200 Subject: Renaming setBadgeCount method to count (#292) --- scudcloud-1.0/lib/wrapper.py | 2 +- scudcloud-1.0/resources/scudcloud.js | 2 +- scudcloud-1.0/scudcloud-src.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scudcloud-1.0/lib/wrapper.py b/scudcloud-1.0/lib/wrapper.py index 13be430..1a62fad 100644 --- a/scudcloud-1.0/lib/wrapper.py +++ b/scudcloud-1.0/lib/wrapper.py @@ -142,7 +142,7 @@ class Wrapper(QWebView): self.window.show() @QtCore.pyqtSlot(int, int) - def setBadgeCount(self, highlight, unread): + def count(self, highlight, unread): self.highlights = highlight self.window.count() diff --git a/scudcloud-1.0/resources/scudcloud.js b/scudcloud-1.0/resources/scudcloud.js index b7a2710..23a8597 100644 --- a/scudcloud-1.0/resources/scudcloud.js +++ b/scudcloud-1.0/resources/scudcloud.js @@ -1 +1 @@ -ScudCloud={hasPreference:function(e){return ScudCloud.na("hasPreference")},getPreference:function(e){return ScudCloud.na("getPreference")},setPreference:function(e,n){return ScudCloud.na("setPreference")},canShowHtmlNotifications:function(){return ScudCloud.na("canShowHtmlNotifications")},call:function(e,n){switch(ScudCloud.log(e),e){case"reload":return ScudCloud.reload();case"didStartLoading":return ScudCloud.didStartLoading();case"didFinishLoading":return ScudCloud.didFinishLoading();case"setConnectionStatus":return ScudCloud.setConnectionStatus(n);case"notify":return ScudCloud.notify(n);case"setBadgeCount":return ScudCloud.setBadgeCount(n);case"displayTeam":return ScudCloud.displayTeam(n);case"getModifierKeys":case"updateTitleBarColor":case"disableSecureInput":case"setImage":case"listWindows":case"focusWindow":case"openWindow":case"closeWindow":case"getGeometryForWindow":case"startDownload":case"supportsOpenFileAtPath":case"cancelDownloadWithToken":case"openFileAtPath":case"retryDownloadWithToken":case"pruneTokensFromHistory":case"metadataForDownloads":case"readFindString":}return!1},reload:function(){window.location.reload()},didStartLoading:function(){},didFinishLoading:function(){ScudCloud.populate()},setConnectionStatus:function(e){switch(e){case"online":desktop.enableMenus(!0);break;default:desktop.enableMenus(!1)}},notify:function(e){desktop.sendMessage(e.title,e.content)},setBadgeCount:function(e){desktop.setBadgeCount(e.all_unread_highlights_cnt,e.all_unread_cnt)},displayTeam:function(e){},na:function(e){return ScudCloud.log(e),!1},log:function(e){console.log("ScudCloud."+e)},populate:function(){desktop.populate(JSON.stringify({channels:ScudCloud.listChannels(),teams:ScudCloud.listTeams(),icon:TS.model.team.icon.image_44}))},createSnippet:function(){return TS.ui.snippet_dialog.start()},listChannels:function(){return TS.channels.getUnarchivedChannelsForUser()},listTeams:function(){var e=TS.getAllTeams();return e[0].team_icon={image_44:TS.model.team.icon.image_44},e},quicklist:function(){desktop.quicklist(ScudCloud.listChannels())},join:function(e){return TS.channels.join(e)},setClipboard:function(e){TS.client.ui.file_pasted_sig.dispatch(e,TS.model.shift_key_pressed)},preferences:function(){return TS.ui.prefs_dialog.start()},addTeam:function(){document.location=TS.boot_data.signin_url},getCurrentTeam:function(){var e=TS.getAllTeams();if(null!=e)for(var n=0;e.length;n++)if(e[n].team_url==TS.boot_data.team_url)return e[n].id;return""},logout:function(){document.location=TS.boot_data.logout_url},help:function(){return TS.help_dialog.start()}},document.onpaste=function(e){desktop.pasted(!1)},window.winssb=TSSSB=ScudCloud; +ScudCloud={hasPreference:function(e){return ScudCloud.na("hasPreference")},getPreference:function(e){return ScudCloud.na("getPreference")},setPreference:function(e,n){return ScudCloud.na("setPreference")},canShowHtmlNotifications:function(){return ScudCloud.na("canShowHtmlNotifications")},call:function(e,n){switch(ScudCloud.log(e),e){case"reload":return ScudCloud.reload();case"didStartLoading":return ScudCloud.didStartLoading();case"didFinishLoading":return ScudCloud.didFinishLoading();case"setConnectionStatus":return ScudCloud.setConnectionStatus(n);case"notify":return ScudCloud.notify(n);case"setBadgeCount":return ScudCloud.setBadgeCount(n);case"displayTeam":return ScudCloud.displayTeam(n);case"getModifierKeys":case"updateTitleBarColor":case"disableSecureInput":case"setImage":case"listWindows":case"focusWindow":case"openWindow":case"closeWindow":case"getGeometryForWindow":case"startDownload":case"supportsOpenFileAtPath":case"cancelDownloadWithToken":case"openFileAtPath":case"retryDownloadWithToken":case"pruneTokensFromHistory":case"metadataForDownloads":case"readFindString":}return!1},reload:function(){window.location.reload()},didStartLoading:function(){},didFinishLoading:function(){ScudCloud.populate()},setConnectionStatus:function(e){switch(e){case"online":desktop.enableMenus(!0);break;default:desktop.enableMenus(!1)}},notify:function(e){desktop.sendMessage(e.title,e.content)},setBadgeCount:function(e){desktop.count(e.all_unread_highlights_cnt,e.all_unread_cnt)},displayTeam:function(e){},na:function(e){return ScudCloud.log(e),!1},log:function(e){console.log("ScudCloud."+e)},populate:function(){desktop.populate(JSON.stringify({channels:ScudCloud.listChannels(),teams:ScudCloud.listTeams(),icon:TS.model.team.icon.image_44}))},createSnippet:function(){return TS.ui.snippet_dialog.start()},listChannels:function(){return TS.channels.getUnarchivedChannelsForUser()},listTeams:function(){var e=TS.getAllTeams();return e[0].team_icon={image_44:TS.model.team.icon.image_44},e},quicklist:function(){desktop.quicklist(ScudCloud.listChannels())},join:function(e){return TS.channels.join(e)},setClipboard:function(e){TS.client.ui.file_pasted_sig.dispatch(e,TS.model.shift_key_pressed)},preferences:function(){return TS.ui.prefs_dialog.start()},addTeam:function(){document.location=TS.boot_data.signin_url},getCurrentTeam:function(){var e=TS.getAllTeams();if(null!=e)for(var n=0;e.length;n++)if(e[n].team_url==TS.boot_data.team_url)return e[n].id;return""},logout:function(){document.location=TS.boot_data.logout_url},help:function(){return TS.help_dialog.start()}},document.onpaste=function(e){desktop.pasted(!1)},window.winssb=TSSSB=ScudCloud; diff --git a/scudcloud-1.0/scudcloud-src.js b/scudcloud-1.0/scudcloud-src.js index 2f253d1..3af0a53 100644 --- a/scudcloud-1.0/scudcloud-src.js +++ b/scudcloud-1.0/scudcloud-src.js @@ -70,7 +70,7 @@ ScudCloud = { desktop.sendMessage(args.title, args.content); }, setBadgeCount: function(args){ - desktop.setBadgeCount(args.all_unread_highlights_cnt, args.all_unread_cnt); + desktop.count(args.all_unread_highlights_cnt, args.all_unread_cnt); }, displayTeam: function(id){ }, -- cgit v1.1 From 6d3df640b7cc469910d8f22a3d10e9950ff936dc Mon Sep 17 00:00:00 2001 From: Rael Date: Wed, 18 Nov 2015 15:53:54 -0200 Subject: More notification replacements (#292) --- scudcloud-1.0/lib/wrapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scudcloud-1.0/lib/wrapper.py b/scudcloud-1.0/lib/wrapper.py index 1a62fad..6ac594a 100644 --- a/scudcloud-1.0/lib/wrapper.py +++ b/scudcloud-1.0/lib/wrapper.py @@ -173,7 +173,7 @@ class Wrapper(QWebView): @QtCore.pyqtSlot(str, str) def sendMessage(self, title, message): - erase = ['New message from ', 'New message in ', '['+self.name.lower()+'] in '] + erase = ['['+self.name.lower()+'] in ', '['+self.name.lower()+'] from '] for s in erase: title = str(title).replace(s, '', 1) self.window.notify(title, str(message), self.icon) -- cgit v1.1 From b05e1291c8154ee2d492514e572c9a78b8df671e Mon Sep 17 00:00:00 2001 From: Rael Date: Wed, 18 Nov 2015 16:29:31 -0200 Subject: Starting the webkit-JS bridge earlier (#292) --- scudcloud-1.0/lib/wrapper.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scudcloud-1.0/lib/wrapper.py b/scudcloud-1.0/lib/wrapper.py index 6ac594a..65c6c6b 100644 --- a/scudcloud-1.0/lib/wrapper.py +++ b/scudcloud-1.0/lib/wrapper.py @@ -83,6 +83,8 @@ class Wrapper(QWebView): def _loadStarted(self): # Some custom CSS to clean/fix UX self.settings().setUserStyleSheetUrl(QUrl.fromLocalFile(Resources.get_path("resources.css"))) + # Starting the webkit-JS bridge + self.page().currentFrame().addToJavaScriptWindowObject("desktop", self) def _urlChanged(self, qUrl): url = qUrl.toString() @@ -92,7 +94,6 @@ class Wrapper(QWebView): self.load(QUrl("https://"+qUrl.host()+"/messages/general")) def _loadFinished(self, ok=True): - self.page().currentFrame().addToJavaScriptWindowObject("desktop", self) self.page().currentFrame().evaluateJavaScript(self.js) self.window.statusBar().hide() -- cgit v1.1 From 6601bcb0fd52e5ea49697dcc60e2613e14f67057 Mon Sep 17 00:00:00 2001 From: Rael Date: Wed, 18 Nov 2015 16:29:53 -0200 Subject: Double checking didFinishLoading (#292) --- scudcloud-1.0/resources/scudcloud.js | 2 +- scudcloud-1.0/scudcloud-src.js | 39 ++++++++++++------------------------ 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/scudcloud-1.0/resources/scudcloud.js b/scudcloud-1.0/resources/scudcloud.js index 23a8597..34bbec3 100644 --- a/scudcloud-1.0/resources/scudcloud.js +++ b/scudcloud-1.0/resources/scudcloud.js @@ -1 +1 @@ -ScudCloud={hasPreference:function(e){return ScudCloud.na("hasPreference")},getPreference:function(e){return ScudCloud.na("getPreference")},setPreference:function(e,n){return ScudCloud.na("setPreference")},canShowHtmlNotifications:function(){return ScudCloud.na("canShowHtmlNotifications")},call:function(e,n){switch(ScudCloud.log(e),e){case"reload":return ScudCloud.reload();case"didStartLoading":return ScudCloud.didStartLoading();case"didFinishLoading":return ScudCloud.didFinishLoading();case"setConnectionStatus":return ScudCloud.setConnectionStatus(n);case"notify":return ScudCloud.notify(n);case"setBadgeCount":return ScudCloud.setBadgeCount(n);case"displayTeam":return ScudCloud.displayTeam(n);case"getModifierKeys":case"updateTitleBarColor":case"disableSecureInput":case"setImage":case"listWindows":case"focusWindow":case"openWindow":case"closeWindow":case"getGeometryForWindow":case"startDownload":case"supportsOpenFileAtPath":case"cancelDownloadWithToken":case"openFileAtPath":case"retryDownloadWithToken":case"pruneTokensFromHistory":case"metadataForDownloads":case"readFindString":}return!1},reload:function(){window.location.reload()},didStartLoading:function(){},didFinishLoading:function(){ScudCloud.populate()},setConnectionStatus:function(e){switch(e){case"online":desktop.enableMenus(!0);break;default:desktop.enableMenus(!1)}},notify:function(e){desktop.sendMessage(e.title,e.content)},setBadgeCount:function(e){desktop.count(e.all_unread_highlights_cnt,e.all_unread_cnt)},displayTeam:function(e){},na:function(e){return ScudCloud.log(e),!1},log:function(e){console.log("ScudCloud."+e)},populate:function(){desktop.populate(JSON.stringify({channels:ScudCloud.listChannels(),teams:ScudCloud.listTeams(),icon:TS.model.team.icon.image_44}))},createSnippet:function(){return TS.ui.snippet_dialog.start()},listChannels:function(){return TS.channels.getUnarchivedChannelsForUser()},listTeams:function(){var e=TS.getAllTeams();return e[0].team_icon={image_44:TS.model.team.icon.image_44},e},quicklist:function(){desktop.quicklist(ScudCloud.listChannels())},join:function(e){return TS.channels.join(e)},setClipboard:function(e){TS.client.ui.file_pasted_sig.dispatch(e,TS.model.shift_key_pressed)},preferences:function(){return TS.ui.prefs_dialog.start()},addTeam:function(){document.location=TS.boot_data.signin_url},getCurrentTeam:function(){var e=TS.getAllTeams();if(null!=e)for(var n=0;e.length;n++)if(e[n].team_url==TS.boot_data.team_url)return e[n].id;return""},logout:function(){document.location=TS.boot_data.logout_url},help:function(){return TS.help_dialog.start()}},document.onpaste=function(e){desktop.pasted(!1)},window.winssb=TSSSB=ScudCloud; +ScudCloud={unloaded:!0,hasPreference:function(n){return!1},getPreference:function(n){return!1},setPreference:function(n,e){return!1},canShowHtmlNotifications:function(){return!1},call:function(n,e){switch(ScudCloud.log(n),n){case"reload":return ScudCloud.reload();case"didStartLoading":return ScudCloud.didStartLoading();case"didFinishLoading":return ScudCloud.didFinishLoading();case"setConnectionStatus":return ScudCloud.setConnectionStatus(e);case"notify":return ScudCloud.notify(e);case"setBadgeCount":return ScudCloud.setBadgeCount(e);case"displayTeam":return ScudCloud.displayTeam(e)}return!1},reload:function(){window.location.reload()},didStartLoading:function(){},didFinishLoading:function(){ScudCloud.unloaded&&(TS.ui.banner.close(),ScudCloud.populate(),ScudCloud.unloaded=!1)},setConnectionStatus:function(n){switch(n){case"online":desktop.enableMenus(!0);break;default:desktop.enableMenus(!1)}},notify:function(n){desktop.sendMessage(n.title,n.content)},setBadgeCount:function(n){desktop.count(n.all_unread_highlights_cnt,n.all_unread_cnt)},displayTeam:function(n){},log:function(n){console.log("ScudCloud."+n)},populate:function(){desktop.populate(JSON.stringify({channels:ScudCloud.listChannels(),teams:ScudCloud.listTeams(),icon:TS.model.team.icon.image_44}))},createSnippet:function(){return TS.ui.snippet_dialog.start()},listChannels:function(){return TS.channels.getUnarchivedChannelsForUser()},listTeams:function(){var n=TS.getAllTeams();return n[0].team_icon={image_44:TS.model.team.icon.image_44},n},quicklist:function(){desktop.quicklist(ScudCloud.listChannels())},join:function(n){return TS.channels.join(n)},setClipboard:function(n){TS.client.ui.file_pasted_sig.dispatch(n,TS.model.shift_key_pressed)},preferences:function(){return TS.ui.prefs_dialog.start()},addTeam:function(){document.location=TS.boot_data.signin_url},getCurrentTeam:function(){var n=TS.getAllTeams();if(null!=n)for(var e=0;n.length;e++)if(n[e].team_url==TS.boot_data.team_url)return n[e].id;return""},logout:function(){document.location=TS.boot_data.logout_url},help:function(){return TS.help_dialog.start()}},document.onpaste=function(n){desktop.pasted(!1)},window.winssb=TSSSB=ScudCloud,ScudCloud.didFinishLoading(); diff --git a/scudcloud-1.0/scudcloud-src.js b/scudcloud-1.0/scudcloud-src.js index 3af0a53..36ce89e 100644 --- a/scudcloud-1.0/scudcloud-src.js +++ b/scudcloud-1.0/scudcloud-src.js @@ -1,16 +1,18 @@ ScudCloud = { + unloaded: true, // App functions hasPreference: function(name){ - return ScudCloud.na("hasPreference"); + return false; }, getPreference: function(name){ - return ScudCloud.na("getPreference"); + return false; }, setPreference: function(name, value){ - return ScudCloud.na("setPreference"); + return false; }, canShowHtmlNotifications: function(){ - return ScudCloud.na("canShowHtmlNotifications"); + // Ubuntu cannot display HTML notifications + return false; }, // TSSSB.call call: function(name, args){ @@ -30,23 +32,6 @@ ScudCloud = { return ScudCloud.setBadgeCount(args); case "displayTeam": return ScudCloud.displayTeam(args); - case "getModifierKeys": - case "updateTitleBarColor": - case "disableSecureInput": - case "setImage": - case "listWindows": - case "focusWindow": - case "openWindow": - case "closeWindow": - case "getGeometryForWindow": - case "startDownload": - case "supportsOpenFileAtPath": - case "cancelDownloadWithToken": - case "openFileAtPath": - case "retryDownloadWithToken": - case "pruneTokensFromHistory": - case "metadataForDownloads": - case "readFindString": } return false; }, @@ -57,7 +42,11 @@ ScudCloud = { didStartLoading: function(){ }, didFinishLoading: function(){ - ScudCloud.populate(); + if(ScudCloud.unloaded){ + TS.ui.banner.close(); + ScudCloud.populate(); + ScudCloud.unloaded = false; + } }, setConnectionStatus: function(status){ // "online", "connecting", "offline" @@ -75,10 +64,6 @@ ScudCloud = { displayTeam: function(id){ }, // ScudCloud internal functions - na: function(name){ - ScudCloud.log(name); - return false; - }, log: function(name){ console.log("ScudCloud."+name); }, @@ -130,3 +115,5 @@ ScudCloud = { }; document.onpaste = function(e){desktop.pasted(false);}; window.winssb = TSSSB = ScudCloud; +// Sometimes didFinishLoading is not loaded +ScudCloud.didFinishLoading(); -- cgit v1.1 From 018b3ad8e1656a1c08ba69d58f53e5a60ac74e79 Mon Sep 17 00:00:00 2001 From: Rael Date: Thu, 19 Nov 2015 09:16:33 -0200 Subject: Don't block didFinishLoading to run again (#292) --- scudcloud-1.0/resources/scudcloud.js | 2 +- scudcloud-1.0/scudcloud-src.js | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/scudcloud-1.0/resources/scudcloud.js b/scudcloud-1.0/resources/scudcloud.js index 34bbec3..82a7621 100644 --- a/scudcloud-1.0/resources/scudcloud.js +++ b/scudcloud-1.0/resources/scudcloud.js @@ -1 +1 @@ -ScudCloud={unloaded:!0,hasPreference:function(n){return!1},getPreference:function(n){return!1},setPreference:function(n,e){return!1},canShowHtmlNotifications:function(){return!1},call:function(n,e){switch(ScudCloud.log(n),n){case"reload":return ScudCloud.reload();case"didStartLoading":return ScudCloud.didStartLoading();case"didFinishLoading":return ScudCloud.didFinishLoading();case"setConnectionStatus":return ScudCloud.setConnectionStatus(e);case"notify":return ScudCloud.notify(e);case"setBadgeCount":return ScudCloud.setBadgeCount(e);case"displayTeam":return ScudCloud.displayTeam(e)}return!1},reload:function(){window.location.reload()},didStartLoading:function(){},didFinishLoading:function(){ScudCloud.unloaded&&(TS.ui.banner.close(),ScudCloud.populate(),ScudCloud.unloaded=!1)},setConnectionStatus:function(n){switch(n){case"online":desktop.enableMenus(!0);break;default:desktop.enableMenus(!1)}},notify:function(n){desktop.sendMessage(n.title,n.content)},setBadgeCount:function(n){desktop.count(n.all_unread_highlights_cnt,n.all_unread_cnt)},displayTeam:function(n){},log:function(n){console.log("ScudCloud."+n)},populate:function(){desktop.populate(JSON.stringify({channels:ScudCloud.listChannels(),teams:ScudCloud.listTeams(),icon:TS.model.team.icon.image_44}))},createSnippet:function(){return TS.ui.snippet_dialog.start()},listChannels:function(){return TS.channels.getUnarchivedChannelsForUser()},listTeams:function(){var n=TS.getAllTeams();return n[0].team_icon={image_44:TS.model.team.icon.image_44},n},quicklist:function(){desktop.quicklist(ScudCloud.listChannels())},join:function(n){return TS.channels.join(n)},setClipboard:function(n){TS.client.ui.file_pasted_sig.dispatch(n,TS.model.shift_key_pressed)},preferences:function(){return TS.ui.prefs_dialog.start()},addTeam:function(){document.location=TS.boot_data.signin_url},getCurrentTeam:function(){var n=TS.getAllTeams();if(null!=n)for(var e=0;n.length;e++)if(n[e].team_url==TS.boot_data.team_url)return n[e].id;return""},logout:function(){document.location=TS.boot_data.logout_url},help:function(){return TS.help_dialog.start()}},document.onpaste=function(n){desktop.pasted(!1)},window.winssb=TSSSB=ScudCloud,ScudCloud.didFinishLoading(); +ScudCloud={unloaded:!0,hasPreference:function(n){return!1},getPreference:function(n){return!1},setPreference:function(n,e){return!1},canShowHtmlNotifications:function(){return!1},call:function(n,e){switch(ScudCloud.log(n),n){case"reload":return ScudCloud.reload();case"didStartLoading":return ScudCloud.didStartLoading();case"didFinishLoading":return ScudCloud.didFinishLoading();case"setConnectionStatus":return ScudCloud.setConnectionStatus(e);case"notify":return ScudCloud.notify(e);case"setBadgeCount":return ScudCloud.setBadgeCount(e);case"displayTeam":return ScudCloud.displayTeam(e)}return!1},reload:function(){window.location.reload()},didStartLoading:function(){},didFinishLoading:function(){TS.ui.banner.close(),ScudCloud.populate(),ScudCloud.unloaded=!1},setConnectionStatus:function(n){switch(n){case"online":desktop.enableMenus(!0);break;default:desktop.enableMenus(!1)}},notify:function(n){desktop.sendMessage(n.title,n.content)},setBadgeCount:function(n){desktop.count(n.all_unread_highlights_cnt,n.all_unread_cnt)},displayTeam:function(n){},log:function(n){console.log("ScudCloud."+n)},populate:function(){desktop.populate(JSON.stringify({channels:ScudCloud.listChannels(),teams:ScudCloud.listTeams(),icon:TS.model.team.icon.image_44}))},createSnippet:function(){return TS.ui.snippet_dialog.start()},listChannels:function(){return TS.channels.getUnarchivedChannelsForUser()},listTeams:function(){var n=TS.getAllTeams();return n[0].team_icon={image_44:TS.model.team.icon.image_44},n},quicklist:function(){desktop.quicklist(ScudCloud.listChannels())},join:function(n){return TS.channels.join(n)},setClipboard:function(n){TS.client.ui.file_pasted_sig.dispatch(n,TS.model.shift_key_pressed)},preferences:function(){return TS.ui.prefs_dialog.start()},addTeam:function(){document.location=TS.boot_data.signin_url},getCurrentTeam:function(){var n=TS.getAllTeams();if(null!=n)for(var e=0;n.length;e++)if(n[e].team_url==TS.boot_data.team_url)return n[e].id;return""},logout:function(){document.location=TS.boot_data.logout_url},help:function(){return TS.help_dialog.start()}},document.onpaste=function(n){desktop.pasted(!1)},window.winssb=TSSSB=ScudCloud,ScudCloud.unloaded&&ScudCloud.didFinishLoading(); diff --git a/scudcloud-1.0/scudcloud-src.js b/scudcloud-1.0/scudcloud-src.js index 36ce89e..3bb9beb 100644 --- a/scudcloud-1.0/scudcloud-src.js +++ b/scudcloud-1.0/scudcloud-src.js @@ -1,3 +1,4 @@ + ScudCloud = { unloaded: true, // App functions @@ -42,11 +43,9 @@ ScudCloud = { didStartLoading: function(){ }, didFinishLoading: function(){ - if(ScudCloud.unloaded){ - TS.ui.banner.close(); - ScudCloud.populate(); - ScudCloud.unloaded = false; - } + TS.ui.banner.close(); + ScudCloud.populate(); + ScudCloud.unloaded = false; }, setConnectionStatus: function(status){ // "online", "connecting", "offline" @@ -116,4 +115,6 @@ ScudCloud = { document.onpaste = function(e){desktop.pasted(false);}; window.winssb = TSSSB = ScudCloud; // Sometimes didFinishLoading is not loaded -ScudCloud.didFinishLoading(); +if(ScudCloud.unloaded){ + ScudCloud.didFinishLoading(); +} -- cgit v1.1 From a33bb67eb0755edbf6bc8d5ecf124a57c3a522f3 Mon Sep 17 00:00:00 2001 From: Rael Date: Thu, 19 Nov 2015 09:39:39 -0200 Subject: Adding some comments --- scudcloud-1.0/lib/wrapper.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scudcloud-1.0/lib/wrapper.py b/scudcloud-1.0/lib/wrapper.py index 65c6c6b..9d1c348 100644 --- a/scudcloud-1.0/lib/wrapper.py +++ b/scudcloud-1.0/lib/wrapper.py @@ -83,8 +83,6 @@ class Wrapper(QWebView): def _loadStarted(self): # Some custom CSS to clean/fix UX self.settings().setUserStyleSheetUrl(QUrl.fromLocalFile(Resources.get_path("resources.css"))) - # Starting the webkit-JS bridge - self.page().currentFrame().addToJavaScriptWindowObject("desktop", self) def _urlChanged(self, qUrl): url = qUrl.toString() @@ -94,6 +92,9 @@ class Wrapper(QWebView): self.load(QUrl("https://"+qUrl.host()+"/messages/general")) def _loadFinished(self, ok=True): + # Starting the webkit-JS bridge + self.page().currentFrame().addToJavaScriptWindowObject("desktop", self) + # Loading ScudCloud JS client self.page().currentFrame().evaluateJavaScript(self.js) self.window.statusBar().hide() -- cgit v1.1 From 57a20803d5b63af55755f89d46eaffdadaea06fc Mon Sep 17 00:00:00 2001 From: Rael Date: Thu, 19 Nov 2015 09:42:25 -0200 Subject: Fixing stuck in loading screen (#294) --- scudcloud-1.0/lib/scudcloud.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scudcloud-1.0/lib/scudcloud.py b/scudcloud-1.0/lib/scudcloud.py index abcc8ca..d53e04f 100755 --- a/scudcloud-1.0/lib/scudcloud.py +++ b/scudcloud-1.0/lib/scudcloud.py @@ -80,6 +80,8 @@ class ScudCloud(QtGui.QMainWindow): QWebSettings.globalSettings().setAttribute(QWebSettings.JavaEnabled, False) # We don't need History QWebSettings.globalSettings().setAttribute(QWebSettings.PrivateBrowsingEnabled, True) + # Enabling Local Storage (now required by Slack) + QWebSettings.globalSettings().setAttribute(QWebSettings.LocalStorageEnabled, True) # Enabling Cache self.diskCache = QNetworkDiskCache(self) self.diskCache.setCacheDirectory(self.settings_path) -- cgit v1.1 From 622a55342859bd3df5321e782fa23c893c2818ed Mon Sep 17 00:00:00 2001 From: Rael Date: Thu, 19 Nov 2015 10:17:38 -0200 Subject: New package release with bump minor version --- README.md | 10 +- scudcloud-1.0/LICENSE | 21 - scudcloud-1.0/VERSION | 1 - scudcloud-1.0/debian/changelog | 676 -------------------- scudcloud-1.0/debian/compat | 1 - scudcloud-1.0/debian/control | 26 - scudcloud-1.0/debian/copyright | 30 - scudcloud-1.0/debian/install | 9 - scudcloud-1.0/debian/postinst | 41 -- scudcloud-1.0/debian/postrm | 39 -- scudcloud-1.0/debian/prerm | 39 -- scudcloud-1.0/debian/rules | 8 - scudcloud-1.0/debian/scudcloud.links | 1 - scudcloud-1.0/leftpane-src.js | 68 -- scudcloud-1.0/lib/cookiejar.py | 24 - scudcloud-1.0/lib/launcher.py | 7 - scudcloud-1.0/lib/leftpane.py | 60 -- scudcloud-1.0/lib/notifier.py | 35 -- scudcloud-1.0/lib/notify2.py | 342 ----------- scudcloud-1.0/lib/resources.py | 19 - scudcloud-1.0/lib/scudcloud.py | 379 ------------ scudcloud-1.0/lib/speller.py | 90 --- scudcloud-1.0/lib/systray.py | 57 -- scudcloud-1.0/lib/wrapper.py | 183 ------ scudcloud-1.0/resources/leftpane.html | 47 -- scudcloud-1.0/resources/leftpane.js | 1 - scudcloud-1.0/resources/resources.css | 2 - scudcloud-1.0/resources/scudcloud.js | 1 - scudcloud-1.0/resources/scudcloud.png | Bin 7751 -> 0 bytes scudcloud-1.0/scudcloud | 93 --- scudcloud-1.0/scudcloud-src.js | 120 ---- scudcloud-1.0/scudcloud.desktop | 13 - scudcloud-1.0/scudcloud.spec | 159 ----- .../systray/hicolor/scudcloud-attention-1.svg | 101 --- .../systray/hicolor/scudcloud-attention-2.svg | 101 --- .../systray/hicolor/scudcloud-attention-3.svg | 101 --- .../systray/hicolor/scudcloud-attention-4.svg | 101 --- .../systray/hicolor/scudcloud-attention-5.svg | 101 --- .../systray/hicolor/scudcloud-attention-6.svg | 101 --- .../systray/hicolor/scudcloud-attention-7.svg | 101 --- .../systray/hicolor/scudcloud-attention-8.svg | 101 --- .../systray/hicolor/scudcloud-attention-9-plus.svg | 115 ---- .../systray/hicolor/scudcloud-attention-9.svg | 101 --- .../systray/hicolor/scudcloud-attention.svg | 61 -- scudcloud-1.0/systray/hicolor/scudcloud.svg | 61 -- .../systray/mono-dark/scudcloud-attention-1.svg | 101 --- .../systray/mono-dark/scudcloud-attention-2.svg | 101 --- .../systray/mono-dark/scudcloud-attention-3.svg | 101 --- .../systray/mono-dark/scudcloud-attention-4.svg | 101 --- .../systray/mono-dark/scudcloud-attention-5.svg | 101 --- .../systray/mono-dark/scudcloud-attention-6.svg | 101 --- .../systray/mono-dark/scudcloud-attention-7.svg | 101 --- .../systray/mono-dark/scudcloud-attention-8.svg | 101 --- .../mono-dark/scudcloud-attention-9-plus.svg | 115 ---- .../systray/mono-dark/scudcloud-attention-9.svg | 101 --- .../systray/mono-dark/scudcloud-attention.svg | 61 -- scudcloud-1.0/systray/mono-dark/scudcloud.svg | 61 -- .../systray/mono-light/scudcloud-attention-1.svg | 101 --- .../systray/mono-light/scudcloud-attention-2.svg | 101 --- .../systray/mono-light/scudcloud-attention-3.svg | 101 --- .../systray/mono-light/scudcloud-attention-4.svg | 101 --- .../systray/mono-light/scudcloud-attention-5.svg | 101 --- .../systray/mono-light/scudcloud-attention-6.svg | 101 --- .../systray/mono-light/scudcloud-attention-7.svg | 101 --- .../systray/mono-light/scudcloud-attention-8.svg | 101 --- .../mono-light/scudcloud-attention-9-plus.svg | 115 ---- .../systray/mono-light/scudcloud-attention-9.svg | 101 --- .../systray/mono-light/scudcloud-attention.svg | 61 -- scudcloud-1.0/systray/mono-light/scudcloud.svg | 61 -- scudcloud-1.1/LICENSE | 21 + scudcloud-1.1/VERSION | 1 + scudcloud-1.1/debian/changelog | 683 +++++++++++++++++++++ scudcloud-1.1/debian/compat | 1 + scudcloud-1.1/debian/control | 26 + scudcloud-1.1/debian/copyright | 30 + scudcloud-1.1/debian/install | 9 + scudcloud-1.1/debian/postinst | 41 ++ scudcloud-1.1/debian/postrm | 39 ++ scudcloud-1.1/debian/prerm | 39 ++ scudcloud-1.1/debian/rules | 8 + scudcloud-1.1/debian/scudcloud.links | 1 + scudcloud-1.1/leftpane-src.js | 68 ++ scudcloud-1.1/lib/cookiejar.py | 24 + scudcloud-1.1/lib/launcher.py | 7 + scudcloud-1.1/lib/leftpane.py | 60 ++ scudcloud-1.1/lib/notifier.py | 35 ++ scudcloud-1.1/lib/notify2.py | 342 +++++++++++ scudcloud-1.1/lib/resources.py | 19 + scudcloud-1.1/lib/scudcloud.py | 379 ++++++++++++ scudcloud-1.1/lib/speller.py | 90 +++ scudcloud-1.1/lib/systray.py | 57 ++ scudcloud-1.1/lib/wrapper.py | 183 ++++++ scudcloud-1.1/resources/leftpane.html | 47 ++ scudcloud-1.1/resources/leftpane.js | 1 + scudcloud-1.1/resources/resources.css | 2 + scudcloud-1.1/resources/scudcloud.js | 1 + scudcloud-1.1/resources/scudcloud.png | Bin 0 -> 7751 bytes scudcloud-1.1/scudcloud | 93 +++ scudcloud-1.1/scudcloud-src.js | 120 ++++ scudcloud-1.1/scudcloud.desktop | 13 + scudcloud-1.1/scudcloud.spec | 159 +++++ .../systray/hicolor/scudcloud-attention-1.svg | 101 +++ .../systray/hicolor/scudcloud-attention-2.svg | 101 +++ .../systray/hicolor/scudcloud-attention-3.svg | 101 +++ .../systray/hicolor/scudcloud-attention-4.svg | 101 +++ .../systray/hicolor/scudcloud-attention-5.svg | 101 +++ .../systray/hicolor/scudcloud-attention-6.svg | 101 +++ .../systray/hicolor/scudcloud-attention-7.svg | 101 +++ .../systray/hicolor/scudcloud-attention-8.svg | 101 +++ .../systray/hicolor/scudcloud-attention-9-plus.svg | 115 ++++ .../systray/hicolor/scudcloud-attention-9.svg | 101 +++ .../systray/hicolor/scudcloud-attention.svg | 61 ++ scudcloud-1.1/systray/hicolor/scudcloud.svg | 61 ++ .../systray/mono-dark/scudcloud-attention-1.svg | 101 +++ .../systray/mono-dark/scudcloud-attention-2.svg | 101 +++ .../systray/mono-dark/scudcloud-attention-3.svg | 101 +++ .../systray/mono-dark/scudcloud-attention-4.svg | 101 +++ .../systray/mono-dark/scudcloud-attention-5.svg | 101 +++ .../systray/mono-dark/scudcloud-attention-6.svg | 101 +++ .../systray/mono-dark/scudcloud-attention-7.svg | 101 +++ .../systray/mono-dark/scudcloud-attention-8.svg | 101 +++ .../mono-dark/scudcloud-attention-9-plus.svg | 115 ++++ .../systray/mono-dark/scudcloud-attention-9.svg | 101 +++ .../systray/mono-dark/scudcloud-attention.svg | 61 ++ scudcloud-1.1/systray/mono-dark/scudcloud.svg | 61 ++ .../systray/mono-light/scudcloud-attention-1.svg | 101 +++ .../systray/mono-light/scudcloud-attention-2.svg | 101 +++ .../systray/mono-light/scudcloud-attention-3.svg | 101 +++ .../systray/mono-light/scudcloud-attention-4.svg | 101 +++ .../systray/mono-light/scudcloud-attention-5.svg | 101 +++ .../systray/mono-light/scudcloud-attention-6.svg | 101 +++ .../systray/mono-light/scudcloud-attention-7.svg | 101 +++ .../systray/mono-light/scudcloud-attention-8.svg | 101 +++ .../mono-light/scudcloud-attention-9-plus.svg | 115 ++++ .../systray/mono-light/scudcloud-attention-9.svg | 101 +++ .../systray/mono-light/scudcloud-attention.svg | 61 ++ scudcloud-1.1/systray/mono-light/scudcloud.svg | 61 ++ 137 files changed, 6042 insertions(+), 6035 deletions(-) delete mode 100644 scudcloud-1.0/LICENSE delete mode 100644 scudcloud-1.0/VERSION delete mode 100644 scudcloud-1.0/debian/changelog delete mode 100644 scudcloud-1.0/debian/compat delete mode 100644 scudcloud-1.0/debian/control delete mode 100644 scudcloud-1.0/debian/copyright delete mode 100644 scudcloud-1.0/debian/install delete mode 100755 scudcloud-1.0/debian/postinst delete mode 100644 scudcloud-1.0/debian/postrm delete mode 100644 scudcloud-1.0/debian/prerm delete mode 100755 scudcloud-1.0/debian/rules delete mode 100644 scudcloud-1.0/debian/scudcloud.links delete mode 100644 scudcloud-1.0/leftpane-src.js delete mode 100644 scudcloud-1.0/lib/cookiejar.py delete mode 100644 scudcloud-1.0/lib/launcher.py delete mode 100644 scudcloud-1.0/lib/leftpane.py delete mode 100644 scudcloud-1.0/lib/notifier.py delete mode 100644 scudcloud-1.0/lib/notify2.py delete mode 100644 scudcloud-1.0/lib/resources.py delete mode 100755 scudcloud-1.0/lib/scudcloud.py delete mode 100644 scudcloud-1.0/lib/speller.py delete mode 100644 scudcloud-1.0/lib/systray.py delete mode 100644 scudcloud-1.0/lib/wrapper.py delete mode 100644 scudcloud-1.0/resources/leftpane.html delete mode 100644 scudcloud-1.0/resources/leftpane.js delete mode 100644 scudcloud-1.0/resources/resources.css delete mode 100644 scudcloud-1.0/resources/scudcloud.js delete mode 100644 scudcloud-1.0/resources/scudcloud.png delete mode 100755 scudcloud-1.0/scudcloud delete mode 100644 scudcloud-1.0/scudcloud-src.js delete mode 100644 scudcloud-1.0/scudcloud.desktop delete mode 100644 scudcloud-1.0/scudcloud.spec delete mode 100644 scudcloud-1.0/systray/hicolor/scudcloud-attention-1.svg delete mode 100644 scudcloud-1.0/systray/hicolor/scudcloud-attention-2.svg delete mode 100644 scudcloud-1.0/systray/hicolor/scudcloud-attention-3.svg delete mode 100644 scudcloud-1.0/systray/hicolor/scudcloud-attention-4.svg delete mode 100644 scudcloud-1.0/systray/hicolor/scudcloud-attention-5.svg delete mode 100644 scudcloud-1.0/systray/hicolor/scudcloud-attention-6.svg delete mode 100644 scudcloud-1.0/systray/hicolor/scudcloud-attention-7.svg delete mode 100644 scudcloud-1.0/systray/hicolor/scudcloud-attention-8.svg delete mode 100644 scudcloud-1.0/systray/hicolor/scudcloud-attention-9-plus.svg delete mode 100644 scudcloud-1.0/systray/hicolor/scudcloud-attention-9.svg delete mode 100644 scudcloud-1.0/systray/hicolor/scudcloud-attention.svg delete mode 100644 scudcloud-1.0/systray/hicolor/scudcloud.svg delete mode 100644 scudcloud-1.0/systray/mono-dark/scudcloud-attention-1.svg delete mode 100644 scudcloud-1.0/systray/mono-dark/scudcloud-attention-2.svg delete mode 100644 scudcloud-1.0/systray/mono-dark/scudcloud-attention-3.svg delete mode 100644 scudcloud-1.0/systray/mono-dark/scudcloud-attention-4.svg delete mode 100644 scudcloud-1.0/systray/mono-dark/scudcloud-attention-5.svg delete mode 100644 scudcloud-1.0/systray/mono-dark/scudcloud-attention-6.svg delete mode 100644 scudcloud-1.0/systray/mono-dark/scudcloud-attention-7.svg delete mode 100644 scudcloud-1.0/systray/mono-dark/scudcloud-attention-8.svg delete mode 100644 scudcloud-1.0/systray/mono-dark/scudcloud-attention-9-plus.svg delete mode 100644 scudcloud-1.0/systray/mono-dark/scudcloud-attention-9.svg delete mode 100644 scudcloud-1.0/systray/mono-dark/scudcloud-attention.svg delete mode 100644 scudcloud-1.0/systray/mono-dark/scudcloud.svg delete mode 100644 scudcloud-1.0/systray/mono-light/scudcloud-attention-1.svg delete mode 100644 scudcloud-1.0/systray/mono-light/scudcloud-attention-2.svg delete mode 100644 scudcloud-1.0/systray/mono-light/scudcloud-attention-3.svg delete mode 100644 scudcloud-1.0/systray/mono-light/scudcloud-attention-4.svg delete mode 100644 scudcloud-1.0/systray/mono-light/scudcloud-attention-5.svg delete mode 100644 scudcloud-1.0/systray/mono-light/scudcloud-attention-6.svg delete mode 100644 scudcloud-1.0/systray/mono-light/scudcloud-attention-7.svg delete mode 100644 scudcloud-1.0/systray/mono-light/scudcloud-attention-8.svg delete mode 100644 scudcloud-1.0/systray/mono-light/scudcloud-attention-9-plus.svg delete mode 100644 scudcloud-1.0/systray/mono-light/scudcloud-attention-9.svg delete mode 100644 scudcloud-1.0/systray/mono-light/scudcloud-attention.svg delete mode 100644 scudcloud-1.0/systray/mono-light/scudcloud.svg create mode 100644 scudcloud-1.1/LICENSE create mode 100644 scudcloud-1.1/VERSION create mode 100644 scudcloud-1.1/debian/changelog create mode 100644 scudcloud-1.1/debian/compat create mode 100644 scudcloud-1.1/debian/control create mode 100644 scudcloud-1.1/debian/copyright create mode 100644 scudcloud-1.1/debian/install create mode 100755 scudcloud-1.1/debian/postinst create mode 100644 scudcloud-1.1/debian/postrm create mode 100644 scudcloud-1.1/debian/prerm create mode 100755 scudcloud-1.1/debian/rules create mode 100644 scudcloud-1.1/debian/scudcloud.links create mode 100644 scudcloud-1.1/leftpane-src.js create mode 100644 scudcloud-1.1/lib/cookiejar.py create mode 100644 scudcloud-1.1/lib/launcher.py create mode 100644 scudcloud-1.1/lib/leftpane.py create mode 100644 scudcloud-1.1/lib/notifier.py create mode 100644 scudcloud-1.1/lib/notify2.py create mode 100644 scudcloud-1.1/lib/resources.py create mode 100755 scudcloud-1.1/lib/scudcloud.py create mode 100644 scudcloud-1.1/lib/speller.py create mode 100644 scudcloud-1.1/lib/systray.py create mode 100644 scudcloud-1.1/lib/wrapper.py create mode 100644 scudcloud-1.1/resources/leftpane.html create mode 100644 scudcloud-1.1/resources/leftpane.js create mode 100644 scudcloud-1.1/resources/resources.css create mode 100644 scudcloud-1.1/resources/scudcloud.js create mode 100644 scudcloud-1.1/resources/scudcloud.png create mode 100755 scudcloud-1.1/scudcloud create mode 100644 scudcloud-1.1/scudcloud-src.js create mode 100644 scudcloud-1.1/scudcloud.desktop create mode 100644 scudcloud-1.1/scudcloud.spec create mode 100644 scudcloud-1.1/systray/hicolor/scudcloud-attention-1.svg create mode 100644 scudcloud-1.1/systray/hicolor/scudcloud-attention-2.svg create mode 100644 scudcloud-1.1/systray/hicolor/scudcloud-attention-3.svg create mode 100644 scudcloud-1.1/systray/hicolor/scudcloud-attention-4.svg create mode 100644 scudcloud-1.1/systray/hicolor/scudcloud-attention-5.svg create mode 100644 scudcloud-1.1/systray/hicolor/scudcloud-attention-6.svg create mode 100644 scudcloud-1.1/systray/hicolor/scudcloud-attention-7.svg create mode 100644 scudcloud-1.1/systray/hicolor/scudcloud-attention-8.svg create mode 100644 scudcloud-1.1/systray/hicolor/scudcloud-attention-9-plus.svg create mode 100644 scudcloud-1.1/systray/hicolor/scudcloud-attention-9.svg create mode 100644 scudcloud-1.1/systray/hicolor/scudcloud-attention.svg create mode 100644 scudcloud-1.1/systray/hicolor/scudcloud.svg create mode 100644 scudcloud-1.1/systray/mono-dark/scudcloud-attention-1.svg create mode 100644 scudcloud-1.1/systray/mono-dark/scudcloud-attention-2.svg create mode 100644 scudcloud-1.1/systray/mono-dark/scudcloud-attention-3.svg create mode 100644 scudcloud-1.1/systray/mono-dark/scudcloud-attention-4.svg create mode 100644 scudcloud-1.1/systray/mono-dark/scudcloud-attention-5.svg create mode 100644 scudcloud-1.1/systray/mono-dark/scudcloud-attention-6.svg create mode 100644 scudcloud-1.1/systray/mono-dark/scudcloud-attention-7.svg create mode 100644 scudcloud-1.1/systray/mono-dark/scudcloud-attention-8.svg create mode 100644 scudcloud-1.1/systray/mono-dark/scudcloud-attention-9-plus.svg create mode 100644 scudcloud-1.1/systray/mono-dark/scudcloud-attention-9.svg create mode 100644 scudcloud-1.1/systray/mono-dark/scudcloud-attention.svg create mode 100644 scudcloud-1.1/systray/mono-dark/scudcloud.svg create mode 100644 scudcloud-1.1/systray/mono-light/scudcloud-attention-1.svg create mode 100644 scudcloud-1.1/systray/mono-light/scudcloud-attention-2.svg create mode 100644 scudcloud-1.1/systray/mono-light/scudcloud-attention-3.svg create mode 100644 scudcloud-1.1/systray/mono-light/scudcloud-attention-4.svg create mode 100644 scudcloud-1.1/systray/mono-light/scudcloud-attention-5.svg create mode 100644 scudcloud-1.1/systray/mono-light/scudcloud-attention-6.svg create mode 100644 scudcloud-1.1/systray/mono-light/scudcloud-attention-7.svg create mode 100644 scudcloud-1.1/systray/mono-light/scudcloud-attention-8.svg create mode 100644 scudcloud-1.1/systray/mono-light/scudcloud-attention-9-plus.svg create mode 100644 scudcloud-1.1/systray/mono-light/scudcloud-attention-9.svg create mode 100644 scudcloud-1.1/systray/mono-light/scudcloud-attention.svg create mode 100644 scudcloud-1.1/systray/mono-light/scudcloud.svg diff --git a/README.md b/README.md index b0fc84e..546a8a0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ScudCloud - Linux Client for Slack -![ScudCloud Logo](/scudcloud-1.0/resources/scudcloud.png?raw=true "Scud clouds are low, ragged and wind-torn cloud fragments, usually not attached to the thunderstorm base. With the 'mother' cloud, the form of them together is like a chat balloon") +![ScudCloud Logo](/scudcloud-1.1/resources/scudcloud.png?raw=true "Scud clouds are low, ragged and wind-torn cloud fragments, usually not attached to the thunderstorm base. With the 'mother' cloud, the form of them together is like a chat balloon") ScudCloud is a **non official** open-source Linux (Debian, Ubuntu, Kubuntu, Mint, Arch, Fedora) desktop client for [Slack](http://slack.com). @@ -95,10 +95,10 @@ First, you'll need to install at least packages for `python3`, `python-qt4` (`qt Then run the below script: it'll download the code and install it: ```bash -wget https://github.com/raelgc/scudcloud/archive/v1.0.89.tar.gz -tar -xvf v1.0.89.tar.gz -cd scudcloud-1.0.89 -SOURCE="scudcloud-1.0" +wget https://github.com/raelgc/scudcloud/archive/v1.1.0.tar.gz +tar -xvf v1.1.0.tar.gz +cd scudcloud-1.1.0 +SOURCE="scudcloud-1.1" INSTALL="/opt/scudcloud" sudo mkdir -p $INSTALL/lib sudo mkdir -p $INSTALL/resources diff --git a/scudcloud-1.0/LICENSE b/scudcloud-1.0/LICENSE deleted file mode 100644 index 23fc66f..0000000 --- a/scudcloud-1.0/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Rael G.C. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/scudcloud-1.0/VERSION b/scudcloud-1.0/VERSION deleted file mode 100644 index 9d25b39..0000000 --- a/scudcloud-1.0/VERSION +++ /dev/null @@ -1 +0,0 @@ -1.0.89 diff --git a/scudcloud-1.0/debian/changelog b/scudcloud-1.0/debian/changelog deleted file mode 100644 index 6d666dc..0000000 --- a/scudcloud-1.0/debian/changelog +++ /dev/null @@ -1,676 +0,0 @@ -scudcloud (1.0-89) trusty; urgency=medium - - * Forgot to bump version - - -- Rael Gugelmin Cunha Sun, 01 Nov 2015 21:31:30 -0200 - -scudcloud (1.0-88) trusty; urgency=medium - - * Restoring wrapper timer to override notifications - - -- Rael Gugelmin Cunha Sun, 01 Nov 2015 10:27:18 -0200 - -scudcloud (1.0-87) trusty; urgency=medium - - * Re-enable desktop notifications on reconnect (#274) - - -- Rael Gugelmin Cunha Wed, 28 Oct 2015 08:47:13 -0200 - -scudcloud (1.0-86) trusty; urgency=medium - - * Set focus after switch teams (#268) - - -- Rael Gugelmin Cunha Sun, 25 Oct 2015 08:00:35 -0200 - -scudcloud (1.0-85) trusty; urgency=medium - - * Restore window when trying to run again (#66) - - -- Rael Gugelmin Cunha Wed, 21 Oct 2015 21:57:36 -0200 - -scudcloud (1.0-84) trusty; urgency=medium - - * Escape single quote on team icon (#264) - - -- Rael Gugelmin Cunha Sat, 17 Oct 2015 15:07:12 -0300 - -scudcloud (1.0-83) trusty; urgency=medium - - * Saving menubar state (#251) - - -- Rael Gugelmin Cunha Sat, 17 Oct 2015 07:42:55 -0300 - -scudcloud (1.0-82) trusty; urgency=medium - - * Escaping single quotes in leftpane JS (#258) - - -- Rael Gugelmin Cunha Thu, 15 Oct 2015 09:50:58 -0300 - -scudcloud (1.0-81) trusty; urgency=medium - - * Removing no more required libraries - * Updating Edit menu on team switch (#259) - - -- Rael Gugelmin Cunha Thu, 15 Oct 2015 07:23:25 -0300 - -scudcloud (1.0-80) trusty; urgency=medium - - * Small improvements - - -- Rael Gugelmin Cunha Thu, 15 Oct 2015 05:34:51 -0300 - -scudcloud (1.0-79) trusty; urgency=medium - - * Workaround for #250 - - -- Rael Gugelmin Cunha Mon, 12 Oct 2015 15:42:22 -0300 - -scudcloud (1.0-78) trusty; urgency=medium - - * Another attempt to minimize effects on reconnect scripts (#250) - - -- Rael Gugelmin Cunha Sat, 10 Oct 2015 21:25:51 -0300 - -scudcloud (1.0-77) trusty; urgency=medium - - * New attempt to fix suspend script (#250) - - -- Rael Gugelmin Cunha Fri, 09 Oct 2015 08:11:40 -0300 - -scudcloud (1.0-76) trusty; urgency=medium - - * Fixing resume from suspend script (#250) - - -- Rael Gugelmin Cunha Wed, 07 Oct 2015 07:45:15 -0300 - -scudcloud (1.0-75) trusty; urgency=medium - - * Fixing random team icon names (#249) - - -- Rael Gugelmin Cunha Mon, 05 Oct 2015 08:21:22 -0300 - -scudcloud (1.0-74) trusty; urgency=medium - - * Fixing fonts (#245) - - -- Rael Gugelmin Cunha Wed, 30 Sep 2015 23:15:13 -0300 - -scudcloud (1.0-73) trusty; urgency=medium - - * Make sure value returned by Speller.suggest is str (#244) - - -- Rael Gugelmin Cunha Wed, 30 Sep 2015 13:10:35 -0300 - -scudcloud (1.0-72) trusty; urgency=medium - - * Listening for resume event - - -- Rael Gugelmin Cunha Wed, 30 Sep 2015 09:01:13 -0300 - -scudcloud (1.0-71) trusty; urgency=medium - - * Fixing dictionary path checking (#241) - - -- Rael Gugelmin Cunha Tue, 29 Sep 2015 06:27:04 -0300 - -scudcloud (1.0-70) trusty; urgency=medium - - * Adding a timer to check server side reloads - * Allow the menubar to be hidden in non Unity environments (#233) - - -- Rael Gugelmin Cunha Fri, 25 Sep 2015 08:12:40 -0300 - -scudcloud (1.0-69) trusty; urgency=medium - - * Fixing crash when python3-hunspell is not present (#237) - - -- Rael Gugelmin Cunha Tue, 22 Sep 2015 19:54:47 -0300 - -scudcloud (1.0-68) trusty; urgency=medium - - * Adding HunSpell suggestions (#55) - - -- Rael Gugelmin Cunha Tue, 22 Sep 2015 16:30:14 -0300 - -scudcloud (1.0-67) trusty; urgency=medium - - * Fixing QuickList - - -- Rael Gugelmin Cunha Wed, 16 Sep 2015 20:37:26 -0300 - -scudcloud (1.0-66) trusty; urgency=medium - - * Adding team icon in notifications - * Trying to fix quicklist load on multiple teams - - -- Rael Gugelmin Cunha Wed, 16 Sep 2015 18:40:13 -0300 - -scudcloud (1.0-65) trusty; urgency=medium - - * Enabling Cache (#82) - - -- Rael Gugelmin Cunha Wed, 16 Sep 2015 10:01:59 -0300 - -scudcloud (1.0-64) trusty; urgency=medium - - * Several code improvements - * Fixing teams loading order (#201) - - -- Rael Gugelmin Cunha Fri, 11 Sep 2015 19:32:26 -0300 - -scudcloud (1.0-63) trusty; urgency=medium - - * Improving JS ScudCloud - * Small improvement in message counting - * Adding initial loading message in status bar (#158) - - -- Rael Gugelmin Cunha Tue, 08 Sep 2015 10:50:20 -0300 - -scudcloud (1.0-62) trusty; urgency=medium - - * Forgot to bump constant version before build package - - -- Rael Gugelmin Cunha Mon, 07 Sep 2015 14:28:57 -0300 - -scudcloud (1.0-61) trusty; urgency=medium - - * Add option to print version in command line (#186) - * Fixing 'Help and Feedback' and 'Help Center' on multiple teams - - -- Rael Gugelmin Cunha Mon, 07 Sep 2015 14:23:24 -0300 - -scudcloud (1.0-60) trusty; urgency=medium - - * Updating login.css - * Reducing JavaScript usage on channel switch - - -- Rael Gugelmin Cunha Mon, 07 Sep 2015 09:20:53 -0300 - -scudcloud (1.0-59) trusty; urgency=medium - - * Handling system interrupt signal (#199) - - -- Rael Gugelmin Cunha Thu, 03 Sep 2015 13:56:25 -0300 - -scudcloud (1.0-58) trusty; urgency=medium - - * Trying to re-enable notifications on page reload - - -- Rael Gugelmin Cunha Wed, 02 Sep 2015 16:45:09 -0300 - -scudcloud (1.0-57) trusty; urgency=medium - - * Ctrl+Tab and Ctrl+Shift+Tab to rotate through teams (#215) - - -- Rael Gugelmin Cunha Thu, 27 Aug 2015 09:46:05 -0300 - -scudcloud (1.0-56) trusty; urgency=medium - - * Allow relative path - * Re-enable desktop notifications on page reload (#163) - - -- Rael Gugelmin Cunha Thu, 13 Aug 2015 08:39:03 -0300 - -scudcloud (1.0-55) trusty; urgency=medium - - * Fixing notifications systray count (#192) - - -- Rael Gugelmin Cunha Thu, 06 Aug 2015 11:18:25 -0300 - -scudcloud (1.0-54) trusty; urgency=medium - - * Updating notifications to match Slack changes - - -- Rael Gugelmin Cunha Wed, 05 Aug 2015 11:02:58 -0300 - -scudcloud (1.0-53) trusty; urgency=medium - - * Fixing notifications count again (#164) - - -- Rael Gugelmin Cunha Sun, 02 Aug 2015 22:10:56 -0300 - -scudcloud (1.0-52) trusty; urgency=medium - - * Fixing code format error - - -- Rael Gugelmin Cunha Sun, 26 Jul 2015 00:14:59 -0300 - -scudcloud (1.0-51) trusty; urgency=medium - - * Using lambdas for dereferenced callbacks (fixes #170 #177) - * Updating unread counter on window focus - - -- Rael Gugelmin Cunha Sat, 25 Jul 2015 23:58:20 -0300 - -scudcloud (1.0-50) trusty; urgency=medium - - * Fixing quicklist and direct messages - - -- Rael Gugelmin Cunha Thu, 25 Jun 2015 14:45:00 -0300 - -scudcloud (1.0-49) trusty; urgency=medium - - * Update read messages (#164) - - -- Rael Gugelmin Cunha Wed, 24 Jun 2015 10:56:18 -0300 - -scudcloud (1.0-48) trusty; urgency=medium - - * Few changes to avoid loose desktop notifications - - -- Rael Gugelmin Cunha Tue, 23 Jun 2015 18:25:15 -0300 - -scudcloud (1.0-47) trusty; urgency=medium - - * Re-working notifications to not use a timer (reduces CPU usage) - - -- Rael Gugelmin Cunha Tue, 23 Jun 2015 13:51:29 -0300 - -scudcloud (1.0-46) trusty; urgency=medium - - * Making current team icon bigger - * Fixing integrations issues (#143) - * Adding option to disable plugins (#155) - - -- Rael Gugelmin Cunha Fri, 19 Jun 2015 11:33:22 -0300 - -scudcloud (1.0-45) trusty; urgency=medium - - * Fixing small issues while loading all teams - - -- Rael Gugelmin Cunha Thu, 18 Jun 2015 11:38:29 -0300 - -scudcloud (1.0-44) trusty; urgency=medium - - * Fixing fullscreen - - -- Rael Gugelmin Cunha Thu, 18 Jun 2015 10:16:09 -0300 - -scudcloud (1.0-43) trusty; urgency=medium - - * Restoring JS inception in all pages - - -- Rael Gugelmin Cunha Thu, 18 Jun 2015 10:02:39 -0300 - -scudcloud (1.0-42) trusty; urgency=medium - - * Auto login for multiple teams (#81) - * Some code improvements - - -- Rael Gugelmin Cunha Thu, 18 Jun 2015 09:13:11 -0300 - -scudcloud (1.0-41) trusty; urgency=medium - - * Adding FullScreen support (#129) - * Fixing stuck on Status (#147) - - -- Rael Gugelmin Cunha Wed, 17 Jun 2015 11:22:45 -0300 - -scudcloud (1.0-40) trusty; urgency=medium - - * Fixing first team icon - * Snippet support (#124) - - -- Rael Gugelmin Cunha Tue, 16 Jun 2015 15:08:05 -0300 - -scudcloud (1.0-39) trusty; urgency=medium - - * Proxy support (#102, #115) - - -- Rael Gugelmin Cunha Tue, 16 Jun 2015 07:52:52 -0300 - -scudcloud (1.0-38) trusty; urgency=low - - * Fixing preferences with multiple teams (#125) - * Enabling cache and storage (#82) - - -- Rael Gugelmin Cunha Wed, 10 Jun 2015 11:53:42 -0300 - -scudcloud (1.0-37) trusty; urgency=low - - * Add the option to start minized to tray (#122) - - -- Rael Gugelmin Cunha Sat, 30 May 2015 09:39:39 -0300 - -scudcloud (1.0-36) trusty; urgency=low - - * Fixing desktop file keywords - - -- Rael Gugelmin Cunha Thu, 21 May 2015 09:10:30 -0300 - -scudcloud (1.0-35) trusty; urgency=low - - * Fixing tray icon in KDE5 (#106) - - -- Rael Gugelmin Cunha Thu, 14 May 2015 12:38:13 -0300 - -scudcloud (1.0-34) trusty; urgency=low - - * Fixing categories (#107) - - -- Rael Gugelmin Cunha Thu, 14 May 2015 08:56:15 -0300 - -scudcloud (1.0-33) trusty; urgency=low - - * Fixing zoom for multiple teams (#103) - - -- Rael Gugelmin Cunha Tue, 12 May 2015 13:28:42 -0300 - -scudcloud (1.0-32) trusty; urgency=low - - * Restoring notification override in DOM ready; - - -- Rael Gugelmin Cunha Sat, 09 May 2015 16:01:13 -0300 - -scudcloud (1.0-31) trusty; urgency=low - - * Trying improve performance a bit - - -- Rael Gugelmin Cunha Fri, 08 May 2015 10:29:29 -0300 - -scudcloud (1.0-30) trusty; urgency=low - - * Better close shortcut behaviour (#70) - - -- Rael Gugelmin Cunha Sat, 02 May 2015 09:29:12 -0300 - -scudcloud (1.0-29) trusty; urgency=low - - * Improved notifications (#93) - - -- Rael Gugelmin Cunha Fri, 01 May 2015 19:27:17 -0300 - -scudcloud (1.0-28) trusty; urgency=low - - * Adding close shortcut (#70) - * Fixing URL whitelist regexp (#88) - - -- Rael Gugelmin Cunha Thu, 30 Apr 2015 15:06:10 -0300 - -scudcloud (1.0-27) trusty; urgency=low - - * Fixing Archives (#60) - * Optional notifications (#72) - * XDG config file (#73,#78) - * Team Icons (#80) - - -- Rael Gugelmin Cunha Sat, 25 Apr 2015 09:14:34 -0300 - -scudcloud (1.0-26) trusty; urgency=low - - * Saving last window settings (#49) - - -- Rael Gugelmin Cunha Sat, 04 Apr 2015 22:21:45 -0300 - -scudcloud (1.0-25) trusty; urgency=medium - - * SAML auth support (#44) - - -- Rael Gugelmin Cunha Tue, 31 Mar 2015 20:35:12 -0300 - -scudcloud (1.0-24) trusty; urgency=low - - * Enabling team switch at ctrl+ (#43) - - -- Rael Gugelmin Cunha Mon, 30 Mar 2015 08:53:19 -0300 - -scudcloud (1.0-23) trusty; urgency=medium - - * Applying same fix from #41 to LeftPane.alert - - -- Rael Gugelmin Cunha Mon, 23 Mar 2015 14:11:56 -0300 - -scudcloud (1.0-22) trusty; urgency=medium - - * Fixing LeftPane.stopAlert (#41) - - -- Rael Gugelmin Cunha Mon, 23 Mar 2015 08:03:03 -0300 - -scudcloud (1.0-21) trusty; urgency=low - - * Notification append(#38) - * Recommending fixed width font(#39) - * Mention notification on team switcher (#40) - - -- Rael Gugelmin Cunha Fri, 20 Mar 2015 20:44:25 -0300 - -scudcloud (1.0-20) trusty; urgency=low - - * Zoom(#30), better dependencies(#32), proper cleanup(#34), app icon(#35) - - -- Rael Gugelmin Cunha Wed, 18 Mar 2015 09:29:34 -0300 - -scudcloud (1.0-19) trusty; urgency=low - - * Fixing Notification JS error (#33) - - -- Rael Gugelmin Cunha Mon, 16 Mar 2015 16:28:59 -0300 - -scudcloud (1.0-18) trusty; urgency=low - - * Trying to override notifications on re-connect - - -- Rael Gugelmin Cunha Mon, 16 Mar 2015 08:47:27 -0300 - -scudcloud (1.0-17) trusty; urgency=low - - * Decoupling dependencies to make it work on Debian (#27) - - -- Rael Gugelmin Cunha Sun, 15 Mar 2015 15:17:30 -0300 - -scudcloud (1.0-16) trusty; urgency=low - - * Fixing startup error on minified JS - - -- Rael Gugelmin Cunha Fri, 13 Mar 2015 22:55:15 -0300 - -scudcloud (1.0-15) trusty; urgency=low - - * Trying speedup JS loading (#26) - - -- Rael Gugelmin Cunha Thu, 12 Mar 2015 17:20:02 -0300 - -scudcloud (1.0-14) trusty; urgency=low - - * Adding count to systray (#16) - - -- Rael Gugelmin Cunha Thu, 12 Mar 2015 10:33:49 -0300 - -scudcloud (1.0-13) trusty; urgency=low - - * Adding gir1.2-unity-5.0 as dependency (#24) - - -- Rael Gugelmin Cunha Wed, 11 Mar 2015 18:34:41 -0300 - -scudcloud (1.0-12) trusty; urgency=low - - * Fixing eventFilter - - -- Rael Gugelmin Cunha Wed, 11 Mar 2015 11:49:15 -0300 - -scudcloud (1.0-11) trusty; urgency=low - - * Fixing alert - - -- Rael Gugelmin Cunha Wed, 11 Mar 2015 11:20:25 -0300 - -scudcloud (1.0-10) trusty; urgency=low - - * Preventing steal focus (#22) and alert on new notifications (#23) - - -- Rael Gugelmin Cunha Wed, 11 Mar 2015 09:58:49 -0300 - -scudcloud (1.0-9) trusty; urgency=low - - * Improving Systray clicking (#17) - - -- Rael Gugelmin Cunha Tue, 10 Mar 2015 10:41:34 -0300 - -scudcloud (1.0-8) trusty; urgency=low - - * Adding missing file (qsingleapplication.py) - - -- Rael Gugelmin Cunha Tue, 10 Mar 2015 09:28:51 -0300 - -scudcloud (1.0-7) trusty; urgency=low - - * Multiple teams (#6); Improving support to Precise (#20) - - -- Rael Gugelmin Cunha Tue, 10 Mar 2015 08:53:58 -0300 - -scudcloud (1.0-6) trusty; urgency=low - - * Support for leff-clicks to restore/hide the tray icon (#17) - - -- Rael Gugelmin Cunha Fri, 06 Mar 2015 12:51:49 -0300 - -scudcloud (1.0-5) trusty; urgency=low - - * Close to Tray (#14) - - -- Rael Gugelmin Cunha Wed, 04 Mar 2015 22:32:09 -0300 - -scudcloud (1.0-4) trusty; urgency=low - - * Removing compiled files from package source (#13) - - -- Rael Gugelmin Cunha Wed, 04 Mar 2015 10:55:30 -0300 - -scudcloud (1.0-3) trusty; urgency=low - - * Adding support to other DEs (#12) - - -- Rael Gugelmin Cunha Wed, 04 Mar 2015 09:32:56 -0300 - -scudcloud (1.0-2) trusty; urgency=low - - * Fixing tray icon paths - - -- Rael Gugelmin Cunha Tue, 03 Mar 2015 18:31:44 -0300 - -scudcloud (1.0-1) trusty; urgency=low - - * Adding tray icon (#8) - - -- Rael Gugelmin Cunha Tue, 03 Mar 2015 13:19:01 -0300 - -scudcloud (0.9-20) trusty; urgency=low - - * Adding lato font (#11) - - -- Rael Gugelmin Cunha Sat, 28 Feb 2015 10:22:36 -0300 - -scudcloud (0.9-19) trusty; urgency=low - - * Adding spell checker (#9) - - -- Rael Gugelmin Cunha Fri, 27 Feb 2015 10:54:20 -0300 - -scudcloud (0.9-18) trusty; urgency=low - - * Fixing support for Google Authentication (#10) - - -- Rael Gugelmin Cunha Thu, 26 Feb 2015 21:24:38 -0300 - -scudcloud (0.9-17) trusty; urgency=low - - * Menus were not enabled after change channel - - -- Rael Gugelmin Cunha Wed, 25 Feb 2015 14:22:03 -0300 - -scudcloud (0.9-16) trusty; urgency=low - - * Adding window menus (#7) - - -- Rael Gugelmin Cunha Wed, 25 Feb 2015 09:25:49 -0300 - -scudcloud (0.9-15) trusty; urgency=low - - * Simple team switcher (#6) - - -- Rael Gugelmin Cunha Wed, 18 Feb 2015 22:56:05 -0200 - -scudcloud (0.9-14) trusty; urgency=low - - * Removing "New message in " from channel notification - - -- Rael Gugelmin Cunha Wed, 18 Feb 2015 19:32:50 -0200 - -scudcloud (0.9-13) trusty; urgency=low - - * Fixing channels quicklist (#5) - - -- Rael Gugelmin Cunha Wed, 18 Feb 2015 14:36:22 -0200 - -scudcloud (0.9-12) trusty; urgency=low - - * Adding webkit debug console option - - -- Rael Gugelmin Cunha Wed, 18 Feb 2015 11:42:21 -0200 - -scudcloud (0.9-11) trusty; urgency=low - - * Fixing package build after file renaming - - -- Rael Gugelmin Cunha Tue, 17 Feb 2015 18:48:29 -0200 - -scudcloud (0.9-10) trusty; urgency=low - - * Simple internal changes - - -- Rael Gugelmin Cunha Tue, 17 Feb 2015 18:43:23 -0200 - -scudcloud (0.9-9) trusty; urgency=low - - * Copy and paste images (#4) - - -- Rael Gugelmin Cunha Tue, 17 Feb 2015 16:58:09 -0200 - -scudcloud (0.9-8) trusty; urgency=low - - * Improving first signign (#3) - - -- Rael Gugelmin Cunha Sat, 14 Feb 2015 22:42:07 -0200 - -scudcloud (0.9-7) trusty; urgency=low - - * Adding # before channel name in quicklist - - -- Rael Gugelmin Cunha Thu, 12 Feb 2015 11:18:53 -0200 - -scudcloud (0.9-6) trusty; urgency=low - - * Quicklist for channels (#2); - - -- Rael Gugelmin Cunha Thu, 12 Feb 2015 10:29:22 -0200 - -scudcloud (0.9-5) trusty; urgency=low - - * Improving .desktop file - - -- Rael Gugelmin Cunha Wed, 11 Feb 2015 10:04:11 -0200 - -scudcloud (0.9-4) trusty; urgency=low - - * Open links in system browser (#1); Enabling clipboard access - - -- Rael Gugelmin Cunha Tue, 10 Feb 2015 21:40:10 -0200 - -scudcloud (0.9-3) trusty; urgency=low - - * Adding a wrapper to .pyc when python3 mime-type is not configured - - -- Rael Gugelmin Cunha Mon, 09 Feb 2015 22:10:01 -0200 - -scudcloud (0.9-2) trusty; urgency=low - - * Adding check for null cookies (usually at the first start) - - -- Rael Gugelmin Cunha Mon, 09 Feb 2015 20:56:26 -0200 - -scudcloud (0.9-1) trusty; urgency=low - - * Initial release - - -- Rael Gugelmin Cunha Mon, 09 Feb 2015 19:12:26 -0200 - diff --git a/scudcloud-1.0/debian/compat b/scudcloud-1.0/debian/compat deleted file mode 100644 index ec63514..0000000 --- a/scudcloud-1.0/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/scudcloud-1.0/debian/control b/scudcloud-1.0/debian/control deleted file mode 100644 index d25cae5..0000000 --- a/scudcloud-1.0/debian/control +++ /dev/null @@ -1,26 +0,0 @@ -Source: scudcloud -Section: utils -Priority: optional -Maintainer: Rael Gugelmin Cunha -Build-Depends: debhelper (>= 9) -Standards-Version: 3.9.5 -Homepage: https://github.com/raelgc/scudcloud - -Package: scudcloud -Architecture: all -Depends: libqtwebkit4 (>= 2.3.2), - python3, - python3-dbus, - python3-pyqt4, - xdg-utils, - ${misc:Depends} -Recommends: sni-qt, - fonts-lato, - gir1.2-unity-5.0, - libqtwebkit-qupzillaplugins, - python3-hunspell, - python3-gi, - ttf-mscorefonts-installer -Description: ScudCloud is a non official desktop client for Slack - ScudCloud is a non official desktop client for Slack. - Slack (http://slack.com) is a platform for team communication. diff --git a/scudcloud-1.0/debian/copyright b/scudcloud-1.0/debian/copyright deleted file mode 100644 index e7d7564..0000000 --- a/scudcloud-1.0/debian/copyright +++ /dev/null @@ -1,30 +0,0 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: scudcloud -Source: https://github.com/raelgc/scudcloud - -Files: * -Copyright: 2015 Rael Gugelmin Cunha -License: MIT - -Files: debian/* -Copyright: 2015 Rael Gugelmin Cunha -License: MIT - -License: MIT - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - . - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/scudcloud-1.0/debian/install b/scudcloud-1.0/debian/install deleted file mode 100644 index aa6e8be..0000000 --- a/scudcloud-1.0/debian/install +++ /dev/null @@ -1,9 +0,0 @@ -LICENSE opt/scudcloud -VERSION opt/scudcloud -lib/*.py opt/scudcloud/lib -resources/* opt/scudcloud/resources -scudcloud opt/scudcloud -scudcloud.desktop usr/share/applications -systray/hicolor/* usr/share/icons/hicolor/scalable/apps -systray/mono-dark/* usr/share/icons/ubuntu-mono-dark/scalable/apps -systray/mono-light/* usr/share/icons/ubuntu-mono-light/scalable/apps diff --git a/scudcloud-1.0/debian/postinst b/scudcloud-1.0/debian/postinst deleted file mode 100755 index 6a8ffa7..0000000 --- a/scudcloud-1.0/debian/postinst +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh -# postinst script for scudcloud -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `configure' -# * `abort-upgrade' -# * `abort-remove' `in-favour' -# -# * `abort-remove' -# * `abort-deconfigure' `in-favour' -# `removing' -# -# for details, see http://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - configure) - python3 -m compileall /opt/scudcloud/lib/ - ;; - - abort-upgrade|abort-remove|abort-deconfigure) - ;; - - *) - echo "postinst called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 - diff --git a/scudcloud-1.0/debian/postrm b/scudcloud-1.0/debian/postrm deleted file mode 100644 index 1ad8f31..0000000 --- a/scudcloud-1.0/debian/postrm +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh -# postrm script for scudcloud -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `purge' -# * `upgrade' -# * `failed-upgrade' -# * `abort-install' -# * `abort-install' -# * `abort-upgrade' -# * `disappear' -# -# for details, see http://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) - xdg-icon-resource forceupdate - ;; - - *) - echo "postrm called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 - diff --git a/scudcloud-1.0/debian/prerm b/scudcloud-1.0/debian/prerm deleted file mode 100644 index ff915b2..0000000 --- a/scudcloud-1.0/debian/prerm +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh -# prerm script for scudcloud -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `upgrade' -# * `failed-upgrade' -# * `remove' `in-favour' -# * `deconfigure' `in-favour' -# `removing' -# -# for details, see http://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - remove|upgrade|deconfigure) - rm -Rf /opt/scudcloud/lib/__pycache__ - ;; - - failed-upgrade) - ;; - - *) - echo "prerm called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff --git a/scudcloud-1.0/debian/rules b/scudcloud-1.0/debian/rules deleted file mode 100755 index 79fd842..0000000 --- a/scudcloud-1.0/debian/rules +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/make -f -# -*- makefile -*- - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -%: - dh $@ diff --git a/scudcloud-1.0/debian/scudcloud.links b/scudcloud-1.0/debian/scudcloud.links deleted file mode 100644 index f8078d1..0000000 --- a/scudcloud-1.0/debian/scudcloud.links +++ /dev/null @@ -1 +0,0 @@ -/opt/scudcloud/scudcloud /usr/bin/scudcloud diff --git a/scudcloud-1.0/leftpane-src.js b/scudcloud-1.0/leftpane-src.js deleted file mode 100644 index 5e735a6..0000000 --- a/scudcloud-1.0/leftpane-src.js +++ /dev/null @@ -1,68 +0,0 @@ -var LeftPane = { - addTeam: function(id, name, url, icon, active){ - var node = document.getElementById(id); - if(node === null){ - var ul = document.getElementById('teams'); - li = document.createElement('li'); - li.id = id; - li.setAttribute("onclick", "LeftPane.switchTo('"+id.replace(/'/g, '"')+"','"+url.replace(/'/g, '"')+"')"); - li.setAttribute("title", name); - li.innerHTML = name[0]; - if( icon ){ - li.style.backgroundImage = "url('"+ icon.replace(/'/g, '"') +"')"; - li.innerHTML = ""; - } - ul.appendChild(li); - if(active){ - LeftPane.setActive(id); - } - LeftPane.switchTo(id, url); - } - }, - click: function(i){ - var list = document.getElementsByTagName("li"); - for(var j=0; j < list.length; j++){ - if(i==j){ - list[j].click(); - break; - } - } - }, - alert: function(team){ - document.getElementById(team).classList.add('alert'); - }, - stopAlert: function(team){ - document.getElementById(team).classList.remove('alert'); - }, - switchTo: function(id, url){ - leftPane.switchTo(url); - LeftPane.setActive(id); - }, - setActive: function(id){ - var list = document.getElementsByTagName("li"); - for(var i=0; i < list.length; i++){ - list[i].className = "inactive"; - } - document.getElementById(id).className = "active"; - }, - clickNext: function(direction){ - var list = document.getElementsByTagName("li"); - - var index = 0; - for(; index < list.length; index++){ - if (list[index].className == "active") { - break; - } - } - - index += direction; //goto next one - if (index >= list.length) { - index = 0; - } else if (index < 0) { - index = list.length - 1; - } - - LeftPane.click(index); - } -}; - diff --git a/scudcloud-1.0/lib/cookiejar.py b/scudcloud-1.0/lib/cookiejar.py deleted file mode 100644 index bd355f2..0000000 --- a/scudcloud-1.0/lib/cookiejar.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python3 -from PyQt4 import QtCore, QtNetwork - -class PersistentCookieJar(QtNetwork.QNetworkCookieJar): - - def __init__(self, parent): - super(PersistentCookieJar, self).__init__(parent) - self.mainWindow = parent - self.load() - self.save() - - def save(self): - listCookies = self.allCookies() - data = QtCore.QByteArray() - for cookie in listCookies: - if not cookie.isSessionCookie(): - data.append(cookie.toRawForm()+ "\n") - self.mainWindow.settings.setValue("Cookies",data) - - def load(self): - data = self.mainWindow.settings.value("Cookies") - if data is not None: - self.setAllCookies(QtNetwork.QNetworkCookie.parseCookies(data)) - diff --git a/scudcloud-1.0/lib/launcher.py b/scudcloud-1.0/lib/launcher.py deleted file mode 100644 index 8ab23cf..0000000 --- a/scudcloud-1.0/lib/launcher.py +++ /dev/null @@ -1,7 +0,0 @@ -from PyQt4.Qt import QApplication - -class DummyLauncher: - def __init__(self, parent): - self.parent = parent - def set_property(self, name, value): - pass diff --git a/scudcloud-1.0/lib/leftpane.py b/scudcloud-1.0/lib/leftpane.py deleted file mode 100644 index b2986c8..0000000 --- a/scudcloud-1.0/lib/leftpane.py +++ /dev/null @@ -1,60 +0,0 @@ -from resources import Resources -from PyQt4 import QtCore -from PyQt4.QtCore import QUrl -from PyQt4.QtWebKit import QWebView, QWebSettings - -class LeftPane(QWebView): - - def __init__(self, window): - QWebView.__init__(self) - self.window = window - with open(Resources.get_path("leftpane.js"), "r") as f: - self.js = f.read() - # We don't want plugins for this simple pane - self.settings().setAttribute(QWebSettings.PluginsEnabled, False) - self.reset() - - def reset(self): - self.setFixedWidth(0) - self.setVisible(False) - self.setUrl(QUrl.fromLocalFile(Resources.get_path("leftpane.html"))) - self.page().currentFrame().addToJavaScriptWindowObject("leftPane", self) - self.page().currentFrame().evaluateJavaScript(self.js) - - def show(self): - self.setFixedWidth(65) - self.setVisible(True) - - def hide(self): - self.setFixedWidth(0) - self.setVisible(False) - - def addTeam(self, id, name, url, icon, active=False): - if active is True: - checked = "true" - else: - checked = "false" - self.page().currentFrame().evaluateJavaScript("LeftPane.addTeam('"+id+"','"+name+"','"+url+"','"+icon+"',"+checked+");") - - def click(self, i): - self.page().currentFrame().evaluateJavaScript("LeftPane.click("+str(i)+");") - - def alert(self, team): - if team is not None: - self.page().currentFrame().evaluateJavaScript("LeftPane.alert('"+team+"');") - - def stopAlert(self, team): - if team is not None: - self.page().currentFrame().evaluateJavaScript("LeftPane.stopAlert('"+team+"');") - - def clickNext(self, direction): - self.page().currentFrame().evaluateJavaScript("LeftPane.clickNext("+str(direction)+");") - - @QtCore.pyqtSlot(str) - def switchTo(self, url): - self.window.switchTo(url) - - def contextMenuEvent(self, event): - pass - - diff --git a/scudcloud-1.0/lib/notifier.py b/scudcloud-1.0/lib/notifier.py deleted file mode 100644 index a67ef5c..0000000 --- a/scudcloud-1.0/lib/notifier.py +++ /dev/null @@ -1,35 +0,0 @@ -from dbus.exceptions import DBusException -try: - from gi.repository import Notify -except ImportError: - import notify2 - Notify = None - -class Notifier(object): - - def __init__(self, app_name, icon): - self.icon = icon - try: - if Notify is not None: - Notify.init(app_name) - self.notifier = Notify - else: - notify2.init(app_name) - self.notifier = notify2 - self.enabled = True - except DBusException: - print("WARNING: No notification daemon found! " - "Notifications will be ignored.") - self.enabled = False - - def notify(self, title, message, icon=None): - if not self.enabled: - return - if icon is None: - icon = self.icon - if Notify is not None: - notice = self.notifier.Notification.new(title, message, icon) - else: - notice = notify2.Notification(title, message, icon) - notice.set_hint_string('x-canonical-append', '') - notice.show() diff --git a/scudcloud-1.0/lib/notify2.py b/scudcloud-1.0/lib/notify2.py deleted file mode 100644 index 1b40269..0000000 --- a/scudcloud-1.0/lib/notify2.py +++ /dev/null @@ -1,342 +0,0 @@ -"""This is a pure-python replacement for notify-python, using python-dbus -to communicate with the notifications server directly. It's compatible with -Python 2 and 3, and its callbacks can work with Gtk 3 or Qt 4 applications. - -To use it, first call ``notify2.init('app name')``, then create and show notifications:: - - n = notify2.Notification("Summary", - "Some body text", - "notification-message-im" # Icon name - ) - n.show() - -To see more of what's possible, refer to docstrings of methods and objects. - -Based on the notifications spec at: -http://developer.gnome.org/notification-spec/ - -Porting applications from pynotify ----------------------------------- - -There are a few differences from pynotify you should be aware of: - -- If you need callbacks from notifications, notify2 must know about your event - loop. The simplest way is to pass 'glib' or 'qt' as the ``mainloop`` parameter - to ``init``. -- The methods ``attach_to_widget`` and ``attach_to_status_icon`` are not - implemented. You can calculate the location you want the notification to - appear and call ``Notification``. -- ``set_property`` and ``get_property`` are not implemented. The summary, body - and icon are accessible as attributes of a ``Notification`` instance. -- Various methods that pynotify Notification instances got from gobject do not - exist, or only implement part of the functionality. - -Several pynotify functions, especially getters and setters, are only supported -for compatibility. You are encouraged to use more direct, Pythonic alternatives. -""" - -import dbus - -# Constants -EXPIRES_DEFAULT = -1 -EXPIRES_NEVER = 0 - -URGENCY_LOW = 0 -URGENCY_NORMAL = 1 -URGENCY_CRITICAL = 2 -urgency_levels = [URGENCY_LOW, URGENCY_NORMAL, URGENCY_CRITICAL] - -# Initialise the module (following pynotify's API) ----------------------------- - -initted = False -appname = "" -_have_mainloop = False - -class UninittedError(RuntimeError): - pass - -class UninittedDbusObj(object): - def __getattr__(self, name): - raise UninittedError("You must call notify2.init() before using the " - "notification features.") - -dbus_iface = UninittedDbusObj() - -def init(app_name, mainloop=None): - """Initialise the Dbus connection. - - To get callbacks from notifications, DBus must be integrated with a mainloop. - There are three ways to achieve this: - - - Set a default mainloop (dbus.set_default_main_loop) before calling init() - - Pass the mainloop parameter as a string 'glib' or 'qt' to integrate with - those mainloops. (N.B. passing 'qt' currently makes that the default dbus - mainloop, because that's the only way it seems to work.) - - Pass the mainloop parameter a DBus compatible mainloop instance, such as - dbus.mainloop.glib.DBusGMainLoop(). - - If you only want to display notifications, without receiving information - back from them, you can safely omit mainloop. - """ - global appname, initted, dbus_iface, _have_mainloop - - if mainloop == 'glib': - from dbus.mainloop.glib import DBusGMainLoop - mainloop = DBusGMainLoop() - elif mainloop == 'qt': - from dbus.mainloop.qt import DBusQtMainLoop - # For some reason, this only works if we make it the default mainloop - # for dbus. That might make life tricky for anyone trying to juggle two - # event loops, but I can't see any way round it. - mainloop = DBusQtMainLoop(set_as_default=True) - - bus = dbus.SessionBus(mainloop=mainloop) - - dbus_obj = bus.get_object('org.freedesktop.Notifications', - '/org/freedesktop/Notifications') - dbus_iface = dbus.Interface(dbus_obj, - dbus_interface='org.freedesktop.Notifications') - appname = app_name - initted = True - - if mainloop or dbus.get_default_main_loop(): - _have_mainloop = True - dbus_iface.connect_to_signal('ActionInvoked', _action_callback) - dbus_iface.connect_to_signal('NotificationClosed', _closed_callback) - - return True - -def is_initted(): - """Has init() been called? Only exists for compatibility with pynotify. - """ - return initted - -def get_app_name(): - """Return appname. Only exists for compatibility with pynotify. - """ - return appname - -def uninit(): - """Undo what init() does.""" - global initted, dbus_iface, _have_mainloop - initted = False - _have_mainloop = False - dbus_iface = UninittedDbusObj() - -# Retrieve basic server information -------------------------------------------- - -def get_server_caps(): - """Get a list of server capabilities. - """ - return [str(x) for x in dbus_iface.GetCapabilities()] - -def get_server_info(): - """Get basic information about the server. - """ - res = dbus_iface.GetServerInformation() - return {'name': str(res[0]), - 'vendor': str(res[1]), - 'version': str(res[2]), - 'spec-version': str(res[3]), - } - -# Action callbacks ------------------------------------------------------------- - -notifications_registry = {} - -def _action_callback(nid, action): - nid, action = int(nid), str(action) - n = notifications_registry[nid] - n._action_callback(action) - -def _closed_callback(nid, reason): - nid, reason = int(nid), int(reason) - n = notifications_registry[nid] - n._closed_callback(n) - del notifications_registry[nid] - -def no_op(*args): - """No-op function for callbacks. - """ - pass - -# Controlling notifications ---------------------------------------------------- - -class Notification(object): - id = 0 - timeout = -1 # -1 = server default settings - _closed_callback = no_op - - def __init__(self, summary, message='', icon=''): - self.summary = summary - self.message = message - self.icon = icon - self.hints = {} - self.actions = {} - self.data = {} # Any data the user wants to attach - - def show(self): - """Ask the server to show the notification. - """ - nid = dbus_iface.Notify(appname, # app_name (spec names) - self.id, # replaces_id - self.icon, # app_icon - self.summary, # summary - self.message, # body - self._make_actions_array(), # actions - self.hints, # hints - self.timeout, # expire_timeout - ) - - self.id = int(nid) - - if _have_mainloop: - notifications_registry[self.id] = self - return True - - def update(self, summary, message="", icon=None): - """Replace the summary and body of the notification, and optionally its - icon. You should call show() again after this to display the updated - notification. - """ - self.summary = summary - self.message = message - if icon is not None: - self.icon = icon - - def close(self): - """Ask the server to close this notification. - """ - if self.id != 0: - dbus_iface.CloseNotification(self.id) - - def set_hint(self, key, value): - """n.set_hint(key, value) <--> n.hints[key] = value - - Only exists for compatibility with pynotify. - """ - self.hints[key] = value - - set_hint_string = set_hint_int32 = set_hint_double = set_hint - - def set_hint_byte(self, key, value): - """Set a hint with a dbus byte value. The input value can be an - integer or a bytes string of length 1. - """ - self.hints[key] = dbus.Byte(value) - - def set_urgency(self, level): - """Set the urgency level to one of URGENCY_LOW, URGENCY_NORMAL or - URGENCY_CRITICAL. - """ - if level not in urgency_levels: - raise ValueError("Unknown urgency level specified", level) - self.set_hint_byte("urgency", level) - - def set_category(self, category): - """Set the 'category' hint for this notification. - """ - self.hints['category'] = category - - def set_timeout(self, timeout): - """Set the display duration in milliseconds, or one of the special - values EXPIRES_DEFAULT or EXPIRES_NEVER. - - Only exists for compatibility with pynotify; you can simply set:: - - n.timeout = 5000 - """ - if not isinstance(timeout, int): - raise TypeError("timeout value was not int", timeout) - self.timeout = timeout - - def get_timeout(self): - """Return the timeout value for this notification. - - Only exists for compatibility with pynotify; you can inspect the - timeout attribute directly. - """ - return self.timeout - - def add_action(self, action, label, callback, user_data=None): - """Add an action to the notification (if the server supports it). - - action : str - A brief key. - label : str - The text displayed on the action button - callback : callable - A function taking at 2-3 parameters: the Notification object, the - action key and (if specified) the user_data. - user_data : - An extra argument to pass to the callback. - """ - self.actions[action] = (label, callback, user_data) - - def _make_actions_array(self): - """Make the actions array to send over DBus. - """ - arr = [] - for action, (label, callback, user_data) in self.actions.items(): - arr.append(action) - arr.append(label) - return arr - - def _action_callback(self, action): - """Called when the user selects an action on the notification, to - dispatch it to the relevant user-specified callback. - """ - try: - label, callback, user_data = self.actions[action] - except KeyError: - return - - if user_data is None: - callback(self, action) - else: - callback(self, action, user_data) - - def connect(self, event, callback): - """Set the callback for the notification closing; the only valid value - for event is 'closed'. The API is compatible with pynotify. - """ - if event != 'closed': - raise ValueError("'closed' is the only valid value for event", event) - self._closed_callback = callback - - def set_data(self, key, value): - """n.set_data(key, value) <--> n.data[key] = value - - Only exists for compatibility with pynotify. - """ - self.data[key] = value - - def get_data(self, key): - """n.get_data(key) <--> n.data[key] - - Only exists for compatibility with pynotify. - """ - return self.data[key] - - def set_icon_from_pixbuf(self, icon): - """Set a custom icon from a GdkPixbuf. - """ - struct = ( - icon.get_width(), - icon.get_height(), - icon.get_rowstride(), - icon.get_has_alpha(), - icon.get_bits_per_sample(), - icon.get_n_channels(), - dbus.ByteArray(icon.get_pixels()) - ) - self.hints['icon_data'] = struct - - def set_location(self, x, y): - """Set the notification location as (x, y), if the server supports it. - """ - if (not isinstance(x, int)) or (not isinstance(y, int)): - raise TypeError("x and y must both be ints", (x,y)) - self.hints['x'] = x - self.hints['y'] = y - diff --git a/scudcloud-1.0/lib/resources.py b/scudcloud-1.0/lib/resources.py deleted file mode 100644 index f9835d8..0000000 --- a/scudcloud-1.0/lib/resources.py +++ /dev/null @@ -1,19 +0,0 @@ -import os, re - -class Resources: - - APP_NAME = "ScudCloud Slack_SSB" - SIGNIN_URL = "https://slack.com/signin" - MAINPAGE_URL_RE = re.compile(r'^http[s]://[a-zA-Z0-9_\-]+.slack.com/?$') - MESSAGES_URL_RE = re.compile(r'^http[s]://[a-zA-Z0-9_\-]+.slack.com/messages/.*') - SSO_URL_RE = re.compile(r'^http[s]://[a-zA-Z0-9_\-]+.slack.com/sso/saml/start$') - SERVICES_URL_RE = re.compile(r'^http[s]://[a-zA-Z0-9_\-]+.slack.com/services/.*') - - SPELL_DICT_PATH = "/usr/share/hunspell/" - SPELL_LIMIT = 6 - - # It's initialized in /scudcloud script - INSTALL_DIR = None - - def get_path(filename): - return os.path.join(Resources.INSTALL_DIR, 'resources', filename) diff --git a/scudcloud-1.0/lib/scudcloud.py b/scudcloud-1.0/lib/scudcloud.py deleted file mode 100755 index d53e04f..0000000 --- a/scudcloud-1.0/lib/scudcloud.py +++ /dev/null @@ -1,379 +0,0 @@ -#!/usr/bin/env python3 -import sys, os, time -from cookiejar import PersistentCookieJar -from leftpane import LeftPane -from notifier import Notifier -from resources import Resources -from speller import Speller -from systray import Systray -from wrapper import Wrapper -from threading import Thread -from PyQt4 import QtCore, QtGui, QtWebKit -from PyQt4.Qt import QApplication, QKeySequence, QTimer -from PyQt4.QtCore import QUrl, QSettings -from PyQt4.QtWebKit import QWebSettings, QWebPage -from PyQt4.QtNetwork import QNetworkDiskCache - -# Auto-detection of Unity and Dbusmenu in gi repository -try: - from gi.repository import Unity, Dbusmenu -except ImportError: - Unity = None - Dbusmenu = None - from launcher import DummyLauncher - -class ScudCloud(QtGui.QMainWindow): - - plugins = True - debug = False - forceClose = False - messages = 0 - speller = Speller() - - def __init__(self, parent = None, settings_path = ""): - super(ScudCloud, self).__init__(parent) - self.setWindowTitle('ScudCloud') - self.settings_path = settings_path - self.notifier = Notifier(Resources.APP_NAME, Resources.get_path('scudcloud.png')) - self.settings = QSettings(self.settings_path + '/scudcloud.cfg', QSettings.IniFormat) - self.identifier = self.settings.value("Domain") - if Unity is not None: - self.launcher = Unity.LauncherEntry.get_for_desktop_id("scudcloud.desktop") - else: - self.launcher = DummyLauncher(self) - self.webSettings() - self.leftPane = LeftPane(self) - self.stackedWidget = QtGui.QStackedWidget() - centralWidget = QtGui.QWidget(self) - layout = QtGui.QHBoxLayout() - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(0) - layout.addWidget(self.leftPane) - layout.addWidget(self.stackedWidget) - centralWidget.setLayout(layout) - self.setCentralWidget(centralWidget) - self.startURL = Resources.SIGNIN_URL - if self.identifier is not None: - self.startURL = self.domain() - self.addWrapper(self.startURL) - self.addMenu() - self.tray = Systray(self) - self.systray(ScudCloud.minimized) - self.installEventFilter(self) - self.statusBar().showMessage('Loading Slack...') - - def addWrapper(self, url): - webView = Wrapper(self) - webView.page().networkAccessManager().setCookieJar(self.cookiesjar) - webView.page().networkAccessManager().setCache(self.diskCache) - webView.load(QtCore.QUrl(url)) - webView.show() - self.stackedWidget.addWidget(webView) - self.stackedWidget.setCurrentWidget(webView) - - def webSettings(self): - self.cookiesjar = PersistentCookieJar(self) - self.zoom = self.readZoom() - # Required by Youtube videos (HTML5 video support only on Qt5) - QWebSettings.globalSettings().setAttribute(QWebSettings.PluginsEnabled, self.plugins) - # We don't want Java - QWebSettings.globalSettings().setAttribute(QWebSettings.JavaEnabled, False) - # We don't need History - QWebSettings.globalSettings().setAttribute(QWebSettings.PrivateBrowsingEnabled, True) - # Enabling Local Storage (now required by Slack) - QWebSettings.globalSettings().setAttribute(QWebSettings.LocalStorageEnabled, True) - # Enabling Cache - self.diskCache = QNetworkDiskCache(self) - self.diskCache.setCacheDirectory(self.settings_path) - # Required for copy and paste clipboard integration - QWebSettings.globalSettings().setAttribute(QWebSettings.JavascriptCanAccessClipboard, True) - # Enabling Inspeclet only when --debug=True (requires more CPU usage) - QWebSettings.globalSettings().setAttribute(QWebSettings.DeveloperExtrasEnabled, self.debug) - - def toggleFullScreen(self): - if self.isFullScreen(): - self.showMaximized() - else: - self.showFullScreen() - - def toggleMenuBar(self): - menu = self.menuBar() - state = menu.isHidden() - menu.setVisible(state) - if state: - self.settings.setValue("Menu", "False") - else: - self.settings.setValue("Menu", "True") - - def restore(self): - geometry = self.settings.value("geometry") - if geometry is not None: - self.restoreGeometry(geometry) - windowState = self.settings.value("windowState") - if windowState is not None: - self.restoreState(windowState) - else: - self.setWindowState(QtCore.Qt.WindowMaximized) - - def systray(self, show=None): - if show is None: - show = self.settings.value("Systray") == "True" - if show: - self.tray.show() - self.menus["file"]["close"].setEnabled(True) - self.settings.setValue("Systray", "True") - else: - self.tray.setVisible(False) - self.menus["file"]["close"].setEnabled(False) - self.settings.setValue("Systray", "False") - - def readZoom(self): - default = 1 - if self.settings.value("Zoom") is not None: - default = float(self.settings.value("Zoom")) - return default - - def setZoom(self, factor=1): - if factor > 0: - for i in range(0, self.stackedWidget.count()): - widget = self.stackedWidget.widget(i) - widget.setZoomFactor(factor) - self.settings.setValue("Zoom", factor) - - def zoomIn(self): - self.setZoom(self.current().zoomFactor() + 0.1) - - def zoomOut(self): - self.setZoom(self.current().zoomFactor() - 0.1) - - def zoomReset(self): - self.setZoom() - - def addMenu(self): - self.menus = { - "file": { - "preferences": self.createAction("Preferences", lambda : self.current().preferences()), - "systray": self.createAction("Close to Tray", self.systray, None, True), - "addTeam": self.createAction("Sign in to Another Team", lambda : self.switchTo(Resources.SIGNIN_URL)), - "signout": self.createAction("Signout", lambda : self.current().logout()), - "close": self.createAction("Close", self.close, QKeySequence.Close), - "exit": self.createAction("Quit", self.exit, QKeySequence.Quit) - }, - "edit": { - }, - "view": { - "zoomin": self.createAction("Zoom In", self.zoomIn, QKeySequence.ZoomIn), - "zoomout": self.createAction("Zoom Out", self.zoomOut, QKeySequence.ZoomOut), - "reset": self.createAction("Reset", self.zoomReset, QtCore.Qt.CTRL + QtCore.Qt.Key_0), - "fullscreen": self.createAction("Toggle Full Screen", self.toggleFullScreen, QtCore.Qt.Key_F11), - "hidemenu": self.createAction("Toggle Menubar", self.toggleMenuBar, QtCore.Qt.Key_F12) - }, - "help": { - "help": self.createAction("Help and Feedback", lambda : self.current().help(), QKeySequence.HelpContents), - "center": self.createAction("Slack Help Center", lambda : self.current().helpCenter()), - "about": self.createAction("About", lambda : self.current().about()) - } - } - menu = self.menuBar() - fileMenu = menu.addMenu("&File") - fileMenu.addAction(self.menus["file"]["preferences"]) - fileMenu.addAction(self.menus["file"]["systray"]) - fileMenu.addSeparator() - fileMenu.addAction(self.menus["file"]["addTeam"]) - fileMenu.addAction(self.menus["file"]["signout"]) - fileMenu.addSeparator() - fileMenu.addAction(self.menus["file"]["close"]) - fileMenu.addAction(self.menus["file"]["exit"]) - self.editMenu = menu.addMenu("&Edit") - self.updateEditMenu() - viewMenu = menu.addMenu("&View") - viewMenu.addAction(self.menus["view"]["zoomin"]) - viewMenu.addAction(self.menus["view"]["zoomout"]) - viewMenu.addAction(self.menus["view"]["reset"]) - viewMenu.addSeparator() - viewMenu.addAction(self.menus["view"]["fullscreen"]) - if Unity is None: - viewMenu.addAction(self.menus["view"]["hidemenu"]) - helpMenu = menu.addMenu("&Help") - helpMenu.addAction(self.menus["help"]["help"]) - helpMenu.addAction(self.menus["help"]["center"]) - helpMenu.addSeparator() - helpMenu.addAction(self.menus["help"]["about"]) - self.enableMenus(False) - showSystray = self.settings.value("Systray") == "True" - self.menus["file"]["systray"].setChecked(showSystray) - self.menus["file"]["close"].setEnabled(showSystray) - # Restore menu visibility - visible = self.settings.value("Menu") - if visible is not None and visible == "False": - menu.setVisible(False) - - def enableMenus(self, enabled): - self.menus["file"]["preferences"].setEnabled(enabled == True) - self.menus["file"]["addTeam"].setEnabled(enabled == True) - self.menus["file"]["signout"].setEnabled(enabled == True) - self.menus["help"]["help"].setEnabled(enabled == True) - - def updateEditMenu(self): - self.editMenu.clear() - self.menus["edit"] = { - "undo": self.current().pageAction(QtWebKit.QWebPage.Undo), - "redo": self.current().pageAction(QtWebKit.QWebPage.Redo), - "cut": self.current().pageAction(QtWebKit.QWebPage.Cut), - "copy": self.current().pageAction(QtWebKit.QWebPage.Copy), - "paste": self.current().pageAction(QtWebKit.QWebPage.Paste), - "back": self.current().pageAction(QtWebKit.QWebPage.Back), - "forward": self.current().pageAction(QtWebKit.QWebPage.Forward), - "reload": self.current().pageAction(QtWebKit.QWebPage.Reload) - } - self.editMenu.addAction(self.menus["edit"]["undo"]) - self.editMenu.addAction(self.menus["edit"]["redo"]) - self.editMenu.addSeparator() - self.editMenu.addAction(self.menus["edit"]["cut"]) - self.editMenu.addAction(self.menus["edit"]["copy"]) - self.editMenu.addAction(self.menus["edit"]["paste"]) - self.editMenu.addSeparator() - self.editMenu.addAction(self.menus["edit"]["back"]) - self.editMenu.addAction(self.menus["edit"]["forward"]) - self.editMenu.addAction(self.menus["edit"]["reload"]) - - def createAction(self, text, slot, shortcut=None, checkable=False): - action = QtGui.QAction(text, self) - action.triggered.connect(slot) - if shortcut is not None: - action.setShortcut(shortcut) - self.addAction(action) - if checkable: - action.setCheckable(True) - return action - - def domain(self): - if self.identifier.endswith(".slack.com"): - return self.identifier - else: - return "https://"+self.identifier+".slack.com" - - def current(self): - return self.stackedWidget.currentWidget() - - def teams(self, teams): - for t in teams: - # If team_icon is not present, it's because team is already connected - if 'team_icon' in t: - self.leftPane.addTeam(t['id'], t['team_name'], t['team_url'], t['team_icon']['image_44'], t == teams[0]) - if len(teams) > 1: - self.leftPane.show() - - def switchTo(self, url): - exists = False - for i in range(0, self.stackedWidget.count()): - if self.stackedWidget.widget(i).url().toString().startswith(url): - self.stackedWidget.setCurrentIndex(i) - self.quicklist(self.current().listChannels()) - self.current().setFocus() - exists = True - break - if not exists: - self.addWrapper(url) - self.updateEditMenu() - - def eventFilter(self, obj, event): - if event.type() == QtCore.QEvent.ActivationChange and self.isActiveWindow(): - self.focusInEvent(event) - if event.type() == QtCore.QEvent.KeyPress: - # Ctrl + - modifiers = QtGui.QApplication.keyboardModifiers() - if modifiers == QtCore.Qt.ControlModifier: - if event.key() == QtCore.Qt.Key_1: self.leftPane.click(0) - elif event.key() == QtCore.Qt.Key_2: self.leftPane.click(1) - elif event.key() == QtCore.Qt.Key_3: self.leftPane.click(2) - elif event.key() == QtCore.Qt.Key_4: self.leftPane.click(3) - elif event.key() == QtCore.Qt.Key_5: self.leftPane.click(4) - elif event.key() == QtCore.Qt.Key_6: self.leftPane.click(5) - elif event.key() == QtCore.Qt.Key_7: self.leftPane.click(6) - elif event.key() == QtCore.Qt.Key_8: self.leftPane.click(7) - elif event.key() == QtCore.Qt.Key_9: self.leftPane.click(8) - # Ctrl + Tab - elif event.key() == QtCore.Qt.Key_Tab: self.leftPane.clickNext(1) - # Ctrl + BackTab - if (modifiers & QtCore.Qt.ControlModifier) and (modifiers & QtCore.Qt.ShiftModifier): - if event.key() == QtCore.Qt.Key_Backtab: self.leftPane.clickNext(-1) - # Ctrl + Shift + - if (modifiers & QtCore.Qt.ShiftModifier) and (modifiers & QtCore.Qt.ShiftModifier): - if event.key() == QtCore.Qt.Key_V: self.current().createSnippet() - return QtGui.QMainWindow.eventFilter(self, obj, event); - - def focusInEvent(self, event): - self.launcher.set_property("urgent", False) - self.tray.stopAlert() - - def titleChanged(self): - self.setWindowTitle(self.current().title()) - - def closeEvent(self, event): - if not self.forceClose and self.settings.value("Systray") == "True": - self.hide() - event.ignore() - else: - self.cookiesjar.save() - self.settings.setValue("geometry", self.saveGeometry()) - self.settings.setValue("windowState", self.saveState()) - # Let's save the first team registered as default - qUrl = self.stackedWidget.widget(0).url() - if self.identifier is None and Resources.MESSAGES_URL_RE.match(qUrl.toString()): - self.settings.setValue("Domain", 'https://'+qUrl.host()) - - def show(self): - self.setWindowState(self.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive) - self.activateWindow() - self.setVisible(True) - - def exit(self): - self.forceClose = True - self.close() - - def quicklist(self, channels): - if Dbusmenu is not None: - if channels is not None: - ql = Dbusmenu.Menuitem.new() - self.launcher.set_property("quicklist", ql) - for c in channels: - if c['is_member']: - item = Dbusmenu.Menuitem.new () - item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, "#"+c['name']) - item.property_set ("id", c['name']) - item.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, True) - item.connect(Dbusmenu.MENUITEM_SIGNAL_ITEM_ACTIVATED, self.current().openChannel) - ql.child_append(item) - self.launcher.set_property("quicklist", ql) - - def notify(self, title, message, icon=None): - self.notifier.notify(title, message, icon) - self.alert() - - def alert(self): - if not self.isActiveWindow(): - self.launcher.set_property("urgent", True) - self.tray.alert() - - def count(self): - total = 0 - for i in range(0, self.stackedWidget.count()): - widget = self.stackedWidget.widget(i) - messages = widget.highlights - if messages == 0: - self.leftPane.stopAlert(widget.team()) - else: - self.leftPane.alert(widget.team()) - if messages is not None: - total+=messages - if total > self.messages: - self.alert() - if 0 == total: - self.launcher.set_property("count_visible", False) - self.tray.setCounter(0) - else: - self.tray.setCounter(total) - self.launcher.set_property("count", total) - self.launcher.set_property("count_visible", True) - self.messages = total diff --git a/scudcloud-1.0/lib/speller.py b/scudcloud-1.0/lib/speller.py deleted file mode 100644 index e60967c..0000000 --- a/scudcloud-1.0/lib/speller.py +++ /dev/null @@ -1,90 +0,0 @@ -import os -from resources import Resources -from PyQt4 import QtGui -from PyQt4.QtCore import QObject -from PyQt4.QtCore import QLocale, QFile, QTextBoundaryFinder - -# Checking if python-hunspell is present -try: - import hunspell -except ImportError: - class hunspell: - HunSpell = None - -# Simplified version of QupZilla Speller (https://github.com/QupZilla/qupzilla/blob/v1.8/src/lib/plugins/qtwebkit/spellcheck/speller.cpp) -class Speller(QObject): - - hunspell = None - initialized = False - startPos = 0 - - def __init__(self): - super(Speller, self).__init__() - if self.initialized or hunspell.HunSpell is None: - return - dictionaryPath = self.getDictionaryPath() - language = self.parseLanguage(dictionaryPath) - if not dictionaryPath or language is None: - return - self.hunspell = hunspell.HunSpell(dictionaryPath + ".dic", dictionaryPath + ".aff") - self.initialized = True - - def isMisspelled(self, s): - return not self.hunspell.spell(s) - - def suggest(self, s): - return self.hunspell.suggest(s) - - def parseLanguage(self, path): - if '/' in path: - pos = path.rfind('/') - return path[-int(pos + 1):] - return path - - def dictionaryExists(self, path): - return QFile(path + ".dic").exists() and QFile(path + ".aff").exists(); - - def getDictionaryPath(self): - dicPath = Resources.SPELL_DICT_PATH + QLocale.system().name() - if self.dictionaryExists(dicPath): - return dicPath - return '' - - def replaceWord(self, element, word): - action = self.sender() - new = action.data() - text = str(element.evaluateJavaScript("this.value")) - cursorPos = int(element.evaluateJavaScript("this.selectionStart")) - text = text[:self.startPos] + new + text[self.startPos+len(word):] - text = text.replace('\\', "\\\\") - text = text.replace('\n', "\\n") - text = text.replace('\'', "\\'") - element.evaluateJavaScript("this.value='{}'".format(text)) - element.evaluateJavaScript("this.selectionStart=this.selectionEnd={}".format(cursorPos)) - - def getWord(self, element): - text = str(element.evaluateJavaScript("this.value")) - pos = int(int(element.evaluateJavaScript("this.selectionStart")) + int(1)) - finder = QTextBoundaryFinder(QTextBoundaryFinder.Word, text) - finder.setPosition(pos) - self.startPos = finder.toPreviousBoundary() - return text[self.startPos:finder.toNextBoundary()].strip() - - def populateContextMenu(self, menu, element): - word = self.getWord(element) - if self.isMisspelled(word): - suggests = self.suggest(word) - count = Resources.SPELL_LIMIT - if len(suggests) < count: - count = len(suggests) - boldFont = menu.font() - boldFont.setBold(True) - for i in range(0, count): - action = QtGui.QAction(str(suggests[i]), self) - action.triggered.connect(lambda:self.replaceWord(element, word)) - action.setData(suggests[i]) - action.setFont(boldFont) - menu.addAction(action) - if count == 0: - menu.addAction(menu.tr("No suggestions")).setEnabled(False) - menu.addSeparator(); diff --git a/scudcloud-1.0/lib/systray.py b/scudcloud-1.0/lib/systray.py deleted file mode 100644 index 567a249..0000000 --- a/scudcloud-1.0/lib/systray.py +++ /dev/null @@ -1,57 +0,0 @@ -from PyQt4 import QtCore, QtGui -from resources import Resources -import scudcloud - -class Systray(QtGui.QSystemTrayIcon): - - urgent = False - - def __init__(self, window): - super(Systray, self).__init__(QtGui.QIcon.fromTheme("scudcloud"), window) - self.connect(self, QtCore.SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.activatedEvent) - self.window = window - self.setToolTip('ScudCloud') - self.menu = QtGui.QMenu(self.window) - self.menu.addAction('Show', self.restore) - if scudcloud.Unity is None: - self.menu.addAction('Toggle Menubar', self.toggleMenuBar) - self.menu.addSeparator() - self.menu.addAction(self.window.menus["file"]["preferences"]) - self.menu.addAction(self.window.menus["help"]["about"]) - self.menu.addSeparator() - self.menu.addAction(self.window.menus["file"]["exit"]) - self.setContextMenu(self.menu) - - def alert(self): - if not self.urgent: - self.urgent = True - self.setIcon(QtGui.QIcon.fromTheme("scudcloud-attention")) - - def stopAlert(self): - self.urgent = False - self.setIcon(QtGui.QIcon.fromTheme("scudcloud")) - - def setCounter(self, i): - if 0 == i: - if True == self.urgent: - self.setIcon(QtGui.QIcon.fromTheme("scudcloud-attention")) - else: - self.setIcon(QtGui.QIcon.fromTheme("scudcloud")) - elif i > 0 and i < 10: - self.setIcon(QtGui.QIcon.fromTheme("scudcloud-attention-"+str(int(i)))) - elif i > 9: - self.setIcon(QtGui.QIcon.fromTheme("scudcloud-attention-9-plus")) - - def restore(self): - self.window.show() - self.stopAlert() - - def toggleMenuBar(self): - self.window.toggleMenuBar() - - def activatedEvent(self, reason): - if reason in [QtGui.QSystemTrayIcon.MiddleClick, QtGui.QSystemTrayIcon.Trigger]: - if self.window.isHidden() or self.window.isMinimized() or not self.window.isActiveWindow(): - self.restore() - else: - self.window.hide() diff --git a/scudcloud-1.0/lib/wrapper.py b/scudcloud-1.0/lib/wrapper.py deleted file mode 100644 index 9d1c348..0000000 --- a/scudcloud-1.0/lib/wrapper.py +++ /dev/null @@ -1,183 +0,0 @@ -import sys, subprocess, os, json, tempfile -from urllib import request -from urllib.parse import urlparse -from resources import Resources -from PyQt4 import QtWebKit, QtGui, QtCore -from PyQt4.Qt import QApplication, QKeySequence, QTimer -from PyQt4.QtCore import QBuffer, QByteArray, QUrl -from PyQt4.QtWebKit import QWebView, QWebPage, QWebSettings -from PyQt4.QtNetwork import QNetworkProxy - -class Wrapper(QWebView): - - highlights = 0 - icon = None - name = '' - - def __init__(self, window): - self.configure_proxy() - QWebView.__init__(self) - self.window = window - with open(Resources.get_path("scudcloud.js"), "r") as f: - self.js = f.read() - self.setZoomFactor(self.window.zoom) - self.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks) - self.urlChanged.connect(self._urlChanged) - self.loadStarted.connect(self._loadStarted) - self.loadFinished.connect(self._loadFinished) - self.linkClicked.connect(self._linkClicked) - self.page().featurePermissionRequested.connect(self.permissionRequested) - self.addActions() - - def permissionRequested(self, frame, feature): - self.page().setFeaturePermission(frame, feature, QWebPage.PermissionGrantedByUser) - self.overrideNotifications() - - def configure_proxy(self): - proxy = urlparse(os.environ.get('http_proxy') or os.environ.get('HTTP_PROXY')) - if proxy.hostname is not None and proxy.port is not None: - q_network_proxy = QNetworkProxy(QNetworkProxy.HttpProxy, proxy.hostname, proxy.port) - if proxy.username is not None: - q_network_proxy.setUser(proxy.username) - if proxy.password is not None: - q_network_proxy.setPassword(proxy.password) - QNetworkProxy.setApplicationProxy(q_network_proxy) - - def addActions(self): - self.pageAction(QWebPage.SetTextDirectionDefault).setVisible(False) - self.pageAction(QWebPage.SetTextDirectionLeftToRight).setVisible(False) - self.pageAction(QWebPage.SetTextDirectionRightToLeft).setVisible(False) - self.pageAction(QWebPage.Undo).setShortcuts(QKeySequence.Undo) - self.pageAction(QWebPage.Redo).setShortcuts(QKeySequence.Redo) - self.pageAction(QWebPage.Cut).setShortcuts(QKeySequence.Cut) - self.pageAction(QWebPage.Copy).setShortcuts(QKeySequence.Copy) - self.pageAction(QWebPage.Paste).setShortcuts(QKeySequence.Paste) - self.pageAction(QWebPage.Back).setShortcuts(QKeySequence.Back) - self.pageAction(QWebPage.Forward).setShortcuts(QKeySequence.Forward) - self.pageAction(QWebPage.Reload).setShortcuts(QKeySequence.Refresh) - - def contextMenuEvent(self, event): - menu = QtGui.QMenu(self) - if self.window.speller.initialized: - hit = self.page().currentFrame().hitTestContent(event.pos()) - element = hit.element() - if hit.isContentEditable() and not hit.isContentSelected() and element.attribute("type") != "password": - self.window.speller.populateContextMenu(menu, element) - pageMenu = self.page().createStandardContextMenu() - if pageMenu is not None: - for a in pageMenu.actions(): - if a.isSeparator(): - menu.addSeparator() - elif a.isVisible(): - menu.addAction(a) - del pageMenu - menu.exec_(event.globalPos()) - - def call(self, function, arg=None): - if isinstance(arg, str): - arg = "'"+arg+"'" - if arg is None: - arg = "" - return self.page().currentFrame().evaluateJavaScript("ScudCloud."+function+"("+arg+");") - - def _loadStarted(self): - # Some custom CSS to clean/fix UX - self.settings().setUserStyleSheetUrl(QUrl.fromLocalFile(Resources.get_path("resources.css"))) - - def _urlChanged(self, qUrl): - url = qUrl.toString() - # Some integrations/auth will get back to /services with no way to get back to chat - if Resources.SERVICES_URL_RE.match(url): - self.systemOpen(url) - self.load(QUrl("https://"+qUrl.host()+"/messages/general")) - - def _loadFinished(self, ok=True): - # Starting the webkit-JS bridge - self.page().currentFrame().addToJavaScriptWindowObject("desktop", self) - # Loading ScudCloud JS client - self.page().currentFrame().evaluateJavaScript(self.js) - self.window.statusBar().hide() - - def systemOpen(self, url): - subprocess.call(('xdg-open', url)) - - def _linkClicked(self, qUrl): - url = qUrl.toString() - handle_link = ( - Resources.SIGNIN_URL == url or - Resources.MAINPAGE_URL_RE.match(url) or - Resources.MESSAGES_URL_RE.match(url) or - Resources.SSO_URL_RE.match(url) or - url.startswith("https://accounts.google.com/o/oauth")) - if handle_link: - self.load(qUrl) - else: - self.systemOpen(url) - - def preferences(self): - self.window.show() - self.call("preferences") - - def createSnippet(self): - self.call("createSnippet") - - def team(self): - return self.call("getCurrentTeam") - - def logout(self): - self.call("logout") - - def help(self): - self.call("help") - - def helpCenter(self): - subprocess.call(('xdg-open', "https://slack.zendesk.com/hc/en-us")) - - def about(self): - subprocess.call(('xdg-open', "https://github.com/raelgc/scudcloud")) - - def listChannels(self): - return self.call("listChannels") - - def openChannel(self, menuitem, timestamp): - self.call("join", menuitem.property_get("id")) - self.window.show() - - @QtCore.pyqtSlot(int, int) - def count(self, highlight, unread): - self.highlights = highlight - self.window.count() - - @QtCore.pyqtSlot(str) - def populate(self, serialized): - data = json.loads(serialized) - self.window.teams(data['teams']) - if self.window.current() == self: - self.window.quicklist(data['channels']) - self.name = data['teams'][0]['team_name'] - filename, headers = request.urlretrieve(data['icon'], tempfile.gettempdir()+'/'+self.name+'.png') - self.icon = filename - - @QtCore.pyqtSlot(bool) - def enableMenus(self, enabled): - self.window.enableMenus(enabled) - - @QtCore.pyqtSlot(bool) - def pasted(self, checked): - clipboard = QApplication.clipboard() - mime = clipboard.mimeData() - if mime.hasImage(): - pixmap = clipboard.pixmap() - byteArray = QByteArray() - buffer = QBuffer(byteArray) - pixmap.save(buffer, "PNG") - self.call("setClipboard", str(byteArray.toBase64(), sys.stdout.encoding)) - - @QtCore.pyqtSlot(str, str) - def sendMessage(self, title, message): - erase = ['['+self.name.lower()+'] in ', '['+self.name.lower()+'] from '] - for s in erase: - title = str(title).replace(s, '', 1) - self.window.notify(title, str(message), self.icon) - - diff --git a/scudcloud-1.0/resources/leftpane.html b/scudcloud-1.0/resources/leftpane.html deleted file mode 100644 index a845ef3..0000000 --- a/scudcloud-1.0/resources/leftpane.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - -
    -
- - diff --git a/scudcloud-1.0/resources/leftpane.js b/scudcloud-1.0/resources/leftpane.js deleted file mode 100644 index 005a43e..0000000 --- a/scudcloud-1.0/resources/leftpane.js +++ /dev/null @@ -1 +0,0 @@ -var LeftPane={addTeam:function(e,t,n,l,c){var i=document.getElementById(e);if(null===i){var a=document.getElementById("teams");li=document.createElement("li"),li.id=e,li.setAttribute("onclick","LeftPane.switchTo('"+e.replace(/'/g,""")+"','"+n.replace(/'/g,""")+"')"),li.setAttribute("title",t),li.innerHTML=t[0],l&&(li.style.backgroundImage="url('"+l.replace(/'/g,""")+"')",li.innerHTML=""),a.appendChild(li),c&&LeftPane.setActive(e),LeftPane.switchTo(e,n)}},click:function(e){for(var t=document.getElementsByTagName("li"),n=0;n=t.length?n=0:0>n&&(n=t.length-1),LeftPane.click(n)}}; diff --git a/scudcloud-1.0/resources/resources.css b/scudcloud-1.0/resources/resources.css deleted file mode 100644 index bc30435..0000000 --- a/scudcloud-1.0/resources/resources.css +++ /dev/null @@ -1,2 +0,0 @@ -nav.top, footer, #prefs_mac_ssb_tab {display: none !important;} -* {font-family: Lato,"Helvetica Neue",Helvetica,"Segoe UI",Tahoma,Arial,sans-serif;} diff --git a/scudcloud-1.0/resources/scudcloud.js b/scudcloud-1.0/resources/scudcloud.js deleted file mode 100644 index 82a7621..0000000 --- a/scudcloud-1.0/resources/scudcloud.js +++ /dev/null @@ -1 +0,0 @@ -ScudCloud={unloaded:!0,hasPreference:function(n){return!1},getPreference:function(n){return!1},setPreference:function(n,e){return!1},canShowHtmlNotifications:function(){return!1},call:function(n,e){switch(ScudCloud.log(n),n){case"reload":return ScudCloud.reload();case"didStartLoading":return ScudCloud.didStartLoading();case"didFinishLoading":return ScudCloud.didFinishLoading();case"setConnectionStatus":return ScudCloud.setConnectionStatus(e);case"notify":return ScudCloud.notify(e);case"setBadgeCount":return ScudCloud.setBadgeCount(e);case"displayTeam":return ScudCloud.displayTeam(e)}return!1},reload:function(){window.location.reload()},didStartLoading:function(){},didFinishLoading:function(){TS.ui.banner.close(),ScudCloud.populate(),ScudCloud.unloaded=!1},setConnectionStatus:function(n){switch(n){case"online":desktop.enableMenus(!0);break;default:desktop.enableMenus(!1)}},notify:function(n){desktop.sendMessage(n.title,n.content)},setBadgeCount:function(n){desktop.count(n.all_unread_highlights_cnt,n.all_unread_cnt)},displayTeam:function(n){},log:function(n){console.log("ScudCloud."+n)},populate:function(){desktop.populate(JSON.stringify({channels:ScudCloud.listChannels(),teams:ScudCloud.listTeams(),icon:TS.model.team.icon.image_44}))},createSnippet:function(){return TS.ui.snippet_dialog.start()},listChannels:function(){return TS.channels.getUnarchivedChannelsForUser()},listTeams:function(){var n=TS.getAllTeams();return n[0].team_icon={image_44:TS.model.team.icon.image_44},n},quicklist:function(){desktop.quicklist(ScudCloud.listChannels())},join:function(n){return TS.channels.join(n)},setClipboard:function(n){TS.client.ui.file_pasted_sig.dispatch(n,TS.model.shift_key_pressed)},preferences:function(){return TS.ui.prefs_dialog.start()},addTeam:function(){document.location=TS.boot_data.signin_url},getCurrentTeam:function(){var n=TS.getAllTeams();if(null!=n)for(var e=0;n.length;e++)if(n[e].team_url==TS.boot_data.team_url)return n[e].id;return""},logout:function(){document.location=TS.boot_data.logout_url},help:function(){return TS.help_dialog.start()}},document.onpaste=function(n){desktop.pasted(!1)},window.winssb=TSSSB=ScudCloud,ScudCloud.unloaded&&ScudCloud.didFinishLoading(); diff --git a/scudcloud-1.0/resources/scudcloud.png b/scudcloud-1.0/resources/scudcloud.png deleted file mode 100644 index ee08336..0000000 Binary files a/scudcloud-1.0/resources/scudcloud.png and /dev/null differ diff --git a/scudcloud-1.0/scudcloud b/scudcloud-1.0/scudcloud deleted file mode 100755 index 734350c..0000000 --- a/scudcloud-1.0/scudcloud +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python3 -import fcntl, os, sys, signal, tempfile -from PyQt4 import QtGui, QtCore -from PyQt4.QtNetwork import QLocalServer, QLocalSocket - -# Flexible install dir (we assume that 'lib' and 'resources' will be subdirs) -INSTALL_DIR = os.path.dirname(os.path.realpath(__file__)) - -# Append the lib directory in our installation path to get remaining libraries. -sys.path.append(os.path.join(INSTALL_DIR, 'lib')) -from resources import Resources -from scudcloud import ScudCloud - -# The ScudCloud QMainWindow -win = None - -def main(): - global win - Resources.INSTALL_DIR = INSTALL_DIR - signal.signal(signal.SIGINT, exit) - args = parse_arguments() - appKey = "scudcloud.pid" - socket = QLocalSocket() - socket.connectToServer(appKey) - if socket.isOpen(): - socket.close() - socket.deleteLater() - return 0 - socket.deleteLater() - app = QtGui.QApplication(sys.argv) - app.setApplicationName(Resources.APP_NAME) - app.setWindowIcon(QtGui.QIcon(Resources.get_path('scudcloud.png'))) - ScudCloud.debug = args.debug - ScudCloud.minimized = True if args.minimized is True else None - ScudCloud.plugins = False if args.no_plugins is True else True - try: - settings_path = load_settings(args.confdir) - except: - print("Configuration directory "+args.confdir+" could not be created! Exiting...") - raise SystemExit() - win = ScudCloud(settings_path=settings_path) - server = QLocalServer() - server.newConnection.connect(restore) - server.listen(appKey) - win.restore() - if win.minimized is None: - win.show() - sys.exit(app.exec_()) - -def restore(): - global win - win.setWindowFlags(win.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) - win.showNormal() - win.setWindowFlags(win.windowFlags() & ~QtCore.Qt.WindowStaysOnTopHint) - win.showNormal() - win.activateWindow() - -def load_settings(confdir): - if not os.path.isdir(confdir): - os.makedirs(confdir) - if confdir not in sys.path: - sys.path[0:0] = [confdir] - return confdir - -def parse_arguments(): - from argparse import ArgumentParser - from os.path import expanduser - if 'XDG_CONFIG_HOME' in os.environ and os.environ['XDG_CONFIG_HOME']: - default_confdir = os.environ['XDG_CONFIG_HOME'] + '/scudcloud' - else: - default_confdir = '~/.config/scudcloud' - parser = ArgumentParser() - parser.add_argument('--confdir', dest='confdir', metavar='dir', default=default_confdir, help="change the configuration directory") - parser.add_argument('--debug', dest='debug', type=bool, default=False, help="enable webkit debug console (default: False)") - parser.add_argument('--minimized', dest='minimized', type=bool, default=False, help="start minimized to tray (default: False)") - parser.add_argument('--no_plugins', dest='no_plugins', type=bool, default=False, help="disable web plugins (default: False)") - parser.add_argument('--version', action="store_true", help="print version and exit") - args = parser.parse_args() - if args.version: - with open(os.path.join(Resources.INSTALL_DIR, 'VERSION'), "r") as f: - print("ScudCloud "+f.read()) - sys.exit() - args.confdir = expanduser(args.confdir) - return args - -def exit(*args): - if win is not None: - win.exit() - else: - QtGui.QApplication.quit() - -if __name__ == '__main__': - main() diff --git a/scudcloud-1.0/scudcloud-src.js b/scudcloud-1.0/scudcloud-src.js deleted file mode 100644 index 3bb9beb..0000000 --- a/scudcloud-1.0/scudcloud-src.js +++ /dev/null @@ -1,120 +0,0 @@ - -ScudCloud = { - unloaded: true, - // App functions - hasPreference: function(name){ - return false; - }, - getPreference: function(name){ - return false; - }, - setPreference: function(name, value){ - return false; - }, - canShowHtmlNotifications: function(){ - // Ubuntu cannot display HTML notifications - return false; - }, - // TSSSB.call - call: function(name, args){ - ScudCloud.log(name); - switch(name){ - case "reload": - return ScudCloud.reload(); - case "didStartLoading": - return ScudCloud.didStartLoading(); - case "didFinishLoading": - return ScudCloud.didFinishLoading(); - case "setConnectionStatus": - return ScudCloud.setConnectionStatus(args); - case "notify": - return ScudCloud.notify(args); - case "setBadgeCount": - return ScudCloud.setBadgeCount(args); - case "displayTeam": - return ScudCloud.displayTeam(args); - } - return false; - }, - // TSSSB.call implementations - reload: function(){ - window.location.reload(); - }, - didStartLoading: function(){ - }, - didFinishLoading: function(){ - TS.ui.banner.close(); - ScudCloud.populate(); - ScudCloud.unloaded = false; - }, - setConnectionStatus: function(status){ - // "online", "connecting", "offline" - switch(status){ - case "online": desktop.enableMenus(true); break; - default: desktop.enableMenus(false); - } - }, - notify: function(args){ - desktop.sendMessage(args.title, args.content); - }, - setBadgeCount: function(args){ - desktop.count(args.all_unread_highlights_cnt, args.all_unread_cnt); - }, - displayTeam: function(id){ - }, - // ScudCloud internal functions - log: function(name){ - console.log("ScudCloud."+name); - }, - populate: function(){ - desktop.populate(JSON.stringify({'channels': ScudCloud.listChannels(), 'teams': ScudCloud.listTeams(), 'icon': TS.model.team.icon.image_44})); - }, - createSnippet: function(){ - return TS.ui.snippet_dialog.start(); - }, - listChannels: function(){ - return TS.channels.getUnarchivedChannelsForUser(); - }, - listTeams: function(){ - var list = TS.getAllTeams(); - // Fix for current team displaying no icon - list[0].team_icon = {"image_44":TS.model.team.icon.image_44}; - return list; - }, - quicklist: function(){ - desktop.quicklist(ScudCloud.listChannels()); - }, - join: function(c){ - return TS.channels.join(c); - }, - setClipboard: function(data){ - TS.client.ui.file_pasted_sig.dispatch(data, TS.model.shift_key_pressed); - }, - preferences: function(){ - return TS.ui.prefs_dialog.start(); - }, - addTeam: function(){ - document.location = TS.boot_data.signin_url; - }, - getCurrentTeam: function(){ - var list = TS.getAllTeams(); - if(list!=null) for(var i=0;list.length;i++){ - if(list[i].team_url==TS.boot_data.team_url){ - return list[i].id; - } - } - return ""; - }, - logout: function(){ - document.location = TS.boot_data.logout_url; - }, - help: function(){ - return TS.help_dialog.start(); - } -}; -document.onpaste = function(e){desktop.pasted(false);}; -window.winssb = TSSSB = ScudCloud; -// Sometimes didFinishLoading is not loaded -if(ScudCloud.unloaded){ - ScudCloud.didFinishLoading(); -} diff --git a/scudcloud-1.0/scudcloud.desktop b/scudcloud-1.0/scudcloud.desktop deleted file mode 100644 index d21cbe6..0000000 --- a/scudcloud-1.0/scudcloud.desktop +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env xdg-open -[Desktop Entry] -Version=1.0 -Terminal=false -Type=Application -Categories=Network;Chat; -Name=ScudCloud -Comment=ScudCloud is an open-source client for Slack -Keywords=slack;chat;instant-messaging;collaboration; -Exec=/opt/scudcloud/scudcloud -StartupWMClass=scudcloud -Icon=/opt/scudcloud/resources/scudcloud.png - diff --git a/scudcloud-1.0/scudcloud.spec b/scudcloud-1.0/scudcloud.spec deleted file mode 100644 index a7a5f1f..0000000 --- a/scudcloud-1.0/scudcloud.spec +++ /dev/null @@ -1,159 +0,0 @@ -# -# spec file for package scudcloud -# -# Copyright (c) 2015 Marcin Trendota (moonwolf@poczta.onet.pl) -# Copyright (c) 2015 Marcin Bajor (marcin.bajor@gmail.com) -# -# All modifications and additions to the file contributed by third parties -# remain the property of their copyright owners, unless otherwise agreed -# upon. The license for this file, and modifications and additions to the -# file, is the same license as for the pristine package itself (unless the -# license for the pristine package is not an Open Source License, in which -# case the license is the MIT License). An "Open Source License" is a -# license that conforms to the Open Source Definition (Version 1.9) -# published by the Open Source Initiative. - -# Please submit bugfixes or comments via http://bugs.opensuse.org/ -# - - -Name: scudcloud -Version: 1.0 -Release: 2%{?dist} -Summary: Non official desktop client for Slack© -License: MIT -Group: Applications/Internet -BuildRequires: python - -%if (0%{?suse_version} || 0%{?fedora_version}) -BuildRequires: fdupes -%endif - -%if 0%{?suse_version} -BuildRequires: update-desktop-files -BuildRequires: hicolor-icon-theme -Requires(post): desktop-file-utils -Requires(postun): desktop-file-utils -%else -Requires(post): xdg-utils -Requires(postun): xdg-utils -%endif - -Url: https://github.com/raelgc/scudcloud/ -Source: %{name}-%{version}.tar.gz -Requires: python3 -Requires: python3-qt4 -%if 0%{?suse_version} -Requires: google-lato-fonts -%else -Requires: lato-fonts -%endif -Requires: libqt4-webkit-qupzillaplugins -Requires: python3-hunspell -BuildRoot: %{_tmppath}/%{name}-%{version}-build -BuildArch: noarch - -%description -ScudCloud uses the QT library + Webkit to render the web version of Slack, -but using the QWebkit-Native bridge to improve desktop integration with: -* multiple teams support, -* native system notifications, -* count of unread direct mentions at launcher/sytray icon, -* alert/wobbling on new messages, -* channels quicklist (Unity only), -* optional "Close to Tray". - -%prep -%setup -q - -%install -INSTALL="/opt/scudcloud" -cd scudcloud-1.0 - -mkdir -p %{buildroot}/$INSTALL/lib -mkdir -p %{buildroot}/$INSTALL/resources -mkdir -p %{buildroot}%{_prefix}/bin -mkdir -p %{buildroot}%{_datadir}/icons/hicolor/scalable/apps -mkdir -p %{buildroot}%{_datadir}/icons/mono-dark/scalable/apps -mkdir -p %{buildroot}%{_datadir}/icons/mono-light/scalable/apps - - -install -m0644 lib/*.py %{buildroot}/$INSTALL/lib -install -m0644 resources/* %{buildroot}/$INSTALL/resources -install -m0755 scudcloud %{buildroot}/$INSTALL -install -m0644 LICENSE %{buildroot}/$INSTALL - -install -m0644 systray/hicolor/* %{buildroot}%{_datadir}/icons/hicolor/scalable/apps -install -m0644 systray/mono-dark/* %{buildroot}%{_datadir}/icons/mono-dark/scalable/apps -install -m0644 systray/mono-light/* %{buildroot}%{_datadir}/icons/mono-light/scalable/apps - -%if 0%{!?suse_version} -install -m0644 scudcloud.desktop %{buildroot}%{_datadir}/applications -%endif - -ln -sf $INSTALL/scudcloud %{buildroot}%{_bindir}/scudcloud - -%if 0%{?suse_version} -%suse_update_desktop_file -i %{name} Network InstantMessaging -%else -desktop-file-install --dir %{buildroot}%{_datadir}/applications %{name}.desktop -%endif - -%if (0%{?suse_version} || 0%{?fedora_version}) -%fdupes %{buildroot}/%{_prefix} -%endif - -%post -%if 0%{?suse_version} -%desktop_database_post -%icon_theme_cache_post -%else -xdg-icon-resource forceupdate --theme hicolor 2> /dev/null || : -xdg-icon-resource forceupdate --theme mono-dark 2> /dev/null || : -xdg-icon-resource forceupdate --theme mono-light 2> /dev/null || : -xdg-desktop-menu forceupdate 2> /dev/null || : -%endif - - -%postun -%if 0%{?suse_version} -%desktop_database_postun -%icon_theme_cache_postun -%else -if [ $1 -eq 0 ] ; then -xdg-icon-resource forceupdate --theme hicolor 2> /dev/null || : -xdg-icon-resource forceupdate --theme mono-dark 2> /dev/null || : -xdg-icon-resource forceupdate --theme mono-light 2> /dev/null || : -xdg-desktop-menu forceupdate 2> /dev/null || : -fi -%endif - - -%files -%defattr(-,root,root) -%dir /opt/scudcloud -%dir %{_datadir}/icons/hicolor -%dir %{_datadir}/icons/hicolor/scalable -%dir %{_datadir}/icons/hicolor/scalable/apps -%dir %{_datadir}/icons/mono-dark -%dir %{_datadir}/icons/mono-dark/scalable -%dir %{_datadir}/icons/mono-dark/scalable/apps -%dir %{_datadir}/icons/mono-light -%dir %{_datadir}/icons/mono-light/scalable -%dir %{_datadir}/icons/mono-light/scalable/apps -/opt/scudcloud/* -%{_datadir}/applications/scudcloud.desktop -%{_datadir}/icons/hicolor/scalable/apps/* -%{_datadir}/icons/mono-dark/scalable/apps/* -%{_datadir}/icons/mono-light/scalable/apps/* -%{_bindir}/scudcloud - -%changelog -* Sat Sep 26 2015 Marcin Bajor -- Added dependencies: libqt4-webkit-qupzillaplugins and python3-hunspell -* Mon Sep 21 2015 Marcin Trendota -- Add lato-fonts dependency -* Mon Aug 10 2015 Marcin Bajor -- Now build for CentOS, Red Hat Enterprise Linux, openSUSE, SUSE Linux Enterprise Server and others is possible -* Mon May 18 2015 Marcin Trendota -- First version \ No newline at end of file diff --git a/scudcloud-1.0/systray/hicolor/scudcloud-attention-1.svg b/scudcloud-1.0/systray/hicolor/scudcloud-attention-1.svg deleted file mode 100644 index 646bf31..0000000 --- a/scudcloud-1.0/systray/hicolor/scudcloud-attention-1.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 1 - - - diff --git a/scudcloud-1.0/systray/hicolor/scudcloud-attention-2.svg b/scudcloud-1.0/systray/hicolor/scudcloud-attention-2.svg deleted file mode 100644 index fa43211..0000000 --- a/scudcloud-1.0/systray/hicolor/scudcloud-attention-2.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 2 - - - diff --git a/scudcloud-1.0/systray/hicolor/scudcloud-attention-3.svg b/scudcloud-1.0/systray/hicolor/scudcloud-attention-3.svg deleted file mode 100644 index b15cfb5..0000000 --- a/scudcloud-1.0/systray/hicolor/scudcloud-attention-3.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 3 - - - diff --git a/scudcloud-1.0/systray/hicolor/scudcloud-attention-4.svg b/scudcloud-1.0/systray/hicolor/scudcloud-attention-4.svg deleted file mode 100644 index d046544..0000000 --- a/scudcloud-1.0/systray/hicolor/scudcloud-attention-4.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 4 - - - diff --git a/scudcloud-1.0/systray/hicolor/scudcloud-attention-5.svg b/scudcloud-1.0/systray/hicolor/scudcloud-attention-5.svg deleted file mode 100644 index d260e59..0000000 --- a/scudcloud-1.0/systray/hicolor/scudcloud-attention-5.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 5 - - - diff --git a/scudcloud-1.0/systray/hicolor/scudcloud-attention-6.svg b/scudcloud-1.0/systray/hicolor/scudcloud-attention-6.svg deleted file mode 100644 index 896507f..0000000 --- a/scudcloud-1.0/systray/hicolor/scudcloud-attention-6.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 6 - - - diff --git a/scudcloud-1.0/systray/hicolor/scudcloud-attention-7.svg b/scudcloud-1.0/systray/hicolor/scudcloud-attention-7.svg deleted file mode 100644 index 7424c32..0000000 --- a/scudcloud-1.0/systray/hicolor/scudcloud-attention-7.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 7 - - - diff --git a/scudcloud-1.0/systray/hicolor/scudcloud-attention-8.svg b/scudcloud-1.0/systray/hicolor/scudcloud-attention-8.svg deleted file mode 100644 index ee41c9d..0000000 --- a/scudcloud-1.0/systray/hicolor/scudcloud-attention-8.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 8 - - - diff --git a/scudcloud-1.0/systray/hicolor/scudcloud-attention-9-plus.svg b/scudcloud-1.0/systray/hicolor/scudcloud-attention-9-plus.svg deleted file mode 100644 index 6e36967..0000000 --- a/scudcloud-1.0/systray/hicolor/scudcloud-attention-9-plus.svg +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 9 - - + - - diff --git a/scudcloud-1.0/systray/hicolor/scudcloud-attention-9.svg b/scudcloud-1.0/systray/hicolor/scudcloud-attention-9.svg deleted file mode 100644 index 6a8259c..0000000 --- a/scudcloud-1.0/systray/hicolor/scudcloud-attention-9.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 9 - - - diff --git a/scudcloud-1.0/systray/hicolor/scudcloud-attention.svg b/scudcloud-1.0/systray/hicolor/scudcloud-attention.svg deleted file mode 100644 index 7e48289..0000000 --- a/scudcloud-1.0/systray/hicolor/scudcloud-attention.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/scudcloud-1.0/systray/hicolor/scudcloud.svg b/scudcloud-1.0/systray/hicolor/scudcloud.svg deleted file mode 100644 index e982393..0000000 --- a/scudcloud-1.0/systray/hicolor/scudcloud.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-1.svg b/scudcloud-1.0/systray/mono-dark/scudcloud-attention-1.svg deleted file mode 100644 index 646bf31..0000000 --- a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-1.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 1 - - - diff --git a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-2.svg b/scudcloud-1.0/systray/mono-dark/scudcloud-attention-2.svg deleted file mode 100644 index fa43211..0000000 --- a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-2.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 2 - - - diff --git a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-3.svg b/scudcloud-1.0/systray/mono-dark/scudcloud-attention-3.svg deleted file mode 100644 index b15cfb5..0000000 --- a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-3.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 3 - - - diff --git a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-4.svg b/scudcloud-1.0/systray/mono-dark/scudcloud-attention-4.svg deleted file mode 100644 index d046544..0000000 --- a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-4.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 4 - - - diff --git a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-5.svg b/scudcloud-1.0/systray/mono-dark/scudcloud-attention-5.svg deleted file mode 100644 index d260e59..0000000 --- a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-5.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 5 - - - diff --git a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-6.svg b/scudcloud-1.0/systray/mono-dark/scudcloud-attention-6.svg deleted file mode 100644 index 896507f..0000000 --- a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-6.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 6 - - - diff --git a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-7.svg b/scudcloud-1.0/systray/mono-dark/scudcloud-attention-7.svg deleted file mode 100644 index 7424c32..0000000 --- a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-7.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 7 - - - diff --git a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-8.svg b/scudcloud-1.0/systray/mono-dark/scudcloud-attention-8.svg deleted file mode 100644 index ee41c9d..0000000 --- a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-8.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 8 - - - diff --git a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-9-plus.svg b/scudcloud-1.0/systray/mono-dark/scudcloud-attention-9-plus.svg deleted file mode 100644 index 6e36967..0000000 --- a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-9-plus.svg +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 9 - - + - - diff --git a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-9.svg b/scudcloud-1.0/systray/mono-dark/scudcloud-attention-9.svg deleted file mode 100644 index 6a8259c..0000000 --- a/scudcloud-1.0/systray/mono-dark/scudcloud-attention-9.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 9 - - - diff --git a/scudcloud-1.0/systray/mono-dark/scudcloud-attention.svg b/scudcloud-1.0/systray/mono-dark/scudcloud-attention.svg deleted file mode 100644 index 7e48289..0000000 --- a/scudcloud-1.0/systray/mono-dark/scudcloud-attention.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/scudcloud-1.0/systray/mono-dark/scudcloud.svg b/scudcloud-1.0/systray/mono-dark/scudcloud.svg deleted file mode 100644 index e982393..0000000 --- a/scudcloud-1.0/systray/mono-dark/scudcloud.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/scudcloud-1.0/systray/mono-light/scudcloud-attention-1.svg b/scudcloud-1.0/systray/mono-light/scudcloud-attention-1.svg deleted file mode 100644 index 646bf31..0000000 --- a/scudcloud-1.0/systray/mono-light/scudcloud-attention-1.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 1 - - - diff --git a/scudcloud-1.0/systray/mono-light/scudcloud-attention-2.svg b/scudcloud-1.0/systray/mono-light/scudcloud-attention-2.svg deleted file mode 100644 index fa43211..0000000 --- a/scudcloud-1.0/systray/mono-light/scudcloud-attention-2.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 2 - - - diff --git a/scudcloud-1.0/systray/mono-light/scudcloud-attention-3.svg b/scudcloud-1.0/systray/mono-light/scudcloud-attention-3.svg deleted file mode 100644 index b15cfb5..0000000 --- a/scudcloud-1.0/systray/mono-light/scudcloud-attention-3.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 3 - - - diff --git a/scudcloud-1.0/systray/mono-light/scudcloud-attention-4.svg b/scudcloud-1.0/systray/mono-light/scudcloud-attention-4.svg deleted file mode 100644 index d046544..0000000 --- a/scudcloud-1.0/systray/mono-light/scudcloud-attention-4.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 4 - - - diff --git a/scudcloud-1.0/systray/mono-light/scudcloud-attention-5.svg b/scudcloud-1.0/systray/mono-light/scudcloud-attention-5.svg deleted file mode 100644 index d260e59..0000000 --- a/scudcloud-1.0/systray/mono-light/scudcloud-attention-5.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 5 - - - diff --git a/scudcloud-1.0/systray/mono-light/scudcloud-attention-6.svg b/scudcloud-1.0/systray/mono-light/scudcloud-attention-6.svg deleted file mode 100644 index 896507f..0000000 --- a/scudcloud-1.0/systray/mono-light/scudcloud-attention-6.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 6 - - - diff --git a/scudcloud-1.0/systray/mono-light/scudcloud-attention-7.svg b/scudcloud-1.0/systray/mono-light/scudcloud-attention-7.svg deleted file mode 100644 index 7424c32..0000000 --- a/scudcloud-1.0/systray/mono-light/scudcloud-attention-7.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 7 - - - diff --git a/scudcloud-1.0/systray/mono-light/scudcloud-attention-8.svg b/scudcloud-1.0/systray/mono-light/scudcloud-attention-8.svg deleted file mode 100644 index ee41c9d..0000000 --- a/scudcloud-1.0/systray/mono-light/scudcloud-attention-8.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 8 - - - diff --git a/scudcloud-1.0/systray/mono-light/scudcloud-attention-9-plus.svg b/scudcloud-1.0/systray/mono-light/scudcloud-attention-9-plus.svg deleted file mode 100644 index 6e36967..0000000 --- a/scudcloud-1.0/systray/mono-light/scudcloud-attention-9-plus.svg +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 9 - - + - - diff --git a/scudcloud-1.0/systray/mono-light/scudcloud-attention-9.svg b/scudcloud-1.0/systray/mono-light/scudcloud-attention-9.svg deleted file mode 100644 index 6a8259c..0000000 --- a/scudcloud-1.0/systray/mono-light/scudcloud-attention-9.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - 9 - - - diff --git a/scudcloud-1.0/systray/mono-light/scudcloud-attention.svg b/scudcloud-1.0/systray/mono-light/scudcloud-attention.svg deleted file mode 100644 index 7e48289..0000000 --- a/scudcloud-1.0/systray/mono-light/scudcloud-attention.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/scudcloud-1.0/systray/mono-light/scudcloud.svg b/scudcloud-1.0/systray/mono-light/scudcloud.svg deleted file mode 100644 index 82eb22d..0000000 --- a/scudcloud-1.0/systray/mono-light/scudcloud.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/scudcloud-1.1/LICENSE b/scudcloud-1.1/LICENSE new file mode 100644 index 0000000..23fc66f --- /dev/null +++ b/scudcloud-1.1/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Rael G.C. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/scudcloud-1.1/VERSION b/scudcloud-1.1/VERSION new file mode 100644 index 0000000..9084fa2 --- /dev/null +++ b/scudcloud-1.1/VERSION @@ -0,0 +1 @@ +1.1.0 diff --git a/scudcloud-1.1/debian/changelog b/scudcloud-1.1/debian/changelog new file mode 100644 index 0000000..665d061 --- /dev/null +++ b/scudcloud-1.1/debian/changelog @@ -0,0 +1,683 @@ +scudcloud (1.1-0) trusty; urgency=medium + + * Fixing stuck in loading screen (#294) + * Implementing a proper Slack JS client (#292) + + -- Rael Gugelmin Cunha Thu, 19 Nov 2015 09:43:01 -0200 + +scudcloud (1.0-89) trusty; urgency=medium + + * Forgot to bump version + + -- Rael Gugelmin Cunha Sun, 01 Nov 2015 21:31:30 -0200 + +scudcloud (1.0-88) trusty; urgency=medium + + * Restoring wrapper timer to override notifications + + -- Rael Gugelmin Cunha Sun, 01 Nov 2015 10:27:18 -0200 + +scudcloud (1.0-87) trusty; urgency=medium + + * Re-enable desktop notifications on reconnect (#274) + + -- Rael Gugelmin Cunha Wed, 28 Oct 2015 08:47:13 -0200 + +scudcloud (1.0-86) trusty; urgency=medium + + * Set focus after switch teams (#268) + + -- Rael Gugelmin Cunha Sun, 25 Oct 2015 08:00:35 -0200 + +scudcloud (1.0-85) trusty; urgency=medium + + * Restore window when trying to run again (#66) + + -- Rael Gugelmin Cunha Wed, 21 Oct 2015 21:57:36 -0200 + +scudcloud (1.0-84) trusty; urgency=medium + + * Escape single quote on team icon (#264) + + -- Rael Gugelmin Cunha Sat, 17 Oct 2015 15:07:12 -0300 + +scudcloud (1.0-83) trusty; urgency=medium + + * Saving menubar state (#251) + + -- Rael Gugelmin Cunha Sat, 17 Oct 2015 07:42:55 -0300 + +scudcloud (1.0-82) trusty; urgency=medium + + * Escaping single quotes in leftpane JS (#258) + + -- Rael Gugelmin Cunha Thu, 15 Oct 2015 09:50:58 -0300 + +scudcloud (1.0-81) trusty; urgency=medium + + * Removing no more required libraries + * Updating Edit menu on team switch (#259) + + -- Rael Gugelmin Cunha Thu, 15 Oct 2015 07:23:25 -0300 + +scudcloud (1.0-80) trusty; urgency=medium + + * Small improvements + + -- Rael Gugelmin Cunha Thu, 15 Oct 2015 05:34:51 -0300 + +scudcloud (1.0-79) trusty; urgency=medium + + * Workaround for #250 + + -- Rael Gugelmin Cunha Mon, 12 Oct 2015 15:42:22 -0300 + +scudcloud (1.0-78) trusty; urgency=medium + + * Another attempt to minimize effects on reconnect scripts (#250) + + -- Rael Gugelmin Cunha Sat, 10 Oct 2015 21:25:51 -0300 + +scudcloud (1.0-77) trusty; urgency=medium + + * New attempt to fix suspend script (#250) + + -- Rael Gugelmin Cunha Fri, 09 Oct 2015 08:11:40 -0300 + +scudcloud (1.0-76) trusty; urgency=medium + + * Fixing resume from suspend script (#250) + + -- Rael Gugelmin Cunha Wed, 07 Oct 2015 07:45:15 -0300 + +scudcloud (1.0-75) trusty; urgency=medium + + * Fixing random team icon names (#249) + + -- Rael Gugelmin Cunha Mon, 05 Oct 2015 08:21:22 -0300 + +scudcloud (1.0-74) trusty; urgency=medium + + * Fixing fonts (#245) + + -- Rael Gugelmin Cunha Wed, 30 Sep 2015 23:15:13 -0300 + +scudcloud (1.0-73) trusty; urgency=medium + + * Make sure value returned by Speller.suggest is str (#244) + + -- Rael Gugelmin Cunha Wed, 30 Sep 2015 13:10:35 -0300 + +scudcloud (1.0-72) trusty; urgency=medium + + * Listening for resume event + + -- Rael Gugelmin Cunha Wed, 30 Sep 2015 09:01:13 -0300 + +scudcloud (1.0-71) trusty; urgency=medium + + * Fixing dictionary path checking (#241) + + -- Rael Gugelmin Cunha Tue, 29 Sep 2015 06:27:04 -0300 + +scudcloud (1.0-70) trusty; urgency=medium + + * Adding a timer to check server side reloads + * Allow the menubar to be hidden in non Unity environments (#233) + + -- Rael Gugelmin Cunha Fri, 25 Sep 2015 08:12:40 -0300 + +scudcloud (1.0-69) trusty; urgency=medium + + * Fixing crash when python3-hunspell is not present (#237) + + -- Rael Gugelmin Cunha Tue, 22 Sep 2015 19:54:47 -0300 + +scudcloud (1.0-68) trusty; urgency=medium + + * Adding HunSpell suggestions (#55) + + -- Rael Gugelmin Cunha Tue, 22 Sep 2015 16:30:14 -0300 + +scudcloud (1.0-67) trusty; urgency=medium + + * Fixing QuickList + + -- Rael Gugelmin Cunha Wed, 16 Sep 2015 20:37:26 -0300 + +scudcloud (1.0-66) trusty; urgency=medium + + * Adding team icon in notifications + * Trying to fix quicklist load on multiple teams + + -- Rael Gugelmin Cunha Wed, 16 Sep 2015 18:40:13 -0300 + +scudcloud (1.0-65) trusty; urgency=medium + + * Enabling Cache (#82) + + -- Rael Gugelmin Cunha Wed, 16 Sep 2015 10:01:59 -0300 + +scudcloud (1.0-64) trusty; urgency=medium + + * Several code improvements + * Fixing teams loading order (#201) + + -- Rael Gugelmin Cunha Fri, 11 Sep 2015 19:32:26 -0300 + +scudcloud (1.0-63) trusty; urgency=medium + + * Improving JS ScudCloud + * Small improvement in message counting + * Adding initial loading message in status bar (#158) + + -- Rael Gugelmin Cunha Tue, 08 Sep 2015 10:50:20 -0300 + +scudcloud (1.0-62) trusty; urgency=medium + + * Forgot to bump constant version before build package + + -- Rael Gugelmin Cunha Mon, 07 Sep 2015 14:28:57 -0300 + +scudcloud (1.0-61) trusty; urgency=medium + + * Add option to print version in command line (#186) + * Fixing 'Help and Feedback' and 'Help Center' on multiple teams + + -- Rael Gugelmin Cunha Mon, 07 Sep 2015 14:23:24 -0300 + +scudcloud (1.0-60) trusty; urgency=medium + + * Updating login.css + * Reducing JavaScript usage on channel switch + + -- Rael Gugelmin Cunha Mon, 07 Sep 2015 09:20:53 -0300 + +scudcloud (1.0-59) trusty; urgency=medium + + * Handling system interrupt signal (#199) + + -- Rael Gugelmin Cunha Thu, 03 Sep 2015 13:56:25 -0300 + +scudcloud (1.0-58) trusty; urgency=medium + + * Trying to re-enable notifications on page reload + + -- Rael Gugelmin Cunha Wed, 02 Sep 2015 16:45:09 -0300 + +scudcloud (1.0-57) trusty; urgency=medium + + * Ctrl+Tab and Ctrl+Shift+Tab to rotate through teams (#215) + + -- Rael Gugelmin Cunha Thu, 27 Aug 2015 09:46:05 -0300 + +scudcloud (1.0-56) trusty; urgency=medium + + * Allow relative path + * Re-enable desktop notifications on page reload (#163) + + -- Rael Gugelmin Cunha Thu, 13 Aug 2015 08:39:03 -0300 + +scudcloud (1.0-55) trusty; urgency=medium + + * Fixing notifications systray count (#192) + + -- Rael Gugelmin Cunha Thu, 06 Aug 2015 11:18:25 -0300 + +scudcloud (1.0-54) trusty; urgency=medium + + * Updating notifications to match Slack changes + + -- Rael Gugelmin Cunha Wed, 05 Aug 2015 11:02:58 -0300 + +scudcloud (1.0-53) trusty; urgency=medium + + * Fixing notifications count again (#164) + + -- Rael Gugelmin Cunha Sun, 02 Aug 2015 22:10:56 -0300 + +scudcloud (1.0-52) trusty; urgency=medium + + * Fixing code format error + + -- Rael Gugelmin Cunha Sun, 26 Jul 2015 00:14:59 -0300 + +scudcloud (1.0-51) trusty; urgency=medium + + * Using lambdas for dereferenced callbacks (fixes #170 #177) + * Updating unread counter on window focus + + -- Rael Gugelmin Cunha Sat, 25 Jul 2015 23:58:20 -0300 + +scudcloud (1.0-50) trusty; urgency=medium + + * Fixing quicklist and direct messages + + -- Rael Gugelmin Cunha Thu, 25 Jun 2015 14:45:00 -0300 + +scudcloud (1.0-49) trusty; urgency=medium + + * Update read messages (#164) + + -- Rael Gugelmin Cunha Wed, 24 Jun 2015 10:56:18 -0300 + +scudcloud (1.0-48) trusty; urgency=medium + + * Few changes to avoid loose desktop notifications + + -- Rael Gugelmin Cunha Tue, 23 Jun 2015 18:25:15 -0300 + +scudcloud (1.0-47) trusty; urgency=medium + + * Re-working notifications to not use a timer (reduces CPU usage) + + -- Rael Gugelmin Cunha Tue, 23 Jun 2015 13:51:29 -0300 + +scudcloud (1.0-46) trusty; urgency=medium + + * Making current team icon bigger + * Fixing integrations issues (#143) + * Adding option to disable plugins (#155) + + -- Rael Gugelmin Cunha Fri, 19 Jun 2015 11:33:22 -0300 + +scudcloud (1.0-45) trusty; urgency=medium + + * Fixing small issues while loading all teams + + -- Rael Gugelmin Cunha Thu, 18 Jun 2015 11:38:29 -0300 + +scudcloud (1.0-44) trusty; urgency=medium + + * Fixing fullscreen + + -- Rael Gugelmin Cunha Thu, 18 Jun 2015 10:16:09 -0300 + +scudcloud (1.0-43) trusty; urgency=medium + + * Restoring JS inception in all pages + + -- Rael Gugelmin Cunha Thu, 18 Jun 2015 10:02:39 -0300 + +scudcloud (1.0-42) trusty; urgency=medium + + * Auto login for multiple teams (#81) + * Some code improvements + + -- Rael Gugelmin Cunha Thu, 18 Jun 2015 09:13:11 -0300 + +scudcloud (1.0-41) trusty; urgency=medium + + * Adding FullScreen support (#129) + * Fixing stuck on Status (#147) + + -- Rael Gugelmin Cunha Wed, 17 Jun 2015 11:22:45 -0300 + +scudcloud (1.0-40) trusty; urgency=medium + + * Fixing first team icon + * Snippet support (#124) + + -- Rael Gugelmin Cunha Tue, 16 Jun 2015 15:08:05 -0300 + +scudcloud (1.0-39) trusty; urgency=medium + + * Proxy support (#102, #115) + + -- Rael Gugelmin Cunha Tue, 16 Jun 2015 07:52:52 -0300 + +scudcloud (1.0-38) trusty; urgency=low + + * Fixing preferences with multiple teams (#125) + * Enabling cache and storage (#82) + + -- Rael Gugelmin Cunha Wed, 10 Jun 2015 11:53:42 -0300 + +scudcloud (1.0-37) trusty; urgency=low + + * Add the option to start minized to tray (#122) + + -- Rael Gugelmin Cunha Sat, 30 May 2015 09:39:39 -0300 + +scudcloud (1.0-36) trusty; urgency=low + + * Fixing desktop file keywords + + -- Rael Gugelmin Cunha Thu, 21 May 2015 09:10:30 -0300 + +scudcloud (1.0-35) trusty; urgency=low + + * Fixing tray icon in KDE5 (#106) + + -- Rael Gugelmin Cunha Thu, 14 May 2015 12:38:13 -0300 + +scudcloud (1.0-34) trusty; urgency=low + + * Fixing categories (#107) + + -- Rael Gugelmin Cunha Thu, 14 May 2015 08:56:15 -0300 + +scudcloud (1.0-33) trusty; urgency=low + + * Fixing zoom for multiple teams (#103) + + -- Rael Gugelmin Cunha Tue, 12 May 2015 13:28:42 -0300 + +scudcloud (1.0-32) trusty; urgency=low + + * Restoring notification override in DOM ready; + + -- Rael Gugelmin Cunha Sat, 09 May 2015 16:01:13 -0300 + +scudcloud (1.0-31) trusty; urgency=low + + * Trying improve performance a bit + + -- Rael Gugelmin Cunha Fri, 08 May 2015 10:29:29 -0300 + +scudcloud (1.0-30) trusty; urgency=low + + * Better close shortcut behaviour (#70) + + -- Rael Gugelmin Cunha Sat, 02 May 2015 09:29:12 -0300 + +scudcloud (1.0-29) trusty; urgency=low + + * Improved notifications (#93) + + -- Rael Gugelmin Cunha Fri, 01 May 2015 19:27:17 -0300 + +scudcloud (1.0-28) trusty; urgency=low + + * Adding close shortcut (#70) + * Fixing URL whitelist regexp (#88) + + -- Rael Gugelmin Cunha Thu, 30 Apr 2015 15:06:10 -0300 + +scudcloud (1.0-27) trusty; urgency=low + + * Fixing Archives (#60) + * Optional notifications (#72) + * XDG config file (#73,#78) + * Team Icons (#80) + + -- Rael Gugelmin Cunha Sat, 25 Apr 2015 09:14:34 -0300 + +scudcloud (1.0-26) trusty; urgency=low + + * Saving last window settings (#49) + + -- Rael Gugelmin Cunha Sat, 04 Apr 2015 22:21:45 -0300 + +scudcloud (1.0-25) trusty; urgency=medium + + * SAML auth support (#44) + + -- Rael Gugelmin Cunha Tue, 31 Mar 2015 20:35:12 -0300 + +scudcloud (1.0-24) trusty; urgency=low + + * Enabling team switch at ctrl+ (#43) + + -- Rael Gugelmin Cunha Mon, 30 Mar 2015 08:53:19 -0300 + +scudcloud (1.0-23) trusty; urgency=medium + + * Applying same fix from #41 to LeftPane.alert + + -- Rael Gugelmin Cunha Mon, 23 Mar 2015 14:11:56 -0300 + +scudcloud (1.0-22) trusty; urgency=medium + + * Fixing LeftPane.stopAlert (#41) + + -- Rael Gugelmin Cunha Mon, 23 Mar 2015 08:03:03 -0300 + +scudcloud (1.0-21) trusty; urgency=low + + * Notification append(#38) + * Recommending fixed width font(#39) + * Mention notification on team switcher (#40) + + -- Rael Gugelmin Cunha Fri, 20 Mar 2015 20:44:25 -0300 + +scudcloud (1.0-20) trusty; urgency=low + + * Zoom(#30), better dependencies(#32), proper cleanup(#34), app icon(#35) + + -- Rael Gugelmin Cunha Wed, 18 Mar 2015 09:29:34 -0300 + +scudcloud (1.0-19) trusty; urgency=low + + * Fixing Notification JS error (#33) + + -- Rael Gugelmin Cunha Mon, 16 Mar 2015 16:28:59 -0300 + +scudcloud (1.0-18) trusty; urgency=low + + * Trying to override notifications on re-connect + + -- Rael Gugelmin Cunha Mon, 16 Mar 2015 08:47:27 -0300 + +scudcloud (1.0-17) trusty; urgency=low + + * Decoupling dependencies to make it work on Debian (#27) + + -- Rael Gugelmin Cunha Sun, 15 Mar 2015 15:17:30 -0300 + +scudcloud (1.0-16) trusty; urgency=low + + * Fixing startup error on minified JS + + -- Rael Gugelmin Cunha Fri, 13 Mar 2015 22:55:15 -0300 + +scudcloud (1.0-15) trusty; urgency=low + + * Trying speedup JS loading (#26) + + -- Rael Gugelmin Cunha Thu, 12 Mar 2015 17:20:02 -0300 + +scudcloud (1.0-14) trusty; urgency=low + + * Adding count to systray (#16) + + -- Rael Gugelmin Cunha Thu, 12 Mar 2015 10:33:49 -0300 + +scudcloud (1.0-13) trusty; urgency=low + + * Adding gir1.2-unity-5.0 as dependency (#24) + + -- Rael Gugelmin Cunha Wed, 11 Mar 2015 18:34:41 -0300 + +scudcloud (1.0-12) trusty; urgency=low + + * Fixing eventFilter + + -- Rael Gugelmin Cunha Wed, 11 Mar 2015 11:49:15 -0300 + +scudcloud (1.0-11) trusty; urgency=low + + * Fixing alert + + -- Rael Gugelmin Cunha Wed, 11 Mar 2015 11:20:25 -0300 + +scudcloud (1.0-10) trusty; urgency=low + + * Preventing steal focus (#22) and alert on new notifications (#23) + + -- Rael Gugelmin Cunha Wed, 11 Mar 2015 09:58:49 -0300 + +scudcloud (1.0-9) trusty; urgency=low + + * Improving Systray clicking (#17) + + -- Rael Gugelmin Cunha Tue, 10 Mar 2015 10:41:34 -0300 + +scudcloud (1.0-8) trusty; urgency=low + + * Adding missing file (qsingleapplication.py) + + -- Rael Gugelmin Cunha Tue, 10 Mar 2015 09:28:51 -0300 + +scudcloud (1.0-7) trusty; urgency=low + + * Multiple teams (#6); Improving support to Precise (#20) + + -- Rael Gugelmin Cunha Tue, 10 Mar 2015 08:53:58 -0300 + +scudcloud (1.0-6) trusty; urgency=low + + * Support for leff-clicks to restore/hide the tray icon (#17) + + -- Rael Gugelmin Cunha Fri, 06 Mar 2015 12:51:49 -0300 + +scudcloud (1.0-5) trusty; urgency=low + + * Close to Tray (#14) + + -- Rael Gugelmin Cunha Wed, 04 Mar 2015 22:32:09 -0300 + +scudcloud (1.0-4) trusty; urgency=low + + * Removing compiled files from package source (#13) + + -- Rael Gugelmin Cunha Wed, 04 Mar 2015 10:55:30 -0300 + +scudcloud (1.0-3) trusty; urgency=low + + * Adding support to other DEs (#12) + + -- Rael Gugelmin Cunha Wed, 04 Mar 2015 09:32:56 -0300 + +scudcloud (1.0-2) trusty; urgency=low + + * Fixing tray icon paths + + -- Rael Gugelmin Cunha Tue, 03 Mar 2015 18:31:44 -0300 + +scudcloud (1.0-1) trusty; urgency=low + + * Adding tray icon (#8) + + -- Rael Gugelmin Cunha Tue, 03 Mar 2015 13:19:01 -0300 + +scudcloud (0.9-20) trusty; urgency=low + + * Adding lato font (#11) + + -- Rael Gugelmin Cunha Sat, 28 Feb 2015 10:22:36 -0300 + +scudcloud (0.9-19) trusty; urgency=low + + * Adding spell checker (#9) + + -- Rael Gugelmin Cunha Fri, 27 Feb 2015 10:54:20 -0300 + +scudcloud (0.9-18) trusty; urgency=low + + * Fixing support for Google Authentication (#10) + + -- Rael Gugelmin Cunha Thu, 26 Feb 2015 21:24:38 -0300 + +scudcloud (0.9-17) trusty; urgency=low + + * Menus were not enabled after change channel + + -- Rael Gugelmin Cunha Wed, 25 Feb 2015 14:22:03 -0300 + +scudcloud (0.9-16) trusty; urgency=low + + * Adding window menus (#7) + + -- Rael Gugelmin Cunha Wed, 25 Feb 2015 09:25:49 -0300 + +scudcloud (0.9-15) trusty; urgency=low + + * Simple team switcher (#6) + + -- Rael Gugelmin Cunha Wed, 18 Feb 2015 22:56:05 -0200 + +scudcloud (0.9-14) trusty; urgency=low + + * Removing "New message in " from channel notification + + -- Rael Gugelmin Cunha Wed, 18 Feb 2015 19:32:50 -0200 + +scudcloud (0.9-13) trusty; urgency=low + + * Fixing channels quicklist (#5) + + -- Rael Gugelmin Cunha Wed, 18 Feb 2015 14:36:22 -0200 + +scudcloud (0.9-12) trusty; urgency=low + + * Adding webkit debug console option + + -- Rael Gugelmin Cunha Wed, 18 Feb 2015 11:42:21 -0200 + +scudcloud (0.9-11) trusty; urgency=low + + * Fixing package build after file renaming + + -- Rael Gugelmin Cunha Tue, 17 Feb 2015 18:48:29 -0200 + +scudcloud (0.9-10) trusty; urgency=low + + * Simple internal changes + + -- Rael Gugelmin Cunha Tue, 17 Feb 2015 18:43:23 -0200 + +scudcloud (0.9-9) trusty; urgency=low + + * Copy and paste images (#4) + + -- Rael Gugelmin Cunha Tue, 17 Feb 2015 16:58:09 -0200 + +scudcloud (0.9-8) trusty; urgency=low + + * Improving first signign (#3) + + -- Rael Gugelmin Cunha Sat, 14 Feb 2015 22:42:07 -0200 + +scudcloud (0.9-7) trusty; urgency=low + + * Adding # before channel name in quicklist + + -- Rael Gugelmin Cunha Thu, 12 Feb 2015 11:18:53 -0200 + +scudcloud (0.9-6) trusty; urgency=low + + * Quicklist for channels (#2); + + -- Rael Gugelmin Cunha Thu, 12 Feb 2015 10:29:22 -0200 + +scudcloud (0.9-5) trusty; urgency=low + + * Improving .desktop file + + -- Rael Gugelmin Cunha Wed, 11 Feb 2015 10:04:11 -0200 + +scudcloud (0.9-4) trusty; urgency=low + + * Open links in system browser (#1); Enabling clipboard access + + -- Rael Gugelmin Cunha Tue, 10 Feb 2015 21:40:10 -0200 + +scudcloud (0.9-3) trusty; urgency=low + + * Adding a wrapper to .pyc when python3 mime-type is not configured + + -- Rael Gugelmin Cunha Mon, 09 Feb 2015 22:10:01 -0200 + +scudcloud (0.9-2) trusty; urgency=low + + * Adding check for null cookies (usually at the first start) + + -- Rael Gugelmin Cunha Mon, 09 Feb 2015 20:56:26 -0200 + +scudcloud (0.9-1) trusty; urgency=low + + * Initial release + + -- Rael Gugelmin Cunha Mon, 09 Feb 2015 19:12:26 -0200 + diff --git a/scudcloud-1.1/debian/compat b/scudcloud-1.1/debian/compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/scudcloud-1.1/debian/compat @@ -0,0 +1 @@ +9 diff --git a/scudcloud-1.1/debian/control b/scudcloud-1.1/debian/control new file mode 100644 index 0000000..d25cae5 --- /dev/null +++ b/scudcloud-1.1/debian/control @@ -0,0 +1,26 @@ +Source: scudcloud +Section: utils +Priority: optional +Maintainer: Rael Gugelmin Cunha +Build-Depends: debhelper (>= 9) +Standards-Version: 3.9.5 +Homepage: https://github.com/raelgc/scudcloud + +Package: scudcloud +Architecture: all +Depends: libqtwebkit4 (>= 2.3.2), + python3, + python3-dbus, + python3-pyqt4, + xdg-utils, + ${misc:Depends} +Recommends: sni-qt, + fonts-lato, + gir1.2-unity-5.0, + libqtwebkit-qupzillaplugins, + python3-hunspell, + python3-gi, + ttf-mscorefonts-installer +Description: ScudCloud is a non official desktop client for Slack + ScudCloud is a non official desktop client for Slack. + Slack (http://slack.com) is a platform for team communication. diff --git a/scudcloud-1.1/debian/copyright b/scudcloud-1.1/debian/copyright new file mode 100644 index 0000000..e7d7564 --- /dev/null +++ b/scudcloud-1.1/debian/copyright @@ -0,0 +1,30 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: scudcloud +Source: https://github.com/raelgc/scudcloud + +Files: * +Copyright: 2015 Rael Gugelmin Cunha +License: MIT + +Files: debian/* +Copyright: 2015 Rael Gugelmin Cunha +License: MIT + +License: MIT + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/scudcloud-1.1/debian/install b/scudcloud-1.1/debian/install new file mode 100644 index 0000000..aa6e8be --- /dev/null +++ b/scudcloud-1.1/debian/install @@ -0,0 +1,9 @@ +LICENSE opt/scudcloud +VERSION opt/scudcloud +lib/*.py opt/scudcloud/lib +resources/* opt/scudcloud/resources +scudcloud opt/scudcloud +scudcloud.desktop usr/share/applications +systray/hicolor/* usr/share/icons/hicolor/scalable/apps +systray/mono-dark/* usr/share/icons/ubuntu-mono-dark/scalable/apps +systray/mono-light/* usr/share/icons/ubuntu-mono-light/scalable/apps diff --git a/scudcloud-1.1/debian/postinst b/scudcloud-1.1/debian/postinst new file mode 100755 index 0000000..6a8ffa7 --- /dev/null +++ b/scudcloud-1.1/debian/postinst @@ -0,0 +1,41 @@ +#!/bin/sh +# postinst script for scudcloud +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + python3 -m compileall /opt/scudcloud/lib/ + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + diff --git a/scudcloud-1.1/debian/postrm b/scudcloud-1.1/debian/postrm new file mode 100644 index 0000000..1ad8f31 --- /dev/null +++ b/scudcloud-1.1/debian/postrm @@ -0,0 +1,39 @@ +#!/bin/sh +# postrm script for scudcloud +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `purge' +# * `upgrade' +# * `failed-upgrade' +# * `abort-install' +# * `abort-install' +# * `abort-upgrade' +# * `disappear' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + xdg-icon-resource forceupdate + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + diff --git a/scudcloud-1.1/debian/prerm b/scudcloud-1.1/debian/prerm new file mode 100644 index 0000000..ff915b2 --- /dev/null +++ b/scudcloud-1.1/debian/prerm @@ -0,0 +1,39 @@ +#!/bin/sh +# prerm script for scudcloud +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + rm -Rf /opt/scudcloud/lib/__pycache__ + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/scudcloud-1.1/debian/rules b/scudcloud-1.1/debian/rules new file mode 100755 index 0000000..79fd842 --- /dev/null +++ b/scudcloud-1.1/debian/rules @@ -0,0 +1,8 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +%: + dh $@ diff --git a/scudcloud-1.1/debian/scudcloud.links b/scudcloud-1.1/debian/scudcloud.links new file mode 100644 index 0000000..f8078d1 --- /dev/null +++ b/scudcloud-1.1/debian/scudcloud.links @@ -0,0 +1 @@ +/opt/scudcloud/scudcloud /usr/bin/scudcloud diff --git a/scudcloud-1.1/leftpane-src.js b/scudcloud-1.1/leftpane-src.js new file mode 100644 index 0000000..5e735a6 --- /dev/null +++ b/scudcloud-1.1/leftpane-src.js @@ -0,0 +1,68 @@ +var LeftPane = { + addTeam: function(id, name, url, icon, active){ + var node = document.getElementById(id); + if(node === null){ + var ul = document.getElementById('teams'); + li = document.createElement('li'); + li.id = id; + li.setAttribute("onclick", "LeftPane.switchTo('"+id.replace(/'/g, '"')+"','"+url.replace(/'/g, '"')+"')"); + li.setAttribute("title", name); + li.innerHTML = name[0]; + if( icon ){ + li.style.backgroundImage = "url('"+ icon.replace(/'/g, '"') +"')"; + li.innerHTML = ""; + } + ul.appendChild(li); + if(active){ + LeftPane.setActive(id); + } + LeftPane.switchTo(id, url); + } + }, + click: function(i){ + var list = document.getElementsByTagName("li"); + for(var j=0; j < list.length; j++){ + if(i==j){ + list[j].click(); + break; + } + } + }, + alert: function(team){ + document.getElementById(team).classList.add('alert'); + }, + stopAlert: function(team){ + document.getElementById(team).classList.remove('alert'); + }, + switchTo: function(id, url){ + leftPane.switchTo(url); + LeftPane.setActive(id); + }, + setActive: function(id){ + var list = document.getElementsByTagName("li"); + for(var i=0; i < list.length; i++){ + list[i].className = "inactive"; + } + document.getElementById(id).className = "active"; + }, + clickNext: function(direction){ + var list = document.getElementsByTagName("li"); + + var index = 0; + for(; index < list.length; index++){ + if (list[index].className == "active") { + break; + } + } + + index += direction; //goto next one + if (index >= list.length) { + index = 0; + } else if (index < 0) { + index = list.length - 1; + } + + LeftPane.click(index); + } +}; + diff --git a/scudcloud-1.1/lib/cookiejar.py b/scudcloud-1.1/lib/cookiejar.py new file mode 100644 index 0000000..bd355f2 --- /dev/null +++ b/scudcloud-1.1/lib/cookiejar.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +from PyQt4 import QtCore, QtNetwork + +class PersistentCookieJar(QtNetwork.QNetworkCookieJar): + + def __init__(self, parent): + super(PersistentCookieJar, self).__init__(parent) + self.mainWindow = parent + self.load() + self.save() + + def save(self): + listCookies = self.allCookies() + data = QtCore.QByteArray() + for cookie in listCookies: + if not cookie.isSessionCookie(): + data.append(cookie.toRawForm()+ "\n") + self.mainWindow.settings.setValue("Cookies",data) + + def load(self): + data = self.mainWindow.settings.value("Cookies") + if data is not None: + self.setAllCookies(QtNetwork.QNetworkCookie.parseCookies(data)) + diff --git a/scudcloud-1.1/lib/launcher.py b/scudcloud-1.1/lib/launcher.py new file mode 100644 index 0000000..8ab23cf --- /dev/null +++ b/scudcloud-1.1/lib/launcher.py @@ -0,0 +1,7 @@ +from PyQt4.Qt import QApplication + +class DummyLauncher: + def __init__(self, parent): + self.parent = parent + def set_property(self, name, value): + pass diff --git a/scudcloud-1.1/lib/leftpane.py b/scudcloud-1.1/lib/leftpane.py new file mode 100644 index 0000000..b2986c8 --- /dev/null +++ b/scudcloud-1.1/lib/leftpane.py @@ -0,0 +1,60 @@ +from resources import Resources +from PyQt4 import QtCore +from PyQt4.QtCore import QUrl +from PyQt4.QtWebKit import QWebView, QWebSettings + +class LeftPane(QWebView): + + def __init__(self, window): + QWebView.__init__(self) + self.window = window + with open(Resources.get_path("leftpane.js"), "r") as f: + self.js = f.read() + # We don't want plugins for this simple pane + self.settings().setAttribute(QWebSettings.PluginsEnabled, False) + self.reset() + + def reset(self): + self.setFixedWidth(0) + self.setVisible(False) + self.setUrl(QUrl.fromLocalFile(Resources.get_path("leftpane.html"))) + self.page().currentFrame().addToJavaScriptWindowObject("leftPane", self) + self.page().currentFrame().evaluateJavaScript(self.js) + + def show(self): + self.setFixedWidth(65) + self.setVisible(True) + + def hide(self): + self.setFixedWidth(0) + self.setVisible(False) + + def addTeam(self, id, name, url, icon, active=False): + if active is True: + checked = "true" + else: + checked = "false" + self.page().currentFrame().evaluateJavaScript("LeftPane.addTeam('"+id+"','"+name+"','"+url+"','"+icon+"',"+checked+");") + + def click(self, i): + self.page().currentFrame().evaluateJavaScript("LeftPane.click("+str(i)+");") + + def alert(self, team): + if team is not None: + self.page().currentFrame().evaluateJavaScript("LeftPane.alert('"+team+"');") + + def stopAlert(self, team): + if team is not None: + self.page().currentFrame().evaluateJavaScript("LeftPane.stopAlert('"+team+"');") + + def clickNext(self, direction): + self.page().currentFrame().evaluateJavaScript("LeftPane.clickNext("+str(direction)+");") + + @QtCore.pyqtSlot(str) + def switchTo(self, url): + self.window.switchTo(url) + + def contextMenuEvent(self, event): + pass + + diff --git a/scudcloud-1.1/lib/notifier.py b/scudcloud-1.1/lib/notifier.py new file mode 100644 index 0000000..a67ef5c --- /dev/null +++ b/scudcloud-1.1/lib/notifier.py @@ -0,0 +1,35 @@ +from dbus.exceptions import DBusException +try: + from gi.repository import Notify +except ImportError: + import notify2 + Notify = None + +class Notifier(object): + + def __init__(self, app_name, icon): + self.icon = icon + try: + if Notify is not None: + Notify.init(app_name) + self.notifier = Notify + else: + notify2.init(app_name) + self.notifier = notify2 + self.enabled = True + except DBusException: + print("WARNING: No notification daemon found! " + "Notifications will be ignored.") + self.enabled = False + + def notify(self, title, message, icon=None): + if not self.enabled: + return + if icon is None: + icon = self.icon + if Notify is not None: + notice = self.notifier.Notification.new(title, message, icon) + else: + notice = notify2.Notification(title, message, icon) + notice.set_hint_string('x-canonical-append', '') + notice.show() diff --git a/scudcloud-1.1/lib/notify2.py b/scudcloud-1.1/lib/notify2.py new file mode 100644 index 0000000..1b40269 --- /dev/null +++ b/scudcloud-1.1/lib/notify2.py @@ -0,0 +1,342 @@ +"""This is a pure-python replacement for notify-python, using python-dbus +to communicate with the notifications server directly. It's compatible with +Python 2 and 3, and its callbacks can work with Gtk 3 or Qt 4 applications. + +To use it, first call ``notify2.init('app name')``, then create and show notifications:: + + n = notify2.Notification("Summary", + "Some body text", + "notification-message-im" # Icon name + ) + n.show() + +To see more of what's possible, refer to docstrings of methods and objects. + +Based on the notifications spec at: +http://developer.gnome.org/notification-spec/ + +Porting applications from pynotify +---------------------------------- + +There are a few differences from pynotify you should be aware of: + +- If you need callbacks from notifications, notify2 must know about your event + loop. The simplest way is to pass 'glib' or 'qt' as the ``mainloop`` parameter + to ``init``. +- The methods ``attach_to_widget`` and ``attach_to_status_icon`` are not + implemented. You can calculate the location you want the notification to + appear and call ``Notification``. +- ``set_property`` and ``get_property`` are not implemented. The summary, body + and icon are accessible as attributes of a ``Notification`` instance. +- Various methods that pynotify Notification instances got from gobject do not + exist, or only implement part of the functionality. + +Several pynotify functions, especially getters and setters, are only supported +for compatibility. You are encouraged to use more direct, Pythonic alternatives. +""" + +import dbus + +# Constants +EXPIRES_DEFAULT = -1 +EXPIRES_NEVER = 0 + +URGENCY_LOW = 0 +URGENCY_NORMAL = 1 +URGENCY_CRITICAL = 2 +urgency_levels = [URGENCY_LOW, URGENCY_NORMAL, URGENCY_CRITICAL] + +# Initialise the module (following pynotify's API) ----------------------------- + +initted = False +appname = "" +_have_mainloop = False + +class UninittedError(RuntimeError): + pass + +class UninittedDbusObj(object): + def __getattr__(self, name): + raise UninittedError("You must call notify2.init() before using the " + "notification features.") + +dbus_iface = UninittedDbusObj() + +def init(app_name, mainloop=None): + """Initialise the Dbus connection. + + To get callbacks from notifications, DBus must be integrated with a mainloop. + There are three ways to achieve this: + + - Set a default mainloop (dbus.set_default_main_loop) before calling init() + - Pass the mainloop parameter as a string 'glib' or 'qt' to integrate with + those mainloops. (N.B. passing 'qt' currently makes that the default dbus + mainloop, because that's the only way it seems to work.) + - Pass the mainloop parameter a DBus compatible mainloop instance, such as + dbus.mainloop.glib.DBusGMainLoop(). + + If you only want to display notifications, without receiving information + back from them, you can safely omit mainloop. + """ + global appname, initted, dbus_iface, _have_mainloop + + if mainloop == 'glib': + from dbus.mainloop.glib import DBusGMainLoop + mainloop = DBusGMainLoop() + elif mainloop == 'qt': + from dbus.mainloop.qt import DBusQtMainLoop + # For some reason, this only works if we make it the default mainloop + # for dbus. That might make life tricky for anyone trying to juggle two + # event loops, but I can't see any way round it. + mainloop = DBusQtMainLoop(set_as_default=True) + + bus = dbus.SessionBus(mainloop=mainloop) + + dbus_obj = bus.get_object('org.freedesktop.Notifications', + '/org/freedesktop/Notifications') + dbus_iface = dbus.Interface(dbus_obj, + dbus_interface='org.freedesktop.Notifications') + appname = app_name + initted = True + + if mainloop or dbus.get_default_main_loop(): + _have_mainloop = True + dbus_iface.connect_to_signal('ActionInvoked', _action_callback) + dbus_iface.connect_to_signal('NotificationClosed', _closed_callback) + + return True + +def is_initted(): + """Has init() been called? Only exists for compatibility with pynotify. + """ + return initted + +def get_app_name(): + """Return appname. Only exists for compatibility with pynotify. + """ + return appname + +def uninit(): + """Undo what init() does.""" + global initted, dbus_iface, _have_mainloop + initted = False + _have_mainloop = False + dbus_iface = UninittedDbusObj() + +# Retrieve basic server information -------------------------------------------- + +def get_server_caps(): + """Get a list of server capabilities. + """ + return [str(x) for x in dbus_iface.GetCapabilities()] + +def get_server_info(): + """Get basic information about the server. + """ + res = dbus_iface.GetServerInformation() + return {'name': str(res[0]), + 'vendor': str(res[1]), + 'version': str(res[2]), + 'spec-version': str(res[3]), + } + +# Action callbacks ------------------------------------------------------------- + +notifications_registry = {} + +def _action_callback(nid, action): + nid, action = int(nid), str(action) + n = notifications_registry[nid] + n._action_callback(action) + +def _closed_callback(nid, reason): + nid, reason = int(nid), int(reason) + n = notifications_registry[nid] + n._closed_callback(n) + del notifications_registry[nid] + +def no_op(*args): + """No-op function for callbacks. + """ + pass + +# Controlling notifications ---------------------------------------------------- + +class Notification(object): + id = 0 + timeout = -1 # -1 = server default settings + _closed_callback = no_op + + def __init__(self, summary, message='', icon=''): + self.summary = summary + self.message = message + self.icon = icon + self.hints = {} + self.actions = {} + self.data = {} # Any data the user wants to attach + + def show(self): + """Ask the server to show the notification. + """ + nid = dbus_iface.Notify(appname, # app_name (spec names) + self.id, # replaces_id + self.icon, # app_icon + self.summary, # summary + self.message, # body + self._make_actions_array(), # actions + self.hints, # hints + self.timeout, # expire_timeout + ) + + self.id = int(nid) + + if _have_mainloop: + notifications_registry[self.id] = self + return True + + def update(self, summary, message="", icon=None): + """Replace the summary and body of the notification, and optionally its + icon. You should call show() again after this to display the updated + notification. + """ + self.summary = summary + self.message = message + if icon is not None: + self.icon = icon + + def close(self): + """Ask the server to close this notification. + """ + if self.id != 0: + dbus_iface.CloseNotification(self.id) + + def set_hint(self, key, value): + """n.set_hint(key, value) <--> n.hints[key] = value + + Only exists for compatibility with pynotify. + """ + self.hints[key] = value + + set_hint_string = set_hint_int32 = set_hint_double = set_hint + + def set_hint_byte(self, key, value): + """Set a hint with a dbus byte value. The input value can be an + integer or a bytes string of length 1. + """ + self.hints[key] = dbus.Byte(value) + + def set_urgency(self, level): + """Set the urgency level to one of URGENCY_LOW, URGENCY_NORMAL or + URGENCY_CRITICAL. + """ + if level not in urgency_levels: + raise ValueError("Unknown urgency level specified", level) + self.set_hint_byte("urgency", level) + + def set_category(self, category): + """Set the 'category' hint for this notification. + """ + self.hints['category'] = category + + def set_timeout(self, timeout): + """Set the display duration in milliseconds, or one of the special + values EXPIRES_DEFAULT or EXPIRES_NEVER. + + Only exists for compatibility with pynotify; you can simply set:: + + n.timeout = 5000 + """ + if not isinstance(timeout, int): + raise TypeError("timeout value was not int", timeout) + self.timeout = timeout + + def get_timeout(self): + """Return the timeout value for this notification. + + Only exists for compatibility with pynotify; you can inspect the + timeout attribute directly. + """ + return self.timeout + + def add_action(self, action, label, callback, user_data=None): + """Add an action to the notification (if the server supports it). + + action : str + A brief key. + label : str + The text displayed on the action button + callback : callable + A function taking at 2-3 parameters: the Notification object, the + action key and (if specified) the user_data. + user_data : + An extra argument to pass to the callback. + """ + self.actions[action] = (label, callback, user_data) + + def _make_actions_array(self): + """Make the actions array to send over DBus. + """ + arr = [] + for action, (label, callback, user_data) in self.actions.items(): + arr.append(action) + arr.append(label) + return arr + + def _action_callback(self, action): + """Called when the user selects an action on the notification, to + dispatch it to the relevant user-specified callback. + """ + try: + label, callback, user_data = self.actions[action] + except KeyError: + return + + if user_data is None: + callback(self, action) + else: + callback(self, action, user_data) + + def connect(self, event, callback): + """Set the callback for the notification closing; the only valid value + for event is 'closed'. The API is compatible with pynotify. + """ + if event != 'closed': + raise ValueError("'closed' is the only valid value for event", event) + self._closed_callback = callback + + def set_data(self, key, value): + """n.set_data(key, value) <--> n.data[key] = value + + Only exists for compatibility with pynotify. + """ + self.data[key] = value + + def get_data(self, key): + """n.get_data(key) <--> n.data[key] + + Only exists for compatibility with pynotify. + """ + return self.data[key] + + def set_icon_from_pixbuf(self, icon): + """Set a custom icon from a GdkPixbuf. + """ + struct = ( + icon.get_width(), + icon.get_height(), + icon.get_rowstride(), + icon.get_has_alpha(), + icon.get_bits_per_sample(), + icon.get_n_channels(), + dbus.ByteArray(icon.get_pixels()) + ) + self.hints['icon_data'] = struct + + def set_location(self, x, y): + """Set the notification location as (x, y), if the server supports it. + """ + if (not isinstance(x, int)) or (not isinstance(y, int)): + raise TypeError("x and y must both be ints", (x,y)) + self.hints['x'] = x + self.hints['y'] = y + diff --git a/scudcloud-1.1/lib/resources.py b/scudcloud-1.1/lib/resources.py new file mode 100644 index 0000000..f9835d8 --- /dev/null +++ b/scudcloud-1.1/lib/resources.py @@ -0,0 +1,19 @@ +import os, re + +class Resources: + + APP_NAME = "ScudCloud Slack_SSB" + SIGNIN_URL = "https://slack.com/signin" + MAINPAGE_URL_RE = re.compile(r'^http[s]://[a-zA-Z0-9_\-]+.slack.com/?$') + MESSAGES_URL_RE = re.compile(r'^http[s]://[a-zA-Z0-9_\-]+.slack.com/messages/.*') + SSO_URL_RE = re.compile(r'^http[s]://[a-zA-Z0-9_\-]+.slack.com/sso/saml/start$') + SERVICES_URL_RE = re.compile(r'^http[s]://[a-zA-Z0-9_\-]+.slack.com/services/.*') + + SPELL_DICT_PATH = "/usr/share/hunspell/" + SPELL_LIMIT = 6 + + # It's initialized in /scudcloud script + INSTALL_DIR = None + + def get_path(filename): + return os.path.join(Resources.INSTALL_DIR, 'resources', filename) diff --git a/scudcloud-1.1/lib/scudcloud.py b/scudcloud-1.1/lib/scudcloud.py new file mode 100755 index 0000000..d53e04f --- /dev/null +++ b/scudcloud-1.1/lib/scudcloud.py @@ -0,0 +1,379 @@ +#!/usr/bin/env python3 +import sys, os, time +from cookiejar import PersistentCookieJar +from leftpane import LeftPane +from notifier import Notifier +from resources import Resources +from speller import Speller +from systray import Systray +from wrapper import Wrapper +from threading import Thread +from PyQt4 import QtCore, QtGui, QtWebKit +from PyQt4.Qt import QApplication, QKeySequence, QTimer +from PyQt4.QtCore import QUrl, QSettings +from PyQt4.QtWebKit import QWebSettings, QWebPage +from PyQt4.QtNetwork import QNetworkDiskCache + +# Auto-detection of Unity and Dbusmenu in gi repository +try: + from gi.repository import Unity, Dbusmenu +except ImportError: + Unity = None + Dbusmenu = None + from launcher import DummyLauncher + +class ScudCloud(QtGui.QMainWindow): + + plugins = True + debug = False + forceClose = False + messages = 0 + speller = Speller() + + def __init__(self, parent = None, settings_path = ""): + super(ScudCloud, self).__init__(parent) + self.setWindowTitle('ScudCloud') + self.settings_path = settings_path + self.notifier = Notifier(Resources.APP_NAME, Resources.get_path('scudcloud.png')) + self.settings = QSettings(self.settings_path + '/scudcloud.cfg', QSettings.IniFormat) + self.identifier = self.settings.value("Domain") + if Unity is not None: + self.launcher = Unity.LauncherEntry.get_for_desktop_id("scudcloud.desktop") + else: + self.launcher = DummyLauncher(self) + self.webSettings() + self.leftPane = LeftPane(self) + self.stackedWidget = QtGui.QStackedWidget() + centralWidget = QtGui.QWidget(self) + layout = QtGui.QHBoxLayout() + layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(0) + layout.addWidget(self.leftPane) + layout.addWidget(self.stackedWidget) + centralWidget.setLayout(layout) + self.setCentralWidget(centralWidget) + self.startURL = Resources.SIGNIN_URL + if self.identifier is not None: + self.startURL = self.domain() + self.addWrapper(self.startURL) + self.addMenu() + self.tray = Systray(self) + self.systray(ScudCloud.minimized) + self.installEventFilter(self) + self.statusBar().showMessage('Loading Slack...') + + def addWrapper(self, url): + webView = Wrapper(self) + webView.page().networkAccessManager().setCookieJar(self.cookiesjar) + webView.page().networkAccessManager().setCache(self.diskCache) + webView.load(QtCore.QUrl(url)) + webView.show() + self.stackedWidget.addWidget(webView) + self.stackedWidget.setCurrentWidget(webView) + + def webSettings(self): + self.cookiesjar = PersistentCookieJar(self) + self.zoom = self.readZoom() + # Required by Youtube videos (HTML5 video support only on Qt5) + QWebSettings.globalSettings().setAttribute(QWebSettings.PluginsEnabled, self.plugins) + # We don't want Java + QWebSettings.globalSettings().setAttribute(QWebSettings.JavaEnabled, False) + # We don't need History + QWebSettings.globalSettings().setAttribute(QWebSettings.PrivateBrowsingEnabled, True) + # Enabling Local Storage (now required by Slack) + QWebSettings.globalSettings().setAttribute(QWebSettings.LocalStorageEnabled, True) + # Enabling Cache + self.diskCache = QNetworkDiskCache(self) + self.diskCache.setCacheDirectory(self.settings_path) + # Required for copy and paste clipboard integration + QWebSettings.globalSettings().setAttribute(QWebSettings.JavascriptCanAccessClipboard, True) + # Enabling Inspeclet only when --debug=True (requires more CPU usage) + QWebSettings.globalSettings().setAttribute(QWebSettings.DeveloperExtrasEnabled, self.debug) + + def toggleFullScreen(self): + if self.isFullScreen(): + self.showMaximized() + else: + self.showFullScreen() + + def toggleMenuBar(self): + menu = self.menuBar() + state = menu.isHidden() + menu.setVisible(state) + if state: + self.settings.setValue("Menu", "False") + else: + self.settings.setValue("Menu", "True") + + def restore(self): + geometry = self.settings.value("geometry") + if geometry is not None: + self.restoreGeometry(geometry) + windowState = self.settings.value("windowState") + if windowState is not None: + self.restoreState(windowState) + else: + self.setWindowState(QtCore.Qt.WindowMaximized) + + def systray(self, show=None): + if show is None: + show = self.settings.value("Systray") == "True" + if show: + self.tray.show() + self.menus["file"]["close"].setEnabled(True) + self.settings.setValue("Systray", "True") + else: + self.tray.setVisible(False) + self.menus["file"]["close"].setEnabled(False) + self.settings.setValue("Systray", "False") + + def readZoom(self): + default = 1 + if self.settings.value("Zoom") is not None: + default = float(self.settings.value("Zoom")) + return default + + def setZoom(self, factor=1): + if factor > 0: + for i in range(0, self.stackedWidget.count()): + widget = self.stackedWidget.widget(i) + widget.setZoomFactor(factor) + self.settings.setValue("Zoom", factor) + + def zoomIn(self): + self.setZoom(self.current().zoomFactor() + 0.1) + + def zoomOut(self): + self.setZoom(self.current().zoomFactor() - 0.1) + + def zoomReset(self): + self.setZoom() + + def addMenu(self): + self.menus = { + "file": { + "preferences": self.createAction("Preferences", lambda : self.current().preferences()), + "systray": self.createAction("Close to Tray", self.systray, None, True), + "addTeam": self.createAction("Sign in to Another Team", lambda : self.switchTo(Resources.SIGNIN_URL)), + "signout": self.createAction("Signout", lambda : self.current().logout()), + "close": self.createAction("Close", self.close, QKeySequence.Close), + "exit": self.createAction("Quit", self.exit, QKeySequence.Quit) + }, + "edit": { + }, + "view": { + "zoomin": self.createAction("Zoom In", self.zoomIn, QKeySequence.ZoomIn), + "zoomout": self.createAction("Zoom Out", self.zoomOut, QKeySequence.ZoomOut), + "reset": self.createAction("Reset", self.zoomReset, QtCore.Qt.CTRL + QtCore.Qt.Key_0), + "fullscreen": self.createAction("Toggle Full Screen", self.toggleFullScreen, QtCore.Qt.Key_F11), + "hidemenu": self.createAction("Toggle Menubar", self.toggleMenuBar, QtCore.Qt.Key_F12) + }, + "help": { + "help": self.createAction("Help and Feedback", lambda : self.current().help(), QKeySequence.HelpContents), + "center": self.createAction("Slack Help Center", lambda : self.current().helpCenter()), + "about": self.createAction("About", lambda : self.current().about()) + } + } + menu = self.menuBar() + fileMenu = menu.addMenu("&File") + fileMenu.addAction(self.menus["file"]["preferences"]) + fileMenu.addAction(self.menus["file"]["systray"]) + fileMenu.addSeparator() + fileMenu.addAction(self.menus["file"]["addTeam"]) + fileMenu.addAction(self.menus["file"]["signout"]) + fileMenu.addSeparator() + fileMenu.addAction(self.menus["file"]["close"]) + fileMenu.addAction(self.menus["file"]["exit"]) + self.editMenu = menu.addMenu("&Edit") + self.updateEditMenu() + viewMenu = menu.addMenu("&View") + viewMenu.addAction(self.menus["view"]["zoomin"]) + viewMenu.addAction(self.menus["view"]["zoomout"]) + viewMenu.addAction(self.menus["view"]["reset"]) + viewMenu.addSeparator() + viewMenu.addAction(self.menus["view"]["fullscreen"]) + if Unity is None: + viewMenu.addAction(self.menus["view"]["hidemenu"]) + helpMenu = menu.addMenu("&Help") + helpMenu.addAction(self.menus["help"]["help"]) + helpMenu.addAction(self.menus["help"]["center"]) + helpMenu.addSeparator() + helpMenu.addAction(self.menus["help"]["about"]) + self.enableMenus(False) + showSystray = self.settings.value("Systray") == "True" + self.menus["file"]["systray"].setChecked(showSystray) + self.menus["file"]["close"].setEnabled(showSystray) + # Restore menu visibility + visible = self.settings.value("Menu") + if visible is not None and visible == "False": + menu.setVisible(False) + + def enableMenus(self, enabled): + self.menus["file"]["preferences"].setEnabled(enabled == True) + self.menus["file"]["addTeam"].setEnabled(enabled == True) + self.menus["file"]["signout"].setEnabled(enabled == True) + self.menus["help"]["help"].setEnabled(enabled == True) + + def updateEditMenu(self): + self.editMenu.clear() + self.menus["edit"] = { + "undo": self.current().pageAction(QtWebKit.QWebPage.Undo), + "redo": self.current().pageAction(QtWebKit.QWebPage.Redo), + "cut": self.current().pageAction(QtWebKit.QWebPage.Cut), + "copy": self.current().pageAction(QtWebKit.QWebPage.Copy), + "paste": self.current().pageAction(QtWebKit.QWebPage.Paste), + "back": self.current().pageAction(QtWebKit.QWebPage.Back), + "forward": self.current().pageAction(QtWebKit.QWebPage.Forward), + "reload": self.current().pageAction(QtWebKit.QWebPage.Reload) + } + self.editMenu.addAction(self.menus["edit"]["undo"]) + self.editMenu.addAction(self.menus["edit"]["redo"]) + self.editMenu.addSeparator() + self.editMenu.addAction(self.menus["edit"]["cut"]) + self.editMenu.addAction(self.menus["edit"]["copy"]) + self.editMenu.addAction(self.menus["edit"]["paste"]) + self.editMenu.addSeparator() + self.editMenu.addAction(self.menus["edit"]["back"]) + self.editMenu.addAction(self.menus["edit"]["forward"]) + self.editMenu.addAction(self.menus["edit"]["reload"]) + + def createAction(self, text, slot, shortcut=None, checkable=False): + action = QtGui.QAction(text, self) + action.triggered.connect(slot) + if shortcut is not None: + action.setShortcut(shortcut) + self.addAction(action) + if checkable: + action.setCheckable(True) + return action + + def domain(self): + if self.identifier.endswith(".slack.com"): + return self.identifier + else: + return "https://"+self.identifier+".slack.com" + + def current(self): + return self.stackedWidget.currentWidget() + + def teams(self, teams): + for t in teams: + # If team_icon is not present, it's because team is already connected + if 'team_icon' in t: + self.leftPane.addTeam(t['id'], t['team_name'], t['team_url'], t['team_icon']['image_44'], t == teams[0]) + if len(teams) > 1: + self.leftPane.show() + + def switchTo(self, url): + exists = False + for i in range(0, self.stackedWidget.count()): + if self.stackedWidget.widget(i).url().toString().startswith(url): + self.stackedWidget.setCurrentIndex(i) + self.quicklist(self.current().listChannels()) + self.current().setFocus() + exists = True + break + if not exists: + self.addWrapper(url) + self.updateEditMenu() + + def eventFilter(self, obj, event): + if event.type() == QtCore.QEvent.ActivationChange and self.isActiveWindow(): + self.focusInEvent(event) + if event.type() == QtCore.QEvent.KeyPress: + # Ctrl + + modifiers = QtGui.QApplication.keyboardModifiers() + if modifiers == QtCore.Qt.ControlModifier: + if event.key() == QtCore.Qt.Key_1: self.leftPane.click(0) + elif event.key() == QtCore.Qt.Key_2: self.leftPane.click(1) + elif event.key() == QtCore.Qt.Key_3: self.leftPane.click(2) + elif event.key() == QtCore.Qt.Key_4: self.leftPane.click(3) + elif event.key() == QtCore.Qt.Key_5: self.leftPane.click(4) + elif event.key() == QtCore.Qt.Key_6: self.leftPane.click(5) + elif event.key() == QtCore.Qt.Key_7: self.leftPane.click(6) + elif event.key() == QtCore.Qt.Key_8: self.leftPane.click(7) + elif event.key() == QtCore.Qt.Key_9: self.leftPane.click(8) + # Ctrl + Tab + elif event.key() == QtCore.Qt.Key_Tab: self.leftPane.clickNext(1) + # Ctrl + BackTab + if (modifiers & QtCore.Qt.ControlModifier) and (modifiers & QtCore.Qt.ShiftModifier): + if event.key() == QtCore.Qt.Key_Backtab: self.leftPane.clickNext(-1) + # Ctrl + Shift + + if (modifiers & QtCore.Qt.ShiftModifier) and (modifiers & QtCore.Qt.ShiftModifier): + if event.key() == QtCore.Qt.Key_V: self.current().createSnippet() + return QtGui.QMainWindow.eventFilter(self, obj, event); + + def focusInEvent(self, event): + self.launcher.set_property("urgent", False) + self.tray.stopAlert() + + def titleChanged(self): + self.setWindowTitle(self.current().title()) + + def closeEvent(self, event): + if not self.forceClose and self.settings.value("Systray") == "True": + self.hide() + event.ignore() + else: + self.cookiesjar.save() + self.settings.setValue("geometry", self.saveGeometry()) + self.settings.setValue("windowState", self.saveState()) + # Let's save the first team registered as default + qUrl = self.stackedWidget.widget(0).url() + if self.identifier is None and Resources.MESSAGES_URL_RE.match(qUrl.toString()): + self.settings.setValue("Domain", 'https://'+qUrl.host()) + + def show(self): + self.setWindowState(self.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive) + self.activateWindow() + self.setVisible(True) + + def exit(self): + self.forceClose = True + self.close() + + def quicklist(self, channels): + if Dbusmenu is not None: + if channels is not None: + ql = Dbusmenu.Menuitem.new() + self.launcher.set_property("quicklist", ql) + for c in channels: + if c['is_member']: + item = Dbusmenu.Menuitem.new () + item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, "#"+c['name']) + item.property_set ("id", c['name']) + item.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, True) + item.connect(Dbusmenu.MENUITEM_SIGNAL_ITEM_ACTIVATED, self.current().openChannel) + ql.child_append(item) + self.launcher.set_property("quicklist", ql) + + def notify(self, title, message, icon=None): + self.notifier.notify(title, message, icon) + self.alert() + + def alert(self): + if not self.isActiveWindow(): + self.launcher.set_property("urgent", True) + self.tray.alert() + + def count(self): + total = 0 + for i in range(0, self.stackedWidget.count()): + widget = self.stackedWidget.widget(i) + messages = widget.highlights + if messages == 0: + self.leftPane.stopAlert(widget.team()) + else: + self.leftPane.alert(widget.team()) + if messages is not None: + total+=messages + if total > self.messages: + self.alert() + if 0 == total: + self.launcher.set_property("count_visible", False) + self.tray.setCounter(0) + else: + self.tray.setCounter(total) + self.launcher.set_property("count", total) + self.launcher.set_property("count_visible", True) + self.messages = total diff --git a/scudcloud-1.1/lib/speller.py b/scudcloud-1.1/lib/speller.py new file mode 100644 index 0000000..e60967c --- /dev/null +++ b/scudcloud-1.1/lib/speller.py @@ -0,0 +1,90 @@ +import os +from resources import Resources +from PyQt4 import QtGui +from PyQt4.QtCore import QObject +from PyQt4.QtCore import QLocale, QFile, QTextBoundaryFinder + +# Checking if python-hunspell is present +try: + import hunspell +except ImportError: + class hunspell: + HunSpell = None + +# Simplified version of QupZilla Speller (https://github.com/QupZilla/qupzilla/blob/v1.8/src/lib/plugins/qtwebkit/spellcheck/speller.cpp) +class Speller(QObject): + + hunspell = None + initialized = False + startPos = 0 + + def __init__(self): + super(Speller, self).__init__() + if self.initialized or hunspell.HunSpell is None: + return + dictionaryPath = self.getDictionaryPath() + language = self.parseLanguage(dictionaryPath) + if not dictionaryPath or language is None: + return + self.hunspell = hunspell.HunSpell(dictionaryPath + ".dic", dictionaryPath + ".aff") + self.initialized = True + + def isMisspelled(self, s): + return not self.hunspell.spell(s) + + def suggest(self, s): + return self.hunspell.suggest(s) + + def parseLanguage(self, path): + if '/' in path: + pos = path.rfind('/') + return path[-int(pos + 1):] + return path + + def dictionaryExists(self, path): + return QFile(path + ".dic").exists() and QFile(path + ".aff").exists(); + + def getDictionaryPath(self): + dicPath = Resources.SPELL_DICT_PATH + QLocale.system().name() + if self.dictionaryExists(dicPath): + return dicPath + return '' + + def replaceWord(self, element, word): + action = self.sender() + new = action.data() + text = str(element.evaluateJavaScript("this.value")) + cursorPos = int(element.evaluateJavaScript("this.selectionStart")) + text = text[:self.startPos] + new + text[self.startPos+len(word):] + text = text.replace('\\', "\\\\") + text = text.replace('\n', "\\n") + text = text.replace('\'', "\\'") + element.evaluateJavaScript("this.value='{}'".format(text)) + element.evaluateJavaScript("this.selectionStart=this.selectionEnd={}".format(cursorPos)) + + def getWord(self, element): + text = str(element.evaluateJavaScript("this.value")) + pos = int(int(element.evaluateJavaScript("this.selectionStart")) + int(1)) + finder = QTextBoundaryFinder(QTextBoundaryFinder.Word, text) + finder.setPosition(pos) + self.startPos = finder.toPreviousBoundary() + return text[self.startPos:finder.toNextBoundary()].strip() + + def populateContextMenu(self, menu, element): + word = self.getWord(element) + if self.isMisspelled(word): + suggests = self.suggest(word) + count = Resources.SPELL_LIMIT + if len(suggests) < count: + count = len(suggests) + boldFont = menu.font() + boldFont.setBold(True) + for i in range(0, count): + action = QtGui.QAction(str(suggests[i]), self) + action.triggered.connect(lambda:self.replaceWord(element, word)) + action.setData(suggests[i]) + action.setFont(boldFont) + menu.addAction(action) + if count == 0: + menu.addAction(menu.tr("No suggestions")).setEnabled(False) + menu.addSeparator(); diff --git a/scudcloud-1.1/lib/systray.py b/scudcloud-1.1/lib/systray.py new file mode 100644 index 0000000..567a249 --- /dev/null +++ b/scudcloud-1.1/lib/systray.py @@ -0,0 +1,57 @@ +from PyQt4 import QtCore, QtGui +from resources import Resources +import scudcloud + +class Systray(QtGui.QSystemTrayIcon): + + urgent = False + + def __init__(self, window): + super(Systray, self).__init__(QtGui.QIcon.fromTheme("scudcloud"), window) + self.connect(self, QtCore.SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.activatedEvent) + self.window = window + self.setToolTip('ScudCloud') + self.menu = QtGui.QMenu(self.window) + self.menu.addAction('Show', self.restore) + if scudcloud.Unity is None: + self.menu.addAction('Toggle Menubar', self.toggleMenuBar) + self.menu.addSeparator() + self.menu.addAction(self.window.menus["file"]["preferences"]) + self.menu.addAction(self.window.menus["help"]["about"]) + self.menu.addSeparator() + self.menu.addAction(self.window.menus["file"]["exit"]) + self.setContextMenu(self.menu) + + def alert(self): + if not self.urgent: + self.urgent = True + self.setIcon(QtGui.QIcon.fromTheme("scudcloud-attention")) + + def stopAlert(self): + self.urgent = False + self.setIcon(QtGui.QIcon.fromTheme("scudcloud")) + + def setCounter(self, i): + if 0 == i: + if True == self.urgent: + self.setIcon(QtGui.QIcon.fromTheme("scudcloud-attention")) + else: + self.setIcon(QtGui.QIcon.fromTheme("scudcloud")) + elif i > 0 and i < 10: + self.setIcon(QtGui.QIcon.fromTheme("scudcloud-attention-"+str(int(i)))) + elif i > 9: + self.setIcon(QtGui.QIcon.fromTheme("scudcloud-attention-9-plus")) + + def restore(self): + self.window.show() + self.stopAlert() + + def toggleMenuBar(self): + self.window.toggleMenuBar() + + def activatedEvent(self, reason): + if reason in [QtGui.QSystemTrayIcon.MiddleClick, QtGui.QSystemTrayIcon.Trigger]: + if self.window.isHidden() or self.window.isMinimized() or not self.window.isActiveWindow(): + self.restore() + else: + self.window.hide() diff --git a/scudcloud-1.1/lib/wrapper.py b/scudcloud-1.1/lib/wrapper.py new file mode 100644 index 0000000..9d1c348 --- /dev/null +++ b/scudcloud-1.1/lib/wrapper.py @@ -0,0 +1,183 @@ +import sys, subprocess, os, json, tempfile +from urllib import request +from urllib.parse import urlparse +from resources import Resources +from PyQt4 import QtWebKit, QtGui, QtCore +from PyQt4.Qt import QApplication, QKeySequence, QTimer +from PyQt4.QtCore import QBuffer, QByteArray, QUrl +from PyQt4.QtWebKit import QWebView, QWebPage, QWebSettings +from PyQt4.QtNetwork import QNetworkProxy + +class Wrapper(QWebView): + + highlights = 0 + icon = None + name = '' + + def __init__(self, window): + self.configure_proxy() + QWebView.__init__(self) + self.window = window + with open(Resources.get_path("scudcloud.js"), "r") as f: + self.js = f.read() + self.setZoomFactor(self.window.zoom) + self.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks) + self.urlChanged.connect(self._urlChanged) + self.loadStarted.connect(self._loadStarted) + self.loadFinished.connect(self._loadFinished) + self.linkClicked.connect(self._linkClicked) + self.page().featurePermissionRequested.connect(self.permissionRequested) + self.addActions() + + def permissionRequested(self, frame, feature): + self.page().setFeaturePermission(frame, feature, QWebPage.PermissionGrantedByUser) + self.overrideNotifications() + + def configure_proxy(self): + proxy = urlparse(os.environ.get('http_proxy') or os.environ.get('HTTP_PROXY')) + if proxy.hostname is not None and proxy.port is not None: + q_network_proxy = QNetworkProxy(QNetworkProxy.HttpProxy, proxy.hostname, proxy.port) + if proxy.username is not None: + q_network_proxy.setUser(proxy.username) + if proxy.password is not None: + q_network_proxy.setPassword(proxy.password) + QNetworkProxy.setApplicationProxy(q_network_proxy) + + def addActions(self): + self.pageAction(QWebPage.SetTextDirectionDefault).setVisible(False) + self.pageAction(QWebPage.SetTextDirectionLeftToRight).setVisible(False) + self.pageAction(QWebPage.SetTextDirectionRightToLeft).setVisible(False) + self.pageAction(QWebPage.Undo).setShortcuts(QKeySequence.Undo) + self.pageAction(QWebPage.Redo).setShortcuts(QKeySequence.Redo) + self.pageAction(QWebPage.Cut).setShortcuts(QKeySequence.Cut) + self.pageAction(QWebPage.Copy).setShortcuts(QKeySequence.Copy) + self.pageAction(QWebPage.Paste).setShortcuts(QKeySequence.Paste) + self.pageAction(QWebPage.Back).setShortcuts(QKeySequence.Back) + self.pageAction(QWebPage.Forward).setShortcuts(QKeySequence.Forward) + self.pageAction(QWebPage.Reload).setShortcuts(QKeySequence.Refresh) + + def contextMenuEvent(self, event): + menu = QtGui.QMenu(self) + if self.window.speller.initialized: + hit = self.page().currentFrame().hitTestContent(event.pos()) + element = hit.element() + if hit.isContentEditable() and not hit.isContentSelected() and element.attribute("type") != "password": + self.window.speller.populateContextMenu(menu, element) + pageMenu = self.page().createStandardContextMenu() + if pageMenu is not None: + for a in pageMenu.actions(): + if a.isSeparator(): + menu.addSeparator() + elif a.isVisible(): + menu.addAction(a) + del pageMenu + menu.exec_(event.globalPos()) + + def call(self, function, arg=None): + if isinstance(arg, str): + arg = "'"+arg+"'" + if arg is None: + arg = "" + return self.page().currentFrame().evaluateJavaScript("ScudCloud."+function+"("+arg+");") + + def _loadStarted(self): + # Some custom CSS to clean/fix UX + self.settings().setUserStyleSheetUrl(QUrl.fromLocalFile(Resources.get_path("resources.css"))) + + def _urlChanged(self, qUrl): + url = qUrl.toString() + # Some integrations/auth will get back to /services with no way to get back to chat + if Resources.SERVICES_URL_RE.match(url): + self.systemOpen(url) + self.load(QUrl("https://"+qUrl.host()+"/messages/general")) + + def _loadFinished(self, ok=True): + # Starting the webkit-JS bridge + self.page().currentFrame().addToJavaScriptWindowObject("desktop", self) + # Loading ScudCloud JS client + self.page().currentFrame().evaluateJavaScript(self.js) + self.window.statusBar().hide() + + def systemOpen(self, url): + subprocess.call(('xdg-open', url)) + + def _linkClicked(self, qUrl): + url = qUrl.toString() + handle_link = ( + Resources.SIGNIN_URL == url or + Resources.MAINPAGE_URL_RE.match(url) or + Resources.MESSAGES_URL_RE.match(url) or + Resources.SSO_URL_RE.match(url) or + url.startswith("https://accounts.google.com/o/oauth")) + if handle_link: + self.load(qUrl) + else: + self.systemOpen(url) + + def preferences(self): + self.window.show() + self.call("preferences") + + def createSnippet(self): + self.call("createSnippet") + + def team(self): + return self.call("getCurrentTeam") + + def logout(self): + self.call("logout") + + def help(self): + self.call("help") + + def helpCenter(self): + subprocess.call(('xdg-open', "https://slack.zendesk.com/hc/en-us")) + + def about(self): + subprocess.call(('xdg-open', "https://github.com/raelgc/scudcloud")) + + def listChannels(self): + return self.call("listChannels") + + def openChannel(self, menuitem, timestamp): + self.call("join", menuitem.property_get("id")) + self.window.show() + + @QtCore.pyqtSlot(int, int) + def count(self, highlight, unread): + self.highlights = highlight + self.window.count() + + @QtCore.pyqtSlot(str) + def populate(self, serialized): + data = json.loads(serialized) + self.window.teams(data['teams']) + if self.window.current() == self: + self.window.quicklist(data['channels']) + self.name = data['teams'][0]['team_name'] + filename, headers = request.urlretrieve(data['icon'], tempfile.gettempdir()+'/'+self.name+'.png') + self.icon = filename + + @QtCore.pyqtSlot(bool) + def enableMenus(self, enabled): + self.window.enableMenus(enabled) + + @QtCore.pyqtSlot(bool) + def pasted(self, checked): + clipboard = QApplication.clipboard() + mime = clipboard.mimeData() + if mime.hasImage(): + pixmap = clipboard.pixmap() + byteArray = QByteArray() + buffer = QBuffer(byteArray) + pixmap.save(buffer, "PNG") + self.call("setClipboard", str(byteArray.toBase64(), sys.stdout.encoding)) + + @QtCore.pyqtSlot(str, str) + def sendMessage(self, title, message): + erase = ['['+self.name.lower()+'] in ', '['+self.name.lower()+'] from '] + for s in erase: + title = str(title).replace(s, '', 1) + self.window.notify(title, str(message), self.icon) + + diff --git a/scudcloud-1.1/resources/leftpane.html b/scudcloud-1.1/resources/leftpane.html new file mode 100644 index 0000000..a845ef3 --- /dev/null +++ b/scudcloud-1.1/resources/leftpane.html @@ -0,0 +1,47 @@ + + + + + +
    +
+ + diff --git a/scudcloud-1.1/resources/leftpane.js b/scudcloud-1.1/resources/leftpane.js new file mode 100644 index 0000000..005a43e --- /dev/null +++ b/scudcloud-1.1/resources/leftpane.js @@ -0,0 +1 @@ +var LeftPane={addTeam:function(e,t,n,l,c){var i=document.getElementById(e);if(null===i){var a=document.getElementById("teams");li=document.createElement("li"),li.id=e,li.setAttribute("onclick","LeftPane.switchTo('"+e.replace(/'/g,""")+"','"+n.replace(/'/g,""")+"')"),li.setAttribute("title",t),li.innerHTML=t[0],l&&(li.style.backgroundImage="url('"+l.replace(/'/g,""")+"')",li.innerHTML=""),a.appendChild(li),c&&LeftPane.setActive(e),LeftPane.switchTo(e,n)}},click:function(e){for(var t=document.getElementsByTagName("li"),n=0;n=t.length?n=0:0>n&&(n=t.length-1),LeftPane.click(n)}}; diff --git a/scudcloud-1.1/resources/resources.css b/scudcloud-1.1/resources/resources.css new file mode 100644 index 0000000..bc30435 --- /dev/null +++ b/scudcloud-1.1/resources/resources.css @@ -0,0 +1,2 @@ +nav.top, footer, #prefs_mac_ssb_tab {display: none !important;} +* {font-family: Lato,"Helvetica Neue",Helvetica,"Segoe UI",Tahoma,Arial,sans-serif;} diff --git a/scudcloud-1.1/resources/scudcloud.js b/scudcloud-1.1/resources/scudcloud.js new file mode 100644 index 0000000..82a7621 --- /dev/null +++ b/scudcloud-1.1/resources/scudcloud.js @@ -0,0 +1 @@ +ScudCloud={unloaded:!0,hasPreference:function(n){return!1},getPreference:function(n){return!1},setPreference:function(n,e){return!1},canShowHtmlNotifications:function(){return!1},call:function(n,e){switch(ScudCloud.log(n),n){case"reload":return ScudCloud.reload();case"didStartLoading":return ScudCloud.didStartLoading();case"didFinishLoading":return ScudCloud.didFinishLoading();case"setConnectionStatus":return ScudCloud.setConnectionStatus(e);case"notify":return ScudCloud.notify(e);case"setBadgeCount":return ScudCloud.setBadgeCount(e);case"displayTeam":return ScudCloud.displayTeam(e)}return!1},reload:function(){window.location.reload()},didStartLoading:function(){},didFinishLoading:function(){TS.ui.banner.close(),ScudCloud.populate(),ScudCloud.unloaded=!1},setConnectionStatus:function(n){switch(n){case"online":desktop.enableMenus(!0);break;default:desktop.enableMenus(!1)}},notify:function(n){desktop.sendMessage(n.title,n.content)},setBadgeCount:function(n){desktop.count(n.all_unread_highlights_cnt,n.all_unread_cnt)},displayTeam:function(n){},log:function(n){console.log("ScudCloud."+n)},populate:function(){desktop.populate(JSON.stringify({channels:ScudCloud.listChannels(),teams:ScudCloud.listTeams(),icon:TS.model.team.icon.image_44}))},createSnippet:function(){return TS.ui.snippet_dialog.start()},listChannels:function(){return TS.channels.getUnarchivedChannelsForUser()},listTeams:function(){var n=TS.getAllTeams();return n[0].team_icon={image_44:TS.model.team.icon.image_44},n},quicklist:function(){desktop.quicklist(ScudCloud.listChannels())},join:function(n){return TS.channels.join(n)},setClipboard:function(n){TS.client.ui.file_pasted_sig.dispatch(n,TS.model.shift_key_pressed)},preferences:function(){return TS.ui.prefs_dialog.start()},addTeam:function(){document.location=TS.boot_data.signin_url},getCurrentTeam:function(){var n=TS.getAllTeams();if(null!=n)for(var e=0;n.length;e++)if(n[e].team_url==TS.boot_data.team_url)return n[e].id;return""},logout:function(){document.location=TS.boot_data.logout_url},help:function(){return TS.help_dialog.start()}},document.onpaste=function(n){desktop.pasted(!1)},window.winssb=TSSSB=ScudCloud,ScudCloud.unloaded&&ScudCloud.didFinishLoading(); diff --git a/scudcloud-1.1/resources/scudcloud.png b/scudcloud-1.1/resources/scudcloud.png new file mode 100644 index 0000000..ee08336 Binary files /dev/null and b/scudcloud-1.1/resources/scudcloud.png differ diff --git a/scudcloud-1.1/scudcloud b/scudcloud-1.1/scudcloud new file mode 100755 index 0000000..734350c --- /dev/null +++ b/scudcloud-1.1/scudcloud @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +import fcntl, os, sys, signal, tempfile +from PyQt4 import QtGui, QtCore +from PyQt4.QtNetwork import QLocalServer, QLocalSocket + +# Flexible install dir (we assume that 'lib' and 'resources' will be subdirs) +INSTALL_DIR = os.path.dirname(os.path.realpath(__file__)) + +# Append the lib directory in our installation path to get remaining libraries. +sys.path.append(os.path.join(INSTALL_DIR, 'lib')) +from resources import Resources +from scudcloud import ScudCloud + +# The ScudCloud QMainWindow +win = None + +def main(): + global win + Resources.INSTALL_DIR = INSTALL_DIR + signal.signal(signal.SIGINT, exit) + args = parse_arguments() + appKey = "scudcloud.pid" + socket = QLocalSocket() + socket.connectToServer(appKey) + if socket.isOpen(): + socket.close() + socket.deleteLater() + return 0 + socket.deleteLater() + app = QtGui.QApplication(sys.argv) + app.setApplicationName(Resources.APP_NAME) + app.setWindowIcon(QtGui.QIcon(Resources.get_path('scudcloud.png'))) + ScudCloud.debug = args.debug + ScudCloud.minimized = True if args.minimized is True else None + ScudCloud.plugins = False if args.no_plugins is True else True + try: + settings_path = load_settings(args.confdir) + except: + print("Configuration directory "+args.confdir+" could not be created! Exiting...") + raise SystemExit() + win = ScudCloud(settings_path=settings_path) + server = QLocalServer() + server.newConnection.connect(restore) + server.listen(appKey) + win.restore() + if win.minimized is None: + win.show() + sys.exit(app.exec_()) + +def restore(): + global win + win.setWindowFlags(win.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) + win.showNormal() + win.setWindowFlags(win.windowFlags() & ~QtCore.Qt.WindowStaysOnTopHint) + win.showNormal() + win.activateWindow() + +def load_settings(confdir): + if not os.path.isdir(confdir): + os.makedirs(confdir) + if confdir not in sys.path: + sys.path[0:0] = [confdir] + return confdir + +def parse_arguments(): + from argparse import ArgumentParser + from os.path import expanduser + if 'XDG_CONFIG_HOME' in os.environ and os.environ['XDG_CONFIG_HOME']: + default_confdir = os.environ['XDG_CONFIG_HOME'] + '/scudcloud' + else: + default_confdir = '~/.config/scudcloud' + parser = ArgumentParser() + parser.add_argument('--confdir', dest='confdir', metavar='dir', default=default_confdir, help="change the configuration directory") + parser.add_argument('--debug', dest='debug', type=bool, default=False, help="enable webkit debug console (default: False)") + parser.add_argument('--minimized', dest='minimized', type=bool, default=False, help="start minimized to tray (default: False)") + parser.add_argument('--no_plugins', dest='no_plugins', type=bool, default=False, help="disable web plugins (default: False)") + parser.add_argument('--version', action="store_true", help="print version and exit") + args = parser.parse_args() + if args.version: + with open(os.path.join(Resources.INSTALL_DIR, 'VERSION'), "r") as f: + print("ScudCloud "+f.read()) + sys.exit() + args.confdir = expanduser(args.confdir) + return args + +def exit(*args): + if win is not None: + win.exit() + else: + QtGui.QApplication.quit() + +if __name__ == '__main__': + main() diff --git a/scudcloud-1.1/scudcloud-src.js b/scudcloud-1.1/scudcloud-src.js new file mode 100644 index 0000000..3bb9beb --- /dev/null +++ b/scudcloud-1.1/scudcloud-src.js @@ -0,0 +1,120 @@ + +ScudCloud = { + unloaded: true, + // App functions + hasPreference: function(name){ + return false; + }, + getPreference: function(name){ + return false; + }, + setPreference: function(name, value){ + return false; + }, + canShowHtmlNotifications: function(){ + // Ubuntu cannot display HTML notifications + return false; + }, + // TSSSB.call + call: function(name, args){ + ScudCloud.log(name); + switch(name){ + case "reload": + return ScudCloud.reload(); + case "didStartLoading": + return ScudCloud.didStartLoading(); + case "didFinishLoading": + return ScudCloud.didFinishLoading(); + case "setConnectionStatus": + return ScudCloud.setConnectionStatus(args); + case "notify": + return ScudCloud.notify(args); + case "setBadgeCount": + return ScudCloud.setBadgeCount(args); + case "displayTeam": + return ScudCloud.displayTeam(args); + } + return false; + }, + // TSSSB.call implementations + reload: function(){ + window.location.reload(); + }, + didStartLoading: function(){ + }, + didFinishLoading: function(){ + TS.ui.banner.close(); + ScudCloud.populate(); + ScudCloud.unloaded = false; + }, + setConnectionStatus: function(status){ + // "online", "connecting", "offline" + switch(status){ + case "online": desktop.enableMenus(true); break; + default: desktop.enableMenus(false); + } + }, + notify: function(args){ + desktop.sendMessage(args.title, args.content); + }, + setBadgeCount: function(args){ + desktop.count(args.all_unread_highlights_cnt, args.all_unread_cnt); + }, + displayTeam: function(id){ + }, + // ScudCloud internal functions + log: function(name){ + console.log("ScudCloud."+name); + }, + populate: function(){ + desktop.populate(JSON.stringify({'channels': ScudCloud.listChannels(), 'teams': ScudCloud.listTeams(), 'icon': TS.model.team.icon.image_44})); + }, + createSnippet: function(){ + return TS.ui.snippet_dialog.start(); + }, + listChannels: function(){ + return TS.channels.getUnarchivedChannelsForUser(); + }, + listTeams: function(){ + var list = TS.getAllTeams(); + // Fix for current team displaying no icon + list[0].team_icon = {"image_44":TS.model.team.icon.image_44}; + return list; + }, + quicklist: function(){ + desktop.quicklist(ScudCloud.listChannels()); + }, + join: function(c){ + return TS.channels.join(c); + }, + setClipboard: function(data){ + TS.client.ui.file_pasted_sig.dispatch(data, TS.model.shift_key_pressed); + }, + preferences: function(){ + return TS.ui.prefs_dialog.start(); + }, + addTeam: function(){ + document.location = TS.boot_data.signin_url; + }, + getCurrentTeam: function(){ + var list = TS.getAllTeams(); + if(list!=null) for(var i=0;list.length;i++){ + if(list[i].team_url==TS.boot_data.team_url){ + return list[i].id; + } + } + return ""; + }, + logout: function(){ + document.location = TS.boot_data.logout_url; + }, + help: function(){ + return TS.help_dialog.start(); + } +}; +document.onpaste = function(e){desktop.pasted(false);}; +window.winssb = TSSSB = ScudCloud; +// Sometimes didFinishLoading is not loaded +if(ScudCloud.unloaded){ + ScudCloud.didFinishLoading(); +} diff --git a/scudcloud-1.1/scudcloud.desktop b/scudcloud-1.1/scudcloud.desktop new file mode 100644 index 0000000..d21cbe6 --- /dev/null +++ b/scudcloud-1.1/scudcloud.desktop @@ -0,0 +1,13 @@ +#!/usr/bin/env xdg-open +[Desktop Entry] +Version=1.0 +Terminal=false +Type=Application +Categories=Network;Chat; +Name=ScudCloud +Comment=ScudCloud is an open-source client for Slack +Keywords=slack;chat;instant-messaging;collaboration; +Exec=/opt/scudcloud/scudcloud +StartupWMClass=scudcloud +Icon=/opt/scudcloud/resources/scudcloud.png + diff --git a/scudcloud-1.1/scudcloud.spec b/scudcloud-1.1/scudcloud.spec new file mode 100644 index 0000000..a7a5f1f --- /dev/null +++ b/scudcloud-1.1/scudcloud.spec @@ -0,0 +1,159 @@ +# +# spec file for package scudcloud +# +# Copyright (c) 2015 Marcin Trendota (moonwolf@poczta.onet.pl) +# Copyright (c) 2015 Marcin Bajor (marcin.bajor@gmail.com) +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# + + +Name: scudcloud +Version: 1.0 +Release: 2%{?dist} +Summary: Non official desktop client for Slack© +License: MIT +Group: Applications/Internet +BuildRequires: python + +%if (0%{?suse_version} || 0%{?fedora_version}) +BuildRequires: fdupes +%endif + +%if 0%{?suse_version} +BuildRequires: update-desktop-files +BuildRequires: hicolor-icon-theme +Requires(post): desktop-file-utils +Requires(postun): desktop-file-utils +%else +Requires(post): xdg-utils +Requires(postun): xdg-utils +%endif + +Url: https://github.com/raelgc/scudcloud/ +Source: %{name}-%{version}.tar.gz +Requires: python3 +Requires: python3-qt4 +%if 0%{?suse_version} +Requires: google-lato-fonts +%else +Requires: lato-fonts +%endif +Requires: libqt4-webkit-qupzillaplugins +Requires: python3-hunspell +BuildRoot: %{_tmppath}/%{name}-%{version}-build +BuildArch: noarch + +%description +ScudCloud uses the QT library + Webkit to render the web version of Slack, +but using the QWebkit-Native bridge to improve desktop integration with: +* multiple teams support, +* native system notifications, +* count of unread direct mentions at launcher/sytray icon, +* alert/wobbling on new messages, +* channels quicklist (Unity only), +* optional "Close to Tray". + +%prep +%setup -q + +%install +INSTALL="/opt/scudcloud" +cd scudcloud-1.0 + +mkdir -p %{buildroot}/$INSTALL/lib +mkdir -p %{buildroot}/$INSTALL/resources +mkdir -p %{buildroot}%{_prefix}/bin +mkdir -p %{buildroot}%{_datadir}/icons/hicolor/scalable/apps +mkdir -p %{buildroot}%{_datadir}/icons/mono-dark/scalable/apps +mkdir -p %{buildroot}%{_datadir}/icons/mono-light/scalable/apps + + +install -m0644 lib/*.py %{buildroot}/$INSTALL/lib +install -m0644 resources/* %{buildroot}/$INSTALL/resources +install -m0755 scudcloud %{buildroot}/$INSTALL +install -m0644 LICENSE %{buildroot}/$INSTALL + +install -m0644 systray/hicolor/* %{buildroot}%{_datadir}/icons/hicolor/scalable/apps +install -m0644 systray/mono-dark/* %{buildroot}%{_datadir}/icons/mono-dark/scalable/apps +install -m0644 systray/mono-light/* %{buildroot}%{_datadir}/icons/mono-light/scalable/apps + +%if 0%{!?suse_version} +install -m0644 scudcloud.desktop %{buildroot}%{_datadir}/applications +%endif + +ln -sf $INSTALL/scudcloud %{buildroot}%{_bindir}/scudcloud + +%if 0%{?suse_version} +%suse_update_desktop_file -i %{name} Network InstantMessaging +%else +desktop-file-install --dir %{buildroot}%{_datadir}/applications %{name}.desktop +%endif + +%if (0%{?suse_version} || 0%{?fedora_version}) +%fdupes %{buildroot}/%{_prefix} +%endif + +%post +%if 0%{?suse_version} +%desktop_database_post +%icon_theme_cache_post +%else +xdg-icon-resource forceupdate --theme hicolor 2> /dev/null || : +xdg-icon-resource forceupdate --theme mono-dark 2> /dev/null || : +xdg-icon-resource forceupdate --theme mono-light 2> /dev/null || : +xdg-desktop-menu forceupdate 2> /dev/null || : +%endif + + +%postun +%if 0%{?suse_version} +%desktop_database_postun +%icon_theme_cache_postun +%else +if [ $1 -eq 0 ] ; then +xdg-icon-resource forceupdate --theme hicolor 2> /dev/null || : +xdg-icon-resource forceupdate --theme mono-dark 2> /dev/null || : +xdg-icon-resource forceupdate --theme mono-light 2> /dev/null || : +xdg-desktop-menu forceupdate 2> /dev/null || : +fi +%endif + + +%files +%defattr(-,root,root) +%dir /opt/scudcloud +%dir %{_datadir}/icons/hicolor +%dir %{_datadir}/icons/hicolor/scalable +%dir %{_datadir}/icons/hicolor/scalable/apps +%dir %{_datadir}/icons/mono-dark +%dir %{_datadir}/icons/mono-dark/scalable +%dir %{_datadir}/icons/mono-dark/scalable/apps +%dir %{_datadir}/icons/mono-light +%dir %{_datadir}/icons/mono-light/scalable +%dir %{_datadir}/icons/mono-light/scalable/apps +/opt/scudcloud/* +%{_datadir}/applications/scudcloud.desktop +%{_datadir}/icons/hicolor/scalable/apps/* +%{_datadir}/icons/mono-dark/scalable/apps/* +%{_datadir}/icons/mono-light/scalable/apps/* +%{_bindir}/scudcloud + +%changelog +* Sat Sep 26 2015 Marcin Bajor +- Added dependencies: libqt4-webkit-qupzillaplugins and python3-hunspell +* Mon Sep 21 2015 Marcin Trendota +- Add lato-fonts dependency +* Mon Aug 10 2015 Marcin Bajor +- Now build for CentOS, Red Hat Enterprise Linux, openSUSE, SUSE Linux Enterprise Server and others is possible +* Mon May 18 2015 Marcin Trendota +- First version \ No newline at end of file diff --git a/scudcloud-1.1/systray/hicolor/scudcloud-attention-1.svg b/scudcloud-1.1/systray/hicolor/scudcloud-attention-1.svg new file mode 100644 index 0000000..646bf31 --- /dev/null +++ b/scudcloud-1.1/systray/hicolor/scudcloud-attention-1.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 1 + + + diff --git a/scudcloud-1.1/systray/hicolor/scudcloud-attention-2.svg b/scudcloud-1.1/systray/hicolor/scudcloud-attention-2.svg new file mode 100644 index 0000000..fa43211 --- /dev/null +++ b/scudcloud-1.1/systray/hicolor/scudcloud-attention-2.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 2 + + + diff --git a/scudcloud-1.1/systray/hicolor/scudcloud-attention-3.svg b/scudcloud-1.1/systray/hicolor/scudcloud-attention-3.svg new file mode 100644 index 0000000..b15cfb5 --- /dev/null +++ b/scudcloud-1.1/systray/hicolor/scudcloud-attention-3.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 3 + + + diff --git a/scudcloud-1.1/systray/hicolor/scudcloud-attention-4.svg b/scudcloud-1.1/systray/hicolor/scudcloud-attention-4.svg new file mode 100644 index 0000000..d046544 --- /dev/null +++ b/scudcloud-1.1/systray/hicolor/scudcloud-attention-4.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 4 + + + diff --git a/scudcloud-1.1/systray/hicolor/scudcloud-attention-5.svg b/scudcloud-1.1/systray/hicolor/scudcloud-attention-5.svg new file mode 100644 index 0000000..d260e59 --- /dev/null +++ b/scudcloud-1.1/systray/hicolor/scudcloud-attention-5.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 5 + + + diff --git a/scudcloud-1.1/systray/hicolor/scudcloud-attention-6.svg b/scudcloud-1.1/systray/hicolor/scudcloud-attention-6.svg new file mode 100644 index 0000000..896507f --- /dev/null +++ b/scudcloud-1.1/systray/hicolor/scudcloud-attention-6.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 6 + + + diff --git a/scudcloud-1.1/systray/hicolor/scudcloud-attention-7.svg b/scudcloud-1.1/systray/hicolor/scudcloud-attention-7.svg new file mode 100644 index 0000000..7424c32 --- /dev/null +++ b/scudcloud-1.1/systray/hicolor/scudcloud-attention-7.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 7 + + + diff --git a/scudcloud-1.1/systray/hicolor/scudcloud-attention-8.svg b/scudcloud-1.1/systray/hicolor/scudcloud-attention-8.svg new file mode 100644 index 0000000..ee41c9d --- /dev/null +++ b/scudcloud-1.1/systray/hicolor/scudcloud-attention-8.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 8 + + + diff --git a/scudcloud-1.1/systray/hicolor/scudcloud-attention-9-plus.svg b/scudcloud-1.1/systray/hicolor/scudcloud-attention-9-plus.svg new file mode 100644 index 0000000..6e36967 --- /dev/null +++ b/scudcloud-1.1/systray/hicolor/scudcloud-attention-9-plus.svg @@ -0,0 +1,115 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 9 + + + + + diff --git a/scudcloud-1.1/systray/hicolor/scudcloud-attention-9.svg b/scudcloud-1.1/systray/hicolor/scudcloud-attention-9.svg new file mode 100644 index 0000000..6a8259c --- /dev/null +++ b/scudcloud-1.1/systray/hicolor/scudcloud-attention-9.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 9 + + + diff --git a/scudcloud-1.1/systray/hicolor/scudcloud-attention.svg b/scudcloud-1.1/systray/hicolor/scudcloud-attention.svg new file mode 100644 index 0000000..7e48289 --- /dev/null +++ b/scudcloud-1.1/systray/hicolor/scudcloud-attention.svg @@ -0,0 +1,61 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/scudcloud-1.1/systray/hicolor/scudcloud.svg b/scudcloud-1.1/systray/hicolor/scudcloud.svg new file mode 100644 index 0000000..e982393 --- /dev/null +++ b/scudcloud-1.1/systray/hicolor/scudcloud.svg @@ -0,0 +1,61 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/scudcloud-1.1/systray/mono-dark/scudcloud-attention-1.svg b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-1.svg new file mode 100644 index 0000000..646bf31 --- /dev/null +++ b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-1.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 1 + + + diff --git a/scudcloud-1.1/systray/mono-dark/scudcloud-attention-2.svg b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-2.svg new file mode 100644 index 0000000..fa43211 --- /dev/null +++ b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-2.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 2 + + + diff --git a/scudcloud-1.1/systray/mono-dark/scudcloud-attention-3.svg b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-3.svg new file mode 100644 index 0000000..b15cfb5 --- /dev/null +++ b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-3.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 3 + + + diff --git a/scudcloud-1.1/systray/mono-dark/scudcloud-attention-4.svg b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-4.svg new file mode 100644 index 0000000..d046544 --- /dev/null +++ b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-4.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 4 + + + diff --git a/scudcloud-1.1/systray/mono-dark/scudcloud-attention-5.svg b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-5.svg new file mode 100644 index 0000000..d260e59 --- /dev/null +++ b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-5.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 5 + + + diff --git a/scudcloud-1.1/systray/mono-dark/scudcloud-attention-6.svg b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-6.svg new file mode 100644 index 0000000..896507f --- /dev/null +++ b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-6.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 6 + + + diff --git a/scudcloud-1.1/systray/mono-dark/scudcloud-attention-7.svg b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-7.svg new file mode 100644 index 0000000..7424c32 --- /dev/null +++ b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-7.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 7 + + + diff --git a/scudcloud-1.1/systray/mono-dark/scudcloud-attention-8.svg b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-8.svg new file mode 100644 index 0000000..ee41c9d --- /dev/null +++ b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-8.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 8 + + + diff --git a/scudcloud-1.1/systray/mono-dark/scudcloud-attention-9-plus.svg b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-9-plus.svg new file mode 100644 index 0000000..6e36967 --- /dev/null +++ b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-9-plus.svg @@ -0,0 +1,115 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 9 + + + + + diff --git a/scudcloud-1.1/systray/mono-dark/scudcloud-attention-9.svg b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-9.svg new file mode 100644 index 0000000..6a8259c --- /dev/null +++ b/scudcloud-1.1/systray/mono-dark/scudcloud-attention-9.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 9 + + + diff --git a/scudcloud-1.1/systray/mono-dark/scudcloud-attention.svg b/scudcloud-1.1/systray/mono-dark/scudcloud-attention.svg new file mode 100644 index 0000000..7e48289 --- /dev/null +++ b/scudcloud-1.1/systray/mono-dark/scudcloud-attention.svg @@ -0,0 +1,61 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/scudcloud-1.1/systray/mono-dark/scudcloud.svg b/scudcloud-1.1/systray/mono-dark/scudcloud.svg new file mode 100644 index 0000000..e982393 --- /dev/null +++ b/scudcloud-1.1/systray/mono-dark/scudcloud.svg @@ -0,0 +1,61 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/scudcloud-1.1/systray/mono-light/scudcloud-attention-1.svg b/scudcloud-1.1/systray/mono-light/scudcloud-attention-1.svg new file mode 100644 index 0000000..646bf31 --- /dev/null +++ b/scudcloud-1.1/systray/mono-light/scudcloud-attention-1.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 1 + + + diff --git a/scudcloud-1.1/systray/mono-light/scudcloud-attention-2.svg b/scudcloud-1.1/systray/mono-light/scudcloud-attention-2.svg new file mode 100644 index 0000000..fa43211 --- /dev/null +++ b/scudcloud-1.1/systray/mono-light/scudcloud-attention-2.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 2 + + + diff --git a/scudcloud-1.1/systray/mono-light/scudcloud-attention-3.svg b/scudcloud-1.1/systray/mono-light/scudcloud-attention-3.svg new file mode 100644 index 0000000..b15cfb5 --- /dev/null +++ b/scudcloud-1.1/systray/mono-light/scudcloud-attention-3.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 3 + + + diff --git a/scudcloud-1.1/systray/mono-light/scudcloud-attention-4.svg b/scudcloud-1.1/systray/mono-light/scudcloud-attention-4.svg new file mode 100644 index 0000000..d046544 --- /dev/null +++ b/scudcloud-1.1/systray/mono-light/scudcloud-attention-4.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 4 + + + diff --git a/scudcloud-1.1/systray/mono-light/scudcloud-attention-5.svg b/scudcloud-1.1/systray/mono-light/scudcloud-attention-5.svg new file mode 100644 index 0000000..d260e59 --- /dev/null +++ b/scudcloud-1.1/systray/mono-light/scudcloud-attention-5.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 5 + + + diff --git a/scudcloud-1.1/systray/mono-light/scudcloud-attention-6.svg b/scudcloud-1.1/systray/mono-light/scudcloud-attention-6.svg new file mode 100644 index 0000000..896507f --- /dev/null +++ b/scudcloud-1.1/systray/mono-light/scudcloud-attention-6.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 6 + + + diff --git a/scudcloud-1.1/systray/mono-light/scudcloud-attention-7.svg b/scudcloud-1.1/systray/mono-light/scudcloud-attention-7.svg new file mode 100644 index 0000000..7424c32 --- /dev/null +++ b/scudcloud-1.1/systray/mono-light/scudcloud-attention-7.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 7 + + + diff --git a/scudcloud-1.1/systray/mono-light/scudcloud-attention-8.svg b/scudcloud-1.1/systray/mono-light/scudcloud-attention-8.svg new file mode 100644 index 0000000..ee41c9d --- /dev/null +++ b/scudcloud-1.1/systray/mono-light/scudcloud-attention-8.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 8 + + + diff --git a/scudcloud-1.1/systray/mono-light/scudcloud-attention-9-plus.svg b/scudcloud-1.1/systray/mono-light/scudcloud-attention-9-plus.svg new file mode 100644 index 0000000..6e36967 --- /dev/null +++ b/scudcloud-1.1/systray/mono-light/scudcloud-attention-9-plus.svg @@ -0,0 +1,115 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 9 + + + + + diff --git a/scudcloud-1.1/systray/mono-light/scudcloud-attention-9.svg b/scudcloud-1.1/systray/mono-light/scudcloud-attention-9.svg new file mode 100644 index 0000000..6a8259c --- /dev/null +++ b/scudcloud-1.1/systray/mono-light/scudcloud-attention-9.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 9 + + + diff --git a/scudcloud-1.1/systray/mono-light/scudcloud-attention.svg b/scudcloud-1.1/systray/mono-light/scudcloud-attention.svg new file mode 100644 index 0000000..7e48289 --- /dev/null +++ b/scudcloud-1.1/systray/mono-light/scudcloud-attention.svg @@ -0,0 +1,61 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/scudcloud-1.1/systray/mono-light/scudcloud.svg b/scudcloud-1.1/systray/mono-light/scudcloud.svg new file mode 100644 index 0000000..82eb22d --- /dev/null +++ b/scudcloud-1.1/systray/mono-light/scudcloud.svg @@ -0,0 +1,61 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + -- cgit v1.1