Convert cases of mxcUrlToHttp to new media customisation
This commit is contained in:
parent
53935782bc
commit
1ac12479ca
33 changed files with 178 additions and 121 deletions
|
@ -36,6 +36,7 @@ import {MatrixClientPeg} from './MatrixClientPeg';
|
|||
import {tryTransformPermalinkToLocalHref} from "./utils/permalinks/Permalinks";
|
||||
import {SHORTCODE_TO_EMOJI, getEmojiFromUnicode} from "./emoji";
|
||||
import ReplyThread from "./components/views/elements/ReplyThread";
|
||||
import {mediaFromMxc} from "./customisations/Media";
|
||||
|
||||
linkifyMatrix(linkify);
|
||||
|
||||
|
@ -181,11 +182,9 @@ const transformTags: IExtendedSanitizeOptions["transformTags"] = { // custom to
|
|||
if (!attribs.src || !attribs.src.startsWith('mxc://') || !SettingsStore.getValue("showImages")) {
|
||||
return { tagName, attribs: {}};
|
||||
}
|
||||
attribs.src = MatrixClientPeg.get().mxcUrlToHttp(
|
||||
attribs.src,
|
||||
attribs.width || 800,
|
||||
attribs.height || 600,
|
||||
);
|
||||
const width = Number(attribs.width) || 800;
|
||||
const height = Number(attribs.height) || 600;
|
||||
attribs.src = mediaFromMxc(attribs.src).getThumbnailOfSourceHttp(width, height);
|
||||
return { tagName, attribs };
|
||||
},
|
||||
'code': function(tagName: string, attribs: sanitizeHtml.Attributes) {
|
||||
|
|
|
@ -36,6 +36,7 @@ import {SettingLevel} from "./settings/SettingLevel";
|
|||
import {isPushNotifyDisabled} from "./settings/controllers/NotificationControllers";
|
||||
import RoomViewStore from "./stores/RoomViewStore";
|
||||
import UserActivity from "./UserActivity";
|
||||
import {mediaFromMxc} from "./customisations/Media";
|
||||
|
||||
/*
|
||||
* Dispatches:
|
||||
|
@ -150,7 +151,7 @@ export const Notifier = {
|
|||
// Ideally in here we could use MSC1310 to detect the type of file, and reject it.
|
||||
|
||||
return {
|
||||
url: MatrixClientPeg.get().mxcUrlToHttp(content.url),
|
||||
url: mediaFromMxc(content.url).srcHttp,
|
||||
name: content.name,
|
||||
type: content.type,
|
||||
size: content.size,
|
||||
|
|
|
@ -27,6 +27,7 @@ import {sortBy} from "lodash";
|
|||
import {makeGroupPermalink} from "../utils/permalinks/Permalinks";
|
||||
import {ICompletion, ISelectionRange} from "./Autocompleter";
|
||||
import FlairStore from "../stores/FlairStore";
|
||||
import {mediaFromMxc} from "../customisations/Media";
|
||||
|
||||
const COMMUNITY_REGEX = /\B\+\S*/g;
|
||||
|
||||
|
@ -95,7 +96,7 @@ export default class CommunityProvider extends AutocompleteProvider {
|
|||
name={name || groupId}
|
||||
width={24}
|
||||
height={24}
|
||||
url={avatarUrl ? cli.mxcUrlToHttp(avatarUrl, 24, 24) : null} />
|
||||
url={avatarUrl ? mediaFromMxc(avatarUrl).getSquareThumbnailHttp(24) : null} />
|
||||
</PillCompletion>
|
||||
),
|
||||
range,
|
||||
|
|
|
@ -39,6 +39,7 @@ import {Group} from "matrix-js-sdk";
|
|||
import {allSettled, sleep} from "../../utils/promise";
|
||||
import RightPanelStore from "../../stores/RightPanelStore";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
import {mediaFromMxc} from "../../customisations/Media";
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
|
||||
const LONG_DESC_PLACEHOLDER = _td(
|
||||
|
@ -368,8 +369,7 @@ class FeaturedUser extends React.Component {
|
|||
|
||||
const permalink = makeUserPermalink(this.props.summaryInfo.user_id);
|
||||
const userNameNode = <a href={permalink} onClick={this.onClick}>{ name }</a>;
|
||||
const httpUrl = MatrixClientPeg.get()
|
||||
.mxcUrlToHttp(this.props.summaryInfo.avatar_url, 64, 64);
|
||||
const httpUrl = mediaFromMxc(this.props.summaryInfo.avatar_url).getSquareThumbnailHttp(64);
|
||||
|
||||
const deleteButton = this.props.editing ?
|
||||
<img
|
||||
|
@ -981,10 +981,9 @@ export default class GroupView extends React.Component {
|
|||
<Spinner />
|
||||
</div>;
|
||||
}
|
||||
const httpInviterAvatar = this.state.inviterProfile ?
|
||||
this._matrixClient.mxcUrlToHttp(
|
||||
this.state.inviterProfile.avatarUrl, 36, 36,
|
||||
) : null;
|
||||
const httpInviterAvatar = this.state.inviterProfile
|
||||
? mediaFromMxc(this.state.inviterProfile.avatarUrl).getSquareThumbnailHttp(36)
|
||||
: null;
|
||||
|
||||
const inviter = group.inviter || {};
|
||||
let inviterName = inviter.userId;
|
||||
|
|
|
@ -41,6 +41,7 @@ import RoomListNumResults from "../views/rooms/RoomListNumResults";
|
|||
import LeftPanelWidget from "./LeftPanelWidget";
|
||||
import SpacePanel from "../views/spaces/SpacePanel";
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../customisations/Media";
|
||||
|
||||
interface IProps {
|
||||
isMinimized: boolean;
|
||||
|
@ -121,7 +122,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
|||
let avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize);
|
||||
const settingBgMxc = SettingsStore.getValue("RoomList.backgroundImage");
|
||||
if (settingBgMxc) {
|
||||
avatarUrl = MatrixClientPeg.get().mxcUrlToHttp(settingBgMxc, avatarSize, avatarSize);
|
||||
avatarUrl = mediaFromMxc(settingBgMxc).getSquareThumbnailHttp(avatarSize);
|
||||
}
|
||||
|
||||
const avatarUrlProp = `url(${avatarUrl})`;
|
||||
|
|
|
@ -34,6 +34,7 @@ import {EnhancedMap} from "../../utils/maps";
|
|||
import StyledCheckbox from "../views/elements/StyledCheckbox";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
import BaseAvatar from "../views/avatars/BaseAvatar";
|
||||
import {mediaFromMxc} from "../../customisations/Media";
|
||||
|
||||
interface IProps {
|
||||
space: Room;
|
||||
|
@ -158,12 +159,7 @@ const SubSpace: React.FC<ISubspaceProps> = ({
|
|||
|
||||
let url: string;
|
||||
if (space.avatar_url) {
|
||||
url = MatrixClientPeg.get().mxcUrlToHttp(
|
||||
space.avatar_url,
|
||||
Math.floor(24 * window.devicePixelRatio),
|
||||
Math.floor(24 * window.devicePixelRatio),
|
||||
"crop",
|
||||
);
|
||||
url = mediaFromMxc(space.avatar_url).getSquareThumbnailHttp(Math.floor(24 * window.devicePixelRatio));
|
||||
}
|
||||
|
||||
return <div className="mx_SpaceRoomDirectory_subspace">
|
||||
|
@ -265,12 +261,7 @@ const RoomTile = ({ room, event, editing, queueAction, onPreviewClick, onJoinCli
|
|||
|
||||
let url: string;
|
||||
if (room.avatar_url) {
|
||||
url = cli.mxcUrlToHttp(
|
||||
room.avatar_url,
|
||||
Math.floor(32 * window.devicePixelRatio),
|
||||
Math.floor(32 * window.devicePixelRatio),
|
||||
"crop",
|
||||
);
|
||||
url = mediaFromMxc(room.avatar_url).getSquareThumbnailHttp(Math.floor(32 * window.devicePixelRatio));
|
||||
}
|
||||
|
||||
const content = <React.Fragment>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2017, 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -18,6 +18,8 @@ import React from 'react';
|
|||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import BaseAvatar from './BaseAvatar';
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
import {ResizeMode} from "../../../customisations/models/ResizeMode";
|
||||
|
||||
export interface IProps {
|
||||
groupId?: string;
|
||||
|
@ -25,7 +27,7 @@ export interface IProps {
|
|||
groupAvatarUrl?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
resizeMethod?: string;
|
||||
resizeMethod?: ResizeMode;
|
||||
onClick?: React.MouseEventHandler;
|
||||
}
|
||||
|
||||
|
@ -38,8 +40,7 @@ export default class GroupAvatar extends React.Component<IProps> {
|
|||
};
|
||||
|
||||
getGroupAvatarUrl() {
|
||||
return MatrixClientPeg.get().mxcUrlToHttp(
|
||||
this.props.groupAvatarUrl,
|
||||
return mediaFromMxc(this.props.groupAvatarUrl).getThumbnailOfSourceHttp(
|
||||
this.props.width,
|
||||
this.props.height,
|
||||
this.props.resizeMethod,
|
||||
|
|
|
@ -21,6 +21,7 @@ import * as sdk from '../../../index';
|
|||
import { _t } from '../../../languageHandler';
|
||||
import { GroupMemberType } from '../../../groups';
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
/*
|
||||
* A dialog for confirming an operation on another user.
|
||||
|
@ -108,8 +109,9 @@ export default class ConfirmUserActionDialog extends React.Component {
|
|||
name = this.props.member.name;
|
||||
userId = this.props.member.userId;
|
||||
} else {
|
||||
const httpAvatarUrl = this.props.groupMember.avatarUrl ?
|
||||
this.props.matrixClient.mxcUrlToHttp(this.props.groupMember.avatarUrl, 48, 48) : null;
|
||||
const httpAvatarUrl = this.props.groupMember.avatarUrl
|
||||
? mediaFromMxc(this.props.groupMember.avatarUrl).getSquareThumbnailHttp(48)
|
||||
: null;
|
||||
name = this.props.groupMember.displayname || this.props.groupMember.userId;
|
||||
userId = this.props.groupMember.userId;
|
||||
avatar = <BaseAvatar name={name} url={httpAvatarUrl} width={48} height={48} />;
|
||||
|
|
|
@ -24,6 +24,7 @@ import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
|||
import { CommunityPrototypeStore } from "../../../stores/CommunityPrototypeStore";
|
||||
import FlairStore from "../../../stores/FlairStore";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
interface IProps extends IDialogProps {
|
||||
communityId: string;
|
||||
|
@ -118,7 +119,7 @@ export default class EditCommunityPrototypeDialog extends React.PureComponent<IP
|
|||
let preview = <img src={this.state.avatarPreview} className="mx_EditCommunityPrototypeDialog_avatar" />;
|
||||
if (!this.state.avatarPreview) {
|
||||
if (this.state.currentAvatarUrl) {
|
||||
const url = MatrixClientPeg.get().mxcUrlToHttp(this.state.currentAvatarUrl);
|
||||
const url = mediaFromMxc(this.state.currentAvatarUrl).srcHttp;
|
||||
preview = <img src={url} className="mx_EditCommunityPrototypeDialog_avatar" />;
|
||||
} else {
|
||||
preview = <div className="mx_EditCommunityPrototypeDialog_placeholderAvatar" />
|
||||
|
|
|
@ -20,6 +20,7 @@ import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
|||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
const PHASE_START = 0;
|
||||
const PHASE_SHOW_SAS = 1;
|
||||
|
@ -123,22 +124,21 @@ export default class IncomingSasDialog extends React.Component {
|
|||
const Spinner = sdk.getComponent("views.elements.Spinner");
|
||||
const BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
|
||||
const isSelf = this.props.verifier.userId == MatrixClientPeg.get().getUserId();
|
||||
const isSelf = this.props.verifier.userId === MatrixClientPeg.get().getUserId();
|
||||
|
||||
let profile;
|
||||
if (this.state.opponentProfile) {
|
||||
const oppProfile = this.state.opponentProfile;
|
||||
if (oppProfile) {
|
||||
const url = oppProfile.avatar_url
|
||||
? mediaFromMxc(oppProfile.avatar_url).getSquareThumbnailHttp(Math.floor(48 * window.devicePixelRatio))
|
||||
: null;
|
||||
profile = <div className="mx_IncomingSasDialog_opponentProfile">
|
||||
<BaseAvatar name={this.state.opponentProfile.displayname}
|
||||
<BaseAvatar name={oppProfile.displayname}
|
||||
idName={this.props.verifier.userId}
|
||||
url={MatrixClientPeg.get().mxcUrlToHttp(
|
||||
this.state.opponentProfile.avatar_url,
|
||||
Math.floor(48 * window.devicePixelRatio),
|
||||
Math.floor(48 * window.devicePixelRatio),
|
||||
'crop',
|
||||
)}
|
||||
url={url}
|
||||
width={48} height={48} resizeMethod='crop'
|
||||
/>
|
||||
<h2>{this.state.opponentProfile.displayname}</h2>
|
||||
<h2>{oppProfile.displayname}</h2>
|
||||
</div>;
|
||||
} else if (this.state.opponentProfileError) {
|
||||
profile = <div>
|
||||
|
|
|
@ -23,6 +23,7 @@ import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
|||
import { _t } from '../../../languageHandler';
|
||||
import { UserAddressType } from '../../../UserAddress.js';
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
@replaceableComponent("views.elements.AddressTile")
|
||||
export default class AddressTile extends React.Component {
|
||||
|
@ -47,9 +48,7 @@ export default class AddressTile extends React.Component {
|
|||
const isMatrixAddress = ['mx-user-id', 'mx-room-id'].includes(address.addressType);
|
||||
|
||||
if (isMatrixAddress && address.avatarMxc) {
|
||||
imgUrls.push(MatrixClientPeg.get().mxcUrlToHttp(
|
||||
address.avatarMxc, 25, 25, 'crop',
|
||||
));
|
||||
imgUrls.push(mediaFromMxc(address.avatarMxc).getSquareThumbnailHttp(25));
|
||||
} else if (address.addressType === 'email') {
|
||||
imgUrls.push(require("../../../../res/img/icon-email-user.svg"));
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import FlairStore from '../../../stores/FlairStore';
|
|||
import dis from '../../../dispatcher/dispatcher';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
|
||||
class FlairAvatar extends React.Component {
|
||||
|
@ -39,8 +40,7 @@ class FlairAvatar extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const httpUrl = this.context.mxcUrlToHttp(
|
||||
this.props.groupProfile.avatarUrl, 16, 16, 'scale', false);
|
||||
const httpUrl = mediaFromMxc(this.props.groupProfile.avatarUrl).getSquareThumbnailHttp(16);
|
||||
const tooltip = this.props.groupProfile.name ?
|
||||
`${this.props.groupProfile.name} (${this.props.groupProfile.groupId})`:
|
||||
this.props.groupProfile.groupId;
|
||||
|
|
|
@ -26,6 +26,7 @@ import FlairStore from "../../../stores/FlairStore";
|
|||
import {getPrimaryPermalinkEntity, parseAppLocalLink} from "../../../utils/permalinks/Permalinks";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
import Tooltip from './Tooltip';
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
|
||||
|
@ -259,7 +260,7 @@ class Pill extends React.Component {
|
|||
linkText = groupId;
|
||||
if (this.props.shouldShowPillAvatar) {
|
||||
avatar = <BaseAvatar name={name || groupId} width={16} height={16} aria-hidden="true"
|
||||
url={avatarUrl ? cli.mxcUrlToHttp(avatarUrl, 16, 16) : null} />;
|
||||
url={avatarUrl ? mediaFromMxc(avatarUrl).getSquareThumbnailHttp(16) : null} />;
|
||||
}
|
||||
pillClass = 'mx_GroupPill';
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import AccessibleButton from "./AccessibleButton";
|
|||
import {_t} from "../../../languageHandler";
|
||||
import {IdentityProviderBrand, IIdentityProvider, ISSOFlow} from "../../../Login";
|
||||
import AccessibleTooltipButton from "./AccessibleTooltipButton";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
interface ISSOButtonProps extends Omit<IProps, "flow"> {
|
||||
idp: IIdentityProvider;
|
||||
|
@ -72,7 +73,7 @@ const SSOButton: React.FC<ISSOButtonProps> = ({
|
|||
brandClass = `mx_SSOButton_brand_${brandName}`;
|
||||
icon = <img src={brandIcon} height="24" width="24" alt={brandName} />;
|
||||
} else if (typeof idp?.icon === "string" && idp.icon.startsWith("mxc://")) {
|
||||
const src = matrixClient.mxcUrlToHttp(idp.icon, 24, 24, "crop", true);
|
||||
const src = mediaFromMxc(idp.icon).getSquareThumbnailHttp(24);
|
||||
icon = <img src={src} height="24" width="24" alt={idp.name} />;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ import GroupFilterOrderStore from '../../../stores/GroupFilterOrderStore';
|
|||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import AccessibleButton from "./AccessibleButton";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
|
||||
// A class for a child of GroupFilterPanel (possibly wrapped in a DNDTagTile) that represents
|
||||
|
@ -130,11 +131,11 @@ export default class TagTile extends React.Component {
|
|||
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||
const profile = this.state.profile || {};
|
||||
const name = profile.name || this.props.tag;
|
||||
const avatarHeight = 32;
|
||||
const avatarSize = 32;
|
||||
|
||||
const httpUrl = profile.avatarUrl ? this.context.mxcUrlToHttp(
|
||||
profile.avatarUrl, avatarHeight, avatarHeight, "crop",
|
||||
) : null;
|
||||
const httpUrl = profile.avatarUrl
|
||||
? mediaFromMxc(profile.avatarUrl).getSquareThumbnailHttp(avatarSize)
|
||||
: null;
|
||||
|
||||
const isPrototype = SettingsStore.getValue("feature_communities_v2_prototypes");
|
||||
const className = classNames({
|
||||
|
@ -180,8 +181,8 @@ export default class TagTile extends React.Component {
|
|||
name={name}
|
||||
idName={this.props.tag}
|
||||
url={httpUrl}
|
||||
width={avatarHeight}
|
||||
height={avatarHeight}
|
||||
width={avatarSize}
|
||||
height={avatarSize}
|
||||
/>
|
||||
{contextButton}
|
||||
{badgeElement}
|
||||
|
|
|
@ -27,6 +27,7 @@ import {ContextMenu, ContextMenuButton, toRightOf} from "../../structures/Contex
|
|||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import {RovingTabIndexWrapper} from "../../../accessibility/RovingTabIndex";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
// XXX this class copies a lot from RoomTile.js
|
||||
@replaceableComponent("views.groups.GroupInviteTile")
|
||||
|
@ -117,8 +118,9 @@ export default class GroupInviteTile extends React.Component {
|
|||
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||
|
||||
const groupName = this.props.group.name || this.props.group.groupId;
|
||||
const httpAvatarUrl = this.props.group.avatarUrl ?
|
||||
this.context.mxcUrlToHttp(this.props.group.avatarUrl, 24, 24) : null;
|
||||
const httpAvatarUrl = this.props.group.avatarUrl
|
||||
? mediaFromMxc(this.props.group.avatarUrl).getSquareThumbnailHttp(24)
|
||||
: null;
|
||||
|
||||
const av = <BaseAvatar name={groupName} width={24} height={24} url={httpAvatarUrl} />;
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import dis from '../../../dispatcher/dispatcher';
|
|||
import { GroupMemberType } from '../../../groups';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
@replaceableComponent("views.groups.GroupMemberTile")
|
||||
export default class GroupMemberTile extends React.Component {
|
||||
|
@ -46,10 +47,9 @@ export default class GroupMemberTile extends React.Component {
|
|||
const EntityTile = sdk.getComponent('rooms.EntityTile');
|
||||
|
||||
const name = this.props.member.displayname || this.props.member.userId;
|
||||
const avatarUrl = this.context.mxcUrlToHttp(
|
||||
this.props.member.avatarUrl,
|
||||
36, 36, 'crop',
|
||||
);
|
||||
const avatarUrl = this.props.member.avatarUrl
|
||||
? mediaFromMxc(this.props.member.avatarUrl).getSquareThumbnailHttp(36)
|
||||
: null;
|
||||
|
||||
const av = (
|
||||
<BaseAvatar
|
||||
|
|
|
@ -25,6 +25,7 @@ import GroupStore from '../../../stores/GroupStore';
|
|||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
@replaceableComponent("views.groups.GroupRoomInfo")
|
||||
export default class GroupRoomInfo extends React.Component {
|
||||
|
@ -204,10 +205,8 @@ export default class GroupRoomInfo extends React.Component {
|
|||
const avatarUrl = this.state.groupRoom.avatarUrl;
|
||||
let avatarElement;
|
||||
if (avatarUrl) {
|
||||
const httpUrl = this.context.mxcUrlToHttp(avatarUrl, 800, 800);
|
||||
avatarElement = (<div className="mx_MemberInfo_avatar">
|
||||
<img src={httpUrl} />
|
||||
</div>);
|
||||
const httpUrl = mediaFromMxc(avatarUrl).getSquareThumbnailHttp(800);
|
||||
avatarElement = <div className="mx_MemberInfo_avatar"><img src={httpUrl} /></div>;
|
||||
}
|
||||
|
||||
const groupRoomName = this.state.groupRoom.displayname;
|
||||
|
|
|
@ -21,6 +21,7 @@ import dis from '../../../dispatcher/dispatcher';
|
|||
import { GroupRoomType } from '../../../groups';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
@replaceableComponent("views.groups.GroupRoomTile")
|
||||
class GroupRoomTile extends React.Component {
|
||||
|
@ -42,10 +43,9 @@ class GroupRoomTile extends React.Component {
|
|||
render() {
|
||||
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
const avatarUrl = this.context.mxcUrlToHttp(
|
||||
this.props.groupRoom.avatarUrl,
|
||||
36, 36, 'crop',
|
||||
);
|
||||
const avatarUrl = this.props.groupRoom.avatarUrl
|
||||
? mediaFromMxc(this.props.groupRoom.avatarUrl).getSquareThumbnailHttp(36)
|
||||
: null;
|
||||
|
||||
const av = (
|
||||
<BaseAvatar name={this.props.groupRoom.displayname}
|
||||
|
|
|
@ -22,6 +22,7 @@ import dis from '../../../dispatcher/dispatcher';
|
|||
import FlairStore from '../../../stores/FlairStore';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
function nop() {}
|
||||
|
||||
|
@ -73,8 +74,9 @@ class GroupTile extends React.Component {
|
|||
const descElement = this.props.showDescription ?
|
||||
<div className="mx_GroupTile_desc">{ profile.shortDescription }</div> :
|
||||
<div />;
|
||||
const httpUrl = profile.avatarUrl ? this.context.mxcUrlToHttp(
|
||||
profile.avatarUrl, avatarHeight, avatarHeight, "crop") : null;
|
||||
const httpUrl = profile.avatarUrl
|
||||
? mediaFromMxc(profile.avatarUrl).getSquareThumbnailHttp(avatarHeight)
|
||||
: null;
|
||||
|
||||
let avatarElement = (
|
||||
<div className="mx_GroupTile_avatar">
|
||||
|
|
|
@ -22,6 +22,7 @@ import { decryptFile } from '../../../utils/DecryptFile';
|
|||
import { _t } from '../../../languageHandler';
|
||||
import InlineSpinner from '../elements/InlineSpinner';
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromContent} from "../../../customisations/Media";
|
||||
|
||||
@replaceableComponent("views.messages.MAudioBody")
|
||||
export default class MAudioBody extends React.Component {
|
||||
|
@ -41,11 +42,11 @@ export default class MAudioBody extends React.Component {
|
|||
}
|
||||
|
||||
_getContentUrl() {
|
||||
const content = this.props.mxEvent.getContent();
|
||||
if (content.file !== undefined) {
|
||||
const media = mediaFromContent(this.props.mxEvent.getContent());
|
||||
if (media.isEncrypted) {
|
||||
return this.state.decryptedUrl;
|
||||
} else {
|
||||
return MatrixClientPeg.get().mxcUrlToHttp(content.url);
|
||||
return media.srcHttp;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import request from 'browser-request';
|
|||
import Modal from '../../../Modal';
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromContent} from "../../../customisations/Media";
|
||||
|
||||
|
||||
// A cached tinted copy of require("../../../../res/img/download.svg")
|
||||
|
@ -178,8 +179,8 @@ export default class MFileBody extends React.Component {
|
|||
}
|
||||
|
||||
_getContentUrl() {
|
||||
const content = this.props.mxEvent.getContent();
|
||||
return MatrixClientPeg.get().mxcUrlToHttp(content.url);
|
||||
const media = mediaFromContent(this.props.mxEvent.getContent());
|
||||
return media.srcHttp;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
|
|
@ -28,6 +28,7 @@ import SettingsStore from "../../../settings/SettingsStore";
|
|||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import InlineSpinner from '../elements/InlineSpinner';
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromContent} from "../../../customisations/Media";
|
||||
|
||||
@replaceableComponent("views.messages.MImageBody")
|
||||
export default class MImageBody extends React.Component {
|
||||
|
@ -167,16 +168,16 @@ export default class MImageBody extends React.Component {
|
|||
}
|
||||
|
||||
_getContentUrl() {
|
||||
const content = this.props.mxEvent.getContent();
|
||||
if (content.file !== undefined) {
|
||||
const media = mediaFromContent(this.props.mxEvent.getContent());
|
||||
if (media.isEncrypted) {
|
||||
return this.state.decryptedUrl;
|
||||
} else {
|
||||
return this.context.mxcUrlToHttp(content.url);
|
||||
return media.srcHttp;
|
||||
}
|
||||
}
|
||||
|
||||
_getThumbUrl() {
|
||||
// FIXME: the dharma skin lets images grow as wide as you like, rather than capped to 800x600.
|
||||
// FIXME: we let images grow as wide as you like, rather than capped to 800x600.
|
||||
// So either we need to support custom timeline widths here, or reimpose the cap, otherwise the
|
||||
// thumbnail resolution will be unnecessarily reduced.
|
||||
// custom timeline widths seems preferable.
|
||||
|
@ -185,21 +186,19 @@ export default class MImageBody extends React.Component {
|
|||
const thumbHeight = Math.round(600 * pixelRatio);
|
||||
|
||||
const content = this.props.mxEvent.getContent();
|
||||
if (content.file !== undefined) {
|
||||
const media = mediaFromContent(content);
|
||||
|
||||
if (media.isEncrypted) {
|
||||
// Don't use the thumbnail for clients wishing to autoplay gifs.
|
||||
if (this.state.decryptedThumbnailUrl) {
|
||||
return this.state.decryptedThumbnailUrl;
|
||||
}
|
||||
return this.state.decryptedUrl;
|
||||
} else if (content.info && content.info.mimetype === "image/svg+xml" && content.info.thumbnail_url) {
|
||||
} else if (content.info && content.info.mimetype === "image/svg+xml" && media.hasThumbnail) {
|
||||
// special case to return clientside sender-generated thumbnails for SVGs, if any,
|
||||
// given we deliberately don't thumbnail them serverside to prevent
|
||||
// billion lol attacks and similar
|
||||
return this.context.mxcUrlToHttp(
|
||||
content.info.thumbnail_url,
|
||||
thumbWidth,
|
||||
thumbHeight,
|
||||
);
|
||||
return media.getThumbnailHttp(thumbWidth, thumbHeight, 'scale');
|
||||
} else {
|
||||
// we try to download the correct resolution
|
||||
// for hi-res images (like retina screenshots).
|
||||
|
@ -218,7 +217,7 @@ export default class MImageBody extends React.Component {
|
|||
pixelRatio === 1.0 ||
|
||||
(!info || !info.w || !info.h || !info.size)
|
||||
) {
|
||||
return this.context.mxcUrlToHttp(content.url, thumbWidth, thumbHeight);
|
||||
return media.getThumbnailOfSourceHttp(thumbWidth, thumbHeight);
|
||||
} else {
|
||||
// we should only request thumbnails if the image is bigger than 800x600
|
||||
// (or 1600x1200 on retina) otherwise the image in the timeline will just
|
||||
|
@ -233,24 +232,17 @@ export default class MImageBody extends React.Component {
|
|||
info.w > thumbWidth ||
|
||||
info.h > thumbHeight
|
||||
);
|
||||
const isLargeFileSize = info.size > 1*1024*1024;
|
||||
const isLargeFileSize = info.size > 1*1024*1024; // 1mb
|
||||
|
||||
if (isLargeFileSize && isLargerThanThumbnail) {
|
||||
// image is too large physically and bytewise to clutter our timeline so
|
||||
// we ask for a thumbnail, despite knowing that it will be max 800x600
|
||||
// despite us being retina (as synapse doesn't do 1600x1200 thumbs yet).
|
||||
return this.context.mxcUrlToHttp(
|
||||
content.url,
|
||||
thumbWidth,
|
||||
thumbHeight,
|
||||
);
|
||||
return media.getThumbnailOfSourceHttp(thumbWidth, thumbHeight);
|
||||
} else {
|
||||
// download the original image otherwise, so we can scale it client side
|
||||
// to take pixelRatio into account.
|
||||
// ( no width/height means we want the original image)
|
||||
return this.context.mxcUrlToHttp(
|
||||
content.url,
|
||||
);
|
||||
return media.srcHttp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import { _t } from '../../../languageHandler';
|
|||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import InlineSpinner from '../elements/InlineSpinner';
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromContent} from "../../../customisations/Media";
|
||||
|
||||
interface IProps {
|
||||
/* the MatrixEvent to show */
|
||||
|
@ -76,11 +77,11 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
|
||||
private getContentUrl(): string|null {
|
||||
const content = this.props.mxEvent.getContent();
|
||||
if (content.file !== undefined) {
|
||||
const media = mediaFromContent(this.props.mxEvent.getContent());
|
||||
if (media.isEncrypted) {
|
||||
return this.state.decryptedUrl;
|
||||
} else {
|
||||
return MatrixClientPeg.get().mxcUrlToHttp(content.url);
|
||||
return media.srcHttp;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,10 +92,11 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
|
|||
|
||||
private getThumbUrl(): string|null {
|
||||
const content = this.props.mxEvent.getContent();
|
||||
if (content.file !== undefined) {
|
||||
const media = mediaFromContent(content);
|
||||
if (media.isEncrypted) {
|
||||
return this.state.decryptedThumbnailUrl;
|
||||
} else if (content.info && content.info.thumbnail_url) {
|
||||
return MatrixClientPeg.get().mxcUrlToHttp(content.info.thumbnail_url);
|
||||
} else if (media.hasThumbnail) {
|
||||
return media.thumbnailHttp;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import * as sdk from '../../../index';
|
|||
import Modal from '../../../Modal';
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
@replaceableComponent("views.messages.RoomAvatarEvent")
|
||||
export default class RoomAvatarEvent extends React.Component {
|
||||
|
@ -35,7 +36,7 @@ export default class RoomAvatarEvent extends React.Component {
|
|||
onAvatarClick = () => {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const ev = this.props.mxEvent;
|
||||
const httpUrl = cli.mxcUrlToHttp(ev.getContent().url);
|
||||
const httpUrl = mediaFromMxc(ev.getContent().url).srcHttp;
|
||||
|
||||
const room = cli.getRoom(this.props.mxEvent.getRoomId());
|
||||
const text = _t('%(senderDisplayName)s changed the avatar for %(roomName)s', {
|
||||
|
|
|
@ -63,6 +63,7 @@ import { EventType } from "matrix-js-sdk/src/@types/event";
|
|||
import { SetRightPanelPhasePayload } from "../../../dispatcher/payloads/SetRightPanelPhasePayload";
|
||||
import RoomAvatar from "../avatars/RoomAvatar";
|
||||
import RoomName from "../elements/RoomName";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
interface IDevice {
|
||||
deviceId: string;
|
||||
|
@ -1408,7 +1409,7 @@ const UserInfoHeader: React.FC<{
|
|||
const avatarUrl = member.getMxcAvatarUrl ? member.getMxcAvatarUrl() : member.avatarUrl;
|
||||
if (!avatarUrl) return;
|
||||
|
||||
const httpUrl = cli.mxcUrlToHttp(avatarUrl);
|
||||
const httpUrl = mediaFromMxc(avatarUrl).srcHttp;
|
||||
const params = {
|
||||
src: httpUrl,
|
||||
name: member.name,
|
||||
|
|
|
@ -21,6 +21,7 @@ import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
|||
import Field from "../elements/Field";
|
||||
import * as sdk from "../../../index";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
// TODO: Merge with ProfileSettings?
|
||||
@replaceableComponent("views.room_settings.RoomProfileSettings")
|
||||
|
@ -38,7 +39,7 @@ export default class RoomProfileSettings extends React.Component {
|
|||
|
||||
const avatarEvent = room.currentState.getStateEvents("m.room.avatar", "");
|
||||
let avatarUrl = avatarEvent && avatarEvent.getContent() ? avatarEvent.getContent()["url"] : null;
|
||||
if (avatarUrl) avatarUrl = client.mxcUrlToHttp(avatarUrl, 96, 96, 'crop', false);
|
||||
if (avatarUrl) avatarUrl = mediaFromMxc(avatarUrl).getSquareThumbnailHttp(96);
|
||||
|
||||
const topicEvent = room.currentState.getStateEvents("m.room.topic", "");
|
||||
const topic = topicEvent && topicEvent.getContent() ? topicEvent.getContent()['topic'] : '';
|
||||
|
@ -112,7 +113,7 @@ export default class RoomProfileSettings extends React.Component {
|
|||
if (this.state.avatarFile) {
|
||||
const uri = await client.uploadContent(this.state.avatarFile);
|
||||
await client.sendStateEvent(this.props.roomId, 'm.room.avatar', {url: uri}, '');
|
||||
newState.avatarUrl = client.mxcUrlToHttp(uri, 96, 96, 'crop', false);
|
||||
newState.avatarUrl = mediaFromMxc(uri).getSquareThumbnailHttp(96);
|
||||
newState.originalAvatarUrl = newState.avatarUrl;
|
||||
newState.avatarFile = null;
|
||||
} else if (this.state.originalAvatarUrl !== this.state.avatarUrl) {
|
||||
|
|
|
@ -26,6 +26,7 @@ import Modal from "../../../Modal";
|
|||
import * as ImageUtils from "../../../ImageUtils";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
@replaceableComponent("views.rooms.LinkPreviewWidget")
|
||||
export default class LinkPreviewWidget extends React.Component {
|
||||
|
@ -83,7 +84,7 @@ export default class LinkPreviewWidget extends React.Component {
|
|||
|
||||
let src = p["og:image"];
|
||||
if (src && src.startsWith("mxc://")) {
|
||||
src = MatrixClientPeg.get().mxcUrlToHttp(src);
|
||||
src = mediaFromMxc(src).srcHttp;
|
||||
}
|
||||
|
||||
const params = {
|
||||
|
@ -109,9 +110,11 @@ export default class LinkPreviewWidget extends React.Component {
|
|||
if (!SettingsStore.getValue("showImages")) {
|
||||
image = null; // Don't render a button to show the image, just hide it outright
|
||||
}
|
||||
const imageMaxWidth = 100; const imageMaxHeight = 100;
|
||||
const imageMaxWidth = 100;
|
||||
const imageMaxHeight = 100;
|
||||
if (image && image.startsWith("mxc://")) {
|
||||
image = MatrixClientPeg.get().mxcUrlToHttp(image, imageMaxWidth, imageMaxHeight);
|
||||
// We deliberately don't want a square here, so use the source HTTP thumbnail function
|
||||
image = mediaFromMxc(image).getThumbnailOfSourceHttp(imageMaxWidth, imageMaxHeight, 'scale');
|
||||
}
|
||||
|
||||
let thumbHeight = imageMaxHeight;
|
||||
|
|
|
@ -21,6 +21,7 @@ import * as sdk from '../../../index';
|
|||
import { _t } from '../../../languageHandler';
|
||||
import Spinner from '../elements/Spinner';
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
@replaceableComponent("views.settings.ChangeAvatar")
|
||||
export default class ChangeAvatar extends React.Component {
|
||||
|
@ -117,7 +118,7 @@ export default class ChangeAvatar extends React.Component {
|
|||
httpPromise.then(function() {
|
||||
self.setState({
|
||||
phase: ChangeAvatar.Phases.Display,
|
||||
avatarUrl: MatrixClientPeg.get().mxcUrlToHttp(newUrl),
|
||||
avatarUrl: mediaFromMxc(newUrl).srcHttp,
|
||||
});
|
||||
}, function(error) {
|
||||
self.setState({
|
||||
|
|
|
@ -24,6 +24,7 @@ import {OwnProfileStore} from "../../../stores/OwnProfileStore";
|
|||
import Modal from "../../../Modal";
|
||||
import ErrorDialog from "../dialogs/ErrorDialog";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
@replaceableComponent("views.settings.ProfileSettings")
|
||||
export default class ProfileSettings extends React.Component {
|
||||
|
@ -32,7 +33,7 @@ export default class ProfileSettings extends React.Component {
|
|||
|
||||
const client = MatrixClientPeg.get();
|
||||
let avatarUrl = OwnProfileStore.instance.avatarMxc;
|
||||
if (avatarUrl) avatarUrl = client.mxcUrlToHttp(avatarUrl, 96, 96, 'crop', false);
|
||||
if (avatarUrl) avatarUrl = mediaFromMxc(avatarUrl).getSquareThumbnailHttp(96);
|
||||
this.state = {
|
||||
userId: client.getUserId(),
|
||||
originalDisplayName: OwnProfileStore.instance.displayName,
|
||||
|
@ -97,7 +98,7 @@ export default class ProfileSettings extends React.Component {
|
|||
` (${this.state.avatarFile.size}) bytes`);
|
||||
const uri = await client.uploadContent(this.state.avatarFile);
|
||||
await client.setAvatarUrl(uri);
|
||||
newState.avatarUrl = client.mxcUrlToHttp(uri, 96, 96, 'crop', false);
|
||||
newState.avatarUrl = mediaFromMxc(uri).getSquareThumbnailHttp(96);
|
||||
newState.originalAvatarUrl = newState.avatarUrl;
|
||||
newState.avatarFile = null;
|
||||
} else if (this.state.originalAvatarUrl !== this.state.avatarUrl) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
import {MatrixClientPeg} from "../MatrixClientPeg";
|
||||
import {IMediaEventContent, IPreparedMedia, prepEventContentAsMedia} from "./models/IMediaEventContent";
|
||||
import {ResizeMode} from "./models/ResizeMode";
|
||||
|
||||
// Populate this class with the details of your customisations when copying it.
|
||||
|
||||
|
@ -33,6 +34,13 @@ export class Media {
|
|||
constructor(private prepared: IPreparedMedia) {
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the media appears to be encrypted. Actual file contents may vary.
|
||||
*/
|
||||
public get isEncrypted(): boolean {
|
||||
return !!this.prepared.file;
|
||||
}
|
||||
|
||||
/**
|
||||
* The MXC URI of the source media.
|
||||
*/
|
||||
|
@ -62,6 +70,15 @@ export class Media {
|
|||
return MatrixClientPeg.get().mxcUrlToHttp(this.srcMxc);
|
||||
}
|
||||
|
||||
/**
|
||||
* The HTTP URL for the thumbnail media (without any specified width, height, etc). Null/undefined
|
||||
* if no thumbnail media recorded.
|
||||
*/
|
||||
public get thumbnailHttp(): string | undefined | null {
|
||||
if (!this.hasThumbnail) return null;
|
||||
return MatrixClientPeg.get().mxcUrlToHttp(this.thumbnailMxc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the HTTP URL for the thumbnail media with the requested characteristics, if a thumbnail
|
||||
* is recorded for this media. Returns null/undefined otherwise.
|
||||
|
@ -70,7 +87,7 @@ export class Media {
|
|||
* @param {"scale"|"crop"} mode The desired thumbnailing mode. Defaults to scale.
|
||||
* @returns {string} The HTTP URL which points to the thumbnail.
|
||||
*/
|
||||
public getThumbnailHttp(width: number, height: number, mode: 'scale' | 'crop' = "scale"): string | null | undefined {
|
||||
public getThumbnailHttp(width: number, height: number, mode: ResizeMode = "scale"): string | null | undefined {
|
||||
if (!this.hasThumbnail) return null;
|
||||
return MatrixClientPeg.get().mxcUrlToHttp(this.thumbnailMxc, width, height, mode);
|
||||
}
|
||||
|
@ -82,10 +99,23 @@ export class Media {
|
|||
* @param {"scale"|"crop"} mode The desired thumbnailing mode. Defaults to scale.
|
||||
* @returns {string} The HTTP URL which points to the thumbnail.
|
||||
*/
|
||||
public getThumbnailOfSourceHttp(width: number, height: number, mode: 'scale' | 'crop' = "scale"): string {
|
||||
public getThumbnailOfSourceHttp(width: number, height: number, mode: ResizeMode = "scale"): string {
|
||||
return MatrixClientPeg.get().mxcUrlToHttp(this.srcMxc, width, height, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a square thumbnail of the media. If the media has a thumbnail recorded, that MXC will
|
||||
* be used, otherwise the source media will be used.
|
||||
* @param {number} dim The desired width and height.
|
||||
* @returns {string} An HTTP URL for the thumbnail.
|
||||
*/
|
||||
public getSquareThumbnailHttp(dim: number): string {
|
||||
if (this.hasThumbnail) {
|
||||
return this.getThumbnailHttp(dim, dim, 'crop');
|
||||
}
|
||||
return this.getThumbnailOfSourceHttp(dim, dim, 'crop');
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the source media.
|
||||
* @returns {Promise<Response>} Resolves to the server's response for chaining.
|
||||
|
@ -102,7 +132,7 @@ export class Media {
|
|||
* @param {"scale"|"crop"} mode The desired thumbnailing mode. Defaults to scale.
|
||||
* @returns {Promise<Response>} Resolves to the server's response for chaining.
|
||||
*/
|
||||
public downloadThumbnail(width: number, height: number, mode: 'scale' | 'crop' = "scale"): Promise<Response> {
|
||||
public downloadThumbnail(width: number, height: number, mode: ResizeMode = "scale"): Promise<Response> {
|
||||
if (!this.hasThumbnail) throw new Error("Cannot download non-existent thumbnail");
|
||||
return fetch(this.getThumbnailHttp(width, height, mode));
|
||||
}
|
||||
|
@ -114,7 +144,7 @@ export class Media {
|
|||
* @param {"scale"|"crop"} mode The desired thumbnailing mode. Defaults to scale.
|
||||
* @returns {Promise<Response>} Resolves to the server's response for chaining.
|
||||
*/
|
||||
public downloadThumbnailOfSource(width: number, height: number, mode: 'scale' | 'crop' = "scale"): Promise<Response> {
|
||||
public downloadThumbnailOfSource(width: number, height: number, mode: ResizeMode = "scale"): Promise<Response> {
|
||||
return fetch(this.getThumbnailOfSourceHttp(width, height, mode));
|
||||
}
|
||||
}
|
||||
|
|
17
src/customisations/models/ResizeMode.ts
Normal file
17
src/customisations/models/ResizeMode.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export type ResizeMode = "scale" | "crop";
|
|
@ -22,6 +22,7 @@ import { User } from "matrix-js-sdk/src/models/user";
|
|||
import { throttle } from "lodash";
|
||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
||||
import { _t } from "../languageHandler";
|
||||
import {mediaFromMxc} from "../customisations/Media";
|
||||
|
||||
interface IState {
|
||||
displayName?: string;
|
||||
|
@ -72,8 +73,12 @@ export class OwnProfileStore extends AsyncStoreWithClient<IState> {
|
|||
*/
|
||||
public getHttpAvatarUrl(size = 0): string {
|
||||
if (!this.avatarMxc) return null;
|
||||
const adjustedSize = size > 1 ? size : undefined; // don't let negatives or zero through
|
||||
return this.matrixClient.mxcUrlToHttp(this.avatarMxc, adjustedSize, adjustedSize);
|
||||
const media = mediaFromMxc(this.avatarMxc);
|
||||
if (!size || size <= 0) {
|
||||
return media.srcHttp;
|
||||
} else {
|
||||
return media.getSquareThumbnailHttp(size);
|
||||
}
|
||||
}
|
||||
|
||||
protected async onNotReady() {
|
||||
|
|
Loading…
Reference in a new issue