fixups for refreshAllTabs

This commit is contained in:
tophf 2018-01-03 18:26:31 +03:00
parent d346cb0a5a
commit 1eea8fdbbf
4 changed files with 64 additions and 94 deletions

View File

@ -22,6 +22,7 @@ var API_METHODS = {
detectSloppyRegexps,
openEditor,
updateIcon,
refreshAllTabs,
closeTab: (msg, sender, respond) => {
chrome.tabs.remove(msg.tabId || sender.tab.id, () => {
@ -306,6 +307,40 @@ function webNavUsercssInstallerFF(data) {
}
function refreshAllTabs(msg, sender = {}) {
return Promise.all([
sender.tab || getActiveTab(),
queryTabs(),
]).then(([ownTab, tabs]) => new Promise(resolve => {
if (FIREFOX) tabs = tabs.filter(tab => tab.width);
const last = tabs.length - 1;
for (let i = 0; i < last; i++) {
refreshTab(tabs[i], ownTab);
}
if (tabs.length) {
refreshTab(tabs[last], ownTab, resolve);
} else {
resolve();
}
}));
function refreshTab(tab, ownTab, resolve) {
const {id: tabId, url: matchUrl} = tab;
chrome.webNavigation.getAllFrames({tabId}, (frames = []) => {
ignoreChromeError();
for (const {frameId} of frames[0] ? frames : [{frameId: 0}]) {
getStyles({matchUrl, enabled: true, asHash: true}).then(styles => {
const message = {method: 'styleReplaceAll', tabId, frameId, styles};
invokeOrPostpone(tab.active, sendMessage, message, ignoreChromeError);
if (!frameId) setTimeout(updateIcon, 0, {tab, styles});
if (resolve) resolve();
});
}
});
}
}
function updateIcon({tab, styles}) {
if (tab.id < 0) {
return;

View File

@ -102,7 +102,8 @@
);
}
function install({url, direct, downloaded}, {tab}) {
function install({url, direct, downloaded, tab}, sender) {
tab = tab !== undefined ? tab : sender.tab;
url = url || tab.url;
if (direct && !downloaded) {
prefetchCodeForInstallation(tab.id, url);

View File

@ -1,4 +1,4 @@
/* global messageBox handleUpdate applyOnMessage styleSectionsEqual */
/* global messageBox handleUpdate handleDelete applyOnMessage styleSectionsEqual */
'use strict';
const STYLISH_DUMP_FILE_EXT = '.txt';
@ -41,7 +41,7 @@ function importFromFile({fileTypeFilter, file} = {}) {
importFromString(text) :
getOwnTab().then(tab => {
tab.url = URL.createObjectURL(new Blob([text], {type: 'text/css'}));
return API.installUsercss({direct: true}, {tab})
return API.installUsercss({direct: true, tab})
.then(() => URL.revokeObjectURL(tab.url));
})
).then(numStyles => {
@ -58,8 +58,7 @@ function importFromFile({fileTypeFilter, file} = {}) {
function importFromString(jsonString, oldStyles) {
if (!oldStyles) {
API.getStyles().then(styles => importFromString(jsonString, styles));
return;
return API.getStyles().then(styles => importFromString(jsonString, styles));
}
const json = tryJSONparse(jsonString) || [];
if (typeof json.slice !== 'function') {
@ -104,8 +103,11 @@ function importFromString(jsonString, oldStyles) {
}
function analyze(item) {
if (!item || !item.name || !item.name.trim() || typeof item !== 'object'
|| (item.sections && typeof item.sections.slice !== 'function')) {
if (typeof item !== 'object' ||
!item ||
!item.name ||
!item.name.trim() ||
(item.sections && !Array.isArray(item.sections))) {
stats.invalid.names.push(`#${index}: ${limitString(item && item.name || '')}`);
return;
}
@ -179,7 +181,7 @@ function importFromString(jsonString, oldStyles) {
stats.metaOnly.names.length +
stats.codeOnly.names.length +
stats.added.names.length;
Promise.resolve(numChanged && refreshAllTabs()).then(() => {
Promise.resolve(numChanged && API.refreshAllTabs()).then(() => {
const report = Object.keys(stats)
.filter(kind => stats[kind].names.length)
.map(kind => {
@ -213,40 +215,34 @@ function importFromString(jsonString, oldStyles) {
}
function undo() {
const oldStylesById = new Map(oldStyles.map(style => [style.id, style]));
const newIds = [
...stats.metaAndCode.ids,
...stats.metaOnly.ids,
...stats.codeOnly.ids,
...stats.added.ids,
];
let resolve;
index = 0;
return new Promise(resolve_ => {
resolve = resolve_;
undoNextId();
}).then(refreshAllTabs)
let tasks = Promise.resolve();
let tasksUI = Promise.resolve();
for (const id of newIds) {
tasks = tasks.then(() => API.deleteStyle({id, notify: false}));
tasksUI = tasksUI.then(() => handleDelete(id));
const oldStyle = oldStylesById.get(id);
if (oldStyle) {
Object.assign(oldStyle, SAVE_OPTIONS);
tasks = tasks.then(() => API.saveStyle(oldStyle));
tasksUI = tasksUI.then(() => handleUpdate(oldStyle, {reason: 'import'}));
}
}
// taskUI is superfast and updates style list only in this page,
// which should account for 99.99999999% of cases, supposedly
return tasks
.then(tasksUI)
.then(API.refreshAllTabs)
.then(() => messageBox({
title: t('importReportUndoneTitle'),
contents: newIds.length + ' ' + t('importReportUndone'),
buttons: [t('confirmOK')],
}));
function undoNextId() {
if (index === newIds.length) {
resolve();
return;
}
const id = newIds[index++];
API.deleteStyle({id, notify: false}).then(id => {
const oldStyle = oldStylesById.get(id);
if (oldStyle) {
API.saveStyle(Object.assign(oldStyle, SAVE_OPTIONS))
.then(undoNextId);
} else {
undoNextId();
}
});
}
}
function bindClick() {
@ -274,42 +270,6 @@ function importFromString(jsonString, oldStyles) {
? oldStyle.name + ' —> ' + newStyle.name
: oldStyle.name;
}
function refreshAllTabs() {
return getOwnTab().then(ownTab => new Promise(resolve => {
queryTabs().then(tabs => {
tabs = !FIREFOX ? tabs : tabs.filter(tab => tab.width);
tabs.forEach((tab, i) =>
refreshTab(tab, ownTab, (i === tabs.length - 1) && resolve));
if (!tabs.length) {
resolve();
}
});
}));
}
function refreshTab(tab, ownTab, resolve) {
const tabId = tab.id;
chrome.webNavigation.getAllFrames({tabId}, frames => {
frames = frames && frames[0] ? frames : [{frameId: 0}];
frames.forEach(({frameId}) =>
API.getStyles({matchUrl: tab.url, enabled: true, asHash: true}).then(styles => {
const message = {method: 'styleReplaceAll', tabId, frameId, styles};
if (tab.id === ownTab.id) {
applyOnMessage(message);
} else {
invokeOrPostpone(tab.active, sendMessage, message, ignoreChromeError);
}
if (frameId === 0) {
setTimeout(API.updateIcon, 0, tab, styles);
}
}));
if (resolve) {
resolve();
}
ignoreChromeError();
});
}
}

View File

@ -112,36 +112,10 @@ var hotkeys = (() => {
});
}
}
if (results.length) {
task.then(refreshAllTabs);
}
if (results.length) task.then(API.refreshAllTabs);
return results;
}
function refreshAllTabs() {
API.getStyles({matchUrl: location.href, enabled: true, asHash: true})
.then(styles => applyOnMessage({method: 'styleReplaceAll', styles}));
queryTabs().then(tabs =>
tabs.forEach(tab => (!FIREFOX || tab.width) &&
refreshTab(tab)));
}
function refreshTab(tab) {
const tabId = tab.id;
chrome.webNavigation.getAllFrames({tabId}, frames => {
frames = frames && frames[0] ? frames : [{frameId: 0}];
frames.forEach(({frameId}) =>
API.getStyles({matchUrl: tab.url, enabled: true, asHash: true}).then(styles => {
const message = {method: 'styleReplaceAll', tabId, frameId, styles};
invokeOrPostpone(tab.active, sendMessage, message, ignoreChromeError);
if (frameId === 0) {
setTimeout(API.updateIcon, 0, {tab, styles});
}
}));
ignoreChromeError();
});
}
function initHotkeyInfo() {
const container = $('#hotkey-info');
let title;