|
2 | 2 | /* global $entry tabURL */// popup.js
|
3 | 3 | /* global API */// msg.js
|
4 | 4 | /* 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 |
6 | 6 | /* global prefs */
|
7 | 7 | /* global t */// localization.js
|
8 | 8 | 'use strict';
|
|
27 | 27 | /**
|
28 | 28 | * @typedef IndexEntry
|
29 | 29 | * @prop {'uso' | 'uso-android'} f - format
|
30 |
| - * @prop {Number} i - id |
| 30 | + * @prop {Number} i - id, later replaced with string like `uso-123` |
31 | 31 | * @prop {string} n - name
|
32 | 32 | * @prop {string} c - category
|
33 | 33 | * @prop {Number} u - updatedTime
|
|
39 | 39 | * @prop {string} sn - screenshotName
|
40 | 40 | * @prop {boolean} sa - screenshotArchived
|
41 | 41 | *
|
42 |
| - * @prop {boolean} _installed |
43 |
| - * @prop {number} _installedStyleId |
| 42 | + * @prop {number} _styleId - installed style id |
| 43 | + * @prop {boolean} _styleVars - installed style has vars |
44 | 44 | * @prop {number} _year
|
45 | 45 | */
|
46 | 46 | /** @type IndexEntry[] */
|
|
73 | 73 | const entry = el.closest(RESULT_SEL);
|
74 | 74 | return {entry, result: entry && entry._result};
|
75 | 75 | };
|
| 76 | + const rid2id = rid => rid.split('-')[1]; |
76 | 77 | Events.searchInline = () => {
|
77 | 78 | calcCategory();
|
78 | 79 | ready = start();
|
|
158 | 159 |
|
159 | 160 | window.on('styleDeleted', ({detail: {style: {id}}}) => {
|
160 | 161 | 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); |
165 | 167 | }
|
166 | 168 | });
|
167 | 169 |
|
168 | 170 | window.on('styleAdded', async ({detail: {style}}) => {
|
169 | 171 | 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]); |
173 | 178 | }
|
174 | 179 | });
|
175 | 180 |
|
|
209 | 214 | results = await search({retry});
|
210 | 215 | }
|
211 | 216 | 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 | + } |
215 | 221 | }
|
216 | 222 | if (!keepYears) resultsAllYears = results;
|
217 | 223 | renderYears();
|
|
330 | 336 | function createSearchResultNode(result) {
|
331 | 337 | const entry = t.template.searchResult.cloneNode(true);
|
332 | 338 | const {
|
333 |
| - i: id, |
| 339 | + i: rid, |
334 | 340 | n: name,
|
335 | 341 | r: rating,
|
336 | 342 | u: updateTime,
|
|
342 | 348 | sn: shot,
|
343 | 349 | f: fmt,
|
344 | 350 | } = entry._result = result;
|
345 |
| - entry.id = RESULT_ID_PREFIX + id; |
| 351 | + const id = rid2id(rid); |
| 352 | + entry.id = RESULT_ID_PREFIX + rid; |
346 | 353 | // title
|
347 | 354 | Object.assign($('.search-result-title', entry), {
|
348 | 355 | onclick: Events.openURLandHide,
|
|
421 | 428 | }
|
422 | 429 | }
|
423 | 430 |
|
424 |
| - function renderActionButtons(entry, installedId) { |
425 |
| - if (Number(entry)) { |
| 431 | + function renderActionButtons(entry) { |
| 432 | + if (typeof entry !== 'object') { |
426 | 433 | entry = $('#' + RESULT_ID_PREFIX + entry);
|
427 | 434 | }
|
428 | 435 | if (!entry) return;
|
429 | 436 | 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 |
435 | 439 | const status = $('.search-result-status', entry).textContent =
|
436 | 440 | isInstalled ? t('clickToUninstall') :
|
437 | 441 | entry.dataset.noImage != null ? t('installButton') :
|
438 | 442 | '';
|
439 |
| - const notMatching = installedId > 0 && !$entry(installedId); |
| 443 | + const notMatching = isInstalled && !$entry(installedId); |
440 | 444 | if (notMatching !== entry.classList.contains('not-matching')) {
|
441 | 445 | entry.classList.toggle('not-matching');
|
442 | 446 | if (notMatching) {
|
|
456 | 460 | disabled: notMatching,
|
457 | 461 | });
|
458 | 462 | toggleDataset(entry, 'installed', isInstalled);
|
| 463 | + toggleDataset(entry, 'customizable', result._styleVars); |
459 | 464 | }
|
460 | 465 |
|
461 | 466 | function renderFullInfo(entry, style) {
|
|
469 | 474 | textContent: description,
|
470 | 475 | title: description,
|
471 | 476 | });
|
| 477 | + vars = !isEmptyObj(vars); |
| 478 | + entry._result._styleVars = vars; |
472 | 479 | toggleDataset(entry, 'customizable', vars);
|
473 | 480 | }
|
474 | 481 |
|
475 | 482 | function configure() {
|
476 |
| - const styleEntry = $entry($resultEntry(this).result._installedStyleId); |
| 483 | + const styleEntry = $entry($resultEntry(this).result._styleId); |
477 | 484 | Events.configure.call(this, {target: styleEntry});
|
478 | 485 | }
|
479 | 486 |
|
480 | 487 | async function install() {
|
481 | 488 | const {entry, result} = $resultEntry(this);
|
482 |
| - const {i: id, f: fmt} = result; |
| 489 | + const {f: fmt} = result; |
| 490 | + const id = rid2id(result.i); |
483 | 491 | const installButton = $('.search-result-install', entry);
|
484 | 492 |
|
485 | 493 | showSpinner(entry);
|
|
507 | 515 | function uninstall() {
|
508 | 516 | const {entry, result} = $resultEntry(this);
|
509 | 517 | saveScrollPosition(entry);
|
510 |
| - API.styles.delete(result._installedStyleId); |
| 518 | + API.styles.delete(result._styleId); |
511 | 519 | }
|
512 | 520 |
|
513 | 521 | function saveScrollPosition(entry) {
|
|
553 | 561 | async function fetchIndex() {
|
554 | 562 | const timer = setTimeout(showSpinner, BUSY_DELAY, dom.list);
|
555 | 563 | 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]) => { |
559 | 567 | const res = transform(await download(url, {responseType: 'json'}));
|
| 568 | + for (const v of res) v.i = `${prefix}-${v.i}`; |
560 | 569 | index = index ? index.concat(res) : res;
|
561 | 570 | if (index !== res) ready = ready.then(start);
|
562 | 571 | });
|
|
607 | 616 | : b[order] - a[order]
|
608 | 617 | ) || b.t - a.t;
|
609 | 618 | }
|
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 |
| - } |
623 | 619 | })();
|
0 commit comments