diff --git a/dist/bundle.js b/dist/bundle.js index 415a22c..2145df6 100644 --- a/dist/bundle.js +++ b/dist/bundle.js @@ -299,7 +299,7 @@ Object.defineProperty(exports, 'doBlurSearchInput', { } }); -var _blacklist = __webpack_require__(34); +var _blacklist = __webpack_require__(35); Object.defineProperty(exports, 'doBlackListedOutpointsSubscribe', { enumerable: true, @@ -452,7 +452,7 @@ Object.defineProperty(exports, 'creditsToString', { } }); -var _claims2 = __webpack_require__(35); +var _claims2 = __webpack_require__(36); Object.defineProperty(exports, 'claimsReducer', { enumerable: true, @@ -461,7 +461,7 @@ Object.defineProperty(exports, 'claimsReducer', { } }); -var _cost_info2 = __webpack_require__(36); +var _cost_info2 = __webpack_require__(37); Object.defineProperty(exports, 'costInfoReducer', { enumerable: true, @@ -470,7 +470,7 @@ Object.defineProperty(exports, 'costInfoReducer', { } }); -var _file_info2 = __webpack_require__(37); +var _file_info2 = __webpack_require__(38); Object.defineProperty(exports, 'fileInfoReducer', { enumerable: true, @@ -479,7 +479,7 @@ Object.defineProperty(exports, 'fileInfoReducer', { } }); -var _notifications2 = __webpack_require__(40); +var _notifications2 = __webpack_require__(41); Object.defineProperty(exports, 'notificationsReducer', { enumerable: true, @@ -488,7 +488,7 @@ Object.defineProperty(exports, 'notificationsReducer', { } }); -var _search2 = __webpack_require__(42); +var _search2 = __webpack_require__(43); Object.defineProperty(exports, 'searchReducer', { enumerable: true, @@ -497,7 +497,7 @@ Object.defineProperty(exports, 'searchReducer', { } }); -var _wallet2 = __webpack_require__(43); +var _wallet2 = __webpack_require__(44); Object.defineProperty(exports, 'walletReducer', { enumerable: true, @@ -506,7 +506,7 @@ Object.defineProperty(exports, 'walletReducer', { } }); -var _blacklist2 = __webpack_require__(44); +var _blacklist2 = __webpack_require__(45); Object.defineProperty(exports, 'blacklistReducer', { enumerable: true, @@ -515,7 +515,7 @@ Object.defineProperty(exports, 'blacklistReducer', { } }); -var _blacklist3 = __webpack_require__(45); +var _blacklist3 = __webpack_require__(46); Object.defineProperty(exports, 'selectBlackListedOutpoints', { enumerable: true, @@ -524,7 +524,7 @@ Object.defineProperty(exports, 'selectBlackListedOutpoints', { } }); -var _notifications3 = __webpack_require__(46); +var _notifications3 = __webpack_require__(47); Object.defineProperty(exports, 'selectToast', { enumerable: true, @@ -782,7 +782,7 @@ Object.defineProperty(exports, 'selectChannelClaimCounts', { } }); -var _cost_info3 = __webpack_require__(47); +var _cost_info3 = __webpack_require__(48); Object.defineProperty(exports, 'makeSelectFetchingCostInfoForUri', { enumerable: true, @@ -1203,7 +1203,7 @@ var _action_types = __webpack_require__(2); var ACTIONS = _interopRequireWildcard(_action_types); -var _thumbnail_upload_statuses = __webpack_require__(48); +var _thumbnail_upload_statuses = __webpack_require__(49); var THUMBNAIL_STATUSES = _interopRequireWildcard(_thumbnail_upload_statuses); @@ -1211,7 +1211,7 @@ var _search4 = __webpack_require__(22); var SEARCH_TYPES = _interopRequireWildcard(_search4); -var _settings = __webpack_require__(49); +var _settings = __webpack_require__(50); var SETTINGS = _interopRequireWildcard(_settings); @@ -1219,11 +1219,11 @@ var _transaction_types = __webpack_require__(27); var TRANSACTIONS = _interopRequireWildcard(_transaction_types); -var _sort_options = __webpack_require__(38); +var _sort_options = __webpack_require__(39); var SORT_OPTIONS = _interopRequireWildcard(_sort_options); -var _pages = __webpack_require__(39); +var _pages = __webpack_require__(40); var PAGES = _interopRequireWildcard(_pages); @@ -5156,7 +5156,11 @@ var _search = __webpack_require__(21); var _batchActions = __webpack_require__(24); -var _handleFetch = __webpack_require__(33); +var _debounce = __webpack_require__(33); + +var _debounce2 = _interopRequireDefault(_debounce); + +var _handleFetch = __webpack_require__(34); var _handleFetch2 = _interopRequireDefault(_handleFetch); @@ -5164,15 +5168,16 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } -// @flow -var DEFAULTSEARCHRESULTSIZE = 10; +var DEFAULTSEARCHRESULTSIZE = 10; // @flow + var DEFAULTSEARCHRESULTFROM = 0; +var DEBOUNCED_SEARCH_SUGGESTION_MS = 300; /*:: type Dispatch = (action: any) => any;*/ /*:: type GetState = () => {};*/ -var doSearch = exports.doSearch = function doSearch(rawQuery) { - var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULTSEARCHRESULTSIZE; - var from = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULTSEARCHRESULTFROM; - var isBackgroundSearch = arguments[3]; +var doSearch = exports.doSearch = function doSearch(rawQuery /*: string*/) { + var size /*: number*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULTSEARCHRESULTSIZE; + var from /*: number*/ = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULTSEARCHRESULTFROM; + var isBackgroundSearch /*: boolean*/ = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; return function (dispatch /*: Dispatch*/, getState /*: GetState*/) { var state = getState(); var query = rawQuery.replace(/^lbry:\/\//i, '').replace(/\//, ' '); @@ -5267,6 +5272,10 @@ var getSearchSuggestions = exports.getSearchSuggestions = function getSearchSugg }; }; +var throttledSearchSuggestions = (0, _debounce2.default)(function (dispatch, query) { + dispatch(getSearchSuggestions(query)); +}, DEBOUNCED_SEARCH_SUGGESTION_MS); + var doUpdateSearchQuery = exports.doUpdateSearchQuery = function doUpdateSearchQuery(query /*: string*/, shouldSkipSuggestions /*: ?boolean*/) { return function (dispatch /*: Dispatch*/) { dispatch({ @@ -5276,7 +5285,7 @@ var doUpdateSearchQuery = exports.doUpdateSearchQuery = function doUpdateSearchQ // Don't fetch new suggestions if the user just added a space if (!query.endsWith(' ') || !shouldSkipSuggestions) { - dispatch(getSearchSuggestions(query)); + throttledSearchSuggestions(dispatch, query); } }; }; @@ -5304,6 +5313,39 @@ var doBlurSearchInput = exports.doBlurSearchInput = function doBlurSearchInput() "use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = debouce; +// Returns a function, that, as long as it continues to be invoked, will not +// be triggered. The function will be called after it stops being called for +// N milliseconds. If `immediate` is passed, trigger the function on the +// leading edge, instead of the trailing. +function debouce(func, wait, immediate) { + var timeout = void 0; + + return function () { + var context = this; + var args = arguments; + var later = function later() { + timeout = null; + if (!immediate) func.apply(context, args); + }; + + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; +} + +/***/ }), +/* 34 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + Object.defineProperty(exports, "__esModule", { value: true }); @@ -5313,7 +5355,7 @@ function handleFetchResponse(response) { } /***/ }), -/* 34 */ +/* 35 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5396,7 +5438,7 @@ function doBlackListedOutpointsSubscribe() { } /***/ }), -/* 35 */ +/* 36 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5721,7 +5763,7 @@ function claimsReducer() { } /***/ }), -/* 36 */ +/* 37 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5779,7 +5821,7 @@ function costInfoReducer() { } /***/ }), -/* 37 */ +/* 38 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5797,11 +5839,11 @@ var _action_types = __webpack_require__(2); var ACTIONS = _interopRequireWildcard(_action_types); -var _sort_options = __webpack_require__(38); +var _sort_options = __webpack_require__(39); var SORT_OPTIONS = _interopRequireWildcard(_sort_options); -var _pages = __webpack_require__(39); +var _pages = __webpack_require__(40); var PAGES = _interopRequireWildcard(_pages); @@ -6021,7 +6063,7 @@ function fileInfoReducer() { } /***/ }), -/* 38 */ +/* 39 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6036,7 +6078,7 @@ var TITLE = exports.TITLE = 'title'; var FILENAME = exports.FILENAME = 'filename'; /***/ }), -/* 39 */ +/* 40 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6068,7 +6110,7 @@ var HISTORY = exports.HISTORY = 'user_history'; var WALLET = exports.WALLET = 'wallet'; /***/ }), -/* 40 */ +/* 41 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6087,7 +6129,7 @@ var _action_types = __webpack_require__(2); var ACTIONS = _interopRequireWildcard(_action_types); -var _reduxUtils = __webpack_require__(41); +var _reduxUtils = __webpack_require__(42); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } @@ -6175,7 +6217,7 @@ var notificationsReducer = (0, _reduxUtils.handleActions)((_handleActions = {}, exports.notificationsReducer = notificationsReducer; /***/ }), -/* 41 */ +/* 42 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6208,7 +6250,7 @@ var handleActions = exports.handleActions = function handleActions(actionMap, de }; /***/ }), -/* 42 */ +/* 43 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6228,7 +6270,7 @@ var _action_types = __webpack_require__(2); var ACTIONS = _interopRequireWildcard(_action_types); -var _reduxUtils = __webpack_require__(41); +var _reduxUtils = __webpack_require__(42); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } @@ -6333,7 +6375,7 @@ var searchReducer = exports.searchReducer = (0, _reduxUtils.handleActions)((_han }), _handleActions), defaultState); /***/ }), -/* 43 */ +/* 44 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6676,7 +6718,7 @@ function walletReducer() { } /***/ }), -/* 44 */ +/* 45 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6695,7 +6737,7 @@ var _action_types = __webpack_require__(2); var ACTIONS = _interopRequireWildcard(_action_types); -var _reduxUtils = __webpack_require__(41); +var _reduxUtils = __webpack_require__(42); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } @@ -6735,7 +6777,7 @@ var blacklistReducer = exports.blacklistReducer = (0, _reduxUtils.handleActions) }), _handleActions), defaultState); /***/ }), -/* 45 */ +/* 46 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6757,7 +6799,7 @@ var selectBlackListedOutpoints = exports.selectBlackListedOutpoints = (0, _resel }); /***/ }), -/* 46 */ +/* 47 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6803,7 +6845,7 @@ var selectError = exports.selectError = (0, _reselect.createSelector)(selectStat }); /***/ }), -/* 47 */ +/* 48 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6847,7 +6889,7 @@ var makeSelectFetchingCostInfoForUri = exports.makeSelectFetchingCostInfoForUri }; /***/ }), -/* 48 */ +/* 49 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6863,7 +6905,7 @@ var COMPLETE = exports.COMPLETE = 'complete'; var MANUAL = exports.MANUAL = 'manual'; /***/ }), -/* 49 */ +/* 50 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; diff --git a/src/redux/actions/search.js b/src/redux/actions/search.js index a3d8416..d0c26fb 100644 --- a/src/redux/actions/search.js +++ b/src/redux/actions/search.js @@ -4,18 +4,20 @@ import { buildURI } from 'lbryURI'; import { doResolveUri } from 'redux/actions/claims'; import { makeSelectSearchUris, selectSuggestions } from 'redux/selectors/search'; import { batchActions } from 'util/batchActions'; +import debounce from 'util/debounce'; import handleFetchResponse from 'util/handle-fetch'; const DEFAULTSEARCHRESULTSIZE = 10; const DEFAULTSEARCHRESULTFROM = 0; +const DEBOUNCED_SEARCH_SUGGESTION_MS = 300; type Dispatch = (action: any) => any; type GetState = () => {}; export const doSearch = ( - rawQuery, - size = DEFAULTSEARCHRESULTSIZE, - from = DEFAULTSEARCHRESULTFROM, - isBackgroundSearch + rawQuery: string, + size: number = DEFAULTSEARCHRESULTSIZE, + from: number = DEFAULTSEARCHRESULTFROM, + isBackgroundSearch: boolean = false ) => (dispatch: Dispatch, getState: GetState) => { const state = getState(); const query = rawQuery.replace(/^lbry:\/\//i, '').replace(/\//, ' '); @@ -51,11 +53,11 @@ export const doSearch = ( const encodedQuery = encodeURIComponent(query); fetch(`https://lighthouse.lbry.io/search?s=${encodedQuery}&size=${size}&from=${from}`) .then(handleFetchResponse) - .then(data => { + .then((data) => { const uris = []; const actions = []; - data.forEach(result => { + data.forEach((result) => { const uri = buildURI({ claimName: result.name, claimId: result.claimId, @@ -98,7 +100,7 @@ export const getSearchSuggestions = (value: string) => (dispatch: Dispatch, getS fetch(`https://lighthouse.lbry.io/autocomplete?s=${searchValue}`) .then(handleFetchResponse) - .then(apiSuggestions => { + .then((apiSuggestions) => { dispatch({ type: ACTIONS.UPDATE_SEARCH_SUGGESTIONS, data: { @@ -113,6 +115,10 @@ export const getSearchSuggestions = (value: string) => (dispatch: Dispatch, getS }); }; +const throttledSearchSuggestions = debounce((dispatch, query) => { + dispatch(getSearchSuggestions(query)); +}, DEBOUNCED_SEARCH_SUGGESTION_MS); + export const doUpdateSearchQuery = (query: string, shouldSkipSuggestions: ?boolean) => ( dispatch: Dispatch ) => { @@ -123,7 +129,7 @@ export const doUpdateSearchQuery = (query: string, shouldSkipSuggestions: ?boole // Don't fetch new suggestions if the user just added a space if (!query.endsWith(' ') || !shouldSkipSuggestions) { - dispatch(getSearchSuggestions(query)); + throttledSearchSuggestions(dispatch, query); } }; diff --git a/src/util/debounce.js b/src/util/debounce.js new file mode 100644 index 0000000..f702f7b --- /dev/null +++ b/src/util/debounce.js @@ -0,0 +1,21 @@ +// Returns a function, that, as long as it continues to be invoked, will not +// be triggered. The function will be called after it stops being called for +// N milliseconds. If `immediate` is passed, trigger the function on the +// leading edge, instead of the trailing. +export default function debouce(func, wait, immediate) { + let timeout; + + return function() { + const context = this; + const args = arguments; + const later = () => { + timeout = null; + if (!immediate) func.apply(context, args); + }; + + const callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; +}