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", |
||||
"description": "A webclient for WeeChat", |
||||
"version": "0.5.2", |
||||
"version": "0.6.0", |
||||
"homepage": "https://github.com/glowing-bear/glowing-bear", |
||||
"license": "GPLv3", |
||||
"private": true, |
||||
"dependencies": { |
||||
"angular": "1.3.x", |
||||
"angular-route": "1.3.x", |
||||
"angular-sanitize": "1.3.x", |
||||
"angular-touch": "1.3.x", |
||||
"angular-loader": "1.3.x", |
||||
"angular-mocks": "1.3.x", |
||||
"angular": "1.4.x", |
||||
"angular-route": "1.4.x", |
||||
"angular-sanitize": "1.4.x", |
||||
"angular-touch": "1.4.x", |
||||
"angular-loader": "1.4.x", |
||||
"angular-mocks": "1.4.x", |
||||
"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"> |
||||
<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> |
||||
<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> |
||||
</div> |
||||
<div id="imgur-upload-progress"></div> |
||||
</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", |
||||
"private": true, |
||||
"version": "0.5.2", |
||||
"version": "0.6.0", |
||||
"description": "A web client for Weechat", |
||||
"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", |
||||
|
||||
"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", |
||||
"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');\"" |
||||
} |
||||
} |
||||
|
@ -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