From 699a4fd9af0aa9ad2badd5880e5cae82bad39391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sun, 1 Nov 2015 12:56:40 +0100 Subject: [PATCH 01/70] Self-host app store badges to reduce number of connections These are so rarely seen, extra connections on page load are really wasteful there --- README.md | 2 +- assets/img/badge_firefoxos.png | Bin 0 -> 4293 bytes assets/img/badge_playstore.png | Bin 0 -> 8913 bytes index.html | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 assets/img/badge_firefoxos.png create mode 100644 assets/img/badge_playstore.png diff --git a/README.md b/README.md index 7416a74..9907c6d 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Please note that the above instructions set up an *unencrypted* relay, and all y You can run Glowing Bear in many ways: use it like any other webpage, as an app in Firefox (choose "Install app" on the landing page) or Chrome ("Tools", then "Create application shortcuts"), or a full-screen Chrome app on Android ("Add to homescreen"). We also provide an [Android app](https://play.google.com/store/apps/details?id=com.glowing_bear) that you can install from the Google Play Store, and a [Firefox OS app](https://marketplace.firefox.com/app/glowing-bear/) in the Firefox Marketplace. -Android app on Google PlayFirefox OS app in the Firefox Marketplace +Android app on Google PlayFirefox OS app in the Firefox Marketplace ##Screenshots diff --git a/assets/img/badge_firefoxos.png b/assets/img/badge_firefoxos.png new file mode 100644 index 0000000000000000000000000000000000000000..3bb6991c3490120b0e92a60dfc566828c2d17df8 GIT binary patch literal 4293 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 literal 0 HcmV?d00001 diff --git a/assets/img/badge_playstore.png b/assets/img/badge_playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..9891cbbd39d36e215940fa18a1fd1a0a83bcb9af GIT binary patch literal 8913 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 don't need to install anything to use this app, it should work with any modern browser. Start using it right now! However, there are a few ways to improve integration with your operating system.

Mobile Applications

If you're running Android 4.4 or later, you can install our app from the Google Play Store! We also provide an optimized application for Firefox OS devices. If you're using the Firefox browser, keep on reading below -- the Firefox OS app won't work for you

-

Android app on Google Play Firefox OS app in the Firefox Marketplace

+

Android app on Google Play Firefox OS app in the Firefox Marketplace

Firefox Browser

If you have a recent version of Firefox you can install Glowing Bear as a Firefox app. Click the button to install.

From 64af0908cf358cd228c0353c1879a05fe8223656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sun, 1 Nov 2015 13:09:48 +0100 Subject: [PATCH 02/70] Use subresource integrity to prevent CDN resource tampering See https://hacks.mozilla.org/2015/09/subresource-integrity-in-firefox-43/ --- index.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/index.html b/index.html index 31af0f3..d0d2b33 100644 --- a/index.html +++ b/index.html @@ -10,18 +10,18 @@ - + - - - - - - + + + + + + From b7c281d058cfd75f4295c66ad500fc1e7938e753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sun, 1 Nov 2015 13:22:27 +0100 Subject: [PATCH 03/70] Use Cloudflare CDN for everything, and always use https they redirect http -> https anyway --- index.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/index.html b/index.html index d0d2b33..fa71eb2 100644 --- a/index.html +++ b/index.html @@ -10,18 +10,18 @@ - + - - - - - - + + + + + + From accbf276ada6bb5a46b586026cf3e902f83abab9 Mon Sep 17 00:00:00 2001 From: Magnus Hauge Bakke Date: Mon, 12 Oct 2015 14:00:45 +0200 Subject: [PATCH 04/70] Add button for sending image --- css/themes/dark.css | 7 ++++--- css/themes/light.css | 5 +++-- directives/input.html | 1 + 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/css/themes/dark.css b/css/themes/dark.css index 9e196f7..f219459 100644 --- a/css/themes/dark.css +++ b/css/themes/dark.css @@ -72,12 +72,13 @@ input[type=text], input[type=password], #sendMessage, .badge { box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.1), 0px 1px 7px 0px rgba(0, 0, 0, 0.8) inset; } -input[type=text], input[type=password], #sendMessage, .badge, .btn-send { +input[type=text], input[type=password], #sendMessage, .badge, .btn-send, .btn-send-image { color: #ccc; background: none repeat scroll 0% 0% rgba(0, 0, 0, 0.3); } -.btn-send:hover, .btn-send:focus { +.btn-send:hover, .btn-send:focus, +.btn-send-image:hover, .btn-send-image:focus { background-color: #555; color: white; } @@ -271,7 +272,7 @@ input[type=text], input[type=password], #sendMessage, .badge, .btn-send { .cob-chat { } .cob-chat_time { - color: #999; + color: #999; } .cob-chat_time_delimiters { } diff --git a/css/themes/light.css b/css/themes/light.css index b292136..6a5c109 100644 --- a/css/themes/light.css +++ b/css/themes/light.css @@ -22,7 +22,8 @@ html { background-color: #222; } -.btn-send { +.btn-send, +.btn-send-image, { background: none repeat scroll 0% 0% rgba(255, 255, 255, 0.3); color: #428BCA; } @@ -257,7 +258,7 @@ select.form-control, select option, input[type=text], input[type=password], #sen .cob-chat { } .cob-chat_time { - color: #999; + color: #999; } .cob-chat_time_delimiters { } diff --git a/directives/input.html b/directives/input.html index 9b23817..26656fd 100644 --- a/directives/input.html +++ b/directives/input.html @@ -3,6 +3,7 @@ + From 0d7d8e0cce15e525c6b9d5c57d68c36f835cefc0 Mon Sep 17 00:00:00 2001 From: Magnus Hauge Bakke Date: Fri, 9 Oct 2015 13:50:55 +0200 Subject: [PATCH 05/70] Add directive for file input change --- index.html | 1 + js/file-change.js | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 js/file-change.js diff --git a/index.html b/index.html index fa71eb2..c42ecae 100644 --- a/index.html +++ b/index.html @@ -33,6 +33,7 @@ + diff --git a/js/file-change.js b/js/file-change.js new file mode 100644 index 0000000..1b22359 --- /dev/null +++ b/js/file-change.js @@ -0,0 +1,23 @@ +(function() { +'use strict'; + +var weechat = angular.module('weechat'); + +weechat.directive('fileChange', ['$parse', function($parse) { + + return { + restrict: 'A', + link: function ($scope, element, attrs) { + var attrHandler = $parse(attrs.fileChange); + var handler = function (e) { + $scope.$apply(function () { + attrHandler($scope, { $event: e, files: e.target.files }); + }); + }; + element[0].addEventListener('change', handler, false); + } + }; + + }]); + +})(); From f6bfa4161bbc37cf50a80697ad1eb41584b641d1 Mon Sep 17 00:00:00 2001 From: Magnus Hauge Bakke Date: Fri, 9 Oct 2015 13:59:34 +0200 Subject: [PATCH 06/70] Add imgur provider --- index.html | 1 + js/imgur.js | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 js/imgur.js diff --git a/index.html b/index.html index c42ecae..9a9ae1f 100644 --- a/index.html +++ b/index.html @@ -39,6 +39,7 @@ + diff --git a/js/imgur.js b/js/imgur.js new file mode 100644 index 0000000..be003c8 --- /dev/null +++ b/js/imgur.js @@ -0,0 +1,75 @@ +(function() { +'use strict'; + +var weechat = angular.module('weechat'); + +weechat.factory('imgur', ['$rootScope', function($rootScope) { + + var process = function(image) { + + // Is it an image? + if (!image || !image.type.match(/image.*/)) return; + + // New file reader + var reader = new FileReader(); + + // When image is read + reader.onload = function (event) { + var image = event.target.result.split(',')[1]; + upload(image); + }; + + // Read image as data url + reader.readAsDataURL(image); + + }; + + // Upload image to imgur from base64 + var upload = function( base64img ) { + + // Set client ID (Glowing Bear) + var clientId = "164efef8979cd4b"; + + // Create new form data + var fd = new FormData(); + fd.append("image", base64img); // Append the file + fd.append("type", "base64"); // Set image type to base64 + + // Create new XMLHttpRequest + var xhttp = new XMLHttpRequest(); + + // Post request to imgur api + xhttp.open("POST", "https://api.imgur.com/3/image", true); + + // Set headers + xhttp.setRequestHeader("Authorization", "Client-ID " + clientId); + xhttp.setRequestHeader("Accept", "application/json"); + + // Handler for response + xhttp.onreadystatechange = function() { + + // Check state and response status + if (xhttp.readyState == 4 && xhttp.status == 200) { + + // Get response text + var response = JSON.parse(xhttp.responseText); + + // Open image in new window + window.open(response.data.link, '_blank'); + + } + + }; + + // Send request with form data + xhttp.send(fd); + + }; + + return { + process: process + }; + +}]); + +})(); From aef26a2dc5fd8c9bdb9a56332e55d284d24ba465 Mon Sep 17 00:00:00 2001 From: Magnus Hauge Bakke Date: Fri, 9 Oct 2015 14:01:45 +0200 Subject: [PATCH 07/70] Add file input with button and send file to imgur --- css/glowingbear.css | 19 +++++++++++++++++++ directives/input.html | 5 ++++- js/inputbar.js | 10 +++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/css/glowingbear.css b/css/glowingbear.css index 46e1243..a7150a5 100644 --- a/css/glowingbear.css +++ b/css/glowingbear.css @@ -84,6 +84,25 @@ input[type=text], input[type=password], #sendMessage { margin-bottom: 5px !important; } +.btn-send-image { + position: relative; + overflow: hidden; + cursor: pointer; +} + +.imgur-upload { + position: absolute; + bottom: 0; + right: 0; + cursor: inherit; + font-size: 1000px !important; + height: 300px; + margin: 0; + padding: 0; + opacity: 0; + filter: ~"alpha(opacity=0)"; +} + .input-group { width: 100%; } diff --git a/directives/input.html b/directives/input.html index 26656fd..01b574a 100644 --- a/directives/input.html +++ b/directives/input.html @@ -3,7 +3,10 @@ - + diff --git a/js/inputbar.js b/js/inputbar.js index e57144a..6610017 100644 --- a/js/inputbar.js +++ b/js/inputbar.js @@ -14,11 +14,12 @@ weechat.directive('inputBar', function() { command: '=command' }, - controller: ['$rootScope', '$scope', '$element', '$log', 'connection', 'models', 'IrcUtils', 'settings', function($rootScope, + controller: ['$rootScope', '$scope', '$element', '$log', 'connection', 'imgur', 'models', 'IrcUtils', 'settings', function($rootScope, $scope, $element, //XXX do we need this? don't seem to be using it $log, connection, //XXX we should eliminate this dependency and use signals instead + imgur, models, IrcUtils, settings) { @@ -69,6 +70,13 @@ weechat.directive('inputBar', function() { }, 0); }; + $scope.uploadImage = function( $event, files ) { + // Get file + var file = files[0]; + + // Process image + imgur.process(file); + }; // Send the message to the websocket $scope.sendMessage = function() { From 960d5ba17ab4c3b86ff637abbac3307758b6857d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sat, 7 Nov 2015 12:32:25 +0100 Subject: [PATCH 08/70] Insert image URL into input bar --- js/imgur.js | 15 +++++++++------ js/inputbar.js | 28 +++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/js/imgur.js b/js/imgur.js index be003c8..a004392 100644 --- a/js/imgur.js +++ b/js/imgur.js @@ -5,7 +5,7 @@ var weechat = angular.module('weechat'); weechat.factory('imgur', ['$rootScope', function($rootScope) { - var process = function(image) { + var process = function(image, callback) { // Is it an image? if (!image || !image.type.match(/image.*/)) return; @@ -16,7 +16,7 @@ weechat.factory('imgur', ['$rootScope', function($rootScope) { // When image is read reader.onload = function (event) { var image = event.target.result.split(',')[1]; - upload(image); + upload(image, callback); }; // Read image as data url @@ -25,7 +25,7 @@ weechat.factory('imgur', ['$rootScope', function($rootScope) { }; // Upload image to imgur from base64 - var upload = function( base64img ) { + var upload = function( base64img, callback ) { // Set client ID (Glowing Bear) var clientId = "164efef8979cd4b"; @@ -54,9 +54,12 @@ weechat.factory('imgur', ['$rootScope', function($rootScope) { // Get response text var response = JSON.parse(xhttp.responseText); - // Open image in new window - window.open(response.data.link, '_blank'); - + // Send link as message + if( response.data && response.data.link ) { + if (callback && typeof(callback) === "function") { + callback(response.data.link); + } + } } }; diff --git a/js/inputbar.js b/js/inputbar.js index 6610017..09152f5 100644 --- a/js/inputbar.js +++ b/js/inputbar.js @@ -75,7 +75,33 @@ weechat.directive('inputBar', function() { var file = files[0]; // Process image - imgur.process(file); + imgur.process(file, function(imageUrl) { + + // Send image + if(imageUrl !== undefined && imageUrl !== '') { + // caret position in the input bar + var inputNode = $scope.getInputNode(), + caretPos = inputNode.selectionStart; + + var prefix = $scope.command.substring(0, caretPos), + suffix = $scope.command.substring(caretPos, $scope.command.length); + // Add spaces if missing + if (prefix.length > 0 && prefix[prefix.length - 1] !== ' ') { + prefix += ' '; + } + if (suffix.length > 0 && suffix[0] !== ' ') { + suffix = ' '.concat(suffix); + } + $scope.command = prefix + String(imageUrl) + suffix; + + setTimeout(function() { + inputNode.focus(); + var pos = $scope.command.length - suffix.length; + inputNode.setSelectionRange(pos, pos); + }, 0); + } + + }); }; // Send the message to the websocket From f2953d11901a7d5b6b4c4ae03123d10d742874f1 Mon Sep 17 00:00:00 2001 From: Magnus Hauge Bakke Date: Fri, 9 Oct 2015 19:32:26 +0200 Subject: [PATCH 09/70] Add image upload progressbar and error msg --- css/glowingbear.css | 23 +++++++++++++++++++++ directives/input.html | 1 + index.html | 3 +++ js/imgur.js | 48 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/css/glowingbear.css b/css/glowingbear.css index a7150a5..dbb2e55 100644 --- a/css/glowingbear.css +++ b/css/glowingbear.css @@ -176,6 +176,14 @@ input[type=text], input[type=password], #sendMessage { padding-right: 6px; } +.upload-error { + width: 100%; + position: absolute; + top: 0; + left: 0; + z-index: 4; +} + #sidebar { position: fixed; width: 140px; @@ -349,6 +357,21 @@ td.time { padding-right: 100px; } +#inputform { + position: relative; +} + +#imgur-upload-progress { + display: none; + content: " "; + width: 0%; + height: 5px; + position: absolute; + top: -5px; + left: 0; + background: #428BCA; +} + /* fix for mobile firefox which ignores :hover */ .nav-pills > li > a:active, .nav-pills > li > a:active span { text-decoration: none; diff --git a/directives/input.html b/directives/input.html index 01b574a..dcb7d2e 100644 --- a/directives/input.html +++ b/directives/input.html @@ -10,4 +10,5 @@ +
diff --git a/index.html b/index.html index 9a9ae1f..566d133 100644 --- a/index.html +++ b/index.html @@ -43,6 +43,9 @@ +
+

Upload error: Image upload failed.

+

logo diff --git a/js/imgur.js b/js/imgur.js index a004392..7b1cfa3 100644 --- a/js/imgur.js +++ b/js/imgur.js @@ -30,6 +30,10 @@ weechat.factory('imgur', ['$rootScope', function($rootScope) { // Set client ID (Glowing Bear) var clientId = "164efef8979cd4b"; + // Progress bar DOM elment + var progressBar = document.getElementById("imgur-upload-progress"); + progressBar.style.width = '0'; + // Create new form data var fd = new FormData(); fd.append("image", base64img); // Append the file @@ -46,29 +50,69 @@ weechat.factory('imgur', ['$rootScope', function($rootScope) { xhttp.setRequestHeader("Accept", "application/json"); // Handler for response - xhttp.onreadystatechange = function() { + xhttp.onload = function() { + + progressBar.style.display = 'none'; // Check state and response status - if (xhttp.readyState == 4 && xhttp.status == 200) { + if(xhttp.status === 200) { // Get response text var response = JSON.parse(xhttp.responseText); // Send link as message if( response.data && response.data.link ) { + if (callback && typeof(callback) === "function") { callback(response.data.link); } + + } else { + showErrorMsg(); } + + } else { + showErrorMsg(); } }; + if( "upload" in xhttp ) { + + // Set progress + xhttp.upload.onprogress = function (event) { + + // Check if we can compute progress + if (event.lengthComputable) { + // Complete in percent + var complete = (event.loaded / event.total * 100 | 0); + + // Set progress bar width + progressBar.style.display = 'block'; + progressBar.style.width = complete + '%'; + } + }; + + } + // Send request with form data xhttp.send(fd); }; + var showErrorMsg = function() { + // Show error msg + $rootScope.uploadError = true; + $rootScope.$apply(); + + // Hide after 5 seconds + setTimeout(function(){ + // Hide error msg + $rootScope.uploadError = false; + $rootScope.$apply(); + }, 5000); + }; + return { process: process }; From 3b4f91249fcc4e9e88530a785cee0c8554d5e98e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sat, 7 Nov 2015 12:37:46 +0100 Subject: [PATCH 10/70] Convert indention to spaces --- js/imgur.js | 159 ++++++++++++++++++++++++++-------------------------- 1 file changed, 79 insertions(+), 80 deletions(-) diff --git a/js/imgur.js b/js/imgur.js index 7b1cfa3..e2b46f5 100644 --- a/js/imgur.js +++ b/js/imgur.js @@ -5,115 +5,114 @@ var weechat = angular.module('weechat'); weechat.factory('imgur', ['$rootScope', function($rootScope) { - var process = function(image, callback) { + var process = function(image, callback) { - // Is it an image? - if (!image || !image.type.match(/image.*/)) return; + // Is it an image? + if (!image || !image.type.match(/image.*/)) return; - // New file reader - var reader = new FileReader(); + // New file reader + var reader = new FileReader(); - // When image is read - reader.onload = function (event) { - var image = event.target.result.split(',')[1]; - upload(image, callback); - }; + // When image is read + reader.onload = function (event) { + var image = event.target.result.split(',')[1]; + upload(image, callback); + }; - // Read image as data url - reader.readAsDataURL(image); + // Read image as data url + reader.readAsDataURL(image); - }; - - // Upload image to imgur from base64 - var upload = function( base64img, callback ) { - - // Set client ID (Glowing Bear) - var clientId = "164efef8979cd4b"; + }; - // Progress bar DOM elment - var progressBar = document.getElementById("imgur-upload-progress"); - progressBar.style.width = '0'; + // Upload image to imgur from base64 + var upload = function( base64img, callback ) { + // Set client ID (Glowing Bear) + var clientId = "164efef8979cd4b"; - // Create new form data - var fd = new FormData(); - fd.append("image", base64img); // Append the file - fd.append("type", "base64"); // Set image type to base64 + // Progress bar DOM elment + var progressBar = document.getElementById("imgur-upload-progress"); + progressBar.style.width = '0'; - // Create new XMLHttpRequest - var xhttp = new XMLHttpRequest(); + // Create new form data + var fd = new FormData(); + fd.append("image", base64img); // Append the file + fd.append("type", "base64"); // Set image type to base64 - // Post request to imgur api - xhttp.open("POST", "https://api.imgur.com/3/image", true); + // Create new XMLHttpRequest + var xhttp = new XMLHttpRequest(); - // Set headers - xhttp.setRequestHeader("Authorization", "Client-ID " + clientId); - xhttp.setRequestHeader("Accept", "application/json"); + // Post request to imgur api + xhttp.open("POST", "https://api.imgur.com/3/image", true); - // Handler for response - xhttp.onload = function() { + // Set headers + xhttp.setRequestHeader("Authorization", "Client-ID " + clientId); + xhttp.setRequestHeader("Accept", "application/json"); - progressBar.style.display = 'none'; + // Handler for response + xhttp.onload = function() { - // Check state and response status - if(xhttp.status === 200) { + progressBar.style.display = 'none'; - // Get response text - var response = JSON.parse(xhttp.responseText); + // Check state and response status + if(xhttp.status === 200) { - // Send link as message - if( response.data && response.data.link ) { + // Get response text + var response = JSON.parse(xhttp.responseText); - if (callback && typeof(callback) === "function") { - callback(response.data.link); - } + // Send link as message + if( response.data && response.data.link ) { - } else { - showErrorMsg(); - } + if (callback && typeof(callback) === "function") { + callback(response.data.link); + } - } else { - showErrorMsg(); - } + } else { + showErrorMsg(); + } - }; + } else { + showErrorMsg(); + } - if( "upload" in xhttp ) { + }; - // Set progress - xhttp.upload.onprogress = function (event) { + if( "upload" in xhttp ) { - // Check if we can compute progress - if (event.lengthComputable) { - // Complete in percent - var complete = (event.loaded / event.total * 100 | 0); + // Set progress + xhttp.upload.onprogress = function (event) { - // Set progress bar width - progressBar.style.display = 'block'; - progressBar.style.width = complete + '%'; - } - }; + // Check if we can compute progress + if (event.lengthComputable) { + // Complete in percent + var complete = (event.loaded / event.total * 100 | 0); - } + // Set progress bar width + progressBar.style.display = 'block'; + progressBar.style.width = complete + '%'; + } + }; - // Send request with form data - xhttp.send(fd); + } - }; + // Send request with form data + xhttp.send(fd); - var showErrorMsg = function() { - // Show error msg - $rootScope.uploadError = true; - $rootScope.$apply(); + }; - // Hide after 5 seconds - setTimeout(function(){ - // Hide error msg - $rootScope.uploadError = false; - $rootScope.$apply(); - }, 5000); - }; + var showErrorMsg = function() { + // Show error msg + $rootScope.uploadError = true; + $rootScope.$apply(); + + // Hide after 5 seconds + setTimeout(function(){ + // Hide error msg + $rootScope.uploadError = false; + $rootScope.$apply(); + }, 5000); + }; - return { + return { process: process }; From f2bb5437969df20b737b4bc9f4fc8cec43754be0 Mon Sep 17 00:00:00 2001 From: Magnus Hauge Bakke Date: Fri, 9 Oct 2015 20:11:30 +0200 Subject: [PATCH 11/70] Add support for dropping images on bufferlines and input form --- directives/input.html | 2 +- index.html | 3 ++- js/imgur-drop-directive.js | 44 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 js/imgur-drop-directive.js diff --git a/directives/input.html b/directives/input.html index dcb7d2e..3fbeb64 100644 --- a/directives/input.html +++ b/directives/input.html @@ -1,4 +1,4 @@ -
+
diff --git a/index.html b/index.html index 566d133..223280e 100644 --- a/index.html +++ b/index.html @@ -34,6 +34,7 @@ + @@ -262,7 +263,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
-
+
  • diff --git a/js/imgur-drop-directive.js b/js/imgur-drop-directive.js new file mode 100644 index 0000000..6d8ac36 --- /dev/null +++ b/js/imgur-drop-directive.js @@ -0,0 +1,44 @@ +(function() { +'use strict'; + +var weechat = angular.module('weechat'); + +weechat.directive('imgurDrop', ['connection','imgur', function(connection, imgur) { + return { + restrict: 'A', + link: function($scope, element, attr) { + var elem = element[0]; + elem.ondragover = function () { this.classList.add('imgur-drop-hover'); return false; }; + elem.ondragend = function () { this.classList.remove('imgur-drop-hover'); return false; }; + elem.ondrop = function(e) { + // Remove hover class + this.classList.remove('imgur-drop-hover'); + + // Get files + var files = e.dataTransfer.files; + + // Stop default behaviour + e.stopPropagation(); + e.preventDefault(); + + // Check files length + if (files.length > 0) { + // Sorry only one file + var file = files[0]; + + // Upload to imgur + imgur.process(file, function(imageUrl) { + + // Send image + if(imageUrl !== undefined && imageUrl !== '') { + connection.sendMessage( String(imageUrl) ); + } + + }); + } + }; + } + }; +}]); + +})(); From 3f661ded6c28445d7790f391385c2a6bacf104e8 Mon Sep 17 00:00:00 2001 From: Magnus Hauge Bakke Date: Mon, 12 Oct 2015 21:09:13 +0200 Subject: [PATCH 12/70] Support sending multiple images --- css/glowingbear.css | 16 ++++++++++------ directives/input.html | 2 +- js/imgur-drop-directive.js | 27 ++++++++++++++++----------- js/imgur.js | 19 +++++++++++++------ js/inputbar.js | 22 +++++++++++++++------- 5 files changed, 55 insertions(+), 31 deletions(-) diff --git a/css/glowingbear.css b/css/glowingbear.css index dbb2e55..a6d10d8 100644 --- a/css/glowingbear.css +++ b/css/glowingbear.css @@ -362,16 +362,20 @@ td.time { } #imgur-upload-progress { - display: none; - content: " "; - width: 0%; - height: 5px; + width: 100%; + height: auto; position: absolute; - top: -5px; + bottom: 100%; left: 0; - background: #428BCA; } + .imgur-progress-bar { + width: 0%; + height: 5px; + margin-top: 1px; + background: #428BCA; + } + /* fix for mobile firefox which ignores :hover */ .nav-pills > li > a:active, .nav-pills > li > a:active span { text-decoration: none; diff --git a/directives/input.html b/directives/input.html index 3fbeb64..38a76f7 100644 --- a/directives/input.html +++ b/directives/input.html @@ -5,7 +5,7 @@ diff --git a/js/imgur-drop-directive.js b/js/imgur-drop-directive.js index 6d8ac36..50a4ca9 100644 --- a/js/imgur-drop-directive.js +++ b/js/imgur-drop-directive.js @@ -21,20 +21,25 @@ weechat.directive('imgurDrop', ['connection','imgur', function(connection, imgur e.stopPropagation(); e.preventDefault(); - // Check files length - if (files.length > 0) { - // Sorry only one file - var file = files[0]; + // Send image url after upload + var sendImageUrl = function(imageUrl) { - // Upload to imgur - imgur.process(file, function(imageUrl) { + // Send image + if(imageUrl !== undefined && imageUrl !== '') { + connection.sendMessage(String(imageUrl)); + } - // Send image - if(imageUrl !== undefined && imageUrl !== '') { - connection.sendMessage( String(imageUrl) ); - } + }; + + // Check files + if(typeof files !== "undefined" && files.length > 0) { + + // Loop through files + for (var i = 0; i < files.length; i++) { + // Upload to imgur + imgur.process(files[i], sendImageUrl); + } - }); } }; } diff --git a/js/imgur.js b/js/imgur.js index e2b46f5..a5a0fd0 100644 --- a/js/imgur.js +++ b/js/imgur.js @@ -29,9 +29,16 @@ weechat.factory('imgur', ['$rootScope', function($rootScope) { // Set client ID (Glowing Bear) var clientId = "164efef8979cd4b"; - // Progress bar DOM elment - var progressBar = document.getElementById("imgur-upload-progress"); - progressBar.style.width = '0'; + // Progress bars container + var progressBars = document.getElementById("imgur-upload-progress"), + currentProgressBar = document.createElement("div"); + + // Set progress bar attributes + currentProgressBar.className='imgur-progress-bar'; + currentProgressBar.style.width = '0'; + + // Append progress bar + progressBars.appendChild(currentProgressBar); // Create new form data var fd = new FormData(); @@ -51,7 +58,8 @@ weechat.factory('imgur', ['$rootScope', function($rootScope) { // Handler for response xhttp.onload = function() { - progressBar.style.display = 'none'; + // Remove progress bar + currentProgressBar.parentNode.removeChild(currentProgressBar); // Check state and response status if(xhttp.status === 200) { @@ -87,8 +95,7 @@ weechat.factory('imgur', ['$rootScope', function($rootScope) { var complete = (event.loaded / event.total * 100 | 0); // Set progress bar width - progressBar.style.display = 'block'; - progressBar.style.width = complete + '%'; + currentProgressBar.style.width = complete + '%'; } }; diff --git a/js/inputbar.js b/js/inputbar.js index 09152f5..aa44927 100644 --- a/js/inputbar.js +++ b/js/inputbar.js @@ -70,12 +70,9 @@ weechat.directive('inputBar', function() { }, 0); }; - $scope.uploadImage = function( $event, files ) { - // Get file - var file = files[0]; - - // Process image - imgur.process(file, function(imageUrl) { + $scope.uploadImage = function($event, files) { + // Send image url after upload + var sendImageUrl = function(imageUrl) { // Send image if(imageUrl !== undefined && imageUrl !== '') { @@ -98,10 +95,21 @@ weechat.directive('inputBar', function() { inputNode.focus(); var pos = $scope.command.length - suffix.length; inputNode.setSelectionRange(pos, pos); + // force refresh? + $scope.$apply(); }, 0); } - }); + }; + + if(typeof files !== "undefined" && files.length > 0) { + // Loop through files + for (var i = 0; i < files.length; i++) { + // Process image + imgur.process(files[i], sendImageUrl); + } + + } }; // Send the message to the websocket From a6c2e6f3872f87eb0abd9d8b595aa98f74c67ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Tue, 10 Nov 2015 19:40:30 +0100 Subject: [PATCH 13/70] Insert URL at caret when dropping image into GB unfortunately this pollutes the root scope a bit more --- js/imgur-drop-directive.js | 4 +-- js/inputbar.js | 50 ++++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/js/imgur-drop-directive.js b/js/imgur-drop-directive.js index 50a4ca9..7e114d0 100644 --- a/js/imgur-drop-directive.js +++ b/js/imgur-drop-directive.js @@ -3,7 +3,7 @@ var weechat = angular.module('weechat'); -weechat.directive('imgurDrop', ['connection','imgur', function(connection, imgur) { +weechat.directive('imgurDrop', ['connection','imgur','$rootScope', function(connection, imgur, $rootScope) { return { restrict: 'A', link: function($scope, element, attr) { @@ -26,7 +26,7 @@ weechat.directive('imgurDrop', ['connection','imgur', function(connection, imgur // Send image if(imageUrl !== undefined && imageUrl !== '') { - connection.sendMessage(String(imageUrl)); + $rootScope.insertAtCaret(String(imageUrl)); } }; diff --git a/js/inputbar.js b/js/inputbar.js index aa44927..9d18506 100644 --- a/js/inputbar.js +++ b/js/inputbar.js @@ -70,36 +70,38 @@ weechat.directive('inputBar', function() { }, 0); }; + $rootScope.insertAtCaret = function(toInsert) { + // caret position in the input bar + var inputNode = $scope.getInputNode(), + caretPos = inputNode.selectionStart; + + var prefix = $scope.command.substring(0, caretPos), + suffix = $scope.command.substring(caretPos, $scope.command.length); + // Add spaces if missing + if (prefix.length > 0 && prefix[prefix.length - 1] !== ' ') { + prefix += ' '; + } + if (suffix.length > 0 && suffix[0] !== ' ') { + suffix = ' '.concat(suffix); + } + $scope.command = prefix + toInsert + suffix; + + setTimeout(function() { + inputNode.focus(); + var pos = $scope.command.length - suffix.length; + inputNode.setSelectionRange(pos, pos); + // force refresh? + $scope.$apply(); + }, 0); + }; + $scope.uploadImage = function($event, files) { // Send image url after upload var sendImageUrl = function(imageUrl) { - // Send image if(imageUrl !== undefined && imageUrl !== '') { - // caret position in the input bar - var inputNode = $scope.getInputNode(), - caretPos = inputNode.selectionStart; - - var prefix = $scope.command.substring(0, caretPos), - suffix = $scope.command.substring(caretPos, $scope.command.length); - // Add spaces if missing - if (prefix.length > 0 && prefix[prefix.length - 1] !== ' ') { - prefix += ' '; - } - if (suffix.length > 0 && suffix[0] !== ' ') { - suffix = ' '.concat(suffix); - } - $scope.command = prefix + String(imageUrl) + suffix; - - setTimeout(function() { - inputNode.focus(); - var pos = $scope.command.length - suffix.length; - inputNode.setSelectionRange(pos, pos); - // force refresh? - $scope.$apply(); - }, 0); + $rootScope.insertAtCaret(String(imageUrl)); } - }; if(typeof files !== "undefined" && files.length > 0) { From 643278478f9ce2ac4a9c737bed6dc2233fbc2502 Mon Sep 17 00:00:00 2001 From: pmelanson Date: Fri, 13 Nov 2015 20:56:43 +0000 Subject: [PATCH 14/70] IPv6 address literals won't be surrounded by [ ... ] if it's already there --- js/connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/connection.js b/js/connection.js index c6a60c9..b39027f 100644 --- a/js/connection.js +++ b/js/connection.js @@ -20,7 +20,7 @@ weechat.factory('connection', connectionData = [host, port, passwd, ssl, noCompression]; var proto = ssl ? 'wss' : 'ws'; // If host is an IPv6 literal wrap it in brackets - if (host.indexOf(":") !== -1) { + if (host.indexOf(":") !== -1 && host[0] !== "[" && host[host.length-1] !== "]") { host = "[" + host + "]"; } var url = proto + "://" + host + ":" + port + "/weechat"; From b5594d57547ede525c5e3997edf6fbf568c6aec1 Mon Sep 17 00:00:00 2001 From: hormigas Date: Fri, 13 Nov 2015 21:38:32 +0000 Subject: [PATCH 15/70] adding imgur gifv support to the videoPlugin --- js/plugins.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/js/plugins.js b/js/plugins.js index f659012..98e4010 100644 --- a/js/plugins.js +++ b/js/plugins.js @@ -302,10 +302,14 @@ plugins.factory('userPlugins', function() { * mp4 video Preview */ var videoPlugin = new UrlPlugin('video', function(url) { - if (url.match(/\.(mp4|webm|ogv)\b/i)) { + if (url.match(/\.(mp4|webm|ogv|gifv)\b/i)) { + if (url.match(/^http:\/\/(i\.)?imgur\.com\//i)) { + // remove protocol specification to load over https if used by g-b + url = url.replace(/\.(gifv)\b/i, ".webm"); + } return function() { var element = this.getElement(); - var velement = angular.element('') + var velement = angular.element('') .addClass('embed') .attr('width', '560') .append(angular.element('') @@ -314,6 +318,7 @@ plugins.factory('userPlugins', function() { }; } }); + /* * Cloud Music Embedded Players From b883a52b0953e44a20020cac090456bc6a505b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sun, 15 Nov 2015 21:50:29 +0100 Subject: [PATCH 16/70] Date change message prototype --- js/handlers.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/js/handlers.js b/js/handlers.js index 98f088c..25ba797 100644 --- a/js/handlers.js +++ b/js/handlers.js @@ -19,12 +19,39 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific models.closeBuffer(bufferId); }; + // inject a fake buffer line for date change + var injectDateChangeMessage = function(message, buffer, date) { + var content = "Date changed to " + date.toDateString(); + var line = { + buffer: buffer, + date: date, + prefix: '—', + tags_array: [], + displayed: true, + highlight: 0, + message: content + }; + var new_message = new models.BufferLine(line); + buffer.addLine(new_message); + }; + var handleLine = function(line, manually) { var message = new models.BufferLine(line); var buffer = models.getBuffer(message.buffer); buffer.requestedLines++; // Only react to line if its displayed if (message.displayed) { + // Check for date change + if (buffer.lines.length > 0) { + var previous_date = new Date(buffer.lines[buffer.lines.length - 1].date), + current_date = new Date(message.date); + previous_date.setHours(0, 0, 0, 0); + current_date.setHours(0, 0, 0, 0); + if (previous_date.valueOf() !== current_date.valueOf()) { + injectDateChangeMessage(message, buffer, current_date); + } + } + message = plugins.PluginManager.contentForMessage(message); buffer.addLine(message); From 94923fb4bbd6241fc4f1ecb1702075a79b4b5daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Thu, 19 Nov 2015 19:46:52 +0100 Subject: [PATCH 17/70] Disable DNS prefetching Fixes #674 --- index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/index.html b/index.html index 223280e..9331471 100644 --- a/index.html +++ b/index.html @@ -9,6 +9,7 @@ + From 0a1726e359792deb93d3e787642f46b0af5943de Mon Sep 17 00:00:00 2001 From: Patrick Melanson Date: Fri, 20 Nov 2015 17:52:39 -0500 Subject: [PATCH 18/70] date change messages are chat_day_change color, multiple messages generated for diff of 1-5 days --- js/handlers.js | 24 ++++++++++++++++++++---- js/weechat.js | 2 +- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/js/handlers.js b/js/handlers.js index 25ba797..be66ea3 100644 --- a/js/handlers.js +++ b/js/handlers.js @@ -21,11 +21,11 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific // inject a fake buffer line for date change var injectDateChangeMessage = function(message, buffer, date) { - var content = "Date changed to " + date.toDateString(); + var content = "\u001943Date changed to " + date.toDateString(); var line = { buffer: buffer, date: date, - prefix: '—', + prefix: '\u001943\u2500\u2500', tags_array: [], displayed: true, highlight: 0, @@ -47,8 +47,24 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific current_date = new Date(message.date); previous_date.setHours(0, 0, 0, 0); current_date.setHours(0, 0, 0, 0); - if (previous_date.valueOf() !== current_date.valueOf()) { - injectDateChangeMessage(message, buffer, current_date); + var dateDifference = + Math.round((current_date - previous_date)/(24*60*60*1000)); + if (dateDifference !== 0) { + console.log(dateDifference); + // if it's a small, positive number display a message + // for each one. Otherwise, just display one big + // date change message + // The range [1,5] was chosen arbitrarily + if (dateDifference >= 1 && dateDifference <= 5) { + var prev_date_clone = previous_date; + for (var i = 1; i <= dateDifference; ++i) { + prev_date_clone.setDate(prev_date_clone.getDate()+1); + injectDateChangeMessage(message, buffer, + prev_date_clone); + } + } else { + injectDateChangeMessage(message, buffer, current_date); + } } } diff --git a/js/weechat.js b/js/weechat.js index 126eda6..4a6d4f0 100644 --- a/js/weechat.js +++ b/js/weechat.js @@ -290,7 +290,7 @@ var ret = {}; var optionCode = parseInt(m[1]); - if (optionCode > 43) { + if (optionCode >= WeeChatProtocol._colorsOptionsNames.length) { // should never happen return { fgColor: null, From 9955056ed927da8922aec0f3ae4be822e9a0bfdc Mon Sep 17 00:00:00 2001 From: Patrick Melanson Date: Fri, 20 Nov 2015 22:26:56 -0500 Subject: [PATCH 19/70] dates change with weechat 2date behaviour --- js/handlers.js | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/js/handlers.js b/js/handlers.js index be66ea3..fa6f818 100644 --- a/js/handlers.js +++ b/js/handlers.js @@ -20,11 +20,26 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific }; // inject a fake buffer line for date change - var injectDateChangeMessage = function(message, buffer, date) { - var content = "\u001943Date changed to " + date.toDateString(); + var injectDateChangeMessage = function(message, buffer, d1, d2) { + var d1_plus_one = d1; + d1_plus_one.setDate(d1_plus_one.getDate() + 1); + d1.setHours(0, 0, 0, 0); + d2.setHours(0, 0, 0, 0); + // it's not always true that a date with time 00:00:00 + // plus one day will be time 00:00:00 + d1_plus_one.setHours(0, 0, 0, 0); + var content = ""; + if (d1_plus_one.valueOf() === d2.valueOf()) { + content = "\u001943Date changed to " + d2.toDateString(); + } else { + var date_diff = Math.round((d2 - d1)/(24*60*60*1000)); + date_diff = date_diff >= 0 ? date_diff : date_diff + 1; + content = "\u001943Date changed to " + d2.toDateString(); + content += " (" + date_diff + " days from " + d1.toDateString() + ")"; + } var line = { buffer: buffer, - date: date, + date: d2, prefix: '\u001943\u2500\u2500', tags_array: [], displayed: true, @@ -47,24 +62,8 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific current_date = new Date(message.date); previous_date.setHours(0, 0, 0, 0); current_date.setHours(0, 0, 0, 0); - var dateDifference = - Math.round((current_date - previous_date)/(24*60*60*1000)); - if (dateDifference !== 0) { - console.log(dateDifference); - // if it's a small, positive number display a message - // for each one. Otherwise, just display one big - // date change message - // The range [1,5] was chosen arbitrarily - if (dateDifference >= 1 && dateDifference <= 5) { - var prev_date_clone = previous_date; - for (var i = 1; i <= dateDifference; ++i) { - prev_date_clone.setDate(prev_date_clone.getDate()+1); - injectDateChangeMessage(message, buffer, - prev_date_clone); - } - } else { - injectDateChangeMessage(message, buffer, current_date); - } + if (previous_date.valueOf() !== current_date.valueOf()) { + injectDateChangeMessage(message, buffer, previous_date, current_date); } } From 5dc40cb1342cb738be3fa4b9608d804e9fff69c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Mon, 23 Nov 2015 10:59:00 +0100 Subject: [PATCH 20/70] Date change: prettier messages, code cleaning Has a weird bug: https://github.com/glowing-bear/glowing-bear/pull/677#issuecomment-158891237 --- js/handlers.js | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/js/handlers.js b/js/handlers.js index fa6f818..eab2101 100644 --- a/js/handlers.js +++ b/js/handlers.js @@ -20,26 +20,32 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific }; // inject a fake buffer line for date change - var injectDateChangeMessage = function(message, buffer, d1, d2) { - var d1_plus_one = d1; - d1_plus_one.setDate(d1_plus_one.getDate() + 1); - d1.setHours(0, 0, 0, 0); - d2.setHours(0, 0, 0, 0); + var injectDateChangeMessage = function(message, buffer, old_date, new_date) { + var old_date_plus_one = old_date; + old_date_plus_one.setDate(old_date.getDate() + 1); + + new_date.setHours(0, 0, 0, 0); + old_date.setHours(0, 0, 0, 0); // it's not always true that a date with time 00:00:00 // plus one day will be time 00:00:00 - d1_plus_one.setHours(0, 0, 0, 0); - var content = ""; - if (d1_plus_one.valueOf() === d2.valueOf()) { - content = "\u001943Date changed to " + d2.toDateString(); - } else { - var date_diff = Math.round((d2 - d1)/(24*60*60*1000)); - date_diff = date_diff >= 0 ? date_diff : date_diff + 1; - content = "\u001943Date changed to " + d2.toDateString(); - content += " (" + date_diff + " days from " + d1.toDateString() + ")"; + old_date_plus_one.setHours(0, 0, 0, 0); + + var content = "\u001943" + // styling + "Date changed to " + new_date.toDateString(); + // Comparing dates in javascript is beyond tedious + if (old_date_plus_one.valueOf() !== new_date.valueOf()) { + var date_diff = Math.round((new_date - old_date)/(24*60*60*1000)); + if (date_diff < 0) { + date_diff = -1*(date_diff + 1); + content += " (" + date_diff + " days before " + old_date.toDateString() + ")"; + } else { + content += " (" + date_diff + " days have passed since " + old_date.toDateString() + ")"; + } } + var line = { buffer: buffer, - date: d2, + date: new_date, prefix: '\u001943\u2500\u2500', tags_array: [], displayed: true, From 271a5d0626b65fbc602c791daf78f11e331e69fb Mon Sep 17 00:00:00 2001 From: Patrick Melanson Date: Fri, 27 Nov 2015 11:24:32 -0500 Subject: [PATCH 21/70] when switching buffers, will inject date change if date changed --- js/handlers.js | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/js/handlers.js b/js/handlers.js index eab2101..a2240de 100644 --- a/js/handlers.js +++ b/js/handlers.js @@ -20,7 +20,7 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific }; // inject a fake buffer line for date change - var injectDateChangeMessage = function(message, buffer, old_date, new_date) { + var injectDateChangeMessage = function(buffer, old_date, new_date) { var old_date_plus_one = old_date; old_date_plus_one.setDate(old_date.getDate() + 1); @@ -56,6 +56,15 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific buffer.addLine(new_message); }; + // wrapper to do the logic checking + var injectDateChangeMessageIfNeeded = function(buffer, previous_date, current_date) { + previous_date.setHours(0, 0, 0, 0); + current_date.setHours(0, 0, 0, 0); + if (previous_date.valueOf() !== current_date.valueOf()) { + injectDateChangeMessage(buffer, previous_date, current_date); + } + }; + var handleLine = function(line, manually) { var message = new models.BufferLine(line); var buffer = models.getBuffer(message.buffer); @@ -66,11 +75,7 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific if (buffer.lines.length > 0) { var previous_date = new Date(buffer.lines[buffer.lines.length - 1].date), current_date = new Date(message.date); - previous_date.setHours(0, 0, 0, 0); - current_date.setHours(0, 0, 0, 0); - if (previous_date.valueOf() !== current_date.valueOf()) { - injectDateChangeMessage(message, buffer, previous_date, current_date); - } + injectDateChangeMessageIfNeeded(buffer, previous_date, current_date); } message = plugins.PluginManager.contentForMessage(message); @@ -235,6 +240,13 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific lines.forEach(function(l) { handleLine(l, manually); }); + if (message.objects[0].content.length > 0) { + var last_line = + message.objects[0].content[message.objects[0].content.length-1]; + var last_message = new models.BufferLine(last_line); + var buffer = models.getBuffer(last_message.buffer); + injectDateChangeMessageIfNeeded(buffer, last_message.date, new Date()); + } }; /* From 9334f44cdeeb1144d4ca9c14dbf8f9917ca9b96e Mon Sep 17 00:00:00 2001 From: Patrick Melanson Date: Fri, 27 Nov 2015 14:38:18 -0500 Subject: [PATCH 22/70] more human readable date change, per #679 For one day later: Friday (November 27) (examples in en-US) For n>1 days: Friday (November 27, 2 days later) For n<0 days: Friday (November 27, 1 day before) For different years: Friday (November 27, 2015, 2156 days later) --- js/handlers.js | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/js/handlers.js b/js/handlers.js index a2240de..3541aa8 100644 --- a/js/handlers.js +++ b/js/handlers.js @@ -30,23 +30,49 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific // plus one day will be time 00:00:00 old_date_plus_one.setHours(0, 0, 0, 0); - var content = "\u001943" + // styling - "Date changed to " + new_date.toDateString(); + var content = "\u001943"; // this colour corresponds to chat_day_change + content += new_date.toLocaleDateString(window.navigator.language, + {weekday: "long"}); + // if you're testing different date formats, + // make sure to test different locales such as "en-US", + // "en-US-u-ca-persian" (which has different weekdays, year 0, and an ERA) + // "ja-JP-u-ca-persian-n-thai" (above, diff numbering, diff text) + var extra_date_format = { + day: "numeric", + month: "long" + }; + if (new_date.getYear() !== old_date.getYear()) { + extra_date_format.year = "numeric"; + } + content += " ("; + content += new_date.toLocaleDateString(window.navigator.language, + extra_date_format); + // Result should be something like + // Friday (November 27) + // or if the year is different, + // Friday (November 27, 2015) + // Comparing dates in javascript is beyond tedious if (old_date_plus_one.valueOf() !== new_date.valueOf()) { - var date_diff = Math.round((new_date - old_date)/(24*60*60*1000)); + var date_diff = Math.round((new_date - old_date)/(24*60*60*1000)) + 1; if (date_diff < 0) { - date_diff = -1*(date_diff + 1); - content += " (" + date_diff + " days before " + old_date.toDateString() + ")"; + date_diff = -1*(date_diff); + if (date_diff === 1) { + content += ", 1 day before"; + } else { + content += ", " + date_diff + " days before"; + } } else { - content += " (" + date_diff + " days have passed since " + old_date.toDateString() + ")"; + content += ", " + date_diff + " days later"; } + // Result: Friday (November 27, 5 days later) } + content += ")"; var line = { buffer: buffer, date: new_date, - prefix: '\u001943\u2500\u2500', + prefix: '\u001943\u2500', tags_array: [], displayed: true, highlight: 0, From 4f686d512dedec4282e54d02ddb8042a7db3f794 Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Sat, 28 Nov 2015 12:22:56 +0100 Subject: [PATCH 23/70] Request nicklist using ptr instead of fullname --- js/connection.js | 7 +++++-- js/glowingbear.js | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/js/connection.js b/js/connection.js index b39027f..4ea55ce 100644 --- a/js/connection.js +++ b/js/connection.js @@ -282,10 +282,13 @@ weechat.factory('connection', }; var requestNicklist = function(bufferId, callback) { - bufferId = bufferId || null; + // Prevent requesting nicklist for all buffers if bufferId is invalid + if (!bufferId) { + return; + } ngWebsockets.send( weeChat.Protocol.formatNicklist({ - buffer: bufferId + buffer: "0x"+bufferId }) ).then(function(nicklist) { handlers.handleNicklist(nicklist); diff --git a/js/glowingbear.js b/js/glowingbear.js index c0b746a..0c209c3 100644 --- a/js/glowingbear.js +++ b/js/glowingbear.js @@ -168,7 +168,7 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', // Send a request for the nicklist if it hasn't been loaded yet if (!ab.nicklistRequested()) { - connection.requestNicklist(ab.fullName, function() { + connection.requestNicklist(ab.id, function() { $scope.showNicklist = $scope.updateShowNicklist(); // Scroll after nicklist has been loaded, as it may break long lines $rootScope.scrollWithBuffer(true); From da7a7f85e87d7328d76a6530ef5c53c1e1ebe2fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sat, 28 Nov 2015 13:23:41 +0100 Subject: [PATCH 24/70] Date change: refactoring --- js/handlers.js | 130 +++++++++++++++++++++++-------------------------- 1 file changed, 62 insertions(+), 68 deletions(-) diff --git a/js/handlers.js b/js/handlers.js index 3541aa8..bf41604 100644 --- a/js/handlers.js +++ b/js/handlers.js @@ -19,75 +19,69 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific models.closeBuffer(bufferId); }; - // inject a fake buffer line for date change - var injectDateChangeMessage = function(buffer, old_date, new_date) { - var old_date_plus_one = old_date; - old_date_plus_one.setDate(old_date.getDate() + 1); - - new_date.setHours(0, 0, 0, 0); + // inject a fake buffer line for date change if needed + var injectDateChangeMessageIfNeeded = function(buffer, old_date, new_date) { old_date.setHours(0, 0, 0, 0); - // it's not always true that a date with time 00:00:00 - // plus one day will be time 00:00:00 - old_date_plus_one.setHours(0, 0, 0, 0); - - var content = "\u001943"; // this colour corresponds to chat_day_change - content += new_date.toLocaleDateString(window.navigator.language, - {weekday: "long"}); - // if you're testing different date formats, - // make sure to test different locales such as "en-US", - // "en-US-u-ca-persian" (which has different weekdays, year 0, and an ERA) - // "ja-JP-u-ca-persian-n-thai" (above, diff numbering, diff text) - var extra_date_format = { - day: "numeric", - month: "long" - }; - if (new_date.getYear() !== old_date.getYear()) { - extra_date_format.year = "numeric"; - } - content += " ("; - content += new_date.toLocaleDateString(window.navigator.language, - extra_date_format); - // Result should be something like - // Friday (November 27) - // or if the year is different, - // Friday (November 27, 2015) - - // Comparing dates in javascript is beyond tedious - if (old_date_plus_one.valueOf() !== new_date.valueOf()) { - var date_diff = Math.round((new_date - old_date)/(24*60*60*1000)) + 1; - if (date_diff < 0) { - date_diff = -1*(date_diff); - if (date_diff === 1) { - content += ", 1 day before"; + new_date.setHours(0, 0, 0, 0); + // Check if the date changed + if (old_date.valueOf() !== new_date.valueOf()) { + var old_date_plus_one = old_date; + old_date_plus_one.setDate(old_date.getDate() + 1); + // it's not always true that a date with time 00:00:00 + // plus one day will be time 00:00:00 + old_date_plus_one.setHours(0, 0, 0, 0); + + var content = "\u001943"; // this colour corresponds to chat_day_change + // Add day of the week + content += new_date.toLocaleDateString(window.navigator.language, + {weekday: "long"}); + // if you're testing different date formats, + // make sure to test different locales such as "en-US", + // "en-US-u-ca-persian" (which has different weekdays, year 0, and an ERA) + // "ja-JP-u-ca-persian-n-thai" (above, diff numbering, diff text) + var extra_date_format = { + day: "numeric", + month: "long" + }; + if (new_date.getYear() !== old_date.getYear()) { + extra_date_format.year = "numeric"; + } + content += " ("; + content += new_date.toLocaleDateString(window.navigator.language, + extra_date_format); + // Result should be something like + // Friday (November 27) + // or if the year is different, + // Friday (November 27, 2015) + + // Comparing dates in javascript is beyond tedious + if (old_date_plus_one.valueOf() !== new_date.valueOf()) { + var date_diff = Math.round((new_date - old_date)/(24*60*60*1000)) + 1; + if (date_diff < 0) { + date_diff = -1*(date_diff); + if (date_diff === 1) { + content += ", 1 day before"; + } else { + content += ", " + date_diff + " days before"; + } } else { - content += ", " + date_diff + " days before"; + content += ", " + date_diff + " days later"; } - } else { - content += ", " + date_diff + " days later"; + // Result: Friday (November 27, 5 days later) } - // Result: Friday (November 27, 5 days later) - } - content += ")"; - - var line = { - buffer: buffer, - date: new_date, - prefix: '\u001943\u2500', - tags_array: [], - displayed: true, - highlight: 0, - message: content - }; - var new_message = new models.BufferLine(line); - buffer.addLine(new_message); - }; - - // wrapper to do the logic checking - var injectDateChangeMessageIfNeeded = function(buffer, previous_date, current_date) { - previous_date.setHours(0, 0, 0, 0); - current_date.setHours(0, 0, 0, 0); - if (previous_date.valueOf() !== current_date.valueOf()) { - injectDateChangeMessage(buffer, previous_date, current_date); + content += ")"; + + var line = { + buffer: buffer, + date: new_date, + prefix: '\u001943\u2500', + tags_array: [], + displayed: true, + highlight: 0, + message: content + }; + var new_message = new models.BufferLine(line); + buffer.addLine(new_message); } }; @@ -99,9 +93,9 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific if (message.displayed) { // Check for date change if (buffer.lines.length > 0) { - var previous_date = new Date(buffer.lines[buffer.lines.length - 1].date), - current_date = new Date(message.date); - injectDateChangeMessageIfNeeded(buffer, previous_date, current_date); + var old_date = new Date(buffer.lines[buffer.lines.length - 1].date), + new_date = new Date(message.date); + injectDateChangeMessageIfNeeded(buffer, old_date, new_date); } message = plugins.PluginManager.contentForMessage(message); From d1176a5b2bb781e4c7bddd6878c413d134d2e04a Mon Sep 17 00:00:00 2001 From: Hannu Hartikainen Date: Fri, 27 Nov 2015 17:58:07 +0200 Subject: [PATCH 25/70] disallow nested links in DOMfilter (fixes #680) --- js/filters.js | 12 +++++++++++- test/unit/filters.js | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/js/filters.js b/js/filters.js index 71ecee9..70f9341 100644 --- a/js/filters.js +++ b/js/filters.js @@ -61,10 +61,15 @@ weechat.filter('inlinecolour', function() { // apply a filter to an HTML string's text nodes, and do so with not exceedingly terrible performance weechat.filter('DOMfilter', ['$filter', '$sce', function($filter, $sce) { + // To prevent nested anchors, we need to know if a filter is going to create them. + // Here's a list of names. See #681 for more information. + var filtersThatCreateAnchors = ['irclinky']; + return function(text, filter) { if (!text || !filter) { return text; } + var createsAnchor = filtersThatCreateAnchors.indexOf(filter) > -1; var escape_html = function(text) { // First, escape entities to prevent escaping issues because it's a bad idea @@ -92,6 +97,7 @@ weechat.filter('DOMfilter', ['$filter', '$sce', function($filter, $sce) { // as innerHTML causes it to be unescaped. var input = escape_html(node.nodeValue); var value = filterFunction(input, extraArgument, thirdArgument); + if (value !== input) { // we changed something. create a new node to replace the current one // we could also only add its children but that would probably incur @@ -114,7 +120,11 @@ weechat.filter('DOMfilter', ['$filter', '$sce', function($filter, $sce) { if (node === undefined || node === null) return; node = node.firstChild; while (node) { - var nextNode = process(node); + var nextNode; + // do not recurse inside links if the filter would create a nested link + if (!(createsAnchor && node.tagName === 'A')) { + nextNode = process(node); + } node = (nextNode ? nextNode : node).nextSibling; } }; diff --git a/test/unit/filters.js b/test/unit/filters.js index ca1228e..b1eedec 100644 --- a/test/unit/filters.js +++ b/test/unit/filters.js @@ -22,6 +22,13 @@ describe('Filters', function() { it('should not mess up IRC channels surrounded by HTML entities', inject(function(irclinkyFilter) { expect(irclinkyFilter('<"#foo">')).toEqual('<"\');">#foo">'); })); + + it('should not touch links created by `linky`', inject(function(linkyFilter, DOMfilterFilter) { + var url = 'http://foo.bar/#baz', + link = linkyFilter(url, '_blank'), + result = DOMfilterFilter(link, 'irclinky').$$unwrapTrustedValue(); + expect(result).toEqual(link); + })); }); describe('inlinecolour', function() { @@ -62,4 +69,19 @@ describe('Filters', function() { })); }); + describe('DOMfilter', function() { + it('should run a filter on all text nodes', inject(function(DOMfilterFilter) { + var dom = 'a

    bcdefgh

    i', + expected = 'A

    BCDEFGH

    I', + result = DOMfilterFilter(dom, 'uppercase').$$unwrapTrustedValue(); + expect(result).toEqual(expected); + })); + + it('should pass additional arguments to the filter', inject(function(DOMfilterFilter) { + var dom = '1

    2

    3.14159265', + expected = '1.00

    2.00

    3.14', + result = DOMfilterFilter(dom, 'number', 2).$$unwrapTrustedValue(); + expect(result).toEqual(expected); + })); + }); }); From 735798831fbe15a99a6451e35a498edc5a60d361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sat, 28 Nov 2015 20:54:45 +0100 Subject: [PATCH 26/70] Date change marker: Don't modify last line's date --- js/handlers.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/js/handlers.js b/js/handlers.js index bf41604..3ee6fb2 100644 --- a/js/handlers.js +++ b/js/handlers.js @@ -261,11 +261,14 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific handleLine(l, manually); }); if (message.objects[0].content.length > 0) { - var last_line = + // fiddle out the buffer ID and take the last line's date + var last_object = message.objects[0].content[message.objects[0].content.length-1]; - var last_message = new models.BufferLine(last_line); - var buffer = models.getBuffer(last_message.buffer); - injectDateChangeMessageIfNeeded(buffer, last_message.date, new Date()); + var buffer = models.getBuffer(last_object.buffer); + if (buffer.lines.length > 0) { + var last_date = new Date(buffer.lines[buffer.lines.length - 1].date); + injectDateChangeMessageIfNeeded(buffer, last_date, new Date()); + } } }; From 507a39f68f9ad8de9eeb9eb5cbbfdfe8d6da1619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sat, 28 Nov 2015 20:55:24 +0100 Subject: [PATCH 27/70] Don't show date change message for free buffers This requires requesting the buffer type and handling the apropriate event --- js/connection.js | 2 +- js/handlers.js | 17 +++++++++++++++-- js/models.js | 4 ++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/js/connection.js b/js/connection.js index 4ea55ce..590606c 100644 --- a/js/connection.js +++ b/js/connection.js @@ -62,7 +62,7 @@ weechat.factory('connection', return ngWebsockets.send( weeChat.Protocol.formatHdata({ path: 'buffer:gui_buffers(*)', - keys: ['local_variables,notify,number,full_name,short_name,title,hidden'] + keys: ['local_variables,notify,number,full_name,short_name,title,hidden,type'] }) ); }; diff --git a/js/handlers.js b/js/handlers.js index 3ee6fb2..577cf2c 100644 --- a/js/handlers.js +++ b/js/handlers.js @@ -21,6 +21,10 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific // inject a fake buffer line for date change if needed var injectDateChangeMessageIfNeeded = function(buffer, old_date, new_date) { + if (buffer.bufferType === 1) { + // Don't add date change messages to free buffers + return; + } old_date.setHours(0, 0, 0, 0); new_date.setHours(0, 0, 0, 0); // Check if the date changed @@ -247,6 +251,14 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific } }; + var handleBufferTypeChanged = function(message) { + var obj = message.objects[0].content[0]; + var buffer = obj.pointers[0]; + var old = models.getBuffer(buffer); + // 0 = formatted (normal); 1 = free + buffer.bufferType = obj.type; + }; + /* * Handle answers to (lineinfo) messages * @@ -262,9 +274,9 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific }); if (message.objects[0].content.length > 0) { // fiddle out the buffer ID and take the last line's date - var last_object = + var last_line = message.objects[0].content[message.objects[0].content.length-1]; - var buffer = models.getBuffer(last_object.buffer); + var buffer = models.getBuffer(last_line.buffer); if (buffer.lines.length > 0) { var last_date = new Date(buffer.lines[buffer.lines.length - 1].date); injectDateChangeMessageIfNeeded(buffer, last_date, new Date()); @@ -351,6 +363,7 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific _buffer_localvar_changed: handleBufferLocalvarChanged, _buffer_opened: handleBufferOpened, _buffer_title_changed: handleBufferTitleChanged, + _buffer_type_changed: handleBufferTypeChanged, _buffer_renamed: handleBufferRenamed, _buffer_hidden: handleBufferHidden, _buffer_unhidden: handleBufferUnhidden, diff --git a/js/models.js b/js/models.js index baa1aec..8a4dd43 100644 --- a/js/models.js +++ b/js/models.js @@ -85,6 +85,9 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter) var unread = 0; var lastSeen = -1; var serverSortKey = fullName.replace(/^irc\.server\.(\w+)/, "irc.$1"); + // There are two kinds of types: bufferType (free vs formatted) and + // the kind of type that distinguishes queries from channels etc + var bufferType = message.type; var type = message.local_variables.type; var indent = (['channel', 'private'].indexOf(type) >= 0); @@ -311,6 +314,7 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter) getNicklistByTime: getNicklistByTime, serverSortKey: serverSortKey, indent: indent, + bufferType: bufferType, type: type, history: history, addToHistory: addToHistory, From 34b25bf80c23bb62d40d3029d990643ff7fc934f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sat, 28 Nov 2015 21:08:42 +0100 Subject: [PATCH 28/70] Add empty hrefs to make browser extensions happy Fixes #656 --- index.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index 9331471..f49dd12 100644 --- a/index.html +++ b/index.html @@ -240,10 +240,10 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
@@ -256,7 +256,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
  • - + {{ buffer.$quickKey }} {{ buffer.trimmedName || buffer.fullName }} @@ -276,7 +276,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel - Fetch more lines + Fetch more lines Fetching more lines... @@ -310,7 +310,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel

    Connection to WeeChat lost

    - Reconnecting... Click to try to reconnect now + Reconnecting... Click to try to reconnect now
    From a631a913c7f019ba2c9fd210ff99ffbf2326c0ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sat, 28 Nov 2015 21:25:06 +0100 Subject: [PATCH 29/70] Fix initialisation of global unread count Fixes #595 --- js/glowingbear.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/js/glowingbear.js b/js/glowingbear.js index 0c209c3..3e3a2e2 100644 --- a/js/glowingbear.js +++ b/js/glowingbear.js @@ -214,8 +214,10 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', ); } notifications.updateTitle(ab); - $scope.notifications = notifications.unreadCount('notification'); - $scope.unread = notifications.unreadCount('unread'); + setTimeout(function(){ + $scope.notifications = notifications.unreadCount('notification'); + $scope.unread = notifications.unreadCount('unread'); + }); $timeout(function() { $rootScope.scrollWithBuffer(true); From b0f4ee4413ea77c154392f57b56e9e63edf5f704 Mon Sep 17 00:00:00 2001 From: Hannu Hartikainen Date: Tue, 1 Dec 2015 21:31:12 +0200 Subject: [PATCH 30/70] fix #688 and provide a unit test --- js/filters.js | 2 +- test/unit/filters.js | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/js/filters.js b/js/filters.js index 70f9341..46fa02e 100644 --- a/js/filters.js +++ b/js/filters.js @@ -120,7 +120,7 @@ weechat.filter('DOMfilter', ['$filter', '$sce', function($filter, $sce) { if (node === undefined || node === null) return; node = node.firstChild; while (node) { - var nextNode; + var nextNode = null; // do not recurse inside links if the filter would create a nested link if (!(createsAnchor && node.tagName === 'A')) { nextNode = process(node); diff --git a/test/unit/filters.js b/test/unit/filters.js index b1eedec..2b1358f 100644 --- a/test/unit/filters.js +++ b/test/unit/filters.js @@ -83,5 +83,13 @@ describe('Filters', function() { result = DOMfilterFilter(dom, 'number', 2).$$unwrapTrustedValue(); expect(result).toEqual(expected); })); + + it('should never lock up like in bug #688', inject(function(linkyFilter, DOMfilterFilter) { + var msg = '#crash http://google.com', + linked = linkyFilter(msg), + irclinked = DOMfilterFilter(linked, 'irclinky'); + // With the bug, the DOMfilterFilter call ends up in an infinite loop. + // I.e. if we ever got this far, the bug is fixed. + })); }); }); From 3b60f992b4623f4d8eac2451f9062e81334df6f2 Mon Sep 17 00:00:00 2001 From: Mukunda Modell Date: Tue, 1 Dec 2015 17:02:32 -0600 Subject: [PATCH 31/70] Switch to adjacent buffer with alt+arrow Use alt+up and alt+down to switch to previous / next buffer. Works when bufferlist is nested or flat. This implements issue #511. --- js/glowingbear.js | 12 ++++++++++++ js/inputbar.js | 8 ++++++++ js/models.js | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/js/glowingbear.js b/js/glowingbear.js index 3e3a2e2..9c2caed 100644 --- a/js/glowingbear.js +++ b/js/glowingbear.js @@ -727,6 +727,18 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', settings.nonicklist = !settings.nonicklist; }; + $rootScope.switchToAdjacentBuffer = function(direction) { + // direction is +1 for next buffer, -1 for previous buffer + var sortedBuffers = _.sortBy($scope.getBuffers(), $rootScope.predicate); + var activeBuffer = models.getActiveBuffer(); + var index = sortedBuffers.indexOf(activeBuffer); + if (index >= 0) { + var newBuffer = sortedBuffers[index + direction]; + if (newBuffer) { + $scope.setActiveBuffer(newBuffer.id); + } + } + }; $scope.handleSearchBoxKey = function($event) { // Support different browser quirks diff --git a/js/inputbar.js b/js/inputbar.js index 9d18506..2cd24c7 100644 --- a/js/inputbar.js +++ b/js/inputbar.js @@ -294,6 +294,14 @@ weechat.directive('inputBar', function() { return true; } + // Alt+Arrow up/down -> switch to prev/next adjacent buffer + if ($event.altKey && !$event.ctrlKey && (code === 38 || code === 40)) { + $event.preventDefault(); + var direction = code - 39; + $rootScope.switchToAdjacentBuffer(direction); + return true; + } + // Alt+L -> focus on input bar if ($event.altKey && (code === 76 || code === 108)) { $event.preventDefault(); diff --git a/js/models.js b/js/models.js index 8a4dd43..5b8a7bb 100644 --- a/js/models.js +++ b/js/models.js @@ -84,7 +84,7 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter) var notification = 0; var unread = 0; var lastSeen = -1; - var serverSortKey = fullName.replace(/^irc\.server\.(\w+)/, "irc.$1"); + var serverSortKey = fullName.replace(/^irc\.server\.(\w+)/, "irc.$1").toLowerCase(); // There are two kinds of types: bufferType (free vs formatted) and // the kind of type that distinguishes queries from channels etc var bufferType = message.type; From ceceac78a2b8ec59ed7c84859afbb60933056e71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sat, 5 Dec 2015 13:58:02 +0100 Subject: [PATCH 32/70] Use buffer localvars instead of regex hackery Fixes #589 --- js/handlers.js | 5 +++++ js/models.js | 13 ++++++++++++- js/notifications.js | 5 ++--- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/js/handlers.js b/js/handlers.js index 577cf2c..1a75b5d 100644 --- a/js/handlers.js +++ b/js/handlers.js @@ -248,6 +248,11 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific // Update indentation status old.type = localvars.type; old.indent = (['channel', 'private'].indexOf(localvars.type) >= 0); + // Update serverSortKey and related variables + old.plugin = localvars.plugin; + old.server = localvars.server; + old.serverSortKey = old.plugin + "." + old.server + + (old.type === "server" ? "" : ("." + old.shortName)); } }; diff --git a/js/models.js b/js/models.js index 5b8a7bb..4bb239e 100644 --- a/js/models.js +++ b/js/models.js @@ -84,13 +84,22 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter) var notification = 0; var unread = 0; var lastSeen = -1; - var serverSortKey = fullName.replace(/^irc\.server\.(\w+)/, "irc.$1").toLowerCase(); // There are two kinds of types: bufferType (free vs formatted) and // the kind of type that distinguishes queries from channels etc var bufferType = message.type; var type = message.local_variables.type; var indent = (['channel', 'private'].indexOf(type) >= 0); + var plugin = message.local_variables.plugin; + var server = message.local_variables.server; + // Server buffers have this "irc.server.freenode" naming schema, which + // messes the sorting up. We need it to be "irc.freenode" instead. + var serverSortKey = plugin + "." + server + + (type === "server" ? "" : ("." + shortName)); + // Lowercase it so alt+up/down traverses buffers in the same order + // angular's sortBy directive puts them in + serverSortKey = serverSortKey.toLowerCase(); + // Buffer opened message does not include notify level if (message.notify !== undefined) { notify = message.notify; @@ -316,6 +325,8 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter) indent: indent, bufferType: bufferType, type: type, + plugin: plugin, + server: server, history: history, addToHistory: addToHistory, getHistoryUp: getHistoryUp, diff --git a/js/notifications.js b/js/notifications.js index 2caca39..1e03db6 100644 --- a/js/notifications.js +++ b/js/notifications.js @@ -83,7 +83,7 @@ weechat.factory('notifications', ['$rootScope', '$log', 'models', 'settings', fu var body = ''; var numNotifications = buffer.notification; - if (['#', '&', '+', '!'].indexOf(buffer.shortName.charAt(0)) < 0) { + if (buffer.type === "private") { if (numNotifications > 1) { title = numNotifications.toString() + ' private messages from '; } else { @@ -102,8 +102,7 @@ weechat.factory('notifications', ['$rootScope', '$log', 'models', 'settings', fu } body = '<' + prefix + '> ' + message.text; } - title += buffer.shortName; - title += buffer.fullName.replace(/irc.([^\.]+)\..+/, " ($1)"); + title += buffer.shortName + " (" + buffer.server + ")"; var notification = new Notification(title, { body: body, From c3f00cd6bcdc53548d364430e40cd8f1e998a492 Mon Sep 17 00:00:00 2001 From: Hannu Hartikainen Date: Tue, 8 Dec 2015 22:57:53 +0200 Subject: [PATCH 33/70] prevent "zalgo text" from exiting the message/bufferline For a review of what zalgo text is and how it works, see http://stackoverflow.com/q/6579844/659526 . Suffice to say it abuses unicode to create a vertical mess that goes over other lines of text. --- css/glowingbear.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/css/glowingbear.css b/css/glowingbear.css index a6d10d8..b46452f 100644 --- a/css/glowingbear.css +++ b/css/glowingbear.css @@ -29,6 +29,7 @@ td.prefix { border-right: 1px solid #444; } td.message { + overflow: hidden; vertical-align: top; width: 100%; padding: 1px 1px 1px 5px; @@ -772,7 +773,13 @@ img.emojione { padding-bottom: 0; } + #bufferlines tr.bufferline { + display: block; + overflow: hidden; + } + #bufferlines td.time { + display: inline-block; padding-right: 3px; font-size: 0.8em; } From 9cf6c84013507ca42a3e76ac0975e210192f6965 Mon Sep 17 00:00:00 2001 From: Hannu Hartikainen Date: Tue, 8 Dec 2015 23:42:20 +0200 Subject: [PATCH 34/70] update karma and install some dependencies; fixes #696 --- package.json | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 32f913d..cb05efc 100644 --- a/package.json +++ b/package.json @@ -6,33 +6,31 @@ "repository": "https://github.com/glowing-bear/glowing-bear", "license": "GPLv3", "devDependencies": { - "karma": "~0.10", - "protractor": "~0.20.1", - "http-server": "^0.6.1", "bower": "^1.3.1", - "shelljs": "^0.2.6", + "http-server": "^0.6.1", + "jasmine-core": "^2.4.1", "jshint": "^2.5.2", + "karma": "~0.13", + "karma-jasmine": "^0.3.6", "karma-junit-reporter": "^0.2.2", + "karma-phantomjs-launcher": "^0.2.1", + "phantomjs": "^1.9.19", + "protractor": "~0.20.1", + "shelljs": "^0.2.6", "uglify-js": "^2.4" }, "scripts": { "postinstall": "bower install", - "minify": " uglifyjs js/localstorage.js js/weechat.js js/irc-utils.js js/glowingbear.js js/settings.js js/utils.js js/notifications.js js/filters.js js/handlers.js js/connection.js js/inputbar.js js/plugin-directive.js js/websockets.js js/models.js js/plugins.js -c -m --screw-ie8 -o min.js --source-map min.map", - "prestart": "npm install", "start": "http-server -a localhost -p 8000", - "pretest": "npm install", "test": "karma start test/karma.conf.js", "test-single-run": "karma start test/karma.conf.js --single-run", - "preupdate-webdriver": "npm install", "update-webdriver": "webdriver-manager update", - "preprotractor": "npm run update-webdriver", "protractor": "protractor test/protractor-conf.js", - "update-index-async": "node -e \"require('shelljs/global'); sed('-i', /\\/\\/@@NG_LOADER_START@@[\\s\\S]*\\/\\/@@NG_LOADER_END@@/, '//@@NG_LOADER_START@@\\n' + cat('app/bower_components/angular-loader/angular-loader.min.js') + '\\n//@@NG_LOADER_END@@', 'app/index-async.html');\"" } } From 17671c560d3e939595a8242dee4e4880a65cf86b Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Mon, 14 Dec 2015 15:49:44 +0100 Subject: [PATCH 35/70] add CSS to make spin icon --- css/glowingbear.css | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/css/glowingbear.css b/css/glowingbear.css index b46452f..44364a9 100644 --- a/css/glowingbear.css +++ b/css/glowingbear.css @@ -638,6 +638,31 @@ img.emojione { width: auto; } +.glyphicon-spin { + -webkit-animation: spin 1000ms infinite linear; + animation: spin 1000ms infinite linear; +} +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + @media (min-width: 1400px) { #sidebar[data-state=visible], #sidebar { width: 200px; From 5494fefbcbe3858f5782a9b9c01fba274075dc0a Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Mon, 14 Dec 2015 16:02:49 +0100 Subject: [PATCH 36/70] use spinner for connect/reconnect/fetchmorelines --- index.html | 8 ++++---- js/glowingbear.js | 9 +++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index f49dd12..61ca137 100644 --- a/index.html +++ b/index.html @@ -112,7 +112,7 @@
  • - +

    @@ -276,8 +276,8 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel - Fetch more lines - Fetching more lines... + Fetch more lines + Fetching more lines @@ -310,7 +310,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel

    Connection to WeeChat lost

    - Reconnecting... Click to try to reconnect now + Reconnecting... Click to try to reconnect now
    diff --git a/js/glowingbear.js b/js/glowingbear.js index 9c2caed..33eeed9 100644 --- a/js/glowingbear.js +++ b/js/glowingbear.js @@ -264,8 +264,10 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', models.reinitialize(); $rootScope.$emit('notificationChanged'); $scope.connectbutton = 'Connect'; + $scope.connectbuttonicon = 'glyphicon-chevron-right'; }); $scope.connectbutton = 'Connect'; + $scope.connectbuttonicon = 'glyphicon-chevron-right'; $scope.getBuffers = models.getBuffers.bind(models); @@ -582,11 +584,13 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', $rootScope.securityError = false; $rootScope.errorMessage = false; $rootScope.bufferBottom = true; - $scope.connectbutton = 'Connecting ...'; + $scope.connectbutton = 'Connecting'; + $scope.connectbuttonicon = 'glyphicon-refresh glyphicon-spin'; connection.connect(settings.host, settings.port, $scope.password, settings.ssl); }; $scope.disconnect = function() { $scope.connectbutton = 'Connect'; + $scope.connectbuttonicon = 'glyphicon-chevron-right'; connection.disconnect(); }; $scope.reconnect = function() { @@ -788,7 +792,8 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', $rootScope.securityError = false; $rootScope.errorMessage = false; $rootScope.bufferBottom = true; - $scope.connectbutton = 'Connecting ...'; + $scope.connectbutton = 'Connecting'; + $scope.connectbuttonicon = 'glyphicon-chevron-right'; connection.connect(host, port, password, ssl); } }; From 59e06623202a3db960c9e78ed86f89f3b7a93271 Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Wed, 16 Dec 2015 12:34:35 +0100 Subject: [PATCH 37/70] fixes regarding EmojiOne * Add attribution, EmojiOne requires attribution, see: http://emojione.com/developers * Upgrade to newest version * Remove mention of old twemoji --- README.md | 2 +- index.html | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9907c6d..2b15643 100644 --- a/README.md +++ b/README.md @@ -83,4 +83,4 @@ If you wish to submit code, we try to make the contribution process as simple as We'd also like to ask you to join our IRC channel, #glowing-bear on freenode, so we can discuss your ideas and changes. -If you're curious about the projects we're using, here's a list: [AngularJS](https://angularjs.org/), [Bootstrap](http://getbootstrap.com/), [Underscore](http://underscorejs.org/), [favico.js](http://lab.ejci.net/favico.js/), [twemoji](https://github.com/twitter/twemoji), and [zlib.js](https://github.com/imaya/zlib.js). Technology-wise, [WebSockets](http://en.wikipedia.org/wiki/WebSocket) are the most important part, but we also use [local storage](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage#localStorage), the [Notification Web API](https://developer.mozilla.org/en/docs/Web/API/notification), and last (but not least) [Apache Cordova](https://cordova.apache.org/) for our mobile app. +If you're curious about the projects we're using, here's a list: [AngularJS](https://angularjs.org/), [Bootstrap](http://getbootstrap.com/), [Underscore](http://underscorejs.org/), [favico.js](http://lab.ejci.net/favico.js/), Emoji provided free by [Emoji One](http://emojione.com/), and [zlib.js](https://github.com/imaya/zlib.js). Technology-wise, [WebSockets](http://en.wikipedia.org/wiki/WebSocket) are the most important part, but we also use [local storage](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage#localStorage), the [Notification Web API](https://developer.mozilla.org/en/docs/Web/API/notification), and last (but not least) [Apache Cordova](https://cordova.apache.org/) for our mobile app. diff --git a/index.html b/index.html index 61ca137..bbbef49 100644 --- a/index.html +++ b/index.html @@ -22,7 +22,7 @@ - + @@ -456,7 +456,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
    From 68a766af0a014f962ecfe0c4cac7e80bbd00718c Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Wed, 16 Dec 2015 14:01:38 +0100 Subject: [PATCH 38/70] Fix for password error The old error handler wasn't really working for unknown reasons, but this seems to fix it. --- js/connection.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/js/connection.js b/js/connection.js index 590606c..a876ee6 100644 --- a/js/connection.js +++ b/js/connection.js @@ -17,6 +17,7 @@ weechat.factory('connection', // Takes care of the connection and websocket hooks var connect = function (host, port, passwd, ssl, noCompression, successCallback, failCallback) { + $rootScope.passwordError = false; connectionData = [host, port, passwd, ssl, noCompression]; var proto = ssl ? 'wss' : 'ws'; // If host is an IPv6 literal wrap it in brackets @@ -98,11 +99,8 @@ weechat.factory('connection', $log.info("Connected to relay"); $rootScope.connected = true; }, - function() { - // Connection got closed, lets check if we ever was connected successfully - if (!$rootScope.waseverconnected) { - $rootScope.passwordError = true; - } + function(e) { + handleWrongPassword(); } ); @@ -121,12 +119,14 @@ weechat.factory('connection', * Handles websocket disconnection */ $log.info("Disconnected from relay"); + $rootScope.$emit('relayDisconnect'); if ($rootScope.userdisconnect || !$rootScope.waseverconnected) { handleClose(evt); $rootScope.userdisconnect = false; } else { reconnect(evt); } + handleWrongPassword(); }; var handleClose = function (evt) { @@ -140,6 +140,14 @@ weechat.factory('connection', } }; + var handleWrongPassword = function() { + // Connection got closed, lets check if we ever was connected successfully + if (!$rootScope.waseverconnected && !$rootScope.errorMessage) { + $rootScope.passwordError = true; + $rootScope.$apply(); + } + }; + var onerror = function (evt) { /* * Handles cases when connection issues come from From e3f2a160b9101c3534c068d21b51c27e953709c1 Mon Sep 17 00:00:00 2001 From: Patrick Melanson Date: Thu, 17 Dec 2015 10:45:38 -0500 Subject: [PATCH 39/70] #700 increment buffer.lastSeen on date change message --- js/handlers.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/handlers.js b/js/handlers.js index 1a75b5d..7fec088 100644 --- a/js/handlers.js +++ b/js/handlers.js @@ -29,6 +29,7 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific new_date.setHours(0, 0, 0, 0); // Check if the date changed if (old_date.valueOf() !== new_date.valueOf()) { + ++buffer.lastSeen var old_date_plus_one = old_date; old_date_plus_one.setDate(old_date.getDate() + 1); // it's not always true that a date with time 00:00:00 From 86f6a377022756d2ed680cbaf16b86c8a347d7d6 Mon Sep 17 00:00:00 2001 From: Patrick Melanson Date: Thu, 17 Dec 2015 10:55:50 -0500 Subject: [PATCH 40/70] semicolons :'( :'( :'( fixes failing build --- js/handlers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/handlers.js b/js/handlers.js index 7fec088..5103b9c 100644 --- a/js/handlers.js +++ b/js/handlers.js @@ -29,7 +29,7 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific new_date.setHours(0, 0, 0, 0); // Check if the date changed if (old_date.valueOf() !== new_date.valueOf()) { - ++buffer.lastSeen + ++buffer.lastSeen; var old_date_plus_one = old_date; old_date_plus_one.setDate(old_date.getDate() + 1); // it's not always true that a date with time 00:00:00 From e1102522ac0ab5297f547e83e5e4ee25215b7433 Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Thu, 17 Dec 2015 16:47:41 +0100 Subject: [PATCH 41/70] weechat.js: implement infolist --- js/weechat.js | 64 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/js/weechat.js b/js/weechat.js index 4a6d4f0..640ccbd 100644 --- a/js/weechat.js +++ b/js/weechat.js @@ -23,9 +23,7 @@ 'buf': this._getString, 'arr': this._getArray, 'htb': this._getHashTable, - 'inl': function() { - this._warnUnimplemented('infolist'); - } + 'inl': this._getInfolist, }; // string value for some object types @@ -699,6 +697,37 @@ return WeeChatProtocol._formatCmd(params.id, 'info', parts); }; + /** + * Formats an infolist command. + * + * @param params Parameters: + * id: command ID (optional) + * name: infolist name (mandatory) + * pointer: optional + * arguments: optional + * @return Formatted infolist command string + */ + WeeChatProtocol.formatInfolist = function(params) { + var defaultParams = { + id: null, + pointer: null, + args: null + + }; + var parts = []; + + params = WeeChatProtocol._mergeParams(defaultParams, params); + parts.push(params.name); + if (params.pointer !== null) { + parts.push(params.pointer); + } + if (params.pointer !== null) { + parts.push(params.args); + } + + return WeeChatProtocol._formatCmd(params.id, 'infolist', parts); + }; + /** * Formats a nicklist command. * @@ -1143,6 +1172,35 @@ return values; }, + /** + * Reads an infolist object from the current set of data + * + * @return Array + */ + _getInfolist: function() { + var self = this; + var name; + var count; + var values; + + name = this._getString(); + count = this._getInt(); + values = []; + + for (var i = 0; i < count; i++) { + var itemcount = self._getInt(); + var litem = []; + for (var j = 0; j < itemcount; j++) { + var item = {}; + item[self._getString()] = self._runType(self._getType()); + litem.push(item); + } + values.push(litem); + } + + return values; + }, + /** * Reads a specified number of bytes from current set data. * From c9dbdc39e432867ddfb22626c6c955fd822a3d3a Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Thu, 17 Dec 2015 17:45:34 +0100 Subject: [PATCH 42/70] fetch weechat configuration variables Usage: fetchConfValue('weechat.look.buffer_time_format') will result in models.wconfig['weechat.look.buffer_time_format'] to be set when the result returns from WeeChat. Could maybe be extended to also call a callback when it's available if needed. --- js/connection.js | 13 ++++++++++++- js/handlers.js | 22 ++++++++++++++++++++++ js/models.js | 3 +++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/js/connection.js b/js/connection.js index a876ee6..319219f 100644 --- a/js/connection.js +++ b/js/connection.js @@ -99,7 +99,7 @@ weechat.factory('connection', $log.info("Connected to relay"); $rootScope.connected = true; }, - function(e) { + function() { handleWrongPassword(); } ); @@ -306,6 +306,17 @@ weechat.factory('connection', }); }; + var fetchConfValue = function(name) { + ngWebsockets.send( + weeChat.Protocol.formatInfolist({ + name: "option", + pointer: 0, + args: name + }) + ).then(function(i) { + handlers.handleConfValue(i); + }); + }; var fetchMoreLines = function(numLines) { $log.debug('Fetching ', numLines, ' lines'); diff --git a/js/handlers.js b/js/handlers.js index 1a75b5d..5de02d1 100644 --- a/js/handlers.js +++ b/js/handlers.js @@ -13,6 +13,27 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific models.version = version.split(".").map(function(c) { return parseInt(c); }); }; + var handleConfValue = function(message) { + var infolist = message.objects[0].content; + for (var i = 0; i < infolist.length ; i++) { + var key, val; + var item = infolist[i]; + for (var j = 0; j < item.length ; j++) { + var confitem = item[j]; + if (confitem.full_name) { + key = confitem.full_name; + } + if (confitem.value) { + val = confitem.value; + } + } + if (key && val) { + $log.debug('Setting wconfig "' + key + '" to value "' + val + '"'); + models.wconfig[key] = val; + } + } + }; + var handleBufferClosing = function(message) { var bufferMessage = message.objects[0].content[0]; var bufferId = bufferMessage.pointers[0]; @@ -392,6 +413,7 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific return { handleVersionInfo: handleVersionInfo, + handleConfValue: handleConfValue, handleEvent: handleEvent, handleLineInfo: handleLineInfo, handleHotlistInfo: handleHotlistInfo, diff --git a/js/models.js b/js/models.js index 4bb239e..f6d7f63 100644 --- a/js/models.js +++ b/js/models.js @@ -11,6 +11,9 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter) // WeeChat version this.version = null; + // WeeChat configuration values + this.wconfig = {}; + // Save outgoing queries this.outgoingQueries = []; From 31ba8db33d2924ffb8c8916c05a40d463cc5d192 Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Fri, 18 Dec 2015 13:48:33 +0100 Subject: [PATCH 43/70] Fix problem with saving of sound notify --- js/glowingbear.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/glowingbear.js b/js/glowingbear.js index 33eeed9..8102930 100644 --- a/js/glowingbear.js +++ b/js/glowingbear.js @@ -23,6 +23,8 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', $scope.command = ''; $scope.themes = ['dark', 'light']; + // Initialise all our settings, this needs to include all settings + // or else they won't be saved to the localStorage. settings.setDefaults({ 'theme': 'dark', 'host': 'localhost', @@ -38,6 +40,7 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', 'useFavico': true, 'showtimestamp': true, 'showtimestampSeconds': false, + 'soundnotification': true, 'fontsize': '14px', 'fontfamily': (utils.isMobileUi() ? 'sans-serif' : 'Inconsolata, Consolas, Monaco, Ubuntu Mono, monospace'), 'readlineBindings': false, From 021d9e6e953d69fd201865092dd0751dd707e425 Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Sat, 19 Dec 2015 14:13:42 +0100 Subject: [PATCH 44/70] set a title on the send button --- directives/input.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/directives/input.html b/directives/input.html index 38a76f7..030708f 100644 --- a/directives/input.html +++ b/directives/input.html @@ -7,7 +7,7 @@ - +
    From df36d56fa71605bf540b359ccfd48faf6d5d6bcc Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Sat, 19 Dec 2015 15:44:34 +0100 Subject: [PATCH 45/70] Implement infinite scrolling I't not perfect but it's a start. --- index.html | 3 ++- js/glowingbear.js | 11 +++++++++++ js/whenscrolled-directive.js | 21 +++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 js/whenscrolled-directive.js diff --git a/index.html b/index.html index bbbef49..249a2b8 100644 --- a/index.html +++ b/index.html @@ -36,6 +36,7 @@ + @@ -264,7 +265,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel -
    +
    • diff --git a/js/glowingbear.js b/js/glowingbear.js index 8102930..e2f48fc 100644 --- a/js/glowingbear.js +++ b/js/glowingbear.js @@ -539,6 +539,17 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', return connection.fetchMoreLines(numLines); }; + $scope.infiniteScroll = function() { + // Check if we are already fetching + if ($rootScope.loadingLines) { + return; + } + var buffer = models.getActiveBuffer(); + if (!buffer.allLinesFetched) { + $scope.fetchMoreLines(); + } + }; + $rootScope.updateBufferBottom = function(bottom) { var eob = document.getElementById("end-of-buffer"); var bl = document.getElementById('bufferlines'); diff --git a/js/whenscrolled-directive.js b/js/whenscrolled-directive.js new file mode 100644 index 0000000..39a43e5 --- /dev/null +++ b/js/whenscrolled-directive.js @@ -0,0 +1,21 @@ +(function() { +'use strict'; + +var weechat = angular.module('weechat'); +weechat.directive('whenScrolled', function() { + return function(scope, elm, attr) { + var raw = elm[0]; + + var fun = function() { + if (raw.scrollTop === 0) { + scope.$apply(attr.whenScrolled); + } + }; + + elm.bind('scroll', function() { + _.debounce(fun, 200)(); + }); + }; +}); + +})(); From efa6e39b937f66545c90b4138f11069148a4094e Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Sun, 20 Dec 2015 14:51:40 +0100 Subject: [PATCH 46/70] Chrome WebApp now loads manifest --- index.html | 4 +++- webapp.manifest.json | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 webapp.manifest.json diff --git a/index.html b/index.html index bbbef49..74fbb4b 100644 --- a/index.html +++ b/index.html @@ -8,8 +8,10 @@ - + + + diff --git a/webapp.manifest.json b/webapp.manifest.json new file mode 100644 index 0000000..8367491 --- /dev/null +++ b/webapp.manifest.json @@ -0,0 +1,33 @@ +{ + "lang": "en-US", + "name": "Glowing Bear", + "short_name": "Glowing Bear", + "icons": [{ + "src": "assets/img/glowing_bear_60x60.png", + "sizes": "60x60", + "type": "image/webapp" + }, { + "src": "assets/img/glowing_bear_90x90.png", + "sizes": "90x90" + }, { + "src": "assets/img/glowing_bear_128x128.png", + "sizes": "128x128" + }], + "splash_screens": [{ + "src": "assets/img/glowing_bear_128x128.png", + "sizes": "128x128" + }], + "scope": "/glowing-bear/", + "start_url": "/glowing-bear/index.html", + "display": "standalone", + "orientation": "portrait-primary", + "theme_color": "#181818", + "background_color": "#333", + "prefer_related_applications": "false", + "chrome_related_applications": [{ + "platform": "web" + }, { + "platform": "android", + "location": "https://play.google.com/store/apps/details?id=com.glowing_bear" + }] +} From 9985e91a69fd77919b8cf8db0b2fd860f377bee7 Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Sun, 20 Dec 2015 15:07:28 +0100 Subject: [PATCH 47/70] use service workers for notifications If Service Workers are available use them to display notifications instead of the old way of creating notifications directly. This has the side effect that it works nicely on chrome on android which the old method does not. This also paves the way to set up GCM for push notification in the future which can give us push notifications without having the app running. This patch can be improved in the future to get existing notifications and change the message instead of just adding more and more notifications. See: ServiceWorkerRegistration.getNotifications() and ServiceWorkerRegistration.update() from https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration --- js/notifications.js | 84 +++++++++++++++++++++++++++++---------------- serviceworker.js | 22 ++++++++++++ 2 files changed, 77 insertions(+), 29 deletions(-) create mode 100644 serviceworker.js diff --git a/js/notifications.js b/js/notifications.js index 1e03db6..2ed9d1b 100644 --- a/js/notifications.js +++ b/js/notifications.js @@ -1,8 +1,9 @@ var weechat = angular.module('weechat'); weechat.factory('notifications', ['$rootScope', '$log', 'models', 'settings', function($rootScope, $log, models, settings) { - // Ask for permission to display desktop notifications + var serviceworker = false; var notifications = []; + // Ask for permission to display desktop notifications var requestNotificationPermission = function() { // Firefox if (window.Notification) { @@ -22,6 +23,58 @@ weechat.factory('notifications', ['$rootScope', '$log', 'models', 'settings', fu window.webkitNotifications.requestPermission(); } } + + if ('serviceWorker' in navigator) { + $log.info('Service Worker is supported'); + navigator.serviceWorker.register('serviceworker.js').then(function(reg) { + $log.info('Service Worker install:', reg); + serviceworker = true; + }).catch(function(err) { + $log.info('Service Worker err:', err); + }); + } + }; + + var showNotification = function(title, body) { + if (serviceworker) { + navigator.serviceWorker.ready.then(function(registration) { + registration.showNotification(title, { + body: body, + icon: 'assets/img/glowing_bear_128x128.png', + vibrate: [200, 100, 200, 100, 200, 100, 200], + tag: 'gb-highlight-vib' + }); + }); + } else { + var notification = new Notification(title, { + body: body, + icon: 'assets/img/favicon.png' + }); + + // Save notification, so we can close all outstanding ones when disconnecting + notification.id = notifications.length; + notifications.push(notification); + + // Cancel notification automatically + var timeout = 15*1000; + notification.onshow = function() { + setTimeout(function() { + notification.close(); + }, timeout); + }; + + // Click takes the user to the buffer + notification.onclick = function() { + models.setActiveBuffer(buffer.id); + window.focus(); + notification.close(); + }; + + // Remove from list of active notifications + notification.onclose = function() { + delete notifications[this.id]; + }; + } }; @@ -104,34 +157,7 @@ weechat.factory('notifications', ['$rootScope', '$log', 'models', 'settings', fu } title += buffer.shortName + " (" + buffer.server + ")"; - var notification = new Notification(title, { - body: body, - icon: 'assets/img/favicon.png' - }); - - // Save notification, so we can close all outstanding ones when disconnecting - notification.id = notifications.length; - notifications.push(notification); - - // Cancel notification automatically - var timeout = 15*1000; - notification.onshow = function() { - setTimeout(function() { - notification.close(); - }, timeout); - }; - - // Click takes the user to the buffer - notification.onclick = function() { - models.setActiveBuffer(buffer.id); - window.focus(); - notification.close(); - }; - - // Remove from list of active notifications - notification.onclose = function() { - delete notifications[this.id]; - }; + showNotification(title, body); if (settings.soundnotification) { // TODO fill in a sound file diff --git a/serviceworker.js b/serviceworker.js new file mode 100644 index 0000000..99f97c5 --- /dev/null +++ b/serviceworker.js @@ -0,0 +1,22 @@ +// File needs to be stored in the root of the app. + +this.addEventListener('install', function(event) { + event.waitUntil( + caches.open('v1').then(function(cache) { + return cache.addAll([ + 'assets/img/glowing_bear_128x128.png', + ]); + }) + ); +}); + +this.addEventListener('push', function(event) { + // TODO, support GCM here + var title = 'Push message'; + event.waitUntil( + self.registration.showNotification(title, { + body: 'The Message', + icon: 'assets/img/favicon.png', + tag: 'my-tag' + })); +}); From 1565c0e72d29826b169b5059984c421139bc2500 Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Tue, 22 Dec 2015 14:03:30 +0100 Subject: [PATCH 48/70] less vibrations --- js/notifications.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/notifications.js b/js/notifications.js index 2ed9d1b..fd56fa3 100644 --- a/js/notifications.js +++ b/js/notifications.js @@ -41,7 +41,7 @@ weechat.factory('notifications', ['$rootScope', '$log', 'models', 'settings', fu registration.showNotification(title, { body: body, icon: 'assets/img/glowing_bear_128x128.png', - vibrate: [200, 100, 200, 100, 200, 100, 200], + vibrate: [200, 100], tag: 'gb-highlight-vib' }); }); From 952da6d9dddb311e2ff8f0a1c53d7219a3b2cda9 Mon Sep 17 00:00:00 2001 From: Tor Hveem Date: Tue, 22 Dec 2015 14:40:01 +0100 Subject: [PATCH 49/70] implement on notification click --- serviceworker.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/serviceworker.js b/serviceworker.js index 99f97c5..7a549b6 100644 --- a/serviceworker.js +++ b/serviceworker.js @@ -20,3 +20,27 @@ this.addEventListener('push', function(event) { tag: 'my-tag' })); }); + +this.onnotificationclick = function(event) { + // Android doesn't close the notification when you click on it + // See: http://crbug.com/463146 + event.notification.close(); + + // This looks to see if the current is already open and + // focuses if it is + event.waitUntil(clients.matchAll({ + type: "window" + }).then(function(clientList) { + for (var i = 0; i < clientList.length; i++) { + var client = clientList[i]; + if ('focus' in client) { + return client.focus(); + } + } + /* + if (clients.openWindow) { + return clients.openWindow('/glowing-bear/'); + } + */ + })); +}; From d8a1beb4dbd32b69b2ae0edf2d5acc28f263bd79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Tue, 22 Dec 2015 15:49:09 +0100 Subject: [PATCH 50/70] Fix missing argument in notification showing --- js/notifications.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/notifications.js b/js/notifications.js index 2ed9d1b..ff0ed53 100644 --- a/js/notifications.js +++ b/js/notifications.js @@ -35,7 +35,7 @@ weechat.factory('notifications', ['$rootScope', '$log', 'models', 'settings', fu } }; - var showNotification = function(title, body) { + var showNotification = function(buffer, title, body) { if (serviceworker) { navigator.serviceWorker.ready.then(function(registration) { registration.showNotification(title, { @@ -157,7 +157,7 @@ weechat.factory('notifications', ['$rootScope', '$log', 'models', 'settings', fu } title += buffer.shortName + " (" + buffer.server + ")"; - showNotification(title, body); + showNotification(buffer, title, body); if (settings.soundnotification) { // TODO fill in a sound file From 01d0891a2d11cc9a50c363cb7300ef674ca2ced7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sat, 26 Dec 2015 11:47:09 +0100 Subject: [PATCH 51/70] Themes: Add black theme for AMOLED displays, fix theme selector background in dark theme Deprecates / closes #671 --- css/glowingbear.css | 12 ++++++------ css/themes/black.css | 22 ++++++++++++++++++++++ css/themes/dark.css | 5 +++++ js/glowingbear.js | 2 +- 4 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 css/themes/black.css diff --git a/css/glowingbear.css b/css/glowingbear.css index 44364a9..1f6c933 100644 --- a/css/glowingbear.css +++ b/css/glowingbear.css @@ -370,12 +370,12 @@ td.time { left: 0; } - .imgur-progress-bar { - width: 0%; - height: 5px; - margin-top: 1px; - background: #428BCA; - } +.imgur-progress-bar { + width: 0%; + height: 5px; + margin-top: 1px; + background: #428BCA; +} /* fix for mobile firefox which ignores :hover */ .nav-pills > li > a:active, .nav-pills > li > a:active span { diff --git a/css/themes/black.css b/css/themes/black.css new file mode 100644 index 0000000..08ca482 --- /dev/null +++ b/css/themes/black.css @@ -0,0 +1,22 @@ +@import "dark.css"; + +body, .modal-content { + background-color: #000; +} + +#topbar, #sidebar, .panel, .dropdown-menu, #topbar .actions { + background: #080808; +} + +.nav-pills li:nth-child(2n) { + background: #000; +} + +.form-control option, input.form-control, select.form-control { + color: #ccc; + background: #080808; +} + +.close, .close:hover, .close:focus { + color: #ddd; +} diff --git a/css/themes/dark.css b/css/themes/dark.css index f219459..8d303aa 100644 --- a/css/themes/dark.css +++ b/css/themes/dark.css @@ -10,6 +10,11 @@ body { border: 0px none; } +.form-control option { + color: #eee; + background: #282828; +} + html { background-color: inherit; } diff --git a/js/glowingbear.js b/js/glowingbear.js index e2f48fc..caea115 100644 --- a/js/glowingbear.js +++ b/js/glowingbear.js @@ -21,7 +21,7 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', }; $scope.command = ''; - $scope.themes = ['dark', 'light']; + $scope.themes = ['dark', 'light', 'black']; // Initialise all our settings, this needs to include all settings // or else they won't be saved to the localStorage. From 407f9111adb99ee9cde7778e970511ed5e4cb423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sun, 27 Dec 2015 19:19:23 +0100 Subject: [PATCH 52/70] Update Angular to 1.4.x series (1.4.8) Angular now has a .$$watchersCount property, which makes our watcher counting function unnecessary. Also add sha384 emojione SRI hash --- index.html | 10 +++++----- js/glowingbear.js | 16 +--------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/index.html b/index.html index 5e2122f..7daf2f2 100644 --- a/index.html +++ b/index.html @@ -19,12 +19,12 @@ - - - - + + + + - + diff --git a/js/glowingbear.js b/js/glowingbear.js index e2f48fc..51de8cc 100644 --- a/js/glowingbear.js +++ b/js/glowingbear.js @@ -49,22 +49,8 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', }); $scope.settings = settings; - // From: http://stackoverflow.com/a/18539624 by StackOverflow user "plantian" $rootScope.countWatchers = function () { - var q = [$rootScope], watchers = 0, scope; - while (q.length > 0) { - scope = q.pop(); - if (scope.$$watchers) { - watchers += scope.$$watchers.length; - } - if (scope.$$childHead) { - q.push(scope.$$childHead); - } - if (scope.$$nextSibling) { - q.push(scope.$$nextSibling); - } - } - $log.debug(watchers); + $log.debug($rootScope.$$watchersCount); }; $scope.isinstalled = (function() { From dfffbeec4689a62fb8f988ea1b5942c7bf3b3e8e Mon Sep 17 00:00:00 2001 From: kurros Date: Sat, 2 Jan 2016 12:14:48 -0500 Subject: [PATCH 53/70] optimize what gets passed to emojione.unicodeToImage --- js/filters.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/js/filters.js b/js/filters.js index 46fa02e..e51f0a2 100644 --- a/js/filters.js +++ b/js/filters.js @@ -161,7 +161,14 @@ weechat.filter('getBufferQuickKeys', function () { weechat.filter('emojify', function() { return function(text, enable_JS_Emoji) { if (enable_JS_Emoji === true && window.emojione !== undefined) { - return emojione.unicodeToImage(text); + // Emoji live in the D800-DFFF surrogate plane; only bother passing + // this range to CPU-expensive unicodeToImage(); + var emojiRegex = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; + if (emojiRegex.test(text)) { + return emojione.unicodeToImage(text); + } else { + return(text); + } } else { return(text); } From 41659493cd645d2eea9c516231c8890f4735c88a Mon Sep 17 00:00:00 2001 From: Furkan Alaca Date: Fri, 1 Jan 2016 21:02:53 -0500 Subject: [PATCH 54/70] parse dropbox URLs for image preview plugin (v5) --- js/plugins.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/js/plugins.js b/js/plugins.js index 98e4010..6f1fa42 100644 --- a/js/plugins.js +++ b/js/plugins.js @@ -280,10 +280,25 @@ plugins.factory('userPlugins', function() { } else if (url.match(/^http:\/\/(i\.)?imgur\.com\//i)) { // remove protocol specification to load over https if used by g-b url = url.replace(/http:/, ""); - } else if (url.match(/^https:\/\/www\.dropbox\.com\/s\/[a-z0-9]+\/[^?]+$/i)) { + } else if (url.match(/^https:\/\/www\.dropbox\.com\/s\/[a-z0-9]+\//i)) { // Dropbox requires a get parameter, dl=1 - // TODO strip an existing dl=0 parameter - url = url + "?dl=1"; + var dbox_url = document.createElement("a"); + dbox_url.href = url; + var base_url = dbox_url.protocol + '//' + dbox_url.host + dbox_url.pathname + '?'; + var dbox_params = dbox_url.search.substring(1).split('&'); + var dl_added = false; + for (var i = 0; i < dbox_params.length; i++) { + if (dbox_params[i].split('=')[0] === "dl") { + dbox_params[i] = "dl=1"; + dl_added = true; + // we continue looking at the other parameters in case + // it's specified twice or something + } + } + if (!dl_added) { + dbox_params.push("dl=1"); + } + url = base_url + dbox_params.join('&'); } return function() { var element = this.getElement(); From 9e8d94b0f27f2309a5c2705be205980d711e857b Mon Sep 17 00:00:00 2001 From: Cameron Kilgore Date: Sat, 2 Jan 2016 21:08:20 -0500 Subject: [PATCH 55/70] #725 Updated wording to include reference to openssl sha256 argument --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 7daf2f2..48c54ea 100644 --- a/index.html +++ b/index.html @@ -174,7 +174,7 @@
       $ mkdir -p ~/.weechat/ssl
       $ cd ~/.weechat/ssl
      -$ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out relay.pem -subj "/CN={{settings.host || 'your weechat host'}}/"
      +$ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out relay.pem -sha256 -subj "/CN={{settings.host || 'your weechat host'}}/"
       

      If WeeChat is already running, you can reload the certificate and private key and set up an encrypted relay on port {{ settings.port || 9001 }} with these WeeChat commands:

      
      From 48cc2356a67e87022b5be9bbc85338d2815e25f7 Mon Sep 17 00:00:00 2001
      From: Patrick Melanson 
      Date: Mon, 4 Jan 2016 19:58:25 -0500
      Subject: [PATCH 56/70] Fixed a circular ref in date change messages
      
      line.buffer was the actual buffer object, which contains the injected
      date
      change message itself. Made this just a buffer id.
      ---
       js/handlers.js | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/js/handlers.js b/js/handlers.js
      index 9342bfc..18e1a31 100644
      --- a/js/handlers.js
      +++ b/js/handlers.js
      @@ -98,7 +98,7 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific
                   content += ")";
       
                   var line = {
      -                buffer: buffer,
      +                buffer: buffer.id,
                       date: new_date,
                       prefix: '\u001943\u2500',
                       tags_array: [],
      
      From 07d706d825da891286279a513caf4af478d6c748 Mon Sep 17 00:00:00 2001
      From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?=
       
      Date: Wed, 6 Jan 2016 21:05:16 +0100
      Subject: [PATCH 57/70] Add a .editorconfig
      
      ---
       .editorconfig | 19 +++++++++++++++++++
       1 file changed, 19 insertions(+)
       create mode 100644 .editorconfig
      
      diff --git a/.editorconfig b/.editorconfig
      new file mode 100644
      index 0000000..1bb1df8
      --- /dev/null
      +++ b/.editorconfig
      @@ -0,0 +1,19 @@
      +# top-most EditorConfig file
      +root = true
      +
      +# Unix-style newlines with a newline ending every file
      +[*]
      +charset = utf-8
      +end_of_line = lf
      +insert_final_newline = true
      +trim_trailing_whitespace = true
      +
      +# Indent JS with four spaces
      +[*.js]
      +indent_style = space
      +indent_size = 4
      +
      +# Indent HTML with two spaces
      +[*.html]
      +indent_style = space
      +indent_size = 2
      
      From b719354a079b4e1e81d5afc71e2109ea3e88f46c Mon Sep 17 00:00:00 2001
      From: Patrick Melanson 
      Date: Tue, 5 Jan 2016 17:04:05 -0500
      Subject: [PATCH 58/70] #700 detect locale formatting support on load
      
      ---
       js/glowingbear.js | 17 +++++++++++++++++
       js/handlers.js    | 28 ++++++++++++++++++++++++----
       2 files changed, 41 insertions(+), 4 deletions(-)
      
      diff --git a/js/glowingbear.js b/js/glowingbear.js
      index 51de8cc..9de3698 100644
      --- a/js/glowingbear.js
      +++ b/js/glowingbear.js
      @@ -761,6 +761,23 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
               }
           };
       
      +    $rootScope.supports_formatting_date = (function() {
      +        // function toLocaleDateStringSupportsLocales taken from MDN:
      +        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString#Checking_for_support_for_locales_and_options_arguments
      +        try {
      +            new Date().toLocaleDateString('i');
      +        } catch (e) {
      +            if (e.name !== 'RangeError') {
      +                $log.info("Browser does not support toLocaleDateString()," +
      +                          " falling back to en-US");
      +            }
      +            return e.name === 'RangeError';
      +        }
      +        $log.info("Browser does not support toLocaleDateString()," +
      +                  " falling back to en-US");
      +        return false;
      +    })();
      +
           // Prevent user from accidentally leaving the page
           window.onbeforeunload = function(event) {
       
      diff --git a/js/handlers.js b/js/handlers.js
      index 18e1a31..0b3ea2f 100644
      --- a/js/handlers.js
      +++ b/js/handlers.js
      @@ -59,8 +59,16 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific
       
                   var content = "\u001943"; // this colour corresponds to chat_day_change
                   // Add day of the week
      -            content += new_date.toLocaleDateString(window.navigator.language,
      -                                                   {weekday: "long"});
      +            if ($rootScope.supports_formatting_date) {
      +                content += new_date.toLocaleDateString(window.navigator.language,
      +                                                       {weekday: "long"});
      +            } else {
      +                // Gross code that only does English dates ew gross
      +                var dow_to_word = [
      +                    "Sunday", "Monday", "Tuesday",
      +                    "Wednesday", "Thursday", "Friday", "Saturday"];
      +                content += dow_to_word[new_date.getDay()];
      +            }
                   // if you're testing different date formats,
                   // make sure to test different locales such as "en-US",
                   // "en-US-u-ca-persian" (which has different weekdays, year 0, and an ERA)
      @@ -73,8 +81,20 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific
                       extra_date_format.year = "numeric";
                   }
                   content += " (";
      -            content += new_date.toLocaleDateString(window.navigator.language,
      -                                                   extra_date_format);
      +            if ($rootScope.supports_formatting_date) {
      +                content += new_date.toLocaleDateString(window.navigator.language,
      +                                                       extra_date_format);
      +            } else {
      +                // ew ew not more gross code
      +                var month_to_word = [
      +                    "January", "February", "March", "April",
      +                    "May", "June", "July", "August",
      +                    "September", "October", "November", "December"];
      +                content += month_to_word[new_date.getMonth()] + " " + new_date.getDate().toString();
      +                if (extra_date_format.year === "numeric") {
      +                    content += ", " + new_date.getFullYear().toString();
      +                }
      +            }
                   // Result should be something like
                   // Friday (November 27)
                   // or if the year is different,
      
      From 19c408ba13cd3da965b8d013134dc65087c366ba Mon Sep 17 00:00:00 2001
      From: Patrick Melanson 
      Date: Thu, 7 Jan 2016 18:03:48 -0500
      Subject: [PATCH 59/70]  #705 bugfix datechange injected under read marker
      
      after #708 was merged, if a date change message is
      injected underneath the read marker the read
      marker would be one line too low. Now, the read
      marker will adjust properly when a date change
      message is injected above and below the read
      marker.
      
      thanks lorenzhs for spotting that
      ---
       js/handlers.js | 6 +++++-
       1 file changed, 5 insertions(+), 1 deletion(-)
      
      diff --git a/js/handlers.js b/js/handlers.js
      index 0b3ea2f..ceab76e 100644
      --- a/js/handlers.js
      +++ b/js/handlers.js
      @@ -50,7 +50,11 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific
               new_date.setHours(0, 0, 0, 0);
               // Check if the date changed
               if (old_date.valueOf() !== new_date.valueOf()) {
      -            ++buffer.lastSeen;
      +            if (buffer.lastSeen + 1 < buffer.lines.length) {
      +                // if the date change should be injected below the read marker,
      +                // adjust the read marker up to make sure it stays under the read marker
      +                ++buffer.lastSeen;
      +            }
                   var old_date_plus_one = old_date;
                   old_date_plus_one.setDate(old_date.getDate() + 1);
                   // it's not always true that a date with time 00:00:00
      
      From a06f567770ca2c97ef85ae42f9b16d785a56fd02 Mon Sep 17 00:00:00 2001
      From: Patrick Melanson 
      Date: Sat, 9 Jan 2016 00:39:33 -0500
      Subject: [PATCH 60/70] #705 date change msg now moves read marker only if
       accompanying msg would
      
      ---
       js/handlers.js | 13 +++++++------
       1 file changed, 7 insertions(+), 6 deletions(-)
      
      diff --git a/js/handlers.js b/js/handlers.js
      index ceab76e..c1b3228 100644
      --- a/js/handlers.js
      +++ b/js/handlers.js
      @@ -41,7 +41,7 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific
           };
       
           // inject a fake buffer line for date change if needed
      -    var injectDateChangeMessageIfNeeded = function(buffer, old_date, new_date) {
      +    var injectDateChangeMessageIfNeeded = function(buffer, manually, old_date, new_date) {
               if (buffer.bufferType === 1) {
                   // Don't add date change messages to free buffers
                   return;
      @@ -50,9 +50,10 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific
               new_date.setHours(0, 0, 0, 0);
               // Check if the date changed
               if (old_date.valueOf() !== new_date.valueOf()) {
      -            if (buffer.lastSeen + 1 < buffer.lines.length) {
      -                // if the date change should be injected below the read marker,
      -                // adjust the read marker up to make sure it stays under the read marker
      +            if (manually) {
      +                // if the message that caused this date change to be sent
      +                // would increment buffer.lastSeen, we should increment as
      +                // well.
                       ++buffer.lastSeen;
                   }
                   var old_date_plus_one = old_date;
      @@ -145,7 +146,7 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific
                   if (buffer.lines.length > 0) {
                       var old_date = new Date(buffer.lines[buffer.lines.length - 1].date),
                           new_date = new Date(message.date);
      -                injectDateChangeMessageIfNeeded(buffer, old_date, new_date);
      +                injectDateChangeMessageIfNeeded(buffer, manually, old_date, new_date);
                   }
       
                   message = plugins.PluginManager.contentForMessage(message);
      @@ -330,7 +331,7 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific
                   var buffer = models.getBuffer(last_line.buffer);
                   if (buffer.lines.length > 0) {
                       var last_date = new Date(buffer.lines[buffer.lines.length - 1].date);
      -                injectDateChangeMessageIfNeeded(buffer, last_date, new Date());
      +                injectDateChangeMessageIfNeeded(buffer, true, last_date, new Date());
                   }
               }
           };
      
      From e6d6272be510a1927562b91a13821f7ae5e008f2 Mon Sep 17 00:00:00 2001
      From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?=
       
      Date: Sun, 10 Jan 2016 11:19:35 +0100
      Subject: [PATCH 61/70] Make buffer prefix lighter on active buffer
      
      the old behaviour was quite counterintuitive in my opinion
      
      See #592
      ---
       css/glowingbear.css | 6 +-----
       1 file changed, 1 insertion(+), 5 deletions(-)
      
      diff --git a/css/glowingbear.css b/css/glowingbear.css
      index 1f6c933..ef540c5 100644
      --- a/css/glowingbear.css
      +++ b/css/glowingbear.css
      @@ -594,11 +594,7 @@ li.buffer.channel_ampersand a span:last-of-type:before, #topbar .title .channel_
       }
       
       li.buffer.channel.active a span:last-of-type:before {
      -    color: #444;
      -}
      -
      -li.buffer.channel.active a:hover span:last-of-type:before {
      -    color: #222;
      +    color: #aaa;
       }
       
       li.buffer.indent.private a {
      
      From d34cf89aaa7105ceee0ef0add7cd150eb43636a9 Mon Sep 17 00:00:00 2001
      From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?=
       
      Date: Sun, 10 Jan 2016 11:37:27 +0100
      Subject: [PATCH 62/70] Add support for custom CSS
      
      Fixes #647
      ---
       index.html        | 11 +++++++++++
       js/glowingbear.js | 19 +++++++++++++++++++
       2 files changed, 30 insertions(+)
      
      diff --git a/index.html b/index.html
      index 48c54ea..6ca73a5 100644
      --- a/index.html
      +++ b/index.html
      @@ -352,6 +352,17 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
                       
                     
    • +
    • +
      +
      + +
      + +
      +
      +
      +
    • +
    • diff --git a/js/glowingbear.js b/js/glowingbear.js index 2233448..271916a 100644 --- a/js/glowingbear.js +++ b/js/glowingbear.js @@ -46,6 +46,7 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', 'readlineBindings': false, 'enableJSEmoji': (utils.isMobileUi() ? false : true), 'enableMathjax': false, + 'customCSS': '', }); $scope.settings = settings; @@ -424,6 +425,24 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', })(); }); + settings.addCallback('customCSS', function(css) { + // We need to delete the old tag and add a new one so that the browser + // notices the change. Thus, first remove old custom CSS. + var old_css = document.getElementById('custom-css-tag'); + if (old_css) { + old_css.parentNode.removeChild(old_css); + } + + // Create new CSS tag + var new_css = document.createElement("style"); + new_css.type = "text/css"; + new_css.id = "custom-css-tag"; + new_css.appendChild(document.createTextNode(css)); + // Append it to the tag + var heads = document.getElementsByTagName("head"); + heads[0].appendChild(new_css); + }); + // Update font family when changed settings.addCallback('fontfamily', function(fontfamily) { From 06d7f6dfee14449889b43bfadbd5c4ce60393614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20H=C3=BCbschle-Schneider?= Date: Sat, 16 Jan 2016 15:01:46 +0100 Subject: [PATCH 63/70] Include version information in settings dialog, update version numbers --- css/glowingbear.css | 4 ++++ index.html | 1 + manifest.json | 2 +- manifest.webapp | 2 +- package.json | 2 +- 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/css/glowingbear.css b/css/glowingbear.css index ef540c5..33719e2 100644 --- a/css/glowingbear.css +++ b/css/glowingbear.css @@ -15,6 +15,10 @@ a { cursor: pointer; } +.version { + margin-right: 1em; +} + .hidden-bracket { position: absolute; left: -1000px; diff --git a/index.html b/index.html index 48c54ea..bf8ca89 100644 --- a/index.html +++ b/index.html @@ -321,6 +321,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel