diff --git a/ios/Ecency/AppDelegate.m b/ios/Ecency/AppDelegate.m index 023c4ec99..33770fada 100644 --- a/ios/Ecency/AppDelegate.m +++ b/ios/Ecency/AppDelegate.m @@ -1,5 +1,6 @@ -#import "RNSplashScreen.h" #import "AppDelegate.h" +#import "RNSplashScreen.h" + #import #import #import diff --git a/ios/Podfile.lock b/ios/Podfile.lock index b15638732..dc123e25e 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -361,8 +361,8 @@ PODS: - React-Core - react-native-safe-area-context (3.1.9): - React-Core - - react-native-splash-screen (3.2.0): - - React + - react-native-splash-screen (3.3.0): + - React-Core - react-native-udp (2.7.0): - React - react-native-version-number (0.3.6): @@ -791,7 +791,7 @@ SPEC CHECKSUMS: react-native-receive-sharing-intent: feba0a332a07977549a85aa58b496eb44368366a react-native-restart: aaad36f3ed7031daac3565f4a79d67e4f3884a50 react-native-safe-area-context: b6e0e284002381d2ff29fa4fff42b4d8282e3c94 - react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865 + react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457 react-native-udp: ff9d13e523f2b58e6bc5d4d32321ac60671b5dc9 react-native-version-number: b415bbec6a13f2df62bf978e85bc0d699462f37f react-native-video: a4c2635d0802f983594b7057e1bce8f442f0ad28 @@ -833,4 +833,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 0282022703ad578ab2d9afbf3147ba3b373b4311 -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 diff --git a/package.json b/package.json index a57a96347..7effffa93 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "react-native-scrollable-tab-view": "ecency/react-native-scrollable-tab-view", "react-native-slider": "^0.11.0", "react-native-snap-carousel": "^3.8.0", - "react-native-splash-screen": "^3.2.0", + "react-native-splash-screen": "^3.3.0", "react-native-svg": "^12.1.1", "react-native-swiper": "^1.6.0-rc.3", "react-native-tcp": "^4.0.0", diff --git a/src/components/basicHeader/container/basicHeaderContainer.js b/src/components/basicHeader/container/basicHeaderContainer.js index 6823d3bec..58c860f3d 100644 --- a/src/components/basicHeader/container/basicHeaderContainer.js +++ b/src/components/basicHeader/container/basicHeaderContainer.js @@ -4,14 +4,14 @@ import { withNavigation } from 'react-navigation'; // Constants import { default as ROUTES } from '../../../constants/routeNames'; import { useAppDispatch, useAppSelector } from '../../../hooks'; -import { hidePostsThumbnails } from '../../../redux/actions/uiAction'; +import { setHidePostsThumbnails } from '../../../redux/actions/applicationActions'; // Components import BasicHeaderView from '../view/basicHeaderView'; const BasicHeaderContainer = (props) => { const dispatch = useAppDispatch(); - const isHideImages = useAppSelector((state) => state.ui.hidePostsThumbnails); + const isHideImages = useAppSelector((state) => state.application.hidePostsThumbnails); const _handleOnPressBackButton = () => { const { navigation, isNewPost, handleOnBackPress } = props; @@ -30,7 +30,7 @@ const BasicHeaderContainer = (props) => { }; const _handleViewModeToggle = () => { - dispatch(hidePostsThumbnails(!isHideImages)); + dispatch(setHidePostsThumbnails(!isHideImages)); }; return ( diff --git a/src/components/header/container/headerContainer.js b/src/components/header/container/headerContainer.js index a1825abf3..b725bc11a 100644 --- a/src/components/header/container/headerContainer.js +++ b/src/components/header/container/headerContainer.js @@ -8,8 +8,8 @@ import { useDispatch, useSelector } from 'react-redux'; import HeaderView from '../view/headerView'; import { AccountContainer, ThemeContainer } from '../../../containers'; -import { hidePostsThumbnails } from '../../../redux/actions/uiAction'; import { parseReputation } from '../../../utils/user'; +import { setHidePostsThumbnails } from '../../../redux/actions/applicationActions'; const HeaderContainer = ({ selectedUser, @@ -22,7 +22,7 @@ const HeaderContainer = ({ const dispatch = useDispatch(); //redux properties - const isHideImages = useSelector((state) => state.ui.hidePostsThumbnails); + const isHideImages = useSelector((state) => state.application.hidePostsThumbnails); const _handleOpenDrawer = () => { if (has(navigation, 'openDrawer') && typeof get(navigation, 'openDrawer') === 'function') { @@ -39,7 +39,7 @@ const HeaderContainer = ({ }; const _handleViewModeTogglePress = () => { - dispatch(hidePostsThumbnails(!isHideImages)); + dispatch(setHidePostsThumbnails(!isHideImages)); }; return ( diff --git a/src/components/posts/container/postsContainer.js b/src/components/posts/container/postsContainer.js index 90a07b603..2c87a9082 100644 --- a/src/components/posts/container/postsContainer.js +++ b/src/components/posts/container/postsContainer.js @@ -25,7 +25,6 @@ import { setOtherPosts, setInitPosts, } from '../../../redux/actions/postsAction'; -import { hidePostsThumbnails } from '../../../redux/actions/uiAction'; import { fetchLeaderboard, followUser, unfollowUser } from '../../../redux/actions/userAction'; import { subscribeCommunity, @@ -34,6 +33,7 @@ import { } from '../../../redux/actions/communitiesAction'; import useIsMountedRef from '../../../customHooks/useIsMountedRef'; +import { setHidePostsThumbnails } from '../../../redux/actions/applicationActions'; const PostsContainer = ({ changeForceLoadPostState, @@ -59,7 +59,7 @@ const PostsContainer = ({ const nsfw = useSelector((state) => state.application.nsfw); const initPosts = useSelector((state) => state.posts.initPosts); const isConnected = useSelector((state) => state.application.isConnected); - const isHideImages = useSelector((state) => state.ui.hidePostsThumbnails); + const isHideImages = useSelector((state) => state.application.hidePostsThumbnails); const username = useSelector((state) => state.account.currentAccount.name); const isLoggedIn = useSelector((state) => state.application.isLoggedIn); const isAnalytics = useSelector((state) => state.application.isAnalytics); @@ -467,7 +467,7 @@ const PostsContainer = ({ }; const _handleImagesHide = () => { - dispatch(hidePostsThumbnails(!isHideImages)); + dispatch(setHidePostsThumbnails(!isHideImages)); }; const _getPromotePosts = async () => { diff --git a/src/components/postsList/container/postsListContainer.tsx b/src/components/postsList/container/postsListContainer.tsx index bac83b254..fa1a7a14d 100644 --- a/src/components/postsList/container/postsListContainer.tsx +++ b/src/components/postsList/container/postsListContainer.tsx @@ -37,7 +37,7 @@ const postsListContainer = ({ const [imageHeights, setImageHeights] = useState(new Map()); - const isHideImages = useSelector((state) => state.ui.hidePostsThumbnails); + const isHideImages = useSelector((state) => state.application.hidePostsThumbnails); const posts = useSelector((state) => { return isFeedScreen ? state.posts.feedPosts diff --git a/src/components/profile/children/commentsTabContent.tsx b/src/components/profile/children/commentsTabContent.tsx index fa8d202d2..a47622e49 100644 --- a/src/components/profile/children/commentsTabContent.tsx +++ b/src/components/profile/children/commentsTabContent.tsx @@ -20,7 +20,7 @@ const CommentsTabContent = ({isOwnProfile, username, type, onScroll, selectedUse const intl = useIntl(); - const isHideImage = useAppSelector(state => state.ui.hidePostsThumbnails); + const isHideImage = useAppSelector(state => state.application.hidePostsThumbnails); const isAnalytics = useAppSelector(state => state.application.isAnalytics); const [data, setData] = useState([]); diff --git a/src/components/tabbedPosts/view/stackedTabBar.tsx b/src/components/tabbedPosts/view/stackedTabBar.tsx index dfd7098b6..eb924b568 100644 --- a/src/components/tabbedPosts/view/stackedTabBar.tsx +++ b/src/components/tabbedPosts/view/stackedTabBar.tsx @@ -2,7 +2,7 @@ import React, { useRef, useState } from "react"; import { useIntl } from "react-intl"; import { useDispatch, useSelector } from "react-redux"; import { CustomiseFiltersModal, FilterBar } from "../.."; -import { hidePostsThumbnails } from "../../../redux/actions/uiAction"; +import { setHidePostsThumbnails } from "../../../redux/actions/applicationActions"; import { CustomiseFiltersModalRef } from "../../customiseFiltersModal/customiseFiltersModal"; export interface TabItem { @@ -42,7 +42,7 @@ export const StackedTabBar = ({ const customiseModalRef = useRef(); //redux properties - const isHideImages = useSelector((state) => state.ui.hidePostsThumbnails); + const isHideImages = useSelector((state) => state.application.hidePostsThumbnails); const [selectedFilterIndex, setSelectedFilterIndex] = useState(initialFirstStackIndex); const [selectedSecondStackIndex, setSelectedSecondStackIndex] = useState(0); @@ -57,7 +57,7 @@ export const StackedTabBar = ({ } const _onToggleImagesPress = () => { - dispatch(hidePostsThumbnails(!isHideImages)) + dispatch(setHidePostsThumbnails(!isHideImages)) } return ( diff --git a/src/config/locales/en-US.json b/src/config/locales/en-US.json index 83e24ac23..2c5b2f8c3 100644 --- a/src/config/locales/en-US.json +++ b/src/config/locales/en-US.json @@ -783,7 +783,9 @@ "line2_body":"Utilizing blockchain, censorship-free, decentralized and rewarding.", "line3_heading":"Join Ecency communities!", "line3_body":"Build community you own, get rewarded and reward others.", - "get_started":"Get started!" + "get_started":"Get started!", + "terms_description": "By accepting, you agree to our Terms of Service and Privacy Policies.", + "terms_text": "Read Here!" }, "time":{ "second":"seconds", diff --git a/src/containers/profileContainer.js b/src/containers/profileContainer.js index dc6ef1451..78d444830 100644 --- a/src/containers/profileContainer.js +++ b/src/containers/profileContainer.js @@ -606,7 +606,7 @@ const mapStateToProps = (state) => ({ isAnalytics: state.application.isAnalytics, activeBottomTab: state.ui.activeBottomTab, currentAccount: state.account.currentAccount, - isHideImage: state.ui.hidePostsThumbnails, + isHideImage: state.application.hidePostsThumbnails, }); export default connect(mapStateToProps)(injectIntl(withNavigation(ProfileContainer))); diff --git a/src/redux/actions/applicationActions.ts b/src/redux/actions/applicationActions.ts index 9d5201119..65effa481 100644 --- a/src/redux/actions/applicationActions.ts +++ b/src/redux/actions/applicationActions.ts @@ -1,7 +1,6 @@ import getSymbolFromCurrency from 'currency-symbol-map'; import { getCurrencyRate } from '../../providers/ecency/ecency'; import { - ACTIVE_APPLICATION, CHANGE_COMMENT_NOTIFICATION, CHANGE_FOLLOW_NOTIFICATION, CHANGE_MENTION_NOTIFICATION, @@ -28,6 +27,11 @@ import { SET_PIN_CODE, IS_PIN_CODE_OPEN, IS_RENDER_REQUIRED, + SET_LAST_APP_VERSION, + SET_COLOR_THEME, + SET_SETTINGS_MIGRATED, + HIDE_POSTS_THUMBNAILS, + SET_TERMS_ACCEPTED } from '../constants/constants'; export const login = (payload) => ({ @@ -47,7 +51,7 @@ export const isLoginDone = () => ({ type: IS_LOGIN_DONE, }); -export const openPinCodeModal = (payload) => ({ +export const openPinCodeModal = (payload = null) => ({ payload, type: OPEN_PIN_CODE_MODAL, }); @@ -56,9 +60,6 @@ export const closePinCodeModal = () => ({ type: CLOSE_PIN_CODE_MODAL, }); -export const activeApplication = () => ({ - type: ACTIVE_APPLICATION, -}); // Settings actions export const setLanguage = (payload) => ({ @@ -135,6 +136,11 @@ export const isDarkTheme = (payload) => ({ type: IS_DARK_THEME, }); +export const setColorTheme = (payload:number) => ({ + payload, + type: SET_COLOR_THEME +}) + export const isPinCodeOpen = (payload) => ({ payload, type: IS_PIN_CODE_OPEN, @@ -183,3 +189,24 @@ export const isRenderRequired = (payload) => ({ type: IS_RENDER_REQUIRED, }); +export const setLastAppVersion = (versionNumber:string) => ({ + payload:versionNumber, + type: SET_LAST_APP_VERSION +}) + +export const setSettingsMigrated = (isMigrated:boolean) => ({ + payload:isMigrated, + type: SET_SETTINGS_MIGRATED +}) + +export const setHidePostsThumbnails = (shouldHide:boolean) => ({ + payload:shouldHide, + type: HIDE_POSTS_THUMBNAILS, +}); + +export const setIsTermsAccepted = (isTermsAccepted:boolean) => ({ + payload:isTermsAccepted, + type: SET_TERMS_ACCEPTED +}) + + diff --git a/src/redux/actions/uiAction.ts b/src/redux/actions/uiAction.ts index afb6f9aeb..5a26206b3 100644 --- a/src/redux/actions/uiAction.ts +++ b/src/redux/actions/uiAction.ts @@ -1,9 +1,7 @@ -import { AlertButton } from 'react-native'; import { TOAST_NOTIFICATION, UPDATE_ACTIVE_BOTTOM_TAB, - HIDE_POSTS_THUMBNAILS, RC_OFFER, TOGGLE_ACCOUNTS_BOTTOM_SHEET, SHOW_ACTION_MODAL, @@ -58,10 +56,6 @@ export const setRcOffer = (payload:boolean) => ({ type: RC_OFFER, }); -export const hidePostsThumbnails = (payload:boolean) => ({ - payload, - type: HIDE_POSTS_THUMBNAILS, -}); export const toggleAccountsBottomSheet = (payload:boolean) => ({ payload, diff --git a/src/redux/constants/constants.js b/src/redux/constants/constants.js index 50571574a..3e8064d1e 100644 --- a/src/redux/constants/constants.js +++ b/src/redux/constants/constants.js @@ -4,7 +4,6 @@ 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_CONNECTED = 'IS_CONNECTED'; export const IS_ANALYTICS = 'IS_ANALYTICS'; @@ -33,6 +32,10 @@ export const CHANGE_MENTION_NOTIFICATION = 'CHANGE_MENTION_NOTIFICATION'; export const CHANGE_REBLOG_NOTIFICATION = 'CHANGE_REBLOG_NOTIFICATION'; export const CHANGE_TRANSFERS_NOTIFICATION = 'CHANGE_TRANSFERS_NOTIFICATION'; export const CHANGE_ALL_NOTIFICATION_SETTINGS = 'CHANGE_ALL_NOTIFICATION_SETTINGS'; +export const SET_LAST_APP_VERSION = 'SET_LAST_APP_VERSION'; +export const SET_COLOR_THEME = 'SET_COLOR_THEME'; +export const SET_SETTINGS_MIGRATED = 'SET_SETTINGS_MIGRATED'; +export const SET_TERMS_ACCEPTED = 'SET_TERMS_ACCEPTED'; // Accounts export const ADD_OTHER_ACCOUNT = 'ADD_OTHER_ACCOUNT'; diff --git a/src/redux/reducers/applicationReducer.ts b/src/redux/reducers/applicationReducer.ts index 16271a630..6d02dfe8d 100644 --- a/src/redux/reducers/applicationReducer.ts +++ b/src/redux/reducers/applicationReducer.ts @@ -1,5 +1,4 @@ import { - ACTIVE_APPLICATION, CHANGE_COMMENT_NOTIFICATION, CHANGE_FOLLOW_NOTIFICATION, CHANGE_MENTION_NOTIFICATION, @@ -26,19 +25,63 @@ import { SET_PIN_CODE, IS_PIN_CODE_OPEN, IS_RENDER_REQUIRED, + SET_LAST_APP_VERSION, + SET_COLOR_THEME, + SET_SETTINGS_MIGRATED, + HIDE_POSTS_THUMBNAILS, + SET_TERMS_ACCEPTED, } from '../constants/constants'; -const initialState = { +interface State { + api: string; + currency: { + currency: string, + currencyRate: number, + currencySymbol: string, + }, + isConnected: boolean|null, // internet connectivity + isDarkTheme: boolean; + colorTheme: number; + isDefaultFooter: boolean; //TODO: remove present of isDefaultFooter as it's no longer in use + isLoggedIn: boolean; // Has any logged in user. + isAnalytics: boolean; + isLoginDone: boolean; + isLogingOut: boolean; + isNotificationOpen: boolean; + isPinCodeRequire: boolean; + pinCodeNavigation: any, + language: string, + loading: boolean; // It is lock to all screen and shows loading animation. + notificationDetails: { + commentNotification: boolean, + followNotification: boolean, + mentionNotification: boolean, + reblogNotification: boolean, + transfersNotification: boolean, + voteNotification: boolean, + }, + upvotePercent: number; + nsfw: string; + pin: string|null; + isPinCodeOpen: boolean; + isRenderRequired: boolean; + lastAppVersion:string; + settingsMigrated: boolean; + hidePostsThumbnails: boolean; + isTermsAccepted: boolean; +} + +const initialState:State = { api: 'rpc.ecency.com', currency: { currency: 'usd', currencyRate: 1, currencySymbol: '$', }, - isActive: false, isConnected: null, // internet connectivity isDarkTheme: false, - isDefaultFooter: true, + colorTheme: 0, //values mapped from => src/constants/options/theme.ts + isDefaultFooter: true, //TODO: remove present of isDefaultFooter as it's no longer in use isLoggedIn: false, // Has any logged in user. isAnalytics: false, isLoginDone: false, @@ -61,7 +104,10 @@ const initialState = { pin: null, isPinCodeOpen: true, isRenderRequired: false, - + lastAppVersion:'', + settingsMigrated: false, + hidePostsThumbnails: false, + isTermsAccepted: false, }; export default function (state = initialState, action) { @@ -107,11 +153,6 @@ export default function (state = initialState, action) { ...state, isPinCodeRequire: false, }; - case ACTIVE_APPLICATION: - return { - ...state, - isActive: true, - }; case SET_API: return Object.assign({}, state, { api: action.payload, @@ -187,6 +228,11 @@ export default function (state = initialState, action) { return Object.assign({}, state, { isDarkTheme: action.payload, }); + case SET_COLOR_THEME: + return { + ...state, + colorTheme:action.payload + }; case IS_PIN_CODE_OPEN: return Object.assign({}, state, { isPinCodeOpen: action.payload, @@ -212,6 +258,30 @@ export default function (state = initialState, action) { return Object.assign({}, state, { isRenderRequired: action.payload, }); + + case SET_LAST_APP_VERSION: + return { + ...state, + lastAppVersion:action.payload + } + + case SET_SETTINGS_MIGRATED: + return { + ...state, + settingsMigrated:action.payload + } + + case HIDE_POSTS_THUMBNAILS: + return { + ...state, + hidePostsThumbnails:action.payload + } + + case SET_TERMS_ACCEPTED: + return { + ...state, + isTermsAccepted:action.payload + } default: return state; diff --git a/src/redux/reducers/uiReducer.ts b/src/redux/reducers/uiReducer.ts index c2fe66a62..d5738f2a4 100644 --- a/src/redux/reducers/uiReducer.ts +++ b/src/redux/reducers/uiReducer.ts @@ -1,7 +1,6 @@ import { UPDATE_ACTIVE_BOTTOM_TAB, TOAST_NOTIFICATION, - HIDE_POSTS_THUMBNAILS, RC_OFFER, TOGGLE_ACCOUNTS_BOTTOM_SHEET, SHOW_ACTION_MODAL, @@ -17,7 +16,6 @@ import { orientations } from '../constants/orientationsConstants'; interface UiState { activeBottomTab:string; toastNotification:string; - hidePostsThumbnails:boolean; rcOffer:boolean; isVisibleAccountsBottomSheet:boolean; actionModalVisible:boolean; @@ -31,7 +29,6 @@ interface UiState { const initialState:UiState = { activeBottomTab: 'HomeTabbar', toastNotification: '', - hidePostsThumbnails: false, rcOffer: false, isVisibleAccountsBottomSheet: false, actionModalVisible: false, @@ -92,12 +89,6 @@ export default function (state = initialState, action) { rcOffer: action.payload, }; - case HIDE_POSTS_THUMBNAILS: - return { - ...state, - hidePostsThumbnails: action.payload, - }; - case TOGGLE_ACCOUNTS_BOTTOM_SHEET: return { ...state, diff --git a/src/redux/store/store.ts b/src/redux/store/store.ts index c3f84a861..cbb740b4f 100644 --- a/src/redux/store/store.ts +++ b/src/redux/store/store.ts @@ -5,7 +5,6 @@ import AsyncStorage from '@react-native-community/async-storage'; import Reactotron from '../../../reactotron-config'; import reducer from '../reducers'; -import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2'; const transformCacheVoteMap = createTransform( (inboundState:any) => ({ @@ -40,7 +39,7 @@ const persistConfig = { // Storage Method (React Native) storage: AsyncStorage, // Blacklist (Don't Save Specific Reducers) - blacklist: ['nav', 'application', 'communities', 'user'], + blacklist: ['nav', 'communities', 'user', 'ui'], timeout: 0, transforms:[ transformCacheVoteMap, diff --git a/src/screens/application/screen/applicationScreen.js b/src/screens/application/children/applicationScreen.tsx similarity index 68% rename from src/screens/application/screen/applicationScreen.js rename to src/screens/application/children/applicationScreen.tsx index d60672014..48280757a 100644 --- a/src/screens/application/screen/applicationScreen.js +++ b/src/screens/application/children/applicationScreen.tsx @@ -1,10 +1,9 @@ import React, { Component, Fragment } from 'react'; -import { StatusBar, Platform, View, Alert, Text, Modal, TouchableHighlight } from 'react-native'; +import { StatusBar, Platform, View, Alert } from 'react-native'; import EStyleSheet from 'react-native-extended-stylesheet'; import { connect } from 'react-redux'; import { createAppContainer } from 'react-navigation'; import { injectIntl } from 'react-intl'; -import VersionNumber from 'react-native-version-number'; import AppNavitation from '../../../navigation/routes'; import { setTopLevelNavigator, navigate } from '../../../navigation/service'; @@ -14,7 +13,6 @@ import { toastNotification as toastNotificationAction, setRcOffer, } from '../../../redux/actions/uiAction'; -import { getVersionForWelcomeModal } from '../../../realm/realm'; import ROUTES from '../../../constants/routeNames'; @@ -32,7 +30,6 @@ import { // Themes (Styles) import darkTheme from '../../../themes/darkTheme'; import lightTheme from '../../../themes/lightTheme'; -import parseVersionNumber from '../../../utils/parseVersionNumber'; const Navigation = createAppContainer(AppNavitation); @@ -41,24 +38,14 @@ class ApplicationScreen extends Component { super(props); this.state = { isShowToastNotification: false, - showWelcomeModal: false, }; } - componentDidMount() { - const { appVersion } = VersionNumber; - - getVersionForWelcomeModal().then((version) => { - if (version < parseVersionNumber(appVersion)) { - this.setState({ showWelcomeModal: true }); - } - }); - } - componentDidUpdate(prevProps) { const { rcOffer, dispatch, intl } = this.props; const { rcOffer: rcOfferPrev } = prevProps; + //TODO: display action modal instead if (!rcOfferPrev && rcOffer) { setTimeout(() => { Alert.alert( @@ -109,25 +96,19 @@ class ApplicationScreen extends Component { } render() { - const { - isConnected, - isDarkTheme, - toastNotification, - isReady, - foregroundNotificationData, - navigation, - } = this.props; - const { isShowToastNotification, showWelcomeModal } = this.state; + const { isConnected, isDarkTheme, toastNotification, foregroundNotificationData } = this.props; + const { isShowToastNotification } = this.state; const barStyle = isDarkTheme ? 'light-content' : 'dark-content'; const barColor = isDarkTheme ? '#1e2835' : '#fff'; return ( - + {Platform.os === 'ios' ? ( ) : ( )} + {!isConnected && } - { - Alert.alert('Modal has been closed.'); - }} - > - - Hello World! - { - this.setState({ showWelcomeModal: !showWelcomeModal }); - }} - > - Hide Modal - - - {isShowToastNotification && ( diff --git a/src/screens/application/screen/errorBoundary.js b/src/screens/application/children/errorBoundary.js similarity index 100% rename from src/screens/application/screen/errorBoundary.js rename to src/screens/application/children/errorBoundary.js diff --git a/src/screens/application/children/migrationHelpers.ts b/src/screens/application/children/migrationHelpers.ts new file mode 100644 index 000000000..4fa87aebb --- /dev/null +++ b/src/screens/application/children/migrationHelpers.ts @@ -0,0 +1,83 @@ +import { Appearance } from 'react-native'; + +// Constants +import THEME_OPTIONS from '../../../constants/options/theme'; + +// Services +import { + getSettings, +} from '../../../realm/realm'; + +import { + isDarkTheme, + changeNotificationSettings, + changeAllNotificationSettings, + setApi, + setCurrency, + setLanguage, + setUpvotePercent, + setNsfw, + isDefaultFooter, + isPinCodeOpen, + setColorTheme, + setSettingsMigrated, +} from '../../../redux/actions/applicationActions'; +import { + hideActionModal, + hideProfileModal, + setRcOffer, + toastNotification, +} from '../../../redux/actions/uiAction'; + + +//migrates settings from realm to redux once and do no user realm for settings again; +export const migrateSettings = async (dispatch: any, settingsMigrated: boolean) => { + + if (settingsMigrated) { + return; + } + + //reset certain properties + dispatch(hideActionModal()); + dispatch(hideProfileModal()); + dispatch(toastNotification('')); + dispatch(setRcOffer(false)); + + + const settings = await getSettings(); + + if (settings) { + const isDarkMode = Appearance.getColorScheme() === 'dark'; + dispatch(isDarkTheme(settings.isDarkTheme !== null ? settings.isDarkTheme : isDarkMode)); + dispatch(setColorTheme(THEME_OPTIONS.findIndex(item => item.value === settings.isDarkTheme))); + if (settings.isPinCodeOpen !== '') await dispatch(isPinCodeOpen(settings.isPinCodeOpen)); + if (settings.language !== '') dispatch(setLanguage(settings.language)); + if (settings.server !== '') dispatch(setApi(settings.server)); + if (settings.upvotePercent !== '') { + dispatch(setUpvotePercent(Number(settings.upvotePercent))); + } + if (settings.isDefaultFooter !== '') dispatch(isDefaultFooter(settings.isDefaultFooter)); //TODO: remove as not being used + + + if (settings.nsfw !== '') dispatch(setNsfw(settings.nsfw)); + + dispatch(setCurrency(settings.currency !== '' ? settings.currency : 'usd')); + + if (settings.notification !== '') { + dispatch( + changeNotificationSettings({ + type: 'notification', + action: settings.notification, + }), + ); + + dispatch(changeAllNotificationSettings(settings)); + } + + await dispatch(setSettingsMigrated(true)) + } +} + +export default { + migrateSettings +} \ No newline at end of file diff --git a/src/screens/application/children/pinCodeModal.tsx b/src/screens/application/children/pinCodeModal.tsx new file mode 100644 index 000000000..f98437a41 --- /dev/null +++ b/src/screens/application/children/pinCodeModal.tsx @@ -0,0 +1,77 @@ + +import React, { useEffect, useRef } from 'react' +import { AppState } from 'react-native'; +import { Modal } from '../../../components'; +import { useAppDispatch, useAppSelector } from '../../../hooks' +import { getExistUser } from '../../../realm/realm'; +import { openPinCodeModal } from '../../../redux/actions/applicationActions'; +import PinCode from '../../pinCode'; + +interface PinCodeModalProps { + welcomeModalVisible: boolean; +} + +const PinCodeModal = ({ welcomeModalVisible }: PinCodeModalProps) => { + const dispatch = useAppDispatch(); + + const pinCodeTimer = useRef(null); + const appState = useRef(AppState.currentState); + + const isPinCodeRequire = useAppSelector(state => state.application.isPinCodeRequire); + const isPinCodeOpen = useAppSelector(state => state.application.isPinCodeOpen); + + + useEffect(() => { + AppState.addEventListener('change', _handleAppStateChange); + return _unmount + }, []) + + + const _unmount = () => { + AppState.removeEventListener('change', _handleAppStateChange); + } + + + const _handleAppStateChange = (nextAppState) => { + getExistUser().then((isExistUser) => { + if (isExistUser) { + if (appState.current.match(/active|forground/) && nextAppState === 'inactive') { + _startPinCodeTimer(); + } + + if (appState.current.match(/inactive|background/) && nextAppState === 'active') { + if (isPinCodeOpen && pinCodeTimer.current) { + clearTimeout(pinCodeTimer.current); + } + } + } + }); + + appState.current = nextAppState; + }; + + + + const _startPinCodeTimer = () => { + if (isPinCodeOpen) { + pinCodeTimer.current = setTimeout(() => { + dispatch(openPinCodeModal()); + }, 1 * 60 * 1000); + } + }; + + + return ( + + + + ) +} + +export default PinCodeModal \ No newline at end of file diff --git a/src/screens/application/children/welcomeModal.tsx b/src/screens/application/children/welcomeModal.tsx new file mode 100644 index 000000000..d49bc7b9a --- /dev/null +++ b/src/screens/application/children/welcomeModal.tsx @@ -0,0 +1,156 @@ +import React, { useState, useEffect } from 'react'; +import { useIntl } from 'react-intl'; +import { Text, Image, View, SafeAreaView, TouchableOpacity, Linking } from 'react-native'; + +import EStyleSheet from 'react-native-extended-stylesheet'; +import { ScrollView } from 'react-native-gesture-handler'; +import VersionNumber from 'react-native-version-number'; + +import { CheckBox, Icon, MainButton, Modal } from '../../../components'; +import { useAppDispatch, useAppSelector } from '../../../hooks'; +import { setLastAppVersion, setIsTermsAccepted } from '../../../redux/actions/applicationActions'; +import parseVersionNumber from '../../../utils/parseVersionNumber'; +import LaunchScreen from '../../launch'; + +import styles from './welcomeStyles'; + +const WelcomeModal = ({ onModalVisibilityChange }) => { + const intl = useIntl(); + const dispatch = useAppDispatch(); + + const lastAppVersion = useAppSelector(state => state.application.lastAppVersion) + const isTermsAccepted = useAppSelector(state => state.application.isTermsAccepted); + + const [showAnimation, setShowAnimation] = useState(true); + const [showWelcomeModal, setShowWelcomeModal] = useState(false); + const [isConsentChecked, setIsConsentChecked] = useState(isTermsAccepted); + + const [appVersion] = useState(VersionNumber.appVersion); + + + useEffect(() => { + _compareAppVersion() + }, []) + + + const _compareAppVersion = () => { + if (!lastAppVersion || (parseVersionNumber(lastAppVersion) < parseVersionNumber(appVersion))) { + _showWelcomeModal(); + } + } + + const _showWelcomeModal = () => { + setShowWelcomeModal(true); + onModalVisibilityChange(true); + setShowAnimation(true); + setTimeout(() => { + setShowAnimation(false); + }, 3550); + } + + + const _handleButtonPress = () => { + dispatch(setLastAppVersion(appVersion)) + dispatch(setIsTermsAccepted(isConsentChecked)); + setShowWelcomeModal(false); + onModalVisibilityChange(false); + } + + const _onCheckPress = (value, isCheck) => { + setIsConsentChecked(isCheck); + }; + + + const _renderInfo = (iconName, headingIntlId, bodyIntlId) => ( + + + + {intl.formatMessage({ id: headingIntlId })} + {intl.formatMessage({ id: bodyIntlId })} + + + ); + + const _renderConsent = () => ( + + + Linking.openURL('https://ecency.com/terms-of-service')}> + + + {intl.formatMessage({ + id: 'welcome.terms_description', + })} + + {' '} + {intl.formatMessage({ + id: 'welcome.terms_text', + })} + + + + + + ); + + const _renderContent = () => ( + + + + + + + {intl.formatMessage({ id: 'welcome.label' })} + {intl.formatMessage({ id: 'welcome.title' })} + + + + + + {_renderInfo('question', 'welcome.line1_heading', 'welcome.line1_body')} + {_renderInfo('emotsmile', 'welcome.line2_heading', 'welcome.line2_body')} + {_renderInfo('people', 'welcome.line3_heading', 'welcome.line3_body')} + + + + + + + {_renderConsent()} + + + + + + {showAnimation && } + + ); + + + return ( + + {_renderContent()} + ) +}; + +export default WelcomeModal; diff --git a/src/screens/application/screen/welcomeStyles.js b/src/screens/application/children/welcomeStyles.js similarity index 69% rename from src/screens/application/screen/welcomeStyles.js rename to src/screens/application/children/welcomeStyles.js index 2f3b125f1..e628108a1 100644 --- a/src/screens/application/screen/welcomeStyles.js +++ b/src/screens/application/children/welcomeStyles.js @@ -20,6 +20,11 @@ export default EStyleSheet.create({ paddingBottom: 20, paddingHorizontal: 40, }, + + contentContainer: { + flexGrow: 1, + justifyContent: 'center', + }, welcomeText: { fontSize: scalePx(34), color: '$primaryBlack', @@ -47,8 +52,10 @@ export default EStyleSheet.create({ topText: { marginTop: 40, }, - bottomButton: { - paddingTop: 10, + bottomContainer: { + marginTop: 8, + borderTopWidth: EStyleSheet.hairlineWidth, + borderColor: '$iconColor', }, sectionRow: { flexDirection: 'row', @@ -69,4 +76,28 @@ export default EStyleSheet.create({ flex1: { flex: 1, }, + consentContainer: { + flexDirection: 'row', + alignItems: 'center', + marginTop: 32, + marginBottom: 40, + }, + checkStyle: { + backgroundColor: '$white', + marginRight: 12, + }, + consentTextContainer: { + flexDirection: 'row', + flex: 1, + flexWrap: 'wrap', + }, + termsDescText: { + fontSize: 14, + color: '$primaryBlack', + }, + termsLinkText: { + fontSize: 14, + fontWeight: '700', + color: '$primaryBlue', + }, }); diff --git a/src/screens/application/container/applicationContainer.js b/src/screens/application/container/applicationContainer.tsx similarity index 84% rename from src/screens/application/container/applicationContainer.js rename to src/screens/application/container/applicationContainer.tsx index 7649be071..67ee3a844 100644 --- a/src/screens/application/container/applicationContainer.js +++ b/src/screens/application/container/applicationContainer.tsx @@ -10,12 +10,12 @@ import { NavigationActions } from 'react-navigation'; import { bindActionCreators } from 'redux'; import EStyleSheet from 'react-native-extended-stylesheet'; import { isEmpty, some } from 'lodash'; -import { useDarkMode } from 'react-native-dynamic'; import messaging from '@react-native-firebase/messaging'; import PushNotification from 'react-native-push-notification'; import VersionNumber from 'react-native-version-number'; import ReceiveSharingIntent from 'react-native-receive-sharing-intent'; import Matomo from 'react-native-matomo-sdk'; +import SplashScreen from 'react-native-splash-screen' // Constants import AUTH_TYPE from '../../../constants/authType'; @@ -25,8 +25,6 @@ import postUrlParser from '../../../utils/postUrlParser'; // Services import { getAuthStatus, - getExistUser, - getSettings, getUserData, removeUserData, getUserDataWithUsername, @@ -34,8 +32,6 @@ import { setAuthStatus, removeSCAccount, setExistUser, - getVersionForWelcomeModal, - setVersionForWelcomeModal, getLastUpdateCheck, setLastUpdateCheck, getTheme, @@ -49,10 +45,8 @@ import { } from '../../../providers/hive/auth'; import { setPushToken, - markActivityAsRead, markNotifications, getUnreadNotificationCount, - getLatestQuotes, } from '../../../providers/ecency/ecency'; import { fetchLatestAppVersion } from '../../../providers/github/github'; import { navigate } from '../../../navigation/service'; @@ -64,34 +58,20 @@ import { updateUnreadActivityCount, removeOtherAccount, fetchGlobalProperties, - removeAllOtherAccount, } from '../../../redux/actions/accountAction'; import { - activeApplication, isDarkTheme, - changeNotificationSettings, - changeAllNotificationSettings, login, logoutDone, openPinCodeModal, - setApi, setConnectivityStatus, setAnalyticsStatus, - setCurrency, - setLanguage, - setUpvotePercent, - setNsfw, - isDefaultFooter, - isPinCodeOpen, setPinCode as savePinCode, isRenderRequired, logout, } from '../../../redux/actions/applicationActions'; import { - hideActionModal, - hideProfileModal, setAvatarCacheStamp, - setRcOffer, showActionModal, toastNotification, updateActiveBottomTab, @@ -105,10 +85,11 @@ import darkTheme from '../../../themes/darkTheme'; import lightTheme from '../../../themes/lightTheme'; import persistAccountGenerator from '../../../utils/persistAccountGenerator'; import parseVersionNumber from '../../../utils/parseVersionNumber'; -import { getTimeFromNow, setMomentLocale } from '../../../utils/time'; +import { setMomentLocale } from '../../../utils/time'; import parseAuthUrl from '../../../utils/parseAuthUrl'; import { purgeExpiredCache } from '../../../redux/actions/cacheActions'; import { fetchSubscribedCommunities } from '../../../redux/actions/communitiesAction'; +import MigrationHelpers from '../children/migrationHelpers'; // Workaround let previousAppState = 'background'; @@ -123,25 +104,20 @@ export const setPreviousAppState = () => { let firebaseOnNotificationOpenedAppListener = null; let firebaseOnMessageListener = null; let removeAppearanceListener = null; -let scAccounts = []; class ApplicationContainer extends Component { constructor(props) { super(props); this.state = { isRenderRequire: true, - isReady: false, isIos: Platform.OS !== 'android', - isThemeReady: false, appState: AppState.currentState, - showWelcomeModal: false, foregroundNotificationData: null, }; } componentDidMount = () => { const { isIos } = this.state; - const { appVersion } = VersionNumber; const { dispatch, isAnalytics } = this.props; this._setNetworkListener(); @@ -163,22 +139,9 @@ class ApplicationContainer extends Component { //set avatar cache stamp to invalidate previous session avatars dispatch(setAvatarCacheStamp(new Date().getTime())); - getVersionForWelcomeModal().then((version) => { - if (version < parseVersionNumber(appVersion)) { - getUserData().then((accounts) => { - this.setState({ showWelcomeModal: true }); - if (accounts && accounts.length > 0) { - accounts.forEach((account) => { - if (get(account, 'authType', '') === AUTH_TYPE.STEEM_CONNECT) { - scAccounts.push(account); - } - }); - } - }); - } - }); - + SplashScreen.hide(); setMomentLocale(); + this._fetchApp(); ReceiveSharingIntent.getReceivedFiles( () => { @@ -235,7 +198,7 @@ class ApplicationContainer extends Component { if (!isIos) BackHandler.removeEventListener('hardwareBackPress', this._onBackPress); - // NetInfo.isConnected.removeEventListener('connectionChange', this._handleConntectionChange); + //TOOD: listen for back press and cancel all pending api requests; Linking.removeEventListener('url', this._handleOpenURL); @@ -439,22 +402,10 @@ class ApplicationContainer extends Component { ); }; + _handleAppStateChange = (nextAppState) => { const { appState } = this.state; - const { isPinCodeOpen: _isPinCodeOpen } = this.props; - getExistUser().then((isExistUser) => { - if (isExistUser) { - if (appState.match(/active|forground/) && nextAppState === 'inactive') { - this._startPinCodeTimer(); - } - if (appState.match(/inactive|background/) && nextAppState === 'active') { - if (_isPinCodeOpen) { - clearTimeout(this._pinCodeTimer); - } - } - } - }); if (appState.match(/inactive|background/) && nextAppState === 'active') { this._refreshGlobalProps(); } @@ -464,24 +415,16 @@ class ApplicationContainer extends Component { }); }; - _startPinCodeTimer = () => { - const { dispatch, isPinCodeOpen: _isPinCodeOpen } = this.props; - - if (_isPinCodeOpen) { - this._pinCodeTimer = setTimeout(() => { - dispatch(openPinCodeModal()); - }, 1 * 60 * 1000); - } - }; _fetchApp = async () => { - await this._getSettings(); - this.setState({ - isReady: true, - }); + const {dispatch, settingsMigrated} = this.props; + + await MigrationHelpers.migrateSettings(dispatch, settingsMigrated) this._refreshGlobalProps(); await this._getUserDataFromRealm(); this._compareAndPromptForUpdate(); + this._registerDeviceForNotifications(); + dispatch(purgeExpiredCache()); }; _pushNavigate = (notification) => { @@ -647,7 +590,6 @@ class ApplicationContainer extends Component { const { currentUsername } = res; if (res) { - dispatch(activeApplication()); dispatch(login(true)); const userData = await getUserData(); @@ -696,11 +638,11 @@ class ApplicationContainer extends Component { // TODO: await switchAccount(realmObject[0].username); } - const isExistUser = await getExistUser(); + realmObject[0].name = currentUsername; // If in dev mode pin code does not show - if ((!isExistUser || !pinCode) && _isPinCodeOpen) { + if (_isPinCodeOpen) { dispatch(openPinCodeModal()); } else if (!_isPinCodeOpen) { const encryptedPin = encryptKey(Config.DEFAULT_PIN, Config.PIN_KEY); @@ -709,13 +651,13 @@ class ApplicationContainer extends Component { if (isConnected) { this._fetchUserDataFromDsteem(realmObject[0]); + } return realmObject[0]; } dispatch(updateCurrentAccount({})); - dispatch(activeApplication()); return null; }; @@ -788,6 +730,7 @@ class ApplicationContainer extends Component { dispatch(updateCurrentAccount(accountData)); dispatch(fetchSubscribedCommunities(realmObject.username)); this._connectNotificationServer(accountData.name); + //TODO: better update device push token here after access token refresh } catch (err) { Alert.alert( `${intl.formatMessage({ id: 'alert.fetch_error' })} \n${err.message.substr(0, 20)}`, @@ -795,63 +738,34 @@ class ApplicationContainer extends Component { } }; - _getSettings = async () => { - const { dispatch, otherAccounts } = this.props; - //reset certain properties - dispatch(hideActionModal()); - dispatch(hideProfileModal()); - dispatch(toastNotification('')); - dispatch(purgeExpiredCache()); - dispatch(setRcOffer(false)); - const settings = await getSettings(); + //update notification settings and update push token for each signed accoutn useing access tokens + _registerDeviceForNotifications = (settings?:any) => { + const { otherAccounts, notificationDetails, isNotificationsEnabled } = this.props; + + const isEnabled = settings ? !!settings.notification : isNotificationsEnabled; + settings = settings || notificationDetails; - if (settings) { - const isDarkMode = Appearance.getColorScheme() === 'dark'; - dispatch(isDarkTheme(settings.isDarkTheme !== null ? settings.isDarkTheme : isDarkMode)); - this.setState({ - isThemeReady: true, - }); - if (settings.isPinCodeOpen !== '') await dispatch(isPinCodeOpen(settings.isPinCodeOpen)); - if (settings.language !== '') dispatch(setLanguage(settings.language)); - if (settings.server !== '') dispatch(setApi(settings.server)); - if (settings.upvotePercent !== '') { - dispatch(setUpvotePercent(Number(settings.upvotePercent))); + + //updateing fcm token with settings; + otherAccounts.forEach((account) => { + //since there can be more than one accounts, process access tokens separate + const encAccessToken = account?.local?.accessToken; + //decrypt access token + let accessToken = null; + if (encAccessToken) { + //NOTE: default pin decryption works also for custom pin as other account + //keys are not yet being affected by changed pin, which I think we should dig more + accessToken = decryptKey(encAccessToken, Config.DEFAULT_PIN); } - if (settings.isDefaultFooter !== '') dispatch(isDefaultFooter(settings.isDefaultFooter)); - if (settings.notification !== '') { - console.log('Notification Settings', settings.notification, otherAccounts); - dispatch( - changeNotificationSettings({ - type: 'notification', - action: settings.notification, - }), - ); - dispatch(changeAllNotificationSettings(settings)); - - //updateing fcm token with settings; - otherAccounts.forEach((account) => { - //since there can be more than one accounts, process access tokens separate - const encAccessToken = account.local.accessToken; - //decrypt access token - let accessToken = null; - if (encAccessToken) { - //NOTE: default pin decryption works also for custom pin as other account - //keys are not yet being affected by changed pin, which I think we should dig more - accessToken = decryptKey(encAccessToken, Config.DEFAULT_PIN); - } - - this._enableNotification(account.name, settings.notification, settings, accessToken); - }); - } - if (settings.nsfw !== '') dispatch(setNsfw(settings.nsfw)); - - await dispatch(setCurrency(settings.currency !== '' ? settings.currency : 'usd')); - } + this._enableNotification(account.name, isEnabled, settings, accessToken); + }); }; + + _connectNotificationServer = (username) => { /* eslint no-undef: "warn" */ const ws = new WebSocket(`${Config.ACTIVITY_WEBSOCKET_URL}?user=${username}`); @@ -988,13 +902,6 @@ class ApplicationContainer extends Component { dispatch(fetchSubscribedCommunities(_currentAccount.username)); }; - _handleWelcomeModalButtonPress = () => { - const { appVersion } = VersionNumber; - - setVersionForWelcomeModal(appVersion); - - this.setState({ showWelcomeModal: false }); - }; UNSAFE_componentWillReceiveProps(nextProps) { const { @@ -1050,13 +957,7 @@ class ApplicationContainer extends Component { isPinCodeRequire, rcOffer, } = this.props; - const { - isRenderRequire, - isReady, - isThemeReady, - showWelcomeModal, - foregroundNotificationData, - } = this.state; + const { isRenderRequire, foregroundNotificationData } = this.state; return ( children && @@ -1064,15 +965,11 @@ class ApplicationContainer extends Component { isConnected, isDarkTheme: _isDarkTheme, isPinCodeRequire, - isReady, isRenderRequire, - isThemeReady, locale: selectedLanguage, rcOffer, toastNotification, - showWelcomeModal, foregroundNotificationData, - handleWelcomeModalButtonPress: this._handleWelcomeModalButtonPress, }) ); } @@ -1085,15 +982,17 @@ export default connect( selectedLanguage: state.application.language, isPinCodeOpen: state.application.isPinCodeOpen, isLogingOut: state.application.isLogingOut, - isLoggedIn: state.application.isLoggedIn, + isLoggedIn: state.application.isLoggedIn, //TODO: remove as is not being used in this class isConnected: state.application.isConnected, nav: state.nav.routes, isPinCodeRequire: state.application.isPinCodeRequire, - isActiveApp: state.application.isActive, api: state.application.api, isGlobalRenderRequired: state.application.isRenderRequired, isAnalytics: state.application.isAnalytics, lastUpdateCheck: state.application.lastUpdateCheck, + settingsMigrated: state.application.settingsMigrated, + isNotificationsEnabled: state.application.isNotificationOpen, + notificationDetails: state.application.notificationDetails, // Account unreadActivityCount: state.account.currentAccount.unread_activity_count, diff --git a/src/screens/application/index.js b/src/screens/application/index.js deleted file mode 100644 index 438f04fd9..000000000 --- a/src/screens/application/index.js +++ /dev/null @@ -1,100 +0,0 @@ -import React, { Fragment, useEffect, useState } from 'react'; -import { Dimensions } from 'react-native'; -import SplashScreen from 'react-native-splash-screen'; - -import { OrientationLocker, PORTRAIT, LANDSCAPE } from 'react-native-orientation-locker'; -import { useDispatch } from 'react-redux'; -import ApplicationContainer from './container/applicationContainer'; -import WelcomeScreen from './screen/welcomeScreen'; -import ApplicationScreen from './screen/applicationScreen'; -import LaunchScreen from '../launch'; -import { Modal } from '../../components'; -import { PinCode } from '../pinCode'; -import ErrorBoundary from './screen/errorBoundary'; -import { setDeviceOrientation } from '../../redux/actions/uiAction'; - -const Application = () => { - const dispatch = useDispatch(); - const [showAnimation, setShowAnimation] = useState(process.env.NODE_ENV !== 'development'); - - useEffect(() => { - SplashScreen.hide(); - if (showAnimation) { - setTimeout(() => { - setShowAnimation(false); - }, 3550); - } - }, [showAnimation]); - - const _handleDeviceOrientationChange = (orientation) => { - console.log('device orientation changed at index : ', orientation); - dispatch(setDeviceOrientation(orientation)); - }; - - return ( - - {({ - isConnected, - isDarkTheme, - isPinCodeRequire, - isReady, - isRenderRequire, - isThemeReady, - locale, - rcOffer, - toastNotification, - showWelcomeModal, - handleWelcomeModalButtonPress, - foregroundNotificationData, - }) => { - const _isAppReady = !showAnimation && isReady && isRenderRequire && isThemeReady; - - return ( - - console.log('orientation changed : ', orientation)} - onDeviceChange={_handleDeviceOrientationChange} - /> - - - - - - - - - {isThemeReady && isRenderRequire && ( - - )} - {!_isAppReady && } - - ); - }} - - ); -}; - -export default Application; - -export { ApplicationContainer, ApplicationScreen }; diff --git a/src/screens/application/index.tsx b/src/screens/application/index.tsx new file mode 100644 index 000000000..47fe7eba8 --- /dev/null +++ b/src/screens/application/index.tsx @@ -0,0 +1,68 @@ +import React, { useState } from 'react'; + +import { OrientationLocker, PORTRAIT } from 'react-native-orientation-locker'; +import { useDispatch } from 'react-redux'; +import ApplicationContainer from './container/applicationContainer'; +import WelcomeModal from './children/welcomeModal'; +import ApplicationScreen from './children/applicationScreen'; +import ErrorBoundary from './children/errorBoundary'; +import { setDeviceOrientation } from '../../redux/actions/uiAction'; +import PinCodeModal from './children/pinCodeModal'; + +const Application = () => { + const dispatch = useDispatch(); + + const [welcomeModalVisible, setWelcomeModalVisible] = useState(false); + + const _handleDeviceOrientationChange = (orientation) => { + console.log('device orientation changed at index : ', orientation); + dispatch(setDeviceOrientation(orientation)); + }; + + return ( + + {({ + isConnected, + isDarkTheme, + isPinCodeRequire, + isRenderRequire, + locale, + rcOffer, + toastNotification, + foregroundNotificationData, + }) => { + + return ( + + console.log('orientation changed : ', orientation)} + onDeviceChange={_handleDeviceOrientationChange} + /> + + + + + + + + {isRenderRequire && ( + + )} + + ); + }} + + ); +}; + +export default Application; + +export { ApplicationContainer, ApplicationScreen }; diff --git a/src/screens/application/screen/welcomeScreen.js b/src/screens/application/screen/welcomeScreen.js deleted file mode 100644 index 6d44ef96b..000000000 --- a/src/screens/application/screen/welcomeScreen.js +++ /dev/null @@ -1,60 +0,0 @@ -import React from 'react'; -import { useIntl } from 'react-intl'; -import { Text, Image, View, SafeAreaView, TouchableOpacity } from 'react-native'; - -import EStyleSheet from 'react-native-extended-stylesheet'; - -import { Icon, MainButton } from '../../../components'; - -import styles from './welcomeStyles'; - -const WelcomeScreen = ({ handleButtonPress }) => { - const intl = useIntl(); - - const _renderInfo = (iconName, headingIntlId, bodyIntlId) => ( - - - - {intl.formatMessage({ id: headingIntlId })} - {intl.formatMessage({ id: bodyIntlId })} - - - ); - - return ( - - - - - {intl.formatMessage({ id: 'welcome.label' })} - {intl.formatMessage({ id: 'welcome.title' })} - - - {_renderInfo('question', 'welcome.line1_heading', 'welcome.line1_body')} - {_renderInfo('emotsmile', 'welcome.line2_heading', 'welcome.line2_body')} - {_renderInfo('people', 'welcome.line3_heading', 'welcome.line3_body')} - - - - - - - ); -}; - -export default WelcomeScreen; diff --git a/src/screens/feed/screen/feedScreen.tsx b/src/screens/feed/screen/feedScreen.tsx index c408a0d42..88fead999 100644 --- a/src/screens/feed/screen/feedScreen.tsx +++ b/src/screens/feed/screen/feedScreen.tsx @@ -1,10 +1,9 @@ -import React, { Fragment, useEffect } from 'react'; -import { SafeAreaView } from 'react-native'; -import { useSelector } from 'react-redux'; +import React, { Fragment, useState, useEffect } from 'react'; +import { ActivityIndicator, SafeAreaView } from 'react-native'; import get from 'lodash/get'; // Components -import { Posts, Header, TabbedPosts } from '../../../components'; +import { Header, TabbedPosts } from '../../../components'; // Container import { AccountContainer } from '../../../containers'; @@ -23,22 +22,37 @@ const FeedScreen = () => { const mainTabs = useAppSelector((state) => state.customTabs.mainTabs || getDefaultFilters('main')); const filterOptions = mainTabs.map((key) => getFilterMap('main')[key]); + const [lazyLoad, setLazyLoad] = useState(false); + + const _lazyLoadContent = () => { + if(!lazyLoad){ + setTimeout(() => { + setLazyLoad(true); + }, 100) + } + } + return ( {({ currentAccount }) => (
- - + + + {lazyLoad && ( + + + )} + )} diff --git a/src/screens/launch/screen/launchScreen.js b/src/screens/launch/screen/launchScreen.js index 975db650d..5a40f7399 100644 --- a/src/screens/launch/screen/launchScreen.js +++ b/src/screens/launch/screen/launchScreen.js @@ -1,10 +1,11 @@ import React from 'react'; -import { View, Appearance } from 'react-native'; +import { View } from 'react-native'; import LottieView from 'lottie-react-native'; import styles from './launchStyles'; +import { useAppSelector } from '../../../hooks'; const LaunchScreen = () => { - const isDarkMode = Appearance.getColorScheme() === 'dark'; + const isDarkMode = useAppSelector((state) => state.application.isDarkTheme); return ( { - this.setState({ - themeSetting, - }); - }); } // Component Functions @@ -127,11 +122,9 @@ class SettingsContainer extends Component { const systemTheme = Appearance.getColorScheme(); dispatch(isDarkTheme(setting === null ? systemTheme === 'dark' : setting)); + dispatch(setColorTheme(action)); + setTheme(setting); //TODO: remove before merging - setTheme(setting); - this.setState({ - themeSetting: setting, - }); break; default: @@ -269,6 +262,7 @@ class SettingsContainer extends Component { type: actionType, }), ); + //TODO: remove setting notification settings setNotificationSettings({ action, type: actionType, @@ -468,7 +462,8 @@ class SettingsContainer extends Component { }; render() { - const { serverList, isNotificationMenuOpen, isLoading, themeSetting } = this.state; + const { serverList, isNotificationMenuOpen, isLoading } = this.state; + const { colorTheme } = this.props; return ( ); @@ -486,6 +481,7 @@ class SettingsContainer extends Component { const mapStateToProps = (state) => ({ isDarkTheme: state.application.isDarkTheme, + colorTheme: state.application.colorTheme, isPinCodeOpen: state.application.isPinCodeOpen, pinCode: state.application.pin, isDefaultFooter: state.application.isDefaultFooter, diff --git a/src/screens/settings/screen/settingsScreen.js b/src/screens/settings/screen/settingsScreen.js index 1f5198b94..5aa362e50 100644 --- a/src/screens/settings/screen/settingsScreen.js +++ b/src/screens/settings/screen/settingsScreen.js @@ -22,7 +22,7 @@ const SettingsScreen = ({ handleOnChange, intl, isDarkTheme, - themeSetting, + colorThemeIndex, isPinCodeOpen, isLoggedIn, isNotificationSettingsOpen, @@ -129,7 +129,7 @@ const SettingsScreen = ({ id: item.key, }), )} - selectedOptionIndex={THEME_OPTIONS.findIndex((item) => item.value === themeSetting)} + selectedOptionIndex={colorThemeIndex} handleOnChange={handleOnChange} /> diff --git a/yarn.lock b/yarn.lock index ed5bf52dc..5d346ba07 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9049,10 +9049,10 @@ react-native-snap-carousel@^3.8.0: prop-types "^15.6.1" react-addons-shallow-compare "15.6.2" -react-native-splash-screen@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.2.0.tgz#d47ec8557b1ba988ee3ea98d01463081b60fff45" - integrity sha512-Ls9qiNZzW/OLFoI25wfjjAcrf2DZ975hn2vr6U9gyuxi2nooVbzQeFoQS5vQcbCt9QX5NY8ASEEAtlLdIa6KVg== +react-native-splash-screen@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.3.0.tgz#3af71ed17afe50fee69590a45aec399d071ead02" + integrity sha512-rGjt6HkoSXxMqH4SQUJ1gnPQlPJV8+J47+4yhgTIan4bVvAwJhEeJH7wWt9hXSdH4+VfwTS0GTaflj1Tw83IhA== react-native-svg@^12.1.1: version "12.1.1"