From 6fe9e9a5f7219861397641ec45237b01612500e8 Mon Sep 17 00:00:00 2001
From: Akinwale Ariwodola <akinwale@gmail.com>
Date: Tue, 10 Dec 2019 16:29:16 +0100
Subject: [PATCH 1/2] fixes before next release

---
 src/constants.js          |   7 +-
 src/page/file/index.js    |   3 +-
 src/page/file/view.js     | 152 +++++++++++++++++++++++++-------------
 src/page/settings/view.js |  53 +++++++------
 src/page/splash/view.js   |   2 +-
 src/styles/filePage.js    |   8 +-
 src/utils/helper.js       |  14 ++++
 7 files changed, 156 insertions(+), 83 deletions(-)

diff --git a/src/constants.js b/src/constants.js
index 1f7c7d7..9bae614 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -95,6 +95,7 @@ const Constants = {
   FULL_ROUTE_NAME_WALLET: 'WalletStack',
 
   ROUTE_FILE: 'File',
+  DRAWER_ROUTE_FILE_VIEW: 'FileView',
 
   ITEM_CREATE_A_CHANNEL: 'Create a channel...',
   ITEM_ANONYMOUS: 'Publish anonymously',
@@ -167,4 +168,8 @@ export const DrawerRoutes = [
 ];
 
 // sub-pages for main routes
-export const InnerDrawerRoutes = [Constants.DRAWER_ROUTE_CHANNEL_CREATOR_FORM, Constants.DRAWER_ROUTE_PUBLISH_FORM];
+export const InnerDrawerRoutes = [
+  Constants.DRAWER_ROUTE_CHANNEL_CREATOR_FORM,
+  Constants.DRAWER_ROUTE_PUBLISH_FORM,
+  Constants.DRAWER_ROUTE_FILE_VIEW,
+];
diff --git a/src/page/file/index.js b/src/page/file/index.js
index 4fd413a..71a9ddc 100644
--- a/src/page/file/index.js
+++ b/src/page/file/index.js
@@ -44,7 +44,7 @@ import {
   doDeleteFile,
   doStopDownloadingFile,
 } from 'redux/actions/file';
-import { doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
+import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
 import { doToggleFullscreenMode } from 'redux/actions/settings';
 import { selectDrawerStack } from 'redux/selectors/drawer';
 import FilePage from './view';
@@ -92,6 +92,7 @@ const perform = dispatch => ({
   fileGet: (uri, saveFile) => dispatch(doFileGet(uri, saveFile)),
   notify: data => dispatch(doToast(data)),
   popDrawerStack: () => dispatch(doPopDrawerStack()),
+  pushDrawerStack: (routeName, params) => dispatch(doPushDrawerStack(routeName, params)),
   purchaseUri: (uri, costInfo, saveFile) => dispatch(doPurchaseUri(uri, costInfo, saveFile)),
   deletePurchasedUri: uri => dispatch(doDeletePurchasedUri(uri)),
   resolveUri: uri => dispatch(doResolveUri(uri)),
diff --git a/src/page/file/view.js b/src/page/file/view.js
index 394a12b..31af1af 100644
--- a/src/page/file/view.js
+++ b/src/page/file/view.js
@@ -44,6 +44,7 @@ import Video from 'react-native-video';
 import FileRewardsDriver from 'component/fileRewardsDriver';
 import filePageStyle from 'styles/filePage';
 import uriBarStyle from 'styles/uriBar';
+import _ from 'lodash';
 
 class FilePage extends React.PureComponent {
   static navigationOptions = {
@@ -62,8 +63,9 @@ class FilePage extends React.PureComponent {
     super(props);
     this.state = {
       attemptAutoGet: false,
-      autoPlayMedia: false,
+      autoOpened: false,
       autoDownloadStarted: false,
+      autoPlayMedia: false,
       downloadButtonShown: false,
       downloadPressed: false,
       fileViewLogged: false,
@@ -127,6 +129,17 @@ class FilePage extends React.PureComponent {
     this.onComponentFocused();
   }
 
+  difference = (object, base) => {
+    function changes(object, base) {
+      return _.transform(object, function(result, value, key) {
+        if (!_.isEqual(value, base[key])) {
+          result[key] = _.isObject(value) && _.isObject(base[key]) ? changes(value, base[key]) : value;
+        }
+      });
+    }
+    return changes(object, base);
+  };
+
   componentWillReceiveProps(nextProps) {
     const {
       claim,
@@ -136,6 +149,7 @@ class FilePage extends React.PureComponent {
       navigation,
       contentType,
       notify,
+      drawerStack: prevDrawerStack,
     } = this.props;
     const { uri } = navigation.state.params;
     const {
@@ -145,6 +159,7 @@ class FilePage extends React.PureComponent {
       purchasedUris,
       purchaseUriErrorMessage,
       streamingUrl,
+      drawerStack,
     } = nextProps;
 
     if (Constants.ROUTE_FILE === currentRoute && currentRoute !== prevRoute) {
@@ -184,6 +199,17 @@ class FilePage extends React.PureComponent {
         this.setState({ streamingMode: true, currentStreamUrl: fileInfo.streaming_url });
       }
     }
+
+    if (
+      prevDrawerStack[prevDrawerStack.length - 1].route === Constants.DRAWER_ROUTE_FILE_VIEW &&
+      prevDrawerStack.length !== drawerStack.length
+    ) {
+      this.setState({
+        downloadPressed: false,
+        showImageViewer: false,
+        showWebView: false,
+      });
+    }
   }
 
   componentDidUpdate(prevProps) {
@@ -633,6 +659,39 @@ class FilePage extends React.PureComponent {
     }
   };
 
+  openFile = (localFileUri, mediaType) => {
+    const { pushDrawerStack } = this.props;
+    const isWebViewable = mediaType === 'text';
+
+    if (mediaType === 'image') {
+      // use image viewer
+      if (!this.state.showImageViewer) {
+        this.setState(
+          {
+            imageUrls: [
+              {
+                url: localFileUri,
+              },
+            ],
+            showImageViewer: true,
+          },
+          () => pushDrawerStack(Constants.DRAWER_ROUTE_FILE_VIEW)
+        );
+      }
+    }
+    if (isWebViewable) {
+      // show webview
+      if (!this.state.showWebView) {
+        this.setState(
+          {
+            showWebView: true,
+          },
+          () => pushDrawerStack(Constants.DRAWER_ROUTE_FILE_VIEW)
+        );
+      }
+    }
+  };
+
   render() {
     const {
       balance,
@@ -651,6 +710,7 @@ class FilePage extends React.PureComponent {
       navigation,
       position,
       purchaseUri,
+      pushDrawerStack,
       isSearchingRecommendContent,
       recommendedContent,
       thumbnail,
@@ -746,6 +806,7 @@ class FilePage extends React.PureComponent {
       const description = metadata.description ? metadata.description : null;
       const mediaType = Lbry.getMediaType(contentType);
       const isPlayable = mediaType === 'video' || mediaType === 'audio';
+      const isWebViewable = mediaType === 'text';
       const { height, signing_channel: signingChannel, value } = claim;
       const channelName = signingChannel && signingChannel.name;
       const channelClaimId = claim && claim.signing_channel && claim.signing_channel.claim_id;
@@ -784,35 +845,10 @@ class FilePage extends React.PureComponent {
         (fileInfo && (fileInfo.written_bytes >= 2097152 || fileInfo.written_bytes === fileInfo.total_bytes)); // 2MB = 1024*1024*2
       const duration = claim && claim.value && claim.value.video ? claim.value.video.duration : null;
       const isViewable = mediaType === 'image' || mediaType === 'text';
-      const isWebViewable = mediaType === 'text';
       const canOpen = isViewable && completed;
       const localFileUri = this.localUriForFileInfo(fileInfo);
       const unsupported = !isPlayable && !canOpen;
 
-      const openFile = () => {
-        if (mediaType === 'image') {
-          // use image viewer
-          if (!this.state.showImageViewer) {
-            this.setState({
-              imageUrls: [
-                {
-                  url: localFileUri,
-                },
-              ],
-              showImageViewer: true,
-            });
-          }
-        }
-        if (isWebViewable) {
-          // show webview
-          if (!this.state.showWebView) {
-            this.setState({
-              showWebView: true,
-            });
-          }
-        }
-      };
-
       if (fileInfo && !this.state.autoDownloadStarted && this.state.uriVars && this.state.uriVars.download === 'true') {
         this.setState({ autoDownloadStarted: true }, () => {
           purchaseUri(uri, costInfo, !isPlayable);
@@ -822,9 +858,9 @@ class FilePage extends React.PureComponent {
         });
       }
 
-      if (this.state.downloadPressed && canOpen) {
+      if (this.state.downloadPressed && canOpen && !this.state.autoOpened) {
         // automatically open a web viewable or image file after the download button is pressed
-        openFile();
+        this.setState({ autoOpened: true }, () => this.openFile(localFileUri, mediaType));
       }
 
       return (
@@ -889,7 +925,7 @@ class FilePage extends React.PureComponent {
                   <FileDownloadButton
                     uri={claim && claim.permanent_url ? claim.permanent_url : uri}
                     style={filePageStyle.downloadButton}
-                    openFile={openFile}
+                    openFile={() => this.openFile(localFileUri, mediaType)}
                     isPlayable={isPlayable}
                     isViewable={isViewable}
                     onPlay={this.onFileDownloadButtonPlayed}
@@ -975,7 +1011,7 @@ class FilePage extends React.PureComponent {
 
                 <View style={filePageStyle.largeButtonsRow}>
                   <TouchableOpacity style={filePageStyle.largeButton} onPress={this.handleSharePress}>
-                    <Icon name={'share-alt'} size={20} style={filePageStyle.largeButtonIcon} />
+                    <Icon name={'share-alt'} size={16} style={filePageStyle.largeButtonIcon} />
                     <Text style={filePageStyle.largeButtonText}>{__('Share')}</Text>
                   </TouchableOpacity>
 
@@ -983,51 +1019,61 @@ class FilePage extends React.PureComponent {
                     style={filePageStyle.largeButton}
                     onPress={() => this.setState({ showTipView: true })}
                   >
-                    <Icon name={'gift'} size={20} style={filePageStyle.largeButtonIcon} />
+                    <Icon name={'gift'} size={16} style={filePageStyle.largeButtonIcon} />
                     <Text style={filePageStyle.largeButtonText}>{__('Tip')}</Text>
                   </TouchableOpacity>
 
-                  <View style={filePageStyle.sharedLargeButton}>
-                    {!isPlayable && !fileInfo && (
-                      <TouchableOpacity style={filePageStyle.innerLargeButton} onPress={this.onDownloadPressed}>
-                        <Icon name={'download'} size={20} style={filePageStyle.largeButtonIcon} />
-                        <Text style={filePageStyle.largeButtonText}>{__('Download')}</Text>
-                      </TouchableOpacity>
-                    )}
+                  {!canEdit && (
+                    <View style={filePageStyle.sharedLargeButton}>
+                      {!fileInfo ||
+                        (fileInfo.written_bytes <= 0 && !completed && (
+                          <TouchableOpacity style={filePageStyle.innerLargeButton} onPress={this.onDownloadPressed}>
+                            <Icon name={'download'} size={16} style={filePageStyle.largeButtonIcon} />
+                            <Text style={filePageStyle.largeButtonText}>{__('Download')}</Text>
+                          </TouchableOpacity>
+                        ))}
 
-                    {!completed &&
-                      fileInfo &&
-                      !fileInfo.stopped &&
-                      fileInfo.written_bytes > 0 &&
-                      fileInfo.written_bytes < fileInfo.total_bytes &&
-                      !this.state.stopDownloadConfirmed && (
-                      <TouchableOpacity style={filePageStyle.innerLargeButton} onPress={this.onStopDownloadPressed}>
-                        <Icon name={'stop'} size={20} style={filePageStyle.largeButtonIcon} />
-                        <Text style={filePageStyle.largeButtonText}>{__('Stop')}</Text>
-                      </TouchableOpacity>
-                    )}
-                  </View>
+                      {!completed &&
+                        fileInfo &&
+                        !fileInfo.stopped &&
+                        fileInfo.written_bytes > 0 &&
+                        fileInfo.written_bytes < fileInfo.total_bytes &&
+                        !this.state.stopDownloadConfirmed && (
+                        <TouchableOpacity style={filePageStyle.innerLargeButton} onPress={this.onStopDownloadPressed}>
+                          <Icon name={'stop'} size={16} style={filePageStyle.largeButtonIcon} />
+                          <Text style={filePageStyle.largeButtonText}>{__('Stop')}</Text>
+                        </TouchableOpacity>
+                      )}
+
+                      {completed && fileInfo && fileInfo.written_bytes >= fileInfo.total_bytes && (
+                        <TouchableOpacity style={filePageStyle.innerLargeButton} onPress={this.onOpenFilePressed}>
+                          <Icon name={'folder-open'} size={16} style={filePageStyle.largeButtonIcon} />
+                          <Text style={filePageStyle.largeButtonText}>{__('Open')}</Text>
+                        </TouchableOpacity>
+                      )}
+                    </View>
+                  )}
 
                   {!canEdit && (
                     <TouchableOpacity
                       style={filePageStyle.largeButton}
                       onPress={() => Linking.openURL(`https://lbry.com/dmca/${claim.claim_id}`)}
                     >
-                      <Icon name={'flag'} size={20} style={filePageStyle.largeButtonIcon} />
+                      <Icon name={'flag'} size={16} style={filePageStyle.largeButtonIcon} />
                       <Text style={filePageStyle.largeButtonText}>{__('Report')}</Text>
                     </TouchableOpacity>
                   )}
 
                   {canEdit && (
                     <TouchableOpacity style={filePageStyle.largeButton} onPress={this.onEditPressed}>
-                      <Icon name={'edit'} size={20} style={filePageStyle.largeButtonIcon} />
+                      <Icon name={'edit'} size={16} style={filePageStyle.largeButtonIcon} />
                       <Text style={filePageStyle.largeButtonText}>{__('Edit')}</Text>
                     </TouchableOpacity>
                   )}
 
                   {(completed || canEdit) && (
                     <TouchableOpacity style={filePageStyle.largeButton} onPress={this.onDeletePressed}>
-                      <Icon name={'trash-alt'} size={20} style={filePageStyle.largeButtonIcon} />
+                      <Icon name={'trash-alt'} size={16} style={filePageStyle.largeButtonIcon} />
                       <Text style={filePageStyle.largeButtonText}>{__('Delete')}</Text>
                     </TouchableOpacity>
                   )}
diff --git a/src/page/settings/view.js b/src/page/settings/view.js
index 0860bf4..53bcd25 100644
--- a/src/page/settings/view.js
+++ b/src/page/settings/view.js
@@ -11,7 +11,6 @@ import settingsStyle from 'styles/settings';
 
 const languageOptions = [
   { code: 'default', name: 'Use device language' },
-  { code: 'ar', name: 'Arabic' },
   { code: 'en', name: 'English' },
   { code: 'gu', name: 'Gujarati' },
   { code: 'hi', name: 'Hindi' },
@@ -90,33 +89,41 @@ class SettingsPage extends React.PureComponent {
     }
 
     // check the local filesystem for the language first? Or download remote strings first?
+    if (language === 'en') {
+      // don't attempt to download English
+      NativeModules.UtilityModule.setNativeStringSetting(SETTINGS.LANGUAGE, language);
 
-    // download and save the language file
-    this.setState({ downloadingLanguage: true }, () => {
-      fetch('https://lbry.com/i18n/get/lbry-mobile/app-strings/' + language + '.json')
-        .then(r => r.json())
-        .then(j => {
-          window.i18n_messages[language] = j;
+      // update state and client setting
+      window.language = language;
+      setClientSetting(SETTINGS.LANGUAGE, value);
+    } else {
+      // download and save the language file
+      this.setState({ downloadingLanguage: true }, () => {
+        fetch('https://lbry.com/i18n/get/lbry-mobile/app-strings/' + language + '.json')
+          .then(r => r.json())
+          .then(j => {
+            window.i18n_messages[language] = j;
 
-          // write the language file to the filesystem
-          const langFilePath = RNFS.ExternalDirectoryPath + '/' + language + '.json';
-          RNFS.writeFile(langFilePath, JSON.stringify(j), 'utf8');
+            // write the language file to the filesystem
+            const langFilePath = RNFS.ExternalDirectoryPath + '/' + language + '.json';
+            RNFS.writeFile(langFilePath, JSON.stringify(j), 'utf8');
 
-          // save the setting outside redux because when the first component mounts, the redux value isn't loaded yet
-          // so we have to load it from native settings
-          NativeModules.UtilityModule.setNativeStringSetting(SETTINGS.LANGUAGE, value);
+            // save the setting outside redux because when the first component mounts, the redux value isn't loaded yet
+            // so we have to load it from native settings
+            NativeModules.UtilityModule.setNativeStringSetting(SETTINGS.LANGUAGE, language);
 
-          // update state and client setting
-          window.language = language;
-          setClientSetting(SETTINGS.LANGUAGE, value);
+            // update state and client setting
+            window.language = language;
+            setClientSetting(SETTINGS.LANGUAGE, value);
 
-          this.setState({ downloadingLanguage: false });
-        })
-        .catch(e => {
-          notify({ message: __('Failed to load %language% translations.', { language: language }), isError: true });
-          this.setState({ downloadingLanguage: false });
-        });
-    });
+            this.setState({ downloadingLanguage: false });
+          })
+          .catch(e => {
+            notify({ message: __('Failed to load %language% translations.', { language: language }), isError: true });
+            this.setState({ downloadingLanguage: false });
+          });
+      });
+    }
   };
 
   handleBackPressed = () => {
diff --git a/src/page/splash/view.js b/src/page/splash/view.js
index 3250202..c4eeb93 100644
--- a/src/page/splash/view.js
+++ b/src/page/splash/view.js
@@ -235,7 +235,7 @@ class SplashScreen extends React.PureComponent {
     }
 
     if (headerSyncProgress < 100) {
-      const downloadProgress = isNaN(parseInt(headerSyncProgress, 10)) ? '0' : headerSyncProgress;
+      const downloadProgress = isNaN(parseInt(headerSyncProgress, 10)) ? '0' : headerSyncProgress || '0';
       this.setState({
         message: __('Blockchain Sync'),
         details: __('Catching up with the blockchain (%progress%%)', { progress: downloadProgress }),
diff --git a/src/styles/filePage.js b/src/styles/filePage.js
index 078b53b..0c2ae8e 100644
--- a/src/styles/filePage.js
+++ b/src/styles/filePage.js
@@ -384,7 +384,7 @@ const filePageStyle = StyleSheet.create({
   sharedLargeButton: {
     alignItems: 'center',
     justifyContent: 'center',
-    marginRight: 36,
+    flex: 0.2,
   },
   innerLargeButton: {
     alignItems: 'center',
@@ -393,7 +393,7 @@ const filePageStyle = StyleSheet.create({
   largeButton: {
     alignItems: 'center',
     justifyContent: 'center',
-    marginRight: 36,
+    flex: 0.2,
   },
   largeButtonIcon: {
     color: Colors.DescriptionGrey,
@@ -406,8 +406,8 @@ const filePageStyle = StyleSheet.create({
   largeButtonsRow: {
     flexDirection: 'row',
     alignItems: 'center',
-    marginLeft: 20,
-    marginRight: 20,
+    marginLeft: 16,
+    marginRight: 16,
     marginTop: 12,
     marginBottom: 12,
   },
diff --git a/src/utils/helper.js b/src/utils/helper.js
index 4b94ac7..bf3e938 100644
--- a/src/utils/helper.js
+++ b/src/utils/helper.js
@@ -155,6 +155,14 @@ export function navigateToUri(navigation, uri, additionalParams, isNavigatingBac
 }
 
 export function navigateBack(navigation, drawerStack, popDrawerStack) {
+  if (drawerStack[drawerStack.length - 1].route === Constants.DRAWER_ROUTE_FILE_VIEW) {
+    // inner file_view (web / image view) is handled differently
+    if (popDrawerStack) {
+      popDrawerStack();
+    }
+    return;
+  }
+
   if (popDrawerStack) {
     popDrawerStack();
   }
@@ -186,6 +194,12 @@ export function navigateBack(navigation, drawerStack, popDrawerStack) {
 }
 
 export function dispatchNavigateBack(dispatch, nav, drawerStack) {
+  if (drawerStack[drawerStack.length - 1].route === Constants.DRAWER_ROUTE_FILE_VIEW) {
+    // inner file_view (web / image view) is handled differently
+    dispatch(doPopDrawerStack());
+    return;
+  }
+
   dispatch(doPopDrawerStack());
 
   const target = drawerStack[drawerStack.length > 1 ? drawerStack.length - 2 : 0];
-- 
2.49.1


From 18b7117765735d1c674c892b873c2e03a463253b Mon Sep 17 00:00:00 2001
From: Akinwale Ariwodola <akinwale@gmail.com>
Date: Wed, 11 Dec 2019 09:04:19 +0100
Subject: [PATCH 2/2] make channel sort by selection component-specific

---
 src/page/channel/view.js       | 22 +++++++++++-----------
 src/page/file/view.js          |  2 +-
 src/page/subscriptions/view.js |  2 +-
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/page/channel/view.js b/src/page/channel/view.js
index 1363a24..3f15e5f 100644
--- a/src/page/channel/view.js
+++ b/src/page/channel/view.js
@@ -38,6 +38,7 @@ class ChannelPage extends React.PureComponent {
     showTimePicker: false,
     orderBy: ['release_time'], // sort by new by default
     activeTab: Constants.CONTENT_TAB,
+    currentSortByItem: Constants.CLAIM_SEARCH_SORT_BY_ITEMS[1], // should always default to sorting channel pages by new
   };
 
   componentWillMount() {
@@ -48,16 +49,14 @@ class ChannelPage extends React.PureComponent {
   }
 
   componentDidMount() {
-    const { fetchChannelListMine, setSortByItem } = this.props;
+    const { fetchChannelListMine } = this.props;
     NativeModules.Firebase.setCurrentScreen('Channel');
-    setSortByItem(Constants.CLAIM_SEARCH_SORT_BY_ITEMS[1]); // sort by newest first
     fetchChannelListMine();
   }
 
   handleSortByItemSelected = item => {
-    const { setSortByItem } = this.props;
-    setSortByItem(item);
-    this.setState({ orderBy: getOrderBy(item), showSortPicker: false });
+    // sort by specific only to this component state
+    this.setState({ currentSortByItem: item, orderBy: getOrderBy(item), showSortPicker: false });
   };
 
   handleTimeItemSelected = item => {
@@ -67,17 +66,18 @@ class ChannelPage extends React.PureComponent {
   };
 
   listHeader = () => {
-    const { sortByItem, timeItem } = this.props;
+    const { timeItem } = this.props;
+    const { currentSortByItem } = this.state;
 
     return (
       <View style={channelPageStyle.listHeader}>
         <View style={discoverStyle.pickerRow}>
           <View style={discoverStyle.leftPickerRow}>
             <TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}>
-              <Text style={discoverStyle.tagSortText}>{__(sortByItem.label.split(' ')[0])}</Text>
+              <Text style={discoverStyle.tagSortText}>{__(currentSortByItem.label.split(' ')[0])}</Text>
               <Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
             </TouchableOpacity>
-            {Constants.SORT_BY_TOP === sortByItem.name && (
+            {Constants.SORT_BY_TOP === currentSortByItem.name && (
               <TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
                 <Text style={discoverStyle.tagSortText}>{__(timeItem.label)}</Text>
                 <Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
@@ -207,9 +207,9 @@ class ChannelPage extends React.PureComponent {
   };
 
   render() {
-    const { channels, claim, navigation, uri, drawerStack, popDrawerStack, sortByItem, timeItem } = this.props;
+    const { channels, claim, navigation, uri, drawerStack, popDrawerStack, timeItem } = this.props;
     const { name, permanent_url: permanentUrl } = claim;
-    const { autoStyle, showSortPicker, showTimePicker } = this.state;
+    const { autoStyle, currentSortByItem, showSortPicker, showTimePicker } = this.state;
     const ownedChannel = channels ? channels.map(channel => channel.permanent_url).includes(permanentUrl) : false;
 
     let thumbnailUrl,
@@ -327,7 +327,7 @@ class ChannelPage extends React.PureComponent {
             title={__('Sort content by')}
             onOverlayPress={() => this.setState({ showSortPicker: false })}
             onItemSelected={this.handleSortByItemSelected}
-            selectedItem={sortByItem}
+            selectedItem={currentSortByItem}
             items={Constants.CLAIM_SEARCH_SORT_BY_ITEMS}
           />
         )}
diff --git a/src/page/file/view.js b/src/page/file/view.js
index 31af1af..b7a5381 100644
--- a/src/page/file/view.js
+++ b/src/page/file/view.js
@@ -1023,7 +1023,7 @@ class FilePage extends React.PureComponent {
                     <Text style={filePageStyle.largeButtonText}>{__('Tip')}</Text>
                   </TouchableOpacity>
 
-                  {!canEdit && (
+                  {!canEdit && !isPlayable && (
                     <View style={filePageStyle.sharedLargeButton}>
                       {!fileInfo ||
                         (fileInfo.written_bytes <= 0 && !completed && (
diff --git a/src/page/subscriptions/view.js b/src/page/subscriptions/view.js
index 97de6f9..e7f5352 100644
--- a/src/page/subscriptions/view.js
+++ b/src/page/subscriptions/view.js
@@ -243,7 +243,7 @@ class SubscriptionsPage extends React.PureComponent {
             title={__('Sort content by')}
             onOverlayPress={() => this.setState({ showSortPicker: false })}
             onItemSelected={this.handleSortByItemSelected}
-            selectedItem={this.state.currentSortByItem}
+            selectedItem={currentSortByItem}
             items={Constants.CLAIM_SEARCH_SORT_BY_ITEMS}
           />
         )}
-- 
2.49.1