Don't apply styles until import is finished

This commit is contained in:
tophf 2017-03-15 02:27:52 +03:00
parent e2e64113fe
commit 38006847f7
6 changed files with 112 additions and 126 deletions

View File

@ -62,10 +62,10 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
&& sender.tab.url == request.matchUrl) {
updateIcon(sender.tab, styles);
}
return true;
return KEEP_CHANNEL_OPEN;
case "saveStyle":
saveStyle(request, sendResponse);
return true;
saveStyle(request).then(sendResponse);
return KEEP_CHANNEL_OPEN;
case "invalidateCache":
if (typeof invalidateCache != "undefined") {
invalidateCache(false);
@ -73,7 +73,7 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
break;
case "healthCheck":
getDatabase(function() { sendResponse(true); }, function() { sendResponse(false); });
return true;
return KEEP_CHANNEL_OPEN;
case "openURL":
openURL(request);
break;
@ -88,6 +88,9 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
chrome.contextMenus.update("disableAll", {checked: request.value});
}
break;
case "refreshAllTabs":
refreshAllTabs().then(sendResponse);
return KEEP_CHANNEL_OPEN;
}
});

View File

@ -1,4 +1,4 @@
/* globals getStyles, saveStyle */
/* globals getStyles, saveStyle, invalidateCache, refreshAllTabs, handleUpdate */
'use strict';
var STYLISH_DUMP_FILE_EXT = '.txt';
@ -71,27 +71,26 @@ document.getElementById('file-all-styles').addEventListener('click', function ()
});
});
document.getElementById('unfile-all-styles').addEventListener('click', function () {
loadFromFile(STYLISH_DUMPFILE_EXTENSION).then(function (rawText) {
var json = JSON.parse(rawText);
var i = 0, nextStyle;
document.getElementById('unfile-all-styles').addEventListener('click', () => {
loadFromFile(STYLISH_DUMPFILE_EXTENSION).then(rawText => {
const json = JSON.parse(rawText);
const numStyles = json.length;
function done() {
window.alert(i + ' styles installed/updated');
location.reload();
}
invalidateCache(true);
proceed();
function proceed() {
nextStyle = json[i++];
const nextStyle = json.shift();
if (nextStyle) {
saveStyle(nextStyle, proceed);
}
else {
i--;
done();
saveStyle(nextStyle, {notify: false}).then(style => {
handleUpdate(style);
setTimeout(proceed, 0);
});
} else {
refreshAllTabs().then(() => {
setTimeout(alert, 100, numStyles + ' styles installed/updated');
});
}
}
proceed();
});
});

View File

@ -19,9 +19,7 @@ function showStyles(styles) {
return;
}
styles.sort(function(a, b) { return a.name.localeCompare(b.name)});
styles.map(createStyleElement).forEach(function(e) {
installed.appendChild(e);
});
styles.forEach(handleUpdate);
if (history.state) {
window.scrollTo(0, history.state.scrollY);
}
@ -163,10 +161,8 @@ function getStyleElement(event) {
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
switch (request.method) {
case "styleUpdated":
handleUpdate(request.style);
break;
case "styleAdded":
installed.appendChild(createStyleElement(request.style));
handleUpdate(request.style);
break;
case "styleDeleted":
handleDelete(request.id);
@ -176,12 +172,17 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
function handleUpdate(style) {
var element = createStyleElement(style);
installed.replaceChild(element, installed.querySelector("[style-id='" + style.id + "']"));
var oldElement = installed.querySelector(`[style-id="${style.id}"]`);
if (!oldElement) {
installed.appendChild(element);
return;
}
installed.replaceChild(element, oldElement);
if (style.id == lastUpdatedStyleId) {
lastUpdatedStyleId = null;
element.className = element.className += " update-done";
element.querySelector(".update-note").innerHTML = t('updateCompleted');
};
element.className = element.className += ' update-done';
element.querySelector('.update-note').innerHTML = t('updateCompleted');
}
}
function handleDelete(id) {
@ -465,41 +466,6 @@ function initFilter(className, node) {
onFilterChange(className, {target: node});
}
function importStyles (e) {
var file = e.target.files[0];
var reader = new FileReader();
var styles = [];
function save () {
var style = styles.shift();
if (style) {
delete style.id;
saveStyle(style, save);
}
else {
window.location.reload()
}
}
reader.onloadend = function (evt) {
try {
styles = JSON.parse(evt.target.result);
save();
}
catch (e) {
window.alert(e.message);
}
};
reader.onerror = function (e) {
window.alert(e.message);
}
reader.readAsText(file)
}
function selectAll () {
document.execCommand('selectAll');
}
document.addEventListener("DOMContentLoaded", function() {
installed = document.getElementById("installed");
if (document.stylishStyles) {
@ -520,5 +486,4 @@ document.addEventListener("DOMContentLoaded", function() {
]);
initFilter("enabled-only", document.getElementById("manage.onlyEnabled"));
initFilter("edited-only", document.getElementById("manage.onlyEdited"));
});

View File

@ -1,3 +1,6 @@
// keep message channel open for sendResponse in chrome.runtime.onMessage listener
const KEEP_CHANNEL_OPEN = true;
function notifyAllTabs(request) {
chrome.windows.getAll({populate: true}, function(windows) {
windows.forEach(function(win) {
@ -16,6 +19,29 @@ function notifyAllTabs(request) {
}
}
function refreshAllTabs() {
return new Promise(resolve => {
chrome.windows.getAll({populate: true}, windows => {
windows.forEach((win, winIndex) => {
win.tabs.forEach((tab, tabIndex) => {
getStyles({matchUrl: tab.url, enabled: true, asHash: true}, styles => {
const message = {method: 'styleReplaceAll', styles};
if (tab.url == location.href && typeof applyOnMessage !== 'undefined') {
applyOnMessage(message);
} else {
chrome.tabs.sendMessage(tab.id, message);
}
updateIcon(tab, styles);
if (winIndex == windows.length - 1 && tabIndex == win.tabs.length - 1) {
resolve();
}
});
});
});
});
});
}
function updateIcon(tab, styles) {
// while NTP is still loading only process the request for its main frame with a real url
// (but when it's loaded we should process style toggle requests from popups, for example)

View File

@ -95,72 +95,65 @@ function filterStyles(styles, options) {
return styles;
}
function saveStyle(o, callback) {
getDatabase(function(db) {
var tx = db.transaction(["styles"], "readwrite");
var os = tx.objectStore("styles");
function saveStyle(style, {notify = true} = {}) {
return new Promise(resolve => {
getDatabase(db => {
const tx = db.transaction(['styles'], 'readwrite');
const os = tx.objectStore('styles');
// Update
if (o.id) {
var request = os.get(Number(o.id));
request.onsuccess = function(event) {
var style = request.result || {};
for (var prop in o) {
if (prop == "id") {
continue;
}
style[prop] = o[prop];
}
request = os.put(style);
request.onsuccess = function(event) {
notifyAllTabs({method: "styleUpdated", style: style});
invalidateCache(true);
if (callback) {
callback(style);
}
// Update
if (style.id) {
style.id = Number(style.id);
os.get(style.id).onsuccess = eventGet => {
style = Object.assign({}, eventGet.target.result, style);
os.put(style).onsuccess = eventPut => {
style.id = style.id || eventPut.target.result;
if (notify) {
notifyAllTabs({method: 'styleUpdated', style});
}
invalidateCache(notify);
resolve(style);
};
};
};
return;
}
// Create
// Set optional things to null if they're undefined
["updateUrl", "md5Url", "url", "originalMd5"].filter(function(att) {
return !(att in o);
}).forEach(function(att) {
o[att] = null;
});
// Set other optional things to empty array if they're undefined
o.sections.forEach(function(section) {
["urls", "urlPrefixes", "domains", "regexps"].forEach(function(property) {
if (!section[property]) {
section[property] = [];
}
});
});
// Set to enabled if not set
if (!("enabled" in o)) {
o.enabled = true;
}
// Make sure it's not null - that makes indexeddb sad
delete o["id"];
var request = os.add(o);
request.onsuccess = function(event) {
invalidateCache(true);
// Give it the ID that was generated
o.id = event.target.result;
notifyAllTabs({method: "styleAdded", style: o});
if (callback) {
callback(o);
return;
}
};
// Create
style = Object.assign({
// Set optional things if they're undefined
enabled: true,
updateUrl: null,
md5Url: null,
url: null,
originalMd5: null,
}, style, {
// Set other optional things to empty array if they're undefined
sections: style.sections.map(section =>
Object.assign({
urls: [],
urlPrefixes: [],
domains: [],
regexps: [],
}, section)
),
})
// Make sure it's not null - that makes indexeddb sad
delete style.id;
os.add(style).onsuccess = event => {
invalidateCache(true);
// Give it the ID that was generated
style.id = event.target.result;
notifyAllTabs({method: 'styleAdded', style});
resolve(style);
};
});
});
}
function enableStyle(id, enabled) {
saveStyle({id: id, enabled: enabled}, function(style) {
saveStyle({id: id, enabled: enabled}).then(style => {
handleUpdate(style);
notifyAllTabs({method: "styleUpdated", style: style});
notifyAllTabs({method: "styleUpdated", style});
});
}

View File

@ -71,7 +71,7 @@ var update = {
json.method = 'saveStyle';
json.id = style.id;
saveStyle(json, function () {
saveStyle(json).then(style => {
observe('single-updated', style.name);
});
}