Add: detail dialog. Move makeAuthor to dom.js. Move external.svg into

images.
This commit is contained in:
eight 2017-10-10 14:27:31 +08:00
parent 3906060aef
commit 5b701d06ad
8 changed files with 191 additions and 40 deletions

View File

@ -159,6 +159,30 @@
"message": "Theme",
"description": "Label for the style editor's CSS theme."
},
"detailName": {
"message": "Name",
"description": "Label for the name of the style"
},
"detailVersion": {
"message": "Version",
"description": "Label for the version of the style"
},
"detailAuthor": {
"message": "Author",
"description": "Label for the author of the style"
},
"detailHomepageURL": {
"message": "Homepage",
"description": "Label for the homepage of the style"
},
"detailSupportURL": {
"message": "Support site",
"description": "Label for the support site of the style"
},
"detailUpdateURL": {
"message": "Update URL",
"description": "Label for the update URL of the style"
},
"dysfunctional": {
"message": "Stylus cannot function in private windows because Firefox disallows direct connection to the internal background page context of the extension.",
"description": "Displayed in Firefox when its settings make Stylus dysfunctional"
@ -223,6 +247,10 @@
"message": "Are you sure you want to delete this style?",
"description": "Confirmation before deleting a style"
},
"detailedInformation": {
"message": "Details",
"description": "The label for detailed information"
},
"dragDropMessage": {
"message": "Drop your backup file anywhere on this page to import.",
"description": "Drag'n'drop message"

View File

Before

Width:  |  Height:  |  Size: 148 B

After

Width:  |  Height:  |  Size: 148 B

View File

@ -1,4 +1,4 @@
/* global CodeMirror semverCompare makeLink closeCurrentTab */
/* global CodeMirror semverCompare makeLink closeCurrentTab makeAuthor */
'use strict';
@ -93,41 +93,6 @@
$('.external-link').appendChild(externalLink);
}
function makeAuthor(text) {
const match = text.match(/^(.+?)(?:\s+<(.+?)>)?(?:\s+\((.+?)\))$/);
if (!match) {
return document.createTextNode(text);
}
const [, name, email, url] = match;
const frag = document.createDocumentFragment();
if (email) {
frag.appendChild($element({
tag: 'a',
textContent: name,
href: `mailto:${email}`
}));
} else {
frag.appendChild($element({
tag: 'span',
textContent: name
}));
}
if (url) {
frag.appendChild($element({
tag: 'a',
href: url,
target: '_blank',
rel: 'noopener',
appendChild: $element({
tag: 'img',
className: 'icon',
src: '/install-usercss/external.svg'
})
}));
}
return frag;
}
function makeExternalLink() {
const urls = [];
if (data.homepageURL) {

View File

@ -194,11 +194,38 @@ function $element(opt) {
}
function makeLink(href = '', textContent) {
function makeLink(href = '', content) {
return $element({
tag: 'a',
target: '_blank',
href,
textContent,
rel: 'noopener',
appendChild: content,
});
}
function makeAuthor(text) {
const match = text.match(/^(.+?)(?:\s+<(.+?)>)?(?:\s+\((.+?)\))$/);
if (!match) {
return document.createTextNode(text);
}
const [, name, email, url] = match;
const frag = document.createDocumentFragment();
if (email) {
frag.appendChild(makeLink(`mailto:${email}`, name));
} else {
frag.appendChild($element({
tag: 'span',
textContent: name
}));
}
if (url) {
frag.appendChild(makeLink(url, $element({
tag: 'img',
className: 'icon',
src: '/images/external.svg'
})));
}
return frag;
}

View File

@ -124,6 +124,14 @@
</span>
</template>
<template data-id="informationIcon">
<span class="detailed-information" i18n-title="detailedInformation">
<svg class="svg-icon" viewBox="0 0 14 16" alt="More info">
<path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path>
</svg>
</span>
</template>
<template data-id="appliesToTarget">
<span class="target"></span>
</template>
@ -152,6 +160,7 @@
<script src="manage/object-diff.js"></script>
<script src="js/usercss.js"></script>
<script src="manage/config-dialog.js"></script>
<script src="manage/detail-dialog.js"></script>
<script src="manage/manage.js"></script>
</head>

84
manage/detail-dialog.js Normal file
View File

@ -0,0 +1,84 @@
/* global messageBox makeLink makeAuthor */
'use strict';
function detailDialog(style) {
const TYPE_NAME = {
'urls': t('appliesUrlOption'),
'urlPrefixes': t('appliesUrlPrefixOption'),
'domains': t('appliesDomainOption'),
'regexps': t('appliesRegexpOption')
};
return messageBox({
title: style.name,
className: 'detail-dialog',
contents: buildContent(),
buttons: [t('confirmClose')]
});
function buildContent() {
return $element({
className: 'detail-table',
appendChild: [
makeRow(t('detailName'), 'name'),
makeRow(t('detailVersion'), 'version', true),
makeRow(t('detailAuthor'), makeStyleAuthor()),
makeRow(t('detailHomepageURL'), 'url'),
makeRow(t('detailSupportURL'), 'supportURL', true),
makeRow(t('detailUpdateURL'), 'updateUrl'),
makeRow(t('appliesLabel'), makeAppliesTo())
]
});
}
function makeRow(label, content, isUsercss) {
if (typeof content === 'string') {
if (isUsercss) {
if (style.usercssData) {
content = style.usercssData[content] || '';
} else {
content = '';
}
} else {
content = style[content] || '';
}
if (/^http[\S]+$/.test(content)) {
content = makeLink(content, content);
}
}
return $element({className: 'meta', appendChild: [
$element({className: 'meta-label', textContent: label}),
$element({className: 'meta-value', appendChild: content})
]});
}
function makeStyleAuthor() {
const author = style.author || style.usercssData && style.usercssData.author;
if (!author) {
return '';
}
return makeAuthor(author);
}
function makeAppliesTo() {
return $element({
'tag': 'ul',
appendChild: getApplies().map(([type, value]) => $element({
tag: 'li', textContent: `${type} - ${value}`
}))
});
}
function getApplies() {
const result = [];
for (const section of style.sections) {
for (const type of ['urls', 'urlPrefixes', 'domains', 'regexps']) {
if (section[type]) {
result.push(...section[type].map(pattern => ([TYPE_NAME[type], pattern])));
}
}
}
return result;
}
}

View File

@ -697,6 +697,38 @@ fieldset > *:not(legend) {
flex-shrink: 0;
}
.detail-table {
border-collapse: collapse;
display: table;
}
.detail-table > * {
display: table-row
}
.detail-table > * > * {
display: table-cell;
padding: 0.3em 0.6em;
border: 1px solid silver;
}
.detail-table .meta-label {
font-weight: bold;
white-space: nowrap;
}
.detail-table ul {
margin: 0;
padding: 0;
list-style: none;
}
.detail-table .icon {
height: 1.3em;
margin: -0.3em 0;
vertical-align: middle;
}
@keyframes fadein {
from {
opacity: 0;

View File

@ -2,7 +2,7 @@
/* global filtersSelector, filterAndAppend */
/* global checkUpdate, handleUpdateInstalled */
/* global objectDiff */
/* global configDialog */
/* global configDialog detailDialog */
'use strict';
let installed;
@ -196,6 +196,7 @@ function createStyleElement({style, name}) {
if (shouldShowConfig() && newUI.enabled) {
$('.actions', entry).appendChild(template.configureIcon.cloneNode(true));
}
$('.actions', entry).appendChild(template.informationIcon.cloneNode(true));
// name being supplied signifies we're invoked by showStyles()
// which debounces its main loop thus loading the postponed favicons
@ -286,7 +287,12 @@ Object.assign(handleEvent, {
'.update': 'update',
'.delete': 'delete',
'.applies-to .expander': 'expandTargets',
'.configure-usercss': 'config'
'.configure-usercss': 'config',
'.detailed-information': 'showDetails'
},
showDetails(event, {styleMeta: style}) {
detailDialog(style);
},
config(event, {styleMeta: style}) {