diff --git a/src/SyncGate.tsx b/src/SyncGate.tsx index bad8b6e..2ba4db0 100644 --- a/src/SyncGate.tsx +++ b/src/SyncGate.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { connect } from 'react-redux'; +import { useSelector } from 'react-redux'; import { Route, Switch, Redirect, RouteComponentProps, withRouter } from 'react-router'; import moment from 'moment'; @@ -21,7 +21,7 @@ import Pim from './Pim'; import * as EteSync from 'etesync'; import { CURRENT_VERSION } from 'etesync'; -import { store, SettingsType, JournalsData, EntriesData, StoreState, CredentialsData, UserInfoData } from './store'; +import { store, JournalsData, EntriesData, StoreState, CredentialsData, UserInfoData } from './store'; import { addJournal, fetchAll, fetchEntries, fetchUserInfo, createUserInfo } from './store/actions'; export interface SyncInfoJournal { @@ -37,19 +37,18 @@ interface PropsType { etesync: CredentialsData; } -type PropsTypeInner = RouteComponentProps<{}> & PropsType & { - settings: SettingsType; +interface SelectorProps { + etesync: CredentialsData; journals: JournalsData; entries: EntriesData; userInfo: UserInfoData; - fetchCount: number; -}; +} const syncInfoSelector = createSelector( - (props: PropsTypeInner) => props.etesync, - (props: PropsTypeInner) => props.journals!, - (props: PropsTypeInner) => props.entries, - (props: PropsTypeInner) => props.userInfo, + (props: SelectorProps) => props.etesync, + (props: SelectorProps) => props.journals!, + (props: SelectorProps) => props.entries, + (props: SelectorProps) => props.userInfo, (etesync, journals, entries, userInfo) => { const derived = etesync.encryptionKey; const userInfoCryptoManager = userInfo.getCryptoManager(etesync.encryptionKey); @@ -98,11 +97,19 @@ const syncInfoSelector = createSelector( const PimRouter = withRouter(Pim); -class SyncGate extends React.PureComponent { - public componentDidMount() { - const me = this.props.etesync.credentials.email; +// FIXME: this and withRouters are only needed here because of https://github.com/ReactTraining/react-router/issues/5795 +export default withRouter(function SyncGate(props: RouteComponentProps<{}> & PropsType) { + const etesync = props.etesync; + const settings = useSelector((state: StoreState) => state.settings); + const fetchCount = useSelector((state: StoreState) => state.fetchCount); + const userInfo = useSelector((state: StoreState) => state.cache.userInfo); + const journals = useSelector((state: StoreState) => state.cache.journals); + const entries = useSelector((state: StoreState) => state.cache.entries); + + React.useEffect(() => { + const me = etesync.credentials.email; const syncAll = () => { - store.dispatch(fetchAll(this.props.etesync, this.props.entries)).then((haveJournals: boolean) => { + store.dispatch(fetchAll(etesync, entries)).then((haveJournals: boolean) => { if (haveJournals) { return; } @@ -114,14 +121,14 @@ class SyncGate extends React.PureComponent { collection.displayName = 'Default'; const journal = new EteSync.Journal({ uid: collection.uid }); - const cryptoManager = new EteSync.CryptoManager(this.props.etesync.encryptionKey, collection.uid); + const cryptoManager = new EteSync.CryptoManager(etesync.encryptionKey, collection.uid); journal.setInfo(cryptoManager, collection); (async () => { try { - const addedJournalAction = addJournal(this.props.etesync, journal); + const addedJournalAction = addJournal(etesync, journal); await addedJournalAction.payload; store.dispatch(addedJournalAction); - store.dispatch(fetchEntries(this.props.etesync, collection.uid)); + store.dispatch(fetchEntries(etesync, collection.uid)); } catch (e) { // FIXME: Limit based on error code to only ignore for associates console.warn(`Failed creating journal for ${collection.type}. Associate?`); @@ -131,113 +138,95 @@ class SyncGate extends React.PureComponent { }); }; - if (this.props.userInfo) { + if (userInfo) { syncAll(); } else { - const fetching = fetchUserInfo(this.props.etesync, me); + const fetching = fetchUserInfo(etesync, me); fetching.payload?.then(() => { store.dispatch(fetching); syncAll(); }).catch(() => { const userInfo = new EteSync.UserInfo(me, CURRENT_VERSION); const keyPair = EteSync.AsymmetricCryptoManager.generateKeyPair(); - const cryptoManager = userInfo.getCryptoManager(this.props.etesync.encryptionKey); + const cryptoManager = userInfo.getCryptoManager(etesync.encryptionKey); userInfo.setKeyPair(cryptoManager, keyPair); - store.dispatch(createUserInfo(this.props.etesync, userInfo)).then(syncAll); + store.dispatch(createUserInfo(etesync, userInfo)).then(syncAll); }); } - } + }, []); - public render() { - const entryArrays = this.props.entries; - const journals = this.props.journals; + const entryArrays = entries; - if ((this.props.userInfo === null) || (journals === null) || - ((this.props.fetchCount > 0) && - ((entryArrays.size === 0) || entryArrays.some((x) => (x.size === 0)))) - ) { - return (); - } + if ((userInfo === null) || (journals === null) || + ((fetchCount > 0) && + ((entryArrays.size === 0) || entryArrays.some((x) => (x.size === 0)))) + ) { + return (); + } - // FIXME: Shouldn't be here - moment.locale(this.props.settings.locale); - - - const journalMap = syncInfoSelector(this.props); - - return ( - - ( - - )} - /> - ( - <> - - - - )} - /> - ( - + ( + + )} + /> + ( + <> + + - )} - /> - ( - - )} - /> - ( - - )} - /> - - ); - } -} - -const mapStateToProps = (state: StoreState, _props: PropsType) => { - return { - settings: state.settings, - journals: state.cache.journals, - entries: state.cache.entries, - userInfo: state.cache.userInfo, - fetchCount: state.fetchCount, - }; -}; - -// FIXME: this and withRouters are only needed here because of https://github.com/ReactTraining/react-router/issues/5795 -export default withRouter(connect( - mapStateToProps -)(SyncGate)); + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + + ); +});