Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Fix: Avatar preview does not update when same file is selected repeatedly #8288

Merged
merged 4 commits into from
Apr 12, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/components/views/elements/MiniAvatarUploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { useTimeout } from "../../../hooks/useTimeout";
import Analytics from "../../../Analytics";
import { TranslatedString } from '../../../languageHandler';
import RoomContext from "../../../contexts/RoomContext";
import { fileOnChangeHandler } from "../../../utils/BrowserWorkarounds";

export const AVATAR_SIZE = 52;

Expand Down Expand Up @@ -62,15 +63,15 @@ const MiniAvatarUploader: React.FC<IProps> = ({ hasAvatar, hasAvatarLabel, noAva
type="file"
ref={uploadRef}
className="mx_MiniAvatarUploader_input"
onChange={async (ev) => {
onChange={fileOnChangeHandler(async (ev) => {
if (!ev.target.files?.length) return;
setBusy(true);
Analytics.trackEvent("mini_avatar", "upload");
const file = ev.target.files[0];
const uri = await cli.uploadContent(file);
await setAvatarUrl(uri);
setBusy(false);
}}
})}
accept="image/*"
/>

Expand Down
5 changes: 3 additions & 2 deletions src/components/views/room_settings/RoomProfileSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Field from "../elements/Field";
import { mediaFromMxc } from "../../../customisations/Media";
import AccessibleButton from "../elements/AccessibleButton";
import AvatarSetting from "../settings/AvatarSetting";
import { fileOnChangeHandler } from "../../../utils/BrowserWorkarounds";

interface IProps {
roomId: string;
Expand Down Expand Up @@ -186,7 +187,7 @@ export default class RoomProfileSettings extends React.Component<IProps, IState>
}
};

private onAvatarChanged = (e: React.ChangeEvent<HTMLInputElement>): void => {
private onAvatarChanged = fileOnChangeHandler((e: React.ChangeEvent<HTMLInputElement>): void => {
if (!e.target.files || !e.target.files.length) {
this.setState({
avatarUrl: this.state.originalAvatarUrl,
Expand All @@ -212,7 +213,7 @@ export default class RoomProfileSettings extends React.Component<IProps, IState>
});
};
reader.readAsDataURL(file);
};
});

public render(): JSX.Element {
let profileSettingsButtons;
Expand Down
5 changes: 3 additions & 2 deletions src/components/views/settings/ChangeAvatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import Spinner from '../elements/Spinner';
import { mediaFromMxc } from "../../../customisations/Media";
import RoomAvatar from '../avatars/RoomAvatar';
import BaseAvatar from '../avatars/BaseAvatar';
import { fileOnChangeHandler } from "../../../utils/BrowserWorkarounds";

interface IProps {
initialAvatarUrl?: string;
Expand Down Expand Up @@ -143,10 +144,10 @@ export default class ChangeAvatar extends React.Component<IProps, IState> {
return httpPromise;
}

private onFileSelected = (ev: React.ChangeEvent<HTMLInputElement>) => {
private onFileSelected = fileOnChangeHandler((ev: React.ChangeEvent<HTMLInputElement>) => {
this.avatarSet = true;
return this.setAvatarFromFile(ev.target.files[0]);
};
});

private onError = (): void => {
this.setState({
Expand Down
5 changes: 3 additions & 2 deletions src/components/views/settings/ProfileSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import AccessibleButton from '../elements/AccessibleButton';
import AvatarSetting from './AvatarSetting';
import ExternalLink from '../elements/ExternalLink';
import UserIdentifierCustomisations from '../../../customisations/UserIdentifier';
import { fileOnChangeHandler } from "../../../utils/BrowserWorkarounds";

interface IState {
userId?: string;
Expand Down Expand Up @@ -135,7 +136,7 @@ export default class ProfileSettings extends React.Component<{}, IState> {
});
};

private onAvatarChanged = (e: React.ChangeEvent<HTMLInputElement>): void => {
private onAvatarChanged = fileOnChangeHandler((e: React.ChangeEvent<HTMLInputElement>): void => {
if (!e.target.files || !e.target.files.length) {
this.setState({
avatarUrl: this.state.originalAvatarUrl,
Expand All @@ -155,7 +156,7 @@ export default class ProfileSettings extends React.Component<{}, IState> {
});
};
reader.readAsDataURL(file);
};
});

public render(): JSX.Element {
const hostingSignupLink = getHostingLink('user-settings');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { RoomNotifState } from '../../../../../RoomNotifs';
import defaultDispatcher from "../../../../../dispatcher/dispatcher";
import { Action } from "../../../../../dispatcher/actions";
import { UserTab } from "../../../dialogs/UserTab";
import { fileOnChangeHandler } from "../../../../../utils/BrowserWorkarounds";

interface IProps {
roomId: string;
Expand Down Expand Up @@ -77,7 +78,7 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
this.soundUpload.current.click();
};

private onSoundUploadChanged = (e: React.ChangeEvent<HTMLInputElement>): Promise<void> => {
private onSoundUploadChanged = fileOnChangeHandler((e: React.ChangeEvent<HTMLInputElement>): void => {
if (!e.target.files || !e.target.files.length) {
this.setState({
uploadedFile: null,
Expand All @@ -89,7 +90,7 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
this.setState({
uploadedFile: file,
});
};
});

private onClickSaveSound = async (e: React.MouseEvent): Promise<void> => {
e.stopPropagation();
Expand Down
5 changes: 3 additions & 2 deletions src/components/views/spaces/SpaceBasicSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import React, { useRef, useState } from "react";
import { _t } from "../../../languageHandler";
import AccessibleButton from "../elements/AccessibleButton";
import Field from "../elements/Field";
import { fileOnChangeHandler } from "../../../utils/BrowserWorkarounds";

interface IProps {
avatarUrl?: string;
Expand Down Expand Up @@ -89,7 +90,7 @@ export const SpaceAvatar = ({
<input
type="file"
ref={avatarUploadRef}
onChange={(e) => {
onChange={fileOnChangeHandler((e) => {
if (!e.target.files?.length) return;
const file = e.target.files[0];
setAvatar(file);
Expand All @@ -98,7 +99,7 @@ export const SpaceAvatar = ({
setAvatarDataUrl(ev.target.result as string);
};
reader.readAsDataURL(file);
}}
})}
accept="image/*"
/>
</div>;
Expand Down
14 changes: 14 additions & 0 deletions src/utils/BrowserWorkarounds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ChangeEvent } from "react";
justjanne marked this conversation as resolved.
Show resolved Hide resolved

type OnChangeHandler<T> = (event: ChangeEvent<HTMLInputElement>) => T;

export function fileOnChangeHandler<T>(handler: OnChangeHandler<T>): OnChangeHandler<T> {
return (event) => {
const result = handler(event);
// Workaround for Chromium Bug
// Chrome does not fire onChange events if the same file is selected twice
// Only required on Chromium-based browsers (Electron, Chrome, Edge, Opera, Vivaldi, etc)
event.target.value = '';
justjanne marked this conversation as resolved.
Show resolved Hide resolved
return result;
};
}