Show rating & install counts in results. Remove artifical delays.

This commit is contained in:
derv82 2017-12-02 17:25:01 -08:00
parent 0fcc6c3596
commit 02260ff65d
4 changed files with 105 additions and 21 deletions

View File

@ -353,6 +353,18 @@
"message": "Search on userstyles.org",
"description": "Text for a link that searches for styles for this current site on userstyles.org"
},
"searchResultsHeader": {
"message": "Results for",
"description": "Text for label above search results"
},
"searchResultRating": {
"message": "Rating",
"description": "Text for label that shows the search result's rating"
},
"searchResultInstallCount": {
"message": "Installs",
"description": "Text for label that shows the number of times a search result was installed"
},
"searchResultInstall": {
"message": "Install",
"description": "Text for a button that installs a search result"

View File

@ -90,6 +90,16 @@
By:
<a class="searchResult-authorLink" target="_blank"></a>
</div>
<div class="searchResult-meta">
<div class="searchResult-metaRating">
<span i18n-text="searchResultRating"></span>:
<span class="searchResult-rating"></span>
</div>
<div class="searchResult-metaInstallCounts">
<span i18n-text="searchResultInstallCount"></span>:
<span class="searchResult-installCount"></span>
</div>
</div>
<div class="actions">
<button class="searchResult-install" i18n-text="searchResultInstall" i18n-title="searchResultInstallTooltip"></button>
</div>
@ -133,7 +143,10 @@
</div>
</div>
<div id="searchResults" class="hidden">
<h3>Search Results for <span id="searchResults-terms">-</span></h3>
<h3>
<span i18n-text="searchResultsHeader"></span>
<span id="searchResults-terms">...</span>
</h3>
<div id="searchResultsNav">
<button id="searchResultsNav-prev" title="Previous page" disabled>Prev</button>
<label>
@ -152,7 +165,7 @@
i18n-text="findStylesForSite"></a>
</div>
<div id="searchResults-error" class="hidden"></div>
<div id="open-search">
<div id="open-search" class="hidden">
<a id="open-search-link" href="https://userstyles.org/styles/browse/"
i18n-text="openSearchWebsite"></a>
</div>

View File

@ -10,7 +10,8 @@
#searchResults.hidden,
#searchResults-error.hidden,
#find-styles.hidden {
#find-styles.hidden,
#open-search.hidden {
display: none;
}
@ -62,6 +63,37 @@
white-space: nowrap;
}
.searchResult-author {
display: none;
}
.searchResult-meta {
display: table;
width: 100%;
}
.searchResult-metaRating, .searchResult-metaInstallCount {
display: table-cell;
}
.searchResult-rating {
font-weight: 600;
padding: 1px 2px 1px 2px;
color: #fff;
}
.searchResult-rating.good {
background-color: darkgreen;
}
.searchResult-rating.okay {
background-color: darkorange;
}
.searchResult-rating.bad {
background-color: darkred;
}
.searchResult-rating.none {
background-color: #333;
}
.searchResult-install {
width: 100%;
}

View File

@ -116,7 +116,7 @@ function SearchUserstyles() {
*/
const SearchResults = (() => {
const DISPLAYED_RESULTS_PER_PAGE = 3; // Number of results to display in popup.html
const DELAY_AFTER_FETCHING_STYLES = 500; // Millisecs to wait before fetching next batch of search results.
const DELAY_AFTER_FETCHING_STYLES = 0; // Millisecs to wait before fetching next batch of search results.
const DELAY_BEFORE_SEARCHING_STYLES = 0; // Millisecs to wait before fetching .JSON for next search result.
const searchAPI = SearchUserstyles();
const unprocessedResults = []; // Search results not yet processed.
@ -126,8 +126,6 @@ const SearchResults = (() => {
let loading = false;
let tabURL; // The active tab's URL.
let currentDisplayedPage = 1; // Current page number in popup.html
let nonApplicableResults = 0; // Number of results that don't apply to the searched site (thx userstyles.org!)
let alreadyInstalledResults = 0; // Number of results that are already installed.
return {load, next, prev};
@ -169,6 +167,9 @@ const SearchResults = (() => {
}
}
/**
* @returns {Boolean} If we should process more results.
*/
function shouldLoadMore() {
const result = (processedResults.length < currentDisplayedPage * DISPLAYED_RESULTS_PER_PAGE);
console.log('shouldLoadMore:',
@ -230,7 +231,7 @@ const SearchResults = (() => {
}
/**
* Loads search result for the (page number is currentPage).
* Initializes search results container, starts fetching results.
* @param {Object} event The click event
*/
function load(event) {
@ -254,6 +255,7 @@ const SearchResults = (() => {
}
$('#find-styles').classList.add('hidden');
$('#open-search').classList.remove('hidden');
$('#searchResults').classList.remove('hidden');
$('#searchResults-error').classList.add('hidden');
@ -281,6 +283,12 @@ const SearchResults = (() => {
return true;
}
/**
* Processes the next search result in `unprocessedResults` and adds to `processedResults`.
* Skips installed/non-applicable styles.
* Fetches more search results if unprocessedResults is empty.
* Recurses until shouldLoadMore() is false.
*/
function processNextResult() {
if (!shouldLoadMore()) {
console.log('[' + unprocessedResults.length + '] search results remain to be processed: STOPPED');
@ -305,13 +313,11 @@ const SearchResults = (() => {
// TODO: Include the style anyway with option to "Uninstall" (?)
console.log('[' + unprocessedResults.length + '] style "' + nextResult.name +
'" already installed: CONTINUING');
alreadyInstalledResults += 1;
setTimeout(processNextResult, DELAY_AFTER_FETCHING_STYLES); // Keep processing
setTimeout(processNextResult, 0); // Keep processing
} else if (nextResult.category !== 'site') {
// Style is not for a website, skip it.
console.log('[' + unprocessedResults.length + '] style "' + nextResult.name +
'" category is for "' + nextResult.category + '", not "site": CONTINUING');
nonApplicableResults += 1;
setTimeout(processNextResult, 0); // Keep processing
} else {
// Style not installed, fetch full style to see if it applies to this site.
@ -324,10 +330,7 @@ const SearchResults = (() => {
matchUrl: tabURL,
stopOnFirst: true
});
if (applicableSections.length === 0) {
// Style is invalid (does not apply to this site).
nonApplicableResults += 1;
} else {
if (applicableSections.length > 0) {
// Style is valid (can apply to this site).
nextResult.json = userstyleJson; // Store Style JSON for easy installing later.
processedResults.push(nextResult);
@ -335,8 +338,6 @@ const SearchResults = (() => {
}
console.log('[' + unprocessedResults.length + '] Processed "' + nextResult.name + '"',
'processedResults=' + processedResults.length,
'skipped-installed=' + alreadyInstalledResults,
'skipped-irrelevant=' + nonApplicableResults,
'CONTINUING @ sleep=' + DELAY_AFTER_FETCHING_STYLES);
setTimeout(processNextResult, DELAY_AFTER_FETCHING_STYLES); // Keep processing
})
@ -358,7 +359,7 @@ const SearchResults = (() => {
return new Promise(function (resolve, reject) {
getStylesSafe()
.then(installedStyles => {
console.log('Seeing if searchResult(', userstyleSearchResult, ') is in matchingStyles');
console.log('Seeing if searchResult(', userstyleSearchResult.name, ') is in matchingStyles');
const matchingStyles = installedStyles.filter(installedStyle => {
// Compare installed name to search result name.
let isMatch = installedStyle.name === userstyleSearchResult.name;
@ -391,7 +392,7 @@ const SearchResults = (() => {
}
}
*/
console.log('createSearchResultNode(', userstyleSearchResult, ')');
console.log('createSearchResultNode(', userstyleSearchResult.name, ')');
if (userstyleSearchResult.installed) {
return;
@ -406,8 +407,8 @@ const SearchResults = (() => {
const searchResultName = userstyleSearchResult.name;
const title = $('.searchResult-title', entry);
Object.assign(title, {
textContent: searchResultName,
title: searchResultName,
textContent: searchResultName + ' (by ' + userstyleSearchResult.user.name + ')',
title: searchResultName + ' by: ' + userstyleSearchResult.user.name,
href: 'https://userstyles.org' + userstyleSearchResult.url,
onclick: handleEvent.openURLandHide
});
@ -424,7 +425,7 @@ const SearchResults = (() => {
}
Object.assign(screenshot, {
src: screenshotUrl,
title: searchResultName
title: '"' + searchResultName + '" by ' + userstyleSearchResult.user.name
});
// TODO: Expand/collapse description
@ -442,6 +443,32 @@ const SearchResults = (() => {
onclick: handleEvent.openURLandHide
});
const rating = $('.searchResult-rating', entry);
let ratingClass;
let ratingValue = userstyleSearchResult.rating;
if (ratingValue === null) {
ratingClass = 'none';
ratingValue = 'n/a';
} else if (ratingValue >= 2.5) {
ratingClass = 'good';
ratingValue = ratingValue.toFixed(1);
} else if (ratingValue >= 1.5) {
ratingClass = 'okay';
ratingValue = ratingValue.toFixed(1);
} else {
ratingClass = 'bad';
ratingValue = ratingValue.toFixed(1);
}
Object.assign(rating, {
textContent: ratingValue,
className: 'searchResult-rating ' + ratingClass
});
const installCount = $('.searchResult-installCount', entry);
Object.assign(installCount, {
textContent: userstyleSearchResult.total_install_count.toLocaleString()
});
// TODO: Total & Weekly Install Counts
// TODO: Rating