Skip to content

Commit 1725c0e

Browse files
committed
show installed styles in popup finder
fixes #1488
1 parent 79dff27 commit 1725c0e

File tree

3 files changed

+66
-43
lines changed

3 files changed

+66
-43
lines changed

background/style-manager.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,18 @@ const styleMan = (() => {
199199

200200
getOrder: () => orderWrap.value,
201201

202+
/** @returns {Promise<string | {[remoteId:string]: styleId}>}>} */
203+
async getRemoteInfo(id) {
204+
if (ready.then) await ready;
205+
if (id) return calcRemoteId(id2style(id));
206+
const res = {};
207+
for (const {style} of dataMap.values()) {
208+
const [rid, vars] = calcRemoteId(style);
209+
if (rid) res[rid] = [style.id, vars];
210+
}
211+
return res;
212+
},
213+
202214
/** @returns {Promise<StyleSectionsToApply>} */
203215
async getSectionsByUrl(url, id, isInitialApply) {
204216
if (ready.then) await ready;
@@ -366,6 +378,17 @@ const styleMan = (() => {
366378
return id2style(uuidIndex.get(uuid));
367379
}
368380

381+
function calcRemoteId({md5Url, updateUrl, usercssData: ucd} = {}) {
382+
let id;
383+
id = (id = /\d+/.test(md5Url) || URLS.extractUsoArchiveId(updateUrl)) && `uso-${id}`
384+
|| (id = URLS.extractUSwId(updateUrl)) && `usw-${id}`
385+
|| '';
386+
return id && [
387+
id,
388+
ucd && !isEmptyObj(ucd.vars),
389+
];
390+
}
391+
369392
/** @returns {StyleObj} */
370393
function createNewStyle() {
371394
return /** @namespace StyleObj */ {

popup/search.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@
134134
width: 100%;
135135
}
136136

137+
.search-result[data-installed] {
138+
box-shadow: 1px 1px 10px darkcyan;
139+
border-color: darkcyan;
140+
}
137141
.search-result:not([data-installed]) .search-result-actions {
138142
opacity: 0;
139143
transition: opacity .5s;

popup/search.js

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/* global $entry tabURL */// popup.js
33
/* global API */// msg.js
44
/* global Events */
5-
/* global FIREFOX URLS debounce download stringAsRegExp tryRegExp tryURL */// toolbox.js
5+
/* global FIREFOX URLS debounce download isEmptyObj stringAsRegExp tryRegExp tryURL */// toolbox.js
66
/* global prefs */
77
/* global t */// localization.js
88
'use strict';
@@ -27,7 +27,7 @@
2727
/**
2828
* @typedef IndexEntry
2929
* @prop {'uso' | 'uso-android'} f - format
30-
* @prop {Number} i - id
30+
* @prop {Number} i - id, later replaced with string like `uso-123`
3131
* @prop {string} n - name
3232
* @prop {string} c - category
3333
* @prop {Number} u - updatedTime
@@ -39,8 +39,8 @@
3939
* @prop {string} sn - screenshotName
4040
* @prop {boolean} sa - screenshotArchived
4141
*
42-
* @prop {boolean} _installed
43-
* @prop {number} _installedStyleId
42+
* @prop {number} _styleId - installed style id
43+
* @prop {boolean} _styleVars - installed style has vars
4444
* @prop {number} _year
4545
*/
4646
/** @type IndexEntry[] */
@@ -73,6 +73,7 @@
7373
const entry = el.closest(RESULT_SEL);
7474
return {entry, result: entry && entry._result};
7575
};
76+
const rid2id = rid => rid.split('-')[1];
7677
Events.searchInline = () => {
7778
calcCategory();
7879
ready = start();
@@ -158,18 +159,22 @@
158159

159160
window.on('styleDeleted', ({detail: {style: {id}}}) => {
160161
restoreScrollPosition();
161-
const result = results.find(r => r._installedStyleId === id);
162-
if (result) {
163-
API.uso.pingback(result.i, false);
164-
renderActionButtons(result.i, -1);
162+
const r = results.find(r => r._styleId === id);
163+
if (r) {
164+
if (r.f) API.uso.pingback(rid2id(r.i), false);
165+
delete r._styleId;
166+
renderActionButtons(r.i);
165167
}
166168
});
167169

168170
window.on('styleAdded', async ({detail: {style}}) => {
169171
restoreScrollPosition();
170-
const id = calcId(style) || calcId(await API.styles.get(style.id));
171-
if (id && results.find(r => r.i === id)) {
172-
renderActionButtons(id, style.id);
172+
const ri = await API.styles.getRemoteInfo(style.id);
173+
const r = ri && results.find(r => ri[0] === r.i);
174+
if (r) {
175+
r._styleId = style.id;
176+
r._styleVars = ri[1];
177+
renderActionButtons(ri[0]);
173178
}
174179
});
175180

@@ -209,9 +214,10 @@
209214
results = await search({retry});
210215
}
211216
if (results.length) {
212-
const installedStyles = await API.styles.getAll();
213-
const allSupportedIds = new Set(installedStyles.map(calcId));
214-
results = results.filter(r => !allSupportedIds.has(r.i));
217+
const info = await API.styles.getRemoteInfo();
218+
for (const r of results) {
219+
[r._styleId, r._styleVars] = info[r.i] || [];
220+
}
215221
}
216222
if (!keepYears) resultsAllYears = results;
217223
renderYears();
@@ -330,7 +336,7 @@
330336
function createSearchResultNode(result) {
331337
const entry = t.template.searchResult.cloneNode(true);
332338
const {
333-
i: id,
339+
i: rid,
334340
n: name,
335341
r: rating,
336342
u: updateTime,
@@ -342,7 +348,8 @@
342348
sn: shot,
343349
f: fmt,
344350
} = entry._result = result;
345-
entry.id = RESULT_ID_PREFIX + id;
351+
const id = rid2id(rid);
352+
entry.id = RESULT_ID_PREFIX + rid;
346353
// title
347354
Object.assign($('.search-result-title', entry), {
348355
onclick: Events.openURLandHide,
@@ -421,22 +428,19 @@
421428
}
422429
}
423430

424-
function renderActionButtons(entry, installedId) {
425-
if (Number(entry)) {
431+
function renderActionButtons(entry) {
432+
if (typeof entry !== 'object') {
426433
entry = $('#' + RESULT_ID_PREFIX + entry);
427434
}
428435
if (!entry) return;
429436
const result = entry._result;
430-
if (typeof installedId === 'number') {
431-
result._installed = installedId > 0;
432-
result._installedStyleId = installedId;
433-
}
434-
const isInstalled = result._installed;
437+
const installedId = result._styleId;
438+
const isInstalled = installedId > 0; // must be boolean for comparisons below
435439
const status = $('.search-result-status', entry).textContent =
436440
isInstalled ? t('clickToUninstall') :
437441
entry.dataset.noImage != null ? t('installButton') :
438442
'';
439-
const notMatching = installedId > 0 && !$entry(installedId);
443+
const notMatching = isInstalled && !$entry(installedId);
440444
if (notMatching !== entry.classList.contains('not-matching')) {
441445
entry.classList.toggle('not-matching');
442446
if (notMatching) {
@@ -456,6 +460,7 @@
456460
disabled: notMatching,
457461
});
458462
toggleDataset(entry, 'installed', isInstalled);
463+
toggleDataset(entry, 'customizable', result._styleVars);
459464
}
460465

461466
function renderFullInfo(entry, style) {
@@ -469,17 +474,20 @@
469474
textContent: description,
470475
title: description,
471476
});
477+
vars = !isEmptyObj(vars);
478+
entry._result._styleVars = vars;
472479
toggleDataset(entry, 'customizable', vars);
473480
}
474481

475482
function configure() {
476-
const styleEntry = $entry($resultEntry(this).result._installedStyleId);
483+
const styleEntry = $entry($resultEntry(this).result._styleId);
477484
Events.configure.call(this, {target: styleEntry});
478485
}
479486

480487
async function install() {
481488
const {entry, result} = $resultEntry(this);
482-
const {i: id, f: fmt} = result;
489+
const {f: fmt} = result;
490+
const id = rid2id(result.i);
483491
const installButton = $('.search-result-install', entry);
484492

485493
showSpinner(entry);
@@ -507,7 +515,7 @@
507515
function uninstall() {
508516
const {entry, result} = $resultEntry(this);
509517
saveScrollPosition(entry);
510-
API.styles.delete(result._installedStyleId);
518+
API.styles.delete(result._styleId);
511519
}
512520

513521
function saveScrollPosition(entry) {
@@ -553,10 +561,11 @@
553561
async function fetchIndex() {
554562
const timer = setTimeout(showSpinner, BUSY_DELAY, dom.list);
555563
const jobs = [
556-
[INDEX_URL, json => json.filter(entry => entry.f === 'uso')],
557-
[USW_INDEX_URL, json => json.data],
558-
].map(async ([url, transform]) => {
564+
[INDEX_URL, 'uso', json => json.filter(v => v.f === 'uso')],
565+
[USW_INDEX_URL, 'usw', json => json.data],
566+
].map(async ([url, prefix, transform]) => {
559567
const res = transform(await download(url, {responseType: 'json'}));
568+
for (const v of res) v.i = `${prefix}-${v.i}`;
560569
index = index ? index.concat(res) : res;
561570
if (index !== res) ready = ready.then(start);
562571
});
@@ -607,17 +616,4 @@
607616
: b[order] - a[order]
608617
) || b.t - a.t;
609618
}
610-
611-
function calcUsoId({md5Url: m, updateUrl}) {
612-
return Number(m && m.match(/\d+|$/)[0]) ||
613-
URLS.extractUsoArchiveId(updateUrl);
614-
}
615-
616-
function calcUswId({updateUrl}) {
617-
return URLS.extractUSwId(updateUrl) || 0;
618-
}
619-
620-
function calcId(style) {
621-
return calcUsoId(style) || calcUswId(style);
622-
}
623619
})();

0 commit comments

Comments
 (0)