show installed styles in popup finder

fixes #1488
This commit is contained in:
tophf 2022-10-12 20:04:45 +03:00
parent 79dff2775b
commit 1725c0ecb9
3 changed files with 66 additions and 43 deletions

View File

@ -199,6 +199,18 @@ const styleMan = (() => {
getOrder: () => orderWrap.value, getOrder: () => orderWrap.value,
/** @returns {Promise<string | {[remoteId:string]: styleId}>}>} */
async getRemoteInfo(id) {
if (ready.then) await ready;
if (id) return calcRemoteId(id2style(id));
const res = {};
for (const {style} of dataMap.values()) {
const [rid, vars] = calcRemoteId(style);
if (rid) res[rid] = [style.id, vars];
}
return res;
},
/** @returns {Promise<StyleSectionsToApply>} */ /** @returns {Promise<StyleSectionsToApply>} */
async getSectionsByUrl(url, id, isInitialApply) { async getSectionsByUrl(url, id, isInitialApply) {
if (ready.then) await ready; if (ready.then) await ready;
@ -366,6 +378,17 @@ const styleMan = (() => {
return id2style(uuidIndex.get(uuid)); return id2style(uuidIndex.get(uuid));
} }
function calcRemoteId({md5Url, updateUrl, usercssData: ucd} = {}) {
let id;
id = (id = /\d+/.test(md5Url) || URLS.extractUsoArchiveId(updateUrl)) && `uso-${id}`
|| (id = URLS.extractUSwId(updateUrl)) && `usw-${id}`
|| '';
return id && [
id,
ucd && !isEmptyObj(ucd.vars),
];
}
/** @returns {StyleObj} */ /** @returns {StyleObj} */
function createNewStyle() { function createNewStyle() {
return /** @namespace StyleObj */ { return /** @namespace StyleObj */ {

View File

@ -134,6 +134,10 @@
width: 100%; width: 100%;
} }
.search-result[data-installed] {
box-shadow: 1px 1px 10px darkcyan;
border-color: darkcyan;
}
.search-result:not([data-installed]) .search-result-actions { .search-result:not([data-installed]) .search-result-actions {
opacity: 0; opacity: 0;
transition: opacity .5s; transition: opacity .5s;

View File

@ -2,7 +2,7 @@
/* global $entry tabURL */// popup.js /* global $entry tabURL */// popup.js
/* global API */// msg.js /* global API */// msg.js
/* global Events */ /* global Events */
/* global FIREFOX URLS debounce download stringAsRegExp tryRegExp tryURL */// toolbox.js /* global FIREFOX URLS debounce download isEmptyObj stringAsRegExp tryRegExp tryURL */// toolbox.js
/* global prefs */ /* global prefs */
/* global t */// localization.js /* global t */// localization.js
'use strict'; 'use strict';
@ -27,7 +27,7 @@
/** /**
* @typedef IndexEntry * @typedef IndexEntry
* @prop {'uso' | 'uso-android'} f - format * @prop {'uso' | 'uso-android'} f - format
* @prop {Number} i - id * @prop {Number} i - id, later replaced with string like `uso-123`
* @prop {string} n - name * @prop {string} n - name
* @prop {string} c - category * @prop {string} c - category
* @prop {Number} u - updatedTime * @prop {Number} u - updatedTime
@ -39,8 +39,8 @@
* @prop {string} sn - screenshotName * @prop {string} sn - screenshotName
* @prop {boolean} sa - screenshotArchived * @prop {boolean} sa - screenshotArchived
* *
* @prop {boolean} _installed * @prop {number} _styleId - installed style id
* @prop {number} _installedStyleId * @prop {boolean} _styleVars - installed style has vars
* @prop {number} _year * @prop {number} _year
*/ */
/** @type IndexEntry[] */ /** @type IndexEntry[] */
@ -73,6 +73,7 @@
const entry = el.closest(RESULT_SEL); const entry = el.closest(RESULT_SEL);
return {entry, result: entry && entry._result}; return {entry, result: entry && entry._result};
}; };
const rid2id = rid => rid.split('-')[1];
Events.searchInline = () => { Events.searchInline = () => {
calcCategory(); calcCategory();
ready = start(); ready = start();
@ -158,18 +159,22 @@
window.on('styleDeleted', ({detail: {style: {id}}}) => { window.on('styleDeleted', ({detail: {style: {id}}}) => {
restoreScrollPosition(); restoreScrollPosition();
const result = results.find(r => r._installedStyleId === id); const r = results.find(r => r._styleId === id);
if (result) { if (r) {
API.uso.pingback(result.i, false); if (r.f) API.uso.pingback(rid2id(r.i), false);
renderActionButtons(result.i, -1); delete r._styleId;
renderActionButtons(r.i);
} }
}); });
window.on('styleAdded', async ({detail: {style}}) => { window.on('styleAdded', async ({detail: {style}}) => {
restoreScrollPosition(); restoreScrollPosition();
const id = calcId(style) || calcId(await API.styles.get(style.id)); const ri = await API.styles.getRemoteInfo(style.id);
if (id && results.find(r => r.i === id)) { const r = ri && results.find(r => ri[0] === r.i);
renderActionButtons(id, style.id); if (r) {
r._styleId = style.id;
r._styleVars = ri[1];
renderActionButtons(ri[0]);
} }
}); });
@ -209,9 +214,10 @@
results = await search({retry}); results = await search({retry});
} }
if (results.length) { if (results.length) {
const installedStyles = await API.styles.getAll(); const info = await API.styles.getRemoteInfo();
const allSupportedIds = new Set(installedStyles.map(calcId)); for (const r of results) {
results = results.filter(r => !allSupportedIds.has(r.i)); [r._styleId, r._styleVars] = info[r.i] || [];
}
} }
if (!keepYears) resultsAllYears = results; if (!keepYears) resultsAllYears = results;
renderYears(); renderYears();
@ -330,7 +336,7 @@
function createSearchResultNode(result) { function createSearchResultNode(result) {
const entry = t.template.searchResult.cloneNode(true); const entry = t.template.searchResult.cloneNode(true);
const { const {
i: id, i: rid,
n: name, n: name,
r: rating, r: rating,
u: updateTime, u: updateTime,
@ -342,7 +348,8 @@
sn: shot, sn: shot,
f: fmt, f: fmt,
} = entry._result = result; } = entry._result = result;
entry.id = RESULT_ID_PREFIX + id; const id = rid2id(rid);
entry.id = RESULT_ID_PREFIX + rid;
// title // title
Object.assign($('.search-result-title', entry), { Object.assign($('.search-result-title', entry), {
onclick: Events.openURLandHide, onclick: Events.openURLandHide,
@ -421,22 +428,19 @@
} }
} }
function renderActionButtons(entry, installedId) { function renderActionButtons(entry) {
if (Number(entry)) { if (typeof entry !== 'object') {
entry = $('#' + RESULT_ID_PREFIX + entry); entry = $('#' + RESULT_ID_PREFIX + entry);
} }
if (!entry) return; if (!entry) return;
const result = entry._result; const result = entry._result;
if (typeof installedId === 'number') { const installedId = result._styleId;
result._installed = installedId > 0; const isInstalled = installedId > 0; // must be boolean for comparisons below
result._installedStyleId = installedId;
}
const isInstalled = result._installed;
const status = $('.search-result-status', entry).textContent = const status = $('.search-result-status', entry).textContent =
isInstalled ? t('clickToUninstall') : isInstalled ? t('clickToUninstall') :
entry.dataset.noImage != null ? t('installButton') : entry.dataset.noImage != null ? t('installButton') :
''; '';
const notMatching = installedId > 0 && !$entry(installedId); const notMatching = isInstalled && !$entry(installedId);
if (notMatching !== entry.classList.contains('not-matching')) { if (notMatching !== entry.classList.contains('not-matching')) {
entry.classList.toggle('not-matching'); entry.classList.toggle('not-matching');
if (notMatching) { if (notMatching) {
@ -456,6 +460,7 @@
disabled: notMatching, disabled: notMatching,
}); });
toggleDataset(entry, 'installed', isInstalled); toggleDataset(entry, 'installed', isInstalled);
toggleDataset(entry, 'customizable', result._styleVars);
} }
function renderFullInfo(entry, style) { function renderFullInfo(entry, style) {
@ -469,17 +474,20 @@
textContent: description, textContent: description,
title: description, title: description,
}); });
vars = !isEmptyObj(vars);
entry._result._styleVars = vars;
toggleDataset(entry, 'customizable', vars); toggleDataset(entry, 'customizable', vars);
} }
function configure() { function configure() {
const styleEntry = $entry($resultEntry(this).result._installedStyleId); const styleEntry = $entry($resultEntry(this).result._styleId);
Events.configure.call(this, {target: styleEntry}); Events.configure.call(this, {target: styleEntry});
} }
async function install() { async function install() {
const {entry, result} = $resultEntry(this); const {entry, result} = $resultEntry(this);
const {i: id, f: fmt} = result; const {f: fmt} = result;
const id = rid2id(result.i);
const installButton = $('.search-result-install', entry); const installButton = $('.search-result-install', entry);
showSpinner(entry); showSpinner(entry);
@ -507,7 +515,7 @@
function uninstall() { function uninstall() {
const {entry, result} = $resultEntry(this); const {entry, result} = $resultEntry(this);
saveScrollPosition(entry); saveScrollPosition(entry);
API.styles.delete(result._installedStyleId); API.styles.delete(result._styleId);
} }
function saveScrollPosition(entry) { function saveScrollPosition(entry) {
@ -553,10 +561,11 @@
async function fetchIndex() { async function fetchIndex() {
const timer = setTimeout(showSpinner, BUSY_DELAY, dom.list); const timer = setTimeout(showSpinner, BUSY_DELAY, dom.list);
const jobs = [ const jobs = [
[INDEX_URL, json => json.filter(entry => entry.f === 'uso')], [INDEX_URL, 'uso', json => json.filter(v => v.f === 'uso')],
[USW_INDEX_URL, json => json.data], [USW_INDEX_URL, 'usw', json => json.data],
].map(async ([url, transform]) => { ].map(async ([url, prefix, transform]) => {
const res = transform(await download(url, {responseType: 'json'})); const res = transform(await download(url, {responseType: 'json'}));
for (const v of res) v.i = `${prefix}-${v.i}`;
index = index ? index.concat(res) : res; index = index ? index.concat(res) : res;
if (index !== res) ready = ready.then(start); if (index !== res) ready = ready.then(start);
}); });
@ -607,17 +616,4 @@
: b[order] - a[order] : b[order] - a[order]
) || b.t - a.t; ) || b.t - a.t;
} }
function calcUsoId({md5Url: m, updateUrl}) {
return Number(m && m.match(/\d+|$/)[0]) ||
URLS.extractUsoArchiveId(updateUrl);
}
function calcUswId({updateUrl}) {
return URLS.extractUSwId(updateUrl) || 0;
}
function calcId(style) {
return calcUsoId(style) || calcUswId(style);
}
})(); })();