From 1162a11d4ed8b40987bf2e884999a6ccea05c992 Mon Sep 17 00:00:00 2001
From: Akinwale Ariwodola <akinwale@gmail.com>
Date: Sat, 10 Aug 2019 21:22:34 +0100
Subject: [PATCH 1/5] return lowercase tag names for unfollowed tags

---
 dist/bundle.es.js           | 2 +-
 src/redux/selectors/tags.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/dist/bundle.es.js b/dist/bundle.es.js
index 14e4c16..3cbd11d 100644
--- a/dist/bundle.es.js
+++ b/dist/bundle.es.js
@@ -4724,7 +4724,7 @@ const selectUnfollowedTags = reselect.createSelector(selectKnownTagsByName, sele
   Object.keys(tagsByName).forEach(key => {
     if (!followedTagsSet.has(key)) {
       const { name } = tagsByName[key];
-      tagsToReturn.push({ name });
+      tagsToReturn.push({ name: name.toLowerCase() });
     }
   });
 
diff --git a/src/redux/selectors/tags.js b/src/redux/selectors/tags.js
index d38d375..ec805a0 100644
--- a/src/redux/selectors/tags.js
+++ b/src/redux/selectors/tags.js
@@ -29,7 +29,7 @@ export const selectUnfollowedTags = createSelector(
     Object.keys(tagsByName).forEach(key => {
       if (!followedTagsSet.has(key)) {
         const { name } = tagsByName[key];
-        tagsToReturn.push({ name });
+        tagsToReturn.push({ name: name.toLowerCase() });
       }
     });
 
-- 
2.49.1


From 11cc6ec31d40a7950dd1ca86690c77bc5a81f6f6 Mon Sep 17 00:00:00 2001
From: Akinwale Ariwodola <akinwale@gmail.com>
Date: Sat, 10 Aug 2019 22:29:46 +0100
Subject: [PATCH 2/5] fix: thumbnail url

---
 dist/bundle.es.js            | 2 +-
 src/redux/actions/publish.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/dist/bundle.es.js b/dist/bundle.es.js
index 3cbd11d..34cee76 100644
--- a/dist/bundle.es.js
+++ b/dist/bundle.es.js
@@ -2925,7 +2925,7 @@ const doUploadThumbnail = (filePath, thumbnailBuffer, fsAdapter) => dispatch =>
         type: UPDATE_PUBLISH_FORM,
         data: {
           uploadThumbnailStatus: COMPLETE,
-          thumbnail: `${json.data.url}${fileExt}`
+          thumbnail: `${json.data.url}.${fileExt}`
         }
       }) : uploadError(json.message)).catch(err => uploadError(err.message));
     });
diff --git a/src/redux/actions/publish.js b/src/redux/actions/publish.js
index 38cb9bd..708654f 100644
--- a/src/redux/actions/publish.js
+++ b/src/redux/actions/publish.js
@@ -121,7 +121,7 @@ export const doUploadThumbnail = (
                 type: ACTIONS.UPDATE_PUBLISH_FORM,
                 data: {
                   uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE,
-                  thumbnail: `${json.data.url}${fileExt}`,
+                  thumbnail: `${json.data.url}.${fileExt}`,
                 },
               })
             : uploadError(json.message)
-- 
2.49.1


From 5c92a42f2bd9c227b4fe42686608d7a279f2685e Mon Sep 17 00:00:00 2001
From: Akinwale Ariwodola <akinwale@gmail.com>
Date: Tue, 13 Aug 2019 09:27:50 +0100
Subject: [PATCH 3/5] fix claim.meta.creation_timestamp check

---
 dist/bundle.es.js             | 2 +-
 src/redux/selectors/claims.js | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/dist/bundle.es.js b/dist/bundle.es.js
index 34cee76..1822b21 100644
--- a/dist/bundle.es.js
+++ b/dist/bundle.es.js
@@ -1392,7 +1392,7 @@ const makeSelectMetadataItemForUri = (uri, key) => reselect.createSelector(makeS
 const makeSelectTitleForUri = uri => reselect.createSelector(makeSelectMetadataForUri(uri), metadata => metadata && metadata.title);
 
 const makeSelectDateForUri = uri => reselect.createSelector(makeSelectClaimForUri(uri), claim => {
-  const timestamp = claim && claim.value && (claim.value.release_time ? claim.value.release_time * 1000 : claim.meta.creation_timestamp ? claim.meta.creation_timestamp * 1000 : null);
+  const timestamp = claim && claim.value && (claim.value.release_time ? claim.value.release_time * 1000 : claim.meta && claim.meta.creation_timestamp ? claim.meta.creation_timestamp * 1000 : null);
   if (!timestamp) {
     return undefined;
   }
diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js
index eac3390..276ebc0 100644
--- a/src/redux/selectors/claims.js
+++ b/src/redux/selectors/claims.js
@@ -222,9 +222,9 @@ export const makeSelectDateForUri = (uri: string) =>
         claim.value &&
         (claim.value.release_time
           ? claim.value.release_time * 1000
-          : claim.meta.creation_timestamp
-          ? claim.meta.creation_timestamp * 1000
-          : null);
+          : claim.meta && claim.meta.creation_timestamp
+            ? claim.meta.creation_timestamp * 1000
+            : null);
       if (!timestamp) {
         return undefined;
       }
-- 
2.49.1


From a46a16cf1adc9b08f06c1a469b4996ec2eeb02e2 Mon Sep 17 00:00:00 2001
From: Akinwale Ariwodola <akinwale@gmail.com>
Date: Tue, 13 Aug 2019 11:59:00 +0100
Subject: [PATCH 4/5] track if the last page reached was reached for
 claim_search queries

---
 dist/bundle.es.js             | 21 ++++++++++++++-------
 src/index.js                  |  1 +
 src/redux/actions/claims.js   |  8 +++++++-
 src/redux/actions/publish.js  | 34 +++++++++++++++++-----------------
 src/redux/reducers/claims.js  | 12 +++++++++++-
 src/redux/selectors/claims.js |  5 +++++
 6 files changed, 55 insertions(+), 26 deletions(-)

diff --git a/dist/bundle.es.js b/dist/bundle.es.js
index 1822b21..64532e9 100644
--- a/dist/bundle.es.js
+++ b/dist/bundle.es.js
@@ -7,8 +7,6 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'defau
 require('proxy-polyfill');
 var reselect = require('reselect');
 var uuid = _interopDefault(require('uuid/v4'));
-var fs = _interopDefault(require('fs'));
-var path = _interopDefault(require('path'));
 
 const MINIMUM_PUBLISH_BID = 0.00000001;
 
@@ -1570,6 +1568,8 @@ const selectFetchingClaimSearch = reselect.createSelector(selectFetchingClaimSea
 
 const selectClaimSearchByQuery = reselect.createSelector(selectState$1, state => state.claimSearchByQuery || {});
 
+const selectClaimSearchByQueryLastPageReached = reselect.createSelector(selectState$1, state => state.claimSearchByQueryLastPageReached || {});
+
 const makeSelectShortUrlForUri = uri => reselect.createSelector(makeSelectClaimForUri(uri), claim => claim && claim.short_url);
 
 const selectState$2 = state => state.wallet || {};
@@ -2403,7 +2403,7 @@ function doClaimSearch(options = {
 
       dispatch({
         type: CLAIM_SEARCH_COMPLETED,
-        data: { query, resolveInfo, uris, append: options.page && options.page !== 1 }
+        data: { query, resolveInfo, uris, append: options.page && options.page !== 1, pageSize: options.page_size }
       });
     };
 
@@ -2880,7 +2880,7 @@ const doUpdatePublishForm = publishFormValue => dispatch => dispatch({
   data: _extends$4({}, publishFormValue)
 });
 
-const doUploadThumbnail = (filePath, thumbnailBuffer, fsAdapter) => dispatch => {
+const doUploadThumbnail = (filePath, thumbnailBuffer, fsAdapter, fs, path) => dispatch => {
   let thumbnail, fileExt, fileName, fileType;
 
   const makeid = () => {
@@ -2963,7 +2963,7 @@ const doUploadThumbnail = (filePath, thumbnailBuffer, fsAdapter) => dispatch =>
   }
 };
 
-const doPrepareEdit = (claim, uri, fileInfo) => dispatch => {
+const doPrepareEdit = (claim, uri, fileInfo, fs) => dispatch => {
   const { name, amount, value } = claim;
   const channelName = claim && claim.signing_channel && claim.signing_channel.normalized_name || null;
   const {
@@ -3017,7 +3017,7 @@ const doPrepareEdit = (claim, uri, fileInfo) => dispatch => {
     publishData['channel'] = channelName;
   }
 
-  if (fileInfo && fileInfo.download_path) {
+  if (fs && fileInfo && fileInfo.download_path) {
     try {
       fs.accessSync(fileInfo.download_path, fs.constants.R_OK);
       publishData.filePath = fileInfo.download_path;
@@ -3462,6 +3462,7 @@ const defaultState = {
   pendingById: {},
   claimSearchError: false,
   claimSearchByQuery: {},
+  claimSearchByQueryLastPageReached: {},
   fetchingClaimSearchByQuery: {}
 };
 
@@ -3703,7 +3704,8 @@ reducers[CLAIM_SEARCH_STARTED] = (state, action) => {
 reducers[CLAIM_SEARCH_COMPLETED] = (state, action) => {
   const fetchingClaimSearchByQuery = Object.assign({}, state.fetchingClaimSearchByQuery);
   const claimSearchByQuery = Object.assign({}, state.claimSearchByQuery);
-  const { append, query, uris } = action.data;
+  const claimSearchByQueryLastPageReached = Object.assign({}, state.claimSearchByQueryLastPageReached);
+  const { append, query, uris, pageSize } = action.data;
 
   if (append) {
     // todo: check for duplicate uris when concatenating?
@@ -3712,10 +3714,14 @@ reducers[CLAIM_SEARCH_COMPLETED] = (state, action) => {
     claimSearchByQuery[query] = uris;
   }
 
+  // the returned number of uris is less than the page size, so we're on the last page
+  claimSearchByQueryLastPageReached[query] = uris.length < pageSize;
+
   delete fetchingClaimSearchByQuery[query];
 
   return Object.assign({}, state, _extends$5({}, handleClaimAction(state, action), {
     claimSearchByQuery,
+    claimSearchByQueryLastPageReached,
     fetchingClaimSearchByQuery
   }));
 };
@@ -4884,6 +4890,7 @@ exports.selectBlocks = selectBlocks;
 exports.selectChannelClaimCounts = selectChannelClaimCounts;
 exports.selectChannelIsBlocked = selectChannelIsBlocked;
 exports.selectClaimSearchByQuery = selectClaimSearchByQuery;
+exports.selectClaimSearchByQueryLastPageReached = selectClaimSearchByQueryLastPageReached;
 exports.selectClaimsById = selectClaimsById;
 exports.selectClaimsByUri = selectClaimsByUri;
 exports.selectCurrentChannelPage = selectCurrentChannelPage;
diff --git a/src/index.js b/src/index.js
index 2f93891..6a3bdc1 100644
--- a/src/index.js
+++ b/src/index.js
@@ -197,6 +197,7 @@ export {
   selectFetchingClaimSearch,
   selectFetchingClaimSearchByQuery,
   selectClaimSearchByQuery,
+  selectClaimSearchByQueryLastPageReached,
 } from 'redux/selectors/claims';
 
 export { makeSelectCommentsForUri } from 'redux/selectors/comments';
diff --git a/src/redux/actions/claims.js b/src/redux/actions/claims.js
index 902c87b..0f6e44e 100644
--- a/src/redux/actions/claims.js
+++ b/src/redux/actions/claims.js
@@ -336,7 +336,13 @@ export function doClaimSearch(
 
       dispatch({
         type: ACTIONS.CLAIM_SEARCH_COMPLETED,
-        data: { query, resolveInfo, uris, append: options.page && options.page !== 1 },
+        data: {
+          query,
+          resolveInfo,
+          uris,
+          append: options.page && options.page !== 1,
+          pageSize: options.page_size,
+        },
       });
     };
 
diff --git a/src/redux/actions/publish.js b/src/redux/actions/publish.js
index 708654f..69844c0 100644
--- a/src/redux/actions/publish.js
+++ b/src/redux/actions/publish.js
@@ -13,8 +13,6 @@ import {
   selectMyClaimsWithoutChannels,
 } from 'redux/selectors/claims';
 import { selectPublishFormValues, selectMyClaimForUri } from 'redux/selectors/publish';
-import fs from 'fs';
-import path from 'path';
 
 export const doResetThumbnailStatus = () => (dispatch: Dispatch) => {
   dispatch({
@@ -66,7 +64,9 @@ export const doUpdatePublishForm = (publishFormValue: UpdatePublishFormData) =>
 export const doUploadThumbnail = (
   filePath: string,
   thumbnailBuffer: Uint8Array,
-  fsAdapter: any
+  fsAdapter: any,
+  fs: any,
+  path: any
 ) => (dispatch: Dispatch) => {
   let thumbnail, fileExt, fileName, fileType;
 
@@ -118,12 +118,12 @@ export const doUploadThumbnail = (
         .then(json =>
           json.success
             ? dispatch({
-                type: ACTIONS.UPDATE_PUBLISH_FORM,
-                data: {
-                  uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE,
-                  thumbnail: `${json.data.url}.${fileExt}`,
-                },
-              })
+              type: ACTIONS.UPDATE_PUBLISH_FORM,
+              data: {
+                uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE,
+                thumbnail: `${json.data.url}.${fileExt}`,
+              },
+            })
             : uploadError(json.message)
         )
         .catch(err => uploadError(err.message));
@@ -157,19 +157,19 @@ export const doUploadThumbnail = (
       .then(json =>
         json.success
           ? dispatch({
-              type: ACTIONS.UPDATE_PUBLISH_FORM,
-              data: {
-                uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE,
-                thumbnail: `${json.data.url}${fileExt}`,
-              },
-            })
+            type: ACTIONS.UPDATE_PUBLISH_FORM,
+            data: {
+              uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE,
+              thumbnail: `${json.data.url}${fileExt}`,
+            },
+          })
           : uploadError(json.message)
       )
       .catch(err => uploadError(err.message));
   }
 };
 
-export const doPrepareEdit = (claim: StreamClaim, uri: string, fileInfo: FileListItem) => (
+export const doPrepareEdit = (claim: StreamClaim, uri: string, fileInfo: FileListItem, fs: any) => (
   dispatch: Dispatch
 ) => {
   const { name, amount, value } = claim;
@@ -226,7 +226,7 @@ export const doPrepareEdit = (claim: StreamClaim, uri: string, fileInfo: FileLis
     publishData['channel'] = channelName;
   }
 
-  if (fileInfo && fileInfo.download_path) {
+  if (fs && fileInfo && fileInfo.download_path) {
     try {
       fs.accessSync(fileInfo.download_path, fs.constants.R_OK);
       publishData.filePath = fileInfo.download_path;
diff --git a/src/redux/reducers/claims.js b/src/redux/reducers/claims.js
index a001d3a..58520c2 100644
--- a/src/redux/reducers/claims.js
+++ b/src/redux/reducers/claims.js
@@ -23,6 +23,7 @@ type State = {
   fetchingMyChannels: boolean,
   fetchingClaimSearchByQuery: { [string]: boolean },
   claimSearchByQuery: { [string]: Array<string> },
+  claimSearchByQueryLastPageReached: { [string]: Array<boolean> },
   claimsByChannel: {
     [string]: {
       all: Array<string>,
@@ -47,6 +48,7 @@ const defaultState = {
   pendingById: {},
   claimSearchError: false,
   claimSearchByQuery: {},
+  claimSearchByQueryLastPageReached: {},
   fetchingClaimSearchByQuery: {},
 };
 
@@ -299,7 +301,11 @@ reducers[ACTIONS.CLAIM_SEARCH_STARTED] = (state: State, action: any): State => {
 reducers[ACTIONS.CLAIM_SEARCH_COMPLETED] = (state: State, action: any): State => {
   const fetchingClaimSearchByQuery = Object.assign({}, state.fetchingClaimSearchByQuery);
   const claimSearchByQuery = Object.assign({}, state.claimSearchByQuery);
-  const { append, query, uris } = action.data;
+  const claimSearchByQueryLastPageReached = Object.assign(
+    {},
+    state.claimSearchByQueryLastPageReached
+  );
+  const { append, query, uris, pageSize } = action.data;
 
   if (append) {
     // todo: check for duplicate uris when concatenating?
@@ -311,11 +317,15 @@ reducers[ACTIONS.CLAIM_SEARCH_COMPLETED] = (state: State, action: any): State =>
     claimSearchByQuery[query] = uris;
   }
 
+  // the returned number of uris is less than the page size, so we're on the last page
+  claimSearchByQueryLastPageReached[query] = uris.length < pageSize;
+
   delete fetchingClaimSearchByQuery[query];
 
   return Object.assign({}, state, {
     ...handleClaimAction(state, action),
     claimSearchByQuery,
+    claimSearchByQueryLastPageReached,
     fetchingClaimSearchByQuery,
   });
 };
diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js
index 276ebc0..896fb76 100644
--- a/src/redux/selectors/claims.js
+++ b/src/redux/selectors/claims.js
@@ -515,6 +515,11 @@ export const selectClaimSearchByQuery = createSelector(
   state => state.claimSearchByQuery || {}
 );
 
+export const selectClaimSearchByQueryLastPageReached = createSelector(
+  selectState,
+  state => state.claimSearchByQueryLastPageReached || {}
+);
+
 export const makeSelectClaimSearchUrisByOptions = (options: {}) =>
   createSelector(
     selectClaimSearchByQuery,
-- 
2.49.1


From 95b9c3dbcd164ff05421aafd5174185227cec04b Mon Sep 17 00:00:00 2001
From: Akinwale Ariwodola <akinwale@gmail.com>
Date: Tue, 13 Aug 2019 16:21:03 +0100
Subject: [PATCH 5/5] fix CLAIM_SEARCH_FAILED reducer

---
 dist/bundle.es.js            | 10 ++++++++--
 src/redux/reducers/claims.js |  2 +-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/dist/bundle.es.js b/dist/bundle.es.js
index 64532e9..4626cbb 100644
--- a/dist/bundle.es.js
+++ b/dist/bundle.es.js
@@ -2403,7 +2403,13 @@ function doClaimSearch(options = {
 
       dispatch({
         type: CLAIM_SEARCH_COMPLETED,
-        data: { query, resolveInfo, uris, append: options.page && options.page !== 1, pageSize: options.page_size }
+        data: {
+          query,
+          resolveInfo,
+          uris,
+          append: options.page && options.page !== 1,
+          pageSize: options.page_size
+        }
       });
     };
 
@@ -3728,7 +3734,7 @@ reducers[CLAIM_SEARCH_COMPLETED] = (state, action) => {
 
 reducers[CLAIM_SEARCH_FAILED] = (state, action) => {
   const fetchingClaimSearchByQuery = Object.assign({}, state.fetchingClaimSearchByQuery);
-  fetchingClaimSearchByQuery[action.data.tags] = false;
+  delete fetchingClaimSearchByQuery[action.data.query];
 
   return Object.assign({}, state, {
     fetchingClaimSearchByQuery
diff --git a/src/redux/reducers/claims.js b/src/redux/reducers/claims.js
index 58520c2..ba94348 100644
--- a/src/redux/reducers/claims.js
+++ b/src/redux/reducers/claims.js
@@ -332,7 +332,7 @@ reducers[ACTIONS.CLAIM_SEARCH_COMPLETED] = (state: State, action: any): State =>
 
 reducers[ACTIONS.CLAIM_SEARCH_FAILED] = (state: State, action: any): State => {
   const fetchingClaimSearchByQuery = Object.assign({}, state.fetchingClaimSearchByQuery);
-  fetchingClaimSearchByQuery[action.data.tags] = false;
+  delete fetchingClaimSearchByQuery[action.data.query];
 
   return Object.assign({}, state, {
     fetchingClaimSearchByQuery,
-- 
2.49.1