- + + + +
@@ -54,15 +57,20 @@
@@ -54,15 +57,20 @@
diff --git a/manage/manage.css b/manage/manage.css index 49816145..b5ddd7af 100644 --- a/manage/manage.css +++ b/manage/manage.css @@ -177,6 +177,25 @@ a:hover { text-decoration: none; } +.style-info { + text-align: right; + padding: 0 .25em; + font-weight: normal; + color: #999; +} +.style-info[data-type=version] { + padding-left: .5em; +} +.newUI .style-info[data-type=version][data-value="1.0.0"] { + display: none; +} +.newUI .style-info[data-type=size][title^=" "] { + opacity: .25; +} +.newUI .style-info[data-type=size][title^=" "]:hover { + opacity: 1; +} + .applies-to { overflow-wrap: break-word; } @@ -357,6 +376,10 @@ a:hover { vertical-align: middle; } +.newUI .entry > .style-info { + padding-right: .5em; +} + .newUI .entry .actions { position: relative; } @@ -629,7 +652,7 @@ a:hover { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - max-width: calc(100vw - var(--header-width) - var(--actions-width) - var(--name-padding-left) - 25vw - var(--name-padding-right)); + max-width: calc(75vw - var(--header-width) - var(--actions-width) - var(--name-padding-left) - var(--name-padding-right) - 6rem); box-sizing: border-box; padding-right: 1rem; line-height: 18px; @@ -1026,6 +1049,12 @@ a:hover { } } +@media (max-width: 1000px) { + .newUI .entry > .style-info { + display: none; + } +} + @media (max-width: 850px) { body { display: table; diff --git a/manage/manage.js b/manage/manage.js index ad4ae465..9e1ebf4b 100644 --- a/manage/manage.js +++ b/manage/manage.js @@ -32,6 +32,7 @@ let installed; const ENTRY_ID_PREFIX_RAW = 'style-'; const ENTRY_ID_PREFIX = '#' + ENTRY_ID_PREFIX_RAW; +const REVEAL_DATES_FOR = 'h2.style-name, [data-type=age]'; const BULK_THROTTLE_MS = 100; const bulkChangeQueue = []; @@ -60,6 +61,12 @@ newUI.renderClass(); const TARGET_TYPES = ['domains', 'urls', 'urlPrefixes', 'regexps']; const GET_FAVICON_URL = 'https://www.google.com/s2/favicons?domain='; const OWN_ICON = chrome.runtime.getManifest().icons['16']; +const AGES = [ + [24, 'h', t('dateAbbrHour', '\x01')], + [30, 'd', t('dateAbbrDay', '\x01')], + [12, 'm', t('dateAbbrMonth', '\x01')], + [Infinity, 'y', t('dateAbbrYear', '\x01')], +]; const handleEvent = {}; @@ -184,7 +191,7 @@ function showStyles(styles = [], matchUrlIds) { function createStyleElement({style, name: nameLC}) { // query the sub-elements just once, then reuse the references if ((createStyleElement.parts || {}).newUI !== newUI.enabled) { - const entry = t.template[`style${newUI.enabled ? 'Compact' : ''}`]; + const entry = t.template[newUI.enabled ? 'styleNewUI' : 'style']; createStyleElement.parts = { newUI: newUI.enabled, entry, @@ -195,6 +202,9 @@ function createStyleElement({style, name: nameLC}) { editHrefBase: 'edit.html?id=', homepage: $('.homepage', entry), homepageIcon: t.template[`homepageIcon${newUI.enabled ? 'Small' : 'Big'}`], + infoAge: $('[data-type=age]', entry), + infoVer: $('[data-type=version]', entry), + infoSize: $('[data-type=size]', entry), appliesTo: $('.applies-to', entry), targets: $('.targets', entry), expander: $('.expander', entry), @@ -209,13 +219,19 @@ function createStyleElement({style, name: nameLC}) { }; } const parts = createStyleElement.parts; - const configurable = style.usercssData && style.usercssData.vars && Object.keys(style.usercssData.vars).length > 0; + const ud = style.usercssData; + const configurable = ud && ud.vars && Object.keys(ud.vars).length > 0; const name = style.customName || style.name; parts.checker.checked = style.enabled; - parts.nameLink.textContent = t.breakWord(name); + parts.nameLink.firstChild.textContent = t.breakWord(name); parts.nameLink.href = parts.editLink.href = parts.editHrefBase + style.id; parts.homepage.href = parts.homepage.title = style.url || ''; - if (!newUI.enabled) { + parts.infoVer.textContent = ud ? ud.version : ''; + parts.infoVer.dataset.value = ud ? ud.version : ''; + if (newUI.enabled) { + createSizeText(parts.infoSize, style); + createAgeText(parts.infoAge, style); + } else { parts.oldConfigure.classList.toggle('hidden', !configurable); parts.oldCheckUpdate.classList.toggle('hidden', !style.updateUrl); parts.oldUpdate.classList.toggle('hidden', !style.updateUrl); @@ -234,7 +250,7 @@ function createStyleElement({style, name: nameLC}) { entry.className = parts.entryClassBase + ' ' + (style.enabled ? 'enabled' : 'disabled') + (style.updateUrl ? ' updatable' : '') + - (style.usercssData ? ' usercss' : ''); + (ud ? ' usercss' : ''); if (style.url) { $('.homepage', entry).appendChild(parts.homepageIcon.cloneNode(true)); @@ -315,6 +331,37 @@ function createStyleTargetsElement({entry, expanded, style = entry.styleMeta}) { entry._numTargets = numTargets; } +function createSizeText(el, style) { + const size = (style.sourceCode || '').length || + style.sections.reduce((sum, sec) => sum + (sec.code || '').length, 0); + if (size) { + el.textContent = size < 1000 ? '<1k' : `${size / 1000 | 0}k`; + el.title = addBigness(size); + } +} + +function createAgeText(el, style) { + let val = style.updateDate; + if (val) { + val = (Date.now() - val) / 3600e3; // age in hours + for (const [max, unit, text] of AGES) { + const rounded = Math.round(val); + if (rounded < max) { + el.textContent = text.replace('\x01', rounded); + el.dataset.value = addBigness(Math.round(rounded), 2) + unit; + break; + } + val /= max; + } + } else if (el.firstChild) { + el.textContent = ''; + delete el.dataset.value; + } +} + +function addBigness(val, max = 8) { + return ' '.repeat(max - Math.ceil(Math.log10(val))) + val; +} function getFaviconImgSrc(container = installed) { if (!newUI.enabled || !newUI.favicons) return; @@ -505,9 +552,9 @@ Object.assign(handleEvent, { }, lazyAddEntryTitle({type, target}) { - const cell = target.closest('h2.style-name'); + const cell = target.closest(REVEAL_DATES_FOR); if (cell) { - const link = $('.style-name-link', cell); + const link = $('.style-name-link', cell) || cell; if (type === 'mouseover' && !link.title) { debounce(handleEvent.addEntryTitle, 50, link); } else { @@ -541,7 +588,7 @@ function handleBulkChange() { } function handleUpdateForId(id, opts) { - return API.getStyle(id, true).then(style => { + return API.getStyle(id).then(style => { handleUpdate(style, opts); bulkChangeQueue.time = performance.now(); });