WIP: switch to API

This commit is contained in:
eight 2018-10-05 18:47:52 +08:00
parent f1639cc33e
commit 34497ebe16
17 changed files with 300 additions and 217 deletions

View File

@ -4,7 +4,7 @@ global handleCssTransitionBug detectSloppyRegexps
global openEditor global openEditor
global styleViaAPI global styleViaAPI
global loadScript global loadScript
global usercss styleManager global usercss styleManager db
*/ */
'use strict'; 'use strict';
@ -14,11 +14,13 @@ window.API_METHODS = Object.assign(window.API_METHODS || {}, {
getSectionsByUrl: styleManager.getSectionsByUrl, getSectionsByUrl: styleManager.getSectionsByUrl,
getSectionsById: styleManager.getSectionsById, getSectionsById: styleManager.getSectionsById,
getStylesInfo: styleManager.getStylesInfo, getStylesInfo: styleManager.getStylesInfo,
toggleStyle: styleManager.toggleStyle,
deleteStyle: styleManager.deleteStyle,
// saveStyle, // saveStyle,
// deleteStyle, // deleteStyle,
getStyleFromDB: id => getStyleFromDB: id =>
dbExec('get', id).then(event => event.target.result), db.exec('get', id).then(event => event.target.result),
download(msg) { download(msg) {
delete msg.method; delete msg.method;

View File

@ -1,4 +1,6 @@
/* global createCache db calcStyleDigest normalizeStyleSections db promisify */ /* eslint no-eq-null: 0, eqeqeq: [2, "smart"] */
/* global createCache db calcStyleDigest normalizeStyleSections db promisify
getStyleWithNoCode */
'use strict'; 'use strict';
const styleManager = (() => { const styleManager = (() => {
@ -14,29 +16,87 @@ const styleManager = (() => {
// FIXME: do we have to prepare `styles` map for all methods? // FIXME: do we have to prepare `styles` map for all methods?
return ensurePrepared({ return ensurePrepared({
styles, // styles,
cachedStyleForUrl, // cachedStyleForUrl,
getStylesInfo, getStylesInfo,
getSectionsByUrl, getSectionsByUrl,
installStyle, installStyle,
deleteStyle, deleteStyle,
setStyleExclusions, setStyleExclusions,
editSave, editSave,
toggleStyle toggleStyle,
getAllStyles, // used by import-export
getStylesInfoForUrl, // used by popup
countStyles,
// TODO: get all styles API? // TODO: get all styles API?
// TODO: get style by ID? // TODO: get style by ID?
}); });
function toggleStyle(id, enabled) { function countStyles(filter) {
const style = styles.get(id); if (!filter) {
style.enabled = enabled; return styles.size;
return saveStyle(style) }
.then(() => broadcastMessage('styleUpdated', {id, enabled})); // TODO
} }
function getStylesInfo() { function getAllStyles() {
// FIXME: remove code? return [...styles.values()].map(s => s.data);
return [...styles.values()]; }
function toggleStyle(id, enabled) {
const style = styles.get(id);
const newData = Object.assign({}, style.data, {enabled});
return saveStyle(newData)
.then(newData => {
style.data = newData;
return emitChanges({
method: 'styleUpdated',
codeIsUpdated: false,
style: {id, enabled}
}, style.appliesTo);
})
.then(() => id);
}
function emitChanges(message, appliesTo) {
const pending = runtimeSendMessage(message);
if (appliesTo && [...appliesTo].every(isExtensionUrl)) {
return pending;
}
// FIXME: does `discared` work in old browsers?
// TODO: send to activated tabs first?
const pendingTabs = tabQuery({discared: false})
.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) {
return /^\w+?-extension:\/\//.test(url);
}
function getStylesInfo(filter) {
if (filter && filter.id) {
return [getStyleWithNoCode(styles.get(filter.id).data)];
}
return [...styles.values()]
.filter(s => !filter || filterMatchStyle(filter, s.data))
.map(s => getStyleWithNoCode(s.data));
}
function filterMatchStyle(filter, style) {
for (const key of Object.keys(filter)) {
if (filter[key] !== style[key]) {
return false;
}
}
return true;
} }
function editSave() {} function editSave() {}
@ -52,13 +112,20 @@ const styleManager = (() => {
} }
function deleteStyle(id) { function deleteStyle(id) {
const style = styles.get(id);
return db.exec('delete', id) return db.exec('delete', id)
.then(() => { .then(() => {
// FIXME: do we really need to clear the entire cache? for (const url of style.appliesTo) {
cachedStyleForUrl.clear(); const cache = cachedStyleForUrl.get(url);
notifyAllTabs({method: 'styleDeleted', id}); delete cache[id];
return id; }
}); styles.delete(id);
return emitChanges({
method: 'styleDeleted',
data: {id}
});
})
.then(() => id);
} }
function installStyle(style) { function installStyle(style) {
@ -90,6 +157,7 @@ const styleManager = (() => {
.then(oldStyle => { .then(oldStyle => {
// FIXME: update installDate? // FIXME: update installDate?
style = Object.assign(oldStyle, style); style = Object.assign(oldStyle, style);
// FIXME: why we always run `normalizeStyleSections` at each `saveStyle`?
style.sections = normalizeStyleSections(style); style.sections = normalizeStyleSections(style);
return db.exec('put', style); return db.exec('put', style);
}) })
@ -124,39 +192,49 @@ const styleManager = (() => {
} }
} }
function getSectionsByUrl(url) { function getStylesInfoForUrl(url) {
// if (!URLS.supported(url) || prefs.get('disableAll')) {
// return []; }
// }
function getSectionsByUrl(url, filterId) {
let result = cachedStyleForUrl.get(url); let result = cachedStyleForUrl.get(url);
if (!result) { if (!result) {
result = []; result = {};
for (const style of styles.values()) { for (const {appliesTo, data} of styles.values()) {
if (!urlMatchStyle(url, style)) { if (!urlMatchStyle(url, data)) {
continue; continue;
} }
const item = { let code = '';
id: style.id, // result[id] = '';
code: '' for (const section of data.sections) {
};
for (const section of style.sections) {
if (urlMatchSection(url, section)) { if (urlMatchSection(url, section)) {
item.code += section.code; code += section.code;
} }
} }
if (item.code) { if (code) {
result.push(item); result[data.id] = code;
appliesTo.add(url);
} }
} }
cachedStyleForUrl.set(url, result);
}
if (filterId) {
return {[filterId]: result[filterId]};
} }
return result; return result;
} }
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;
if (!styleList) {
return;
}
for (const style of styleList) { for (const style of styleList) {
styles.set(style.id, style); styles.set(style.id, {
appliesTo: new Set(),
data: style
});
if (!style.name) { if (!style.name) {
style.name = 'ID: ' + style.id; style.name = 'ID: ' + style.id;
} }
@ -233,18 +311,18 @@ const styleManager = (() => {
return url.split('#')[0]; return url.split('#')[0];
} }
function cleanData(method, data) { // function cleanData(method, data) {
if ( // if (
(method === 'styleUpdated' || method === 'styleAdded') && // (method === 'styleUpdated' || method === 'styleAdded') &&
(data.sections || data.sourceCode) // (data.sections || data.sourceCode)
) { // ) {
// apply/popup/manage use only meta for these two methods, // apply/popup/manage use only meta for these two methods,
// editor may need the full code but can fetch it directly, // editor may need the full code but can fetch it directly,
// so we send just the meta to avoid spamming lots of tabs with huge styles // so we send just the meta to avoid spamming lots of tabs with huge styles
return getStyleWithNoCode(data); // return getStyleWithNoCode(data);
} // }
return output; // return data;
} // }
function isExtensionStyle(id) { function isExtensionStyle(id) {
// TODO // TODO
@ -253,8 +331,8 @@ const styleManager = (() => {
return false; return false;
} }
function broadcastMessage(method, data) { // function emitChanges(method, data) {
const pendingPrivilage = runtimeSendMessage({method, cleanData(method, data)}); // const pendingPrivilage = runtimeSendMessage({method, cleanData(method, data)});
// const affectsAll = !msg.affects || msg.affects.all; // const affectsAll = !msg.affects || msg.affects.all;
// const affectsOwnOriginOnly = // const affectsOwnOriginOnly =
// !affectsAll && (msg.affects.editor || msg.affects.manager); // !affectsAll && (msg.affects.editor || msg.affects.manager);
@ -268,45 +346,47 @@ const styleManager = (() => {
// sendMessage(msg, ignoreChromeError); // sendMessage(msg, ignoreChromeError);
// } // }
// notify tabs // notify tabs
if (affectsTabs || affectsIcon) { // if (affectsTabs || affectsIcon) {
const notifyTab = tab => { // const notifyTab = tab => {
if (!styleUpdated // if (!styleUpdated
&& (affectsTabs || URLS.optionsUI.includes(tab.url)) // && (affectsTabs || URLS.optionsUI.includes(tab.url))
// own pages are already notified via sendMessage // own pages are already notified via sendMessage
&& !(affectsSelf && tab.url.startsWith(URLS.ownOrigin)) // && !(affectsSelf && tab.url.startsWith(URLS.ownOrigin))
// skip lazy-loaded aka unloaded tabs that seem to start loading on message in FF // skip lazy-loaded aka unloaded tabs that seem to start loading on message in FF
&& (!FIREFOX || tab.width)) { // && (!FIREFOX || tab.width)) {
msg.tabId = tab.id; // msg.tabId = tab.id;
sendMessage(msg, ignoreChromeError); // sendMessage(msg, ignoreChromeError);
} // }
if (affectsIcon) { // if (affectsIcon) {
// eslint-disable-next-line no-use-before-define // eslint-disable-next-line no-use-before-define
// debounce(API.updateIcon, 0, {tab}); // debounce(API.updateIcon, 0, {tab});
} // }
}; // };
// list all tabs including chrome-extension:// which can be ours // list all tabs including chrome-extension:// which can be ours
Promise.all([ // Promise.all([
queryTabs(isExtensionStyle(data.id) ? {url: URLS.ownOrigin + '*'} : {}), // queryTabs(isExtensionStyle(data.id) ? {url: URLS.ownOrigin + '*'} : {}),
getActiveTab(), // getActiveTab(),
]).then(([tabs, activeTab]) => { // ]).then(([tabs, activeTab]) => {
const activeTabId = activeTab && activeTab.id; // const activeTabId = activeTab && activeTab.id;
for (const tab of tabs) { // for (const tab of tabs) {
invokeOrPostpone(tab.id === activeTabId, notifyTab, tab); // invokeOrPostpone(tab.id === activeTabId, notifyTab, tab);
} // }
}); // });
} // }
// notify self: the message no longer is sent to the origin in new Chrome // notify self: the message no longer is sent to the origin in new Chrome
if (typeof onRuntimeMessage !== 'undefined') { // if (typeof onRuntimeMessage !== 'undefined') {
onRuntimeMessage(originalMessage); // onRuntimeMessage(originalMessage);
} // }
// notify apply.js on own pages // notify apply.js on own pages
if (typeof applyOnMessage !== 'undefined') { // if (typeof applyOnMessage !== 'undefined') {
applyOnMessage(originalMessage); // applyOnMessage(originalMessage);
} // }
// propagate saved style state/code efficiently // propagate saved style state/code efficiently
if (styleUpdated) { // if (styleUpdated) {
msg.refreshOwnTabs = false; // msg.refreshOwnTabs = false;
API.refreshAllTabs(msg); // API.refreshAllTabs(msg);
} // }
} // }
})(); })();
function notifyAllTabs() {}

View File

@ -2,8 +2,10 @@
'use strict'; 'use strict';
const API = (() => { const API = (() => {
const preparing = promisify(chrome.runtime.getBackgroundPage.bind(chrome.runtime))() const preparing = chrome.runtime.getBackgroundPage ?
.catch(() => null); promisify(chrome.runtime.getBackgroundPage.bind(chrome.runtime))()
.catch(() => null) :
Promise.resolve(null);
const runtimeSendMessage = promisify(chrome.runtime.sendMessage.bind(chrome.runtime)); const runtimeSendMessage = promisify(chrome.runtime.sendMessage.bind(chrome.runtime));
return new Proxy(() => {}, { return new Proxy(() => {}, {
get: (target, name) => get: (target, name) =>

View File

@ -45,6 +45,14 @@
API.styleViaAPI({action: 'styleApply'}); API.styleViaAPI({action: 'styleApply'});
return; return;
} }
// FIXME: options?
// FIXME: getStylesFallback?
API.getSectionsByUrl(getMatchUrl())
.then(buildSections)
.then(callback);
}
function getMatchUrl() {
var matchUrl = location.href; var matchUrl = location.href;
if (!matchUrl.match(/^(http|file|chrome|ftp)/)) { if (!matchUrl.match(/^(http|file|chrome|ftp)/)) {
// dynamic about: and javascript: iframes don't have an URL yet // dynamic about: and javascript: iframes don't have an URL yet
@ -55,15 +63,11 @@
} }
} catch (e) {} } catch (e) {}
} }
// const request = Object.assign({ return matchUrl;
// method: 'getStylesForFrame', }
// asHash: true,
// matchUrl, function buildSections(result) {
// }, options); return Object.entries(result).map(([id, code]) => ({id: +id, code}));
// FIXME: options?
// FIXME: getStylesFallback?
API.getSectionsByUrl(matchUrl)
.then(callback);
} }
/** /**
@ -122,7 +126,9 @@
} }
if (request.style.enabled) { if (request.style.enabled) {
removeStyle({id: request.style.id, retire: true}); removeStyle({id: request.style.id, retire: true});
API.getSectionsById(request.style.id).then(applyStyles); API.getSectionsByUrl(getMatchUrl(), request.style.id)
.then(buildSections)
.then(applyStyles);
} else { } else {
removeStyle(request.style); removeStyle(request.style);
} }
@ -130,7 +136,9 @@
case 'styleAdded': case 'styleAdded':
if (request.style.enabled) { if (request.style.enabled) {
API.getSectionsById(request.style.id).then(applyStyles); API.getSectionsByUrl(getMatchUrl(), request.style.id)
.then(buildSections)
.then(applyStyles);
} }
break; break;
@ -195,7 +203,9 @@
addStyleElement(inCache); addStyleElement(inCache);
disabledElements.delete(id); disabledElements.delete(id);
} else { } else {
API.getSectionsById(id).then(applyStyles); API.getSectionsByUrl(getMatchUrl(), id)
.then(buildSections)
.then(applyStyles);
} }
} else { } else {
if (inDoc) { if (inDoc) {

View File

@ -33,11 +33,10 @@
&& event.data.type === 'ouc-is-installed' && event.data.type === 'ouc-is-installed'
&& allowedOrigins.includes(event.origin) && allowedOrigins.includes(event.origin)
) { ) {
chrome.runtime.sendMessage({ API.findUsercss({
method: 'findUsercss',
name: event.data.name, name: event.data.name,
namespace: event.data.namespace namespace: event.data.namespace
}, style => { }).then(style => {
const data = {event}; const data = {event};
const callbackObject = { const callbackObject = {
installed: Boolean(style), installed: Boolean(style),
@ -129,12 +128,11 @@
&& event.data.type === 'ouc-install-usercss' && event.data.type === 'ouc-install-usercss'
&& allowedOrigins.includes(event.origin) && allowedOrigins.includes(event.origin)
) { ) {
chrome.runtime.sendMessage({ API.saveUsercss({
method: 'saveUsercss',
reason: 'install', reason: 'install',
name: event.data.title, name: event.data.title,
sourceCode: event.data.code, sourceCode: event.data.code,
}, style => { }).then(style => {
sendInstallCallback({ sendInstallCallback({
enabled: style.enabled, enabled: style.enabled,
key: event.data.key key: event.data.key

View File

@ -16,8 +16,8 @@
let sourceCode, port, timer; let sourceCode, port, timer;
chrome.runtime.onConnect.addListener(onConnected); chrome.runtime.onConnect.addListener(onConnected);
chrome.runtime.sendMessage({method: 'installUsercss', url}, r => API.installUsercss({url})
r && r.__ERROR__ && alert(r.__ERROR__)); .catch(err => alert(err));
function onConnected(newPort) { function onConnected(newPort) {
port = newPort; port = newPort;

View File

@ -30,10 +30,9 @@
gotBody = true; gotBody = true;
// TODO: remove the following statement when USO pagination title is fixed // TODO: remove the following statement when USO pagination title is fixed
document.title = document.title.replace(/^(\d+)&\w+=/, '#$1: '); document.title = document.title.replace(/^(\d+)&\w+=/, '#$1: ');
chrome.runtime.sendMessage({ API.getStylesInfo({
method: 'getStyles',
md5Url: getMeta('stylish-md5-url') || location.href md5Url: getMeta('stylish-md5-url') || location.href
}, checkUpdatability); }).then(checkUpdatability);
} }
if (document.getElementById('install_button')) { if (document.getElementById('install_button')) {
onDOMready().then(() => { onDOMready().then(() => {
@ -148,10 +147,9 @@
function onUpdate() { function onUpdate() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
chrome.runtime.sendMessage({ API.getStylesInfo({
method: 'getStyles', md5Url: getMeta('stylish-md5-url') || location.href
md5Url: getMeta('stylish-md5-url') || location.href, }).then(([style]) => {
}, ([style]) => {
saveStyleCode('styleUpdate', style.name, {id: style.id}) saveStyleCode('styleUpdate', style.name, {id: style.id})
.then(resolve, reject); .then(resolve, reject);
}); });
@ -160,36 +158,27 @@
function saveStyleCode(message, name, addProps) { function saveStyleCode(message, name, addProps) {
return new Promise((resolve, reject) => { const isNew = message === 'styleInstall';
const isNew = message === 'styleInstall'; const needsConfirmation = isNew || !saveStyleCode.confirmed;
const needsConfirmation = isNew || !saveStyleCode.confirmed; if (needsConfirmation && !confirm(chrome.i18n.getMessage(message, [name]))) {
if (needsConfirmation && !confirm(chrome.i18n.getMessage(message, [name]))) { return Promise.reject();
reject(); }
saveStyleCode.confirmed = true;
enableUpdateButton(false);
return getStyleJson().then(json => {
if (!json) {
prompt(chrome.i18n.getMessage('styleInstallFailed', ''),
'https://github.com/openstyles/stylus/issues/195');
return; return;
} }
saveStyleCode.confirmed = true; return API.installStyle(Object.assign(json, addProps))
enableUpdateButton(false); .then(style => {
getStyleJson().then(json => { if (!isNew && style.updateUrl.includes('?')) {
if (!json) { enableUpdateButton(true);
prompt(chrome.i18n.getMessage('styleInstallFailed', ''), } else {
'https://github.com/openstyles/stylus/issues/195'); sendEvent({type: 'styleInstalledChrome'});
return;
}
chrome.runtime.sendMessage(
Object.assign(json, addProps, {
method: 'saveStyle',
reason: isNew ? 'install' : 'update',
}),
style => {
if (!isNew && style.updateUrl.includes('?')) {
enableUpdateButton(true);
} else {
sendEvent({type: 'styleInstalledChrome'});
}
} }
); });
resolve();
});
}); });
function enableUpdateButton(state) { function enableUpdateButton(state) {
@ -220,13 +209,12 @@
if (url.startsWith('#')) { if (url.startsWith('#')) {
resolve(document.getElementById(url.slice(1)).textContent); resolve(document.getElementById(url.slice(1)).textContent);
} else { } else {
chrome.runtime.sendMessage(Object.assign({ API.download(Object.assign({
url, url,
method: 'download',
timeout: 60e3, timeout: 60e3,
// USO can't handle POST requests for style json // USO can't handle POST requests for style json
body: null, body: null,
}, options), result => { }, options)).then(result => {
const error = result && result.__ERROR__; const error = result && result.__ERROR__;
if (error) { if (error) {
alert('Error' + (error ? '\n' + error : '')); alert('Error' + (error ? '\n' + error : ''));
@ -249,12 +237,12 @@
if (codeElement && !codeElement.textContent.trim()) { if (codeElement && !codeElement.textContent.trim()) {
return style; return style;
} }
return getResource(getMeta('stylish-update-url')).then(code => new Promise(resolve => { return getResource(getMeta('stylish-update-url'))
chrome.runtime.sendMessage({method: 'parseCss', code}, ({sections}) => { .then(code => API.parseCss({code}))
style.sections = sections; .then(result => {
resolve(style); style.sections = result.sections;
return style;
}); });
}));
}) })
.catch(() => null); .catch(() => null);
} }

View File

@ -18,6 +18,7 @@
} }
</style> </style>
<script src="js/promisify.js"></script>
<script src="js/dom.js"></script> <script src="js/dom.js"></script>
<script src="js/messaging.js"></script> <script src="js/messaging.js"></script>
<script src="js/prefs.js"></script> <script src="js/prefs.js"></script>
@ -25,6 +26,7 @@
<script src="js/script-loader.js"></script> <script src="js/script-loader.js"></script>
<script src="js/storage-util.js"></script> <script src="js/storage-util.js"></script>
<script src="js/exclusions.js"></script> <script src="js/exclusions.js"></script>
<script src="content/api.js"></script>
<script src="content/apply.js"></script> <script src="content/apply.js"></script>
<script src="edit/util.js"></script> <script src="edit/util.js"></script>
<script src="edit/regexp-tester.js"></script> <script src="edit/regexp-tester.js"></script>

View File

@ -165,7 +165,7 @@ function onRuntimeMessage(request) {
// code-less style from notifyAllTabs // code-less style from notifyAllTabs
const {sections, id} = request.style; const {sections, id} = request.style;
((sections && sections[0] || {}).code === null ((sections && sections[0] || {}).code === null
? API.getStyles({id}) ? API.getStyleFromDB(id)
: Promise.resolve([request.style]) : Promise.resolve([request.style])
).then(([style]) => { ).then(([style]) => {
if (isUsercss(style)) { if (isUsercss(style)) {
@ -372,11 +372,10 @@ function save() {
return; return;
} }
API.saveStyle({ API.editSave({
id: styleId, id: styleId,
name: $('#name').value.trim(), name: $('#name').value.trim(),
enabled: $('#enabled').checked, enabled: $('#enabled').checked,
reason: 'editSave',
sections: getSectionsHashes(), sections: getSectionsHashes(),
exclusions: exclusions.get() exclusions: exclusions.get()
}) })

View File

@ -264,7 +264,6 @@ function openURL({
index, index,
active, active,
currentWindow = true, currentWindow = true,
message,
}) { }) {
url = url.includes('://') ? url : chrome.runtime.getURL(url); url = url.includes('://') ? url : chrome.runtime.getURL(url);
// [some] chromium forks don't handle their fake branded protocols // [some] chromium forks don't handle their fake branded protocols
@ -280,15 +279,7 @@ function openURL({
url.replace(/%2F.*/, '*').replace(/#.*/, '') : url.replace(/%2F.*/, '*').replace(/#.*/, '') :
url.replace(/#.*/, ''); url.replace(/#.*/, '');
const task = queryTabs({url: urlQuery, currentWindow}).then(maybeSwitch); return queryTabs({url: urlQuery, currentWindow}).then(maybeSwitch);
if (!message) {
return task;
} else {
return task.then(onTabReady).then(tab => {
message.tabId = tab.id;
return sendMessage(message).then(() => tab);
});
}
function maybeSwitch(tabs = []) { function maybeSwitch(tabs = []) {
const urlWithSlash = url + '/'; const urlWithSlash = url + '/';

View File

@ -58,7 +58,7 @@ function importFromFile({fileTypeFilter, file} = {}) {
function importFromString(jsonString, oldStyles) { function importFromString(jsonString, oldStyles) {
if (!oldStyles) { if (!oldStyles) {
return API.getStyles().then(styles => importFromString(jsonString, styles)); return API.getStylesInfo().then(styles => importFromString(jsonString, styles));
} }
const json = tryJSONparse(jsonString) || []; const json = tryJSONparse(jsonString) || [];
if (typeof json.slice !== 'function') { if (typeof json.slice !== 'function') {
@ -93,8 +93,9 @@ function importFromString(jsonString, oldStyles) {
const info = analyze(item); const info = analyze(item);
if (info) { if (info) {
// using saveStyle directly since json was parsed in background page context // using saveStyle directly since json was parsed in background page context
return API.saveStyle(Object.assign(item, SAVE_OPTIONS)) // FIXME: rewrite importStyle
.then(style => account({style, info, resolve})); // return API.saveStyle(Object.assign(item, SAVE_OPTIONS))
// .then(style => account({style, info, resolve}));
} }
} }
renderQueue.forEach(style => handleUpdate(style, {reason: 'import'})); renderQueue.forEach(style => handleUpdate(style, {reason: 'import'}));
@ -224,12 +225,13 @@ function importFromString(jsonString, oldStyles) {
let tasks = Promise.resolve(); let tasks = Promise.resolve();
let tasksUI = Promise.resolve(); let tasksUI = Promise.resolve();
for (const id of newIds) { for (const id of newIds) {
tasks = tasks.then(() => API.deleteStyle({id, notify: false})); tasks = tasks.then(() => API.deleteStyle(id));
tasksUI = tasksUI.then(() => handleDelete(id)); tasksUI = tasksUI.then(() => handleDelete(id));
const oldStyle = oldStylesById.get(id); const oldStyle = oldStylesById.get(id);
if (oldStyle) { if (oldStyle) {
Object.assign(oldStyle, SAVE_OPTIONS); Object.assign(oldStyle, SAVE_OPTIONS);
tasks = tasks.then(() => API.saveStyle(oldStyle)); // FIXME: import undo
// tasks = tasks.then(() => API.saveStyle(oldStyle));
tasksUI = tasksUI.then(() => handleUpdate(oldStyle, {reason: 'import'})); tasksUI = tasksUI.then(() => handleUpdate(oldStyle, {reason: 'import'}));
} }
} }
@ -274,7 +276,7 @@ function importFromString(jsonString, oldStyles) {
$('#file-all-styles').onclick = () => { $('#file-all-styles').onclick = () => {
API.getStyles().then(styles => { API.getAllStyles().then(styles => {
// https://crbug.com/714373 // https://crbug.com/714373
document.documentElement.appendChild( document.documentElement.appendChild(
$create('iframe', { $create('iframe', {

View File

@ -431,7 +431,7 @@ Object.assign(handleEvent, {
}) })
.then(({button}) => { .then(({button}) => {
if (button === 0) { if (button === 0) {
API.deleteStyle({id}); API.deleteStyle(id);
} }
}); });
}, },
@ -646,7 +646,7 @@ function switchUI({styleOnly} = {}) {
const missingFavicons = newUI.enabled && newUI.favicons && !$('.applies-to img'); const missingFavicons = newUI.enabled && newUI.favicons && !$('.applies-to img');
if (changed.enabled || (missingFavicons && !createStyleElement.parts)) { if (changed.enabled || (missingFavicons && !createStyleElement.parts)) {
installed.textContent = ''; installed.textContent = '';
API.getStyles().then(showStyles); API.getStylesInfo().then(showStyles);
return; return;
} }
if (changed.targets) { if (changed.targets) {
@ -670,7 +670,9 @@ function onVisibilityChange() {
// assuming other changes aren't important enough to justify making a complicated DOM sync // assuming other changes aren't important enough to justify making a complicated DOM sync
case 'visible': case 'visible':
if (sessionStorage.justEditedStyleId) { if (sessionStorage.justEditedStyleId) {
API.getStyles({id: sessionStorage.justEditedStyleId}).then(([style]) => { API.getStylesInfo({
id: sessionStorage.justEditedStyleId
}).then(([style]) => {
handleUpdate(style, {method: 'styleUpdated'}); handleUpdate(style, {method: 'styleUpdated'});
}); });
delete sessionStorage.justEditedStyleId; delete sessionStorage.justEditedStyleId;

View File

@ -67,13 +67,13 @@
"matches": ["http://userstyles.org/*", "https://userstyles.org/*"], "matches": ["http://userstyles.org/*", "https://userstyles.org/*"],
"run_at": "document_start", "run_at": "document_start",
"all_frames": true, "all_frames": true,
"js": ["content/install-hook-userstyles.js"] "js": ["js/promisify.js", "content/api.js", "content/install-hook-userstyles.js"]
}, },
{ {
"matches": ["https://openusercss.org/*", "https://openusercss.com/*"], "matches": ["https://openusercss.org/*", "https://openusercss.com/*"],
"run_at": "document_start", "run_at": "document_start",
"all_frames": false, "all_frames": false,
"js": ["content/install-hook-openusercss.js"] "js": ["js/promisify.js", "content/api.js", "content/install-hook-openusercss.js"]
}, },
{ {
"matches": [ "matches": [
@ -97,7 +97,7 @@
], ],
"run_at": "document_idle", "run_at": "document_idle",
"all_frames": false, "all_frames": false,
"js": ["content/install-hook-usercss.js"] "js": ["js/promisify.js", "content/api.js", "content/install-hook-usercss.js"]
} }
], ],
"browser_action": { "browser_action": {

View File

@ -155,6 +155,8 @@
<script src="js/messaging.js"></script> <script src="js/messaging.js"></script>
<script src="js/localization.js"></script> <script src="js/localization.js"></script>
<script src="js/prefs.js"></script> <script src="js/prefs.js"></script>
<script src="js/promisify.js"></script>
<script src="content/api.js"></script>
<script src="content/apply.js"></script> <script src="content/apply.js"></script>
<link rel="stylesheet" href="popup/popup.css"> <link rel="stylesheet" href="popup/popup.css">

View File

@ -101,15 +101,13 @@ var hotkeys = (() => {
entry = typeof entry === 'string' ? $('#' + entry) : entry; entry = typeof entry === 'string' ? $('#' + entry) : entry;
if (!match && $('.checker', entry).checked !== enable || entry.classList.contains(match)) { if (!match && $('.checker', entry).checked !== enable || entry.classList.contains(match)) {
results.push(entry.id); results.push(entry.id);
task = task.then(() => API.saveStyle({ task = task
id: entry.styleId, .then(() => API.toggleStyle(entry.styleId, enable))
enabled: enable, .then(() => {
notify: false, entry.classList.toggle('enabled', enable);
})).then(() => { entry.classList.toggle('disabled', !enable);
entry.classList.toggle('enabled', enable); $('.checker', entry).checked = enable;
entry.classList.toggle('disabled', !enable); });
$('.checker', entry).checked = enable;
});
} }
} }
if (results.length) task.then(API.refreshAllTabs); if (results.length) task.then(API.refreshAllTabs);

View File

@ -1,6 +1,6 @@
/* /*
global configDialog hotkeys global configDialog hotkeys
global popupExclusions global popupExclusions promisify onTabReady
*/ */
'use strict'; 'use strict';
@ -20,10 +20,7 @@ getActiveTab().then(tab =>
: getTabRealURL(tab) : getTabRealURL(tab)
).then(url => Promise.all([ ).then(url => Promise.all([
(tabURL = URLS.supported(url) ? url : '') && (tabURL = URLS.supported(url) ? url : '') &&
API.getStyles({ API.getStylesInfoForUrl(tabURL),
matchUrl: tabURL,
omitCode: !BG,
}),
onDOMready().then(initPopup), onDOMready().then(initPopup),
])).then(([styles]) => { ])).then(([styles]) => {
showStyles(styles); showStyles(styles);
@ -115,7 +112,8 @@ function initPopup() {
} }
getActiveTab().then(function ping(tab, retryCountdown = 10) { getActiveTab().then(function ping(tab, retryCountdown = 10) {
sendMessage({tabId: tab.id, method: 'ping', frameId: 0}, pong => { const sendMessage = promisify(chrome.tabs.sendMessage.bind(chrome.tabs));
sendMessage(tab.id, {method: 'ping'}, {frameId: 0}).then(pong => {
if (pong) { if (pong) {
return; return;
} }
@ -233,18 +231,19 @@ function showStyles(styles) {
installed.appendChild(container); installed.appendChild(container);
setTimeout(detectSloppyRegexps, 100, styles); setTimeout(detectSloppyRegexps, 100, styles);
API.getStyles({ // FIXME: detect sloppy regexp?
matchUrl: tabURL, // API.getStyles({
strictRegexp: false, // matchUrl: tabURL,
omitCode: true, // strictRegexp: false,
}).then(unscreenedStyles => { // omitCode: true,
for (const style of unscreenedStyles) { // }).then(unscreenedStyles => {
if (!styles.find(({id}) => id === style.id)) { // for (const style of unscreenedStyles) {
createStyleElement({style, check: true}); // if (!styles.find(({id}) => id === style.id)) {
} // createStyleElement({style, check: true});
} // }
window.dispatchEvent(new Event('showStyles:done')); // }
}); window.dispatchEvent(new Event('showStyles:done'));
// });
} }
@ -347,10 +346,10 @@ Object.assign(handleEvent, {
toggle(event) { toggle(event) {
// when fired on checkbox, prevent the parent label from seeing the event, see #501 // when fired on checkbox, prevent the parent label from seeing the event, see #501
event.stopPropagation(); event.stopPropagation();
API.saveStyle({ API.toggleStyle(
id: handleEvent.getClickedStyleId(event), handleEvent.getClickedStyleId(event),
enabled: this.matches('.enable') || this.checked, this.matches('.enable') || this.checked
}); );
}, },
delete(event) { delete(event) {
@ -377,14 +376,14 @@ Object.assign(handleEvent, {
className: 'lights-on', className: 'lights-on',
onComplete: () => (box.dataset.display = false), onComplete: () => (box.dataset.display = false),
}); });
if (ok) API.deleteStyle({id}); if (ok) API.deleteStyle(id);
} }
}, },
configure(event) { configure(event) {
const {styleId, styleIsUsercss} = handleEvent.getClickedStyleElement(event); const {styleId, styleIsUsercss} = handleEvent.getClickedStyleElement(event);
if (styleIsUsercss) { if (styleIsUsercss) {
API.getStyles({id: styleId}).then(([style]) => { API.getStylesInfo({id: styleId}).then(([style]) => {
hotkeys.setState(false); hotkeys.setState(false);
configDialog(style).then(() => { configDialog(style).then(() => {
hotkeys.setState(true); hotkeys.setState(true);
@ -452,12 +451,19 @@ Object.assign(handleEvent, {
openURLandHide(event) { openURLandHide(event) {
event.preventDefault(); event.preventDefault();
const message = tryJSONparse(this.dataset.sendMessage);
getActiveTab() getActiveTab()
.then(activeTab => API.openURL({ .then(activeTab => API.openURL({
url: this.href || this.dataset.href, url: this.href || this.dataset.href,
index: activeTab.index + 1, index: activeTab.index + 1
message: tryJSONparse(this.dataset.sendMessage),
})) }))
.then(tab => {
if (message) {
const sendMessage = promisify(chrome.tabs.sendMessage.bind(chrome.tabs.sendMessage));
return onTabReady(tab)
.then(() => sendMessage(tab.id, message));
}
})
.then(window.close); .then(window.close);
}, },
@ -495,17 +501,18 @@ function handleUpdate(style) {
} }
if (!tabURL) return; if (!tabURL) return;
// Add an entry when a new style for the current url is installed // Add an entry when a new style for the current url is installed
API.getStyles({ // FIXME: what does this do?
matchUrl: tabURL, // API.getStyles({
stopOnFirst: true, // matchUrl: tabURL,
omitCode: true, // stopOnFirst: true,
}).then(([style]) => { // omitCode: true,
if (style) { // }).then(([style]) => {
document.body.classList.remove('blocked'); // if (style) {
$$.remove('.blocked-info, #no-styles'); // document.body.classList.remove('blocked');
createStyleElement({style, check: true}); // $$.remove('.blocked-info, #no-styles');
} // createStyleElement({style, check: true});
}); // }
// });
} }

View File

@ -287,7 +287,7 @@ window.addEventListener('showStyles:done', function _() {
return; return;
} }
const md5Url = UPDATE_URL.replace('%', result.id); const md5Url = UPDATE_URL.replace('%', result.id);
API.getStyles({md5Url}).then(([installedStyle]) => { API.countStyles({md5Url}).then(installedStyle => {
if (installedStyle) { if (installedStyle) {
totalResults = Math.max(0, totalResults - 1); totalResults = Math.max(0, totalResults - 1);
} else { } else {
@ -529,7 +529,7 @@ window.addEventListener('showStyles:done', function _() {
event.stopPropagation(); event.stopPropagation();
const entry = this.closest('.search-result'); const entry = this.closest('.search-result');
saveScrollPosition(entry); saveScrollPosition(entry);
API.deleteStyle({id: entry._result.installedStyleId}) API.deleteStyle(entry._result.installedStyleId)
.then(restoreScrollPosition); .then(restoreScrollPosition);
} }