diff --git a/lib/hooks/invite-links.js b/lib/hooks/invite-links.js new file mode 100644 --- /dev/null +++ b/lib/hooks/invite-links.js @@ -0,0 +1,105 @@ +// @flow + +import React from 'react'; + +import { + createOrUpdatePublicLink, + createOrUpdatePublicLinkActionTypes, + disableInviteLink as callDisableInviteLink, + disableInviteLinkLinkActionTypes, +} from '../actions/link-actions.js'; +import { createLoadingStatusSelector } from '../selectors/loading-selectors.js'; +import type { SetState } from '../types/hook-types.js'; +import type { InviteLink } from '../types/link-types.js'; +import { + useDispatchActionPromise, + useServerCall, +} from '../utils/action-utils.js'; +import { useSelector } from '../utils/redux-utils.js'; + +const createOrUpdatePublicLinkStatusSelector = createLoadingStatusSelector( + createOrUpdatePublicLinkActionTypes, +); +const disableInviteLinkStatusSelector = createLoadingStatusSelector( + disableInviteLinkLinkActionTypes, +); + +function useInviteLinksActions( + communityID: string, + inviteLink: ?InviteLink, +): { + +error: ?string, + +isLoading: boolean, + +name: string, + +setName: SetState, + +createOrUpdateInviteLink: () => mixed, + +disableInviteLink: () => mixed, +} { + const [name, setName] = React.useState( + inviteLink?.name ?? Math.random().toString(36).slice(-9), + ); + const [error, setError] = React.useState(null); + const dispatchActionPromise = useDispatchActionPromise(); + + const callCreateOrUpdatePublicLink = useServerCall(createOrUpdatePublicLink); + const createCreateOrUpdateActionPromise = React.useCallback(async () => { + setError(null); + try { + return await callCreateOrUpdatePublicLink({ + name, + communityID, + }); + } catch (e) { + setError(e.message); + throw e; + } + }, [callCreateOrUpdatePublicLink, communityID, name]); + const createOrUpdateInviteLink = React.useCallback(() => { + dispatchActionPromise( + createOrUpdatePublicLinkActionTypes, + createCreateOrUpdateActionPromise(), + ); + }, [createCreateOrUpdateActionPromise, dispatchActionPromise]); + + const disableInviteLinkServerCall = useServerCall(callDisableInviteLink); + const createDisableLinkActionPromise = React.useCallback(async () => { + setError(null); + try { + return await disableInviteLinkServerCall({ + name, + communityID, + }); + } catch (e) { + setError(e.message); + throw e; + } + }, [disableInviteLinkServerCall, communityID, name]); + const disableInviteLink = React.useCallback(() => { + dispatchActionPromise( + disableInviteLinkLinkActionTypes, + createDisableLinkActionPromise(), + ); + }, [createDisableLinkActionPromise, dispatchActionPromise]); + const disableInviteLinkStatus = useSelector(disableInviteLinkStatusSelector); + + const createOrUpdatePublicLinkStatus = useSelector( + createOrUpdatePublicLinkStatusSelector, + ); + const isLoading = + createOrUpdatePublicLinkStatus === 'loading' || + disableInviteLinkStatus === 'loading'; + + return React.useMemo( + () => ({ + error, + isLoading, + name, + setName, + createOrUpdateInviteLink, + disableInviteLink, + }), + [createOrUpdateInviteLink, disableInviteLink, error, isLoading, name], + ); +} + +export { useInviteLinksActions }; diff --git a/native/invite-links/manage-public-link-screen.react.js b/native/invite-links/manage-public-link-screen.react.js --- a/native/invite-links/manage-public-link-screen.react.js +++ b/native/invite-links/manage-public-link-screen.react.js @@ -3,20 +3,10 @@ import * as React from 'react'; import { Text, View, Alert } from 'react-native'; -import { - createOrUpdatePublicLink, - createOrUpdatePublicLinkActionTypes, - disableInviteLink as callDisableInviteLink, - disableInviteLinkLinkActionTypes, -} from 'lib/actions/link-actions.js'; import { inviteLinkUrl } from 'lib/facts/links.js'; +import { useInviteLinksActions } from 'lib/hooks/invite-links.js'; import { primaryInviteLinksSelector } from 'lib/selectors/invite-links-selectors.js'; -import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils.js'; import Button from '../components/button.react.js'; import TextInput from '../components/text-input.react.js'; @@ -37,34 +27,14 @@ function ManagePublicLinkScreen(props: Props): React.Node { const { community } = props.route.params; const inviteLink = useSelector(primaryInviteLinksSelector)[community.id]; - const [name, setName] = React.useState( - inviteLink?.name ?? Math.random().toString(36).slice(-9), - ); - const [error, setError] = React.useState(null); - - const dispatchActionPromise = useDispatchActionPromise(); - const callCreateOrUpdatePublicLink = useServerCall(createOrUpdatePublicLink); - const createCreateOrUpdateActionPromise = React.useCallback(async () => { - setError(null); - try { - return await callCreateOrUpdatePublicLink({ - name, - communityID: community.id, - }); - } catch (e) { - setError(e.message); - throw e; - } - }, [callCreateOrUpdatePublicLink, community.id, name]); - const createInviteLink = React.useCallback(() => { - dispatchActionPromise( - createOrUpdatePublicLinkActionTypes, - createCreateOrUpdateActionPromise(), - ); - }, [createCreateOrUpdateActionPromise, dispatchActionPromise]); - const createOrUpdatePublicLinkStatus = useSelector( - createOrUpdatePublicLinkStatusSelector, - ); + const { + error, + isLoading, + name, + setName, + createOrUpdateInviteLink, + disableInviteLink, + } = useInviteLinksActions(community.id, inviteLink); const styles = useStyles(unboundStyles); @@ -73,31 +43,6 @@ errorComponent = {error}; } - const disableInviteLinkServerCall = useServerCall(callDisableInviteLink); - const createDisableLinkActionPromise = React.useCallback(async () => { - setError(null); - try { - return await disableInviteLinkServerCall({ - name, - communityID: community.id, - }); - } catch (e) { - setError(e.message); - throw e; - } - }, [disableInviteLinkServerCall, community.id, name]); - const disableInviteLink = React.useCallback(() => { - dispatchActionPromise( - disableInviteLinkLinkActionTypes, - createDisableLinkActionPromise(), - ); - }, [createDisableLinkActionPromise, dispatchActionPromise]); - const disableInviteLinkStatus = useSelector(disableInviteLinkStatusSelector); - - const isLoading = - createOrUpdatePublicLinkStatus === 'loading' || - disableInviteLinkStatus === 'loading'; - const onDisableButtonClick = React.useCallback(() => { Alert.alert( 'Disable public link', @@ -162,7 +107,7 @@ {errorComponent}