WIP: emitChangesToTabs

This commit is contained in:
eight 2018-10-05 21:28:19 +08:00
parent 34497ebe16
commit 2472e91f57

View File

@ -32,13 +32,6 @@ const styleManager = (() => {
// TODO: get style by ID? // TODO: get style by ID?
}); });
function countStyles(filter) {
if (!filter) {
return styles.size;
}
// TODO
}
function getAllStyles() { function getAllStyles() {
return [...styles.values()].map(s => s.data); return [...styles.values()].map(s => s.data);
} }
@ -58,23 +51,38 @@ const styleManager = (() => {
.then(() => id); .then(() => id);
} }
function emitChangesToTabs(getMessage, appliesTo, ignoreExtension = false) {
// FIXME: does `discarded` work in old browsers?
// TODO: send to activated tabs first?
return tabQuery({discarded: false})
.then(tabs => {
const pending = [];
for (const tab of tabs) {
if (
!URLS.supported(tab.url) ||
ignoreExtension && isExtensionUrl(tab.url) ||
appliesTo && !appliesTo.has(tab.url)
) {
continue;
}
const message = typeof getMessage === 'function' ? getMessage(tab) : getMessage;
if (message) {
pending.push(tabSendMessage(tab.id, message));
}
}
return Promise.all(pending);
});
}
function emitChanges(message, appliesTo) { function emitChanges(message, appliesTo) {
const pending = runtimeSendMessage(message); const pending = runtimeSendMessage(message);
if (appliesTo && [...appliesTo].every(isExtensionUrl)) { if (appliesTo && [...appliesTo].every(isExtensionUrl)) {
return pending; return pending;
} }
// FIXME: does `discared` work in old browsers? return Promise.all([
// TODO: send to activated tabs first? pending,
const pendingTabs = tabQuery({discared: false}) emitChangesToTabs(message, appliesTo, true),
.then(tabs => tabs ]);
.filter(t =>
URLS.supported(t.url) &&
!isExtensionUrl(t.url) &&
(!appliesTo || appliesTo.has(t.url))
)
.map(t => tabSendMessage(t.id, message))
);
return Promise.all([pending, pendingTabs]);
} }
function isExtensionUrl(url) { function isExtensionUrl(url) {
@ -90,6 +98,18 @@ const styleManager = (() => {
.map(s => getStyleWithNoCode(s.data)); .map(s => getStyleWithNoCode(s.data));
} }
function countStyles(filter) {
if (!filter) {
return styles.size;
}
if (filter.id) {
return styles.has(filter.id) ? 1 : 0;
}
return [...styles.values()]
.filter(s => filterMatchStyle(filter, s.data))
.length;
}
function filterMatchStyle(filter, style) { function filterMatchStyle(filter, style) {
for (const key of Object.keys(filter)) { for (const key of Object.keys(filter)) {
if (filter[key] !== style[key]) { if (filter[key] !== style[key]) {
@ -99,7 +119,9 @@ const styleManager = (() => {
return true; return true;
} }
function editSave() {} function editSave(style) {
return saveStyle(style);
}
function setStyleExclusions() {} function setStyleExclusions() {}
@ -128,15 +150,64 @@ const styleManager = (() => {
.then(() => id); .then(() => id);
} }
function installStyle(style) { function createNewStyle() {
return calcStyleDigest(style) return {
enabled: true,
updateUrl: null,
md5Url: null,
url: null,
originalMd5: null,
installDate: Date.now()
};
}
function installStyle(data) {
let style = styles.get(style.id);
if (!style) {
data = Object.assign(createNewStyle(), data);
} else {
data = Object.assign({}, style.data, data);
}
// FIXME: update installDate?
return calcStyleDigest(data)
.then(digest => { .then(digest => {
style.originalDigest = digest; data.originalDigest = digest;
return saveStyle(style); return saveStyle(data);
}) })
.then(style => { .then(newData => {
// FIXME: do we really need to clear the entire cache? // FIXME: do we really need to clear the entire cache?
cachedStyleForUrl.clear(); // cachedStyleForUrl.clear();
if (!style) {
const appliesTo = new Set();
styles.set(newData.id, {
appliesTo,
data: newData
});
// update cache
tabQuery()
.then(tabs => {
for (const tab of tabs) {
// FIXME: switch to something like `shouldApplyTo` that doesn't use code
const code = getAppliedCode(tab.url, newData);
if (!code) {
continue;
}
const cache = cachedStyleForUrl.get(tab.url);
if (!cache) {
continue;
}
cache[newData.id] = code;
appliesTo.add(tab.url);
}
return emitChanges()
})
}
const appliesTo = style.appliesTo;
style.appliesTo = new Set;
for (const url of style.appliesTo) {
cachedStyleForUrl.delete(url);
}
emitChanges()
// FIXME: invalid signature // FIXME: invalid signature
notifyAllTabs(); notifyAllTabs();
return style; return style;
@ -155,7 +226,6 @@ const styleManager = (() => {
function saveStyle(style) { function saveStyle(style) {
return (style.id == null ? getNewStyle() : getOldStyle()) return (style.id == null ? getNewStyle() : getOldStyle())
.then(oldStyle => { .then(oldStyle => {
// FIXME: update installDate?
style = Object.assign(oldStyle, style); style = Object.assign(oldStyle, style);
// FIXME: why we always run `normalizeStyleSections` at each `saveStyle`? // FIXME: why we always run `normalizeStyleSections` at each `saveStyle`?
style.sections = normalizeStyleSections(style); style.sections = normalizeStyleSections(style);
@ -181,14 +251,7 @@ const styleManager = (() => {
// FIXME: don't overwrite style name when the name is empty // FIXME: don't overwrite style name when the name is empty
function getNewStyle() { function getNewStyle() {
return Promise.resolve({ return Promise.resolve();
enabled: true,
updateUrl: null,
md5Url: null,
url: null,
originalMd5: null,
installDate: Date.now()
});
} }
} }
@ -201,16 +264,7 @@ const styleManager = (() => {
if (!result) { if (!result) {
result = {}; result = {};
for (const {appliesTo, data} of styles.values()) { for (const {appliesTo, data} of styles.values()) {
if (!urlMatchStyle(url, data)) { const code = getAppliedCode(url, data);
continue;
}
let code = '';
// result[id] = '';
for (const section of data.sections) {
if (urlMatchSection(url, section)) {
code += section.code;
}
}
if (code) { if (code) {
result[data.id] = code; result[data.id] = code;
appliesTo.add(url); appliesTo.add(url);
@ -224,6 +278,19 @@ const styleManager = (() => {
return result; return result;
} }
function getAppliedCode(url, data) {
if (!urlMatchStyle(url, data)) {
return;
}
let code = '';
for (const section of data.sections) {
if (urlMatchSection(url, section)) {
code += section.code;
}
}
return code;
}
function prepare() { function prepare() {
return db.exec('getAll').then(event => { return db.exec('getAll').then(event => {
const styleList = event.target.result; const styleList = event.target.result;