Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32525176
D7504.1767138775.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D7504.1767138775.diff
View Options
diff --git a/native/avatars/emoji-avatar-creation.react.js b/native/avatars/emoji-avatar-creation.react.js
--- a/native/avatars/emoji-avatar-creation.react.js
+++ b/native/avatars/emoji-avatar-creation.react.js
@@ -9,50 +9,29 @@
} from 'react-native';
import EmojiPicker from 'rn-emoji-keyboard';
-import { changeThreadSettingsActionTypes } from 'lib/actions/thread-actions.js';
-import { updateUserAvatarActionTypes } from 'lib/actions/user-actions.js';
-import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
-import { savedEmojiAvatarSelectorForThread } from 'lib/selectors/thread-selectors.js';
-import { savedEmojiAvatarSelectorForCurrentUser } from 'lib/selectors/user-selectors.js';
-import type { ClientEmojiAvatar } from 'lib/types/avatar-types.js';
+import type {
+ UpdateUserAvatarRequest,
+ ClientEmojiAvatar,
+} from 'lib/types/avatar-types';
import Avatar from './avatar.react.js';
import Button from '../components/button.react.js';
import ColorRows from '../components/color-rows.react.js';
import { useSelector } from '../redux/redux-utils.js';
+import type { AppState } from '../redux/state-types.js';
import { useStyles } from '../themes/colors.js';
-import {
- useSaveUserAvatar,
- useSaveThreadAvatar,
-} from '../utils/avatar-utils.js';
-
-const userAvatarLoadingStatusSelector = createLoadingStatusSelector(
- updateUserAvatarActionTypes,
-);
-
-const threadAvatarLoadingStatusSelector = createLoadingStatusSelector(
- changeThreadSettingsActionTypes,
- `${changeThreadSettingsActionTypes.started}:avatar`,
-);
-
-export type EmojiAvatarCreationParams = {
- +threadID?: string,
- +containingThreadID?: ?string,
-};
type Props = {
- +threadID?: string,
- +containingThreadID?: ?string,
+ +saveAvatarCall: (newAvatarRequest: UpdateUserAvatarRequest) => mixed,
+ +saveAvatarCallLoading: boolean,
+ +savedEmojiAvatarSelector: (state: AppState) => () => ClientEmojiAvatar,
};
function EmojiAvatarCreation(props: Props): React.Node {
- const { threadID, containingThreadID } = props;
+ const { saveAvatarCall, saveAvatarCallLoading, savedEmojiAvatarSelector } =
+ props;
- const selector = threadID
- ? savedEmojiAvatarSelectorForThread(threadID, containingThreadID)
- : savedEmojiAvatarSelectorForCurrentUser;
-
- const savedEmojiAvatarFunc = useSelector(selector);
+ const savedEmojiAvatarFunc = useSelector(savedEmojiAvatarSelector);
const [pendingEmoji, setPendingEmoji] = React.useState<string>(
() => savedEmojiAvatarFunc().emoji,
@@ -65,16 +44,6 @@
const styles = useStyles(unboundStyles);
- const saveUserAvatar = useSaveUserAvatar();
- const saveThreadAvatar = useSaveThreadAvatar();
-
- const saveUserAvatarCallLoading = useSelector(
- state => userAvatarLoadingStatusSelector(state) === 'loading',
- );
- const saveThreadAvatarCallLoading = useSelector(
- state => threadAvatarLoadingStatusSelector(state) === 'loading',
- );
-
const onPressEditEmoji = React.useCallback(() => {
setEmojiKeyboardOpen(true);
}, []);
@@ -86,12 +55,8 @@
color: pendingColor,
};
- if (!threadID) {
- saveUserAvatar(newEmojiAvatarRequest);
- } else {
- saveThreadAvatar(newEmojiAvatarRequest, threadID);
- }
- }, [pendingColor, pendingEmoji, saveThreadAvatar, saveUserAvatar, threadID]);
+ saveAvatarCall(newEmojiAvatarRequest);
+ }, [pendingColor, pendingEmoji, saveAvatarCall]);
const onPressReset = React.useCallback(() => {
const resetEmojiAvatar = savedEmojiAvatarFunc();
@@ -119,7 +84,7 @@
);
const loadingContainer = React.useMemo(() => {
- if (!saveUserAvatarCallLoading && !saveThreadAvatarCallLoading) {
+ if (!saveAvatarCallLoading) {
return null;
}
@@ -128,11 +93,7 @@
<ActivityIndicator size="large" color="white" />
</View>
);
- }, [
- saveThreadAvatarCallLoading,
- saveUserAvatarCallLoading,
- styles.loadingContainer,
- ]);
+ }, [saveAvatarCallLoading, styles.loadingContainer]);
return (
<View style={styles.container}>
@@ -160,14 +121,14 @@
<Button
onPress={onPressSetAvatar}
style={styles.saveButton}
- disabled={saveUserAvatarCallLoading || saveThreadAvatarCallLoading}
+ disabled={saveAvatarCallLoading}
>
<Text style={styles.saveButtonText}>Save Avatar</Text>
</Button>
<Button
onPress={onPressReset}
style={styles.resetButton}
- disabled={saveUserAvatarCallLoading || saveThreadAvatarCallLoading}
+ disabled={saveAvatarCallLoading}
>
<Text style={styles.resetButtonText}>Reset</Text>
</Button>
diff --git a/native/chat/settings/emoji-thread-avatar-creation.react.js b/native/chat/settings/emoji-thread-avatar-creation.react.js
--- a/native/chat/settings/emoji-thread-avatar-creation.react.js
+++ b/native/chat/settings/emoji-thread-avatar-creation.react.js
@@ -1,36 +1,16 @@
// @flow
import * as React from 'react';
-import {
- View,
- Text,
- TouchableWithoutFeedback,
- ActivityIndicator,
-} from 'react-native';
-import EmojiPicker from 'rn-emoji-keyboard';
import { changeThreadSettingsActionTypes } from 'lib/actions/thread-actions.js';
-import { updateUserAvatarActionTypes } from 'lib/actions/user-actions.js';
import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
import { savedEmojiAvatarSelectorForThread } from 'lib/selectors/thread-selectors.js';
-import { savedEmojiAvatarSelectorForCurrentUser } from 'lib/selectors/user-selectors.js';
-import type { ClientEmojiAvatar } from 'lib/types/avatar-types.js';
-import Avatar from '../../avatars/avatar.react.js';
+import EmojiAvatarCreation from '../../avatars/emoji-avatar-creation.react.js';
import type { ChatNavigationProp } from '../../chat/chat.react.js';
-import Button from '../../components/button.react.js';
-import ColorRows from '../../components/color-rows.react.js';
import type { NavigationRoute } from '../../navigation/route-names.js';
import { useSelector } from '../../redux/redux-utils.js';
-import { useStyles } from '../../themes/colors.js';
-import {
- useSaveUserAvatar,
- useSaveThreadAvatar,
-} from '../../utils/avatar-utils.js';
-
-const userAvatarLoadingStatusSelector = createLoadingStatusSelector(
- updateUserAvatarActionTypes,
-);
+import { useSaveThreadAvatar } from '../../utils/avatar-utils.js';
const threadAvatarLoadingStatusSelector = createLoadingStatusSelector(
changeThreadSettingsActionTypes,
@@ -38,7 +18,7 @@
);
export type EmojiThreadAvatarCreationParams = {
- +threadID?: string,
+ +threadID: string,
+containingThreadID?: ?string,
};
@@ -50,207 +30,28 @@
function EmojiThreadAvatarCreation(props: Props): React.Node {
const { threadID, containingThreadID } = props.route.params;
- const selector = threadID
- ? savedEmojiAvatarSelectorForThread(threadID, containingThreadID)
- : savedEmojiAvatarSelectorForCurrentUser;
-
- const savedEmojiAvatarFunc = useSelector(selector);
-
- const [pendingEmoji, setPendingEmoji] = React.useState<string>(
- () => savedEmojiAvatarFunc().emoji,
- );
- const [pendingColor, setPendingColor] = React.useState<string>(
- () => savedEmojiAvatarFunc().color,
+ const selector = savedEmojiAvatarSelectorForThread(
+ threadID,
+ containingThreadID,
);
- const [emojiKeyboardOpen, setEmojiKeyboardOpen] =
- React.useState<boolean>(false);
- const styles = useStyles(unboundStyles);
-
- const saveUserAvatar = useSaveUserAvatar();
const saveThreadAvatar = useSaveThreadAvatar();
-
- const saveUserAvatarCallLoading = useSelector(
- state => userAvatarLoadingStatusSelector(state) === 'loading',
- );
const saveThreadAvatarCallLoading = useSelector(
state => threadAvatarLoadingStatusSelector(state) === 'loading',
);
- const onPressEditEmoji = React.useCallback(() => {
- setEmojiKeyboardOpen(true);
- }, []);
-
- const onPressSetAvatar = React.useCallback(() => {
- const newEmojiAvatarRequest = {
- type: 'emoji',
- emoji: pendingEmoji,
- color: pendingColor,
- };
-
- if (!threadID) {
- saveUserAvatar(newEmojiAvatarRequest);
- } else {
- saveThreadAvatar(newEmojiAvatarRequest, threadID);
- }
- }, [pendingColor, pendingEmoji, saveThreadAvatar, saveUserAvatar, threadID]);
-
- const onPressReset = React.useCallback(() => {
- const resetEmojiAvatar = savedEmojiAvatarFunc();
-
- setPendingEmoji(resetEmojiAvatar.emoji);
- setPendingColor(resetEmojiAvatar.color);
- }, [savedEmojiAvatarFunc]);
-
- const onEmojiSelected = React.useCallback(emoji => {
- setPendingEmoji(emoji.emoji);
- }, []);
-
- const onEmojiKeyboardClose = React.useCallback(
- () => setEmojiKeyboardOpen(false),
- [],
- );
-
- const stagedAvatarInfo: ClientEmojiAvatar = React.useMemo(
- () => ({
- type: 'emoji',
- emoji: pendingEmoji,
- color: pendingColor,
- }),
- [pendingColor, pendingEmoji],
+ const saveThreadAvatarCallback = React.useCallback(
+ newAvatarRequest => saveThreadAvatar(newAvatarRequest, threadID),
+ [saveThreadAvatar, threadID],
);
- const loadingContainer = React.useMemo(() => {
- if (!saveUserAvatarCallLoading && !saveThreadAvatarCallLoading) {
- return null;
- }
-
- return (
- <View style={styles.loadingContainer}>
- <ActivityIndicator size="large" color="white" />
- </View>
- );
- }, [
- saveThreadAvatarCallLoading,
- saveUserAvatarCallLoading,
- styles.loadingContainer,
- ]);
-
return (
- <View style={styles.container}>
- <View style={styles.emojiAvatarCreationContainer}>
- <View style={styles.stagedAvatarSection}>
- <TouchableWithoutFeedback onPress={onPressEditEmoji}>
- <View>
- <View>
- <Avatar size="profile" avatarInfo={stagedAvatarInfo} />
- {loadingContainer}
- </View>
- <Text style={styles.editEmojiText}>Edit Emoji</Text>
- </View>
- </TouchableWithoutFeedback>
- </View>
- <View style={styles.colorRowsSection}>
- <ColorRows
- pendingColor={pendingColor}
- setPendingColor={setPendingColor}
- outerRingSelectedColorStyle={styles.selectedColorOuterRing}
- />
- </View>
- </View>
- <View style={styles.buttonsContainer}>
- <Button
- onPress={onPressSetAvatar}
- style={styles.saveButton}
- disabled={saveUserAvatarCallLoading || saveThreadAvatarCallLoading}
- >
- <Text style={styles.saveButtonText}>Save Avatar</Text>
- </Button>
- <Button
- onPress={onPressReset}
- style={styles.resetButton}
- disabled={saveUserAvatarCallLoading || saveThreadAvatarCallLoading}
- >
- <Text style={styles.resetButtonText}>Reset</Text>
- </Button>
- </View>
- <EmojiPicker
- onEmojiSelected={onEmojiSelected}
- open={emojiKeyboardOpen}
- onClose={onEmojiKeyboardClose}
- />
- </View>
+ <EmojiAvatarCreation
+ saveAvatarCall={saveThreadAvatarCallback}
+ saveAvatarCallLoading={saveThreadAvatarCallLoading}
+ savedEmojiAvatarSelector={selector}
+ />
);
}
-const unboundStyles = {
- container: {
- flex: 1,
- justifyContent: 'space-between',
- },
- emojiAvatarCreationContainer: {
- paddingTop: 16,
- },
- stagedAvatarSection: {
- backgroundColor: 'panelForeground',
- paddingVertical: 24,
- alignItems: 'center',
- },
- editEmojiText: {
- color: 'purpleLink',
- marginTop: 16,
- fontWeight: '500',
- fontSize: 16,
- lineHeight: 24,
- textAlign: 'center',
- },
- colorRowsSection: {
- paddingVertical: 24,
- marginTop: 24,
- backgroundColor: 'panelForeground',
- alignItems: 'center',
- },
- selectedColorOuterRing: {
- backgroundColor: 'modalSubtext',
- },
- buttonsContainer: {
- paddingHorizontal: 16,
- paddingBottom: 8,
- },
- saveButton: {
- backgroundColor: 'purpleButton',
- paddingVertical: 12,
- borderRadius: 8,
- },
- saveButtonText: {
- color: 'whiteText',
- textAlign: 'center',
- fontWeight: '500',
- fontSize: 16,
- lineHeight: 24,
- },
- resetButton: {
- padding: 12,
- borderRadius: 8,
- marginTop: 8,
- alignSelf: 'center',
- },
- resetButtonText: {
- color: 'redText',
- textAlign: 'center',
- fontWeight: '500',
- fontSize: 16,
- lineHeight: 24,
- },
- loadingContainer: {
- position: 'absolute',
- backgroundColor: 'black',
- width: 112,
- height: 112,
- borderRadius: 56,
- opacity: 0.6,
- justifyContent: 'center',
- },
-};
-
export default EmojiThreadAvatarCreation;
diff --git a/native/navigation/route-names.js b/native/navigation/route-names.js
--- a/native/navigation/route-names.js
+++ b/native/navigation/route-names.js
@@ -26,7 +26,6 @@
import type { ImageModalParams } from '../media/image-modal.react.js';
import type { VideoPlaybackModalParams } from '../media/video-playback-modal.react.js';
import type { CustomServerModalParams } from '../profile/custom-server-modal.react.js';
-import type { EmojiUserAvatarCreationParams } from '../profile/emoji-user-avatar-creation.react.js';
import type { RelationshipListItemTooltipModalParams } from '../profile/relationship-list-item-tooltip-modal.react.js';
export const ActionResultModalRouteName = 'ActionResultModal';
@@ -143,7 +142,7 @@
export type ProfileParamList = {
+ProfileScreen: void,
- +EmojiUserAvatarCreation: EmojiUserAvatarCreationParams,
+ +EmojiUserAvatarCreation: void,
+EditPassword: void,
+DeleteAccount: void,
+BuildInfo: void,
diff --git a/native/profile/emoji-user-avatar-creation.react.js b/native/profile/emoji-user-avatar-creation.react.js
--- a/native/profile/emoji-user-avatar-creation.react.js
+++ b/native/profile/emoji-user-avatar-creation.react.js
@@ -1,256 +1,33 @@
// @flow
import * as React from 'react';
-import {
- View,
- Text,
- TouchableWithoutFeedback,
- ActivityIndicator,
-} from 'react-native';
-import EmojiPicker from 'rn-emoji-keyboard';
-import { changeThreadSettingsActionTypes } from 'lib/actions/thread-actions.js';
import { updateUserAvatarActionTypes } from 'lib/actions/user-actions.js';
import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
-import { savedEmojiAvatarSelectorForThread } from 'lib/selectors/thread-selectors.js';
import { savedEmojiAvatarSelectorForCurrentUser } from 'lib/selectors/user-selectors.js';
-import type { ClientEmojiAvatar } from 'lib/types/avatar-types.js';
-import Avatar from '../avatars/avatar.react.js';
-import Button from '../components/button.react.js';
-import ColorRows from '../components/color-rows.react.js';
-import type { NavigationRoute } from '../navigation/route-names.js';
-import type { ProfileNavigationProp } from '../profile/profile.react.js';
+import EmojiAvatarCreation from '../avatars/emoji-avatar-creation.react.js';
import { useSelector } from '../redux/redux-utils.js';
-import { useStyles } from '../themes/colors.js';
-import {
- useSaveUserAvatar,
- useSaveThreadAvatar,
-} from '../utils/avatar-utils.js';
+import { useSaveUserAvatar } from '../utils/avatar-utils.js';
const userAvatarLoadingStatusSelector = createLoadingStatusSelector(
updateUserAvatarActionTypes,
);
-const threadAvatarLoadingStatusSelector = createLoadingStatusSelector(
- changeThreadSettingsActionTypes,
- `${changeThreadSettingsActionTypes.started}:avatar`,
-);
-
-export type EmojiUserAvatarCreationParams = {
- +threadID?: string,
- +containingThreadID?: ?string,
-};
-
-type Props = {
- +navigation: ProfileNavigationProp<'EmojiUserAvatarCreation'>,
- +route: NavigationRoute<'EmojiUserAvatarCreation'>,
-};
-
-function EmojiUserAvatarCreation(props: Props): React.Node {
- const { threadID, containingThreadID } = props.route.params;
-
- const selector = threadID
- ? savedEmojiAvatarSelectorForThread(threadID, containingThreadID)
- : savedEmojiAvatarSelectorForCurrentUser;
-
- const savedEmojiAvatarFunc = useSelector(selector);
-
- const [pendingEmoji, setPendingEmoji] = React.useState<string>(
- () => savedEmojiAvatarFunc().emoji,
- );
- const [pendingColor, setPendingColor] = React.useState<string>(
- () => savedEmojiAvatarFunc().color,
- );
- const [emojiKeyboardOpen, setEmojiKeyboardOpen] =
- React.useState<boolean>(false);
-
- const styles = useStyles(unboundStyles);
-
+// eslint-disable-next-line no-unused-vars
+function EmojiUserAvatarCreation(props: { ... }): React.Node {
const saveUserAvatar = useSaveUserAvatar();
- const saveThreadAvatar = useSaveThreadAvatar();
-
const saveUserAvatarCallLoading = useSelector(
state => userAvatarLoadingStatusSelector(state) === 'loading',
);
- const saveThreadAvatarCallLoading = useSelector(
- state => threadAvatarLoadingStatusSelector(state) === 'loading',
- );
-
- const onPressEditEmoji = React.useCallback(() => {
- setEmojiKeyboardOpen(true);
- }, []);
-
- const onPressSetAvatar = React.useCallback(() => {
- const newEmojiAvatarRequest = {
- type: 'emoji',
- emoji: pendingEmoji,
- color: pendingColor,
- };
-
- if (!threadID) {
- saveUserAvatar(newEmojiAvatarRequest);
- } else {
- saveThreadAvatar(newEmojiAvatarRequest, threadID);
- }
- }, [pendingColor, pendingEmoji, saveThreadAvatar, saveUserAvatar, threadID]);
-
- const onPressReset = React.useCallback(() => {
- const resetEmojiAvatar = savedEmojiAvatarFunc();
-
- setPendingEmoji(resetEmojiAvatar.emoji);
- setPendingColor(resetEmojiAvatar.color);
- }, [savedEmojiAvatarFunc]);
-
- const onEmojiSelected = React.useCallback(emoji => {
- setPendingEmoji(emoji.emoji);
- }, []);
-
- const onEmojiKeyboardClose = React.useCallback(
- () => setEmojiKeyboardOpen(false),
- [],
- );
-
- const stagedAvatarInfo: ClientEmojiAvatar = React.useMemo(
- () => ({
- type: 'emoji',
- emoji: pendingEmoji,
- color: pendingColor,
- }),
- [pendingColor, pendingEmoji],
- );
-
- const loadingContainer = React.useMemo(() => {
- if (!saveUserAvatarCallLoading && !saveThreadAvatarCallLoading) {
- return null;
- }
-
- return (
- <View style={styles.loadingContainer}>
- <ActivityIndicator size="large" color="white" />
- </View>
- );
- }, [
- saveThreadAvatarCallLoading,
- saveUserAvatarCallLoading,
- styles.loadingContainer,
- ]);
return (
- <View style={styles.container}>
- <View style={styles.emojiAvatarCreationContainer}>
- <View style={styles.stagedAvatarSection}>
- <TouchableWithoutFeedback onPress={onPressEditEmoji}>
- <View>
- <View>
- <Avatar size="profile" avatarInfo={stagedAvatarInfo} />
- {loadingContainer}
- </View>
- <Text style={styles.editEmojiText}>Edit Emoji</Text>
- </View>
- </TouchableWithoutFeedback>
- </View>
- <View style={styles.colorRowsSection}>
- <ColorRows
- pendingColor={pendingColor}
- setPendingColor={setPendingColor}
- outerRingSelectedColorStyle={styles.selectedColorOuterRing}
- />
- </View>
- </View>
- <View style={styles.buttonsContainer}>
- <Button
- onPress={onPressSetAvatar}
- style={styles.saveButton}
- disabled={saveUserAvatarCallLoading || saveThreadAvatarCallLoading}
- >
- <Text style={styles.saveButtonText}>Save Avatar</Text>
- </Button>
- <Button
- onPress={onPressReset}
- style={styles.resetButton}
- disabled={saveUserAvatarCallLoading || saveThreadAvatarCallLoading}
- >
- <Text style={styles.resetButtonText}>Reset</Text>
- </Button>
- </View>
- <EmojiPicker
- onEmojiSelected={onEmojiSelected}
- open={emojiKeyboardOpen}
- onClose={onEmojiKeyboardClose}
- />
- </View>
+ <EmojiAvatarCreation
+ saveAvatarCall={saveUserAvatar}
+ saveAvatarCallLoading={saveUserAvatarCallLoading}
+ savedEmojiAvatarSelector={savedEmojiAvatarSelectorForCurrentUser}
+ />
);
}
-const unboundStyles = {
- container: {
- flex: 1,
- justifyContent: 'space-between',
- },
- emojiAvatarCreationContainer: {
- paddingTop: 16,
- },
- stagedAvatarSection: {
- backgroundColor: 'panelForeground',
- paddingVertical: 24,
- alignItems: 'center',
- },
- editEmojiText: {
- color: 'purpleLink',
- marginTop: 16,
- fontWeight: '500',
- fontSize: 16,
- lineHeight: 24,
- textAlign: 'center',
- },
- colorRowsSection: {
- paddingVertical: 24,
- marginTop: 24,
- backgroundColor: 'panelForeground',
- alignItems: 'center',
- },
- selectedColorOuterRing: {
- backgroundColor: 'modalSubtext',
- },
- buttonsContainer: {
- paddingHorizontal: 16,
- paddingBottom: 8,
- },
- saveButton: {
- backgroundColor: 'purpleButton',
- paddingVertical: 12,
- borderRadius: 8,
- },
- saveButtonText: {
- color: 'whiteText',
- textAlign: 'center',
- fontWeight: '500',
- fontSize: 16,
- lineHeight: 24,
- },
- resetButton: {
- padding: 12,
- borderRadius: 8,
- marginTop: 8,
- alignSelf: 'center',
- },
- resetButtonText: {
- color: 'redText',
- textAlign: 'center',
- fontWeight: '500',
- fontSize: 16,
- lineHeight: 24,
- },
- loadingContainer: {
- position: 'absolute',
- backgroundColor: 'black',
- width: 112,
- height: 112,
- borderRadius: 56,
- opacity: 0.6,
- justifyContent: 'center',
- },
-};
-
export default EmojiUserAvatarCreation;
diff --git a/native/profile/profile-screen.react.js b/native/profile/profile-screen.react.js
--- a/native/profile/profile-screen.react.js
+++ b/native/profile/profile-screen.react.js
@@ -194,10 +194,7 @@
}
onPressEmojiAvatarFlow = () => {
- this.props.navigation.navigate<'EmojiUserAvatarCreation'>({
- name: EmojiUserAvatarCreationRouteName,
- params: {},
- });
+ this.props.navigation.navigate(EmojiUserAvatarCreationRouteName);
};
onPressLogOut = () => {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Dec 30, 11:52 PM (7 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5870867
Default Alt Text
D7504.1767138775.diff (21 KB)
Attached To
Mode
D7504: [native] factor out shared code between Emoji[User/Thread]AvatarCreation into EmojiAvatarCreation
Attached
Detach File
Event Timeline
Log In to Comment