make manager load real fast
This commit is contained in:
parent
bc6c9c826a
commit
d1b9338707
|
@ -23,11 +23,11 @@
|
|||
<script src="js/polyfill.js"></script>
|
||||
<script src="js/dom.js"></script>
|
||||
<script src="js/messaging.js"></script>
|
||||
<script src="js/msg.js"></script>
|
||||
<script src="js/prefs.js"></script>
|
||||
<script src="js/localization.js"></script>
|
||||
<script src="js/script-loader.js"></script>
|
||||
<script src="js/storage-util.js"></script>
|
||||
<script src="js/msg.js"></script>
|
||||
|
||||
<script src="content/style-injector.js"></script>
|
||||
<script src="content/apply.js"></script>
|
||||
|
|
|
@ -33,7 +33,8 @@ self.msg = self.INJECTED === 1 ? self.msg : (() => {
|
|||
onExtension,
|
||||
off,
|
||||
RX_NO_RECEIVER,
|
||||
RX_PORT_CLOSED
|
||||
RX_PORT_CLOSED,
|
||||
isBg,
|
||||
};
|
||||
|
||||
function getBg() {
|
||||
|
|
15
js/prefs.js
15
js/prefs.js
|
@ -1,6 +1,8 @@
|
|||
/* global promisifyChrome */
|
||||
/* global promisifyChrome msg API */
|
||||
'use strict';
|
||||
|
||||
// Needs msg.js loaded first
|
||||
|
||||
self.prefs = self.INJECTED === 1 ? self.prefs : (() => {
|
||||
const defaults = {
|
||||
'openEditInWindow': false, // new editor opens in a own browser window
|
||||
|
@ -112,12 +114,11 @@ self.prefs = self.INJECTED === 1 ? self.prefs : (() => {
|
|||
'storage.sync': ['get', 'set'],
|
||||
});
|
||||
|
||||
const initializing = browser.storage.sync.get('settings')
|
||||
.then(result => {
|
||||
if (result.settings) {
|
||||
setAll(result.settings, true);
|
||||
}
|
||||
});
|
||||
const initializing = (
|
||||
msg.isBg
|
||||
? browser.storage.sync.get('settings').then(res => res.settings)
|
||||
: API.getPrefs()
|
||||
).then(res => res && setAll(res, true));
|
||||
|
||||
chrome.storage.onChanged.addListener((changes, area) => {
|
||||
if (area !== 'sync' || !changes.settings || !changes.settings.newValue) {
|
||||
|
|
|
@ -48,73 +48,3 @@ const loadScript = (() => {
|
|||
));
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
(() => {
|
||||
let subscribers, observer;
|
||||
// natively declared <script> elements in html can't have onload= attribute
|
||||
// due to the default extension CSP that forbids inline code (and we don't want to relax it),
|
||||
// so we're using MutationObserver to add onload event listener to the script element to be loaded
|
||||
window.onDOMscriptReady = (srcSuffix, timeout = 1000) => {
|
||||
if (!subscribers) {
|
||||
subscribers = new Map();
|
||||
observer = new MutationObserver(observe);
|
||||
observer.observe(document.head, {childList: true});
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const listeners = subscribers.get(srcSuffix);
|
||||
if (listeners) {
|
||||
listeners.push(resolve);
|
||||
} else {
|
||||
subscribers.set(srcSuffix, [resolve]);
|
||||
}
|
||||
// a resolved Promise won't reject anymore
|
||||
setTimeout(() => {
|
||||
emptyAfterCleanup(srcSuffix);
|
||||
reject(new Error('Timeout'));
|
||||
}, timeout);
|
||||
});
|
||||
};
|
||||
|
||||
return;
|
||||
|
||||
function observe(mutations) {
|
||||
for (const {addedNodes} of mutations) {
|
||||
for (const n of addedNodes) {
|
||||
if (n.src && getSubscribersForSrc(n.src)) {
|
||||
n.addEventListener('load', notifySubscribers, {once: true});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSubscribersForSrc(src) {
|
||||
for (const [suffix, listeners] of subscribers.entries()) {
|
||||
if (src.endsWith(suffix)) {
|
||||
return {suffix, listeners};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function notifySubscribers(event) {
|
||||
for (let data; (data = getSubscribersForSrc(this.src));) {
|
||||
data.listeners.forEach(fn => fn(event));
|
||||
if (emptyAfterCleanup(data.suffix)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emptyAfterCleanup(suffix) {
|
||||
if (!subscribers) {
|
||||
return true;
|
||||
}
|
||||
subscribers.delete(suffix);
|
||||
if (!subscribers.size) {
|
||||
observer.disconnect();
|
||||
observer = null;
|
||||
subscribers = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -149,8 +149,8 @@
|
|||
<script src="js/polyfill.js"></script>
|
||||
<script src="js/dom.js"></script>
|
||||
<script src="js/messaging.js"></script>
|
||||
<script src="js/prefs.js"></script>
|
||||
<script src="js/msg.js"></script>
|
||||
<script src="js/prefs.js"></script>
|
||||
<script src="js/router.js"></script>
|
||||
<script src="content/style-injector.js"></script>
|
||||
<script src="content/apply.js"></script>
|
||||
|
|
|
@ -14,7 +14,7 @@ let initialized = false;
|
|||
router.watch({search: ['search']}, ([search]) => {
|
||||
$('#search').value = search || '';
|
||||
if (!initialized) {
|
||||
init();
|
||||
initFilters();
|
||||
initialized = true;
|
||||
} else {
|
||||
searchStyles();
|
||||
|
@ -36,7 +36,7 @@ HTMLSelectElement.prototype.adjustWidth = function () {
|
|||
parent.replaceChild(this, singleSelect);
|
||||
};
|
||||
|
||||
function init() {
|
||||
function initFilters() {
|
||||
$('#search').oninput = e => {
|
||||
router.updateSearch('search', e.target.value);
|
||||
};
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
/* global messageBox styleSectionsEqual API onDOMready
|
||||
tryJSONparse scrollElementIntoView $ $$ API $create t animateElement
|
||||
styleJSONseemsValid */
|
||||
/* exported bulkChangeQueue bulkChangeTime */
|
||||
styleJSONseemsValid bulkChangeQueue */
|
||||
'use strict';
|
||||
|
||||
const STYLISH_DUMP_FILE_EXT = '.txt';
|
||||
const STYLUS_BACKUP_FILE_EXT = '.json';
|
||||
|
||||
let bulkChangeQueue = [];
|
||||
let bulkChangeTime = 0;
|
||||
|
||||
onDOMready().then(() => {
|
||||
$('#file-all-styles').onclick = () => exportToFile();
|
||||
$('#unfile-all-styles').onclick = () => importFromFile({fileTypeFilter: STYLUS_BACKUP_FILE_EXT});
|
||||
|
@ -135,7 +131,7 @@ function importFromString(jsonString) {
|
|||
}
|
||||
});
|
||||
bulkChangeQueue.length = 0;
|
||||
bulkChangeTime = performance.now();
|
||||
bulkChangeQueue.time = performance.now();
|
||||
return API.importManyStyles(items.map(i => i.item))
|
||||
.then(styles => {
|
||||
for (let i = 0; i < styles.length; i++) {
|
||||
|
|
119
manage/manage.js
119
manage/manage.js
|
@ -4,11 +4,10 @@ global messageBox getStyleWithNoCode
|
|||
checkUpdate handleUpdateInstalled
|
||||
objectDiff
|
||||
configDialog
|
||||
sorter msg prefs API onDOMready $ $$ $create template setupLivePrefs
|
||||
sorter msg prefs API $ $$ $create template setupLivePrefs
|
||||
t tWordBreak formatDate
|
||||
getOwnTab getActiveTab openURL animateElement sessionStorageHash debounce
|
||||
scrollElementIntoView CHROME VIVALDI router
|
||||
bulkChangeTime:true bulkChangeQueue
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
|
@ -18,6 +17,8 @@ const ENTRY_ID_PREFIX_RAW = 'style-';
|
|||
const ENTRY_ID_PREFIX = '#' + ENTRY_ID_PREFIX_RAW;
|
||||
|
||||
const BULK_THROTTLE_MS = 100;
|
||||
const bulkChangeQueue = [];
|
||||
bulkChangeQueue.time = 0;
|
||||
|
||||
// define pref-mapped ids separately
|
||||
const newUI = {
|
||||
|
@ -49,46 +50,10 @@ Promise.all([
|
|||
API.getAllStyles(true),
|
||||
// FIXME: integrate this into filter.js
|
||||
router.getSearch('search') && API.searchDB({query: router.getSearch('search')}),
|
||||
Promise.all([
|
||||
onDOMready(),
|
||||
prefs.initializing,
|
||||
])
|
||||
.then(() => {
|
||||
initGlobalEvents();
|
||||
if (!VIVALDI) {
|
||||
$$('#header select').forEach(el => el.adjustWidth());
|
||||
}
|
||||
}),
|
||||
]).then(args => {
|
||||
showStyles(...args);
|
||||
});
|
||||
|
||||
msg.onExtension(onRuntimeMessage);
|
||||
|
||||
function onRuntimeMessage(msg) {
|
||||
switch (msg.method) {
|
||||
case 'styleUpdated':
|
||||
case 'styleAdded':
|
||||
case 'styleDeleted':
|
||||
bulkChangeQueue.push(msg);
|
||||
if (performance.now() - bulkChangeTime < BULK_THROTTLE_MS) {
|
||||
debounce(handleBulkChange, BULK_THROTTLE_MS);
|
||||
} else {
|
||||
handleBulkChange();
|
||||
}
|
||||
break;
|
||||
case 'styleApply':
|
||||
case 'styleReplaceAll':
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
setTimeout(sorter.updateStripes, 0, {onlyWhenColumnsChanged: true});
|
||||
}
|
||||
|
||||
|
||||
function initGlobalEvents() {
|
||||
installed = $('#installed');
|
||||
waitForSelector('#installed'), // needed to avoid flicker due to an extra frame and layout shift
|
||||
prefs.initializing
|
||||
]).then(([styles, ids, el]) => {
|
||||
installed = el;
|
||||
installed.onclick = handleEvent.entryClicked;
|
||||
$('#manage-options-button').onclick = () => router.updateHash('#stylus-options');
|
||||
$('#sync-styles').onclick = () => router.updateHash('#stylus-options');
|
||||
|
@ -96,31 +61,12 @@ function initGlobalEvents() {
|
|||
// show date installed & last update on hover
|
||||
installed.addEventListener('mouseover', handleEvent.lazyAddEntryTitle);
|
||||
installed.addEventListener('mouseout', handleEvent.lazyAddEntryTitle);
|
||||
|
||||
document.addEventListener('visibilitychange', onVisibilityChange);
|
||||
|
||||
$$('[data-toggle-on-click]').forEach(el => {
|
||||
// dataset on SVG doesn't work in Chrome 49-??, works in 57+
|
||||
const target = $(el.getAttribute('data-toggle-on-click'));
|
||||
el.onclick = event => {
|
||||
event.preventDefault();
|
||||
target.classList.toggle('hidden');
|
||||
if (target.classList.contains('hidden')) {
|
||||
el.removeAttribute('open');
|
||||
} else {
|
||||
el.setAttribute('open', '');
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// N.B. triggers existing onchange listeners
|
||||
setupLivePrefs();
|
||||
sorter.init();
|
||||
|
||||
prefs.subscribe(newUI.ids.map(newUI.prefKeyForId), () => switchUI());
|
||||
|
||||
switchUI({styleOnly: true});
|
||||
|
||||
// translate CSS manually
|
||||
document.head.appendChild($create('style', `
|
||||
.disabled h2::after {
|
||||
|
@ -133,6 +79,39 @@ function initGlobalEvents() {
|
|||
content: "${t('filteredStylesAllHidden')}";
|
||||
}
|
||||
`));
|
||||
if (!VIVALDI) {
|
||||
$$('#header select').forEach(el => el.adjustWidth());
|
||||
}
|
||||
if (CHROME >= 80 && CHROME <= 88) {
|
||||
// Wrong checkboxes are randomly checked after going back in history, https://crbug.com/1138598
|
||||
addEventListener('pagehide', () => {
|
||||
$$('input[type=checkbox]').forEach((el, i) => (el.name = `bug${i}`));
|
||||
});
|
||||
}
|
||||
showStyles(styles, ids);
|
||||
});
|
||||
|
||||
msg.onExtension(onRuntimeMessage);
|
||||
|
||||
function onRuntimeMessage(msg) {
|
||||
switch (msg.method) {
|
||||
case 'styleUpdated':
|
||||
case 'styleAdded':
|
||||
case 'styleDeleted':
|
||||
bulkChangeQueue.push(msg);
|
||||
if (performance.now() - bulkChangeQueue.time < BULK_THROTTLE_MS) {
|
||||
debounce(handleBulkChange, BULK_THROTTLE_MS);
|
||||
} else {
|
||||
handleBulkChange();
|
||||
}
|
||||
break;
|
||||
case 'styleApply':
|
||||
case 'styleReplaceAll':
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
setTimeout(sorter.updateStripes, 0, {onlyWhenColumnsChanged: true});
|
||||
}
|
||||
|
||||
function showStyles(styles = [], matchUrlIds) {
|
||||
|
@ -538,7 +517,7 @@ function handleBulkChange() {
|
|||
const {id} = msg.style;
|
||||
if (msg.method === 'styleDeleted') {
|
||||
handleDelete(id);
|
||||
bulkChangeTime = performance.now();
|
||||
bulkChangeQueue.time = performance.now();
|
||||
} else {
|
||||
handleUpdateForId(id, msg);
|
||||
}
|
||||
|
@ -549,7 +528,7 @@ function handleBulkChange() {
|
|||
function handleUpdateForId(id, opts) {
|
||||
return API.getStyle(id, true).then(style => {
|
||||
handleUpdate(style, opts);
|
||||
bulkChangeTime = performance.now();
|
||||
bulkChangeQueue.time = performance.now();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -723,6 +702,20 @@ function highlightEditedStyle() {
|
|||
}
|
||||
}
|
||||
|
||||
function waitForSelector(selector) {
|
||||
// TODO: if used in other places, move to dom.js
|
||||
// TODO: if used concurrently, rework to use just one observer internally
|
||||
return new Promise(resolve => {
|
||||
const mo = new MutationObserver(() => {
|
||||
const el = $(selector);
|
||||
if (el) {
|
||||
mo.disconnect();
|
||||
resolve(el);
|
||||
}
|
||||
});
|
||||
mo.observe(document, {childList: true, subtree: true});
|
||||
});
|
||||
}
|
||||
|
||||
function embedOptions() {
|
||||
let options = $('#stylus-embedded-options');
|
||||
|
|
|
@ -180,8 +180,8 @@
|
|||
<script src="js/dom.js"></script>
|
||||
<script src="js/messaging.js"></script>
|
||||
<script src="js/localization.js"></script>
|
||||
<script src="js/prefs.js"></script>
|
||||
<script src="js/msg.js"></script>
|
||||
<script src="js/prefs.js"></script>
|
||||
<script src="content/style-injector.js"></script>
|
||||
<script src="content/apply.js"></script>
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user