Fix: various

This commit is contained in:
eight 2018-10-10 16:14:51 +08:00
parent 37e1f43f75
commit 6494985b50
12 changed files with 88 additions and 51 deletions

View File

@ -15,6 +15,7 @@ window.API_METHODS = Object.assign(window.API_METHODS || {}, {
deleteStyle: styleManager.deleteStyle, deleteStyle: styleManager.deleteStyle,
getStylesInfoByUrl: styleManager.getStylesInfoByUrl, getStylesInfoByUrl: styleManager.getStylesInfoByUrl,
installStyle: styleManager.installStyle, installStyle: styleManager.installStyle,
editSave: styleManager.editSave,
getStyleFromDB: id => getStyleFromDB: id =>
db.exec('get', id).then(event => event.target.result), db.exec('get', id).then(event => event.target.result),
@ -96,7 +97,10 @@ navigatorUtil.onUrlChange(({tabId, frameId}, type) => {
// styles would be updated when content script is injected. // styles would be updated when content script is injected.
return; return;
} }
msg.sendTab(tabId, {method: 'urlChanged'}, {frameId}); msg.sendTab(tabId, {method: 'urlChanged'}, {frameId})
.catch(err => {
console.warn(tabId, frameId, err);
});
}); });
if (FIREFOX) { if (FIREFOX) {

View File

@ -1,4 +1,4 @@
/* global API_METHODS filterStyles cachedStyles */ /* global API_METHODS styleManager */
'use strict'; 'use strict';
(() => { (() => {
@ -25,7 +25,8 @@
if (/^url:/i.test(query)) { if (/^url:/i.test(query)) {
matchUrl = query.slice(query.indexOf(':') + 1).trim(); matchUrl = query.slice(query.indexOf(':') + 1).trim();
if (matchUrl) { if (matchUrl) {
return filterStyles({matchUrl}).map(style => style.id); return styleManager.getStylesInfoByUrl(matchUrl)
.then(styles => styles.map(style => style.id));
} }
} }
if (query.startsWith('/') && /^\/(.+?)\/([gimsuy]*)$/.test(query)) { if (query.startsWith('/') && /^\/(.+?)\/([gimsuy]*)$/.test(query)) {
@ -44,14 +45,20 @@
} }
const results = []; const results = [];
for (const item of ids || cachedStyles.list) { return styleManager.getAllStyles(styles => {
const id = isNaN(item) ? item.id : item; if (ids) {
const idSet = new Set(ids);
return styles.filter(s => idSet.has(s.id));
}
return styles;
})
.then(styles => {
for (const style of styles) {
const id = style.id;
if (!query || words && !words.length) { if (!query || words && !words.length) {
results.push(id); results.push(id);
continue; continue;
} }
const style = isNaN(item) ? item : cachedStyles.byId.get(item);
if (!style) continue;
for (const part in PARTS) { for (const part in PARTS) {
const text = style[part]; const text = style[part];
if (text && PARTS[part](text, rx, words, icase)) { if (text && PARTS[part](text, rx, words, icase)) {
@ -63,6 +70,7 @@
if (cache.size) debounce(clearCache, 60e3); if (cache.size) debounce(clearCache, 60e3);
return results; return results;
});
}; };
function searchText(text, rx, words, icase) { function searchText(text, rx, words, icase) {

View File

@ -460,11 +460,15 @@
</div> </div>
</div> </div>
<section id="sections"> <section id="sections">
<h2><span id="sections-heading" i18n-text="styleSectionsTitle"></span> <!--
It seems that we don't use these anymore
https://github.com/openstyles/stylus/blob/5cbe8a8d780a6eb9fce11d5846e92bf244c3a3f3/edit/sections.js#L18
-->
<!-- <h2><span id="sections-heading" i18n-text="styleSectionsTitle"></span>
<a id="sections-help" href="#" class="svg-inline-wrapper" tabindex="0"> <a id="sections-help" href="#" class="svg-inline-wrapper" tabindex="0">
<svg class="svg-icon info"><use xlink:href="#svg-icon-help"/></svg> <svg class="svg-icon info"><use xlink:href="#svg-icon-help"/></svg>
</a> </a>
</h2> </h2> -->
</section> </section>
<div id="help-popup"> <div id="help-popup">
<div class="title"></div><svg id="sections-help" class="svg-icon dismiss"><use xlink:href="#svg-icon-close"/></svg> <div class="title"></div><svg id="sections-help" class="svg-icon dismiss"><use xlink:href="#svg-icon-close"/></svg>

View File

@ -1,7 +1,7 @@
/* global CodeMirror loadScript showHelp cmFactory */ /* global CodeMirror loadScript showHelp cmFactory */
'use strict'; 'use strict';
onDOMscriptReady('/colorview.js').then(() => { (() => {
onDOMready().then(() => { onDOMready().then(() => {
$('#colorpicker-settings').onclick = configureColorpicker; $('#colorpicker-settings').onclick = configureColorpicker;
}); });
@ -112,4 +112,4 @@ onDOMscriptReady('/colorview.js').then(() => {
} }
input.focus(); input.focus();
} }
}); })();

View File

@ -358,7 +358,8 @@ input:invalid {
} }
.section.removed .code-label, .section.removed .code-label,
.section.removed .applies-to, .section.removed .applies-to,
.section.removed .edit-actions { .section.removed .edit-actions,
.section.removed .CodeMirror {
display: none; display: none;
} }
.move-section-up:after { .move-section-up:after {

View File

@ -23,6 +23,7 @@ const CssToProperty = Object.entries(propertyToCss)
let editor; let editor;
document.addEventListener('visibilitychange', beforeUnload); document.addEventListener('visibilitychange', beforeUnload);
window.addEventListener('beforeunload', beforeUnload);
msg.onExtension(onRuntimeMessage); msg.onExtension(onRuntimeMessage);
preinit(); preinit();
@ -375,7 +376,7 @@ function onRuntimeMessage(request) {
* > Never add a beforeunload listener unconditionally or use it as an end-of-session signal. * > Never add a beforeunload listener unconditionally or use it as an end-of-session signal.
* > Only add it when a user has unsaved work, and remove it as soon as that work has been saved. * > Only add it when a user has unsaved work, and remove it as soon as that work has been saved.
*/ */
function beforeUnload() { function beforeUnload(e) {
if (saveSizeOnClose) rememberWindowSize(); if (saveSizeOnClose) rememberWindowSize();
const activeElement = document.activeElement; const activeElement = document.activeElement;
if (activeElement) { if (activeElement) {
@ -384,10 +385,14 @@ function beforeUnload() {
// refocus if unloading was canceled // refocus if unloading was canceled
setTimeout(() => activeElement.focus()); setTimeout(() => activeElement.focus());
} }
if (editor.isDirty()) { if (editor && editor.isDirty()) {
// neither confirm() nor custom messages work in modern browsers but just in case // neither confirm() nor custom messages work in modern browsers but just in case
if (e) {
e.returnValue = t('styleChangesNotSaved');
} else {
return t('styleChangesNotSaved'); return t('styleChangesNotSaved');
} }
}
} }
function isUsercss(style) { function isUsercss(style) {

View File

@ -10,7 +10,7 @@ function createLivePreview(preprocess) {
prefs.subscribe(['editor.livePreview'], (key, value) => { prefs.subscribe(['editor.livePreview'], (key, value) => {
if (value && data && data.id && data.enabled) { if (value && data && data.id && data.enabled) {
previewer = createPreviewer; previewer = createPreviewer();
previewer.update(data); previewer.update(data);
} }
if (!value && previewer) { if (!value && previewer) {

View File

@ -1,9 +1,9 @@
/* global dirtyReporter showToMozillaHelp /* global dirtyReporter showToMozillaHelp
showSectionHelp toggleContextMenuDelete setGlobalProgress maximizeCodeHeight showSectionHelp toggleContextMenuDelete setGlobalProgress maximizeCodeHeight
CodeMirror nextPrevEditorOnKeydown showAppliesToHelp propertyToCss CodeMirror nextPrevEditorOnKeydown showAppliesToHelp propertyToCss
regExpTester linter cssToProperty createLivePreview showCodeMirrorPopup regExpTester linter createLivePreview showCodeMirrorPopup
sectionsToMozFormat editorWorker messageBox clipString beautify sectionsToMozFormat editorWorker messageBox clipString beautify
rerouteHotkeys cmFactory rerouteHotkeys cmFactory CssToProperty
*/ */
'use strict'; 'use strict';
@ -76,7 +76,7 @@ function createResizeGrip(cm) {
function createSectionsEditor(style) { function createSectionsEditor(style) {
let INC_ID = 0; // an increment id that is used by various object to track the order let INC_ID = 0; // an increment id that is used by various object to track the order
const dirty = dirtyReporter(); const dirty = dirtyReporter();
dirty.onChange(() => updateTitle); dirty.onChange(updateTitle);
const container = $('#sections'); const container = $('#sections');
const sections = []; const sections = [];
@ -91,6 +91,7 @@ function createSectionsEditor(style) {
enabledEl.addEventListener('change', () => { enabledEl.addEventListener('change', () => {
dirty.modify('enabled', style.enabled, enabledEl.checked); dirty.modify('enabled', style.enabled, enabledEl.checked);
style.enabled = enabledEl.checked; style.enabled = enabledEl.checked;
updateLivePreview();
}); });
$('#to-mozilla').addEventListener('click', showMozillaFormat); $('#to-mozilla').addEventListener('click', showMozillaFormat);
@ -120,14 +121,13 @@ function createSectionsEditor(style) {
dirty.clear(); dirty.clear();
rerouteHotkeys(true); rerouteHotkeys(true);
resolve(); resolve();
updateHeader();
} }
})); }));
const livePreview = createLivePreview(); const livePreview = createLivePreview();
livePreview.show(Boolean(style.id)); livePreview.show(Boolean(style.id));
updateHeader();
return { return {
ready: () => initializing, ready: () => initializing,
replaceStyle, replaceStyle,
@ -137,7 +137,7 @@ function createSectionsEditor(style) {
scrollToEditor, scrollToEditor,
getStyleId: () => style.id, getStyleId: () => style.id,
getEditorTitle: cm => { getEditorTitle: cm => {
const index = sections.filter(s => !s.isRemoved()).findIndex(s => s.cm === cm) + 1; const index = sections.filter(s => !s.isRemoved()).findIndex(s => s.cm === cm);
return `${t('sectionCode')} ${index + 1}`; return `${t('sectionCode')} ${index + 1}`;
}, },
save: saveStyle, save: saveStyle,
@ -162,6 +162,7 @@ function createSectionsEditor(style) {
nearbyElement instanceof Node && nearbyElement instanceof Node &&
(nearbyElement.closest('#sections > .section') || {}).CodeMirror || (nearbyElement.closest('#sections > .section') || {}).CodeMirror ||
getLastActivatedEditor(); getLastActivatedEditor();
console.log(cm);
if (nearbyElement instanceof Node && cm) { if (nearbyElement instanceof Node && cm) {
const {left, top} = nearbyElement.getBoundingClientRect(); const {left, top} = nearbyElement.getBoundingClientRect();
const bounds = cm.display.wrapper.getBoundingClientRect(); const bounds = cm.display.wrapper.getBoundingClientRect();
@ -281,8 +282,9 @@ function createSectionsEditor(style) {
if (section.isRemoved()) { if (section.isRemoved()) {
continue; continue;
} }
if (!result || section.getLastActive() > result.getLastActive) { // .lastActive is initiated by codemirror-factory
result = section; if (!result || section.cm.lastActive > result.lastActive) {
result = section.cm;
} }
} }
return result; return result;
@ -431,11 +433,12 @@ function createSectionsEditor(style) {
sectionOrder = validSections.map(s => s.id).join(','); sectionOrder = validSections.map(s => s.id).join(',');
dirty.modify('sectionOrder', oldOrder, sectionOrder); dirty.modify('sectionOrder', oldOrder, sectionOrder);
container.dataset.sectionCount = validSections.length; container.dataset.sectionCount = validSections.length;
linter.refreshReport();
} }
function getModel() { function getModel() {
return Object.assign({}, style, { return Object.assign({}, style, {
sections: sections.map(s => s.getModel()) sections: sections.filter(s => !s.isRemoved()).map(s => s.getModel())
}); });
} }
@ -557,12 +560,13 @@ function createSectionsEditor(style) {
init = {code: '', urlPrefixes: ['http://example.com']}; init = {code: '', urlPrefixes: ['http://example.com']};
} }
const section = createSection(init); const section = createSection(init);
container.appendChild(section.el);
if (base) { if (base) {
const index = sections.indexOf(base); const index = sections.indexOf(base);
sections.splice(index, 0, section); sections.splice(index + 1, 0, section);
container.insertBefore(section.el, base.el.nextSibling);
} else { } else {
sections.push(section); sections.push(section);
container.appendChild(section.el);
} }
section.render(); section.render();
// maximizeCodeHeight(section.el); // maximizeCodeHeight(section.el);
@ -623,7 +627,6 @@ function createSectionsEditor(style) {
createResizeGrip(cm); createResizeGrip(cm);
linter.enableForEditor(cm); linter.enableForEditor(cm);
linter.refreshReport();
let lastActive = 0; let lastActive = 0;
@ -640,6 +643,7 @@ function createSectionsEditor(style) {
onChange, onChange,
off, off,
getLastActive: () => lastActive, getLastActive: () => lastActive,
appliesTo
}; };
return section; return section;
@ -665,7 +669,7 @@ function createSectionsEditor(style) {
if (apply.all) { if (apply.all) {
continue; continue;
} }
const key = cssToProperty(apply.getType()); const key = CssToProperty[apply.getType()];
if (!section[key]) { if (!section[key]) {
section[key] = []; section[key] = [];
} }
@ -767,7 +771,7 @@ function createSectionsEditor(style) {
const apply = createApply(init); const apply = createApply(init);
if (base) { if (base) {
const index = appliesTo.indexOf(base); const index = appliesTo.indexOf(base);
appliesTo.splice(index, 0, apply); appliesTo.splice(index + 1, 0, apply);
appliesToContainer.insertBefore(apply.el, base.el.nextSibling); appliesToContainer.insertBefore(apply.el, base.el.nextSibling);
} else { } else {
appliesTo.push(apply); appliesTo.push(apply);
@ -792,7 +796,7 @@ function createSectionsEditor(style) {
emitSectionChange(); emitSectionChange();
} }
function createApply({type, value, all}) { function createApply({type = 'url', value, all = false}) {
const applyId = INC_ID++; const applyId = INC_ID++;
const dirtyPrefix = `section.${sectionId}.apply.${applyId}`; const dirtyPrefix = `section.${sectionId}.apply.${applyId}`;
const el = all ? template.appliesToEverything.cloneNode(true) : const el = all ? template.appliesToEverything.cloneNode(true) :
@ -834,7 +838,8 @@ function createSectionsEditor(style) {
restore, restore,
el, el,
getType: () => type, getType: () => type,
getValue: () => value getValue: () => value,
valueEl
}; };
const removeButton = $('.remove-applies-to', el); const removeButton = $('.remove-applies-to', el);
@ -867,13 +872,13 @@ function createSectionsEditor(style) {
} }
} }
function replaceSections(sections) { function replaceSections(originalSections) {
for (const section of sections) { for (const section of sections) {
section.remove(true); section.remove(true);
} }
sections.length = 0; sections.length = 0;
container.textContent = ''; container.textContent = '';
return new Promise(resolve => initSection({sections, done: resolve})); return new Promise(resolve => initSection({sections: originalSections, done: resolve}));
} }
function replaceStyle(newStyle, codeIsUpdated) { function replaceStyle(newStyle, codeIsUpdated) {

View File

@ -21,7 +21,6 @@ function createSourceEditor(style) {
const dirty = dirtyReporter(); const dirty = dirtyReporter();
dirty.onChange(() => { dirty.onChange(() => {
const isDirty = dirty.isDirty(); const isDirty = dirty.isDirty();
window.onbeforeunload = isDirty ? beforeUnload : null;
document.body.classList.toggle('dirty', isDirty); document.body.classList.toggle('dirty', isDirty);
$('#save-button').disabled = !isDirty; $('#save-button').disabled = !isDirty;
updateTitle(); updateTitle();

View File

@ -11,8 +11,16 @@ function createCache(size = 1000) {
delete: delete_, delete: delete_,
clear, clear,
has: id => map.has(id), has: id => map.has(id),
entries: () => map.entries(), entries: function *() {
values: () => map.values(), for (const [id, item] of map) {
yield [id, item.data];
}
},
values: function *() {
for (const item of map.values()) {
yield item.data;
}
},
get size() { get size() {
return map.size; return map.size;
} }

View File

@ -100,7 +100,7 @@ const msg = (() => {
!tab.url.startsWith('chrome://newtab/') && !tab.url.startsWith('chrome://newtab/') &&
!isExtension || !isExtension ||
isExtension && ignoreExtension || isExtension && ignoreExtension ||
!filter(tab) filter && !filter(tab)
) { ) {
continue; continue;
} }

View File

@ -65,7 +65,10 @@ var loadScript = (() => {
subscribers.set(srcSuffix, [resolve]); subscribers.set(srcSuffix, [resolve]);
} }
// a resolved Promise won't reject anymore // a resolved Promise won't reject anymore
setTimeout(() => emptyAfterCleanup(srcSuffix) + reject(), timeout); setTimeout(() => {
emptyAfterCleanup(srcSuffix);
reject(new Error('Timeout'));
}, timeout);
}); });
}; };