Save users' avatars

This commit is contained in:
Jaiwanth 2021-05-31 22:27:29 +05:30
parent fa073cd958
commit 28a1a551fe
4 changed files with 35 additions and 7 deletions

View file

@ -36,6 +36,7 @@ interface IProps extends Omit<React.ComponentProps<typeof BaseAvatar>, "name" |
// Whether the onClick of the avatar should be overriden to dispatch `Action.ViewUser` // Whether the onClick of the avatar should be overriden to dispatch `Action.ViewUser`
viewUserOnClick?: boolean; viewUserOnClick?: boolean;
title?: string; title?: string;
avatarSrc?: string;
} }
interface IState { interface IState {
@ -66,7 +67,8 @@ export default class MemberAvatar extends React.Component<IProps, IState> {
private static getState(props: IProps): IState { private static getState(props: IProps): IState {
if (props.member?.name) { if (props.member?.name) {
let imageUrl = null; let imageUrl = null;
if (props.member.getMxcAvatarUrl()) { if (props.avatarSrc) imageUrl = props.avatarSrc;
else if (props.member.getMxcAvatarUrl()) {
imageUrl = mediaFromMxc(props.member.getMxcAvatarUrl()).getThumbnailOfSourceHttp( imageUrl = mediaFromMxc(props.member.getMxcAvatarUrl()).getThumbnailOfSourceHttp(
props.width, props.width,
props.height, props.height,

View file

@ -407,7 +407,7 @@ export default class MImageBody extends React.Component {
<div className="mx_MImageBody_thumbnail_container" style={{ maxHeight: maxHeight + "px" }} > <div className="mx_MImageBody_thumbnail_container" style={{ maxHeight: maxHeight + "px" }} >
{ /* Calculate aspect ratio, using %padding will size _container correctly */ } { /* Calculate aspect ratio, using %padding will size _container correctly */ }
<div style={{ paddingBottom: (100 * infoHeight / infoWidth) + '%' }} /> <div style={{ paddingBottom: (100 * infoHeight / infoWidth) + '%' }} />
{ showPlaceholder && { !this.props.mediaSrc && showPlaceholder &&
<div className="mx_MImageBody_thumbnail" style={{ <div className="mx_MImageBody_thumbnail" style={{
// Constrain width here so that spinner appears central to the loaded thumbnail // Constrain width here so that spinner appears central to the loaded thumbnail
maxWidth: infoWidth + "px", maxWidth: infoWidth + "px",
@ -418,7 +418,7 @@ export default class MImageBody extends React.Component {
</div> </div>
} }
<div style={{display: !showPlaceholder ? undefined : 'none'}}> <div style={{display: this.props.mediaSrc ? "block" : !showPlaceholder ? undefined : 'none'}}>
{ img } { img }
{ gifLabel } { gifLabel }
</div> </div>

View file

@ -254,6 +254,9 @@ interface IProps {
// Used while exporting to refer to the local source rather than the online one // Used while exporting to refer to the local source rather than the online one
mediaSrc?: string; mediaSrc?: string;
// Used while exporting to refer to the local avatar rather than the online one
avatarSrc?: string;
// show twelve hour timestamps // show twelve hour timestamps
isTwelveHour?: boolean; isTwelveHour?: boolean;
@ -939,8 +942,11 @@ export default class EventTile extends React.Component<IProps, IState> {
} }
avatar = ( avatar = (
<div className="mx_EventTile_avatar"> <div className="mx_EventTile_avatar">
<MemberAvatar member={member} <MemberAvatar
width={avatarSize} height={avatarSize} avatarSrc = {this.props.avatarSrc}
member={member}
width={avatarSize}
height={avatarSize}
viewUserOnClick={true} viewUserOnClick={true}
/> />
</div> </div>

View file

@ -2,7 +2,7 @@ import React from "react"
import streamSaver from "streamsaver"; import streamSaver from "streamsaver";
import JSZip from "jszip"; import JSZip from "jszip";
import { decryptFile } from "../DecryptFile"; import { decryptFile } from "../DecryptFile";
import { mediaFromContent } from "../../customisations/Media"; import { mediaFromContent, mediaFromMxc } from "../../customisations/Media";
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { Exporter } from "./Exporter"; import { Exporter } from "./Exporter";
@ -133,7 +133,23 @@ export default class HTMLExporter extends Exporter {
</html>` </html>`
} }
// will be used in the future protected hasAvatar(event: MatrixEvent): boolean {
const member = event.sender;
if (member.getMxcAvatarUrl()) return true;
return false;
}
protected async saveAvatarIfNeeded(event: MatrixEvent) {
const member = event.sender;
const avatarUrl = mediaFromMxc(member.getMxcAvatarUrl()).getThumbnailOfSourceHttp(30, 30, "crop");
if (!this.avatars.has(member.userId)) {
this.avatars.set(member.userId, true);
const image = await fetch(avatarUrl);
const blob = await image.blob();
this.zip.file(`users/${member.userId}`, blob);
}
}
protected async getMediaBlob(event: MatrixEvent) { protected async getMediaBlob(event: MatrixEvent) {
let blob: Blob; let blob: Blob;
try { try {
@ -165,6 +181,9 @@ export default class HTMLExporter extends Exporter {
protected getEventTile(mxEv: MatrixEvent, continuation: boolean, mediaSrc?: string) { protected getEventTile(mxEv: MatrixEvent, continuation: boolean, mediaSrc?: string) {
const hasAvatar = this.hasAvatar(mxEv);
if (hasAvatar) this.saveAvatarIfNeeded(mxEv);
return <li id={mxEv.getId()}> return <li id={mxEv.getId()}>
<EventTile <EventTile
mxEvent={mxEv} mxEvent={mxEv}
@ -179,6 +198,7 @@ export default class HTMLExporter extends Exporter {
isTwelveHour={false} isTwelveHour={false}
last={false} last={false}
mediaSrc={mediaSrc} mediaSrc={mediaSrc}
avatarSrc={hasAvatar ? `users/${mxEv.sender.userId}` : null}
lastInSection={false} lastInSection={false}
permalinkCreator={this.permalinkCreator} permalinkCreator={this.permalinkCreator}
lastSuccessful={false} lastSuccessful={false}