diff --git a/src/css/cloud-ui.css b/src/css/cloud-ui.css new file mode 100644 index 000000000..b6f941fca --- /dev/null +++ b/src/css/cloud-ui.css @@ -0,0 +1,87 @@ +#cloudWidget { + background: url("../img/cloud.png") hsl(216, 100%, 93%); + border-radius: 3px; + margin: 0.5em 0; + padding: 1em; + position: relative; + } +#cloudWidget.hide { + display: none; + } +#cloudWidget > button { + font-size: 160%; + padding: 0.1em 0.2em; + } +#cloudPull[disabled] { + visibility: hidden; + } +body[dir="ltr"] #cloudPush:after , +body[dir="ltr"] #cloudPull:before { + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + vertical-align: baseline; + display: inline-block; + } +body[dir="ltr"] #cloudPush:after { + content: '\f0ee'; + } +body[dir="rtl"] #cloudPush:after { + content: '\f0ee'; + } +body[dir="ltr"] #cloudPull:before { + content: '\f0ed'; + } +body[dir="rtl"] #cloudPull:before { + content: '\f0ed'; + } +#cloudWidget > span { + color: gray; + display: inline-block; + font-size: 90%; + margin: 0 1em; + padding: 0; + vertical-align: bottom; + white-space: pre; + } +#cloudWidget > .nodata { + } +#cloudWidget > #cloudCog { + cursor: pointer; + display: inline-block; + font-size: 110%; + margin: 0; + opacity: 0.5; + padding: 4px; + position: absolute; + right: 0; + top: 0; + } +#cloudWidget > #cloudCog:hover { + opacity: 1; + } +#cloudWidget > #cloudOptions { + align-items: center; + -webkit-align-items: center; + background-color: rgba(0, 0, 0, 0.75); + bottom: 0; + display: none; + justify-content: center; + -webkit-justify-content: center; + left: 0; + position: fixed; + right: 0; + top: 0; + z-index: 2000; + } +#cloudWidget > #cloudOptions.show { + display: flex; + display: -webkit-flex; + } +#cloudWidget > #cloudOptions > div { + background-color: white; + border-radius: 3px; + padding: 1em; + text-align: center; + } diff --git a/src/img/cloud.png b/src/img/cloud.png new file mode 100644 index 000000000..6c78dde2e Binary files /dev/null and b/src/img/cloud.png differ diff --git a/src/js/cloud-ui.js b/src/js/cloud-ui.js new file mode 100644 index 000000000..9bca1fbcf --- /dev/null +++ b/src/js/cloud-ui.js @@ -0,0 +1,199 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + Copyright (C) 2015 Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +/* global uDom */ +'use strict'; + +/******************************************************************************/ + +(function() { + +/******************************************************************************/ + +self.cloud = { + options: {}, + datakey: '', + data: undefined, + onPush: null, + onPull: null +}; + +/******************************************************************************/ + +var widget = uDom.nodeFromId('cloudWidget'); +if ( widget === null ) { + return; +} + +self.cloud.datakey = widget.getAttribute('data-cloud-entry') || ''; +if ( self.cloud.datakey === '' ) { + return; +} + +/******************************************************************************/ + +var messager = vAPI.messaging.channel('cloud-ui.js'); + +/******************************************************************************/ + +var onCloudDataReceived = function(entry) { + if ( typeof entry !== 'object' || entry === null ) { + return; + } + + self.cloud.data = entry.data; + + uDom.nodeFromId('cloudPull').removeAttribute('disabled'); + + var timeOptions = { + weekday: 'short', + year: 'numeric', + month: 'short', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + timeZoneName: 'short' + }; + + var time = new Date(entry.tstamp); + widget.querySelector('span').textContent = + entry.source + '\n' + + time.toLocaleString('fullwide', timeOptions); +}; + +/******************************************************************************/ + +var fetchCloudData = function() { + messager.send( + { + what: 'cloudPull', + datakey: self.cloud.datakey + }, + onCloudDataReceived + ); +}; + +/******************************************************************************/ + +var pushData = function() { + if ( typeof self.cloud.onPush !== 'function' ) { + return; + } + messager.send( + { + what: 'cloudPush', + datakey: self.cloud.datakey, + data: self.cloud.onPush() + }, + fetchCloudData + ); +}; + +/******************************************************************************/ + +var pullData = function() { + if ( typeof self.cloud.onPull === 'function' ) { + self.cloud.onPull(self.cloud.data); + } +}; + +/******************************************************************************/ + +var openOptions = function() { + var input = uDom.nodeFromId('cloudDeviceName'); + input.value = self.cloud.options.deviceName; + input.setAttribute('placeholder', self.cloud.options.defaultDeviceName); + uDom.nodeFromId('cloudOptions').classList.add('show'); +}; + +/******************************************************************************/ + +var closeOptions = function(ev) { + var root = uDom.nodeFromId('cloudOptions'); + if ( ev.target !== root ) { + return; + } + root.classList.remove('show'); +}; + +/******************************************************************************/ + +var submitOptions = function() { + var onOptions = function(options) { + if ( typeof options !== 'object' || options === null ) { + return; + } + self.cloud.options = options; + }; + + messager.send({ + what: 'cloudSetOptions', + options: { + deviceName: uDom.nodeFromId('cloudDeviceName').value + } + }, onOptions); + uDom.nodeFromId('cloudOptions').classList.remove('show'); +}; + +/******************************************************************************/ + +var onInitialize = function(options) { + if ( typeof options !== 'object' || options === null ) { + return; + } + + if ( !options.enabled ) { + return; + } + self.cloud.options = options; + + fetchCloudData(); + + var html = [ + '', + '', + '', + '', + '
', + '
', + '

', + '

', + '

', + '
', + ].join(''); + + vAPI.insertHTML(widget, html); + vAPI.i18n.render(widget); + widget.classList.remove('hide'); + + uDom('#cloudPush').on('click', pushData); + uDom('#cloudPull').on('click', pullData); + uDom('#cloudCog').on('click', openOptions); + uDom('#cloudOptions').on('click', closeOptions); + uDom('#cloudOptionsSubmit').on('click', submitOptions); +}; + +messager.send({ what: 'cloudGetOptions' }, onInitialize); + +/******************************************************************************/ + +})();