commit
8a898d8278
@ -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 |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 8.7 KiB |
@ -1,17 +1,17 @@ |
|||||||
{ |
{ |
||||||
"name": "glowing-bear", |
"name": "glowing-bear", |
||||||
"description": "A webclient for WeeChat", |
"description": "A webclient for WeeChat", |
||||||
"version": "0.5.2", |
"version": "0.6.0", |
||||||
"homepage": "https://github.com/glowing-bear/glowing-bear", |
"homepage": "https://github.com/glowing-bear/glowing-bear", |
||||||
"license": "GPLv3", |
"license": "GPLv3", |
||||||
"private": true, |
"private": true, |
||||||
"dependencies": { |
"dependencies": { |
||||||
"angular": "1.3.x", |
"angular": "1.4.x", |
||||||
"angular-route": "1.3.x", |
"angular-route": "1.4.x", |
||||||
"angular-sanitize": "1.3.x", |
"angular-sanitize": "1.4.x", |
||||||
"angular-touch": "1.3.x", |
"angular-touch": "1.4.x", |
||||||
"angular-loader": "1.3.x", |
"angular-loader": "1.4.x", |
||||||
"angular-mocks": "1.3.x", |
"angular-mocks": "1.4.x", |
||||||
"html5-boilerplate": "~4.3.0" |
"html5-boilerplate": "~4.3.0" |
||||||
} |
} |
||||||
} |
} |
||||||
|
@ -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; |
||||||
|
} |
@ -1,9 +1,14 @@ |
|||||||
<form class="form form-horizontal" id="inputform" ng-submit="sendMessage()"> |
<form class="form form-horizontal" id="inputform" ng-submit="sendMessage()" imgur-drop> |
||||||
<div class="input-group"> |
<div class="input-group"> |
||||||
<textarea id="{{inputId}}" class="form-control favorite-font" ng-trim="false" rows="1" ng-change="inputChanged()" autocomplete="on" ng-model="command" ng-focus="hideSidebar()"> |
<textarea id="{{inputId}}" class="form-control favorite-font" ng-trim="false" rows="1" ng-change="inputChanged()" autocomplete="on" ng-model="command" ng-focus="hideSidebar()"> |
||||||
</textarea> |
</textarea> |
||||||
<span class="input-group-btn"> |
<span class="input-group-btn"> |
||||||
<button class="btn btn-send unselectable"><i class="glyphicon glyphicon-send"></i></button> |
<label class="btn btn-send-image unselectable" for="imgur-upload" title="Send image"> |
||||||
|
<i class="glyphicon glyphicon-picture"></i> |
||||||
|
<input type="file" accept="image/*" multiple title="Send image" id="imgur-upload" class="imgur-upload" file-change="uploadImage($event, files)"> |
||||||
|
</label> |
||||||
|
<button class="btn btn-send unselectable" title="Send"><i class="glyphicon glyphicon-send"></i></button> |
||||||
</span> |
</span> |
||||||
</div> |
</div> |
||||||
|
<div id="imgur-upload-progress"></div> |
||||||
</form> |
</form> |
||||||
|
@ -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); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
}]); |
||||||
|
|
||||||
|
})(); |
@ -0,0 +1,49 @@ |
|||||||
|
(function() { |
||||||
|
'use strict'; |
||||||
|
|
||||||
|
var weechat = angular.module('weechat'); |
||||||
|
|
||||||
|
weechat.directive('imgurDrop', ['connection','imgur','$rootScope', function(connection, imgur, $rootScope) { |
||||||
|
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(); |
||||||
|
|
||||||
|
// Send image url after upload
|
||||||
|
var sendImageUrl = function(imageUrl) { |
||||||
|
|
||||||
|
// Send image
|
||||||
|
if(imageUrl !== undefined && imageUrl !== '') { |
||||||
|
$rootScope.insertAtCaret(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); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
}; |
||||||
|
}]); |
||||||
|
|
||||||
|
})(); |
@ -0,0 +1,128 @@ |
|||||||
|
(function() { |
||||||
|
'use strict'; |
||||||
|
|
||||||
|
var weechat = angular.module('weechat'); |
||||||
|
|
||||||
|
weechat.factory('imgur', ['$rootScope', function($rootScope) { |
||||||
|
|
||||||
|
var process = function(image, callback) { |
||||||
|
|
||||||
|
// 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, callback); |
||||||
|
}; |
||||||
|
|
||||||
|
// 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 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(); |
||||||
|
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.onload = function() { |
||||||
|
|
||||||
|
// Remove progress bar
|
||||||
|
currentProgressBar.parentNode.removeChild(currentProgressBar); |
||||||
|
|
||||||
|
// Check state and response status
|
||||||
|
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
|
||||||
|
currentProgressBar.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 |
||||||
|
}; |
||||||
|
|
||||||
|
}]); |
||||||
|
|
||||||
|
})(); |
@ -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)(); |
||||||
|
}); |
||||||
|
}; |
||||||
|
}); |
||||||
|
|
||||||
|
})(); |
@ -1,38 +1,36 @@ |
|||||||
{ |
{ |
||||||
"name": "glowing-bear", |
"name": "glowing-bear", |
||||||
"private": true, |
"private": true, |
||||||
"version": "0.5.2", |
"version": "0.6.0", |
||||||
"description": "A web client for Weechat", |
"description": "A web client for Weechat", |
||||||
"repository": "https://github.com/glowing-bear/glowing-bear", |
"repository": "https://github.com/glowing-bear/glowing-bear", |
||||||
"license": "GPLv3", |
"license": "GPLv3", |
||||||
"devDependencies": { |
"devDependencies": { |
||||||
"karma": "~0.10", |
|
||||||
"protractor": "~0.20.1", |
|
||||||
"http-server": "^0.6.1", |
|
||||||
"bower": "^1.3.1", |
"bower": "^1.3.1", |
||||||
"shelljs": "^0.2.6", |
"http-server": "^0.6.1", |
||||||
|
"jasmine-core": "^2.4.1", |
||||||
"jshint": "^2.5.2", |
"jshint": "^2.5.2", |
||||||
|
"karma": "~0.13", |
||||||
|
"karma-jasmine": "^0.3.6", |
||||||
"karma-junit-reporter": "^0.2.2", |
"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" |
"uglify-js": "^2.4" |
||||||
}, |
}, |
||||||
"scripts": { |
"scripts": { |
||||||
"postinstall": "bower install", |
"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/file-change.js js/imgur-drop-directive.js js/whenscrolled-directive.js js/inputbar.js js/plugin-directive.js js/websockets.js js/models.js js/plugins.js js/imgur.js -c -m --screw-ie8 -o min.js --source-map min.map", |
||||||
"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", |
"prestart": "npm install", |
||||||
"start": "http-server -a localhost -p 8000", |
"start": "http-server -a localhost -p 8000", |
||||||
|
|
||||||
"pretest": "npm install", |
"pretest": "npm install", |
||||||
"test": "karma start test/karma.conf.js", |
"test": "karma start test/karma.conf.js", |
||||||
"test-single-run": "karma start test/karma.conf.js --single-run", |
"test-single-run": "karma start test/karma.conf.js --single-run", |
||||||
|
|
||||||
"preupdate-webdriver": "npm install", |
"preupdate-webdriver": "npm install", |
||||||
"update-webdriver": "webdriver-manager update", |
"update-webdriver": "webdriver-manager update", |
||||||
|
|
||||||
"preprotractor": "npm run update-webdriver", |
"preprotractor": "npm run update-webdriver", |
||||||
"protractor": "protractor test/protractor-conf.js", |
"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');\"" |
"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');\"" |
||||||
} |
} |
||||||
} |
} |
||||||
|
@ -0,0 +1,46 @@ |
|||||||
|
// 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' |
||||||
|
})); |
||||||
|
}); |
||||||
|
|
||||||
|
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/'); |
||||||
|
} |
||||||
|
*/ |
||||||
|
})); |
||||||
|
}; |
@ -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" |
||||||
|
}] |
||||||
|
} |
Loading…
Reference in new issue