Add widget to convey the amount of sync storage in use

This commit is contained in:
Raymond Hill 2020-08-14 15:29:25 -04:00
parent ba833d3391
commit 2afcc13ca6
No known key found for this signature in database
GPG key ID: 25E1490B761470C2
6 changed files with 97 additions and 29 deletions

View file

@ -1649,6 +1649,28 @@ vAPI.cloud = (( ) => {
return entry;
};
const used = async function(dataKey) {
if ( webext.storage.sync.getBytesInUse instanceof Function === false ) {
return;
}
const coarseCount = await getCoarseChunkCount(dataKey);
if ( typeof coarseCount !== 'number' ) { return; }
const keys = [];
for ( let i = 0; i < coarseCount; i++ ) {
keys.push(`${dataKey}${i}`);
}
let results;
try {
results = await Promise.all([
webext.storage.sync.getBytesInUse(keys),
webext.storage.sync.getBytesInUse(null),
]);
} catch(ex) {
}
if ( Array.isArray(results) === false ) { return; }
return { used: results[0], total: results[1], max: QUOTA_BYTES };
};
const getOptions = function(callback) {
if ( typeof callback !== 'function' ) { return; }
callback(options);
@ -1665,7 +1687,7 @@ vAPI.cloud = (( ) => {
getOptions(callback);
};
return { push, pull, getOptions, setOptions };
return { push, pull, used, getOptions, setOptions };
})();
/******************************************************************************/

View file

@ -6,15 +6,18 @@
</head>
<body>
<div id="cloudToolbar">
<button id="cloudPush" type="button" data-i18n-title="cloudPush"><span class="fa-icon">cloud-upload</span></button>
<span id="cloudInfo" data-i18n="cloudNoData"></span>
<button id="cloudPull" type="button" data-i18n-title="cloudPull" disabled><span class="fa-icon">cloud-download</span></button>
<button id="cloudPullAndMerge" type="button" data-i18n-title="cloudPullAndMerge" disabled><span class="fa-icon">cloud-download</span><span class="fa-icon">plus</span></button>
<span id="cloudCog" class="fa-icon">cog</span>
<div>
<button id="cloudPush" type="button" data-i18n-title="cloudPush"><span class="fa-icon">cloud-upload</span></button>
<span id="cloudInfo" data-i18n="cloudNoData"></span>
<button id="cloudPull" type="button" data-i18n-title="cloudPull" disabled><span class="fa-icon">cloud-download</span></button>
<button id="cloudPullAndMerge" type="button" data-i18n-title="cloudPullAndMerge" disabled><span class="fa-icon">cloud-download</span><span class="fa-icon">plus</span></button>
</div>
<div id="cloudCog" class="fa-icon">cog</div>
<div id="cloudOptions">
<label data-i18n="cloudDeviceNamePrompt"></label> <input id="cloudDeviceName" type="text" value=""> <button id="cloudOptionsSubmit" class="vflex" type="button" data-i18n="genericSubmit"></button>
<label data-i18n="cloudDeviceNamePrompt"></label> <input id="cloudDeviceName" type="text" value=""> <button id="cloudOptionsSubmit" type="button" data-i18n="genericSubmit"></button>
</div>
</div>
<div id="cloudError"></div>
<div id="cloudCapacity"><div><div></div></div></div>
</body>
</html>

View file

@ -1,22 +1,29 @@
#cloudWidget {
background: url("../img/cloud.png") hsl(216, 100%, 93%);
border-radius: 3px;
margin: 0.5em 0;
overflow: auto;
padding: 0.5em;
position: relative;
}
#cloudWidget.hide {
display: none;
}
#cloudToolbar > button {
font-size: 180%;
#cloudWidget div {
display: flex;
}
#cloudToolbar {
align-items: flex-start;
flex-wrap: nowrap;
justify-content: space-between;
}
#cloudToolbar > div:first-of-type {
margin: 0.5em;
}
#cloudToolbar button {
padding: 0 0.25em;
position: relative;
}
#cloudToolbar {
display: flex;
flex-wrap: nowrap;
#cloudToolbar button .fa-icon {
font-size: 180%;
}
#cloudToolbar button[disabled] {
visibility: hidden;
@ -28,13 +35,12 @@
margin-left: 0.25em;
}
#cloudPullAndMerge > span:nth-of-type(2) {
font-size: 50%;
font-size: 90%;
position: absolute;
right: 0;
top: 0;
}
#cloudInfo {
color: var(--fg-0-60);
flex-shrink: 0;
font-size: 90%;
margin: 0 1em;
@ -42,42 +48,52 @@
padding: 0;
white-space: pre-line;
}
#cloudCapacity {
background-color: var(--light-gray-30);
height: 4px;
}
#cloudCapacity > div {
background-color: var(--light-gray-60);
}
#cloudCapacity > div > div {
background-color: var(--violet-60);
}
#cloudError {
color: var(--fg-icon-info-lvl-4);
flex-grow: 1;
flex-shrink: 2;
font-size: small;
margin: 0.5em 0.5em 0 0;
margin: 0 0.5em 0.5em 0.5em;
}
#cloudError:empty {
display: none;
}
#cloudToolbar #cloudCog {
#cloudCog {
color: var(--fg-0-50);
cursor: pointer;
fill: var(--fg-0-50);
flex-grow: 1;
font-size: 110%;
justify-content: flex-end;
padding: 0.4em;
}
#cloudToolbar #cloudCog:hover {
#cloudCog:hover {
color: inherit;
fill: inherit;
}
#cloudToolbar #cloudOptions {
#cloudWidget #cloudOptions {
background-color: var(--default-surface);
border: 1px solid var(--bg-1-border);
bottom: 0;
display: none;
margin: 0.4em;
padding: 0.4em;
padding: 0.5em;
position: absolute;
right: 0;
text-align: center;
top: 0;
z-index: 10;
}
#cloudToolbar #cloudOptions.show {
#cloudWidget #cloudOptions.show {
display: block;
white-space: nowrap;
}
#cloudOptions button {
min-height: var(--default-gap-xlarge);
}

View file

@ -38,6 +38,7 @@
--light-gray-90: #80808f;
--red-60: #e22850;
--violet-40: #ab71ff;
--violet-60: #7542e5;
--violet-70: #592acb;
--violet-80: #45278d;
--yellow-30: #ffd567;

View file

@ -34,7 +34,7 @@ self.cloud = {
datakey: '',
data: undefined,
onPush: null,
onPull: null
onPull: null,
};
/******************************************************************************/
@ -47,6 +47,25 @@ if ( self.cloud.datakey === '' ) { return; }
/******************************************************************************/
const fetchStorageUsed = async function() {
const elem = widget.querySelector('#cloudCapacity');
if ( elem.classList.contains('hide') ) { return; }
const result = await vAPI.messaging.send('cloudWidget', {
what: 'cloudUsed',
datakey: self.cloud.datakey,
});
if ( result instanceof Object === false ) {
elem.classList.add('hide');
return;
}
const total = (result.total / result.max * 100).toFixed(1);
elem.firstElementChild.style.width = `${total}%`;
const used = (result.used / result.total * 100).toFixed(1);
elem.firstElementChild.firstElementChild.style.width = `${used}%`;
};
/******************************************************************************/
const fetchCloudData = async function() {
const entry = await vAPI.messaging.send('cloudWidget', {
what: 'cloudPull',
@ -94,6 +113,7 @@ const pushData = async function() {
.textContent = failed ? error : '';
if ( failed ) { return; }
fetchCloudData();
fetchStorageUsed();
};
/******************************************************************************/
@ -151,7 +171,7 @@ const submitOptions = async function() {
const onInitialize = function(options) {
if ( options instanceof Object === false ) { return; }
if ( !options.enabled ) { return; }
if ( options.enabled !== true ) { return; }
self.cloud.options = options;
const xhr = new XMLHttpRequest();
@ -180,12 +200,13 @@ const onInitialize = function(options) {
uDom('#cloudCog').on('click', openOptions);
uDom('#cloudOptions').on('click', closeOptions);
uDom('#cloudOptionsSubmit').on('click', ( ) => { submitOptions(); });
fetchCloudData().then(result => {
if ( typeof result !== 'string' ) { return; }
document.getElementById('cloudPush').classList.add('error');
document.querySelector('#cloudError').textContent = result;
});
fetchStorageUsed();
};
xhr.send();
};

View file

@ -828,6 +828,11 @@ const onMessage = function(request, sender, callback) {
callback(result);
});
case 'cloudUsed':
return vAPI.cloud.used(request.datakey).then(result => {
callback(result);
});
default:
break;
}