fix merge conflict
This commit is contained in:
commit
dd34e0a64b
13 changed files with 138 additions and 159 deletions
|
@ -33,6 +33,7 @@ import {
|
|||
DeviceEventEmitter,
|
||||
Linking,
|
||||
NativeModules,
|
||||
StatusBar,
|
||||
TextInput,
|
||||
ToastAndroid,
|
||||
} from 'react-native';
|
||||
|
@ -50,7 +51,7 @@ import {
|
|||
selectHashChanged,
|
||||
selectUser,
|
||||
} from 'lbryinc';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { makeSelectClientSetting, selectFullscreenMode } from 'redux/selectors/settings';
|
||||
import { decode as atob } from 'base-64';
|
||||
import { dispatchNavigateBack, dispatchNavigateToUri, transformUrl } from 'utils/helper';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
|
@ -435,6 +436,26 @@ class AppWithNavigationState extends React.Component {
|
|||
if (backgroundPlayEnabled || NativeModules.BackgroundMedia) {
|
||||
NativeModules.BackgroundMedia.hidePlaybackNotification();
|
||||
}
|
||||
|
||||
// check fullscreen mode and show / hide navigation bar accordingly
|
||||
this.checkFullscreenMode();
|
||||
}
|
||||
};
|
||||
|
||||
checkFullscreenMode = () => {
|
||||
const { fullscreenMode } = this.props;
|
||||
StatusBar.setHidden(fullscreenMode);
|
||||
|
||||
if (fullscreenMode) {
|
||||
// fullscreen, so change orientation to landscape mode
|
||||
NativeModules.ScreenOrientation.lockOrientationLandscape();
|
||||
// hide the navigation bar (on devices that have the soft navigation bar)
|
||||
NativeModules.UtilityModule.hideNavigationBar();
|
||||
} else {
|
||||
// Switch back to portrait mode when the media is not fullscreen
|
||||
NativeModules.ScreenOrientation.lockOrientationPortrait();
|
||||
// hide the navigation bar (on devices that have the soft navigation bar)
|
||||
NativeModules.UtilityModule.showNavigationBar();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -489,6 +510,7 @@ const mapStateToProps = state => ({
|
|||
emailVerifyErrorMessage: selectEmailVerifyErrorMessage(state),
|
||||
showNsfw: makeSelectClientSetting(SETTINGS.SHOW_NSFW)(state),
|
||||
user: selectUser(state),
|
||||
fullscreenMode: selectFullscreenMode(state),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(AppWithNavigationState);
|
||||
|
|
|
@ -40,8 +40,8 @@ class FileListItem extends React.PureComponent {
|
|||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { claim, resolveUri, uri } = this.props;
|
||||
if (!claim) {
|
||||
const { claim, resolveUri, uri, batchResolve } = this.props;
|
||||
if (!claim && !batchResolve) {
|
||||
resolveUri(uri);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { connect } from 'react-redux';
|
||||
import {
|
||||
doResolveUris,
|
||||
makeSelectClaimForUri,
|
||||
makeSelectRecommendedContentForUri,
|
||||
makeSelectTitleForUri,
|
||||
selectIsSearching,
|
||||
} from 'lbry-redux';
|
||||
import { doNativeSearch } from 'redux/actions/performance';
|
||||
import RelatedContent from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
|
@ -16,7 +16,7 @@ const select = (state, props) => ({
|
|||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
search: query => dispatch(doNativeSearch(query, 20, undefined, true)),
|
||||
resolveUris: uris => dispatch(doResolveUris(uris)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -8,45 +8,23 @@ import fileListStyle from 'styles/fileList';
|
|||
import relatedContentStyle from 'styles/relatedContent';
|
||||
|
||||
export default class RelatedContent extends React.PureComponent {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.didSearch = undefined;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getRecommendedContent();
|
||||
}
|
||||
state = {
|
||||
urlsResolved: false,
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { claim, uri } = this.props;
|
||||
const { resolveUris, recommendedContent } = this.props;
|
||||
|
||||
if (uri !== prevProps.uri) {
|
||||
this.didSearch = false;
|
||||
}
|
||||
|
||||
if (claim && !this.didSearch) {
|
||||
this.getRecommendedContent();
|
||||
if (recommendedContent && recommendedContent.length > 0 && !this.state.urisResolved) {
|
||||
this.setState({ urisResolved: true }, () => {
|
||||
// batch resolve the uris
|
||||
resolveUris(recommendedContent);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getRecommendedContent() {
|
||||
const { search, title } = this.props;
|
||||
|
||||
if (title) {
|
||||
search(title);
|
||||
this.didSearch = true;
|
||||
}
|
||||
}
|
||||
|
||||
didSearch;
|
||||
|
||||
render() {
|
||||
const { recommendedContent, isSearching, navigation, uri, fullUri } = this.props;
|
||||
|
||||
if (!isSearching && (!recommendedContent || recommendedContent.length === 0)) {
|
||||
return null;
|
||||
}
|
||||
const { recommendedContent, navigation, uri, fullUri } = this.props;
|
||||
|
||||
return (
|
||||
<View style={relatedContentStyle.container}>
|
||||
|
@ -59,13 +37,11 @@ export default class RelatedContent extends React.PureComponent {
|
|||
style={fileListStyle.item}
|
||||
key={recommendedUri}
|
||||
uri={recommendedUri}
|
||||
batchResolve
|
||||
navigation={navigation}
|
||||
autoplay
|
||||
/>
|
||||
))}
|
||||
{isSearching && (
|
||||
<ActivityIndicator size="small" color={Colors.NextLbryGreen} style={relatedContentStyle.loading} />
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -66,6 +66,8 @@ const Constants = {
|
|||
ACTION_CLEAR_PUBLISH_FORM_STATE: 'CLEAR_PUBLISH_FORM_STATE',
|
||||
ACTION_CLEAR_CHANNEL_FORM_STATE: 'CLEAR_CHANNEL_FORM_STATE',
|
||||
|
||||
ACTION_FULLSCREEN_MODE_TOGGLED: 'FULLSCREEN_MODE_TOGGLED',
|
||||
|
||||
ORIENTATION_HORIZONTAL: 'horizontal',
|
||||
ORIENTATION_VERTICAL: 'vertical',
|
||||
|
||||
|
@ -129,7 +131,7 @@ const Constants = {
|
|||
{ name: TIME_ALL, label: __('All time') },
|
||||
],
|
||||
|
||||
DEFAULT_ORDER_BY: ['trending_global', 'trending_mixed'],
|
||||
DEFAULT_ORDER_BY: ['trending_group', 'trending_mixed'],
|
||||
|
||||
ORDER_BY_EFFECTIVE_AMOUNT: 'effective_amount',
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ class ChannelPage extends React.PureComponent {
|
|||
autoStyle: null,
|
||||
showSortPicker: false,
|
||||
showTimePicker: false,
|
||||
orderBy: Constants.DEFAULT_ORDER_BY,
|
||||
orderBy: ['release_time'], // sort by new by default
|
||||
activeTab: Constants.CONTENT_TAB,
|
||||
};
|
||||
|
||||
|
@ -48,8 +48,9 @@ class ChannelPage extends React.PureComponent {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { fetchChannelListMine } = this.props;
|
||||
const { fetchChannelListMine, setSortByItem } = this.props;
|
||||
NativeModules.Firebase.setCurrentScreen('Channel');
|
||||
setSortByItem(Constants.CLAIM_SEARCH_SORT_BY_ITEMS[1]); // sort by newest first
|
||||
fetchChannelListMine();
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
doPurchaseUri,
|
||||
doDeletePurchasedUri,
|
||||
doResolveUri,
|
||||
doSearch,
|
||||
doSendTip,
|
||||
doToast,
|
||||
makeSelectIsUriResolving,
|
||||
|
@ -17,6 +18,7 @@ import {
|
|||
makeSelectContentPositionForUri,
|
||||
makeSelectContentTypeForUri,
|
||||
makeSelectMetadataForUri,
|
||||
makeSelectRecommendedContentForUri,
|
||||
makeSelectStreamingUrlForUri,
|
||||
makeSelectThumbnailForUri,
|
||||
makeSelectTitleForUri,
|
||||
|
@ -26,6 +28,7 @@ import {
|
|||
selectPurchasedUris,
|
||||
selectFailedPurchaseUris,
|
||||
selectPurchaseUriErrorMessage,
|
||||
selectIsSearching,
|
||||
} from 'lbry-redux';
|
||||
import {
|
||||
doClaimEligiblePurchaseRewards,
|
||||
|
@ -42,6 +45,7 @@ import {
|
|||
doStopDownloadingFile,
|
||||
} from 'redux/actions/file';
|
||||
import { doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||
import { doToggleFullscreenMode } from 'redux/actions/settings';
|
||||
import { selectDrawerStack } from 'redux/selectors/drawer';
|
||||
import FilePage from './view';
|
||||
|
||||
|
@ -70,6 +74,8 @@ const select = (state, props) => {
|
|||
streamingUrl: makeSelectStreamingUrlForUri(contentUri)(state),
|
||||
thumbnail: makeSelectThumbnailForUri(contentUri)(state),
|
||||
title: makeSelectTitleForUri(contentUri)(state),
|
||||
recommendedContent: makeSelectRecommendedContentForUri(contentUri)(state),
|
||||
isSearchingRecommendContent: selectIsSearching(state),
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -89,6 +95,7 @@ const perform = dispatch => ({
|
|||
purchaseUri: (uri, costInfo, saveFile) => dispatch(doPurchaseUri(uri, costInfo, saveFile)),
|
||||
deletePurchasedUri: uri => dispatch(doDeletePurchasedUri(uri)),
|
||||
resolveUri: uri => dispatch(doResolveUri(uri)),
|
||||
searchRecommended: query => dispatch(doSearch(query, 20, undefined, true)),
|
||||
sendTip: (amount, claimId, isSupport, successCallback, errorCallback) =>
|
||||
dispatch(doSendTip(amount, claimId, isSupport, successCallback, errorCallback)),
|
||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(true)),
|
||||
|
@ -96,6 +103,7 @@ const perform = dispatch => ({
|
|||
startDownload: (uri, outpoint, fileInfo) => dispatch(doStartDownload(uri, outpoint, fileInfo)),
|
||||
updateDownload: (uri, outpoint, fileInfo, progress) => dispatch(doUpdateDownload(uri, outpoint, fileInfo, progress)),
|
||||
completeDownload: (uri, outpoint, fileInfo) => dispatch(doCompleteDownload(uri, outpoint, fileInfo)),
|
||||
toggleFullscreenMode: mode => dispatch(doToggleFullscreenMode(mode)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -61,6 +61,7 @@ class FilePage extends React.PureComponent {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
attemptAutoGet: false,
|
||||
autoPlayMedia: false,
|
||||
autoDownloadStarted: false,
|
||||
downloadButtonShown: false,
|
||||
|
@ -85,6 +86,7 @@ class FilePage extends React.PureComponent {
|
|||
uriVars: null,
|
||||
stopDownloadConfirmed: false,
|
||||
streamingMode: false,
|
||||
didSearchRecommended: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -185,12 +187,27 @@ class FilePage extends React.PureComponent {
|
|||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { claim, contentType, fileInfo, isResolvingUri, resolveUri, navigation } = this.props;
|
||||
const {
|
||||
claim,
|
||||
contentType,
|
||||
costInfo,
|
||||
fileInfo,
|
||||
isResolvingUri,
|
||||
resolveUri,
|
||||
navigation,
|
||||
purchaseUri,
|
||||
searchRecommended,
|
||||
title,
|
||||
} = this.props;
|
||||
const { uri } = this.state;
|
||||
if (!isResolvingUri && claim === undefined && uri) {
|
||||
resolveUri(uri);
|
||||
}
|
||||
|
||||
if (title && !this.state.didSearchRecommended) {
|
||||
this.setState({ didSearchRecommended: true }, () => searchRecommended(title));
|
||||
}
|
||||
|
||||
// Returned to the page. If mediaLoaded, and currentMediaInfo is different, update
|
||||
if (this.state.mediaLoaded && window.currentMediaInfo && window.currentMediaInfo.uri !== this.state.uri) {
|
||||
const { metadata } = this.props;
|
||||
|
@ -200,6 +217,21 @@ class FilePage extends React.PureComponent {
|
|||
uri: this.state.uri,
|
||||
};
|
||||
}
|
||||
|
||||
// attempt to retrieve images and html/text automatically once the claim is loaded, and it's free
|
||||
const mediaType = Lbry.getMediaType(contentType);
|
||||
const isViewable = mediaType === 'image' || mediaType === 'text';
|
||||
if (claim && costInfo && costInfo.cost === 0 && !this.state.autoGetAttempted && isViewable) {
|
||||
this.setState(
|
||||
{
|
||||
autoGetAttempted: true,
|
||||
downloadPressed: true,
|
||||
autoPlayMedia: true,
|
||||
stopDownloadConfirmed: false,
|
||||
},
|
||||
() => purchaseUri(claim.permanent_url, costInfo, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fetchFileInfo(props) {
|
||||
|
@ -214,25 +246,25 @@ class FilePage extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
handleFullscreenToggle = mode => {
|
||||
this.setState({ fullscreenMode: mode });
|
||||
StatusBar.setHidden(mode);
|
||||
if (NativeModules.ScreenOrientation) {
|
||||
if (mode) {
|
||||
// fullscreen, so change orientation to landscape mode
|
||||
NativeModules.ScreenOrientation.lockOrientationLandscape();
|
||||
if (NativeModules.UtilityModule) {
|
||||
// hide the navigation bar (on devices that use have soft navigation bar)
|
||||
NativeModules.UtilityModule.hideNavigationBar();
|
||||
}
|
||||
} else {
|
||||
// Switch back to portrait mode when the media is not fullscreen
|
||||
NativeModules.ScreenOrientation.lockOrientationPortrait();
|
||||
if (NativeModules.UtilityModule) {
|
||||
// hide the navigation bar (on devices that use have soft navigation bar)
|
||||
NativeModules.UtilityModule.showNavigationBar();
|
||||
}
|
||||
}
|
||||
handleFullscreenToggle = isFullscreen => {
|
||||
const { toggleFullscreenMode } = this.props;
|
||||
this.setState({ fullscreenMode: isFullscreen });
|
||||
toggleFullscreenMode(isFullscreen);
|
||||
|
||||
StatusBar.setHidden(isFullscreen);
|
||||
|
||||
if (isFullscreen) {
|
||||
// fullscreen, so change orientation to landscape mode
|
||||
NativeModules.ScreenOrientation.lockOrientationLandscape();
|
||||
|
||||
// hide the navigation bar (on devices that have the soft navigation bar)
|
||||
NativeModules.UtilityModule.hideNavigationBar();
|
||||
} else {
|
||||
// Switch back to portrait mode when the media is not fullscreen
|
||||
NativeModules.ScreenOrientation.lockOrientationPortrait();
|
||||
|
||||
// hide the navigation bar (on devices that have the soft navigation bar)
|
||||
NativeModules.UtilityModule.showNavigationBar();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -607,6 +639,8 @@ class FilePage extends React.PureComponent {
|
|||
navigation,
|
||||
position,
|
||||
purchaseUri,
|
||||
isSearchingRecommendContent,
|
||||
recommendedContent,
|
||||
thumbnail,
|
||||
title,
|
||||
} = this.props;
|
||||
|
@ -1106,7 +1140,13 @@ class FilePage extends React.PureComponent {
|
|||
)}
|
||||
|
||||
<View onLayout={this.setRelatedContentPosition} />
|
||||
<RelatedContent navigation={navigation} uri={uri} fullUri={fullUri} />
|
||||
|
||||
{isSearchingRecommendContent && (
|
||||
<ActivityIndicator size="small" color={Colors.NextLbryGreen} style={filePageStyle.relatedLoading} />
|
||||
)}
|
||||
{!isSearchingRecommendContent && recommendedContent && recommendedContent.length > 0 && (
|
||||
<RelatedContent navigation={navigation} uri={uri} fullUri={fullUri} />
|
||||
)}
|
||||
</ScrollView>
|
||||
</View>
|
||||
)}
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
// @flow
|
||||
import { NativeModules } from 'react-native';
|
||||
import {
|
||||
ACTIONS,
|
||||
batchActions,
|
||||
buildURI,
|
||||
doResolveUri,
|
||||
doUpdateSearchQuery,
|
||||
makeSelectSearchUris,
|
||||
selectSuggestions,
|
||||
makeSelectQueryWithOptions,
|
||||
selectSearchValue,
|
||||
} from 'lbry-redux';
|
||||
|
||||
let CONNECTION_STRING = 'https://lighthouse.lbry.com/';
|
||||
|
||||
const handleNativeFetchResponse = str => {
|
||||
const json = JSON.parse(str);
|
||||
if (json.error) {
|
||||
return Promise.reject(new Error(json.error));
|
||||
}
|
||||
|
||||
return Promise.resolve(json);
|
||||
};
|
||||
|
||||
// Use a native asyncTask to call the lighthouse api
|
||||
export const doNativeSearch = (
|
||||
rawQuery: string, // pass in a query if you don't want to search for what's in the search bar
|
||||
size: ?number, // only pass in if you don't want to use the users setting (ex: related content)
|
||||
from: ?number,
|
||||
isBackgroundSearch: boolean = false
|
||||
) => (dispatch: Dispatch, getState: GetState) => {
|
||||
const query = rawQuery.replace(/^lbry:\/\//i, '').replace(/\//, ' ');
|
||||
|
||||
if (!query) {
|
||||
dispatch({
|
||||
type: ACTIONS.SEARCH_FAIL,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const state = getState();
|
||||
const queryWithOptions = makeSelectQueryWithOptions(query, size, from, isBackgroundSearch)(state);
|
||||
|
||||
// If we have already searched for something, we don't need to do anything
|
||||
const urisForQuery = makeSelectSearchUris(queryWithOptions)(state);
|
||||
if (urisForQuery && !!urisForQuery.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.SEARCH_START,
|
||||
});
|
||||
|
||||
// If the user is on the file page with a pre-populated uri and they select
|
||||
// the search option without typing anything, searchQuery will be empty
|
||||
// We need to populate it so the input is filled on the search page
|
||||
// isBackgroundSearch means the search is happening in the background, don't update the search query
|
||||
if (!state.search.searchQuery && !isBackgroundSearch) {
|
||||
dispatch(doUpdateSearchQuery(query));
|
||||
}
|
||||
|
||||
const url = `${CONNECTION_STRING}search?${queryWithOptions}`;
|
||||
NativeModules.Requests.get(url)
|
||||
.then(handleNativeFetchResponse)
|
||||
.then((data: Array<{ name: String, claimId: string }>) => {
|
||||
const uris = [];
|
||||
const actions = [];
|
||||
|
||||
data.forEach(result => {
|
||||
if (result.name) {
|
||||
const uri = buildURI({
|
||||
claimName: result.name,
|
||||
claimId: result.claimId,
|
||||
});
|
||||
actions.push(doResolveUri(uri));
|
||||
uris.push(uri);
|
||||
}
|
||||
});
|
||||
|
||||
actions.push({
|
||||
type: ACTIONS.SEARCH_SUCCESS,
|
||||
data: {
|
||||
query: queryWithOptions,
|
||||
uris,
|
||||
},
|
||||
});
|
||||
dispatch(batchActions(...actions));
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch({
|
||||
type: ACTIONS.SEARCH_FAIL,
|
||||
});
|
||||
});
|
||||
};
|
|
@ -38,3 +38,14 @@ export function doSetTimeItem(item) {
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doToggleFullscreenMode(mode) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: Constants.ACTION_FULLSCREEN_MODE_TOGGLED,
|
||||
data: {
|
||||
mode,
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ const defaultState = {
|
|||
clientSettings: {},
|
||||
sortByItemName: Constants.SORT_BY_HOT,
|
||||
timeItemName: Constants.TIME_WEEK,
|
||||
fullscreenMode: false,
|
||||
};
|
||||
|
||||
reducers[ACTIONS.CLIENT_SETTING_CHANGED] = (state, action) => {
|
||||
|
@ -29,6 +30,11 @@ reducers[Constants.ACTION_TIME_ITEM_CHANGED] = (state, action) =>
|
|||
timeItemName: action.data.name,
|
||||
});
|
||||
|
||||
reducers[Constants.ACTION_FULLSCREEN_MODE_TOGGLED] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
fullscreenMode: action.data.mode,
|
||||
});
|
||||
|
||||
export default function reducer(state = defaultState, action) {
|
||||
const handler = reducers[action.type];
|
||||
if (handler) return handler(state, action);
|
||||
|
|
|
@ -34,3 +34,8 @@ export const makeSelectClientSetting = setting =>
|
|||
export const selectShowNsfw = makeSelectClientSetting(SETTINGS.SHOW_NSFW);
|
||||
|
||||
export const selectKeepDaemonRunning = makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING);
|
||||
|
||||
export const selectFullscreenMode = createSelector(
|
||||
selectState,
|
||||
state => state.fullscreenMode
|
||||
);
|
||||
|
|
|
@ -435,6 +435,9 @@ const filePageStyle = StyleSheet.create({
|
|||
fontSize: 16,
|
||||
marginTop: 4,
|
||||
},
|
||||
relatedLoading: {
|
||||
marginTop: 16,
|
||||
},
|
||||
});
|
||||
|
||||
export default filePageStyle;
|
||||
|
|
Loading…
Add table
Reference in a new issue