diff --git a/background/background.js b/background/background.js index cdbfd33e..58c741a9 100644 --- a/background/background.js +++ b/background/background.js @@ -4,7 +4,7 @@ global handleCssTransitionBug detectSloppyRegexps global openEditor global styleViaAPI global loadScript -global usercss styleManager +global usercss styleManager db */ 'use strict'; @@ -14,11 +14,13 @@ window.API_METHODS = Object.assign(window.API_METHODS || {}, { getSectionsByUrl: styleManager.getSectionsByUrl, getSectionsById: styleManager.getSectionsById, getStylesInfo: styleManager.getStylesInfo, + toggleStyle: styleManager.toggleStyle, + deleteStyle: styleManager.deleteStyle, // saveStyle, // deleteStyle, getStyleFromDB: id => - dbExec('get', id).then(event => event.target.result), + db.exec('get', id).then(event => event.target.result), download(msg) { delete msg.method; diff --git a/background/style-manager.js b/background/style-manager.js index f89696fe..3f5995ad 100644 --- a/background/style-manager.js +++ b/background/style-manager.js @@ -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'; const styleManager = (() => { @@ -14,29 +16,87 @@ const styleManager = (() => { // FIXME: do we have to prepare `styles` map for all methods? return ensurePrepared({ - styles, - cachedStyleForUrl, + // styles, + // cachedStyleForUrl, getStylesInfo, getSectionsByUrl, installStyle, deleteStyle, setStyleExclusions, editSave, - toggleStyle + toggleStyle, + getAllStyles, // used by import-export + getStylesInfoForUrl, // used by popup + countStyles, // TODO: get all styles API? // TODO: get style by ID? }); - function toggleStyle(id, enabled) { - const style = styles.get(id); - style.enabled = enabled; - return saveStyle(style) - .then(() => broadcastMessage('styleUpdated', {id, enabled})); + function countStyles(filter) { + if (!filter) { + return styles.size; + } + // TODO } - function getStylesInfo() { - // FIXME: remove code? - return [...styles.values()]; + function getAllStyles() { + return [...styles.values()].map(s => s.data); + } + + 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() {} @@ -52,13 +112,20 @@ const styleManager = (() => { } function deleteStyle(id) { + const style = styles.get(id); return db.exec('delete', id) .then(() => { - // FIXME: do we really need to clear the entire cache? - cachedStyleForUrl.clear(); - notifyAllTabs({method: 'styleDeleted', id}); - return id; - }); + for (const url of style.appliesTo) { + const cache = cachedStyleForUrl.get(url); + delete cache[id]; + } + styles.delete(id); + return emitChanges({ + method: 'styleDeleted', + data: {id} + }); + }) + .then(() => id); } function installStyle(style) { @@ -90,6 +157,7 @@ const styleManager = (() => { .then(oldStyle => { // FIXME: update installDate? style = Object.assign(oldStyle, style); + // FIXME: why we always run `normalizeStyleSections` at each `saveStyle`? style.sections = normalizeStyleSections(style); return db.exec('put', style); }) @@ -124,39 +192,49 @@ const styleManager = (() => { } } - function getSectionsByUrl(url) { - // if (!URLS.supported(url) || prefs.get('disableAll')) { - // return []; - // } + function getStylesInfoForUrl(url) { + + } + + function getSectionsByUrl(url, filterId) { let result = cachedStyleForUrl.get(url); if (!result) { - result = []; - for (const style of styles.values()) { - if (!urlMatchStyle(url, style)) { + result = {}; + for (const {appliesTo, data} of styles.values()) { + if (!urlMatchStyle(url, data)) { continue; } - const item = { - id: style.id, - code: '' - }; - for (const section of style.sections) { + let code = ''; + // result[id] = ''; + for (const section of data.sections) { if (urlMatchSection(url, section)) { - item.code += section.code; + code += section.code; } } - if (item.code) { - result.push(item); + if (code) { + result[data.id] = code; + appliesTo.add(url); } } + cachedStyleForUrl.set(url, result); + } + if (filterId) { + return {[filterId]: result[filterId]}; } return result; } function prepare() { return db.exec('getAll').then(event => { - const styleList = event.target.result || []; + const styleList = event.target.result; + if (!styleList) { + return; + } for (const style of styleList) { - styles.set(style.id, style); + styles.set(style.id, { + appliesTo: new Set(), + data: style + }); if (!style.name) { style.name = 'ID: ' + style.id; } @@ -233,18 +311,18 @@ const styleManager = (() => { return url.split('#')[0]; } - function cleanData(method, data) { - if ( - (method === 'styleUpdated' || method === 'styleAdded') && - (data.sections || data.sourceCode) - ) { + // function cleanData(method, data) { + // if ( + // (method === 'styleUpdated' || method === 'styleAdded') && + // (data.sections || data.sourceCode) + // ) { // apply/popup/manage use only meta for these two methods, // 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 - return getStyleWithNoCode(data); - } - return output; - } + // return getStyleWithNoCode(data); + // } + // return data; + // } function isExtensionStyle(id) { // TODO @@ -253,8 +331,8 @@ const styleManager = (() => { return false; } - function broadcastMessage(method, data) { - const pendingPrivilage = runtimeSendMessage({method, cleanData(method, data)}); + // function emitChanges(method, data) { + // const pendingPrivilage = runtimeSendMessage({method, cleanData(method, data)}); // const affectsAll = !msg.affects || msg.affects.all; // const affectsOwnOriginOnly = // !affectsAll && (msg.affects.editor || msg.affects.manager); @@ -268,45 +346,47 @@ const styleManager = (() => { // sendMessage(msg, ignoreChromeError); // } // notify tabs - if (affectsTabs || affectsIcon) { - const notifyTab = tab => { - if (!styleUpdated - && (affectsTabs || URLS.optionsUI.includes(tab.url)) + // if (affectsTabs || affectsIcon) { + // const notifyTab = tab => { + // if (!styleUpdated + // && (affectsTabs || URLS.optionsUI.includes(tab.url)) // 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 - && (!FIREFOX || tab.width)) { - msg.tabId = tab.id; - sendMessage(msg, ignoreChromeError); - } - if (affectsIcon) { + // && (!FIREFOX || tab.width)) { + // msg.tabId = tab.id; + // sendMessage(msg, ignoreChromeError); + // } + // if (affectsIcon) { // eslint-disable-next-line no-use-before-define // debounce(API.updateIcon, 0, {tab}); - } - }; + // } + // }; // list all tabs including chrome-extension:// which can be ours - Promise.all([ - queryTabs(isExtensionStyle(data.id) ? {url: URLS.ownOrigin + '*'} : {}), - getActiveTab(), - ]).then(([tabs, activeTab]) => { - const activeTabId = activeTab && activeTab.id; - for (const tab of tabs) { - invokeOrPostpone(tab.id === activeTabId, notifyTab, tab); - } - }); - } + // Promise.all([ + // queryTabs(isExtensionStyle(data.id) ? {url: URLS.ownOrigin + '*'} : {}), + // getActiveTab(), + // ]).then(([tabs, activeTab]) => { + // const activeTabId = activeTab && activeTab.id; + // for (const tab of tabs) { + // invokeOrPostpone(tab.id === activeTabId, notifyTab, tab); + // } + // }); + // } // notify self: the message no longer is sent to the origin in new Chrome - if (typeof onRuntimeMessage !== 'undefined') { - onRuntimeMessage(originalMessage); - } + // if (typeof onRuntimeMessage !== 'undefined') { + // onRuntimeMessage(originalMessage); + // } // notify apply.js on own pages - if (typeof applyOnMessage !== 'undefined') { - applyOnMessage(originalMessage); - } + // if (typeof applyOnMessage !== 'undefined') { + // applyOnMessage(originalMessage); + // } // propagate saved style state/code efficiently - if (styleUpdated) { - msg.refreshOwnTabs = false; - API.refreshAllTabs(msg); - } - } + // if (styleUpdated) { + // msg.refreshOwnTabs = false; + // API.refreshAllTabs(msg); + // } + // } })(); + +function notifyAllTabs() {} diff --git a/content/api.js b/content/api.js index 3fe85d68..fa87f720 100644 --- a/content/api.js +++ b/content/api.js @@ -2,8 +2,10 @@ 'use strict'; const API = (() => { - const preparing = promisify(chrome.runtime.getBackgroundPage.bind(chrome.runtime))() - .catch(() => null); + const preparing = chrome.runtime.getBackgroundPage ? + promisify(chrome.runtime.getBackgroundPage.bind(chrome.runtime))() + .catch(() => null) : + Promise.resolve(null); const runtimeSendMessage = promisify(chrome.runtime.sendMessage.bind(chrome.runtime)); return new Proxy(() => {}, { get: (target, name) => diff --git a/content/apply.js b/content/apply.js index 8c07f685..45d44e06 100644 --- a/content/apply.js +++ b/content/apply.js @@ -45,6 +45,14 @@ API.styleViaAPI({action: 'styleApply'}); return; } + // FIXME: options? + // FIXME: getStylesFallback? + API.getSectionsByUrl(getMatchUrl()) + .then(buildSections) + .then(callback); + } + + function getMatchUrl() { var matchUrl = location.href; if (!matchUrl.match(/^(http|file|chrome|ftp)/)) { // dynamic about: and javascript: iframes don't have an URL yet @@ -55,15 +63,11 @@ } } catch (e) {} } - // const request = Object.assign({ - // method: 'getStylesForFrame', - // asHash: true, - // matchUrl, - // }, options); - // FIXME: options? - // FIXME: getStylesFallback? - API.getSectionsByUrl(matchUrl) - .then(callback); + return matchUrl; + } + + function buildSections(result) { + return Object.entries(result).map(([id, code]) => ({id: +id, code})); } /** @@ -122,7 +126,9 @@ } if (request.style.enabled) { 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 { removeStyle(request.style); } @@ -130,7 +136,9 @@ case 'styleAdded': if (request.style.enabled) { - API.getSectionsById(request.style.id).then(applyStyles); + API.getSectionsByUrl(getMatchUrl(), request.style.id) + .then(buildSections) + .then(applyStyles); } break; @@ -195,7 +203,9 @@ addStyleElement(inCache); disabledElements.delete(id); } else { - API.getSectionsById(id).then(applyStyles); + API.getSectionsByUrl(getMatchUrl(), id) + .then(buildSections) + .then(applyStyles); } } else { if (inDoc) { diff --git a/content/install-hook-openusercss.js b/content/install-hook-openusercss.js index e9699073..93d709b5 100644 --- a/content/install-hook-openusercss.js +++ b/content/install-hook-openusercss.js @@ -33,11 +33,10 @@ && event.data.type === 'ouc-is-installed' && allowedOrigins.includes(event.origin) ) { - chrome.runtime.sendMessage({ - method: 'findUsercss', + API.findUsercss({ name: event.data.name, namespace: event.data.namespace - }, style => { + }).then(style => { const data = {event}; const callbackObject = { installed: Boolean(style), @@ -129,12 +128,11 @@ && event.data.type === 'ouc-install-usercss' && allowedOrigins.includes(event.origin) ) { - chrome.runtime.sendMessage({ - method: 'saveUsercss', + API.saveUsercss({ reason: 'install', name: event.data.title, sourceCode: event.data.code, - }, style => { + }).then(style => { sendInstallCallback({ enabled: style.enabled, key: event.data.key diff --git a/content/install-hook-usercss.js b/content/install-hook-usercss.js index 4a4d8f9d..9c42f5b9 100644 --- a/content/install-hook-usercss.js +++ b/content/install-hook-usercss.js @@ -16,8 +16,8 @@ let sourceCode, port, timer; chrome.runtime.onConnect.addListener(onConnected); - chrome.runtime.sendMessage({method: 'installUsercss', url}, r => - r && r.__ERROR__ && alert(r.__ERROR__)); + API.installUsercss({url}) + .catch(err => alert(err)); function onConnected(newPort) { port = newPort; diff --git a/content/install-hook-userstyles.js b/content/install-hook-userstyles.js index d26a88af..40097b3d 100644 --- a/content/install-hook-userstyles.js +++ b/content/install-hook-userstyles.js @@ -30,10 +30,9 @@ gotBody = true; // TODO: remove the following statement when USO pagination title is fixed document.title = document.title.replace(/^(\d+)&\w+=/, '#$1: '); - chrome.runtime.sendMessage({ - method: 'getStyles', + API.getStylesInfo({ md5Url: getMeta('stylish-md5-url') || location.href - }, checkUpdatability); + }).then(checkUpdatability); } if (document.getElementById('install_button')) { onDOMready().then(() => { @@ -148,10 +147,9 @@ function onUpdate() { return new Promise((resolve, reject) => { - chrome.runtime.sendMessage({ - method: 'getStyles', - md5Url: getMeta('stylish-md5-url') || location.href, - }, ([style]) => { + API.getStylesInfo({ + md5Url: getMeta('stylish-md5-url') || location.href + }).then(([style]) => { saveStyleCode('styleUpdate', style.name, {id: style.id}) .then(resolve, reject); }); @@ -160,36 +158,27 @@ function saveStyleCode(message, name, addProps) { - return new Promise((resolve, reject) => { - const isNew = message === 'styleInstall'; - const needsConfirmation = isNew || !saveStyleCode.confirmed; - if (needsConfirmation && !confirm(chrome.i18n.getMessage(message, [name]))) { - reject(); + const isNew = message === 'styleInstall'; + const needsConfirmation = isNew || !saveStyleCode.confirmed; + if (needsConfirmation && !confirm(chrome.i18n.getMessage(message, [name]))) { + return Promise.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; } - saveStyleCode.confirmed = true; - enableUpdateButton(false); - getStyleJson().then(json => { - if (!json) { - prompt(chrome.i18n.getMessage('styleInstallFailed', ''), - 'https://github.com/openstyles/stylus/issues/195'); - 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'}); - } + return API.installStyle(Object.assign(json, addProps)) + .then(style => { + if (!isNew && style.updateUrl.includes('?')) { + enableUpdateButton(true); + } else { + sendEvent({type: 'styleInstalledChrome'}); } - ); - resolve(); - }); + }); }); function enableUpdateButton(state) { @@ -220,13 +209,12 @@ if (url.startsWith('#')) { resolve(document.getElementById(url.slice(1)).textContent); } else { - chrome.runtime.sendMessage(Object.assign({ + API.download(Object.assign({ url, - method: 'download', timeout: 60e3, // USO can't handle POST requests for style json body: null, - }, options), result => { + }, options)).then(result => { const error = result && result.__ERROR__; if (error) { alert('Error' + (error ? '\n' + error : '')); @@ -249,12 +237,12 @@ if (codeElement && !codeElement.textContent.trim()) { return style; } - return getResource(getMeta('stylish-update-url')).then(code => new Promise(resolve => { - chrome.runtime.sendMessage({method: 'parseCss', code}, ({sections}) => { - style.sections = sections; - resolve(style); + return getResource(getMeta('stylish-update-url')) + .then(code => API.parseCss({code})) + .then(result => { + style.sections = result.sections; + return style; }); - })); }) .catch(() => null); } diff --git a/edit.html b/edit.html index fc46e07b..2387fefb 100644 --- a/edit.html +++ b/edit.html @@ -18,6 +18,7 @@ } + @@ -25,6 +26,7 @@ + diff --git a/edit/edit.js b/edit/edit.js index 3073b811..5b307aa8 100644 --- a/edit/edit.js +++ b/edit/edit.js @@ -165,7 +165,7 @@ function onRuntimeMessage(request) { // code-less style from notifyAllTabs const {sections, id} = request.style; ((sections && sections[0] || {}).code === null - ? API.getStyles({id}) + ? API.getStyleFromDB(id) : Promise.resolve([request.style]) ).then(([style]) => { if (isUsercss(style)) { @@ -372,11 +372,10 @@ function save() { return; } - API.saveStyle({ + API.editSave({ id: styleId, name: $('#name').value.trim(), enabled: $('#enabled').checked, - reason: 'editSave', sections: getSectionsHashes(), exclusions: exclusions.get() }) diff --git a/js/messaging.js b/js/messaging.js index 1f594fab..8b5fa2ba 100644 --- a/js/messaging.js +++ b/js/messaging.js @@ -264,7 +264,6 @@ function openURL({ index, active, currentWindow = true, - message, }) { url = url.includes('://') ? url : chrome.runtime.getURL(url); // [some] chromium forks don't handle their fake branded protocols @@ -280,15 +279,7 @@ function openURL({ url.replace(/%2F.*/, '*').replace(/#.*/, '') : url.replace(/#.*/, ''); - const task = 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); - }); - } + return queryTabs({url: urlQuery, currentWindow}).then(maybeSwitch); function maybeSwitch(tabs = []) { const urlWithSlash = url + '/'; diff --git a/manage/import-export.js b/manage/import-export.js index 935f5901..a1dc3f23 100644 --- a/manage/import-export.js +++ b/manage/import-export.js @@ -58,7 +58,7 @@ function importFromFile({fileTypeFilter, file} = {}) { function importFromString(jsonString, oldStyles) { if (!oldStyles) { - return API.getStyles().then(styles => importFromString(jsonString, styles)); + return API.getStylesInfo().then(styles => importFromString(jsonString, styles)); } const json = tryJSONparse(jsonString) || []; if (typeof json.slice !== 'function') { @@ -93,8 +93,9 @@ function importFromString(jsonString, oldStyles) { const info = analyze(item); if (info) { // using saveStyle directly since json was parsed in background page context - return API.saveStyle(Object.assign(item, SAVE_OPTIONS)) - .then(style => account({style, info, resolve})); + // FIXME: rewrite importStyle + // return API.saveStyle(Object.assign(item, SAVE_OPTIONS)) + // .then(style => account({style, info, resolve})); } } renderQueue.forEach(style => handleUpdate(style, {reason: 'import'})); @@ -224,12 +225,13 @@ function importFromString(jsonString, oldStyles) { let tasks = Promise.resolve(); let tasksUI = Promise.resolve(); for (const id of newIds) { - tasks = tasks.then(() => API.deleteStyle({id, notify: false})); + tasks = tasks.then(() => API.deleteStyle(id)); tasksUI = tasksUI.then(() => handleDelete(id)); const oldStyle = oldStylesById.get(id); if (oldStyle) { 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'})); } } @@ -274,7 +276,7 @@ function importFromString(jsonString, oldStyles) { $('#file-all-styles').onclick = () => { - API.getStyles().then(styles => { + API.getAllStyles().then(styles => { // https://crbug.com/714373 document.documentElement.appendChild( $create('iframe', { diff --git a/manage/manage.js b/manage/manage.js index 0430c371..004398fa 100644 --- a/manage/manage.js +++ b/manage/manage.js @@ -431,7 +431,7 @@ Object.assign(handleEvent, { }) .then(({button}) => { 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'); if (changed.enabled || (missingFavicons && !createStyleElement.parts)) { installed.textContent = ''; - API.getStyles().then(showStyles); + API.getStylesInfo().then(showStyles); return; } if (changed.targets) { @@ -670,7 +670,9 @@ function onVisibilityChange() { // assuming other changes aren't important enough to justify making a complicated DOM sync case 'visible': if (sessionStorage.justEditedStyleId) { - API.getStyles({id: sessionStorage.justEditedStyleId}).then(([style]) => { + API.getStylesInfo({ + id: sessionStorage.justEditedStyleId + }).then(([style]) => { handleUpdate(style, {method: 'styleUpdated'}); }); delete sessionStorage.justEditedStyleId; diff --git a/manifest.json b/manifest.json index ced9f3a0..3062e02e 100644 --- a/manifest.json +++ b/manifest.json @@ -67,13 +67,13 @@ "matches": ["http://userstyles.org/*", "https://userstyles.org/*"], "run_at": "document_start", "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/*"], "run_at": "document_start", "all_frames": false, - "js": ["content/install-hook-openusercss.js"] + "js": ["js/promisify.js", "content/api.js", "content/install-hook-openusercss.js"] }, { "matches": [ @@ -97,7 +97,7 @@ ], "run_at": "document_idle", "all_frames": false, - "js": ["content/install-hook-usercss.js"] + "js": ["js/promisify.js", "content/api.js", "content/install-hook-usercss.js"] } ], "browser_action": { diff --git a/popup.html b/popup.html index 4a1a2695..1ac9f685 100644 --- a/popup.html +++ b/popup.html @@ -155,6 +155,8 @@ + + diff --git a/popup/hotkeys.js b/popup/hotkeys.js index b04fda72..eccb0a35 100644 --- a/popup/hotkeys.js +++ b/popup/hotkeys.js @@ -101,15 +101,13 @@ var hotkeys = (() => { entry = typeof entry === 'string' ? $('#' + entry) : entry; if (!match && $('.checker', entry).checked !== enable || entry.classList.contains(match)) { results.push(entry.id); - task = task.then(() => API.saveStyle({ - id: entry.styleId, - enabled: enable, - notify: false, - })).then(() => { - entry.classList.toggle('enabled', enable); - entry.classList.toggle('disabled', !enable); - $('.checker', entry).checked = enable; - }); + task = task + .then(() => API.toggleStyle(entry.styleId, enable)) + .then(() => { + entry.classList.toggle('enabled', enable); + entry.classList.toggle('disabled', !enable); + $('.checker', entry).checked = enable; + }); } } if (results.length) task.then(API.refreshAllTabs); diff --git a/popup/popup.js b/popup/popup.js index 22d9efaa..c999ba28 100644 --- a/popup/popup.js +++ b/popup/popup.js @@ -1,6 +1,6 @@ /* global configDialog hotkeys -global popupExclusions +global popupExclusions promisify onTabReady */ 'use strict'; @@ -20,10 +20,7 @@ getActiveTab().then(tab => : getTabRealURL(tab) ).then(url => Promise.all([ (tabURL = URLS.supported(url) ? url : '') && - API.getStyles({ - matchUrl: tabURL, - omitCode: !BG, - }), + API.getStylesInfoForUrl(tabURL), onDOMready().then(initPopup), ])).then(([styles]) => { showStyles(styles); @@ -115,7 +112,8 @@ function initPopup() { } 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) { return; } @@ -233,18 +231,19 @@ function showStyles(styles) { installed.appendChild(container); setTimeout(detectSloppyRegexps, 100, styles); - API.getStyles({ - matchUrl: tabURL, - strictRegexp: false, - omitCode: true, - }).then(unscreenedStyles => { - for (const style of unscreenedStyles) { - if (!styles.find(({id}) => id === style.id)) { - createStyleElement({style, check: true}); - } - } - window.dispatchEvent(new Event('showStyles:done')); - }); + // FIXME: detect sloppy regexp? + // API.getStyles({ + // matchUrl: tabURL, + // strictRegexp: false, + // omitCode: true, + // }).then(unscreenedStyles => { + // for (const style of unscreenedStyles) { + // if (!styles.find(({id}) => id === style.id)) { + // createStyleElement({style, check: true}); + // } + // } + window.dispatchEvent(new Event('showStyles:done')); + // }); } @@ -347,10 +346,10 @@ Object.assign(handleEvent, { toggle(event) { // when fired on checkbox, prevent the parent label from seeing the event, see #501 event.stopPropagation(); - API.saveStyle({ - id: handleEvent.getClickedStyleId(event), - enabled: this.matches('.enable') || this.checked, - }); + API.toggleStyle( + handleEvent.getClickedStyleId(event), + this.matches('.enable') || this.checked + ); }, delete(event) { @@ -377,14 +376,14 @@ Object.assign(handleEvent, { className: 'lights-on', onComplete: () => (box.dataset.display = false), }); - if (ok) API.deleteStyle({id}); + if (ok) API.deleteStyle(id); } }, configure(event) { const {styleId, styleIsUsercss} = handleEvent.getClickedStyleElement(event); if (styleIsUsercss) { - API.getStyles({id: styleId}).then(([style]) => { + API.getStylesInfo({id: styleId}).then(([style]) => { hotkeys.setState(false); configDialog(style).then(() => { hotkeys.setState(true); @@ -452,12 +451,19 @@ Object.assign(handleEvent, { openURLandHide(event) { event.preventDefault(); + const message = tryJSONparse(this.dataset.sendMessage); getActiveTab() .then(activeTab => API.openURL({ url: this.href || this.dataset.href, - index: activeTab.index + 1, - message: tryJSONparse(this.dataset.sendMessage), + index: activeTab.index + 1 })) + .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); }, @@ -495,17 +501,18 @@ function handleUpdate(style) { } if (!tabURL) return; // Add an entry when a new style for the current url is installed - API.getStyles({ - matchUrl: tabURL, - stopOnFirst: true, - omitCode: true, - }).then(([style]) => { - if (style) { - document.body.classList.remove('blocked'); - $$.remove('.blocked-info, #no-styles'); - createStyleElement({style, check: true}); - } - }); + // FIXME: what does this do? + // API.getStyles({ + // matchUrl: tabURL, + // stopOnFirst: true, + // omitCode: true, + // }).then(([style]) => { + // if (style) { + // document.body.classList.remove('blocked'); + // $$.remove('.blocked-info, #no-styles'); + // createStyleElement({style, check: true}); + // } + // }); } diff --git a/popup/search-results.js b/popup/search-results.js index 0a7b489b..6b18d255 100755 --- a/popup/search-results.js +++ b/popup/search-results.js @@ -287,7 +287,7 @@ window.addEventListener('showStyles:done', function _() { return; } const md5Url = UPDATE_URL.replace('%', result.id); - API.getStyles({md5Url}).then(([installedStyle]) => { + API.countStyles({md5Url}).then(installedStyle => { if (installedStyle) { totalResults = Math.max(0, totalResults - 1); } else { @@ -529,7 +529,7 @@ window.addEventListener('showStyles:done', function _() { event.stopPropagation(); const entry = this.closest('.search-result'); saveScrollPosition(entry); - API.deleteStyle({id: entry._result.installedStyleId}) + API.deleteStyle(entry._result.installedStyleId) .then(restoreScrollPosition); }