New attachment storage system

This commit is contained in:
Fedor Indutny
2024-07-11 12:44:09 -07:00
committed by GitHub
parent 273e1ccb15
commit 28664a606f
161 changed files with 2418 additions and 1562 deletions
@@ -120,7 +120,7 @@ export function AboutContactModal({
<div className="AboutContactModal__row AboutContactModal__row--centered">
<Avatar
acceptedMessageRequest={conversation.acceptedMessageRequest}
avatarPath={conversation.avatarPath}
avatarUrl={conversation.avatarUrl}
blur={avatarBlur}
onClick={avatarBlur === AvatarBlur.NoBlur ? undefined : onAvatarClick}
badge={undefined}
@@ -132,7 +132,7 @@ export function AboutContactModal({
sharedGroupNames={[]}
size={AvatarSize.TWO_HUNDRED_SIXTEEN}
title={conversation.title}
unblurredAvatarPath={conversation.unblurredAvatarPath}
unblurredAvatarUrl={conversation.unblurredAvatarUrl}
/>
</div>
@@ -126,7 +126,7 @@ export function AttachmentList<T extends AttachmentType | AttachmentDraftType>({
if (isImage && canEditImages) {
return (
<div className="module-attachments--editable">
<div className="module-attachments--editable" key={key}>
{imgElement}
<div className="module-attachments__edit-icon" />
</div>
+3 -3
View File
@@ -314,7 +314,7 @@ export function ContactModal({
<div className="ContactModal">
<Avatar
acceptedMessageRequest={contact.acceptedMessageRequest}
avatarPath={contact.avatarPath}
avatarUrl={contact.avatarUrl}
badge={preferredBadge}
color={contact.color}
conversationType="direct"
@@ -338,7 +338,7 @@ export function ContactModal({
storyRing={hasStories}
theme={theme}
title={contact.title}
unblurredAvatarPath={contact.unblurredAvatarPath}
unblurredAvatarUrl={contact.unblurredAvatarUrl}
/>
<button
type="button"
@@ -472,7 +472,7 @@ export function ContactModal({
return (
<AvatarLightbox
avatarColor={contact.color}
avatarPath={contact.avatarPath}
avatarUrl={contact.avatarUrl}
conversationTitle={contact.title}
i18n={i18n}
onClose={() => setView(ContactModalView.Default)}
@@ -87,7 +87,7 @@ export function PrivateConvo(): JSX.Element {
conversation: getDefaultConversation({
color: getRandomColor(),
isVerified: true,
avatarPath: gifUrl,
avatarUrl: gifUrl,
title: 'Someone 🔥 Somewhere',
name: 'Someone 🔥 Somewhere',
phoneNumber: '(202) 555-0001',
@@ -443,7 +443,7 @@ function HeaderContent({
<span className="module-ConversationHeader__header__avatar">
<Avatar
acceptedMessageRequest={conversation.acceptedMessageRequest}
avatarPath={conversation.avatarPath ?? undefined}
avatarUrl={conversation.avatarUrl ?? undefined}
badge={badge ?? undefined}
color={conversation.color ?? undefined}
conversationType={conversation.type}
@@ -459,7 +459,7 @@ function HeaderContent({
storyRing={conversation.isMe ? undefined : hasStories ?? undefined}
theme={theme}
title={conversation.title}
unblurredAvatarPath={conversation.unblurredAvatarPath ?? undefined}
unblurredAvatarUrl={conversation.unblurredAvatarUrl ?? undefined}
/>
</span>
);
@@ -84,7 +84,7 @@ DirectNoGroupsJustPhoneNumber.args = {
export const DirectNoGroupsNoData = Template.bind({});
DirectNoGroupsNoData.args = {
avatarPath: undefined,
avatarUrl: undefined,
phoneNumber: '',
profileName: '',
title: casual.phone,
@@ -93,7 +93,7 @@ DirectNoGroupsNoData.args = {
export const DirectNoGroupsNoDataNotAccepted = Template.bind({});
DirectNoGroupsNoDataNotAccepted.args = {
acceptedMessageRequest: false,
avatarPath: undefined,
avatarUrl: undefined,
phoneNumber: '',
profileName: '',
title: '',
@@ -116,7 +116,7 @@ GroupManyMembers.args = {
export const GroupOneMember = Template.bind({});
GroupOneMember.args = {
avatarPath: undefined,
avatarUrl: undefined,
conversationType: 'group',
groupDescription: casual.sentence,
membersCount: 1,
@@ -125,7 +125,7 @@ GroupOneMember.args = {
export const GroupZeroMembers = Template.bind({});
GroupZeroMembers.args = {
avatarPath: undefined,
avatarUrl: undefined,
conversationType: 'group',
groupDescription: casual.sentence,
membersCount: 0,
@@ -31,7 +31,7 @@ export type Props = {
phoneNumber?: string;
sharedGroupNames?: ReadonlyArray<string>;
unblurAvatar: (conversationId: string) => void;
unblurredAvatarPath?: string;
unblurredAvatarUrl?: string;
updateSharedGroups: (conversationId: string) => unknown;
theme: ThemeType;
viewUserStories: ViewUserStoriesActionCreatorType;
@@ -136,7 +136,7 @@ export function ConversationHero({
i18n,
about,
acceptedMessageRequest,
avatarPath,
avatarUrl,
badge,
color,
conversationType,
@@ -152,7 +152,7 @@ export function ConversationHero({
theme,
title,
unblurAvatar,
unblurredAvatarPath,
unblurredAvatarUrl,
updateSharedGroups,
viewUserStories,
toggleAboutContactModal,
@@ -174,10 +174,10 @@ export function ConversationHero({
if (
shouldBlurAvatar({
acceptedMessageRequest,
avatarPath,
avatarUrl,
isMe,
sharedGroupNames,
unblurredAvatarPath,
unblurredAvatarUrl,
})
) {
avatarBlur = AvatarBlur.BlurPictureWithClickToView;
@@ -221,7 +221,7 @@ export function ConversationHero({
<div className="module-conversation-hero">
<Avatar
acceptedMessageRequest={acceptedMessageRequest}
avatarPath={avatarPath}
avatarUrl={avatarUrl}
badge={badge}
blur={avatarBlur}
className="module-conversation-hero__avatar"
+4 -4
View File
@@ -229,7 +229,7 @@ export type PropsData = {
author: Pick<
ConversationType,
| 'acceptedMessageRequest'
| 'avatarPath'
| 'avatarUrl'
| 'badges'
| 'color'
| 'id'
@@ -238,7 +238,7 @@ export type PropsData = {
| 'profileName'
| 'sharedGroupNames'
| 'title'
| 'unblurredAvatarPath'
| 'unblurredAvatarUrl'
>;
conversationType: ConversationTypeType;
attachments?: ReadonlyArray<AttachmentType>;
@@ -1814,7 +1814,7 @@ export class Message extends React.PureComponent<Props, State> {
) : (
<Avatar
acceptedMessageRequest={author.acceptedMessageRequest}
avatarPath={author.avatarPath}
avatarUrl={author.avatarUrl}
badge={getPreferredBadge(author.badges)}
color={author.color}
conversationType="direct"
@@ -1832,7 +1832,7 @@ export class Message extends React.PureComponent<Props, State> {
size={GROUP_AVATAR_SIZE}
theme={theme}
title={author.title}
unblurredAvatarPath={author.unblurredAvatarPath}
unblurredAvatarUrl={author.unblurredAvatarUrl}
/>
)}
</div>
+6 -6
View File
@@ -37,7 +37,7 @@ import {
export type Contact = Pick<
ConversationType,
| 'acceptedMessageRequest'
| 'avatarPath'
| 'avatarUrl'
| 'badges'
| 'color'
| 'id'
@@ -46,7 +46,7 @@ export type Contact = Pick<
| 'profileName'
| 'sharedGroupNames'
| 'title'
| 'unblurredAvatarPath'
| 'unblurredAvatarUrl'
> & {
status?: SendStatus;
statusTimestamp?: number;
@@ -154,7 +154,7 @@ export function MessageDetail({
function renderAvatar(contact: Contact): JSX.Element {
const {
acceptedMessageRequest,
avatarPath,
avatarUrl,
badges,
color,
isMe,
@@ -162,13 +162,13 @@ export function MessageDetail({
profileName,
sharedGroupNames,
title,
unblurredAvatarPath,
unblurredAvatarUrl,
} = contact;
return (
<Avatar
acceptedMessageRequest={acceptedMessageRequest}
avatarPath={avatarPath}
avatarUrl={avatarUrl}
badge={getPreferredBadge(badges)}
color={color}
conversationType="direct"
@@ -180,7 +180,7 @@ export function MessageDetail({
title={title}
sharedGroupNames={sharedGroupNames}
size={AvatarSize.THIRTY_TWO}
unblurredAvatarPath={unblurredAvatarPath}
unblurredAvatarUrl={unblurredAvatarUrl}
/>
);
}
+1 -3
View File
@@ -614,9 +614,7 @@ function ThumbnailImage({
return (
<div
className={className}
style={
loadedSrc ? { backgroundImage: `url('${encodeURI(loadedSrc)}')` } : {}
}
style={loadedSrc ? { backgroundImage: `url('${loadedSrc}')` } : {}}
>
{children}
</div>
@@ -22,7 +22,7 @@ export type Reaction = {
from: Pick<
ConversationType,
| 'acceptedMessageRequest'
| 'avatarPath'
| 'avatarUrl'
| 'badges'
| 'color'
| 'id'
@@ -226,7 +226,7 @@ export const ReactionViewer = React.forwardRef<HTMLDivElement, Props>(
<div className="module-reaction-viewer__body__row__avatar">
<Avatar
acceptedMessageRequest={from.acceptedMessageRequest}
avatarPath={from.avatarPath}
avatarUrl={from.avatarUrl}
badge={getPreferredBadge(from.badges)}
conversationType="direct"
sharedGroupNames={from.sharedGroupNames}
@@ -399,7 +399,7 @@ const renderHeroRow = () => {
<ConversationHero
about={getAbout()}
acceptedMessageRequest
avatarPath={getAvatarPath()}
avatarUrl={getAvatarPath()}
badge={undefined}
conversationType="direct"
id={getDefaultConversation().id}
@@ -721,7 +721,7 @@ ReactionsShortMessage.args = {
export const AvatarInGroup = Template.bind({});
AvatarInGroup.args = {
author: getDefaultConversation({ avatarPath: pngUrl }),
author: getDefaultConversation({ avatarUrl: pngUrl }),
conversationType: 'group',
status: 'sent',
text: 'Hello it is me, the saxophone.',
@@ -27,7 +27,7 @@ const CONTACTS = times(10, index => {
return getDefaultConversation({
id: `contact-${index}`,
acceptedMessageRequest: false,
avatarPath: '',
avatarUrl: '',
badges: [],
color: AvatarColors[index],
name: `${letter} ${letter}`,
+2 -2
View File
@@ -19,7 +19,7 @@ const MAX_AVATARS_COUNT = 3;
type TypingContactType = Pick<
ConversationType,
| 'acceptedMessageRequest'
| 'avatarPath'
| 'avatarUrl'
| 'badges'
| 'color'
| 'id'
@@ -120,7 +120,7 @@ function TypingBubbleAvatar({
<animated.div className="module-message__typing-avatar" style={springProps}>
<Avatar
acceptedMessageRequest={contact.acceptedMessageRequest}
avatarPath={contact.avatarPath}
avatarUrl={contact.avatarUrl}
badge={getPreferredBadge(contact.badges)}
color={contact.color}
conversationType="direct"
+2 -2
View File
@@ -25,7 +25,7 @@ export function renderAvatar({
}): JSX.Element {
const { avatar } = contact;
const avatarPath = avatar && avatar.avatar && avatar.avatar.path;
const avatarUrl = avatar && avatar.avatar && avatar.avatar.path;
const pending = avatar && avatar.avatar && avatar.avatar.pending;
const title = getName(contact) || '';
const spinnerSvgSize = size < 50 ? 'small' : 'normal';
@@ -46,7 +46,7 @@ export function renderAvatar({
return (
<Avatar
acceptedMessageRequest={false}
avatarPath={avatarPath}
avatarUrl={avatarUrl}
badge={undefined}
blur={AvatarBlur.NoBlur}
color={AvatarColors[0]}
@@ -412,7 +412,7 @@ export function ChooseGroupMembersModal({
<ContactPill
key={contact.id}
acceptedMessageRequest={contact.acceptedMessageRequest}
avatarPath={contact.avatarPath}
avatarUrl={contact.avatarUrl}
color={contact.color}
firstName={contact.systemGivenName ?? contact.firstName}
i18n={i18n}
@@ -245,7 +245,7 @@ export function ConversationDetails({
modalNode = (
<EditConversationAttributesModal
avatarColor={conversation.color}
avatarPath={conversation.avatarPath}
avatarUrl={conversation.avatarUrl}
conversationId={conversation.id}
groupDescription={conversation.groupDescription}
i18n={i18n}
@@ -107,7 +107,7 @@ export function ConversationDetailsHeader({
modal = (
<AvatarLightbox
avatarColor={conversation.color}
avatarPath={conversation.avatarPath}
avatarUrl={conversation.avatarUrl}
conversationTitle={conversation.title}
i18n={i18n}
isGroup={isGroup}
@@ -20,7 +20,7 @@ export default {
type PropsType = ComponentProps<typeof EditConversationAttributesModal>;
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
avatarPath: undefined,
avatarUrl: undefined,
conversationId: '123',
i18n,
initiallyFocusDescription: false,
@@ -43,7 +43,7 @@ export function AvatarAndTitle(): JSX.Element {
return (
<EditConversationAttributesModal
{...createProps({
avatarPath: '/fixtures/kitten-3-64-64.jpg',
avatarUrl: '/fixtures/kitten-3-64-64.jpg',
})}
/>
);
@@ -23,7 +23,7 @@ import type { AvatarColorType } from '../../../types/Colors';
type PropsType = {
avatarColor?: AvatarColorType;
avatarPath?: string;
avatarUrl?: string;
conversationId: string;
groupDescription?: string;
i18n: LocalizerType;
@@ -46,7 +46,7 @@ type PropsType = {
export function EditConversationAttributesModal({
avatarColor,
avatarPath: externalAvatarPath,
avatarUrl: externalAvatarUrl,
conversationId,
groupDescription: externalGroupDescription = '',
i18n,
@@ -66,7 +66,7 @@ export function EditConversationAttributesModal({
const focusDescription = focusDescriptionRef.current;
const startingTitleRef = useRef<string>(externalTitle);
const startingAvatarPathRef = useRef<undefined | string>(externalAvatarPath);
const startingAvatarUrlRef = useRef<undefined | string>(externalAvatarUrl);
const [editingAvatar, setEditingAvatar] = useState(false);
const [avatar, setAvatar] = useState<undefined | Uint8Array>();
@@ -87,7 +87,7 @@ export function EditConversationAttributesModal({
};
const hasChangedExternally =
startingAvatarPathRef.current !== externalAvatarPath ||
startingAvatarUrlRef.current !== externalAvatarUrl ||
startingTitleRef.current !== externalTitle;
const hasTitleChanged = trimmedTitle !== externalTitle.trim();
const hasGroupDescriptionChanged =
@@ -123,16 +123,14 @@ export function EditConversationAttributesModal({
makeRequest(request);
};
const avatarPathForPreview = hasAvatarChanged
? undefined
: externalAvatarPath;
const avatarUrlForPreview = hasAvatarChanged ? undefined : externalAvatarUrl;
let content: JSX.Element;
if (editingAvatar) {
content = (
<AvatarEditor
avatarColor={avatarColor}
avatarPath={avatarPathForPreview}
avatarUrl={avatarUrlForPreview}
avatarValue={avatar}
conversationId={conversationId}
deleteAvatarFromDisk={deleteAvatarFromDisk}
@@ -161,7 +159,7 @@ export function EditConversationAttributesModal({
>
<AvatarPreview
avatarColor={avatarColor}
avatarPath={avatarPathForPreview}
avatarUrl={avatarUrlForPreview}
avatarValue={avatar}
i18n={i18n}
isEditable