Add: live-reload
This commit is contained in:
parent
04ebc837e2
commit
c2eadda708
|
@ -393,6 +393,10 @@
|
||||||
"message": "Install",
|
"message": "Install",
|
||||||
"description": "Label for install button"
|
"description": "Label for install button"
|
||||||
},
|
},
|
||||||
|
"installButtonInstalled": {
|
||||||
|
"message": "Installed",
|
||||||
|
"description": "Text displayed when the style is successfully installed"
|
||||||
|
},
|
||||||
"installButtonUpdate": {
|
"installButtonUpdate": {
|
||||||
"message": "Update",
|
"message": "Update",
|
||||||
"description": "Label for update button"
|
"description": "Label for update button"
|
||||||
|
|
|
@ -68,7 +68,10 @@ function createSourceLoader() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function initUsercssInstall() {
|
function initUsercssInstall() {
|
||||||
const pendingSource = createSourceLoader().load();
|
const sourceLoader = createSourceLoader();
|
||||||
|
const pendingSource = sourceLoader.load();
|
||||||
|
let watcher;
|
||||||
|
|
||||||
chrome.runtime.onConnect.addListener(port => {
|
chrome.runtime.onConnect.addListener(port => {
|
||||||
// FIXME: is this the correct way to reject a connection?
|
// FIXME: is this the correct way to reject a connection?
|
||||||
// https://developer.chrome.com/extensions/messaging#connect
|
// https://developer.chrome.com/extensions/messaging#connect
|
||||||
|
@ -83,6 +86,19 @@ function initUsercssInstall() {
|
||||||
port.postMessage({method: msg.method + 'Response', error: err.message || String(err)})
|
port.postMessage({method: msg.method + 'Response', error: err.message || String(err)})
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'liveReloadStart':
|
||||||
|
if (!watcher) {
|
||||||
|
watcher = sourceLoader.watch(sourceCode => {
|
||||||
|
port.postMessage({method: 'sourceCodeChanged', sourceCode});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
watcher.start();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'liveReloadStop':
|
||||||
|
watcher.stop();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -54,6 +54,10 @@
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<span></span>
|
<span></span>
|
||||||
</label>
|
</label>
|
||||||
|
<label class="live-reload">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span i18n-text="liveReloadLabel"></span>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<h1>
|
<h1>
|
||||||
<span class="meta-name"></span>
|
<span class="meta-name"></span>
|
||||||
|
|
|
@ -85,6 +85,18 @@ h1 small {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main > :first-child {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main > :last-child {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main .code,
|
.main .code,
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
const params = getParams();
|
const params = getParams();
|
||||||
|
let liveReload = false;
|
||||||
|
let installed = false;
|
||||||
|
|
||||||
const port = chrome.tabs.connect(
|
const port = chrome.tabs.connect(
|
||||||
Number(params.tabId),
|
Number(params.tabId),
|
||||||
|
@ -19,11 +21,104 @@
|
||||||
initSourceCode(msg.sourceCode);
|
initSourceCode(msg.sourceCode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'sourceCodeChanged':
|
||||||
|
if (msg.error) {
|
||||||
|
alert(msg.error);
|
||||||
|
} else {
|
||||||
|
liveReloadUpdate(msg.sourceCode);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
port.onDisconnect.addListener(closeCurrentTab);
|
port.onDisconnect.addListener(closeCurrentTab);
|
||||||
|
|
||||||
const cm = CodeMirror.fromTextArea($('.code textarea'), {readOnly: true});
|
const cm = CodeMirror.fromTextArea($('.code textarea'), {readOnly: true});
|
||||||
|
let liveReloadPending = Promise.resolve();
|
||||||
|
|
||||||
|
function liveReloadUpdate(sourceCode) {
|
||||||
|
liveReloadPending = liveReloadPending.then(() => {
|
||||||
|
const scrollInfo = cm.getScrollInfo();
|
||||||
|
const cursor = cm.getCursor();
|
||||||
|
cm.setValue(sourceCode);
|
||||||
|
cm.setCursor(cursor);
|
||||||
|
cm.scrollTo(scrollInfo.left, scrollInfo.top);
|
||||||
|
|
||||||
|
return runtimeSend({
|
||||||
|
method: 'saveUsercss',
|
||||||
|
reason: 'update',
|
||||||
|
sourceCode
|
||||||
|
}).then(updateMeta).catch(showError);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateMeta(style, dup) {
|
||||||
|
$$('.main .warning').forEach(e => e.remove());
|
||||||
|
|
||||||
|
const data = style.usercssData;
|
||||||
|
const dupData = dup && dup.usercssData;
|
||||||
|
const versionTest = dup && semverCompare(data.version, dupData.version);
|
||||||
|
|
||||||
|
// update editor
|
||||||
|
cm.setPreprocessor(data.preprocessor);
|
||||||
|
|
||||||
|
// update metas
|
||||||
|
document.title = `${installButtonLabel()} ${data.name}`;
|
||||||
|
|
||||||
|
$('.install').textContent = installButtonLabel();
|
||||||
|
$('.set-update-url').title = dup && dup.updateUrl && t('installUpdateFrom', dup.updateUrl) || '';
|
||||||
|
$('.meta-name').textContent = data.name;
|
||||||
|
$('.meta-version').textContent = data.version;
|
||||||
|
$('.meta-description').textContent = data.description;
|
||||||
|
|
||||||
|
$('.meta-author').parentNode.style.display = data.author ? '' : 'none';
|
||||||
|
$('.meta-author').textContent = data.author;
|
||||||
|
|
||||||
|
$('.meta-license').parentNode.style.display = data.license ? '' : 'none';
|
||||||
|
$('.meta-license').textContent = data.license;
|
||||||
|
|
||||||
|
$('.applies-to').textContent = '';
|
||||||
|
getAppliesTo(style).forEach(pattern =>
|
||||||
|
$('.applies-to').appendChild($element({tag: 'li', textContent: pattern}))
|
||||||
|
);
|
||||||
|
|
||||||
|
$('.external-link').textContent = '';
|
||||||
|
const externalLink = makeExternalLink();
|
||||||
|
if (externalLink) {
|
||||||
|
$('.external-link').appendChild(externalLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeExternalLink() {
|
||||||
|
const urls = [];
|
||||||
|
if (data.homepageURL) {
|
||||||
|
urls.push([data.homepageURL, t('externalHomepage')]);
|
||||||
|
}
|
||||||
|
if (data.supportURL) {
|
||||||
|
urls.push([data.supportURL, t('externalSupport')]);
|
||||||
|
}
|
||||||
|
if (urls.length) {
|
||||||
|
return $element({appendChild: [
|
||||||
|
$element({tag: 'h3', textContent: t('externalLink')}),
|
||||||
|
$element({tag: 'ul', appendChild: urls.map(args =>
|
||||||
|
$element({tag: 'li', appendChild: makeLink(...args)})
|
||||||
|
)})
|
||||||
|
]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function installButtonLabel() {
|
||||||
|
return t(
|
||||||
|
installed ? 'installButtonInstalled' :
|
||||||
|
!dup ? 'installButton' :
|
||||||
|
versionTest > 0 ? 'installButtonUpdate' : 'installButtonReinstall'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showError(err) {
|
||||||
|
$$('.main .warning').forEach(e => e.remove());
|
||||||
|
const main = $('.main');
|
||||||
|
main.insertBefore(buildWarning(err), main.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
function runtimeSend(request) {
|
function runtimeSend(request) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -41,15 +136,25 @@
|
||||||
});
|
});
|
||||||
return runtimeSend(request)
|
return runtimeSend(request)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
|
installed = true;
|
||||||
|
|
||||||
$$('.warning')
|
$$('.warning')
|
||||||
.forEach(el => el.remove());
|
.forEach(el => el.remove());
|
||||||
$('.install').textContent = 'Installed';
|
|
||||||
$('.install').disabled = true;
|
$('.install').disabled = true;
|
||||||
$('.install').classList.add('installed');
|
$('.install').classList.add('installed');
|
||||||
$('.set-update-url input[type=checkbox]').disabled = true;
|
$('.set-update-url input[type=checkbox]').disabled = true;
|
||||||
$('.set-update-url').title = result.updateUrl ?
|
$('.set-update-url').title = result.updateUrl ?
|
||||||
t('installUpdateFrom', result.updateUrl) : '';
|
t('installUpdateFrom', result.updateUrl) : '';
|
||||||
window.dispatchEvent(new CustomEvent('installed', {detail: result}));
|
|
||||||
|
updateMeta(result);
|
||||||
|
|
||||||
|
if (liveReload) {
|
||||||
|
port.postMessage({method: 'liveReloadStart'});
|
||||||
|
}
|
||||||
|
$('.live-reload').addEventListener('change', () => {
|
||||||
|
const method = 'liveReload' + (liveReload ? 'Start' : 'Stop');
|
||||||
|
port.postMessage({method});
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
alert(chrome.i18n.getMessage('styleInstallFailed', String(err)));
|
alert(chrome.i18n.getMessage('styleInstallFailed', String(err)));
|
||||||
|
@ -81,6 +186,8 @@
|
||||||
const dupData = dup && dup.usercssData;
|
const dupData = dup && dup.usercssData;
|
||||||
const versionTest = dup && semverCompare(data.version, dupData.version);
|
const versionTest = dup && semverCompare(data.version, dupData.version);
|
||||||
|
|
||||||
|
updateMeta(style, dup);
|
||||||
|
|
||||||
// update UI
|
// update UI
|
||||||
if (versionTest < 0) {
|
if (versionTest < 0) {
|
||||||
$('.actions').parentNode.insertBefore(
|
$('.actions').parentNode.insertBefore(
|
||||||
|
@ -120,59 +227,14 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// update editor
|
// live reload
|
||||||
cm.setPreprocessor(data.preprocessor);
|
const setLiveReload = $('.live-reload input[type=checkbox]');
|
||||||
|
if (updateUrl.protocol !== 'file:') {
|
||||||
// update metas
|
setLiveReload.parentNode.remove();
|
||||||
document.title = `${installButtonLabel()} ${data.name}`;
|
|
||||||
|
|
||||||
$('.install').textContent = installButtonLabel();
|
|
||||||
$('.set-update-url').title = dup && dup.updateUrl && t('installUpdateFrom', dup.updateUrl) || '';
|
|
||||||
$('.meta-name').textContent = data.name;
|
|
||||||
$('.meta-version').textContent = data.version;
|
|
||||||
$('.meta-description').textContent = data.description;
|
|
||||||
|
|
||||||
if (data.author) {
|
|
||||||
$('.meta-author').textContent = data.author;
|
|
||||||
} else {
|
} else {
|
||||||
$('.meta-author').parentNode.remove();
|
setLiveReload.addEventListener('change', () => {
|
||||||
}
|
liveReload = setLiveReload.checked;
|
||||||
if (data.license) {
|
});
|
||||||
$('.meta-license').textContent = data.license;
|
|
||||||
} else {
|
|
||||||
$('.meta-license').parentNode.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
getAppliesTo(style).forEach(pattern =>
|
|
||||||
$('.applies-to').appendChild($element({tag: 'li', textContent: pattern}))
|
|
||||||
);
|
|
||||||
|
|
||||||
const externalLink = makeExternalLink();
|
|
||||||
if (externalLink) {
|
|
||||||
$('.external-link').appendChild(externalLink);
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeExternalLink() {
|
|
||||||
const urls = [];
|
|
||||||
if (data.homepageURL) {
|
|
||||||
urls.push([data.homepageURL, t('externalHomepage')]);
|
|
||||||
}
|
|
||||||
if (data.supportURL) {
|
|
||||||
urls.push([data.supportURL, t('externalSupport')]);
|
|
||||||
}
|
|
||||||
if (urls.length) {
|
|
||||||
return $element({appendChild: [
|
|
||||||
$element({tag: 'h3', textContent: t('externalLink')}),
|
|
||||||
$element({tag: 'ul', appendChild: urls.map(args =>
|
|
||||||
$element({tag: 'li', appendChild: makeLink(...args)})
|
|
||||||
)})
|
|
||||||
]});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function installButtonLabel() {
|
|
||||||
return t(!dup ? 'installButton' :
|
|
||||||
versionTest > 0 ? 'installButtonUpdate' : 'installButtonReinstall');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user