diff --git a/App/Config/ReduxPersist.ts b/App/Config/ReduxPersist.ts index 833a878b2..93ae3cbd9 100644 --- a/App/Config/ReduxPersist.ts +++ b/App/Config/ReduxPersist.ts @@ -186,13 +186,26 @@ const migrations: MigrationManifest = { } } } + }, + 11: (persistedState) => { + const state = persistedState as any + return { + ...state, + preferences: { + ...state.preferences, + tourScreens: { + ...state.preferences.tourScreens, + location: true + } + } + } } } const persistConfig: PersistConfig = { key: 'primary', storage: AsyncStorage, - version: 10, + version: 11, whitelist: ['preferences', 'uploadingImages', 'processingImages', 'cameraRoll', 'storage', 'deviceLogs'], migrate: createMigrate(migrations, { debug: false }) } diff --git a/App/Redux/PreferencesRedux.ts b/App/Redux/PreferencesRedux.ts index b97f3e341..ccc71ca17 100644 --- a/App/Redux/PreferencesRedux.ts +++ b/App/Redux/PreferencesRedux.ts @@ -37,7 +37,7 @@ const actions = { export type PreferencesAction = ActionType -export type TourScreens = 'wallet' | 'threads' | 'threadView' | 'notifications' | 'feed' +export type TourScreens = 'wallet' | 'threads' | 'threadView' | 'notifications' | 'feed' | 'location' export type ServiceType = 'backgroundLocation' | 'notifications' | 'photoAddedNotification' | @@ -75,7 +75,8 @@ export const initialState: PreferencesState = { threads: true, threadView: true, notifications: true, - feed: true + feed: true, + location: true }, services: { notifications: { @@ -97,7 +98,7 @@ export const initialState: PreferencesState = { status: true }, peerJoinedNotification: { - status: false + status: true }, peerLeftNotification: { status: false diff --git a/App/Redux/__tests__/__snapshots__/PreferencesRedux.ts.snap b/App/Redux/__tests__/__snapshots__/PreferencesRedux.ts.snap index 4849c4723..b6892f809 100644 --- a/App/Redux/__tests__/__snapshots__/PreferencesRedux.ts.snap +++ b/App/Redux/__tests__/__snapshots__/PreferencesRedux.ts.snap @@ -20,7 +20,7 @@ Object { "status": false, }, "peerJoinedNotification": Object { - "status": false, + "status": true, }, "peerLeftNotification": Object { "status": false, @@ -51,6 +51,7 @@ Object { }, "tourScreens": Object { "feed": true, + "location": true, "notifications": true, "threadView": true, "threads": true, diff --git a/App/SB/views/ThreadDetail/index.js b/App/SB/views/ThreadDetail/index.js index d7f4e7a91..a0e495808 100644 --- a/App/SB/views/ThreadDetail/index.js +++ b/App/SB/views/ThreadDetail/index.js @@ -1,6 +1,6 @@ import React from 'react' import { connect } from 'react-redux' -import { View, FlatList, Text, Image } from 'react-native' +import { Alert, View, FlatList, Text, Image } from 'react-native' import { NavigationActions } from 'react-navigation' import { TextileHeaderButtons, Item } from '../../../Components/HeaderButtons' @@ -18,7 +18,7 @@ import ProcessingImagesActions from '../../../Redux/ProcessingImagesRedux' import { Photo } from '../../../Models/TextileTypes' import ActionSheet from 'react-native-actionsheet' -import Alert from '../../../SB/components/Alert' +import AlertComponent from '../../../SB/components/Alert' import { RootState } from '../../../Redux/Types' import ProcessingImageCard, { IProcessingImageProps } from '../../../Components/ProcessingImage' @@ -70,6 +70,12 @@ class ThreadDetail extends React.PureComponent { if (this.props.displayError) { setTimeout(this.props.dismissError, 2500) } + + if ( + this.props.showLocationPrompt + ) { + this._locationPrompt() + } } componentWillMount () { @@ -81,6 +87,24 @@ class ThreadDetail extends React.PureComponent { this._setHeaderParams() } + _locationPrompt () { + this.props.completeScreen('location') + Alert.alert( + 'Background Location', + 'Even snappier sharing is possible. Enabling background location allows Textile to occasionally get woken up and check the network for photos you may have missed. We never collect or store your location data. Want in?', + [ + { + text: 'Yes please', + onPress: () => { + this.props.enableLocation() + } + }, + { text: 'Not now', style: 'cancel' } + ], + { cancelable: false } + ) + } + showActionSheet () { this.actionSheet.show() } @@ -236,7 +260,7 @@ class ThreadDetail extends React.PureComponent { onPress={this.handleActionSheetResponse.bind(this)} /> - + ) } @@ -245,9 +269,9 @@ class ThreadDetail extends React.PureComponent { const mapStateToProps = (state: RootState) => { const viewingThreadId = state.photoViewing.viewingThreadId - var items: [{type: string, photo: Photo}] = [] - var processingItems: { type: 'processingItem', props: IProcessingImageProps }[] = [] - var threadName + let items: [{type: string, photo: Photo}] = [] + let processingItems: { type: 'processingItem', props: IProcessingImageProps }[] = [] + let threadName if (viewingThreadId) { const threadData: ThreadData = threadDataByThreadId(state, viewingThreadId) || { querying: false, photos: [] } @@ -282,6 +306,17 @@ const mapStateToProps = (state: RootState) => { threadName = threadData.name } + const displayImages = state.textileNode.nodeState.state === 'started' + + const showLocationPrompt = displayImages && + state.preferences.tourScreens.location && + // it's not already enabled... + !state.preferences.services.backgroundLocation.status && + // only show the location prompt after a few photos exists in a thread + items.length > 2 && + // only show location prompt if notifications are enabled + state.preferences.services.notifications.status + // add processing items to the beginning of the list items.unshift(...processingItems) @@ -289,12 +324,13 @@ const mapStateToProps = (state: RootState) => { threadId: viewingThreadId, threadName, items, - displayImages: state.textileNode.nodeState.state === 'started', + displayImages, profile: state.preferences.profile, // Image Picker details errorMessage: state.ui.imagePickerError, displayError: state.ui.hasOwnProperty('imagePickerError') && state.ui.imagePickerError !== undefined, - showOnboarding: state.preferences.tourScreens.threadView && items && items.length === 0 + showOnboarding: state.preferences.tourScreens.threadView && items && items.length === 0, + showLocationPrompt } } @@ -309,7 +345,8 @@ const mapDispatchToProps = (dispatch) => { retryShare: (uuid: string) => { dispatch(ProcessingImagesActions.retry(uuid)) }, cancelShare: (uuid: string) => { dispatch(ProcessingImagesActions.cancelRequest(uuid)) }, addFriendRequest: (threadId: string, threadName: string) => { dispatch(UIActions.addFriendRequest(threadId, threadName)) }, - completeScreen: (name) => { dispatch(PreferencesActions.completeTourSuccess(name)) } + completeScreen: (name) => { dispatch(PreferencesActions.completeTourSuccess(name)) }, + enableLocation: () => { dispatch(PreferencesActions.toggleServicesRequest('backgroundLocation', true)) } } }