show Size column + simplify sorter

This commit is contained in:
tophf 2022-09-03 19:36:59 +03:00
parent d91cf11366
commit c351413c3f
6 changed files with 54 additions and 35 deletions

View File

@ -498,6 +498,9 @@
"message": "Saved",
"description": "Used in various parts of the UI to indicate that something was saved"
},
"genericSize": {
"message": "Size"
},
"genericTest": {
"message": "Test",
"description": "Label for the action that runs some test e.g. opens the regexp tester panel in the editor"

View File

@ -31,6 +31,8 @@
<button class="check-update" i18n="checkForUpdate"></button>
<button class="update" i18n="installUpdate"></button>
<button class="configure-usercss" i18n="configureStyle"></button>
<span class="style-info" data-type="size"></span>
<span class="style-info" data-type="age"></span>
<span class="update-note"></span>
</p>
</div>
@ -57,6 +59,7 @@
</svg>
</a>
</p>
<p class="style-info" data-type="size"></p>
<p class="style-info" data-type="age"></p>
<div class="applies-to">
<a class="expander" tabindex="0">

View File

@ -1,7 +1,7 @@
/* global API */// msg.js
/* global changeQueue installed newUI */// manage.js
/* global checkUpdate handleUpdateInstalled */// updater-ui.js
/* global createStyleElement createTargetsElement getFaviconSrc */// render.js
/* global createStyleElement createTargetsElement getFaviconSrc styleToDummyEntry */// render.js
/* global debounce getOwnTab openURL sessionStore */// toolbox.js
/* global filterAndAppend showFiltersStats */// filters.js
/* global sorter */
@ -191,7 +191,7 @@ function handleUpdate(style, {reason, method} = {}) {
if (oldEntry && method === 'styleUpdated') {
handleToggledOrCodeOnly();
}
entry = entry || createStyleElement({style});
entry = entry || createStyleElement(styleToDummyEntry(style));
if (oldEntry) {
if (oldEntry.styleNameLowerCase === entry.styleNameLowerCase) {
installed.replaceChild(entry, oldEntry);

View File

@ -356,8 +356,9 @@ a:hover {
.newUI .style-info[data-type=version][data-value="1.0.0"] {
display: none;
}
.newUI .entry .style-info[data-type=size],
.newUI .entry .style-info[data-type=age] {
color: var(--c60);
color: var(--c50);
text-align: right;
padding-right: 1em;
}

View File

@ -17,6 +17,7 @@ const AGES = [
[12, 'm', t('dateAbbrMonth', '\x01')],
[Infinity, 'y', t('dateAbbrYear', '\x01')],
];
const groupThousands = num => `${num}`.replace(/\d(?=(\d{3})+$)/g, '$&\xA0');
(() => {
const proto = HTMLImageElement.prototype;
@ -70,7 +71,15 @@ function createAgeText(el, style) {
}
}
function createStyleElement({style, name: nameLC}) {
function calcObjSize(obj) {
// Inaccurate but simple
return typeof obj !== 'object' ? `${obj}`.length :
!obj ? 0 :
Array.isArray(obj) ? obj.reduce((sum, v) => sum + calcObjSize(v), 0) :
Object.entries(obj).reduce((sum, [k, v]) => sum + k.length + calcObjSize(v), 0);
}
function createStyleElement({styleMeta: style, styleNameLowerCase: nameLC, styleSize: size}) {
// query the sub-elements just once, then reuse the references
if ((elementParts || {}).newUI !== newUI.enabled) {
const entry = t.template[newUI.enabled ? 'styleNewUI' : 'style'].cloneNode(true);
@ -85,6 +94,7 @@ function createStyleElement({style, name: nameLC}) {
homepage: $('.homepage', entry),
homepageIcon: t.template[`homepageIcon${newUI.enabled ? 'Small' : 'Big'}`],
infoAge: $('[data-type=age]', entry),
infoSize: $('[data-type=size]', entry),
infoVer: $('[data-type=version]', entry),
appliesTo: $('.applies-to', entry),
targets: $('.targets', entry),
@ -114,9 +124,11 @@ function createStyleElement({style, name: nameLC}) {
} else {
delete parts.infoVer.dataset.isDate;
}
if (newUI.enabled) {
createAgeText(parts.infoAge, style);
} else {
parts.infoSize.dataset.value = Math.log10(size || 1) >> 0; // for CSS to target big/small styles
parts.infoSize.textContent = groupThousands(Math.round(size / 1024)) + 'k';
parts.infoSize.title = `${t('genericSize')}: ${groupThousands(size)} B`;
if (!newUI.enabled) {
parts.oldConfigure.classList.toggle('hidden', !configurable);
parts.oldCheckUpdate.classList.toggle('hidden', !style.updateUrl);
parts.oldUpdate.classList.toggle('hidden', !style.updateUrl);
@ -130,8 +142,9 @@ function createStyleElement({style, name: nameLC}) {
const entry = parts.entry.cloneNode(true);
entry.id = ENTRY_ID_PREFIX_RAW + style.id;
entry.styleId = style.id;
entry.styleNameLowerCase = nameLC || name.toLocaleLowerCase() + '\n' + name;
entry.styleNameLowerCase = nameLC;
entry.styleMeta = style;
entry.styleSize = size;
entry.className = parts.entryClassBase + ' ' +
(style.enabled ? 'enabled' : 'disabled') +
(style.updateUrl ? ' updatable' : '') +
@ -340,16 +353,7 @@ function padLeft(val, width) {
}
function showStyles(styles = [], matchUrlIds) {
const sorted = sorter.sort({
styles: styles.map(style => {
const name = style.customName || style.name || '';
return {
style,
// sort case-insensitively the whole list then sort dupes like `Foo` and `foo` case-sensitively
name: name.toLocaleLowerCase() + '\n' + name,
};
}),
});
const sorted = sorter.sort(styles.map(styleToDummyEntry));
let index = 0;
let firstRun = true;
installed.dataset.total = styles.length;
@ -388,6 +392,16 @@ function showStyles(styles = [], matchUrlIds) {
}
}
function styleToDummyEntry(style) {
const name = style.customName || style.name || '';
return {
styleMeta: style,
styleSize: calcObjSize(style),
// sort case-insensitively the whole list then sort dupes like `Foo` and `foo` case-sensitively
styleNameLowerCase: name.toLocaleLowerCase() + '\n' + name,
};
}
/* exported switchUI */
function switchUI({styleOnly} = {}) {
const current = {};

View File

@ -14,27 +14,32 @@ const sorter = (() => {
const tagData = {
title: {
text: t('genericTitle'),
parse: ({name}) => name,
parse: v => v.styleNameLowerCase,
sorter: sorterType.alpha,
},
usercss: {
text: 'Usercss',
parse: ({style}) => style.usercssData ? 0 : 1,
parse: v => v.styleMeta.usercssData ? 0 : 1,
sorter: sorterType.number,
},
disabled: {
text: '', // added as either "enabled" or "disabled" by the addOptions function
parse: ({style}) => style.enabled ? 1 : 0,
parse: v => v.styleMeta.enabled ? 1 : 0,
sorter: sorterType.number,
},
dateInstalled: {
text: t('dateInstalled'),
parse: ({style}) => style.installDate,
parse: v => v.styleMeta.installDate,
sorter: sorterType.number,
},
dateUpdated: {
text: t('dateUpdated'),
parse: ({style}) => style.updateDate || style.installDate,
parse: ({styleMeta: s}) => s.updateDate || s.installDate,
sorter: sorterType.number,
},
size: {
text: t('genericSize'),
parse: v => v.styleSize,
sorter: sorterType.number,
},
};
@ -53,6 +58,7 @@ const sorter = (() => {
'disabled,asc, title,asc',
'disabled,desc, title,asc',
'disabled,desc, usercss,asc, title,asc',
'size,desc, title,asc',
'{groupDesc}',
'title,desc',
'usercss,asc, title,desc',
@ -120,7 +126,7 @@ const sorter = (() => {
init,
sort({styles}) {
sort(styles) {
const sortBy = getPref().split(splitRegex);
const len = sortBy.length;
return styles.sort((a, b) => {
@ -140,17 +146,9 @@ const sorter = (() => {
update() {
if (!installed) return;
const current = [...installed.children];
const sorted = sorter.sort({
styles: current.map(entry => ({
entry,
name: entry.styleNameLowerCase,
style: entry.styleMeta,
})),
});
if (current.some((entry, index) => entry !== sorted[index].entry)) {
const renderBin = document.createDocumentFragment();
sorted.forEach(({entry}) => renderBin.appendChild(entry));
installed.appendChild(renderBin);
const sorted = sorter.sort([...current]);
if (current.some((el, i) => el !== sorted[i])) {
installed.append(...sorted);
}
sorter.updateStripes();
},