created logout feature

This commit is contained in:
u-e 2018-12-14 19:37:35 +03:00
parent 956508c93a
commit 62b64a607c
21 changed files with 9051 additions and 167 deletions

View File

@ -46,7 +46,6 @@
"react-native-keyboard-aware-scroll-view": "^0.7.2",
"react-native-linear-gradient": "^2.4.2",
"react-native-markdown-renderer": "^3.2.8",
"react-native-modal": "^6.5.0",
"react-native-modal-dropdown": "^0.6.2",
"react-native-modal-popover": "0.0.12",
"react-native-restart": "0.0.6",

View File

@ -1,3 +1,4 @@
import ModalView from './view/modalView';
import Modal from './view/modalView';
export default ModalView;
export { Modal };
export default Modal;

View File

@ -6,11 +6,11 @@ import { IconButton } from '../../iconButton';
import styles from './modalStyles';
/*
* Props Name Description Value
*@props --> fullModal For modal size all screen or quick modal Boolean
*@props --> isOpen For modal is open or not Boolean
*
*/
* Props Name Description Value
*@props --> fullModal For modal size all screen or quick modal Boolean
*@props --> isOpen For modal is open or not Boolean
*
*/
export default class Modal extends Component {
constructor(props) {
@ -50,7 +50,7 @@ export default class Modal extends Component {
isFullScreen ? styles.fullModal : styles.centerModal,
]}
transparent={isTransparent}
animationType="fade"
animationType={animationType || "fade"}
visible={isOpen}
onRequestClose={() => this._handleOnClose(this)}
onShow={() => this._handleOnOpen(this)}

View File

@ -13,6 +13,9 @@ import { Upvote } from '../../upvote';
// Styles
import styles from './postCardStyles';
// Defaults
import DEFAULT_IMAGE from '../../../assets/no_image.png';
class PostCard extends Component {
/* Props
* ------------------------------------------------
@ -56,11 +59,7 @@ class PostCard extends Component {
render() {
const { content, isHideImage, fetchPost } = this.props;
// const likersText = `@${content.top_likers[0]}, @${content.top_likers[1]}, @${
// content.top_likers[2]
// }`;
// const otherLikers = ` & ${content.vote_count - content.top_likers.length} others like this`;
// const likesCount = `${content.vote_count} likes`;
const _image = content && content.image ? { uri: content.image } : DEFAULT_IMAGE;
return (
<View style={styles.post}>
@ -85,11 +84,7 @@ class PostCard extends Component {
onPress={() => this._handleOnContentPress()}
>
{!isHideImage && (
<Image
source={{ uri: content && content.image }}
defaultSource={require('../../../assets/no_image.png')}
style={styles.image}
/>
<Image source={_image} style={styles.image} defaultSource={DEFAULT_IMAGE} />
)}
<View style={[styles.postDescripton]}>
<Text style={styles.title}>{content.title}</Text>

View File

@ -2,10 +2,11 @@ import React, { Component } from 'react';
import { connect } from 'react-redux';
// Actions
import { getUserData } from '../../../realm/realm';
import { getUserData, getUserDataWithUsername } from '../../../realm/realm';
import { switchAccount } from '../../../providers/steem/auth';
import { updateCurrentAccount } from '../../../redux/actions/accountAction';
import { openPinCodeModal } from '../../../redux/actions/applicationActions';
import { openPinCodeModal, logout } from '../../../redux/actions/applicationActions';
// Constanst
import { default as ROUTES } from '../../../constants/routeNames';
@ -42,7 +43,7 @@ class SideMenuContainer extends Component {
accounts.push({
name: 'Add Account',
route: ROUTES.SCREENS.LOGIN,
icon: 'plus',
icon: 'add',
id: 'add_account',
});
this.setState({ accounts });
@ -61,16 +62,27 @@ class SideMenuContainer extends Component {
_switchAccount = (anchor = null) => {
const { dispatch, currentAccount, navigation } = this.props;
const username = anchor.slice(1);
dispatch(openPinCodeModal());
if (username !== currentAccount.name) {
switchAccount(username).then((accountData) => {
dispatch(updateCurrentAccount(accountData));
const realmData = getUserDataWithUsername(username);
const _currentAccount = accountData;
_currentAccount.username = _currentAccount.name;
_currentAccount.local = realmData[0];
dispatch(updateCurrentAccount(_currentAccount));
navigation.closeDrawer();
});
}
};
_handleLogout = () => {
const { dispatch } = this.props;
dispatch(logout());
};
render() {
const { currentAccount, isLoggedIn } = this.props;
const { accounts } = this.state;
@ -83,6 +95,7 @@ class SideMenuContainer extends Component {
accounts={accounts}
currentAccount={currentAccount}
switchAccount={this._switchAccount}
handleLogout={this._handleLogout}
/>
);
}

View File

@ -4,6 +4,7 @@ import {
} from 'react-native';
import { injectIntl } from 'react-intl';
import LinearGradient from 'react-native-linear-gradient';
import ActionSheet from 'react-native-actionsheet';
// Components
import { Icon, IconButton } from '../..';
@ -63,9 +64,27 @@ class SideMenuView extends Component {
});
};
_handleOnMenuItemPress = (item) => {
const { navigateToRoute, switchAccount } = this.props;
if (item.id === 'logout') {
this.ActionSheet.show();
return;
}
if (item.route) {
navigateToRoute(item.route);
} else {
switchAccount(item.name);
}
};
render() {
const {
navigateToRoute, currentAccount, isLoggedIn, switchAccount, intl,
currentAccount,
isLoggedIn,
intl,
handleLogout,
} = this.props;
const { menuItems, isAddAccountIconActive } = this.state;
@ -118,11 +137,7 @@ class SideMenuView extends Component {
<TouchableOpacity
style={styles.listItem}
onPress={() => {
if (item.item.route) {
navigateToRoute(item.item.route);
} else {
switchAccount(item.item.name);
}
this._handleOnMenuItemPress(item.item);
}}
>
<View style={styles.itemWrapper}>
@ -148,6 +163,16 @@ class SideMenuView extends Component {
)}
/>
</View>
<ActionSheet
ref={o => (this.ActionSheet = o)}
options={['Logout', 'Cancel']}
title="Are you sure want to logout?"
cancelButtonIndex={1}
destructiveButtonIndex={0}
onPress={(index) => {
index === 0 ? handleLogout() : null;
}}
/>
</View>
);
}

View File

@ -80,9 +80,7 @@ const stackNavigatior = createStackNavigator(
},
},
{
// cardStyle: {
// backgroundColor: 'white',
// },
headerMode: 'none',
},
);

View File

@ -45,7 +45,7 @@ const authMenuItems = [
},
{
name: 'Logout',
route: ROUTES.MODAL.LOGOUT,
route: '',
icon: 'exit-to-app',
id: 'logout',
},

View File

@ -146,6 +146,40 @@ export const updateUserData = userData => new Promise((resolve, reject) => {
}
});
export const removeUserData = username => new Promise((resolve, reject) => {
try {
const account = realm.objects(USER_SCHEMA).filtered('username = $0', username);
if (Array.from(account).length > 0) {
realm.write(() => {
realm.delete(account);
resolve();
});
} else {
reject('Could not remove selected user');
}
} catch (error) {
reject(error);
}
});
// // TODO: This method deleting ALL users. This should delete just a user.
// export const removeUserData = () => new Promise((resolve, reject) => {
// setAuthStatus({ isLoggedIn: false }).then(() => {
// try {
// const accounts = realm.objects(USER_SCHEMA);
// realm.write(() => {
// realm.delete(accounts);
// });
// resolve();
// } catch (error) {
// alert(error);
// reject(error);
// }
// });
// });
export const setDraftPost = (fields, username) => new Promise((resolve, reject) => {
try {
const draft = realm.objects(DRAFT_SCHEMA).filtered('username = $0', username);
@ -180,22 +214,6 @@ export const getDraftPost = username => new Promise((resolve, reject) => {
}
});
// TODO: This method deleting ALL users. This should delete just a user.
export const removeUserData = () => new Promise((resolve, reject) => {
setAuthStatus({ isLoggedIn: false }).then(() => {
try {
const accounts = realm.objects(USER_SCHEMA);
realm.write(() => {
realm.delete(accounts);
});
resolve();
} catch (error) {
alert(error);
reject(error);
}
});
});
export const getAuthStatus = () => new Promise((resolve, reject) => {
try {
const auth = realm.objects(AUTH_SCHEMA);

View File

@ -5,6 +5,7 @@ import {
ADD_OTHER_ACCOUNT,
UPDATE_CURRENT_ACCOUNT,
UPDATE_UNREAD_ACTIVITY_COUNT,
REMOVE_OTHER_ACCOUNT,
} from '../constants/constants';
export const fetchAccountFromSteem = (username, password) => (dispatch) => {
@ -37,3 +38,8 @@ export const updateUnreadActivityCount = data => ({
type: UPDATE_UNREAD_ACTIVITY_COUNT,
payload: data,
});
export const removeOtherAccount = data => ({
type: REMOVE_OTHER_ACCOUNT,
payload: data,
});

View File

@ -11,9 +11,11 @@ import {
SET_CURRENCY,
SET_LANGUAGE,
SET_UPVOTE_PERCENT,
LOGOUT_DONE,
} from '../constants/constants';
export const login = () => ({
export const login = payload => ({
payload,
type: LOGIN,
});
@ -21,6 +23,10 @@ export const logout = () => ({
type: LOGOUT,
});
export const logoutDone = () => ({
type: LOGOUT_DONE,
});
export const isLoginDone = () => ({
type: IS_LOGIN_DONE,
});

View File

@ -1,31 +0,0 @@
import { getUser } from '../../providers/steem/dsteem';
import {
FETCH_USER,
FETCH_USER_SUCCESS,
FETCH_USER_FAIL,
LOGOUT,
IS_LOGGED_IN,
} from '../constants/constants';
export function isLoggedIn(payload) {
return {
payload,
type: IS_LOGGED_IN,
};
}
export function fetchAccount(user) {
return (dispatch) => {
dispatch({ type: FETCH_USER });
return getUser(user)
.then(res => dispatch({ type: FETCH_USER_SUCCESS, payload: res }))
.catch(err => dispatch({ type: FETCH_USER_FAIL, payload: err }));
};
}
export function logout() {
return {
type: LOGOUT,
};
}

View File

@ -1,32 +1,34 @@
export const FETCH_USER = 'FETCH_USER';
export const FETCH_USER_SUCCESS = 'FETCH_USER_SUCCESS';
export const FETCH_USER_FAIL = 'FETCH_USER_FAIL';
export const FETCH_USER_SUCCESS = 'FETCH_USER_SUCCESS';
export const SET_USER_DATA = 'SET_USER_DATA';
// Applicaiton
export const ACTIVE_APPLICATION = 'ACTIVE_APPLICATION';
export const CLOSE_PIN_CODE_MODAL = 'CLOSE_PIN_CODE_MODAL';
export const IS_DARK_THEME = 'IS_DARK_THEME';
export const IS_LOGGED_IN = 'IS_LOGGED_IN';
export const IS_LOGIN_DONE = 'IS_LOGIN_DONE';
export const IS_NOTIFICATION_OPEN = 'IS_NOTIFICATION_OPEN';
export const LOGIN = 'LOGIN';
export const LOGOUT = 'LOGOUT';
export const LOGOUT_SUCCESS = 'LOGOUT_SUCCESS';
export const LOGOUT_DONE = 'LOGOUT_DONE';
export const LOGOUT_FAIL = 'LOGOUT_FAIL';
export const IS_LOGIN_DONE = 'IS_LOGIN_DONE';
export const ADD_OTHER_ACCOUNT = 'ADD_OTHER_ACCOUNT';
export const UPDATE_CURRENT_ACCOUNT = 'UPDATE_CURRENT_ACCOUNT';
export const FETCHING_ACCOUNT = 'FETCHING_ACCOUNT';
export const FETCH_ACCOUNT_FAIL = 'FETCH_ACCOUNT_FAIL';
export const UPDATE_UNREAD_ACTIVITY_COUNT = 'UPDATE_UNREAD_ACTIVITY_COUNT';
export const IS_LOGGED_IN = 'IS_LOGGED_IN';
export const LOGOUT_SUCCESS = 'LOGOUT_SUCCESS';
export const OPEN_PIN_CODE_MODAL = 'OPEN_PIN_CODE_MODAL';
export const CLOSE_PIN_CODE_MODAL = 'CLOSE_PIN_CODE_MODAL';
export const ACTIVE_APPLICATION = 'ACTIVE_APPLICATION';
export const IS_DARK_THEME = 'IS_DARK_THEME';
export const IS_NOTIFICATION_OPEN = 'IS_NOTIFICATION_OPEN';
export const SET_API = 'SET_API';
export const SET_CURRENCY = 'SET_CURRENCY';
export const SET_LANGUAGE = 'SET_LANGUAGE';
export const SET_UPVOTE_PERCENT = 'SET_UPVOTE_PERCENT';
// Accounts
export const ADD_OTHER_ACCOUNT = 'ADD_OTHER_ACCOUNT';
export const FETCH_ACCOUNT_FAIL = 'FETCH_ACCOUNT_FAIL';
export const FETCHING_ACCOUNT = 'FETCHING_ACCOUNT';
export const REMOVE_OTHER_ACCOUNT = 'REMOVE_OTHER_ACCOUNT';
export const UPDATE_CURRENT_ACCOUNT = 'UPDATE_CURRENT_ACCOUNT';
export const UPDATE_UNREAD_ACTIVITY_COUNT = 'UPDATE_UNREAD_ACTIVITY_COUNT';
// UI
export const UPDATE_ACTIVE_BOTTOM_TAB = 'UPDATE_ACTIVE_BOTTOM_TAB';
export const IS_COLLAPSE_POST_BUTTON = 'IS_COLLAPSE_POST_BUTTON';
export const UPDATE_ACTIVE_BOTTOM_TAB = 'UPDATE_ACTIVE_BOTTOM_TAB';

View File

@ -4,6 +4,9 @@ import {
ADD_OTHER_ACCOUNT,
UPDATE_CURRENT_ACCOUNT,
UPDATE_UNREAD_ACTIVITY_COUNT,
LOGOUT,
REMOVE_OTHER_ACCOUNT,
LOGOUT_FAIL,
} from '../constants/constants';
const initialState = {
@ -12,9 +15,11 @@ const initialState = {
currentAccount: {},
hasError: false,
errorMessage: null,
isLogingOut: false,
};
export default function (state = initialState, action) {
console.log(action);
switch (action.type) {
case FETCHING_ACCOUNT:
return {
@ -23,6 +28,7 @@ export default function (state = initialState, action) {
hasError: false,
errorMessage: null,
};
case FETCH_ACCOUNT_FAIL:
return {
...state,
@ -40,6 +46,12 @@ export default function (state = initialState, action) {
errorMessage: null,
};
case REMOVE_OTHER_ACCOUNT:
return {
...state,
otherAccounts: state.otherAccounts.filter(item => item.username !== action.payload),
};
case UPDATE_CURRENT_ACCOUNT:
return {
...state,
@ -48,6 +60,7 @@ export default function (state = initialState, action) {
hasError: false,
errorMessage: null,
};
case UPDATE_UNREAD_ACTIVITY_COUNT:
return {
...state,
@ -59,6 +72,18 @@ export default function (state = initialState, action) {
hasError: false,
errorMessage: null,
};
case LOGOUT_FAIL:
return {
...state,
isLogingOut: true,
};
// case LOGOUT_SUCCESS:
// return {
// ...state,
// initialState,
// };
default:
return state;
}

View File

@ -11,6 +11,7 @@ import {
IS_DARK_THEME,
IS_LOGIN_DONE,
SET_UPVOTE_PERCENT,
LOGOUT_DONE,
} from '../constants/constants';
const initialState = {
@ -20,6 +21,7 @@ const initialState = {
isDarkTheme: false,
isLoggedIn: false, // Has any logged in user.
isLoginDone: false,
isLogingOut: false,
isNotificationOpen: true,
isPinCodeReqiure: false,
language: 'en-US',
@ -32,7 +34,7 @@ export default function (state = initialState, action) {
case LOGIN:
return {
...state,
isLoggedIn: true,
isLoggedIn: action.payload,
};
case IS_LOGIN_DONE:
return {
@ -42,7 +44,12 @@ export default function (state = initialState, action) {
case LOGOUT:
return {
...state,
isLoggedIn: false,
isLogingOut: true,
};
case LOGOUT_DONE:
return {
...state,
isLogingOut: false,
};
case OPEN_PIN_CODE_MODAL:
return {

View File

@ -1,53 +0,0 @@
import {
FETCH_USER,
FETCH_USER_SUCCESS,
FETCH_USER_FAIL,
LOGOUT,
IS_LOGGED_IN,
} from '../constants/constants';
const initialState = {
isFetching: null,
data: [],
hasError: false,
errorMessage: null,
};
export default function (state = initialState, action) {
switch (action.type) {
case FETCH_USER:
return Object.assign({}, state, {
isFetching: true,
data: null,
hasError: false,
errorMessage: null,
});
case FETCH_USER_SUCCESS:
return Object.assign({}, state, {
isFetching: false,
data: action.payload,
hasError: false,
errorMessage: null,
});
case FETCH_USER_FAIL:
return Object.assign({}, state, {
isFetching: false,
data: action.payload,
hasError: true,
errorMessage: action.err,
});
case IS_LOGGED_IN:
return Object.assign({}, state, {
isLoggedIn: action.payload,
});
case LOGOUT:
return initialState;
default:
return state;
}
}

View File

@ -12,21 +12,25 @@ import tr from 'react-intl/locale-data/tr';
// Services
import {
getUserData,
getAuthStatus,
getSettings,
getPushTokenSaved,
setPushTokenSaved,
getExistUser,
getPushTokenSaved,
getSettings,
getUserData,
removeUserData,
setPushTokenSaved,
getUserDataWithUsername,
} from '../../../realm/realm';
import { getUser } from '../../../providers/steem/dsteem';
import { setPushToken } from '../../../providers/esteem/esteem';
import { switchAccount } from '../../../providers/steem/auth';
// Actions
import {
addOtherAccount,
updateCurrentAccount,
updateUnreadActivityCount,
removeOtherAccount
} from '../../../redux/actions/accountAction';
import {
activeApplication,
@ -39,6 +43,7 @@ import {
setCurrency,
setLanguage,
setUpvotePercent,
logoutDone,
} from '../../../redux/actions/applicationActions';
// Container
@ -61,11 +66,15 @@ class ApplicationContainer extends Component {
};
componentWillReceiveProps(nextProps) {
const { isDarkTheme: _isDarkTheme, selectedLanguage } = this.props;
const { isDarkTheme: _isDarkTheme, selectedLanguage, isLogingOut } = this.props;
if (_isDarkTheme !== nextProps.isDarkTheme || selectedLanguage !== nextProps.selectedLanguage) {
this.setState({ isRenderRequire: false }, () => this.setState({ isRenderRequire: true }));
}
if (isLogingOut !== nextProps.isLogingOut && nextProps.isLogingOut) {
this._logout();
}
}
componentWillUnmount() {
@ -88,7 +97,7 @@ class ApplicationContainer extends Component {
await getAuthStatus().then((res) => {
authStatus = res;
currentUsername = res.currentUsername;
console.log(res);
if (authStatus.isLoggedIn) {
getUserData().then((userData) => {
if (userData.length > 0) {
@ -96,7 +105,7 @@ class ApplicationContainer extends Component {
userData.forEach((accountData) => {
dispatch(
addOtherAccount({ username: accountData.username, avatar: accountData.avatar }),
addOtherAccount({ username: accountData.username }),
);
});
}
@ -107,7 +116,7 @@ class ApplicationContainer extends Component {
if (realmData) {
await getUser(currentUsername)
.then((accountData) => {
dispatch(login());
dispatch(login(true));
const realmObject = realmData.filter(data => data.username === currentUsername);
accountData.local = realmObject[0];
@ -177,6 +186,47 @@ class ApplicationContainer extends Component {
});
};
_logout = () => {
const {
otherAccounts, currentAccountUsername, dispatch,
} = this.props;
removeUserData(currentAccountUsername)
.then(() => {
const _otherAccounts = otherAccounts.filter(
user => user.username !== currentAccountUsername,
);
if (_otherAccounts.length > 0) {
const targetAccountUsername = _otherAccounts[0].username;
this._switchAccount(targetAccountUsername);
} else {
dispatch(updateCurrentAccount({}));
dispatch(login(false));
}
dispatch(removeOtherAccount(currentAccountUsername));
dispatch(logoutDone());
})
.catch((err) => {
alert('err');
});
};
_switchAccount = (targetAccountUsername) => {
const { dispatch } = this.props;
switchAccount(targetAccountUsername).then((accountData) => {
const realmData = getUserDataWithUsername(targetAccountUsername);
const _currentAccount = accountData;
_currentAccount.username = accountData.name;
_currentAccount.local = realmData[0];
dispatch(updateCurrentAccount(_currentAccount));
});
}
render() {
const { selectedLanguage } = this.props;
const { isRenderRequire } = this.state;
@ -194,11 +244,17 @@ class ApplicationContainer extends Component {
}
const mapStateToProps = state => ({
// Application
isDarkTheme: state.application.isDarkTheme,
selectedLanguage: state.application.language,
unreadActivityCount: state.account.currentAccount.unread_activity_count,
isLoggedIn: state.application.isLoggedIn,
notificationSettings: state.application.isNotificationOpen,
isLogingOut: state.application.isLogingOut,
isLoggedIn: state.application.isLoggedIn,
// Account
unreadActivityCount: state.account.currentAccount.unread_activity_count,
currentAccountUsername: state.account.currentAccount.name,
otherAccounts: state.account.otherAccounts,
});
export default connect(mapStateToProps)(ApplicationContainer);

View File

@ -24,13 +24,14 @@ class ApplicationScreen extends Component {
render() {
const { locale, isDarkTheme } = this.props;
const barStyle = isDarkTheme ? 'light-content' : 'dark-content';
const barColor = isDarkTheme ? '#1e2835' : '#fff';
return (
<Fragment>
{Platform.os === 'ios' ? (
<StatusBar barStyle={barStyle} />
) : (
<StatusBar barStyle={barStyle} backgroundColor="white" />
<StatusBar barStyle={barStyle} backgroundColor={barColor} />
)}
<IntlProvider locale={locale} messages={flattenMessages(messages[locale])}>

View File

@ -42,7 +42,6 @@ class HomeScreen extends PureComponent {
return (
<Fragment>
<Header />
<View style={styles.container}>
<ScrollableTabView
style={styles.tabView}

View File

@ -58,9 +58,9 @@ class LoginScreen extends Component {
if (result) {
dispatch(updateCurrentAccount({ ...result }));
dispatch(addOtherAccount({ username: result.name }));
dispatch(loginAction());
dispatch(openPinCodeModal());
setPinCodeState({ navigateTo: ROUTES.DRAWER.MAIN });
dispatch(loginAction(true));
}
})
.catch((err) => {

8817
yarn.lock Normal file

File diff suppressed because it is too large Load Diff