diff --git a/native/avatars/avatar-hooks.js b/native/avatars/avatar-hooks.js
--- a/native/avatars/avatar-hooks.js
+++ b/native/avatars/avatar-hooks.js
@@ -17,10 +17,7 @@
filenameFromPathOrURI,
} from 'lib/media/file-utils.js';
import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
-import type {
- ImageAvatarDBContent,
- UpdateUserAvatarRemoveRequest,
-} from 'lib/types/avatar-types.js';
+import type { ImageAvatarDBContent } from 'lib/types/avatar-types.js';
import type { SetState } from 'lib/types/hook-types.js';
import type { LoadingStatus } from 'lib/types/loading-types.js';
import type {
@@ -267,45 +264,6 @@
);
}
-function useRemoveThreadAvatar(threadID: string): [() => void, boolean] {
- const dispatchActionPromise = useDispatchActionPromise();
- const changeThreadSettingsCall = useServerCall(changeThreadSettings);
- const updateThreadAvatarLoadingStatus: LoadingStatus = useSelector(
- threadAvatarLoadingStatusSelector,
- );
-
- const removeThreadAvatar = React.useCallback(() => {
- const removeAvatarRequest: UpdateUserAvatarRemoveRequest = {
- type: 'remove',
- };
-
- const updateThreadRequest: UpdateThreadRequest = {
- threadID,
- changes: {
- avatar: removeAvatarRequest,
- },
- };
-
- dispatchActionPromise(
- changeThreadSettingsActionTypes,
- (async () => {
- try {
- return await changeThreadSettingsCall(updateThreadRequest);
- } catch (e) {
- Alert.alert('Avatar update failed', 'Unable to update avatar.');
- throw e;
- }
- })(),
- { customKeyName: `${changeThreadSettingsActionTypes.started}:avatar` },
- );
- }, [changeThreadSettingsCall, dispatchActionPromise, threadID]);
-
- return React.useMemo(
- () => [removeThreadAvatar, updateThreadAvatarLoadingStatus === 'loading'],
- [removeThreadAvatar, updateThreadAvatarLoadingStatus],
- );
-}
-
type ShowAvatarActionSheetOptions = {
+id: 'emoji' | 'image' | 'camera' | 'ens' | 'cancel' | 'remove',
+onPress?: () => mixed,
@@ -436,5 +394,4 @@
useProcessSelectedMedia,
useShowAvatarActionSheet,
useSelectFromGalleryAndUpdateThreadAvatar,
- useRemoveThreadAvatar,
};
diff --git a/native/avatars/edit-thread-avatar-provider.react.js b/native/avatars/edit-thread-avatar-provider.react.js
new file mode 100644
--- /dev/null
+++ b/native/avatars/edit-thread-avatar-provider.react.js
@@ -0,0 +1,93 @@
+// @flow
+
+import * as React from 'react';
+import { Alert } from 'react-native';
+
+import {
+ changeThreadSettings,
+ changeThreadSettingsActionTypes,
+} from 'lib/actions/thread-actions.js';
+import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
+import type { UpdateUserAvatarRemoveRequest } from 'lib/types/avatar-types.js';
+import type { LoadingStatus } from 'lib/types/loading-types.js';
+import type { UpdateThreadRequest } from 'lib/types/thread-types.js';
+import {
+ useDispatchActionPromise,
+ useServerCall,
+} from 'lib/utils/action-utils.js';
+
+import { useSelector } from '../redux/redux-utils.js';
+
+export type EditThreadAvatarContextType = {
+ +threadAvatarSaveInProgress: boolean,
+ +removeThreadAvatar: (threadID: string) => void,
+};
+
+const EditThreadAvatarContext: React.Context =
+ React.createContext();
+
+const threadAvatarLoadingStatusSelector = createLoadingStatusSelector(
+ changeThreadSettingsActionTypes,
+ `${changeThreadSettingsActionTypes.started}:avatar`,
+);
+
+type Props = {
+ +children: React.Node,
+};
+function EditThreadAvatarProvider(props: Props): React.Node {
+ const { children } = props;
+
+ const dispatchActionPromise = useDispatchActionPromise();
+ const changeThreadSettingsCall = useServerCall(changeThreadSettings);
+ const updateThreadAvatarLoadingStatus: LoadingStatus = useSelector(
+ threadAvatarLoadingStatusSelector,
+ );
+
+ const threadAvatarSaveInProgress =
+ updateThreadAvatarLoadingStatus === 'loading';
+
+ const removeThreadAvatar = React.useCallback(
+ (threadID: string) => {
+ const removeAvatarRequest: UpdateUserAvatarRemoveRequest = {
+ type: 'remove',
+ };
+
+ const updateThreadRequest: UpdateThreadRequest = {
+ threadID,
+ changes: {
+ avatar: removeAvatarRequest,
+ },
+ };
+
+ dispatchActionPromise(
+ changeThreadSettingsActionTypes,
+ (async () => {
+ try {
+ return await changeThreadSettingsCall(updateThreadRequest);
+ } catch (e) {
+ Alert.alert('Avatar update failed', 'Unable to update avatar.');
+ throw e;
+ }
+ })(),
+ { customKeyName: `${changeThreadSettingsActionTypes.started}:avatar` },
+ );
+ },
+ [changeThreadSettingsCall, dispatchActionPromise],
+ );
+
+ const context = React.useMemo(
+ () => ({
+ threadAvatarSaveInProgress,
+ removeThreadAvatar,
+ }),
+ [removeThreadAvatar, threadAvatarSaveInProgress],
+ );
+
+ return (
+
+ {children}
+
+ );
+}
+
+export { EditThreadAvatarContext, EditThreadAvatarProvider };
diff --git a/native/avatars/edit-thread-avatar.react.js b/native/avatars/edit-thread-avatar.react.js
--- a/native/avatars/edit-thread-avatar.react.js
+++ b/native/avatars/edit-thread-avatar.react.js
@@ -1,16 +1,17 @@
// @flow
+import invariant from 'invariant';
import * as React from 'react';
import { ActivityIndicator, TouchableOpacity, View } from 'react-native';
import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js';
import {
- useRemoveThreadAvatar,
useSelectFromGalleryAndUpdateThreadAvatar,
useShowAvatarActionSheet,
} from './avatar-hooks.js';
import EditAvatarBadge from './edit-avatar-badge.react.js';
+import { EditThreadAvatarContext } from './edit-thread-avatar-provider.react.js';
import ThreadAvatar from './thread-avatar.react.js';
import { useStyles } from '../themes/colors.js';
@@ -23,24 +24,31 @@
const styles = useStyles(unboundStyles);
const { threadInfo, onPressEmojiAvatarFlow, disabled } = props;
+ const editThreadAvatarContext = React.useContext(EditThreadAvatarContext);
+ invariant(editThreadAvatarContext, 'editThreadAvatarContext should be set');
+ const { threadAvatarSaveInProgress, removeThreadAvatar } =
+ editThreadAvatarContext;
+
const [selectFromGalleryAndUpdateThreadAvatar, isGalleryAvatarUpdateLoading] =
useSelectFromGalleryAndUpdateThreadAvatar(threadInfo.id);
- const [removeThreadAvatar, isRemoveAvatarUpdateLoading] =
- useRemoveThreadAvatar(threadInfo.id);
-
const isAvatarUpdateInProgress =
- isGalleryAvatarUpdateLoading || isRemoveAvatarUpdateLoading;
+ isGalleryAvatarUpdateLoading || threadAvatarSaveInProgress;
+
+ const removeAvatar = React.useCallback(
+ () => removeThreadAvatar(threadInfo.id),
+ [removeThreadAvatar, threadInfo.id],
+ );
const actionSheetConfig = React.useMemo(
() => [
{ id: 'emoji', onPress: onPressEmojiAvatarFlow },
{ id: 'image', onPress: selectFromGalleryAndUpdateThreadAvatar },
- { id: 'remove', onPress: removeThreadAvatar },
+ { id: 'remove', onPress: removeAvatar },
],
[
onPressEmojiAvatarFlow,
- removeThreadAvatar,
+ removeAvatar,
selectFromGalleryAndUpdateThreadAvatar,
],
);
diff --git a/native/root.react.js b/native/root.react.js
--- a/native/root.react.js
+++ b/native/root.react.js
@@ -22,6 +22,7 @@
import { MediaCacheProvider } from 'lib/components/media-cache-provider.react.js';
import { actionLogger } from 'lib/utils/action-logger.js';
+import { EditThreadAvatarProvider } from './avatars/edit-thread-avatar-provider.react.js';
import { EditUserAvatarProvider } from './avatars/edit-user-avatar-provider.react.js';
import ChatContextProvider from './chat/chat-context-provider.react.js';
import { FeatureFlagsProvider } from './components/feature-flags-provider.react.js';
@@ -258,23 +259,25 @@
-
-
-
-
-
- {gated}
-
-
-
-
- {navigation}
-
-
+
+
+
+
+
+
+ {gated}
+
+
+
+
+ {navigation}
+
+
+