Commit ae9d6c2a authored by Martin Santangelo's avatar Martin Santangelo

wip

1 merge request!521WIP: refactor navigator 5
......@@ -120,7 +120,7 @@ sessionService.onLogin(async () => {
try {
// handle deep link (if the app is opened by one)
if (deepLinkUrl) {
deeplinkService.navigate(deepLinkUrl);
deeplinkService.navigate('App', { screen: deepLinkUrl});
deepLinkUrl = '';
}
......@@ -215,6 +215,13 @@ class App extends Component<Props, State> {
* On component did mount
*/
async componentDidMount() {
this.appInit();
}
/**
* App initialization
*/
async appInit() {
try {
// load app setting before start
const results = await Promise.all([settingsStore.init(), Linking.getInitialURL()]);
......@@ -233,7 +240,7 @@ class App extends Component<Props, State> {
if (!token) {
logService.info('[App] there is no active session');
RNBootSplash.hide({ duration: 250 });
NavigationService.navigate('Login');
// NavigationService.navigate('Auth', { screen: 'Login'});
} else {
logService.info('[App] session initialized');
}
......@@ -318,16 +325,18 @@ class App extends Component<Props, State> {
return null;
}
const isLoggedIn = sessionService.userLoggedIn;
const app = (
<SafeAreaProvider>
<NavigationContainer
ref={navigatorRef => setTopLevelNavigator(navigatorRef)}
theme={ThemedStyles.theme === 1 ? DarkTheme : DefaultTheme}
theme={ThemedStyles.navTheme}
>
<Provider key="app" {...stores}>
<ErrorBoundary message="An error occurred" containerStyle={CS.centered}>
<StatusBar barStyle={statusBarStyle} />
<NavigationStack key={ThemedStyles.theme}/>
<NavigationStack key={ThemedStyles.theme} isLoggedIn={isLoggedIn}/>
<FlashMessage renderCustomContent={this.renderNotification} />
</ErrorBoundary>
</Provider>
......
......@@ -43,13 +43,13 @@ describe('Activity screen component', () => {
it('renders correctly with an entity as param', async () => {
navigation = {
push: jest.fn(),
state: {
route: {
routeName: 'some',
params: {entity: activitiesServiceFaker().load(1).activities[0]}
}
};
entitiesService.single.mockResolvedValue(ActivityModel.create(navigation.state.params.entity));
entitiesService.single.mockResolvedValue(ActivityModel.create(navigation.route.entity));
screen = shallow(
<ActivityScreen navigation={navigation}/>
......
......@@ -20,8 +20,8 @@
android.useAndroidX=true
android.enableJetifier=true
# MYAPP_RELEASE_STORE_FILE=minds.keystore
# MYAPP_RELEASE_KEY_ALIAS=alias_name
MYAPP_RELEASE_STORE_FILE=minds.keystore
MYAPP_RELEASE_KEY_ALIAS=alias_name
org.gradle.jvmargs=-Xmx2048m
systemProp.org.gradle.internal.http.connectionTimeout=180000
systemProp.org.gradle.internal.http.socketTimeout=180000
......
......@@ -22,8 +22,8 @@ export default class ForgotScreen extends Component {
*/
render() {
const code =
this.props.navigation.state.params &&
this.props.navigation.state.params.code;
this.props.route.params &&
this.props.route.params.code;
const CS = ThemedStyles.style;
return (
......
......@@ -115,7 +115,7 @@ export default class ResetPassword extends PureComponent {
if (!this.state.sent ) {
this.setState({sending: true});
const state = navigation.getCurrentState();
const state = navigation.dangerouslyGetState();
try {
const data = await authService.reset(state.params.username, this.state.password, state.params.code);
......
......@@ -69,15 +69,15 @@ export default class BlockchainWalletDetailsScreen extends Component {
this.setState({
editable: false,
importable: false,
address: this.props.navigation.state.params.address,
edit: !!this.props.navigation.state.params.edit,
new: this.props.navigation.state.params.new,
address: this.props.route.params.address,
edit: !!this.props.route.params.edit,
new: this.props.route.params.new,
offchain: false,
tokens: null,
eth: null,
});
this.load(this.props.navigation.state.params.address);
this.load(this.props.route.params.address);
}
componentDidMount() {
......
......@@ -31,7 +31,7 @@ export default class BlockchainWalletImportScreen extends Component {
};
componentWillMount() {
const params = this.props.navigation.state.params || {};
const params = this.props.route.params || {};
this.setState({
importingRemote: !!params.address,
......@@ -81,7 +81,7 @@ export default class BlockchainWalletImportScreen extends Component {
async import() {
await this.props.blockchainWallet.import(this.state.privateKey);
const params = this.props.navigation.state.params || {};
const params = this.props.route.params || {};
if (params.onSuccess) {
params.onSuccess();
......
......@@ -41,7 +41,7 @@ import ThumbDownAction from '../newsfeed/activity/actions/ThumbDownAction';
import RemindAction from '../newsfeed/activity/actions/RemindAction';
import CommentsAction from '../newsfeed/activity/actions/CommentsAction';
import shareService from '../share/ShareService';
import commentsStoreProvider from '../comments/CommentsStoreProvider';
import Provider from '../comments/CommentsStoreProvider';
import CommentList from '../comments/CommentList';
import CenteredLoading from '../common/components/CenteredLoading';
import logService from '../common/services/log.service';
......@@ -86,7 +86,7 @@ export default class BlogsViewScreen extends Component {
* Component did mount
*/
async componentDidMount() {
const params = this.props.navigation.state.params;
const params = this.props.route.params;
try {
if (params.blog) {
if (params.blog._list && params.blog._list.metadataService) {
......@@ -267,6 +267,7 @@ export default class BlogsViewScreen extends Component {
entity={this.props.blogsView.blog}
store={this.comments}
navigation={this.props.navigation}
route={this.props.route}
keyboardVerticalOffset = {Header.HEIGHT - 65}
/>
:
......
......@@ -37,7 +37,7 @@ export default class BoostConsoleScreen extends Component {
* On component will mount
*/
componentWillMount() {
const filter = this.props.navigation.state.params.filter;
const filter = this.props.route.params.filter;
if (filter) {
this.props.boost.setFilter(filter);
......
......@@ -271,7 +271,7 @@ export default class BoostScreen extends Component {
}
buildAllowedTypes() {
const entity = this.props.navigation.state.params.entity;
const entity = this.props.route.params.entity;
if (!entity || !entity.type) {
this.setState({});
......@@ -400,7 +400,7 @@ export default class BoostScreen extends Component {
}
async _submitBoost() {
const entity = this.props.navigation.state.params.entity;
const entity = this.props.route.params.entity;
this.setState({ inProgress: true });
let guid = null;
......
......@@ -47,11 +47,11 @@ export default class CapturePoster extends Component {
/**
* Disable navigation bar
*/
static navigationOptions = ({ navigation }) => ({
static navigationOptions = ({ route }) => ({
tabBarIcon: ({ tintColor }) => (
<TabIcon name="md-add-circle-outline" size={44} color={tintColor} />
),
headerRight: navigation.state.params && navigation.state.params.headerRight
headerRight: route && route.headerRight
});
state = {
......@@ -140,17 +140,19 @@ export default class CapturePoster extends Component {
*/
navToPrevious(entity, group) {
const {state, dispatch, goBack} = this.props.navigation;
const {dispatch, goBack} = this.props.navigation;
const params = {
const { params } = this.props.route;
const routeParams = {
prepend: ActivityModel.checkOrCreate(entity),
};
if (group) params.group = group;
if (group) routeParams.group = group;
dispatch(NavigationActions.setParams({
params,
key: state.params.parentKey, // passed from index
routeParams,
key: params.parentKey, // passed from index
}));
goBack(null);
......
......@@ -50,19 +50,12 @@ class ChannelScreen extends Component {
guid: null,
};
/**
* Disable navigation bar
*/
static navigationOptions = {
header: null,
};
/**
* Load data on mount
*/
async componentWillMount() {
this.disposeEnter = this.props.navigation.addListener('didFocus', (s) => {
const params = this.props.navigation.state.params;
const params = this.props.route.params;
const store = this.props.channel.store(this.guid);
if (params && params.prepend) {
if (store.channel && store.channel.isOwner && store.channel.isOwner()) {
......@@ -84,7 +77,7 @@ class ChannelScreen extends Component {
* Initial load
*/
async initialLoad() {
const params = this.props.navigation.state.params;
const params = this.props.route.params;
if (params.entity) {
// load channel from endpoint
......@@ -182,7 +175,7 @@ class ChannelScreen extends Component {
}
get guid() {
const params = this.props.navigation.state.params;
const params = this.props.route.params;
let guid = params.entity ? params.entity.guid : params.guid;
......
......@@ -120,6 +120,7 @@ class Comment extends Component {
onInputFocus={this.onInputFocus}
onCommentFocus={this.onCommentFocus}
navigation={this.props.navigation}
route={this.props.route}
/>
}
......
......@@ -54,6 +54,7 @@ type PropsType = {
store: any,
user: any,
navigation: any,
route: any,
onInputFocus?: Function,
onCommentFocus?: Function
};
......@@ -280,7 +281,7 @@ class CommentList extends React.Component<PropsType, StateType> {
*/
loadComments = async (loadingMore: boolean = false, descending: boolean = true): Promise<void> => {
let guid;
const scrollToBottom = this.props.navigation.state.params.scrollToBottom;
const scrollToBottom = this.props.route.params.scrollToBottom;
if (this.props.entity) {
guid = this.props.entity.guid;
......@@ -453,6 +454,7 @@ class CommentList extends React.Component<PropsType, StateType> {
onTextInputfocus={this.onChildFocus}
onCommentFocus={this.onCommentFocus}
navigation={this.props.navigation}
route={this.props.route}
commentFocusCall={this.commentFocusCall}
index={row.index}
/>
......
......@@ -40,7 +40,7 @@ export const CODE_PUSH_TOKEN = '';
export const MINDS_FEATURES = {
crypto: Platform.OS === 'ios' ? false : true,
'onboarding-december-2019': true,
'navigation-2020': true,
// 'navigation-2020': true,
};
/**
......
......@@ -94,7 +94,7 @@ class DiscoveryScreen extends Component {
constructor(props) {
super(props);
this.props.discovery.init();
// this.props.discovery.init();
const params = this.props.route.params;
if (params && params.type) {
......
......@@ -85,7 +85,7 @@ export default class GroupViewScreen extends Component {
* Load initial data
*/
async initialLoad() {
const params = this.props.navigation.state.params;
const params = this.props.route.params;
if (params.group) {
// load group and update async
......@@ -113,13 +113,13 @@ export default class GroupViewScreen extends Component {
}
componentDidMount() {
const params = this.props.navigation.state.params;
const params = this.props.route.params;
// load data async
this.initialLoad();
this.disposeEnter = this.props.navigation.addListener('didFocus', (s) => {
const params = this.props.navigation.state.params;
const params = this.props.route.params;
if (params && params.prepend) {
this.props.groupView.prepend(params.prepend);
// we clear the parameter to prevent prepend it again on goBack
......@@ -214,6 +214,7 @@ export default class GroupViewScreen extends Component {
entity={group.group}
store={this.comments}
navigation={this.props.navigation}
route={this.props.route}
keyboardVerticalOffset = {Header.HEIGHT - 65}
/>
);
......
......@@ -39,7 +39,7 @@ export default class GroupsBarItem extends Component {
}
navToGroup = () => {
navigationService.push('GroupView', {group: this.props.group});
navigationService.navigate('GroupView', {group: this.props.group});
}
render() {
......
......@@ -3,11 +3,10 @@ import { NavigationActions, StackActions, SwitchActions } from '@react-navigatio
let _navigator = null;
function getStateFrom(nav) {
let state = nav.routes[nav.index];
if (state.routes) {
state = getStateFrom(state);
if (nav.routes && nav.routes[nav.index].state) {
return getStateFrom(nav.routes[nav.index].state);
}
return state;
return nav.routes[nav.index];
}
export function setTopLevelNavigator(navigatorRef) {
......@@ -19,7 +18,8 @@ function getState() {
}
function getCurrentState() {
return getStateFrom(_navigator.state.nav);
const root = _navigator.getRootState();
return getStateFrom(root);
}
function navigate(routeName, params) {
......
import React from 'react';
import React, { Fragment } from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import LoadingScreen from '../LoadingScreen';
......@@ -74,7 +74,7 @@ const AppStack = function(props) {
<Stack.Screen name="DeleteChannel" component={DeleteChannelScreen}/>
<Stack.Screen name="Notifications" component={NotificationsScreen}/>
<Stack.Screen name="NotificationsSettings" component={NotificationsSettingsScreen}/>
<Stack.Screen name="Channel" component={ChannelScreen}/>
<Stack.Screen name="Channel" component={ChannelScreen} options={hideHeader}/>
<Stack.Screen name="Capture" component={CapturePoster}/>
<Stack.Screen name="Activity" component={ActivityScreen}/>
<Stack.Screen name="Conversation" component={ConversationScreen}/>
......@@ -87,7 +87,7 @@ const AppStack = function(props) {
<Stack.Screen name="SettingsRekey" component={RekeyScreen}/>
<Stack.Screen name="SettingsBilling" component={BillingScreen}/>
<Stack.Screen name="GroupsList" component={GroupsListScreen}/>
<Stack.Screen name="GroupView" component={GroupViewScreen}/>
<Stack.Screen name="GroupView" component={GroupViewScreen} options={hideHeader}/>
<Stack.Screen name="Wallet" component={WalletScreen}/>
<Stack.Screen name="BlogList" component={BlogsListScreen}/>
<Stack.Screen name="BoostConsole" component={BoostConsoleScreen}/>
......@@ -125,9 +125,14 @@ const AuthStack = function(props) {
const RootStack = function(props) {
return (
<Stack.Navigator mode="modal" headerMode="none">
<Stack.Screen name="Auth" component={AuthStack} />
<Stack.Screen name="App" component={AppStack} />
<Stack.Screen name="Gathering" component={Gathering} />
{props.isLoggedIn ? (
<Fragment>
<Stack.Screen name="App" component={AppStack} />
<Stack.Screen name="Gathering" component={Gathering} />
</Fragment>
) : (
<Stack.Screen name="Auth" component={AuthStack} />
)}
</Stack.Navigator>
);
};
......
......@@ -46,8 +46,11 @@ class ActivityScreen extends Component {
this.loadEntity();
}
/**
* Load entity
*/
async loadEntity() {
const params = this.props.navigation.state.params;
const params = this.props.route.params;
if (params.entity && (params.entity.guid || params.entity.entity_guid)) {
......@@ -141,6 +144,7 @@ class ActivityScreen extends Component {
store={this.comments}
navigation={this.props.navigation}
onInputFocus={this.onFocus}
route={this.props.route}
/>
:
<View style={CS.flexColumnCentered}>
......
......@@ -84,6 +84,7 @@ export default class NewsfeedScreen extends Component {
// load groups after the feed
await this.groupsBar.wrappedInstance.initialLoad();
// load discovery after the feed is loaded
this.props.discovery.init();
this.props.discovery.fetch();
}
......
......@@ -40,10 +40,10 @@ export default
@observer
class SettingsScreen extends Component {
static navigationOptions = {
title: 'Settings',
leftHandedInitial: false,
};
// static navigationOptions = {
// title: 'Settings',
// leftHandedInitial: false,
// };
state = {
showLanguages: false,
......@@ -158,8 +158,6 @@ class SettingsScreen extends Component {
icon: (<Icon name='power-settings-new' size={ICON_SIZE} style={[styles.icon, CS.colorPrimaryText]} />),
onPress: () => {
authService.logout();
this.props.navigation.navigate( 'Login');
}
},
{
......
......@@ -55,7 +55,6 @@ class SettingsService {
try {
await api.delete('api/v1/channel');
await sessionService.logout();
navigationService.navigate('Login');
} catch (e) {
Alert.alert('Error disabling the channel');
}
......@@ -69,7 +68,6 @@ class SettingsService {
try {
await api.post('api/v2/settings/delete', { password });
await sessionService.logout();
navigationService.navigate('Login');
} catch (e) {
Alert.alert('Error deleting the channel');
}
......
......@@ -2,7 +2,7 @@ import { StyleSheet } from 'react-native';
import { observable, action, reaction } from 'mobx';
import { DARK_THEME, LIGHT_THEME } from './Colors';
import { DefaultTheme } from '@react-navigation/native';
import { DefaultTheme, DarkTheme } from '@react-navigation/native';
const repetitions = 8;
const step = 5;
......@@ -111,10 +111,18 @@ class ThemedStylesStore {
const theme = this.theme ? DARK_THEME : LIGHT_THEME;
// this.navTheme = {
// ...DefaultTheme,
// dark: this.theme === 1,
// };
const baseTheme = this.theme === 0 ? DefaultTheme : DarkTheme;
this.navTheme = {
...baseTheme,
colors: {
...baseTheme.colors,
background: 'transparent',
// card: theme.backgroundSecondary, // generates an error in ios
text: theme.primary_text,
primary: theme.icon
},
};
this.style = StyleSheet.create({
...dynamicStyles,
......
......@@ -99,7 +99,6 @@ export default class MoreScreen extends Component {
icon: (<Icon name='power-settings-new' size={ICON_SIZE} style={ styles.icon } />),
onPress: () => {
authService.logout();
this.props.navigation.navigate('Login');
}
}
];
......
......@@ -118,7 +118,6 @@ class MoreScreenNew extends Component {
icon: (<Icon name='power-settings-new' size={ICON_SIZE} style={ CS.colorIcon } />),
onPress: () => {
authService.logout();
this.props.navigation.navigate('Login');
}
}
];
......@@ -126,23 +125,36 @@ class MoreScreenNew extends Component {
return list;
}
/**
* Recieve a list a return a view container with a list of items
* @param {Array} list
*/
renderList = list => {
render() {
const avatar = this.getAvatar(),
channel = this.props.user.me;
const CS = ThemedStyles.style;
return (
<SafeAreaView style={[
CS.flexContainer,
CS.backgroundPrimary,
]}>
<ScrollView
style={[
styles.container,
CS.flexContainer,
CS.backgroundPrimary,
CS.marginTop4x,
CS.marginTop11x,
]}
>
<View style={styles.headerContainer} >
<TouchableOpacity onPress={this.navToChannel}>
<Image source={avatar} style={styles.wrappedAvatar}/>
</TouchableOpacity>
<Text style={[CS.titleText, CS.colorPrimaryText, CS.marginTop2x]}>{channel.name}</Text>
<Text style={[CS.subTitleText, CS.colorSecondaryText, CS.fontNormal]}>@{channel.username}</Text>
<Text style={[CS.subTitleText, CS.colorSecondaryText, CS.fontNormal, CS.marginTop3x]}>
{`${abbrev(channel.subscribers_count, 0)} ${i18n.t('subscribers')} · ${abbrev(channel.subscriptions_count, 0)} ${i18n.t('subscriptions')}`}
</Text>
</View>
{
list.map((l, i) => (
this.getOptionsList().map((l, i) => (
<ListItem
key={i}
title={l.name}
......@@ -158,35 +170,7 @@ class MoreScreenNew extends Component {
))
}
</ScrollView>
)
}
render() {
const avatar = this.getAvatar(),
channel = this.props.user.me;
const CS = ThemedStyles.style;
return (
<SafeAreaView style={[
CS.flexContainer,
CS.backgroundPrimary,
]}>
{/* CHANNEL DATA */}
<View style={styles.headerContainer} >
<TouchableOpacity onPress={this.navToChannel}>
<Image source={avatar} style={styles.wrappedAvatar}/>
</TouchableOpacity>
<Text style={[CS.titleText, CS.colorPrimaryText, CS.marginTop2x]}>{channel.name}</Text>
<Text style={[CS.subTitleText, CS.colorSecondaryText, CS.fontNormal]}>@{channel.username}</Text>
<Text style={[CS.subTitleText, CS.colorSecondaryText, CS.fontNormal, CS.marginTop3x]}>
{`${abbrev(channel.subscribers_count, 0)} ${i18n.t('subscribers')} · ${abbrev(channel.subscriptions_count, 0)} ${i18n.t('subscriptions')}`}
</Text>
</View>
{/* MENU */}
{this.renderList(this.getOptionsList())}
</SafeAreaView>
);
}
......
......@@ -3,7 +3,7 @@ import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
import { View } from 'react-native';
import { View, Platform } from 'react-native';
import NewsfeedScreen from '../newsfeed/NewsfeedScreen';
import NotificationsScreen from '../notifications/NotificationsScreen';
......@@ -22,6 +22,9 @@ import { Avatar } from 'react-native-elements';
* @param {Object} props
*/
const Tabs = function(props) {
const isIOS = Platform.OS === 'ios';
return (
<Tab.Navigator
initialRouteName="Newsfeed"
......@@ -33,8 +36,8 @@ const Tabs = function(props) {
style: {
borderTopWidth: 0,
backgroundColor: ThemedStyles.getColor('secondary_background'),
height: 100,
paddingTop: 10
height: isIOS ? 90 : 65,
paddingTop: isIOS ? 20 : 2,
},
tabStyle: {
height: 66,
......
......@@ -66,22 +66,22 @@ export default class TopbarNew extends Component {
}
}
let topbarHeight = 100;
let topbarHeight = 50;
let topMargin = 0;
if (Platform.OS == 'ios') {
topbarHeight = 100;
topbarHeight = 80;
}
const styles = StyleSheet.create({
lineHeight0: {
lineHeight:0,
lineHeight: 28,
},
container: {
height: topbarHeight,
display: 'flex',
flexDirection: 'row',
paddingBottom: 5,
paddingBottom: 8,
},
topbar: {
flex: 1,
......
......@@ -69,7 +69,7 @@ export default class FabScreen extends Component {
}
async loadUserAndSetDefaults() {
const params = this.props.navigation.state.params;
const params = this.props.route.params;
// if there is no default data we reset the store
if (!params || !params.default) {
......
Please register or to comment