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